]> code.delx.au - gnu-emacs/blobdiff - src/image.c
* xdisp.c (cursor_type_changed): Now static.
[gnu-emacs] / src / image.c
index 7ecd59d27b4e62c89788ba3e51cc63356a4e010b..d93d1b517bfa7178a75908f45bb8bbf2c0a936b6 100644 (file)
@@ -164,20 +164,20 @@ XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel)
 /* Functions to access the contents of a bitmap, given an id.  */
 
 int
-x_bitmap_height (FRAME_PTR f, ptrdiff_t id)
+x_bitmap_height (struct frame *f, ptrdiff_t id)
 {
   return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
 }
 
 int
-x_bitmap_width (FRAME_PTR f, ptrdiff_t id)
+x_bitmap_width (struct frame *f, ptrdiff_t id)
 {
   return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
 }
 
 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
 ptrdiff_t
-x_bitmap_pixmap (FRAME_PTR f, ptrdiff_t id)
+x_bitmap_pixmap (struct frame *f, ptrdiff_t id)
 {
   /* HAVE_NTGUI needs the explicit cast here.  */
   return (ptrdiff_t) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
@@ -186,7 +186,7 @@ x_bitmap_pixmap (FRAME_PTR f, ptrdiff_t id)
 
 #ifdef HAVE_X_WINDOWS
 int
-x_bitmap_mask (FRAME_PTR f, ptrdiff_t id)
+x_bitmap_mask (struct frame *f, ptrdiff_t id)
 {
   return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
 }
@@ -195,7 +195,7 @@ x_bitmap_mask (FRAME_PTR f, ptrdiff_t id)
 /* Allocate a new bitmap record.  Returns index of new record.  */
 
 static ptrdiff_t
-x_allocate_bitmap_record (FRAME_PTR f)
+x_allocate_bitmap_record (struct frame *f)
 {
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   ptrdiff_t i;
@@ -216,7 +216,7 @@ x_allocate_bitmap_record (FRAME_PTR f)
 /* Add one reference to the reference count of the bitmap with id ID.  */
 
 void
-x_reference_bitmap (FRAME_PTR f, ptrdiff_t id)
+x_reference_bitmap (struct frame *f, ptrdiff_t id)
 {
   ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
 }
@@ -316,7 +316,6 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file)
   int xhot, yhot, result;
   ptrdiff_t id;
   Lisp_Object found;
-  int fd;
   char *filename;
 
   /* Look for an existing bitmap with the same name.  */
@@ -332,10 +331,8 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file)
     }
 
   /* Search bitmap-file-path for the file, if appropriate.  */
-  fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
-  if (fd < 0)
+  if (openp (Vx_bitmap_file_path, file, Qnil, &found, make_number (R_OK)) < 0)
     return -1;
-  emacs_close (fd);
 
   filename = SSDATA (found);
 
@@ -387,7 +384,7 @@ free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm)
 /* Remove reference to bitmap with id number ID.  */
 
 void
-x_destroy_bitmap (FRAME_PTR f, ptrdiff_t id)
+x_destroy_bitmap (struct frame *f, ptrdiff_t id)
 {
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
@@ -1572,7 +1569,7 @@ which is then usually a filename.  */)
 
 DEFUN ("image-flush", Fimage_flush, Simage_flush,
        1, 2, 0,
-       doc: /* Fush the image with specification SPEC on frame FRAME.
+       doc: /* Flush the image with specification SPEC on frame FRAME.
 This removes the image from the Emacs image cache.  If SPEC specifies
 an image file, the next redisplay of this image will read from the
 current contents of that file.
@@ -2260,7 +2257,8 @@ x_find_image_file (Lisp_Object file)
   else
     {
       file_found = ENCODE_FILE (file_found);
-      close (fd);
+      if (fd != -2)
+       emacs_close (fd);
     }
 
   return file_found;
@@ -2278,23 +2276,28 @@ slurp_file (char *file, ptrdiff_t *size)
   unsigned char *buf = NULL;
   struct stat st;
 
-  if (fp && fstat (fileno (fp), &st) == 0
-      && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
-      && (buf = xmalloc (st.st_size),
-         fread (buf, 1, st.st_size, fp) == st.st_size))
-    {
-      *size = st.st_size;
-      fclose (fp);
-    }
-  else
+  if (fp)
     {
-      if (fp)
-       fclose (fp);
-      if (buf)
+      ptrdiff_t count = SPECPDL_INDEX ();
+      record_unwind_protect_ptr (fclose_unwind, fp);
+
+      if (fstat (fileno (fp), &st) == 0
+         && 0 <= st.st_size && st.st_size < min (PTRDIFF_MAX, SIZE_MAX))
        {
-         xfree (buf);
-         buf = NULL;
+         /* Report an error if we read past the purported EOF.
+            This can happen if the file grows as we read it.  */
+         ptrdiff_t buflen = st.st_size;
+         buf = xmalloc (buflen + 1);
+         if (fread (buf, 1, buflen + 1, fp) == buflen)
+           *size = buflen;
+         else
+           {
+             xfree (buf);
+             buf = NULL;
+           }
        }
+
+      unbind_to (count, Qnil);
     }
 
   return buf;
@@ -3329,7 +3332,7 @@ static int
 xpm_alloc_color (Display *dpy, Colormap cmap, char *color_name, XColor *color,
                 void *closure)
 {
-  return xpm_lookup_color ((struct frame *) closure, color_name, color);
+  return xpm_lookup_color (closure, color_name, color);
 }
 
 
@@ -5649,8 +5652,7 @@ struct png_memory_storage
 static void
 png_read_from_memory (png_structp png_ptr, png_bytep data, png_size_t length)
 {
-  struct png_memory_storage *tbr
-    = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
+  struct png_memory_storage *tbr = fn_png_get_io_ptr (png_ptr);
 
   if (length > tbr->len - tbr->index)
     fn_png_error (png_ptr, "Read error");
@@ -5667,7 +5669,7 @@ png_read_from_memory (png_structp png_ptr, png_bytep data, png_size_t length)
 static void
 png_read_from_file (png_structp png_ptr, png_bytep data, png_size_t length)
 {
-  FILE *fp = (FILE *) fn_png_get_io_ptr (png_ptr);
+  FILE *fp = fn_png_get_io_ptr (png_ptr);
 
   if (fread (data, 1, length, fp) < length)
     fn_png_error (png_ptr, "Read error");
@@ -5734,8 +5736,8 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
       if (fread (sig, 1, sizeof sig, fp) != sizeof sig
          || fn_png_sig_cmp (sig, 0, sizeof sig))
        {
-         image_error ("Not a PNG file: `%s'", file, Qnil);
          fclose (fp);
+         image_error ("Not a PNG file: `%s'", file, Qnil);
          return 0;
        }
     }
@@ -5811,9 +5813,9 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
 
   /* Read image info.  */
   if (!NILP (specified_data))
-    fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
+    fn_png_set_read_fn (png_ptr, &tbr, png_read_from_memory);
   else
-    fn_png_set_read_fn (png_ptr, (void *) fp, png_read_from_file);
+    fn_png_set_read_fn (png_ptr, fp, png_read_from_file);
 
   fn_png_set_sig_bytes (png_ptr, sizeof sig);
   fn_png_read_info (png_ptr, info_ptr);
@@ -6303,7 +6305,7 @@ our_memory_fill_input_buffer (j_decompress_ptr cinfo)
 static void
 our_memory_skip_input_data (j_decompress_ptr cinfo, long int num_bytes)
 {
-  struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
+  struct jpeg_source_mgr *src = cinfo->src;
 
   if (src)
     {
@@ -6323,19 +6325,17 @@ our_memory_skip_input_data (j_decompress_ptr cinfo, long int num_bytes)
 static void
 jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, ptrdiff_t len)
 {
-  struct jpeg_source_mgr *src;
+  struct jpeg_source_mgr *src = cinfo->src;
 
-  if (cinfo->src == NULL)
+  if (! src)
     {
       /* First time for this JPEG object?  */
-      cinfo->src = (struct jpeg_source_mgr *)
-       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
-                                   sizeof (struct jpeg_source_mgr));
-      src = (struct jpeg_source_mgr *) cinfo->src;
+      src = cinfo->mem->alloc_small ((j_common_ptr) cinfo,
+                                    JPOOL_PERMANENT, sizeof *src);
+      cinfo->src = src;
       src->next_input_byte = data;
     }
 
-  src = (struct jpeg_source_mgr *) cinfo->src;
   src->init_source = our_common_init_source;
   src->fill_input_buffer = our_memory_fill_input_buffer;
   src->skip_input_data = our_memory_skip_input_data;
@@ -6427,20 +6427,17 @@ our_stdio_skip_input_data (j_decompress_ptr cinfo, long int num_bytes)
 static void
 jpeg_file_src (j_decompress_ptr cinfo, FILE *fp)
 {
-  struct jpeg_stdio_mgr *src;
+  struct jpeg_stdio_mgr *src = (struct jpeg_stdio_mgr *) cinfo->src;
 
-  if (cinfo->src != NULL)
-      src = (struct jpeg_stdio_mgr *) cinfo->src;
-  else
+  if (! src)
     {
       /* First time for this JPEG object?  */
-      cinfo->src = (struct jpeg_source_mgr *)
-        (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
-                                    sizeof (struct jpeg_stdio_mgr));
-      src = (struct jpeg_stdio_mgr *) cinfo->src;
-      src->buffer = (JOCTET *)
-          (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
-                                      JPEG_STDIO_BUFFER_SIZE);
+      src = cinfo->mem->alloc_small ((j_common_ptr) cinfo,
+                                    JPOOL_PERMANENT, sizeof *src);
+      cinfo->src = (struct jpeg_source_mgr *) src;
+      src->buffer = cinfo->mem->alloc_small ((j_common_ptr) cinfo,
+                                            JPOOL_PERMANENT,
+                                            JPEG_STDIO_BUFFER_SIZE);
     }
 
   src->file = fp;
@@ -7583,8 +7580,7 @@ gif_load (struct frame *f, struct image *img)
              delay |= ext->Bytes[1];
            }
        }
-      img->lisp_data = Fcons (Qextension_data,
-                             Fcons (img->lisp_data, Qnil));
+      img->lisp_data = list2 (Qextension_data, img->lisp_data);
       if (delay)
        img->lisp_data
          = Fcons (Qdelay,
@@ -7744,6 +7740,7 @@ enum imagemagick_keyword_index
     IMAGEMAGICK_WIDTH,
     IMAGEMAGICK_MAX_HEIGHT,
     IMAGEMAGICK_MAX_WIDTH,
+    IMAGEMAGICK_FORMAT,
     IMAGEMAGICK_ROTATION,
     IMAGEMAGICK_CROP,
     IMAGEMAGICK_LAST
@@ -7768,6 +7765,7 @@ static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] =
     {":width",         IMAGE_INTEGER_VALUE,                    0},
     {":max-height",    IMAGE_INTEGER_VALUE,                    0},
     {":max-width",     IMAGE_INTEGER_VALUE,                    0},
+    {":format",                IMAGE_SYMBOL_VALUE,                     0},
     {":rotation",      IMAGE_NUMBER_VALUE,                     0},
     {":crop",          IMAGE_DONT_CHECK_VALUE_TYPE,            0}
   };
@@ -7846,6 +7844,30 @@ imagemagick_error (MagickWand *wand)
   description = (char *) MagickRelinquishMemory (description);
 }
 
+/* Possibly give ImageMagick some extra help to determine the image
+   type by supplying a "dummy" filename based on the Content-Type.  */
+
+static char *
+imagemagick_filename_hint (Lisp_Object spec, char hint_buffer[MaxTextExtent])
+{
+  Lisp_Object symbol = intern ("image-format-suffixes");
+  Lisp_Object val = find_symbol_value (symbol);
+  Lisp_Object format;
+
+  if (! CONSP (val))
+    return NULL;
+
+  format = image_spec_value (spec, intern (":format"), NULL);
+  val = Fcar_safe (Fcdr_safe (Fassq (format, val)));
+  if (! STRINGP (val))
+    return NULL;
+
+  /* It's OK to truncate the hint if it has MaxTextExtent or more bytes,
+     as ImageMagick would ignore the extra bytes anyway.  */
+  snprintf (hint_buffer, MaxTextExtent, "/tmp/foo.%s", SSDATA (val));
+  return hint_buffer;
+}
+
 /* Helper function for imagemagick_load, which does the actual loading
    given contents and size, apart from frame and image structures,
    passed from imagemagick_load.  Uses librimagemagick to do most of
@@ -7879,6 +7901,8 @@ imagemagick_load_image (struct frame *f, struct image *img,
   int desired_width, desired_height;
   double rotation;
   int pixelwidth;
+  char hint_buffer[MaxTextExtent];
+  char *filename_hint = NULL;
 
   /* Handle image index for image types who can contain more than one image.
      Interface :index is same as for GIF.  First we "ping" the image to see how
@@ -7892,9 +7916,14 @@ imagemagick_load_image (struct frame *f, struct image *img,
   ping_wand = NewMagickWand ();
   /* MagickSetResolution (ping_wand, 2, 2);   (Bug#10112)  */
 
-  status = filename
-    ? MagickPingImage (ping_wand, filename)
-    : MagickPingImageBlob (ping_wand, contents, size);
+  if (filename)
+    status = MagickPingImage (ping_wand, filename);
+  else
+    {
+      filename_hint = imagemagick_filename_hint (img->spec, hint_buffer);
+      MagickSetFilename (ping_wand, filename_hint);
+      status = MagickPingImageBlob (ping_wand, contents, size);
+    }
 
   if (status == MagickFalse)
     {
@@ -7924,10 +7953,15 @@ imagemagick_load_image (struct frame *f, struct image *img,
 
   image_wand = NewMagickWand ();
 
-  if ((filename
-       ? MagickReadImage (image_wand, filename)
-       : MagickReadImageBlob (image_wand, contents, size))
-      == MagickFalse)
+  if (filename)
+    status = MagickReadImage (image_wand, filename);
+  else
+    {
+      MagickSetFilename (image_wand, filename_hint);
+      status = MagickReadImageBlob (image_wand, contents, size);
+    }
+
+  if (status == MagickFalse)
     {
       imagemagick_error (image_wand);
       goto imagemagick_error;
@@ -8054,7 +8088,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
 
   init_color_table ();
 
-#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS
+#if defined (HAVE_MAGICKEXPORTIMAGEPIXELS) && ! defined (HAVE_NS)
   if (imagemagick_render_type != 0)
     {
       /* Magicexportimage is normally faster than pixelpushing.  This
@@ -8118,7 +8152,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
 
       /* Copy pixels from the imagemagick image structure to the x image map. */
       iterator = NewPixelIterator (image_wand);
-      if (iterator == (PixelIterator *) NULL)
+      if (! iterator)
         {
 #ifdef COLOR_TABLE_SUPPORT
          free_color_table ();
@@ -8133,7 +8167,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
       for (y = 0; y < image_height; y++)
         {
           pixels = PixelGetNextIteratorRow (iterator, &width);
-          if (pixels == (PixelWand **) NULL)
+          if (! pixels)
             break;
           for (x = 0; x < (long) width; x++)
             {
@@ -9198,7 +9232,7 @@ A cross is always drawn on black & white displays.  */);
 
   DEFVAR_LISP ("x-bitmap-file-path", Vx_bitmap_file_path,
     doc: /* List of directories to search for window system bitmap files.  */);
-  Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
+  Vx_bitmap_file_path = decode_env_path (0, PATH_BITMAPS);
 
   DEFVAR_LISP ("image-cache-eviction-delay", Vimage_cache_eviction_delay,
     doc: /* Maximum time after which images are removed from the cache.