changeset 83160:c5bae78b527c

Merged in changes from CVS trunk. Patches applied: * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-408 Update from CVS git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-200
author Karoly Lorentey <lorentey@elte.hu>
date Tue, 15 Jun 2004 16:45:35 +0000
parents 38500c0c86ab (current diff) d61ec0ebc281 (diff)
children 8d62eda26760
files lisp/ChangeLog man/ChangeLog src/dispextern.h src/xdisp.c src/xterm.h
diffstat 14 files changed, 402 insertions(+), 124 deletions(-) [+]
line wrap: on
line diff
--- a/etc/NEWS	Mon Jun 14 20:00:54 2004 +0000
+++ b/etc/NEWS	Tue Jun 15 16:45:35 2004 +0000
@@ -16,6 +16,11 @@
 
 * Installation Changes in Emacs 21.4
 
+** Emacs includes now support for loading image libraries on demand.
+(Currently this feature is only used on MS Windows.)  You can configure
+the supported image types and their associated dynamic libraries by
+setting the variable `image-library-alist'.
+
 ---
 ** A Bulgarian translation of the Emacs Tutorial is available.
 
--- a/lisp/ChangeLog	Mon Jun 14 20:00:54 2004 +0000
+++ b/lisp/ChangeLog	Tue Jun 15 16:45:35 2004 +0000
@@ -1,3 +1,14 @@
+2004-06-14  Juanma Barranquero  <lektu@terra.es>
+
+	* image.el (image-library-alist): New variable to map image types
+	to external libraries.  Initialized to nil, unless system-specific
+	configs change it.
+	(image-type-available-p): Determine whether an image type is
+	available by calling `init-image-library'.
+
+	* term/w32-win.el (image-library-alist): Initialize to a known set
+	of probable library names.
+
 2004-06-14  Kenichi Handa  <handa@m17n.org>
 
 	* international/code-pages.el (windows-1256, cp1125): Fix tables
@@ -28,7 +39,7 @@
 	* files.el (before-save-hook): Add `time-stamp' to the options.
 
 	* time-stamp.el (time-stamp): Recommend adding it to
-	`before-save-hook', rather than `write-file-functions'
+	`before-save-hook', rather than `write-file-functions'.
 	Make a similar change in `Commentary' section.
 
 2004-06-13  Kai Grossjohann  <kai.grossjohann@gmx.net>
--- a/lisp/image.el	Mon Jun 14 20:00:54 2004 +0000
+++ b/lisp/image.el	Tue Jun 15 16:45:35 2004 +0000
@@ -1,6 +1,6 @@
 ;;; image.el --- image API
 
-;; Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 99, 2000, 01, 04 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: multimedia
@@ -48,6 +48,17 @@
 with one argument, a string containing the image data.  If PREDICATE returns
 a non-nil value, TYPE is the image's type.")
 
+;;;###autoload
+(defvar image-library-alist nil
+  "Alist of image types vs external libraries needed to display them.
+
+Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
+representing a supported image type, and the rest are strings giving
+alternate filenames for the corresponding external libraries to load.
+They are tried in the order they appear on the list; if none of them can
+be loaded, the running session of Emacs won't display the image type.
+No entries are needed for pbm and xbm images; they're always supported.")
+;;;###autoload (put 'image-library-alist 'risky-local-variable t)
 
 (defun image-jpeg-p (data)
   "Value is non-nil if DATA, a string, consists of JFIF image data.
@@ -111,8 +122,8 @@
 (defun image-type-available-p (type)
   "Value is non-nil if image type TYPE is available.
 Image types are symbols like `xbm' or `jpeg'."
-  (and (boundp 'image-types) (not (null (memq type image-types)))))
-
+  (and (fboundp 'init-image-library)
+       (init-image-library type image-library-alist)))
 
 ;;;###autoload
 (defun create-image (file-or-data &optional type data-p &rest props)
--- a/lisp/term/w32-win.el	Mon Jun 14 20:00:54 2004 +0000
+++ b/lisp/term/w32-win.el	Tue Jun 15 16:45:35 2004 +0000
@@ -1,6 +1,6 @@
 ;;; w32-win.el --- parse switches controlling interface with W32 window system
 
-;; Copyright (C) 1993, 1994, 2003 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1994, 2003, 2004 Free Software Foundation, Inc.
 
 ;; Author: Kevin Gallo
 ;; Keywords: terminals
@@ -1261,5 +1261,13 @@
 	(if (null font)
 	    (error "Font not found")))))
 
+;;; Set default known names for image libraries
+(setq image-library-alist
+      '((xpm "libXpm-nox4.dll" "libxpm.dll")
+        (png "libpng13d.dll" "libpng13.dll" "libpng12d.dll" "libpng12.dll" "libpng.dll")
+        (jpeg "jpeg62.dll" "libjpeg.dll" "jpeg-62.dll" "jpeg.dll")
+        (tiff "libtiff3.dll" "libtiff.dll")
+        (gif "libungif.dll")))
+
 ;;; arch-tag: 69fb1701-28c2-4890-b351-3d1fe4b4f166
 ;;; w32-win.el ends here
--- a/lispref/ChangeLog	Mon Jun 14 20:00:54 2004 +0000
+++ b/lispref/ChangeLog	Tue Jun 15 16:45:35 2004 +0000
@@ -1,3 +1,9 @@
+2004-06-14  Juanma Barranquero  <lektu@terra.es>
+
+	* display.texi (Images): Document new delayed library loading,
+	variable `image-library-alist' and (existing but undocumented)
+	function `image-type-available-p'.
+
 2004-06-05  Richard M. Stallman  <rms@gnu.org>
 
 	* minibuf.texi (Minibuffer Completion): For INITIAL arg,
@@ -41,7 +47,7 @@
 	* lists.texi (Cons Cells): Explain dotted lists, true lists,
 	circular lists.
 	(List Elements): Explain handling of circular and dotted lists.
-	
+
 2004-05-19  Thien-Thi Nguyen  <ttn@gnu.org>
 
 	* modes.texi (Search-based Fontification): Fix typo.
--- a/lispref/display.texi	Mon Jun 14 20:00:54 2004 +0000
+++ b/lispref/display.texi	Tue Jun 15 16:45:35 2004 +0000
@@ -2875,8 +2875,13 @@
 @code{display} property, this feature is available starting in Emacs 21.
 
   Emacs can display a number of different image formats; some of them
-are supported only if particular support libraries are installed on your
-machine.  The supported image formats include XBM, XPM (needing the
+are supported only if particular support libraries are installed on
+your machine.  In some environments, Emacs allows loading image
+libraries on demand; if so, the variable @code{image-library-alist}
+can be used to modify the set of known names for these dynamic
+libraries (though it is not posible to add new image formats).
+
+  The supported image formats include XBM, XPM (needing the
 libraries @code{libXpm} version 3.4k and @code{libz}), GIF (needing
 @code{libungif} 4.1.0), Postscript, PBM, JPEG (needing the
 @code{libjpeg} library version v6a), TIFF (needing @code{libtiff} v3.4),
@@ -2887,10 +2892,48 @@
 @code{pbm}, @code{jpeg}, @code{tiff}, and @code{png}.
 
 @defvar image-types
+@vindex image-types
 This variable contains a list of those image type symbols that are
-supported in the current configuration.
+potentially supported in the current configuration.
+@emph{Potentially} here means that Emacs knows about the image types,
+not necessarily that they can be loaded (they could depend on
+unavailable dynamic libraries, for example).
+
+To know which image types are really available, use
+@code{image-type-available-p}.
 @end defvar
 
+@defvar image-library-alist
+@vindex image-library-alist
+This in an alist of image types vs external libraries needed to
+display them.
+
+Each element is a list @code{(@var{IMAGE-TYPE} @var{LIBRARY}...)},
+where the car is a supported image format from @code{image-types}, and
+the rest are strings giving alternate filenames for the corresponding
+external libraries to load.
+
+They are tried in the order they appear on the list; if none of them
+can be loaded, the running session of Emacs won't support the image
+type.  No entries are needed for @code{pbm} and @code{xbm} images;
+they're always supported.
+
+This variable is ignored if the image libraries are statically linked
+into Emacs.
+@end defvar
+
+@defun  image-type-available-p type
+@findex image-type-available-p
+
+This function returns non-nil if image type TYPE is available, i.e.,
+if images of this type can be loaded and displayed in Emacs.  TYPE
+should be one of the types contained in @code{image-types}.
+
+For image types whose support libraries are statically linked, this
+function always returns @code{t}; for other image types, it returns
+@code{t} if the dynamic library could be loaded, @code{nil} otherwise.
+@end defun
+
 @menu
 * Image Descriptors::   How to specify an image for use in @code{:display}.
 * XBM Images::          Special features for XBM format.
--- a/man/ChangeLog	Mon Jun 14 20:00:54 2004 +0000
+++ b/man/ChangeLog	Tue Jun 15 16:45:35 2004 +0000
@@ -1,3 +1,8 @@
+2004-06-14  Luc Teirlinck  <teirllm@auburn.edu>
+
+	* dired.texi (Dired Enter): Mention conditions on `ls' switches.
+	(Dired and Find): Mention differences with ordinary Dired buffers.
+
 2004-06-13  Luc Teirlinck  <teirllm@auburn.edu>
 
 	* autotype.texi (Copyrights, Timestamps): Recommend
--- a/man/dired.texi	Mon Jun 14 20:00:54 2004 +0000
+++ b/man/dired.texi	Tue Jun 15 16:45:35 2004 +0000
@@ -58,7 +58,9 @@
 give to @code{ls} for listing directory; this string @emph{must} contain
 @samp{-l}.  If you use a numeric prefix argument with the @code{dired}
 command, you can specify the @code{ls} switches with the minibuffer
-before you enter the directory specification.
+before you enter the directory specification.  No matter how they are
+specified, the @code{ls} switches should all be short options (that
+is, single characters) requiring no arguments.
 
 @findex dired-other-window
 @kindex C-x 4 d
@@ -1099,6 +1101,11 @@
 program.  @kbd{M-x locate-with-filter} is similar, but keeps only lines
 matching a given regular expression.
 
+These buffers don't work entirely like ordinary Dired buffers.  File
+operations work, but do not always automatically update the buffer.
+Reverting the buffer with @kbd{g} deletes all inserted subdirectories,
+and erases all flags and marks.
+
 @node Misc Dired Commands
 @section Other Dired Commands
 
--- a/src/ChangeLog	Mon Jun 14 20:00:54 2004 +0000
+++ b/src/ChangeLog	Tue Jun 15 16:45:35 2004 +0000
@@ -1,9 +1,51 @@
+2004-06-14  Jan Dj,Ad(Brv  <jan.h.d@swipnet.se>
+
+	* gtkutil.c (xg_get_image_for_pixmap): New function.
+	(xg_get_gdk_pixmap_and_mask): Removed.
+	(update_frame_tool_bar): Call xg_get_image_for_pixmap instead of
+	xg_get_gdk_pixmap_and_mask.
+	
+	* xterm.h (struct x_display_info): Typo in comment fixed.
+
+2004-06-14  Juanma Barranquero  <lektu@terra.es>
+
+	* dispextern.h (Vimage_types): Make it conditional on
+	HAVE_WINDOW_SYSTEM.
+
+	* image.c (Vimage_types): Move from xdisp.c.
+	(Vimage_type_cache): New variable.
+	(define_image_type): New argument indicating whether an image
+	library was loaded; cache loaded status and return t on success,
+	nil otherwise.
+	(CACHE_IMAGE_TYPE, ADD_IMAGE_TYPE): New macros.
+	(w32_delayed_load): New function to load an image library from a
+	list of possible filenames.
+	(init_xpm_functions, init_png_functions, init_jpeg_functions)
+	(init_tiff_functions, init_gif_functions): Use `w32_delayed_load'.
+	(CHECK_LIB_AVAILABLE): Call `define_image_library' with new
+	argument.
+	(Finit_image_library): New function, extracted from `init_image'.
+	Try to initialize an image library on demand and cache whether we
+	were successful or not.
+	(syms_of_image): Initialize `Vimage_types' and
+	`Vimage_type_cache'.  Add recognized image types to Vimage_types.
+	Export `init-image-library'.
+	(init_image): Remove initialization of all image types, except xbm
+	and pbm.
+
+	* xdisp.c (Vimage_types): Delete (moved to image.c).
+
+2004-06-14  Andreas Schwab  <schwab@suse.de>
+
+	* minibuf.c (Ftry_completion, Fall_completions, Ftest_completion):
+	Avoid calling specbind when completion-regexp-list is empty.
+
 2004-06-13  Richard M. Stallman  <rms@gnu.org>
 
 	* regex.h (CHAR_CLASS_MAX_LENGTH, re_wctype_t, re_wchar_t)
 	(re_wctype, re_iswctype, re_wctype_to_bit):
 	Non-function definitions moved here from regex.c.
-	
+
 	* regex.c (re_wctype, re_iswctype): Function defs longer static.
 	(CHAR_CLASS_MAX_LENGTH, re_wctype_t, re_wchar_t)
 	(re_wctype, re_iswctype, re_wctype_to_bit):
--- a/src/dispextern.h	Mon Jun 14 20:00:54 2004 +0000
+++ b/src/dispextern.h	Tue Jun 15 16:45:35 2004 +0000
@@ -2560,7 +2560,6 @@
 extern Lisp_Object Vshow_trailing_whitespace;
 extern int mode_line_in_non_selected_windows;
 extern int redisplaying_p;
-extern Lisp_Object Vimage_types;
 extern void add_to_log P_ ((char *, Lisp_Object, Lisp_Object));
 extern int help_echo_showing_p;
 extern int current_mode_line_height, current_header_line_height;
@@ -2646,6 +2645,8 @@
 
 #ifdef HAVE_WINDOW_SYSTEM
 
+extern Lisp_Object Vimage_types;
+
 extern int x_bitmap_height P_ ((struct frame *, int));
 extern int x_bitmap_width P_ ((struct frame *, int));
 extern int x_bitmap_pixmap P_ ((struct frame *, int));
--- a/src/gtkutil.c	Mon Jun 14 20:00:54 2004 +0000
+++ b/src/gtkutil.c	Tue Jun 15 16:45:35 2004 +0000
@@ -229,23 +229,100 @@
   return gdk_cursor_new_for_display (gdpy, GDK_LEFT_PTR);
 }
 
-/* For the image defined in IMG, make and return a GdkPixmap for
-   the pixmap in *GPIX, and a GdkBitmap for the mask in *GMASK.
-   If IMG has no mask, *GMASK is set to NULL.
-   The image is defined on the display where frame F is.  */
-static void
-xg_get_gdk_pixmap_and_mask (f, img, gpix, gmask)
+/* For the image defined in IMG, make and return a GtkImage.  For displays with
+   8 planes or less we must make a GdkPixbuf and apply the mask manually.
+   Otherwise the highlightning and dimming the tool bar code in GTK does
+   will look bad.  For display with more than 8 planes we just use the
+   pixmap and mask directly.  For monochrome displays, GTK doesn't seem
+   able to use external pixmaps, it looks bad whatever we do.
+   The image is defined on the display where frame F is.
+   WIDGET is used to find the GdkColormap to use for the GdkPixbuf.
+   If OLD_WIDGET is NULL, a new widget is constructed and returned.
+   If OLD_WIDGET is not NULL, that widget is modified.  */
+static GtkWidget *
+xg_get_image_for_pixmap (f, img, widget, old_widget)
      FRAME_PTR f;
      struct image *img;
-     GdkPixmap **gpix;
-     GdkBitmap **gmask;
+     GtkWidget *widget;
+     GtkImage *old_widget;
 {
+  GdkPixmap *gpix;
+  GdkPixmap *gmask;
   GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f));
 
-  *gpix = gdk_pixmap_foreign_new_for_display (gdpy, img->pixmap);
-  *gmask = img->mask ?
-    (GdkBitmap*) gdk_pixmap_foreign_new_for_display (gdpy, img->mask)
-    : 0;
+  gpix = gdk_pixmap_foreign_new_for_display (gdpy, img->pixmap);
+  gmask = img->mask ? gdk_pixmap_foreign_new_for_display (gdpy, img->mask) : 0;
+
+  if (x_screen_planes (f) > 8 || x_screen_planes (f) == 1)
+    {
+      if (! old_widget)
+        old_widget = GTK_IMAGE (gtk_image_new_from_pixmap (gpix, gmask));
+      else
+        gtk_image_set_from_pixmap (old_widget, gpix, gmask);
+    }
+  else
+    {
+      int x, y, width, height, rowstride, mask_rowstride;
+      GdkPixbuf *icon_buf, *tmp_buf;
+      guchar *pixels;
+      guchar *mask_pixels;
+
+      gdk_drawable_get_size (gpix, &width, &height);
+      tmp_buf = gdk_pixbuf_get_from_drawable (NULL,
+                                              gpix,
+				              gtk_widget_get_colormap (widget),
+                                              0, 0, 0, 0, width, height);
+      icon_buf = gdk_pixbuf_add_alpha (tmp_buf, FALSE, 0, 0, 0);
+      g_object_unref (G_OBJECT (tmp_buf));
+
+      if (gmask)
+        {
+          GdkPixbuf *mask_buf = gdk_pixbuf_get_from_drawable (NULL,
+                                                              gmask,
+                                                              NULL,
+                                                              0, 0, 0, 0,
+                                                              width, height);
+          guchar *pixels = gdk_pixbuf_get_pixels (icon_buf);
+          guchar *mask_pixels = gdk_pixbuf_get_pixels (mask_buf);
+          int rowstride = gdk_pixbuf_get_rowstride (icon_buf);
+          int mask_rowstride = gdk_pixbuf_get_rowstride (mask_buf);
+          int y;
+
+          for (y = 0; y < height; ++y)
+            {
+              guchar *iconptr, *maskptr;
+              int x;
+
+              iconptr = pixels + y * rowstride;
+              maskptr = mask_pixels + y * mask_rowstride;
+
+              for (x = 0; x < width; ++x)
+                {
+                  /* In a bitmap, RGB is either 255/255/255 or 0/0/0.  Checking
+                     just R is sufficient.  */
+                  if (maskptr[0] == 0)
+                    iconptr[3] = 0; /* 0, 1, 2 is R, G, B.  3 is alpha.  */
+
+                  iconptr += rowstride/width;
+                  maskptr += mask_rowstride/width;
+                }
+            }
+
+          g_object_unref (G_OBJECT (gmask));
+          g_object_unref (G_OBJECT (mask_buf));
+        }
+
+      g_object_unref (G_OBJECT (gpix));
+
+      if (! old_widget)
+        old_widget = GTK_IMAGE (gtk_image_new_from_pixbuf (icon_buf));
+      else
+        gtk_image_set_from_pixbuf (old_widget, icon_buf);
+
+      g_object_unref (G_OBJECT (icon_buf));
+    }
+
+  return GTK_WIDGET (old_widget);
 }
 
 
@@ -3205,12 +3282,8 @@
 
       if (! wicon)
         {
-          GdkPixmap *gpix;
-          GdkBitmap *gmask;
-          GtkWidget *w;
-
-          xg_get_gdk_pixmap_and_mask (f, img, &gpix, &gmask);
-          w = gtk_image_new_from_pixmap (gpix, gmask);
+          GtkWidget *w = xg_get_image_for_pixmap (f, img, x->widget, NULL);
+
           gtk_toolbar_append_item (GTK_TOOLBAR (x->toolbar_widget),
                                    0, 0, 0,
                                    w,
@@ -3267,13 +3340,7 @@
           g_list_free (chlist);
 
           if (old_img != img->pixmap)
-            {
-              GdkPixmap *gpix;
-              GdkBitmap *gmask;
-
-              xg_get_gdk_pixmap_and_mask (f, img, &gpix, &gmask);
-              gtk_image_set_from_pixmap (wimage, gpix, gmask);
-            }
+            (void) xg_get_image_for_pixmap (f, img, x->widget, wimage);
 
           g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA,
                              (gpointer)img->pixmap);
--- a/src/image.c	Mon Jun 14 20:00:54 2004 +0000
+++ b/src/image.c	Tue Jun 15 16:45:35 2004 +0000
@@ -606,6 +606,14 @@
 
 static struct image_type *image_types;
 
+/* A list of symbols, one for each supported image type.  */
+
+Lisp_Object Vimage_types;
+
+/* Cache for delayed-loading image types.  */
+
+static Lisp_Object Vimage_type_cache;
+
 /* The symbol `xbm' which is used as the type symbol for XBM images.  */
 
 Lisp_Object Qxbm;
@@ -630,7 +638,7 @@
 
 /* Function prototypes.  */
 
-static void define_image_type P_ ((struct image_type *type));
+static Lisp_Object define_image_type P_ ((struct image_type *type, int loaded));
 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
 static void x_laplace P_ ((struct frame *, struct image *));
@@ -638,21 +646,37 @@
 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
 				       Lisp_Object));
 
+#define CACHE_IMAGE_TYPE(type, status) \
+  do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
+
+#define ADD_IMAGE_TYPE(type) \
+  do { Vimage_types = Fcons (type, Vimage_types); } while (0)
 
 /* Define a new image type from TYPE.  This adds a copy of TYPE to
-   image_types and adds the symbol *TYPE->type to Vimage_types.  */
-
-static void
-define_image_type (type)
+   image_types and caches the loading status of TYPE.  */
+
+static Lisp_Object
+define_image_type (type, loaded)
      struct image_type *type;
-{
-  /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
-     The initialized data segment is read-only.  */
-  struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
-  bcopy (type, p, sizeof *p);
-  p->next = image_types;
-  image_types = p;
-  Vimage_types = Fcons (*p->type, Vimage_types);
+     int loaded;
+{
+  Lisp_Object success;
+
+  if (!loaded)
+    success = Qnil;
+  else
+    {
+      /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
+         The initialized data segment is read-only.  */
+      struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
+      bcopy (type, p, sizeof *p);
+      p->next = image_types;
+      image_types = p;
+      success = Qt;
+    }
+
+  CACHE_IMAGE_TYPE(*type->type, success);
+  return success;
 }
 
 
@@ -1789,6 +1813,33 @@
     if (!fn_##func) return 0;						\
   }
 
+/* Load a DLL implementing an image type.
+   The `image-library-alist' variable associates a symbol,
+   identifying  an image type, to a list of possible filenames.
+   The function returns NULL if no library could be loaded for
+   the given image type, or if the library was previously loaded;
+   else the handle of the DLL.  */
+static HMODULE
+w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
+{
+  HMODULE library = NULL;
+
+  if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
+    {
+      Lisp_Object dlls = Fassq (type, libraries);
+
+      if (CONSP (dlls))
+        for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
+          {
+            CHECK_STRING_CAR (dlls);
+            if (library = LoadLibrary (SDATA (XCAR (dlls))))
+              break;
+          }
+    }
+
+  return library;
+}
+
 #endif /* HAVE_NTGUI */
 
 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
@@ -3489,13 +3540,12 @@
 DEF_IMGLIB_FN (XpmReadFileToImage);
 DEF_IMGLIB_FN (XImageFree);
 
-
 static int
-init_xpm_functions (void)
+init_xpm_functions (Lisp_Object libraries)
 {
   HMODULE library;
 
-  if (!(library = LoadLibrary ("libXpm.dll")))
+  if (!(library = w32_delayed_load (libraries, Qxpm)))
     return 0;
 
   LOAD_IMGLIB_FN (library, XpmFreeAttributes);
@@ -5589,21 +5639,12 @@
 DEF_IMGLIB_FN (png_error);
 
 static int
-init_png_functions (void)
+init_png_functions (Lisp_Object libraries)
 {
   HMODULE library;
 
-  /* Ensure zlib is loaded.  Try debug version first.  */
-  if (!LoadLibrary ("zlibd.dll")
-      && !LoadLibrary ("zlib.dll"))
-    return 0;
-
   /* Try loading libpng under probable names.  */
-  if (!(library = LoadLibrary ("libpng13d.dll"))
-      && !(library = LoadLibrary ("libpng13.dll"))
-      && !(library = LoadLibrary ("libpng12d.dll"))
-      && !(library = LoadLibrary ("libpng12.dll"))
-      && !(library = LoadLibrary ("libpng.dll")))
+  if (!(library = w32_delayed_load (libraries, Qpng)))
     return 0;
 
   LOAD_IMGLIB_FN (library, png_get_io_ptr);
@@ -6247,13 +6288,11 @@
 DEF_IMGLIB_FN (jpeg_resync_to_restart);
 
 static int
-init_jpeg_functions (void)
+init_jpeg_functions (Lisp_Object libraries)
 {
   HMODULE library;
 
-  if (!(library = LoadLibrary ("libjpeg.dll"))
-      && !(library = LoadLibrary ("jpeg-62.dll"))
-      && !(library = LoadLibrary ("jpeg.dll")))
+  if (!(library = w32_delayed_load (libraries, Qjpeg)))
     return 0;
 
   LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
@@ -6684,11 +6723,11 @@
 DEF_IMGLIB_FN (TIFFClose);
 
 static int
-init_tiff_functions (void)
+init_tiff_functions (Lisp_Object libraries)
 {
   HMODULE library;
 
-  if (!(library = LoadLibrary ("libtiff.dll")))
+  if (!(library = w32_delayed_load (libraries, Qtiff)))
     return 0;
 
   LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
@@ -7104,11 +7143,11 @@
 DEF_IMGLIB_FN (DGifOpenFileName);
 
 static int
-init_gif_functions (void)
+init_gif_functions (Lisp_Object libraries)
 {
   HMODULE library;
 
-  if (!(library = LoadLibrary ("libungif.dll")))
+  if (!(library = w32_delayed_load (libraries, Qgif)))
     return 0;
 
   LOAD_IMGLIB_FN (library, DGifCloseFile);
@@ -7881,9 +7920,81 @@
 			    Initialization
  ***********************************************************************/
 
+#ifdef HAVE_NTGUI
+/* Image types that rely on external libraries are loaded dynamically
+   if the library is available.  */
+#define CHECK_LIB_AVAILABLE(image_type, init_lib_fn) \
+  define_image_type (image_type, init_lib_fn (libraries))
+#else
+#define CHECK_LIB_AVAILABLE(image_type, init_lib_fn) \
+  define_image_type (image_type, TRUE)
+#endif /* HAVE_NTGUI */
+
+DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0,
+       doc: /* Initialize image library implementing image type TYPE.
+Return non-nil if TYPE is a supported image type.
+
+Image types pbm and xbm are prebuilt; other types are loaded here.
+Libraries to load are specified in alist LIBRARIES (usually, the value
+of `image-library-alist', which see.  */)
+  (type, libraries)
+{
+  Lisp_Object tested;
+
+  /* Don't try to reload the library.  */
+  tested = Fassq (type, Vimage_type_cache);
+  if (CONSP (tested))
+    return XCDR (tested);
+
+#if defined (HAVE_XPM) || defined (MAC_OS)
+  if (EQ (type, Qxpm))
+    return CHECK_LIB_AVAILABLE(&xpm_type, init_xpm_functions);
+#endif
+
+#if defined (HAVE_JPEG) || defined (MAC_OS)
+  if (EQ (type, Qjpeg))
+    return CHECK_LIB_AVAILABLE(&jpeg_type, init_jpeg_functions);
+#endif
+
+#if defined (HAVE_TIFF) || defined (MAC_OS)
+  if (EQ (type, Qtiff))
+    return CHECK_LIB_AVAILABLE(&tiff_type, init_tiff_functions);
+#endif
+
+#if defined (HAVE_GIF) || defined (MAC_OS)
+  if (EQ (type, Qgif))
+    return CHECK_LIB_AVAILABLE(&gif_type, init_gif_functions);
+#endif
+
+#if defined (HAVE_PNG) || defined (MAC_OS)
+  if (EQ (type, Qpng))
+    return CHECK_LIB_AVAILABLE(&png_type, init_png_functions);
+#endif
+
+#ifdef HAVE_GHOSTSCRIPT
+  if (EQ (type, Qpostscript))
+    return CHECK_LIB_AVAILABLE(&gs_type, init_gs_functions);
+#endif
+
+  /* If the type is not recognized, avoid testing it ever again.  */
+  CACHE_IMAGE_TYPE(type, Qnil);
+  return Qnil;
+}
+
 void
 syms_of_image ()
 {
+  /* Must be defined now becase we're going to update it below, while
+     defining the supported image types.  */
+  DEFVAR_LISP ("image-types", &Vimage_types,
+    doc: /* List of potentially supported image types.
+Each element of the list is a symbol for a image type, like 'jpeg or 'png.
+To check whether it is really supported, use `image-type-available-p'.  */);
+  Vimage_types = Qnil;
+
+  Vimage_type_cache = Qnil;
+  staticpro (&Vimage_type_cache);
+
   QCascent = intern (":ascent");
   staticpro (&QCascent);
   QCmargin = intern (":margin");
@@ -7917,6 +8028,7 @@
   Qpostscript = intern ("postscript");
   staticpro (&Qpostscript);
 #ifdef HAVE_GHOSTSCRIPT
+  ADD_IMAGE_TYPE(Qpostscript);
   QCloader = intern (":loader");
   staticpro (&QCloader);
   QCbounding_box = intern (":bounding-box");
@@ -7929,35 +8041,43 @@
 
   Qpbm = intern ("pbm");
   staticpro (&Qpbm);
+  ADD_IMAGE_TYPE(Qpbm);
 
   Qxbm = intern ("xbm");
   staticpro (&Qxbm);
+  ADD_IMAGE_TYPE(Qxbm);
 
 #if defined (HAVE_XPM) || defined (MAC_OS)
   Qxpm = intern ("xpm");
   staticpro (&Qxpm);
+  ADD_IMAGE_TYPE(Qxpm);
 #endif
 
 #if defined (HAVE_JPEG) || defined (MAC_OS)
   Qjpeg = intern ("jpeg");
   staticpro (&Qjpeg);
+  ADD_IMAGE_TYPE(Qjpeg);
 #endif
 
 #if defined (HAVE_TIFF) || defined (MAC_OS)
   Qtiff = intern ("tiff");
   staticpro (&Qtiff);
+  ADD_IMAGE_TYPE(Qtiff);
 #endif
 
 #if defined (HAVE_GIF) || defined (MAC_OS)
   Qgif = intern ("gif");
   staticpro (&Qgif);
+  ADD_IMAGE_TYPE(Qgif);
 #endif
 
 #if defined (HAVE_PNG) || defined (MAC_OS)
   Qpng = intern ("png");
   staticpro (&Qpng);
+  ADD_IMAGE_TYPE(Qpng);
 #endif
 
+  defsubr (&Sinit_image_library);
   defsubr (&Sclear_image_cache);
   defsubr (&Simage_size);
   defsubr (&Simage_mask_p);
@@ -7985,52 +8105,13 @@
   Vimage_cache_eviction_delay = make_number (30 * 60);
 }
 
-
-#ifdef HAVE_NTGUI
-/* Image types that rely on external libraries are loaded dynamically
-   if the library is available.  */
-#define IF_LIB_AVAILABLE(init_lib_fn)  if (init_lib_fn())
-#else
-#define IF_LIB_AVAILABLE(init_func)    /* Load unconditionally */
-#endif /* HAVE_NTGUI */
-
 void
 init_image ()
 {
   image_types = NULL;
-  Vimage_types = Qnil;
-
-  define_image_type (&xbm_type);
-  define_image_type (&pbm_type);
-
-#if defined (HAVE_XPM) || defined (MAC_OS)
-  IF_LIB_AVAILABLE(init_xpm_functions)
-    define_image_type (&xpm_type);
-#endif
-
-#if defined (HAVE_JPEG) || defined (MAC_OS)
-  IF_LIB_AVAILABLE(init_jpeg_functions)
-    define_image_type (&jpeg_type);
-#endif
-
-#if defined (HAVE_TIFF) || defined (MAC_OS)
-  IF_LIB_AVAILABLE(init_tiff_functions)
-    define_image_type (&tiff_type);
-#endif
-
-#if defined (HAVE_GIF) || defined (MAC_OS)
-  IF_LIB_AVAILABLE(init_gif_functions)
-    define_image_type (&gif_type);
-#endif
-
-#if defined (HAVE_PNG) || defined (MAC_OS)
-  IF_LIB_AVAILABLE(init_png_functions)
-    define_image_type (&png_type);
-#endif
-
-#ifdef HAVE_GHOSTSCRIPT
-  define_image_type (&gs_type);
-#endif
+
+  define_image_type (&xbm_type, TRUE);
+  define_image_type (&pbm_type, TRUE);
 
 #ifdef MAC_OS
   /* Animated gifs use QuickTime Movie Toolbox.  So initialize it here. */
--- a/src/xdisp.c	Mon Jun 14 20:00:54 2004 +0000
+++ b/src/xdisp.c	Tue Jun 15 16:45:35 2004 +0000
@@ -670,10 +670,6 @@
 /* How much to scroll horizontally when point is inside the above margin.  */
 Lisp_Object Vhscroll_step;
 
-/* A list of symbols, one for each supported image type.  */
-
-Lisp_Object Vimage_types;
-
 /* The variable `resize-mini-windows'.  If nil, don't resize
    mini-windows.  If t, always resize them to fit the text they
    display.  If `grow-only', let mini-windows grow only until they
@@ -22259,11 +22255,6 @@
 and `scroll-right' overrides this variable's effect.  */);
   Vhscroll_step = make_number (0);
 
-  DEFVAR_LISP ("image-types", &Vimage_types,
-    doc: /* List of supported image types.
-Each element of the list is a symbol for a supported image type.  */);
-  Vimage_types = Qnil;
-
   DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines,
     doc: /* If non-nil, messages are truncated instead of resizing the echo area.
 Bind this around calls to `message' to let it take effect.  */);
--- a/src/xterm.h	Mon Jun 14 20:00:54 2004 +0000
+++ b/src/xterm.h	Tue Jun 15 16:45:35 2004 +0000
@@ -167,7 +167,7 @@
   /* The colormap being used.  */
   Colormap cmap;
 
-  /* Number of panes on this screen.  */
+  /* Number of planes on this screen.  */
   int n_planes;
 
   /* Dimensions of this screen.  */