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
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));
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));
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
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. */
#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. */
struct frame *f;
{
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
- Lisp_Object rest, frame;
int i;
xassert (FRAME_WINDOW_P (f));
{
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;
}
}
***********************************************************************/
/* A version of defined_color for non-X frames. */
+
int
tty_defined_color (f, color_name, color_def, alloc)
struct frame *f;
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;
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;
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. */
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,
return color.pixel;
}
+
#ifdef HAVE_WINDOW_SYSTEM
/* Load colors for face FACE which is used on frame F. Colors are
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 */
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);
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]));
}
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]);
clear_current_matrices (f);
++windows_or_buffers_changed;
}
+
+ UNBLOCK_INPUT;
}
}
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];
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;
}
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)
#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));
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))
{
success_p = 1;
}
+ UNBLOCK_INPUT;
return success_p;
}
/* 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)
/* 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;
/* 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)
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);
{
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;
}
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;
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
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
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
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\