Beispiel #1
0
static gint
read_image_resource_block (PSDimage  *img_a,
                           FILE      *f,
                           GError   **error)
{
  guint32 block_len;
  guint32 block_end;

  if (fread (&block_len, 4, 1, f) < 1)
    {
      psd_set_error (feof (f), errno, error);
      return -1;
    }
  img_a->image_res_len = GUINT32_FROM_BE (block_len);

  IFDBG(1) g_debug ("Image resource block size = %d", (int)img_a->image_res_len);

  img_a->image_res_start = ftell (f);
  block_end = img_a->image_res_start + img_a->image_res_len;

  if (fseek (f, block_end, SEEK_SET) < 0)
    {
      psd_set_error (feof (f), errno, error);
      return -1;
    }

  return 0;
}
Beispiel #2
0
ioctl_tree *
ioctl_tree_execute(ioctl_tree * tree, ioctl_tree * last, unsigned long id, void *arg, int *ret)
{
    const ioctl_type *t;
    ioctl_tree *i;
    int r, handled;

    DBG("ioctl_tree_execute ioctl %lX\n", id);

    /* check if it's a hardware independent stateless ioctl */
    t = ioctl_type_get_by_id(id);
    if (t != NULL && t->insertion_parent == NULL) {
	DBG("  ioctl_tree_execute: stateless\n");
	if (t->execute(NULL, id, arg, &r))
	    *ret = r;
	else
	    *ret = -1;
	return last;
    }

    if (tree == NULL)
	return NULL;

    i = ioctl_tree_next_wrap(tree, last);
    /* start at the previously executed node to maintain original order of
     * ioctls as much as possible (i. e. maintain it while the requests come in
     * at the same order as originally recorded) */
    for (;;) {
	DBG("   ioctl_tree_execute: checking node %s(%lX, base id %lX) ", i->type->name, i->id, i->type->id);
	IFDBG(i->type->write(i, stdout));
	DBG("\n");
	handled = i->type->execute(i, id, arg, &r);
	if (handled) {
	    DBG("    -> match, ret %i, adv: %i\n", r, handled);
	    *ret = r;
	    if (handled == 1)
		return i;
	    else
		return last;
	}

	if (last != NULL && i == last) {
	    /* we did a full circle */
	    DBG("    -> full iteration, not found\n");
	    break;
	}

	i = ioctl_tree_next_wrap(tree, i);

	if (last == NULL && i == tree) {
	    /* we did a full circle */
	    DBG("    -> full iteration with last == NULL, not found\n");
	    break;
	}
    }

    /* not found */
    return NULL;
}
Beispiel #3
0
static gint
read_header_block (PSDimage  *img_a,
                   FILE      *f,
                   GError   **error)
{
  guint16  version;
  gchar    sig[4];
  gchar    buf[6];

  if (fread (sig, 4, 1, f) < 1
      || fread (&version, 2, 1, f) < 1
      || fread (buf, 6, 1, f) < 1
      || fread (&img_a->channels, 2, 1, f) < 1
      || fread (&img_a->rows, 4, 1, f) < 1
      || fread (&img_a->columns, 4, 1, f) < 1
      || fread (&img_a->bps, 2, 1, f) < 1
      || fread (&img_a->color_mode, 2, 1, f) < 1)
    {
      psd_set_error (feof (f), errno, error);
      return -1;
    }
  version = GUINT16_FROM_BE (version);
  img_a->channels = GUINT16_FROM_BE (img_a->channels);
  img_a->rows = GUINT32_FROM_BE (img_a->rows);
  img_a->columns = GUINT32_FROM_BE (img_a->columns);
  img_a->bps = GUINT16_FROM_BE (img_a->bps);
  img_a->color_mode = GUINT16_FROM_BE (img_a->color_mode);

  IFDBG(1) g_debug ("\n\n\tSig: %.4s\n\tVer: %d\n\tChannels: "
                    "%d\n\tSize: %dx%d\n\tBPS: %d\n\tMode: %d\n",
                    sig, version, img_a->channels,
                    img_a->columns, img_a->rows,
                    img_a->bps, img_a->color_mode);

  if (memcmp (sig, "8BPS", 4) != 0)
    return -1;

  if (version != 1)
    return -1;

  if (img_a->channels > MAX_CHANNELS)
    return -1;

  if (img_a->rows < 1 || img_a->rows > GIMP_MAX_IMAGE_SIZE)
    return -1;

  if (img_a->columns < 1 || img_a->columns > GIMP_MAX_IMAGE_SIZE)
    return -1;

  return 0;
}
Beispiel #4
0
static gint32
create_gimp_image (PSDimage    *img_a,
                   const gchar *filename)
{
  gint32 image_id = -1;

  img_a->base_type = GIMP_RGB;

  /* Create gimp image */
  IFDBG(2) g_debug ("Create image");
  image_id = gimp_image_new (img_a->columns, img_a->rows, img_a->base_type);

  gimp_image_set_filename (image_id, filename);
  gimp_image_undo_disable (image_id);

  return image_id;
}
Beispiel #5
0
static void
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
{
  static GimpParam  values[4];
  GimpRunMode       run_mode;
  GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  gint32            image_ID;
  GError           *error  = NULL;

  run_mode = param[0].data.d_int32;

  INIT_I18N ();
  gegl_init (NULL, NULL);

  *nreturn_vals = 1;
  *return_vals  = values;

  values[0].type          = GIMP_PDB_STATUS;
  values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;

  if (strcmp (name, LOAD_PROC) == 0)
    {
      gboolean resolution_loaded = FALSE;
      gboolean interactive;

      switch (run_mode)
        {
        case GIMP_RUN_INTERACTIVE:
        case GIMP_RUN_WITH_LAST_VALS:
          gimp_ui_init (PLUG_IN_BINARY, FALSE);
          interactive = TRUE;
          break;
        default:
          interactive = FALSE;
          break;
        }

      image_ID = load_image (param[1].data.d_string,
                             &resolution_loaded, &error);

      if (image_ID != -1)
        {
          GFile        *file = g_file_new_for_path (param[1].data.d_string);
          GimpMetadata *metadata;

          metadata = gimp_image_metadata_load_prepare (image_ID, "image/x-psd",
                                                       file, NULL);

          if (metadata)
            {
              GimpMetadataLoadFlags flags = GIMP_METADATA_LOAD_ALL;

              if (resolution_loaded)
                flags &= ~GIMP_METADATA_LOAD_RESOLUTION;

              gimp_image_metadata_load_finish (image_ID, "image/x-psd",
                                               metadata, flags,
                                               interactive);

              g_object_unref (metadata);
            }

          g_object_unref (file);

          *nreturn_vals = 2;
          values[1].type         = GIMP_PDB_IMAGE;
          values[1].data.d_image = image_ID;
        }
      else
        {
          status = GIMP_PDB_EXECUTION_ERROR;
        }
    }
  else if (strcmp (name, LOAD_THUMB_PROC) == 0)
    {
      if (nparams < 2)
        {
          status = GIMP_PDB_CALLING_ERROR;
        }
      else
        {
          const gchar *filename = param[0].data.d_string;
          gint         width    = 0;
          gint         height   = 0;

          image_ID = load_thumbnail_image (filename, &width, &height, &error);

          if (image_ID != -1)
            {
              *nreturn_vals = 4;
              values[1].type         = GIMP_PDB_IMAGE;
              values[1].data.d_image = image_ID;
              values[2].type         = GIMP_PDB_INT32;
              values[2].data.d_int32 = width;
              values[3].type         = GIMP_PDB_INT32;
              values[3].data.d_int32 = height;
            }
          else
            {
              status = GIMP_PDB_EXECUTION_ERROR;
            }
        }
    }
  else if (strcmp (name, SAVE_PROC) == 0)
    {
      gint32                 drawable_id;
      GimpMetadata          *metadata;
      GimpMetadataSaveFlags  metadata_flags;
      GimpExportReturn       export = GIMP_EXPORT_IGNORE;

      IFDBG(2) g_debug ("\n---------------- %s ----------------\n",
                        param[3].data.d_string);

      image_ID    = param[1].data.d_int32;
      drawable_id = param[2].data.d_int32;

      switch (run_mode)
        {
        case GIMP_RUN_INTERACTIVE:
        case GIMP_RUN_WITH_LAST_VALS:
          gimp_ui_init (PLUG_IN_BINARY, FALSE);

          export = gimp_export_image (&image_ID, &drawable_id, "PSD",
                                      GIMP_EXPORT_CAN_HANDLE_RGB     |
                                      GIMP_EXPORT_CAN_HANDLE_GRAY    |
                                      GIMP_EXPORT_CAN_HANDLE_INDEXED |
                                      GIMP_EXPORT_CAN_HANDLE_ALPHA   |
                                      GIMP_EXPORT_CAN_HANDLE_LAYERS  |
                                      GIMP_EXPORT_CAN_HANDLE_LAYER_MASKS);

          if (export == GIMP_EXPORT_CANCEL)
            {
              values[0].data.d_status = GIMP_PDB_CANCEL;
              return;
            }
          break;

        default:
          break;
        }
Beispiel #6
0
/* Main file load function */
gint32
load_thumbnail_image (const gchar  *filename,
                      gint         *width,
                      gint         *height,
                      GError      **load_error)
{
  FILE        *f;
  struct stat  st;
  PSDimage     img_a;
  gint32       image_id = -1;
  GError      *error    = NULL;

  /* ----- Open PSD file ----- */
  if (g_stat (filename, &st) == -1)
    return -1;

  IFDBG(1) g_debug ("Open file %s", gimp_filename_to_utf8 (filename));
  f = g_fopen (filename, "rb");
  if (f == NULL)
    {
      g_set_error (load_error, G_FILE_ERROR, g_file_error_from_errno (errno),
                   _("Could not open '%s' for reading: %s"),
                   gimp_filename_to_utf8 (filename), g_strerror (errno));
      return -1;
    }

  gimp_progress_init_printf (_("Opening thumbnail for '%s'"),
                             gimp_filename_to_utf8 (filename));

  /* ----- Read the PSD file Header block ----- */
  IFDBG(2) g_debug ("Read header block");
  if (read_header_block (&img_a, f, &error) < 0)
    goto load_error;
  gimp_progress_update (0.2);

  /* ----- Read the PSD file Colour Mode block ----- */
  IFDBG(2) g_debug ("Read colour mode block");
  if (read_color_mode_block (&img_a, f, &error) < 0)
    goto load_error;
  gimp_progress_update (0.4);

  /* ----- Read the PSD file Image Resource block ----- */
  IFDBG(2) g_debug ("Read image resource block");
  if (read_image_resource_block (&img_a, f, &error) < 0)
    goto load_error;
  gimp_progress_update (0.6);

  /* ----- Create GIMP image ----- */
  IFDBG(2) g_debug ("Create GIMP image");
  image_id = create_gimp_image (&img_a, filename);
  if (image_id < 0)
    goto load_error;

  /* ----- Add image resources ----- */
  IFDBG(2) g_debug ("Add image resources");
  if (add_image_resources (image_id, &img_a, f, &error) < 1)
    goto load_error;
  gimp_progress_update (1.0);

  gimp_image_clean_all (image_id);
  gimp_image_undo_enable (image_id);
  fclose (f);

  *width = img_a.columns;
  *height = img_a.rows;
  return image_id;

  /* ----- Process load errors ----- */
 load_error:
  if (error)
    {
      g_set_error (load_error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
                   _("Error loading PSD file: %s"), error->message);
      g_error_free (error);
    }

  /* Delete partially loaded image */
  if (image_id > 0)
    gimp_image_delete (image_id);

  /* Close file if Open */
  if (! (f == NULL))
    fclose (f);

  return -1;
}
Beispiel #7
0
static int
usbdevfs_reapurb_execute(const ioctl_tree * node, unsigned long id, void *arg, int *ret)
{
    /* set in SUBMIT, cleared in REAP */
    static const ioctl_tree *submit_node = NULL;
    static struct usbdevfs_urb *submit_urb = NULL;

    if (id == USBDEVFS_SUBMITURB) {
	const struct usbdevfs_urb *n_urb = node->data;
	struct usbdevfs_urb *a_urb = arg;
	assert(submit_node == NULL);

	if (n_urb->type != a_urb->type || n_urb->endpoint != a_urb->endpoint ||
	    n_urb->flags != a_urb->flags || n_urb->buffer_length != a_urb->buffer_length)
	    return 0;

	DBG("  usbdevfs_reapurb_execute: handling SUBMITURB, metadata match\n");

	/* for an output URB we also require the buffer contents to match; for
	 * an input URB it can be uninitialized */
	if ((n_urb->endpoint & 0x80) == 0 && memcmp(n_urb->buffer, a_urb->buffer, n_urb->buffer_length) != 0) {
	    DBG("  usbdevfs_reapurb_execute: handling SUBMITURB, buffer mismatch, rejecting\n");
	    return 0;
	}
	DBG("  usbdevfs_reapurb_execute: handling SUBMITURB, buffer match, remembering\n");

	/* remember the node for the next REAP */
	submit_node = node;
	submit_urb = a_urb;
	*ret = 0;
	return 1;
    }

    if (id == node->type->id) {
	struct usbdevfs_urb *orig_node_urb;
	if (submit_node == NULL) {
	    DBG("  usbdevfs_reapurb_execute: handling %s, but no submit node -> EAGAIN\n", node->type->name);
	    *ret = -1;
	    errno = EAGAIN;
	    return 2;
	}
	orig_node_urb = submit_node->data;

	submit_urb->actual_length = orig_node_urb->actual_length;
	submit_urb->error_count = orig_node_urb->error_count;
	/* for an input EP we need to copy the buffer data */
	if (orig_node_urb->endpoint & 0x80) {
	    memcpy(submit_urb->buffer, orig_node_urb->buffer, orig_node_urb->actual_length);
	}
	submit_urb->status = orig_node_urb->status;
	*((struct usbdevfs_urb **)arg) = submit_urb;

	DBG("  usbdevfs_reapurb_execute: handling %s %u %u %i %u %i %i %i ",
	    node->type->name, (unsigned)submit_urb->type,
	    (unsigned)submit_urb->endpoint, submit_urb->status,
	    (unsigned)submit_urb->flags, submit_urb->buffer_length, submit_urb->actual_length, submit_urb->error_count);
	IFDBG(write_hex(stdout, submit_urb->buffer, submit_urb->endpoint & 0x80 ?
			submit_urb->actual_length : submit_urb->buffer_length));

	submit_urb = NULL;
	submit_node = NULL;
	*ret = 0;
	return 2;
    }

    return 0;
}
Beispiel #8
0
gchar *
fread_pascal_string (gint32         *bytes_read,
                     gint32         *bytes_written,
                     const guint16   mod_len,
                     FILE           *f,
                     GError        **error)
{
  /*
   * Reads a pascal string from the file padded to a multiple of mod_len
   * and returns a utf-8 string.
   */

  gchar        *str;
  gchar        *utf8_str;
  guchar        len;
  gint32        padded_len;

  *bytes_read = 0;
  *bytes_written = -1;

  if (fread (&len, 1, 1, f) < 1)
    {
      psd_set_error (feof (f), errno, error);
      return NULL;
    }
  (*bytes_read)++;
  IFDBG(3) g_debug ("Pascal string length %d", len);

  if (len == 0)
    {
      if (fseek (f, mod_len - 1, SEEK_CUR) < 0)
        {
          psd_set_error (feof (f), errno, error);
          return NULL;
        }
      *bytes_read += (mod_len - 1);
      *bytes_written = 0;
      return NULL;
    }

  str = g_malloc (len);
  if (fread (str, len, 1, f) < 1)
    {
      psd_set_error (feof (f), errno, error);
      return NULL;
    }
  *bytes_read += len;

  if (mod_len > 0)
    {
      padded_len = len + 1;
      while (padded_len % mod_len != 0)
        {
          if (fseek (f, 1, SEEK_CUR) < 0)
            {
              psd_set_error (feof (f), errno, error);
              return NULL;
            }
          (*bytes_read)++;
          padded_len++;
        }
    }

  utf8_str = gimp_any_to_utf8 (str, len, NULL);
  *bytes_written = strlen (utf8_str);
  g_free (str);

  IFDBG(3) g_debug ("Pascal string: %s, bytes_read: %d, bytes_written: %d",
                    utf8_str, *bytes_read, *bytes_written);

  return utf8_str;
}
Beispiel #9
0
gchar *
encode_packbits (const gchar   *src,
                 const guint32  unpacked_len,
                 guint16       *packed_len)
{
/*
 *  Encode a PackBits chunk.
 */
  GString *dst_str;                      /* destination string */
  gint     curr_char;                    /* current character */
  gchar    char_buff[128];               /* buffer of already read characters */
  guchar   run_len;                      /* number of characters in a run */
  gint32   unpack_left = unpacked_len;

  IFDBG(2) g_debug ("Encode packbits");

  /* Initialise destination string */
  dst_str = g_string_sized_new (unpacked_len);

  /* prime the read loop */
  curr_char = *src;
  src++;
  run_len = 0;

  /* read input until there's nothing left */
  while (unpack_left > 0)
    {
        char_buff[run_len] = (gchar) curr_char;
        IFDBG(2) g_debug ("buff %x, run len %d, curr char %x",
                          char_buff[run_len], run_len, (gchar) curr_char);
        run_len++;

        if (run_len >= MIN_RUN)
          {
            gint i;

            /* check for run  */
            for (i = 2; i <= MIN_RUN; ++i)
              {
                if (curr_char != char_buff[run_len - i])
                  {
                    /* no run */
                    i = 0;
                    break;
                  }
              }

            if (i != 0)
              {
                /* we have a run write out buffer before run*/
                gint next_char;

                if (run_len > MIN_RUN)
                  {
                    /* block size - 1 followed by contents */
                    g_string_append_c (dst_str, (run_len - MIN_RUN - 1));
                    g_string_append_len (dst_str, char_buff, (run_len - MIN_RUN));
                    IFDBG(2) g_debug ("(1) Number of chars: %d, run length tag: %d",
                                      run_len - MIN_RUN, run_len - MIN_RUN - 1);
                  }

                /* determine run length (MIN_RUN so far) */
                run_len = MIN_RUN;

                /* get next character */
                next_char = *src;
                src++;
                unpack_left--;
                while (next_char == curr_char)
                  {
                    run_len++;
                    if (run_len == 128)
                      {
                        /* run is at max length */
                        break;
                      }
                    next_char = *src;
                    src++;
                    unpack_left--;
                  }

                /* write out encoded run length and run symbol */
                g_string_append_c (dst_str, (gchar)(1 - (gint)(run_len)));
                g_string_append_c (dst_str, curr_char);
                IFDBG(2) g_debug ("(2) Number of chars: %d, run length tag: %d",
                                  run_len, (1 - (gint)(run_len)));

                if (unpack_left > 0)
                  {
                    /* make run breaker start of next buffer */
                    char_buff[0] = next_char;
                    run_len = 1;
                  }
                else
                  {
                    /* file ends in a run */
                    run_len = 0;
                  }
              }
          }

        if (run_len == 128)
          {
            /* write out buffer */
            g_string_append_c (dst_str, 127);
            g_string_append_len (dst_str, char_buff, 128);
            IFDBG(2) g_debug ("(3) Number of chars: 128, run length tag: 127");

            /* start a new buffer */
            run_len = 0;
          }

        curr_char = *src;
        src++;
        unpack_left--;
    }

  /* write out last buffer */
  if (run_len != 0)
    {
        if (run_len <= 128)
          {
            /* write out entire copy buffer */
            g_string_append_c (dst_str, run_len - 1);
            g_string_append_len (dst_str, char_buff, run_len);
            IFDBG(2) g_debug ("(4) Number of chars: %d, run length tag: %d",
                              run_len, run_len - 1);
          }
        else
          {
            IFDBG(2) g_debug ("(5) Very bad - should not be here");
          }
    }

  *packed_len = dst_str->len;
  IFDBG(2) g_debug ("Packed len %d, unpacked %d", *packed_len, unpacked_len);

  return g_string_free (dst_str, FALSE);
}
Beispiel #10
0
gint
decode_packbits (const gchar *src,
                 gchar       *dst,
                 guint16      packed_len,
                 guint32      unpacked_len)
{
/*
 *  Decode a PackBits chunk.
 */
  gint      n;
  gchar     dat;
  gint32    unpack_left = unpacked_len;
  gint32    pack_left = packed_len;
  gint32    error_code = 0;
  gint32    return_val = 0;

  while (unpack_left > 0 && pack_left > 0)
    {
      n = *src;
      src++;
      pack_left--;

      if (n == 128)     /* nop */
        continue;
      else if (n > 128)
        n -= 256;

      if (n < 0)        /* replicate next gchar |n|+ 1 times */
        {
          n  = 1 - n;
          if (! pack_left)
            {
              IFDBG(2) g_debug ("Input buffer exhausted in replicate");
              error_code = 1;
              break;
            }
          if (n > unpack_left)
            {
              IFDBG(2) g_debug ("Overrun in packbits replicate of %d chars", n - unpack_left);
              error_code = 2;
            }
          dat = *src;
          for (; n > 0; --n)
            {
              if (! unpack_left)
                break;
              *dst = dat;
              dst++;
              unpack_left--;
            }
          if (unpack_left)
            {
              src++;
              pack_left--;
            }
        }
      else              /* copy next n+1 gchars literally */
        {
          n++;
          for (; n > 0; --n)
            {
              if (! pack_left)
                {
                  IFDBG(2) g_debug ("Input buffer exhausted in copy");
                  error_code = 3;
                  break;
                }
              if (! unpack_left)
                {
                  IFDBG(2) g_debug ("Output buffer exhausted in copy");
                  error_code = 4;
                  break;
                }
              *dst = *src;
              dst++;
              unpack_left--;
              src++;
              pack_left--;
            }
        }
    }

  if (unpack_left > 0)
    {
      /* Pad with zeros to end of output buffer */
      for (n = 0; n < pack_left; ++n)
        {
          *dst = 0;
          dst++;
        }
    }

  if (unpack_left)
    {
      IFDBG(2) g_debug ("Packbits decode - unpack left %d", unpack_left);
      return_val -= unpack_left;
    }
  if (pack_left)
    {
      /* Some images seem to have a pad byte at the end of the packed data */
      if (error_code || pack_left != 1)
        {
          IFDBG(2) g_debug ("Packbits decode - pack left %d", pack_left);
          return_val = pack_left;
        }
    }

  IFDBG(2)
    if (error_code)
      g_debug ("Error code %d", error_code);

  return return_val;
}
Beispiel #11
0
gint32
fwrite_unicode_string (const gchar    *src,
                       const guint16   mod_len,
                       FILE           *f,
                       GError        **error)
{
  /*
   *  Converts utf-8 string to utf-16 and writes 4 byte length
   *  then string padding to multiple of mod_len.
   */

  gunichar2    *utf16_str;
  gchar         null_str = 0x0;
  gint32        utf16_len = 0;
  gint32        bytes_written = 0;
  gint          i;
  glong         len;

  if (src == NULL)
    {
       /* Write null string as four byte 0 int32 */
      if (fwrite (&utf16_len, 4, 1, f) < 1)
        {
          psd_set_error (feof (f), errno, error);
          return -1;
        }
      bytes_written += 4;
    }
  else
    {
      utf16_str = g_utf8_to_utf16 (src, -1, NULL, &len, NULL);
      /* Byte swap as required */
      utf16_len = len;
      for (i = 0; i < utf16_len; ++i)
          utf16_str[i] = GINT16_TO_BE (utf16_str[i]);
      utf16_len = GINT32_TO_BE (utf16_len);

      if (fwrite (&utf16_len, 4, 1, f) < 1
          || fwrite (utf16_str, 2, utf16_len + 1, f) < utf16_len + 1)
        {
          psd_set_error (feof (f), errno, error);
          return -1;
        }
      bytes_written += (4 + 2 * utf16_len + 2);
      IFDBG(2) g_debug ("Unicode string: %s, bytes_written: %d",
                        src, bytes_written);
    }

  /* Pad with nulls */
  if (mod_len > 0)
    {
      while (bytes_written % mod_len != 0)
        {
          if (fwrite (&null_str, 1, 1, f) < 1)
            {
              psd_set_error (feof (f), errno, error);
              return -1;
            }
          bytes_written++;
        }
    }

  return bytes_written;
}
Beispiel #12
0
gchar *
fread_unicode_string (gint32         *bytes_read,
                      gint32         *bytes_written,
                      const guint16   mod_len,
                      FILE           *f,
                      GError        **error)
{
  /*
   * Reads a utf-16 string from the file padded to a multiple of mod_len
   * and returns a utf-8 string.
   */

  gchar        *utf8_str;
  gunichar2    *utf16_str;
  gint32        len;
  gint32        i;
  gint32        padded_len;
  glong         utf8_str_len;

  *bytes_read = 0;
  *bytes_written = -1;

  if (fread (&len, 4, 1, f) < 1)
    {
      psd_set_error (feof (f), errno, error);
      return NULL;
    }
  *bytes_read += 4;
  len = GINT32_FROM_BE (len);
  IFDBG(3) g_debug ("Unicode string length %d", len);

  if (len == 0)
    {
      if (fseek (f, mod_len - 1, SEEK_CUR) < 0)
        {
          psd_set_error (feof (f), errno, error);
          return NULL;
        }
      *bytes_read += (mod_len - 1);
      *bytes_written = 0;
      return NULL;
    }

  utf16_str = g_malloc (len * 2);
  for (i = 0; i < len; ++i)
    {
      if (fread (&utf16_str[i], 2, 1, f) < 1)
        {
          psd_set_error (feof (f), errno, error);
          return NULL;
        }
      *bytes_read += 2;
      utf16_str[i] = GINT16_FROM_BE (utf16_str[i]);
    }

  if (mod_len > 0)
    {
      padded_len = len + 1;
      while (padded_len % mod_len != 0)
        {
          if (fseek (f, 1, SEEK_CUR) < 0)
            {
              psd_set_error (feof (f), errno, error);
              return NULL;
            }
          (*bytes_read)++;
          padded_len++;
        }
    }

  utf8_str = g_utf16_to_utf8 (utf16_str, len, NULL, &utf8_str_len, NULL);
  *bytes_written = utf8_str_len;
  g_free (utf16_str);

  IFDBG(3) g_debug ("Unicode string: %s, bytes_read: %d, bytes_written: %d",
                    utf8_str, *bytes_read, *bytes_written);

  return utf8_str;
}
Beispiel #13
0
gint32
fwrite_pascal_string (const gchar    *src,
                      const guint16   mod_len,
                      FILE           *f,
                      GError        **error)
{
  /*
   *  Converts utf-8 string to current locale and writes as pascal
   *  string with padding to a multiple of mod_len.
   */

  gchar        *str;
  gchar        *pascal_str;
  gchar         null_str = 0x0;
  guchar        pascal_len;
  gint32        bytes_written = 0;
  gsize         len;

  if (src == NULL)
    {
       /* Write null string as two null bytes (0x0) */
      if (fwrite (&null_str, 1, 1, f) < 1
          || fwrite (&null_str, 1, 1, f) < 1)
        {
          psd_set_error (feof (f), errno, error);
          return -1;
        }
      bytes_written += 2;
    }
  else
    {
      str = g_locale_from_utf8 (src, -1, NULL, &len, NULL);
      if (len > 255)
        pascal_len = 255;
      else
        pascal_len = len;
      pascal_str = g_strndup (str, pascal_len);
      g_free (str);
      if (fwrite (&pascal_len, 1, 1, f) < 1
          || fwrite (pascal_str, pascal_len, 1, f) < 1)
        {
          psd_set_error (feof (f), errno, error);
          return -1;
        }
      bytes_written++;
      bytes_written += pascal_len;
      IFDBG(2) g_debug ("Pascal string: %s, bytes_written: %d",
                        pascal_str, bytes_written);
    }

  /* Pad with nulls */
  if (mod_len > 0)
    {
      while (bytes_written % mod_len != 0)
        {
          if (fwrite (&null_str, 1, 1, f) < 1)
            {
              psd_set_error (feof (f), errno, error);
              return -1;
            }
          bytes_written++;
        }
    }

  return bytes_written;
}