]> code.delx.au - gnu-emacs/blobdiff - src/xfns.c
Rewritten to take advantage of shy-groups and
[gnu-emacs] / src / xfns.c
index d23d4f0f38442d1570636331ba13e6628de16edc..cf2ba14bb956aa6baca6c140aa3f759db739c68e 100644 (file)
@@ -236,7 +236,7 @@ Lisp_Object Quser_position;
 Lisp_Object Quser_size;
 extern Lisp_Object Qdisplay;
 Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
-Lisp_Object Qscreen_gamma;
+Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
 
 /* The below are defined in frame.c.  */
 
@@ -740,6 +740,7 @@ struct x_frame_parm_table
 
 static void x_create_im P_ ((struct frame *));
 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
+static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
 void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
@@ -775,30 +776,31 @@ static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
 
 static struct x_frame_parm_table x_frame_parms[] =
 {
-  "auto-raise", x_set_autoraise,
-  "auto-lower", x_set_autolower,
-  "background-color", x_set_background_color,
-  "border-color", x_set_border_color,
-  "border-width", x_set_border_width,
-  "cursor-color", x_set_cursor_color,
-  "cursor-type", x_set_cursor_type,
-  "font", x_set_font,
-  "foreground-color", x_set_foreground_color,
-  "icon-name", x_set_icon_name,
-  "icon-type", x_set_icon_type,
-  "internal-border-width", x_set_internal_border_width,
-  "menu-bar-lines", x_set_menu_bar_lines,
-  "mouse-color", x_set_mouse_color,
-  "name", x_explicitly_set_name,
-  "scroll-bar-width", x_set_scroll_bar_width,
-  "title", x_set_title,
-  "unsplittable", x_set_unsplittable,
-  "vertical-scroll-bars", x_set_vertical_scroll_bars,
-  "visibility", x_set_visibility,
-  "tool-bar-lines", x_set_tool_bar_lines,
-  "scroll-bar-foreground", x_set_scroll_bar_foreground,
-  "scroll-bar-background", x_set_scroll_bar_background,
-  "screen-gamma", x_set_screen_gamma
+  "auto-raise",                        x_set_autoraise,
+  "auto-lower",                        x_set_autolower,
+  "background-color",          x_set_background_color,
+  "border-color",              x_set_border_color,
+  "border-width",              x_set_border_width,
+  "cursor-color",              x_set_cursor_color,
+  "cursor-type",               x_set_cursor_type,
+  "font",                      x_set_font,
+  "foreground-color",          x_set_foreground_color,
+  "icon-name",                 x_set_icon_name,
+  "icon-type",                 x_set_icon_type,
+  "internal-border-width",     x_set_internal_border_width,
+  "menu-bar-lines",            x_set_menu_bar_lines,
+  "mouse-color",               x_set_mouse_color,
+  "name",                      x_explicitly_set_name,
+  "scroll-bar-width",          x_set_scroll_bar_width,
+  "title",                     x_set_title,
+  "unsplittable",              x_set_unsplittable,
+  "vertical-scroll-bars",      x_set_vertical_scroll_bars,
+  "visibility",                        x_set_visibility,
+  "tool-bar-lines",            x_set_tool_bar_lines,
+  "scroll-bar-foreground",     x_set_scroll_bar_foreground,
+  "scroll-bar-background",     x_set_scroll_bar_background,
+  "screen-gamma",              x_set_screen_gamma,
+  "line-spacing",              x_set_line_spacing
 };
 
 /* Attach the `x-frame-parameter' properties to
@@ -1288,6 +1290,26 @@ x_decode_color (f, color_name, mono_color)
 
 
 \f
+/* Change the `line-spacing' frame parameter of frame F.  OLD_VALUE is
+   the previous value of that parameter, NEW_VALUE is the new value.  */
+
+static void
+x_set_line_spacing (f, new_value, old_value)
+     struct frame *f;
+     Lisp_Object new_value, old_value;
+{
+  if (NILP (new_value))
+    f->extra_line_spacing = 0;
+  else if (NATNUMP (new_value))
+    f->extra_line_spacing = XFASTINT (new_value);
+  else
+    Fsignal (Qerror, Fcons (build_string ("Illegal line-spacing"),
+                           Fcons (new_value, Qnil)));
+  if (FRAME_VISIBLE_P (f))
+    redraw_frame (f);
+}
+
+
 /* Change the `screen-gamma' frame parameter of frame F.  OLD_VALUE is
    the previous value of that parameter, NEW_VALUE is the new value.  */
 
@@ -4022,6 +4044,8 @@ This function is an internal primitive--use `make-frame' instead.")
                       "borderColor", "BorderColor", RES_TYPE_STRING);
   x_default_parameter (f, parms, Qscreen_gamma, Qnil,
                       "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
+  x_default_parameter (f, parms, Qline_spacing, Qnil,
+                      "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
 
   x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
                                        "scrollBarForeground",
@@ -4873,10 +4897,6 @@ x_sync (f)
 
 static struct image_type *image_types;
 
-/* A list of symbols, one for each supported image type.  */
-
-Lisp_Object Vimage_types;
-
 /* The symbol `image' which is the car of the lists used to represent
    images in Lisp.  */
 
@@ -5000,6 +5020,7 @@ enum image_value_type
   IMAGE_SYMBOL_VALUE,
   IMAGE_POSITIVE_INTEGER_VALUE,
   IMAGE_NON_NEGATIVE_INTEGER_VALUE,
+  IMAGE_ASCENT_VALUE,
   IMAGE_INTEGER_VALUE,
   IMAGE_FUNCTION_VALUE,
   IMAGE_NUMBER_VALUE,
@@ -5102,6 +5123,15 @@ parse_image_spec (spec, keywords, nkeywords, type)
            return 0;
          break;
 
+       case IMAGE_ASCENT_VALUE:
+         if (SYMBOLP (value) && EQ (value, Qcenter))
+           break;
+         else if (INTEGERP (value)
+                  && XINT (value) >= 0
+                  && XINT (value) <= 100)
+           break;
+         return 0;
+             
        case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
          if (!INTEGERP (value) || XINT (value) < 0)
            return 0;
@@ -5264,6 +5294,31 @@ prepare_image_for_display (f, img)
 }
      
 
+/* Value is the number of pixels for the ascent of image IMG when
+   drawn in face FACE.  */
+
+int
+image_ascent (img, face)
+     struct image *img;
+     struct face *face;
+{
+  int height = img->height + img->margin;
+  int ascent;
+
+  if (img->ascent == CENTERED_IMAGE_ASCENT)
+    {
+      if (face->font)
+       ascent = height / 2 - (face->font->descent - face->font->ascent) / 2;
+      else
+       ascent = height / 2;
+    }
+  else
+    ascent = height * img->ascent / 100.0;
+
+  return ascent;
+}
+
+
 \f
 /***********************************************************************
                  Helper functions for X image types
@@ -5516,13 +5571,15 @@ lookup_image (f, spec)
       else
        {
          /* Handle image type independent image attributes
-            `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'.  */
+            `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'.  */
          Lisp_Object ascent, margin, relief, algorithm, heuristic_mask;
          Lisp_Object file;
 
          ascent = image_spec_value (spec, QCascent, NULL);
          if (INTEGERP (ascent))
            img->ascent = XFASTINT (ascent);
+         else if (EQ (ascent, Qcenter))
+           img->ascent = CENTERED_IMAGE_ASCENT;
          
          margin = image_spec_value (spec, QCmargin, NULL);
          if (INTEGERP (margin) && XINT (margin) >= 0)
@@ -5713,10 +5770,12 @@ x_put_x_image (f, ximg, pixmap, width, height)
 
 \f
 /***********************************************************************
-                             Searching files
+                             File Handling
  ***********************************************************************/
 
 static Lisp_Object x_find_image_file P_ ((Lisp_Object));
+static char *slurp_file P_ ((char *, int *));
+
 
 /* Find image file FILE.  Look in data-directory, then
    x-bitmap-file-path.  Value is the full name of the file found, or
@@ -5747,17 +5806,55 @@ x_find_image_file (file)
 }
 
 
+/* Read FILE into memory.  Value is a pointer to a buffer allocated
+   with xmalloc holding FILE's contents.  Value is null if an error
+   occured.  *SIZE is set to the size of the file.  */
+
+static char *
+slurp_file (file, size)
+     char *file;
+     int *size;
+{
+  FILE *fp = NULL;
+  char *buf = NULL;
+  struct stat st;
+
+  if (stat (file, &st) == 0
+      && (fp = fopen (file, "r")) != NULL
+      && (buf = (char *) xmalloc (st.st_size),
+         fread (buf, 1, st.st_size, fp) == st.st_size))
+    {
+      *size = st.st_size;
+      fclose (fp);
+    }
+  else
+    {
+      if (fp)
+       fclose (fp);
+      if (buf)
+       {
+         xfree (buf);
+         buf = NULL;
+       }
+    }
+  
+  return buf;
+}
+
+
 \f
 /***********************************************************************
                              XBM images
  ***********************************************************************/
 
+static int xbm_scan P_ ((char **, char *, char *, int *));
 static int xbm_load P_ ((struct frame *f, struct image *img));
-static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
-                                        Lisp_Object file));
+static int xbm_load_image P_ ((struct frame *f, struct image *img,
+                              char *, char *));
 static int xbm_image_p P_ ((Lisp_Object object));
-static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
-                                         unsigned char **));
+static int xbm_read_bitmap_data P_ ((char *, char *, int *, int *,
+                                    unsigned char **));
+static int xbm_file_p P_ ((Lisp_Object));
 
 
 /* Indices of image specification fields in xbm_format, below.  */
@@ -5791,7 +5888,7 @@ static struct image_keyword xbm_format[XBM_LAST] =
   {":data",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":foreground",      IMAGE_STRING_VALUE,                     0},
   {":background",      IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -5838,6 +5935,10 @@ enum xbm_token
    3. a vector of strings or bool-vectors, one for each line of the
    bitmap.
 
+   4. A string containing an in-memory XBM file.  WIDTH and HEIGHT
+   may not be specified in this case because they are defined in the
+   XBM file.
+
    Both the file and data forms may contain the additional entries
    `:background COLOR' and `:foreground COLOR'.  If not present,
    foreground and background of the frame on which the image is
@@ -5860,6 +5961,12 @@ xbm_image_p (object)
       if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
        return 0;
     }
+  else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
+    {
+      /* In-memory XBM file.  */
+      if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
+       return 0;
+    }
   else
     {
       Lisp_Object data;
@@ -5921,11 +6028,6 @@ xbm_image_p (object)
        return 0;
     }
 
-  /* Baseline must be a value between 0 and 100 (a percentage).  */
-  if (kw[XBM_ASCENT].count
-      && XFASTINT (kw[XBM_ASCENT].value) > 100)
-    return 0;
-  
   return 1;
 }
 
@@ -5937,30 +6039,31 @@ xbm_image_p (object)
    scanning a number, store its value in *IVAL.  */
 
 static int
-xbm_scan (fp, sval, ival)
-     FILE *fp;
+xbm_scan (s, end, sval, ival)
+     char **s, *end;
      char *sval;
      int *ival;
 {
   int c;
   
   /* Skip white space.  */
-  while ((c = fgetc (fp)) != EOF && isspace (c))
+  while (*s < end && (c = *(*s)++, isspace (c)))
     ;
 
-  if (c == EOF)
+  if (*s >= end)
     c = 0;
   else if (isdigit (c))
     {
       int value = 0, digit;
       
-      if (c == '0')
+      if (c == '0' && *s < end)
        {
-         c = fgetc (fp);
+         c = *(*s)++;
          if (c == 'x' || c == 'X')
            {
-             while ((c = fgetc (fp)) != EOF)
+             while (*s < end)
                {
+                 c = *(*s)++;
                  if (isdigit (c))
                    digit = c - '0';
                  else if (c >= 'a' && c <= 'f')
@@ -5975,33 +6078,33 @@ xbm_scan (fp, sval, ival)
          else if (isdigit (c))
            {
              value = c - '0';
-             while ((c = fgetc (fp)) != EOF
-                    && isdigit (c))
+             while (*s < end
+                    && (c = *(*s)++, isdigit (c)))
                value = 8 * value + c - '0';
            }
        }
       else
        {
          value = c - '0';
-         while ((c = fgetc (fp)) != EOF
-                && isdigit (c))
+         while (*s < end
+                && (c = *(*s)++, isdigit (c)))
            value = 10 * value + c - '0';
        }
 
-      if (c != EOF)
-       ungetc (c, fp);
+      if (*s < end)
+       *s = *s - 1;
       *ival = value;
       c = XBM_TK_NUMBER;
     }
   else if (isalpha (c) || c == '_')
     {
       *sval++ = c;
-      while ((c = fgetc (fp)) != EOF
-            && (isalnum (c) || c == '_'))
+      while (*s < end
+            && (c = *(*s)++, (isalnum (c) || c == '_')))
        *sval++ = c;
       *sval = 0;
-      if (c != EOF)
-       ungetc (c, fp);
+      if (*s < end)
+       *s = *s - 1;
       c = XBM_TK_IDENT;
     }
 
@@ -6010,18 +6113,19 @@ xbm_scan (fp, sval, ival)
 
 
 /* Replacement for XReadBitmapFileData which isn't available under old
-   X versions.  FILE is the name of the bitmap file to read.  Set
-   *WIDTH and *HEIGHT to the width and height of the image.  Return in
-   *DATA the bitmap data allocated with xmalloc.  Value is non-zero if
-   successful.  */
+   X versions.  CONTENTS is a pointer to a buffer to parse; END is the
+   buffer's end.  Set *WIDTH and *HEIGHT to the width and height of
+   the image.  Return in *DATA the bitmap data allocated with xmalloc.
+   Value is non-zero if successful.  DATA null means just test if
+   CONTENTS looks like an im-memory XBM file.  */
 
 static int
-xbm_read_bitmap_file_data (file, width, height, data)
-     char *file;
+xbm_read_bitmap_data (contents, end, width, height, data)
+     char *contents, *end;
      int *width, *height;
      unsigned char **data;
 {
-  FILE *fp;
+  char *s = contents;
   char buffer[BUFSIZ];
   int padding_p = 0;
   int v10 = 0;
@@ -6031,7 +6135,7 @@ xbm_read_bitmap_file_data (file, width, height, data)
   int LA1;
 
 #define match() \
-     LA1 = xbm_scan (fp, buffer, &value)
+     LA1 = xbm_scan (&s, end, buffer, &value)
 
 #define expect(TOKEN)          \
      if (LA1 != (TOKEN))       \
@@ -6045,13 +6149,10 @@ xbm_read_bitmap_file_data (file, width, height, data)
      else                                                      \
        goto failure
 
-  fp = fopen (file, "r");
-  if (fp == NULL)
-    return 0;
-
   *width = *height = -1;
-  *data = NULL;
-  LA1 = xbm_scan (fp, buffer, &value);
+  if (data)
+    *data = NULL;
+  LA1 = xbm_scan (&s, end, buffer, &value);
 
   /* Parse defines for width, height and hot-spots.  */
   while (LA1 == '#')
@@ -6074,6 +6175,8 @@ xbm_read_bitmap_file_data (file, width, height, data)
 
   if (*width < 0 || *height < 0)
     goto failure;
+  else if (data == NULL)
+    goto success;
 
   /* Parse bits.  Must start with `static'.  */
   expect_ident ("static");
@@ -6142,13 +6245,12 @@ xbm_read_bitmap_file_data (file, width, height, data)
        }
     }
 
-  fclose (fp);
+ success:
   return 1;
 
  failure:
   
-  fclose (fp);
-  if (*data)
+  if (data && *data)
     {
       xfree (*data);
       *data = NULL;
@@ -6161,35 +6263,21 @@ xbm_read_bitmap_file_data (file, width, height, data)
 }
 
 
-/* Load XBM image IMG which will be displayed on frame F from file
-   SPECIFIED_FILE.  Value is non-zero if successful.  */
+/* Load XBM image IMG which will be displayed on frame F from buffer
+   CONTENTS.  END is the end of the buffer.  Value is non-zero if
+   successful.  */
 
 static int
-xbm_load_image_from_file (f, img, specified_file)
+xbm_load_image (f, img, contents, end)
      struct frame *f;
      struct image *img;
-     Lisp_Object specified_file;
+     char *contents, *end;
 {
   int rc;
   unsigned char *data;
   int success_p = 0;
-  Lisp_Object file;
-  struct gcpro gcpro1;
   
-  xassert (STRINGP (specified_file));
-  file = Qnil;
-  GCPRO1 (file);
-
-  file = x_find_image_file (specified_file);
-  if (!STRINGP (file))
-    {
-      image_error ("Cannot find image file `%s'", specified_file, Qnil);
-      UNGCPRO;
-      return 0;
-    }
-         
-  rc = xbm_read_bitmap_file_data (XSTRING (file)->data, &img->width,
-                                 &img->height, &data);
+  rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
   if (rc)
     {
       int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
@@ -6221,7 +6309,7 @@ xbm_load_image_from_file (f, img, specified_file)
       if (img->pixmap == 0)
        {
          x_clear_image (f, img);
-         image_error ("Unable to create X pixmap for `%s'", file, Qnil);
+         image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
        }
       else
        success_p = 1;
@@ -6231,11 +6319,25 @@ xbm_load_image_from_file (f, img, specified_file)
   else
     image_error ("Error loading XBM image `%s'", img->spec, Qnil);
 
-  UNGCPRO;
   return success_p;
 }
 
 
+/* Value is non-zero if DATA looks like an in-memory XBM file.  */
+
+static int
+xbm_file_p (data)
+     Lisp_Object data;
+{
+  int w, h;
+  return (STRINGP (data)
+         && xbm_read_bitmap_data (XSTRING (data)->data,
+                                  (XSTRING (data)->data
+                                   + STRING_BYTES (XSTRING (data))),
+                                  &w, &h, NULL));
+}
+
+    
 /* Fill image IMG which is used on frame F with pixmap data.  Value is
    non-zero if successful.  */
 
@@ -6252,32 +6354,63 @@ xbm_load (f, img)
   /* If IMG->spec specifies a file name, create a non-file spec from it.  */
   file_name = image_spec_value (img->spec, QCfile, NULL);
   if (STRINGP (file_name))
-    success_p = xbm_load_image_from_file (f, img, file_name);
+    {
+      Lisp_Object file;
+      char *contents;
+      int size;
+      struct gcpro gcpro1;
+      
+      file = x_find_image_file (file_name);
+      GCPRO1 (file);
+      if (!STRINGP (file))
+       {
+         image_error ("Cannot find image file `%s'", file_name, Qnil);
+         UNGCPRO;
+         return 0;
+       }
+
+      contents = slurp_file (XSTRING (file)->data, &size);
+      if (contents == NULL)
+       {
+         image_error ("Error loading XBM image `%s'", img->spec, Qnil);
+         UNGCPRO;
+         return 0;
+       }
+
+      success_p = xbm_load_image (f, img, contents, contents + size);
+      UNGCPRO;
+    }
   else
     {
       struct image_keyword fmt[XBM_LAST];
       Lisp_Object data;
+      unsigned char *bitmap_data;
       int depth;
       unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
       unsigned long background = FRAME_BACKGROUND_PIXEL (f);
       char *bits;
-      int parsed_p;
+      int parsed_p, height, width;
+      int in_memory_file_p = 0;
+
+      /* See if data looks like an in-memory XBM file.  */
+      data = image_spec_value (img->spec, QCdata, NULL);
+      in_memory_file_p = xbm_file_p (data);
 
-      /* Parse the list specification.  */
+      /* Parse the image specification.  */
       bcopy (xbm_format, fmt, sizeof fmt);
       parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
       xassert (parsed_p);
 
       /* Get specified width, and height.  */
-      img->width = XFASTINT (fmt[XBM_WIDTH].value);
-      img->height = XFASTINT (fmt[XBM_HEIGHT].value);
-      xassert (img->width > 0 && img->height > 0);
+      if (!in_memory_file_p)
+       {
+         img->width = XFASTINT (fmt[XBM_WIDTH].value);
+         img->height = XFASTINT (fmt[XBM_HEIGHT].value);
+         xassert (img->width > 0 && img->height > 0);
+       }
 
       BLOCK_INPUT;
       
-      if (fmt[XBM_ASCENT].count)
-       img->ascent = XFASTINT (fmt[XBM_ASCENT].value);
-
       /* Get foreground and background colors, maybe allocate colors.  */
       if (fmt[XBM_FOREGROUND].count)
        foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
@@ -6286,46 +6419,51 @@ xbm_load (f, img)
        background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
                                          background);
 
-      /* Set bits to the bitmap image data.  */
-      data = fmt[XBM_DATA].value;
-      if (VECTORP (data))
+      if (in_memory_file_p)
+       success_p = xbm_load_image (f, img, XSTRING (data)->data,
+                                   (XSTRING (data)->data
+                                    + STRING_BYTES (XSTRING (data))));
+      else
        {
-         int i;
-         char *p;
-         int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
+         if (VECTORP (data))
+           {
+             int i;
+             char *p;
+             int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
          
-         p = bits = (char *) alloca (nbytes * img->height);
-         for (i = 0; i < img->height; ++i, p += nbytes)
+             p = bits = (char *) alloca (nbytes * img->height);
+             for (i = 0; i < img->height; ++i, p += nbytes)
+               {
+                 Lisp_Object line = XVECTOR (data)->contents[i];
+                 if (STRINGP (line))
+                   bcopy (XSTRING (line)->data, p, nbytes);
+                 else
+                   bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
+               }
+           }
+         else if (STRINGP (data))
+           bits = XSTRING (data)->data;
+         else
+           bits = XBOOL_VECTOR (data)->data;
+
+         /* Create the pixmap.  */
+         depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
+         img->pixmap
+           = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
+                                          FRAME_X_WINDOW (f),
+                                          bits,
+                                          img->width, img->height,
+                                          foreground, background,
+                                          depth);
+         if (img->pixmap)
+           success_p = 1;
+         else
            {
-             Lisp_Object line = XVECTOR (data)->contents[i];
-             if (STRINGP (line))
-               bcopy (XSTRING (line)->data, p, nbytes);
-             else
-               bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
+             image_error ("Unable to create pixmap for XBM image `%s'",
+                          img->spec, Qnil);
+             x_clear_image (f, img);
            }
        }
-      else if (STRINGP (data))
-       bits = XSTRING (data)->data;
-      else
-       bits = XBOOL_VECTOR (data)->data;
-
-      /* Create the pixmap.  */
-      depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
-      img->pixmap
-       = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
-                                      FRAME_X_WINDOW (f),
-                                      bits,
-                                      img->width, img->height,
-                                      foreground, background,
-                                      depth);
-      if (img->pixmap)
-       success_p = 1;
-      else
-       {
-         image_error ("Unable to create pixmap for XBM image `%s'",
-                      img->spec, Qnil);
-         x_clear_image (f, img);
-       }
 
       UNBLOCK_INPUT;
     }
@@ -6375,7 +6513,7 @@ static struct image_keyword xpm_format[XPM_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":data",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -6431,9 +6569,7 @@ xpm_image_p (object)
          /* Either no `:color-symbols' or it's a list of conses
             whose car and cdr are strings.  */
          && (fmt[XPM_COLOR_SYMBOLS].count == 0
-             || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))
-         && (fmt[XPM_ASCENT].count == 0
-             || XFASTINT (fmt[XPM_ASCENT].value) < 100));
+             || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
 }
 
 
@@ -6536,7 +6672,12 @@ xpm_load (f, img)
       img->colors = (unsigned long *) xmalloc (img->ncolors
                                               * sizeof *img->colors);
       for (i = 0; i < attrs.nalloc_pixels; ++i)
-       img->colors[i] = attrs.alloc_pixels[i];
+       {
+         img->colors[i] = attrs.alloc_pixels[i];
+#ifdef DEBUG_X_COLORS
+         register_color (img->colors[i]);
+#endif
+       }
 
       img->width = attrs.width;
       img->height = attrs.height;
@@ -7069,7 +7210,7 @@ static struct image_keyword pbm_format[PBM_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":data",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -7098,9 +7239,7 @@ pbm_image_p (object)
   
   bcopy (pbm_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
-      || (fmt[PBM_ASCENT].count 
-         && XFASTINT (fmt[PBM_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
     return 0;
 
   /* Must specify either :data or :file.  */
@@ -7146,42 +7285,6 @@ pbm_scan_number (s, end)
 }
 
 
-/* Read FILE into memory.  Value is a pointer to a buffer allocated
-   with xmalloc holding FILE's contents.  Value is null if an error
-   occured.  *SIZE is set to the size of the file.  */
-
-static char *
-pbm_read_file (file, size)
-     Lisp_Object file;
-     int *size;
-{
-  FILE *fp = NULL;
-  char *buf = NULL;
-  struct stat st;
-
-  if (stat (XSTRING (file)->data, &st) == 0
-      && (fp = fopen (XSTRING (file)->data, "r")) != NULL
-      && (buf = (char *) xmalloc (st.st_size),
-         fread (buf, 1, st.st_size, fp) == st.st_size))
-    {
-      *size = st.st_size;
-      fclose (fp);
-    }
-  else
-    {
-      if (fp)
-       fclose (fp);
-      if (buf)
-       {
-         xfree (buf);
-         buf = NULL;
-       }
-    }
-  
-  return buf;
-}
-
-
 /* Load PBM image IMG for use on frame F.  */
 
 static int 
@@ -7213,7 +7316,7 @@ pbm_load (f, img)
          return 0;
        }
 
-      contents = pbm_read_file (file, &size);
+      contents = slurp_file (XSTRING (file)->data, &size);
       if (contents == NULL)
        {
          image_error ("Error reading `%s'", file, Qnil);
@@ -7425,7 +7528,7 @@ static struct image_keyword png_format[PNG_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -7453,9 +7556,7 @@ png_image_p (object)
   struct image_keyword fmt[PNG_LAST];
   bcopy (png_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
-      || (fmt[PNG_ASCENT].count 
-         && XFASTINT (fmt[PNG_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
     return 0;
 
   /* Must specify either the :data or :file keyword.  */
@@ -7911,7 +8012,7 @@ static struct image_keyword jpeg_format[JPEG_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -7940,9 +8041,7 @@ jpeg_image_p (object)
   
   bcopy (jpeg_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
-      || (fmt[JPEG_ASCENT].count 
-         && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
     return 0;
 
   /* Must specify either the :data or :file keyword.  */
@@ -8275,7 +8374,7 @@ static struct image_keyword tiff_format[TIFF_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -8303,9 +8402,7 @@ tiff_image_p (object)
   struct image_keyword fmt[TIFF_LAST];
   bcopy (tiff_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
-      || (fmt[TIFF_ASCENT].count 
-         && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
     return 0;
   
   /* Must specify either the :data or :file keyword.  */
@@ -8602,7 +8699,7 @@ static struct image_keyword gif_format[GIF_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -8631,9 +8728,7 @@ gif_image_p (object)
   struct image_keyword fmt[GIF_LAST];
   bcopy (gif_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
-      || (fmt[GIF_ASCENT].count 
-         && XFASTINT (fmt[GIF_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
     return 0;
   
   /* Must specify either the :data or :file keyword.  */
@@ -8919,7 +9014,7 @@ static struct image_keyword gs_format[GS_LAST] =
   {":file",            IMAGE_STRING_VALUE,                     1},
   {":loader",          IMAGE_FUNCTION_VALUE,                   0},
   {":bounding-box",    IMAGE_DONT_CHECK_VALUE_TYPE,            1},
-  {":ascent",          IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -8964,9 +9059,7 @@ gs_image_p (object)
   
   bcopy (gs_format, fmt, sizeof fmt);
   
-  if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
-      || (fmt[GS_ASCENT].count 
-         && XFASTINT (fmt[GS_ASCENT].value) > 100))
+  if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
     return 0;
 
   /* Bounding box must be a list or vector containing 4 integers.  */
@@ -9727,8 +9820,8 @@ TIMEOUT nil means use the default timeout of 5 seconds.")
      will loose.  I don't think this is a realistic case.  */
   w = XWINDOW (FRAME_ROOT_WINDOW (f));
   w->left = w->top = make_number (0);
-  w->width = 80;
-  w->height = 40;
+  w->width = make_number (80);
+  w->height = make_number (40);
   adjust_glyphs (f);
   w->pseudo_window_p = 1;
 
@@ -9738,7 +9831,7 @@ TIMEOUT nil means use the default timeout of 5 seconds.")
   old_buffer = current_buffer;
   set_buffer_internal_1 (XBUFFER (buffer));
   Ferase_buffer ();
-  Finsert (make_number (1), &string);
+  Finsert (1, &string);
   clear_glyph_matrix (w->desired_matrix);
   clear_glyph_matrix (w->current_matrix);
   SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
@@ -10010,37 +10103,6 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
 
 #endif /* USE_MOTIF */
 
-\f
-/***********************************************************************
-                               Tests
- ***********************************************************************/
-
-#if GLYPH_DEBUG
-
-DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
-  "Value is non-nil if SPEC is a valid image specification.")
-  (spec)
-     Lisp_Object spec;
-{
-  return valid_image_p (spec) ? Qt : Qnil;
-}
-
-
-DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
-  (spec)
-     Lisp_Object spec;
-{
-  int id = -1;
-  
-  if (valid_image_p (spec))
-    id = lookup_image (SELECTED_FRAME (), spec);
-
-  debug_print (spec);
-  return make_number (id);
-}
-
-#endif /* GLYPH_DEBUG != 0 */
-
 
 \f
 /***********************************************************************
@@ -10122,6 +10184,10 @@ syms_of_xfns ()
   staticpro (&Qscroll_bar_background);
   Qscreen_gamma = intern ("screen-gamma");
   staticpro (&Qscreen_gamma);
+  Qline_spacing = intern ("line-spacing");
+  staticpro (&Qline_spacing);
+  Qcenter = intern ("center");
+  staticpro (&Qcenter);
   /* This is the end of symbol initialization.  */
 
   /* Text property `display' should be nonsticky by default.  */
@@ -10242,11 +10308,6 @@ from the image cache.  Value must be an integer or nil with nil\n\
 meaning don't clear the cache.");
   Vimage_cache_eviction_delay = make_number (30 * 60);
 
-  DEFVAR_LISP ("image-types", &Vimage_types,
-     "List of supported image types.\n\
-Each element of the list is a symbol for a supported image type.");
-  Vimage_types = Qnil;
-
 #ifdef USE_X_TOOLKIT
   Fprovide (intern ("x-toolkit"));
 #endif
@@ -10359,11 +10420,6 @@ Each element of the list is a symbol for a supported image type.");
 
   defsubr (&Sclear_image_cache);
 
-#if GLYPH_DEBUG
-  defsubr (&Simagep);
-  defsubr (&Slookup_image);
-#endif
-
   busy_cursor_atimer = NULL;
   busy_cursor_shown_p = 0;