(syms_of_xfaces) [DEBUG_X_COLORS]: Defsubr dump_colors
[bpt/emacs.git] / src / xfaces.c
index c2fe41f..6379b13 100644 (file)
@@ -410,6 +410,13 @@ static int clear_font_table_count;
 
 int face_change_count;
 
+/* Non-zero means don't display bold text if a face's foreground
+   and background colors are the inverse of the default colors of the
+   display.   This is a kluge to suppress `bold black' foreground text
+   which is hard to read on an LCD monitor.  */
+
+int tty_suppress_bold_inverse_default_colors_p;
+
 /* The total number of colors currently allocated.  */
 
 #if GLYPH_DEBUG
@@ -437,7 +444,6 @@ static int x_face_list_fonts P_ ((struct frame *, char *,
 static int font_scalable_p P_ ((struct font_name *));
 static int get_lface_attributes P_ ((struct frame *, Lisp_Object, Lisp_Object *, int));
 static int load_pixmap P_ ((struct frame *, Lisp_Object, unsigned *, unsigned *));
-static char *xstrdup P_ ((char *));
 static unsigned char *xstrlwr P_ ((unsigned char *));
 static void signal_error P_ ((char *, Lisp_Object));
 static struct frame *frame_or_selected_frame P_ ((Lisp_Object, int));
@@ -500,7 +506,8 @@ static int xlfd_fixed_p P_ ((struct font_name *));
 static int xlfd_numeric_value P_ ((struct table_entry *, int, struct font_name *,
                                   int, int));
 static Lisp_Object xlfd_symbolic_value P_ ((struct table_entry *, int,
-                                           struct font_name *, int, int));
+                                           struct font_name *, int,
+                                           Lisp_Object));
 static struct table_entry *xlfd_lookup_field_contents P_ ((struct table_entry *, int,
                                                           struct font_name *, int));
 
@@ -579,6 +586,32 @@ unregister_colors (pixels, n)
     unregister_color (pixels[i]);
 }
 
+
+DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0,
+  "Dump currently allocated colors and their reference counts to stderr.")
+  ()
+{
+  int i, n;
+
+  fputc ('\n', stderr);
+  
+  for (i = n = 0; i < sizeof color_count / sizeof color_count[0]; ++i)
+    if (color_count[i])
+      {
+       fprintf (stderr, "%3d: %5d", i, color_count[i]);
+       ++n;
+       if (n % 5 == 0)
+         fputc ('\n', stderr);
+       else
+         fputc ('\t', stderr);
+      }
+
+  if (n % 5 != 0)
+    fputc ('\n', stderr);
+  return Qnil;
+}
+
+
 #endif /* DEBUG_X_COLORS */
 
 /* Free colors used on frame F.  PIXELS is an array of NPIXELS pixel
@@ -597,44 +630,42 @@ x_free_colors (f, pixels, npixels)
      necessary and some servers don't allow it.  So don't do it.  */
   if (class != StaticColor && class != StaticGray && class != TrueColor)
     {
-      Display *dpy = FRAME_X_DISPLAY (f);
-      Colormap cmap = FRAME_X_COLORMAP (f);
-      Screen *screen = FRAME_X_SCREEN (f);
-      int default_cmap_p = cmap == DefaultColormapOfScreen (screen);
-
-      if (default_cmap_p)
-       {
-         /* Be paranoid.  If using the default color map, don't ever
-            try to free the default black and white colors.  */
-         int screen_no = XScreenNumberOfScreen (screen);
-         unsigned long black = BlackPixel (dpy, screen_no);
-         unsigned long white = WhitePixel (dpy, screen_no);
-         unsigned long *px;
-         int i, j;
-         
-         px = (unsigned long *) alloca (npixels * sizeof *px);
-         for (i = j = 0; i < npixels; ++i)
-           if (pixels[i] != black && pixels[i] != white)
-             px[j++] = pixels[i];
-
-         if (j)
-           {
-             XFreeColors (dpy, cmap, px, j, 0);
+      XFreeColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+                  pixels, npixels, 0);
 #ifdef DEBUG_X_COLORS
-             unregister_colors (px, j);
+      unregister_colors (pixels, npixels);
 #endif
-           }
-       }
-      else
-       {
-         XFreeColors (dpy, cmap, pixels, npixels, 0);
+    }
+}
+
+
+/* Free colors used on frame F.  PIXELS is an array of NPIXELS pixel
+   color values.  Interrupt input must be blocked when this function
+   is called.  */
+
+void
+x_free_dpy_colors (dpy, screen, cmap, pixels, npixels)
+     Display *dpy;
+     Screen *screen;
+     Colormap cmap;
+     unsigned long *pixels;
+     int npixels;
+{
+  struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
+  int class = dpyinfo->visual->class;
+
+  /* If display has an immutable color map, freeing colors is not
+     necessary and some servers don't allow it.  So don't do it.  */
+  if (class != StaticColor && class != StaticGray && class != TrueColor)
+    {
+      XFreeColors (dpy, cmap, pixels, npixels, 0);
 #ifdef DEBUG_X_COLORS
-         unregister_colors (pixels, npixels);
+      unregister_colors (pixels, npixels);
 #endif
-       }
     }
 }
 
+
 /* Create and return a GC for use on frame F.  GC values and mask
    are given by XGCV and MASK.  */
 
@@ -701,19 +732,6 @@ x_free_gc (f, gc)
 
 #endif  /* WINDOWSNT */
 
-/* Like strdup, but uses xmalloc.  */
-
-static char *
-xstrdup (s)
-     char *s;
-{
-  int len = strlen (s) + 1;
-  char *p = (char *) xmalloc (len);
-  bcopy (s, p, len);
-  return p;
-}
-
-
 /* Like stricmp.  Used to compare parts of font names which are in
    ISO8859-1.  */
 
@@ -936,7 +954,6 @@ clear_font_table (f)
      struct frame *f;
 {
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  Lisp_Object rest, frame;
   int i;
 
   xassert (FRAME_WINDOW_P (f));
@@ -1022,7 +1039,7 @@ the pixmap.  Bits are stored row by row, each row occupies\n\
        {
          int bytes_per_row = ((XFASTINT (width) + BITS_PER_CHAR - 1)
                               / BITS_PER_CHAR);
-         if (STRING_BYTES (XSTRING (data)) >= bytes_per_row * height)
+         if (STRING_BYTES (XSTRING (data)) >= bytes_per_row * XINT (height))
            pixmap_p = 1;
        }
     }
@@ -1185,6 +1202,7 @@ load_face_font (f, face, c)
  ***********************************************************************/
 
 /* A version of defined_color for non-X frames.  */
+
 int
 tty_defined_color (f, color_name, color_def, alloc)
      struct frame *f;
@@ -1241,11 +1259,13 @@ tty_defined_color (f, color_name, color_def, alloc)
   return status;
 }
 
-/* Decide if color named COLOR is valid for the display associated
-   with the frame F; if so, return the rgb values in COLOR_DEF.  If
-   ALLOC is nonzero, allocate a new colormap cell.
+
+/* Decide if color named COLOR_NAME is valid for the display
+   associated with the frame F; if so, return the rgb values in
+   COLOR_DEF.  If ALLOC is nonzero, allocate a new colormap cell.
 
    This does the right thing for any type of frame.  */
+
 int
 defined_color (f, color_name, color_def, alloc)
      struct frame *f;
@@ -1272,15 +1292,15 @@ defined_color (f, color_name, color_def, alloc)
     abort ();
 }
 
-/* Given the index of the tty color, return its name, a Lisp string.  */
+
+/* Given the index IDX of a tty color on frame F, return its name, a
+   Lisp string.  */
 
 Lisp_Object
 tty_color_name (f, idx)
      struct frame *f;
      int idx;
 {
-  char *color;
-
   if (idx >= 0 && !NILP (Ffboundp (Qtty_color_by_index)))
     {
       Lisp_Object frame;
@@ -1311,6 +1331,7 @@ tty_color_name (f, idx)
   return Qunspecified;
 }
 
+
 /* Return non-zero if COLOR_NAME is a shade of gray (or white or
    black) on frame F.  The algorithm is taken from 20.2 faces.el.  */
 
@@ -1397,6 +1418,7 @@ COLOR must be a valid color name.")
   return Qnil;
 }
 
+
 /* Load color with name NAME for use by face FACE on frame F.
    TARGET_INDEX must be one of LFACE_FOREGROUND_INDEX,
    LFACE_BACKGROUND_INDEX, LFACE_UNDERLINE_INDEX, LFACE_OVERLINE_INDEX,
@@ -1473,6 +1495,7 @@ load_color (f, face, name, target_index)
   return color.pixel;
 }
 
+
 #ifdef HAVE_WINDOW_SYSTEM
 
 /* Load colors for face FACE which is used on frame F.  Colors are
@@ -1540,60 +1563,52 @@ free_face_colors (f, face)
      struct face *face;
 {
 #ifdef HAVE_X_WINDOWS
-  int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
-  
-  /* If display has an immutable color map, freeing colors is not
-     necessary and some servers don't allow it.  So don't do it.  */
-  if (class != StaticColor
-      && class != StaticGray
-      && class != TrueColor)
-    {
-      BLOCK_INPUT;
+  BLOCK_INPUT;
       
-      if (!face->foreground_defaulted_p)
-       {
-         x_free_colors (f, &face->foreground, 1);
-         IF_DEBUG (--ncolors_allocated);
-       }
+  if (!face->foreground_defaulted_p)
+    {
+      x_free_colors (f, &face->foreground, 1);
+      IF_DEBUG (--ncolors_allocated);
+    }
       
-      if (!face->background_defaulted_p)
-       {
-         x_free_colors (f, &face->background, 1);
-         IF_DEBUG (--ncolors_allocated);
-       }
-
-      if (face->underline_p
-         && !face->underline_defaulted_p)
-       {
-         x_free_colors (f, &face->underline_color, 1);
-         IF_DEBUG (--ncolors_allocated);
-       }
+  if (!face->background_defaulted_p)
+    {
+      x_free_colors (f, &face->background, 1);
+      IF_DEBUG (--ncolors_allocated);
+    }
 
-      if (face->overline_p
-         && !face->overline_color_defaulted_p)
-       {
-         x_free_colors (f, &face->overline_color, 1);
-         IF_DEBUG (--ncolors_allocated);
-       }
+  if (face->underline_p
+      && !face->underline_defaulted_p)
+    {
+      x_free_colors (f, &face->underline_color, 1);
+      IF_DEBUG (--ncolors_allocated);
+    }
 
-      if (face->strike_through_p
-         && !face->strike_through_color_defaulted_p)
-       {
-         x_free_colors (f, &face->strike_through_color, 1);
-         IF_DEBUG (--ncolors_allocated);
-       }
+  if (face->overline_p
+      && !face->overline_color_defaulted_p)
+    {
+      x_free_colors (f, &face->overline_color, 1);
+      IF_DEBUG (--ncolors_allocated);
+    }
 
-      if (face->box != FACE_NO_BOX
-         && !face->box_color_defaulted_p)
-       {
-         x_free_colors (f, &face->box_color, 1);
-         IF_DEBUG (--ncolors_allocated);
-       }
+  if (face->strike_through_p
+      && !face->strike_through_color_defaulted_p)
+    {
+      x_free_colors (f, &face->strike_through_color, 1);
+      IF_DEBUG (--ncolors_allocated);
+    }
 
-      UNBLOCK_INPUT;
+  if (face->box != FACE_NO_BOX
+      && !face->box_color_defaulted_p)
+    {
+      x_free_colors (f, &face->box_color, 1);
+      IF_DEBUG (--ncolors_allocated);
     }
+
+  UNBLOCK_INPUT;
 #endif /* HAVE_X_WINDOWS */
 }
+
 #endif /* HAVE_WINDOW_SYSTEM */
 
 
@@ -1838,7 +1853,7 @@ xlfd_symbolic_value (table, dim, font, field_index, dflt)
      int dim;
      struct font_name *font;
      int field_index;
-     int dflt;
+     Lisp_Object dflt;
 {
   struct table_entry *p;
   p = xlfd_lookup_field_contents (table, dim, font, field_index);
@@ -4469,9 +4484,9 @@ lface_hash (v)
   return (hash_string_case_insensitive (v[LFACE_FAMILY_INDEX])
          ^ hash_string_case_insensitive (v[LFACE_FOREGROUND_INDEX])
          ^ hash_string_case_insensitive (v[LFACE_BACKGROUND_INDEX])
-         ^ (unsigned) v[LFACE_WEIGHT_INDEX]
-         ^ (unsigned) v[LFACE_SLANT_INDEX]
-         ^ (unsigned) v[LFACE_SWIDTH_INDEX]
+         ^ XFASTINT (v[LFACE_WEIGHT_INDEX])
+         ^ XFASTINT (v[LFACE_SLANT_INDEX])
+         ^ XFASTINT (v[LFACE_SWIDTH_INDEX])
          ^ XFASTINT (v[LFACE_HEIGHT_INDEX]));
 }
 
@@ -4669,6 +4684,11 @@ free_realized_faces (c)
       int i, size;
       struct frame *f = c->f;
 
+      /* We must block input here because we can't process X events
+        safely while only some faces are freed, or when the frame's
+        current matrix still references freed faces.  */
+      BLOCK_INPUT;
+
       for (i = 0; i < c->used; ++i)
        {
          free_realized_face (f, c->faces_by_id[i]);
@@ -4688,6 +4708,8 @@ free_realized_faces (c)
          clear_current_matrices (f);
          ++windows_or_buffers_changed;
        }
+
+      UNBLOCK_INPUT;
     }
 }
 
@@ -4704,6 +4726,11 @@ free_realized_multibyte_face (f, fontset)
   struct face *face;
   int i;
 
+  /* We must block input here because we can't process X events safely
+     while only some faces are freed, or when the frame's current
+     matrix still references freed faces.  */
+  BLOCK_INPUT;
+      
   for (i = 0; i < cache->used; i++)
     {
       face = cache->faces_by_id[i];
@@ -4715,11 +4742,18 @@ free_realized_multibyte_face (f, fontset)
          free_realized_face (f, face);
        }
     }
+  
+  /* Must do a thorough redisplay the next time.  Mark current
+     matrices as invalid because they will reference faces freed
+     above.  This function is also called when a frame is destroyed.
+     In this case, the root window of F is nil.  */
   if (WINDOWP (f->root_window))
     {
       clear_current_matrices (f);
       ++windows_or_buffers_changed;
     }
+  
+  UNBLOCK_INPUT;
 }
 
 
@@ -4864,7 +4898,7 @@ uncache_face (c, face)
    of frame F.  The face will be used to display character C.  Value
    is the ID of the face found.  If no suitable face is found, realize
    a new one.  In that case, if C is a multibyte character, BASE_FACE
-   is a face for ASCII characters that has the same attributes.  */
+   is a face that has the same attributes.  */
 
 INLINE int
 lookup_face (f, attr, c, base_face)
@@ -4898,6 +4932,12 @@ lookup_face (f, attr, c, base_face)
 
 #if GLYPH_DEBUG
   xassert (face == FACE_FROM_ID (f, face->id));
+
+/* When this function is called from face_for_char (in this case, C is
+   a multibyte character), a fontset of a face returned by
+   realize_face is not yet set, i.e. FACE_SUITABLE_FOR_CHAR_P (FACE,
+   C) is not sutisfied.  The fontset is set for this face by
+   face_for_char later.  */
 #if 0
   if (FRAME_WINDOW_P (f))
     xassert (FACE_SUITABLE_FOR_CHAR_P (face, c));
@@ -5593,6 +5633,10 @@ realize_basic_faces (f)
      struct frame *f;
 {
   int success_p = 0;
+
+  /* Block input there so that we won't be surprised by an X expose
+     event, for instance without having the faces set up.  */
+  BLOCK_INPUT;
   
   if (realize_default_face (f))
     {
@@ -5608,6 +5652,7 @@ realize_basic_faces (f)
       success_p = 1;
     }
 
+  UNBLOCK_INPUT;
   return success_p;
 }
 
@@ -5754,10 +5799,10 @@ realize_named_face (f, symbol, id)
 
 /* Realize the fully-specified face with attributes ATTRS in face
    cache CACHE for character C.  If C is a multibyte character,
-   BASE_FACE is a face for ASCII characters that has the same
-   attributes.  Otherwise, BASE_FACE is ignored.  If FORMER_FACE_ID is
-   non-negative, it is an ID of face to remove before caching the new
-   face.  Value is a pointer to the newly created realized face.  */
+   BASE_FACE is a face that has the same attributes.  Otherwise,
+   BASE_FACE is ignored.  If FORMER_FACE_ID is non-negative, it is an
+   ID of face to remove before caching the new face.  Value is a
+   pointer to the newly created realized face.  */
 
 static struct face *
 realize_face (cache, attrs, c, base_face, former_face_id)
@@ -5791,7 +5836,7 @@ realize_face (cache, attrs, c, base_face, former_face_id)
   /* Insert the new face.  */
   cache_face (cache, face, lface_hash (attrs));
 #ifdef HAVE_WINDOW_SYSTEM
-  if (FRAME_X_P (cache->f) && face->font == NULL)
+  if (FRAME_WINDOW_P (cache->f) && face->font == NULL)
     load_face_font (cache->f, face, c);
 #endif  /* HAVE_WINDOW_SYSTEM */
   return face;
@@ -5800,12 +5845,12 @@ realize_face (cache, attrs, c, base_face, former_face_id)
 
 /* Realize the fully-specified face with attributes ATTRS in face
    cache CACHE for character C.  Do it for X frame CACHE->f.  If C is
-   a multibyte character, BASE_FACE is a face for ASCII characters
-   that has the same attributes.  Otherwise, BASE_FACE is ignored.  If
-   the new face doesn't share font with the default face, a fontname
-   is allocated from the heap and set in `font_name' of the new face,
-   but it is not yet loaded here.  Value is a pointer to the newly
-   created realized face.  */
+   a multibyte character, BASE_FACE is a face that has the same
+   attributes.  Otherwise, BASE_FACE is ignored.  If the new face
+   doesn't share font with the default face, a fontname is allocated
+   from the heap and set in `font_name' of the new face, but it is not
+   yet loaded here.  Value is a pointer to the newly created realized
+   face.  */
 
 static struct face *
 realize_x_face (cache, attrs, c, base_face)
@@ -5821,7 +5866,7 @@ realize_x_face (cache, attrs, c, base_face)
 
   xassert (FRAME_WINDOW_P (cache->f));
   xassert (SINGLE_BYTE_CHAR_P (c)
-          || (base_face && base_face->ascii_face == base_face));
+          || base_face);
 
   /* Allocate a new realized face.  */
   face = make_realized_face (attrs);
@@ -5835,7 +5880,17 @@ realize_x_face (cache, attrs, c, base_face)
     {
       bcopy (base_face, face, sizeof *face);
       face->gc = 0;
-      face->font = NULL;       /* to force realize_face to load font */
+
+      /* Don't try to free the colors copied bitwise from BASE_FACE.  */
+      face->foreground_defaulted_p = 1;
+      face->background_defaulted_p = 1;
+      face->underline_defaulted_p = 1; 
+      face->overline_color_defaulted_p = 1;
+      face->strike_through_color_defaulted_p = 1;
+      face->box_color_defaulted_p = 1;
+      
+      /* to force realize_face to load font */
+      face->font = NULL;
       return face;
     }
 
@@ -6021,8 +6076,8 @@ realize_tty_face (cache, attrs, c)
   struct face *face;
   int weight, slant;
   Lisp_Object color;
-  Lisp_Object tty_defined_color_alist =
-    Fsymbol_value (intern ("tty-defined-color-alist"));
+  Lisp_Object tty_defined_color_alist
+    = find_symbol_value (intern ("tty-defined-color-alist"));
   Lisp_Object tty_color_alist = intern ("tty-color-alist");
   Lisp_Object frame;
   int face_colors_defaulted = 0;
@@ -6057,7 +6112,7 @@ realize_tty_face (cache, attrs, c)
   color = attrs[LFACE_FOREGROUND_INDEX];
   if (STRINGP (color)
       && XSTRING (color)->size
-      && !NILP (tty_defined_color_alist)
+      && CONSP (tty_defined_color_alist)
       && (color = Fassoc (color, call1 (tty_color_alist, frame)),
          CONSP (color)))
     /* Associations in tty-defined-color-alist are of the form
@@ -6103,7 +6158,7 @@ realize_tty_face (cache, attrs, c)
   color = attrs[LFACE_BACKGROUND_INDEX];
   if (STRINGP (color)
       && XSTRING (color)->size
-      && !NILP (tty_defined_color_alist)
+      && CONSP (tty_defined_color_alist)
       && (color = Fassoc (color, call1 (tty_color_alist, frame)),
          CONSP (color)))
     /* Associations in tty-defined-color-alist are of the form
@@ -6156,10 +6211,33 @@ realize_tty_face (cache, attrs, c)
       face->background = tem;
     }
 
+  if (tty_suppress_bold_inverse_default_colors_p
+      && face->tty_bold_p
+      && face->background == FACE_TTY_DEFAULT_FG_COLOR
+      && face->foreground == FACE_TTY_DEFAULT_BG_COLOR)
+    face->tty_bold_p = 0;
+
   return face;
 }
 
 
+DEFUN ("tty-suppress-bold-inverse-default-colors",
+       Ftty_suppress_bold_inverse_default_colors,
+       Stty_suppress_bold_inverse_default_colors, 1, 1, 0,
+  "Suppress/allow boldness of faces with inverse default colors.\n\
+SUPPRESS non-nil means suppress it.\n\
+This affects bold faces on TTYs whose foreground is the default background\n\
+color of the display and whose background is the default foreground color.\n\
+For such faces, no bold text will be displayed.")
+  (suppress)
+     Lisp_Object suppress;
+{
+  tty_suppress_bold_inverse_default_colors_p = !NILP (suppress);
+  ++face_change_count;
+  return suppress;
+}
+
+
 \f
 /***********************************************************************
                           Computing Faces
@@ -6672,6 +6750,11 @@ syms_of_xfaces ()
   defsubr (&Sshow_face_resources);
 #endif /* GLYPH_DEBUG */
   defsubr (&Sclear_face_cache);
+  defsubr (&Stty_suppress_bold_inverse_default_colors);
+
+#if defined DEBUG_X_COLORS && defined HAVE_X_WINDOWS
+  defsubr (&Sdump_colors);
+#endif
 
   DEFVAR_LISP ("font-list-limit", &Vfont_list_limit,
     "*Limit for font matching.\n\