#define SCALABLE_FONTS 1
+#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <config.h>
#include "lisp.h"
#include "charset.h"
#include "frame.h"
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#include "fontset.h"
+#ifdef USE_MOTIF
+#include <Xm/Xm.h>
+#include <Xm/XmStrDefs.h>
+#endif /* USE_MOTIF */
#endif
#ifdef MSDOS
#endif /* HAVE_X_WINDOWS */
#include <stdio.h>
-#include <stdlib.h>
#include <ctype.h>
#include "keyboard.h"
Lisp_Object Qx_charset_registry;
+/* The name of the function to call when the background of the frame
+ has changed, frame_update_face_colors. */
+
+Lisp_Object Qframe_update_face_colors;
+
/* Names of basic faces. */
-Lisp_Object Qdefault, Qmodeline, Qtoolbar, Qregion, Qbitmap_area;
-Lisp_Object Qtop_line;
+Lisp_Object Qdefault, Qmode_line, Qtool_bar, Qregion, Qfringe;
+Lisp_Object Qheader_line, Qscroll_bar, Qcursor, Qborder, Qmouse, Qmenu;
+
+/* The symbol `face-alias'. A symbols having that property is an
+ alias for another face. Value of the property is the name of
+ the aliased face. */
+
+Lisp_Object Qface_alias;
+
+/* Names of frame parameters related to faces. */
+
+extern Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
+extern Lisp_Object Qborder_color, Qcursor_color, Qmouse_color;
/* Default stipple pattern used on monochrome displays. This stipple
pattern is used on monochrome displays instead of shades of gray
Lisp_Object Vscalable_fonts_allowed;
#endif
+/* Maximum number of fonts to consider in font_list. If not an
+ integer > 0, DEFAULT_FONT_LIST_LIMIT is used instead. */
+
+Lisp_Object Vfont_list_limit;
+#define DEFAULT_FONT_LIST_LIMIT 100
+
/* The symbols `foreground-color' and `background-color' which can be
used as part of a `face' property. This is for compatibility with
Emacs 20.2. */
/* Error symbol for wrong_type_argument in load_pixmap. */
-Lisp_Object Qpixmap_spec_p;
+Lisp_Object Qbitmap_spec_p;
/* Alist of global face definitions. Each element is of the form
(FACE . LFACE) where FACE is a symbol naming a face and LFACE
struct font_name;
struct table_entry;
+static Lisp_Object resolve_face_name P_ ((Lisp_Object));
static int may_use_scalable_font_p P_ ((struct font_name *, char *));
static void set_font_frame_param P_ ((Lisp_Object, Lisp_Object));
static int better_font_p P_ ((int *, struct font_name *, struct font_name *,
static char *xstrdup P_ ((char *));
static unsigned char *xstrlwr P_ ((unsigned char *));
static void signal_error P_ ((char *, Lisp_Object));
-static void display_message P_ ((struct frame *, char *, Lisp_Object, Lisp_Object));
static struct frame *frame_or_selected_frame P_ ((Lisp_Object, int));
static void load_face_font_or_fontset P_ ((struct frame *, struct face *, char *, int));
-static unsigned long load_color P_ ((struct frame *,
- struct face *,
- Lisp_Object,
- enum lface_attribute_index));
static void load_face_colors P_ ((struct frame *, struct face *, Lisp_Object *));
static void free_face_colors P_ ((struct frame *, struct face *));
static int face_color_gray_p P_ ((struct frame *, char *));
}
-/* Display a message with format string FORMAT and arguments ARG1 and
- ARG2 on frame F. Used to display errors if fonts, bitmaps, colors
- etc. for a realized face on frame F cannot be loaded. (If we would
- signal an error in these cases, we would end up in an infinite
- recursion because this would stop realization, and the redisplay
- triggered by the signal would try to realize that same face again.)
-
- If basic faces of F are not realized, just add the message to the
- messages buffer "*Messages*". Because Fmessage calls
- echo_area_display which tries to realize basic faces again, we would
- otherwise also end in an infinite recursion. */
-
-static void
-display_message (f, format, arg1, arg2)
- struct frame *f;
- char *format;
- Lisp_Object arg1, arg2;
-{
- Lisp_Object args[3];
- Lisp_Object nargs;
- extern int waiting_for_input;
-
- /* Function note_mouse_highlight calls face_at_buffer_position which
- may realize a face. If some attribute of that face is invalid,
- say an invalid color, don't display an error to avoid calling
- Lisp from XTread_socket. */
- if (waiting_for_input)
- return;
-
- nargs = make_number (DIM (args));
- args[0] = build_string (format);
- args[1] = arg1;
- args[2] = arg2;
-
- if (f->face_cache->used >= BASIC_FACE_ID_SENTINEL)
- Fmessage (nargs, args);
- else
- {
- Lisp_Object msg = Fformat (nargs, args);
- char *buffer = LSTRDUPA (msg);
- message_dolog (buffer, strlen (buffer), 1, 0);
- }
-}
-
-
-/* If FRAME is nil, return selected_frame. Otherwise, check that
- FRAME is a live frame, and return a pointer to it. NPARAM
- is the parameter number of FRAME, for CHECK_LIVE_FRAME. This is
- here because it's a frequent pattern in Lisp function definitions. */
+/* If FRAME is nil, return a pointer to the selected frame.
+ Otherwise, check that FRAME is a live frame, and return a pointer
+ to it. NPARAM is the parameter number of FRAME, for
+ CHECK_LIVE_FRAME. This is here because it's a frequent pattern in
+ Lisp function definitions. */
static INLINE struct frame *
frame_or_selected_frame (frame, nparam)
Lisp_Object frame;
int nparam;
{
- struct frame *f;
-
if (NILP (frame))
- f = selected_frame;
- else
- {
- CHECK_LIVE_FRAME (frame, nparam);
- f = XFRAME (frame);
- }
-
- return f;
+ frame = selected_frame;
+
+ CHECK_LIVE_FRAME (frame, nparam);
+ return XFRAME (frame);
}
\f
}
-/* Recompute basic faces for frame F. Call this after changing frame
- parameters on which those faces depend, or when realized faces have
- been freed due to changing attributes of named faces. */
+/* Clear face caches, and recompute basic faces for frame F. Call
+ this after changing frame parameters on which those faces depend,
+ or when realized faces have been freed due to changing attributes
+ of named faces. */
void
recompute_basic_faces (f)
{
if (FRAME_FACE_CACHE (f))
{
- int realized_p = realize_basic_faces (f);
+ int realized_p;
+ clear_face_cache (0);
+ realized_p = realize_basic_faces (f);
xassert (realized_p);
}
}
#ifdef HAVE_X_WINDOWS
-DEFUN ("pixmap-spec-p", Fpixmap_spec_p, Spixmap_spec_p, 1, 1, 0,
- "Non-nil if OBJECT is a valid pixmap specification.\n\
-A pixmap specification is either a string, or a list (WIDTH HEIGHT DATA)\n\
-where WIDTH is the pixel width of the pixmap, HEIGHT is its height,\n\
-and DATA contains the bits of the pixmap.")
+DEFUN ("bitmap-spec-p", Fbitmap_spec_p, Sbitmap_spec_p, 1, 1, 0,
+ "Value is non-nil if OBJECT is a valid bitmap specification.\n\
+A bitmap specification is either a string, a file name, or a list\n\
+(WIDTH HEIGHT DATA) where WIDTH is the pixel width of the bitmap,\n\
+HEIGHT is its height, and DATA is a string containing the bits of\n\
+the pixmap. Bits are stored row by row, each row occupies\n\
+(WIDTH + 7)/8 bytes.")
(object)
Lisp_Object object;
{
- Lisp_Object height, width;
+ int pixmap_p = 0;
+
+ if (STRINGP (object))
+ /* If OBJECT is a string, it's a file name. */
+ pixmap_p = 1;
+ else if (CONSP (object))
+ {
+ /* Otherwise OBJECT must be (WIDTH HEIGHT DATA), WIDTH and
+ HEIGHT must be integers > 0, and DATA must be string large
+ enough to hold a bitmap of the specified size. */
+ Lisp_Object width, height, data;
- return ((STRINGP (object)
- || (CONSP (object)
- && CONSP (XCONS (object)->cdr)
- && CONSP (XCONS (XCONS (object)->cdr)->cdr)
- && NILP (XCONS (XCONS (XCONS (object)->cdr)->cdr)->cdr)
- && (width = XCONS (object)->car, INTEGERP (width))
- && (height = XCONS (XCONS (object)->cdr)->car,
- INTEGERP (height))
- && STRINGP (XCONS (XCONS (XCONS (object)->cdr)->cdr)->car)
- && XINT (width) > 0
- && XINT (height) > 0
- /* The string must have enough bits for width * height. */
- && ((XSTRING (XCONS (XCONS (XCONS (object)->cdr)->cdr)->car)->size
- * (BITS_PER_INT / sizeof (int)))
- >= XFASTINT (width) * XFASTINT (height))))
- ? Qt : Qnil);
+ height = width = data = Qnil;
+
+ if (CONSP (object))
+ {
+ width = XCAR (object);
+ object = XCDR (object);
+ if (CONSP (object))
+ {
+ height = XCAR (object);
+ object = XCDR (object);
+ if (CONSP (object))
+ data = XCAR (object);
+ }
+ }
+
+ if (NATNUMP (width) && NATNUMP (height) && STRINGP (data))
+ {
+ int bytes_per_row = ((XFASTINT (width) + BITS_PER_CHAR - 1)
+ / BITS_PER_CHAR);
+ if (STRING_BYTES (XSTRING (data)) >= bytes_per_row * height)
+ pixmap_p = 1;
+ }
+ }
+
+ return pixmap_p ? Qt : Qnil;
}
if (NILP (name))
return 0;
- tem = Fpixmap_spec_p (name);
+ tem = Fbitmap_spec_p (name);
if (NILP (tem))
- wrong_type_argument (Qpixmap_spec_p, name);
+ wrong_type_argument (Qbitmap_spec_p, name);
BLOCK_INPUT;
if (CONSP (name))
if (bitmap_id < 0)
{
- display_message (f, "Invalid or undefined bitmap %s", name, Qnil);
+ add_to_log ("Invalid or undefined bitmap %s", name, Qnil);
bitmap_id = 0;
if (w_ptr)
}
}
else if (fontset >= 0)
- display_message (f, "Unable to load ASCII font of fontset %d",
- make_number (fontset), Qnil);
+ add_to_log ("Unable to load ASCII font of fontset %d",
+ make_number (fontset), Qnil);
else if (font_name)
- display_message (f, "Unable to load font %s",
- build_string (font_name), Qnil);
+ add_to_log ("Unable to load font %s",
+ build_string (font_name), Qnil);
}
#endif /* HAVE_X_WINDOWS */
record that fact in flags of the face so that we don't try to free
these colors. */
-static unsigned long
+unsigned long
load_color (f, face, name, target_index)
struct frame *f;
struct face *face;
to the values in an existing cell. */
if (!defined_color (f, XSTRING (name)->data, &color, 1))
{
- display_message (f, "Unable to load color %s", name, Qnil);
+ add_to_log ("Unable to load color %s", name, Qnil);
switch (target_index)
{
"supported" as background because we are supposed to use stipple
for them. */
if (!face_color_supported_p (f, XSTRING (bg)->data, 0)
- && !NILP (Fpixmap_spec_p (Vface_default_stipple)))
+ && !NILP (Fbitmap_spec_p (Vface_default_stipple)))
{
x_destroy_bitmap (f, face->stipple);
face->stipple = load_pixmap (f, Vface_default_stipple,
}
}
-#endif /* HAVE_X_WINDOWS */
+#else /* ! HAVE_X_WINDOWS */
+
+#ifdef MSDOS
+unsigned long
+load_color (f, face, name, target_index)
+ struct frame *f;
+ struct face *face;
+ Lisp_Object name;
+ enum lface_attribute_index target_index;
+{
+ Lisp_Object color;
+ int color_idx = FACE_TTY_DEFAULT_COLOR;
+
+ if (NILP (name))
+ return (unsigned long)FACE_TTY_DEFAULT_COLOR;
+
+ CHECK_STRING (name, 0);
+
+ color = Qnil;
+ if (XSTRING (name)->size && !NILP (Ffboundp (Qmsdos_color_translate)))
+ {
+ color = call1 (Qmsdos_color_translate, name);
+
+ if (INTEGERP (color))
+ return (unsigned long)XINT (color);
+
+ add_to_log ("Unable to load color %s", name, Qnil);
+
+ switch (target_index)
+ {
+ case LFACE_FOREGROUND_INDEX:
+ face->foreground_defaulted_p = 1;
+ color_idx = FRAME_FOREGROUND_PIXEL (f);
+ break;
+
+ case LFACE_BACKGROUND_INDEX:
+ face->background_defaulted_p = 1;
+ color_idx = FRAME_BACKGROUND_PIXEL (f);
+ break;
+
+ case LFACE_UNDERLINE_INDEX:
+ face->underline_defaulted_p = 1;
+ color_idx = FRAME_FOREGROUND_PIXEL (f);
+ break;
+
+ case LFACE_OVERLINE_INDEX:
+ face->overline_color_defaulted_p = 1;
+ color_idx = FRAME_FOREGROUND_PIXEL (f);
+ break;
+
+ case LFACE_STRIKE_THROUGH_INDEX:
+ face->strike_through_color_defaulted_p = 1;
+ color_idx = FRAME_FOREGROUND_PIXEL (f);
+ break;
+
+ case LFACE_BOX_INDEX:
+ face->box_color_defaulted_p = 1;
+ color_idx = FRAME_FOREGROUND_PIXEL (f);
+ break;
+ }
+ }
+ else
+ color_idx = msdos_stdcolor_idx (XSTRING (name)->data);
+
+ return (unsigned long)color_idx;
+}
+#endif /* MSDOS */
+#endif /* ! HAVE_X_WINDOWS */
\f
int nfonts;
/* Get the list of fonts matching pattern. 100 should suffice. */
- nfonts = 100;
+ nfonts = DEFAULT_FONT_LIST_LIMIT;
+ if (INTEGERP (Vfont_list_limit) && XINT (Vfont_list_limit) > 0)
+ nfonts = XFASTINT (Vfont_list_limit);
+
*fonts = (struct font_name *) xmalloc (nfonts * sizeof **fonts);
#if SCALABLE_FONTS
nfonts = x_face_list_fonts (f, pattern, *fonts, nfonts, 1, 1);
/* Remove elements from LIST whose cars are `equal'. Called from
- x-font-list and x-font-family-list to remove duplicate font
+ x-family-fonts and x-font-family-list to remove duplicate font
entries. */
static void
}
-DEFUN ("x-font-list", Fxfont_list, Sx_font_list, 0, 2, 0,
+DEFUN ("x-family-fonts", Fx_family_fonts, Sx_family_fonts, 0, 2, 0,
"Return a list of available fonts of family FAMILY on FRAME.\n\
If FAMILY is omitted or nil, list all families.\n\
Otherwise, FAMILY must be a string, possibly containing wildcards\n\
`?' and `*'.\n\
If FRAME is omitted or nil, use the selected frame.\n\
Each element of the result is a vector [FAMILY WIDTH POINT-SIZE WEIGHT\n\
-SLANT FIXED-P].\n\
+SLANT FIXED-P FULL REGISTRY-AND-ENCODING].\n\
FAMILY is the font family name. POINT-SIZE is the size of the\n\
font in 1/10 pt. WIDTH, WEIGHT, and SLANT are symbols describing the\n\
width, weight and slant of the font. These symbols are the same as for\n\
face attributes. FIXED-P is non-nil if the font is fixed-pitch.\n\
+FULL is the full name of the font, and REGISTRY-AND-ENCODING is a string\n\
+giving the registry and encoding of the font.\n\
The result list is sorted according to the current setting of\n\
the face font sort order.")
(family, frame)
nfonts = font_list (f, NULL, family_pattern, NULL, &fonts);
for (i = nfonts - 1; i >= 0; --i)
{
- Lisp_Object v = Fmake_vector (make_number (6), Qnil);
+ Lisp_Object v = Fmake_vector (make_number (8), Qnil);
+ char *tem;
#define ASET(VECTOR, IDX, VAL) (XVECTOR (VECTOR)->contents[IDX] = (VAL))
ASET (v, 3, xlfd_symbolic_weight (fonts + i));
ASET (v, 4, xlfd_symbolic_slant (fonts + i));
ASET (v, 5, xlfd_fixed_p (fonts + i) ? Qt : Qnil);
+ tem = build_font_name (fonts + i);
+ ASET (v, 6, build_string (tem));
+ sprintf (tem, "%s-%s", fonts[i].fields[XLFD_REGISTRY],
+ fonts[i].fields[XLFD_ENCODING]);
+ ASET (v, 7, build_string (tem));
+ xfree (tem);
+
result = Fcons (v, result);
#undef ASET
struct font_name *fonts;
Lisp_Object result;
struct gcpro gcpro1;
+ int count = specpdl_ptr - specpdl;
+ int limit;
+
+ /* Let's consider all fonts. Increase the limit for matching
+ fonts until we have them all. */
+ for (limit = 500;;)
+ {
+ specbind (intern ("font-list-limit"), make_number (limit));
+ nfonts = font_list (f, NULL, "*", NULL, &fonts);
+
+ if (nfonts == limit)
+ {
+ free_font_names (fonts, nfonts);
+ limit *= 2;
+ }
+ else
+ break;
+ }
- nfonts = font_list (f, NULL, "*", NULL, &fonts);
result = Qnil;
GCPRO1 (result);
for (i = nfonts - 1; i >= 0; --i)
remove_duplicates (result);
free_font_names (fonts, nfonts);
UNGCPRO;
- return result;
+ return unbind_to (count, result);
}
#ifdef HAVE_WINDOW_SYSTEM
xassert (UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX])
|| SYMBOLP (attrs[LFACE_STIPPLE_INDEX])
- || !NILP (Fpixmap_spec_p (attrs[LFACE_STIPPLE_INDEX])));
+ || !NILP (Fbitmap_spec_p (attrs[LFACE_STIPPLE_INDEX])));
#endif
}
#endif /* GLYPH_DEBUG == 0 */
+/* Resolve face name FACE_NAME. If FACE_NAME Is a string, intern it
+ to make it a symvol. If FACE_NAME is an alias for another face,
+ return that face's name. */
+
+static Lisp_Object
+resolve_face_name (face_name)
+ Lisp_Object face_name;
+{
+ Lisp_Object aliased;
+
+ if (STRINGP (face_name))
+ face_name = intern (XSTRING (face_name)->data);
+
+ for (;;)
+ {
+ aliased = Fget (face_name, Qface_alias);
+ if (NILP (aliased))
+ break;
+ else
+ face_name = aliased;
+ }
+
+ return face_name;
+}
+
+
/* Return the face definition of FACE_NAME on frame F. F null means
return the global definition. FACE_NAME may be a string or a
symbol (apparently Emacs 20.2 allows strings as face names in face
- text properties; ediff uses that). If SIGNAL_P is non-zero, signal
- an error if FACE_NAME is not a valid face name. If SIGNAL_P is
- zero, value is nil if FACE_NAME is not a valid face name. */
+ text properties; ediff uses that). If FACE_NAME is an alias for
+ another face, return that face's definition. If SIGNAL_P is
+ non-zero, signal an error if FACE_NAME is not a valid face name.
+ If SIGNAL_P is zero, value is nil if FACE_NAME is not a valid face
+ name. */
static INLINE Lisp_Object
lface_from_face_name (f, face_name, signal_p)
{
Lisp_Object lface;
- if (STRINGP (face_name))
- face_name = intern (XSTRING (face_name)->data);
+ face_name = resolve_face_name (face_name);
if (f)
lface = assq_no_quit (face_name, f->face_alist);
to[LFACE_BACKGROUND_INDEX] = color_name;
}
else
- display_message (f, "Invalid face color", color_name, Qnil);
+ add_to_log ("Invalid face color", color_name, Qnil);
}
else if (SYMBOLP (first)
&& *XSYMBOL (first)->name->data == ':')
if (STRINGP (value))
to[LFACE_FAMILY_INDEX] = value;
else
- display_message (f, "Illegal face font family",
- value, Qnil);
+ add_to_log ("Illegal face font family", value, Qnil);
}
else if (EQ (keyword, QCheight))
{
if (INTEGERP (value))
to[LFACE_HEIGHT_INDEX] = value;
else
- display_message (f, "Illegal face font height",
- value, Qnil);
+ add_to_log ("Illegal face font height", value, Qnil);
}
else if (EQ (keyword, QCweight))
{
&& face_numeric_weight (value) >= 0)
to[LFACE_WEIGHT_INDEX] = value;
else
- display_message (f, "Illegal face weight", value, Qnil);
+ add_to_log ("Illegal face weight", value, Qnil);
}
else if (EQ (keyword, QCslant))
{
&& face_numeric_slant (value) >= 0)
to[LFACE_SLANT_INDEX] = value;
else
- display_message (f, "Illegal face slant", value, Qnil);
+ add_to_log ("Illegal face slant", value, Qnil);
}
else if (EQ (keyword, QCunderline))
{
|| STRINGP (value))
to[LFACE_UNDERLINE_INDEX] = value;
else
- display_message (f, "Illegal face underline", value, Qnil);
+ add_to_log ("Illegal face underline", value, Qnil);
}
else if (EQ (keyword, QCoverline))
{
|| STRINGP (value))
to[LFACE_OVERLINE_INDEX] = value;
else
- display_message (f, "Illegal face overline", value, Qnil);
+ add_to_log ("Illegal face overline", value, Qnil);
}
else if (EQ (keyword, QCstrike_through))
{
|| STRINGP (value))
to[LFACE_STRIKE_THROUGH_INDEX] = value;
else
- display_message (f, "Illegal face strike-through",
- value, Qnil);
+ add_to_log ("Illegal face strike-through", value, Qnil);
}
else if (EQ (keyword, QCbox))
{
|| NILP (value))
to[LFACE_BOX_INDEX] = value;
else
- display_message (f, "Illegal face box", value, Qnil);
+ add_to_log ("Illegal face box", value, Qnil);
}
else if (EQ (keyword, QCinverse_video)
|| EQ (keyword, QCreverse_video))
if (EQ (value, Qt) || NILP (value))
to[LFACE_INVERSE_INDEX] = value;
else
- display_message (f, "Illegal face inverse-video",
- value, Qnil);
+ add_to_log ("Illegal face inverse-video", value, Qnil);
}
else if (EQ (keyword, QCforeground))
{
if (STRINGP (value))
to[LFACE_FOREGROUND_INDEX] = value;
else
- display_message (f, "Illegal face foreground",
- value, Qnil);
+ add_to_log ("Illegal face foreground", value, Qnil);
}
else if (EQ (keyword, QCbackground))
{
if (STRINGP (value))
to[LFACE_BACKGROUND_INDEX] = value;
else
- display_message (f, "Illegal face background",
- value, Qnil);
+ add_to_log ("Illegal face background", value, Qnil);
}
else if (EQ (keyword, QCstipple))
{
#ifdef HAVE_X_WINDOWS
- Lisp_Object pixmap_p = Fpixmap_spec_p (value);
+ Lisp_Object pixmap_p = Fbitmap_spec_p (value);
if (!NILP (pixmap_p))
to[LFACE_STIPPLE_INDEX] = value;
else
- display_message (f, "Illegal face stipple", value, Qnil);
+ add_to_log ("Illegal face stipple", value, Qnil);
#endif
}
else if (EQ (keyword, QCwidth))
&& face_numeric_swidth (value) >= 0)
to[LFACE_SWIDTH_INDEX] = value;
else
- display_message (f, "Illegal face width", value, Qnil);
+ add_to_log ("Illegal face width", value, Qnil);
}
else
- display_message (f, "Invalid attribute %s in face property",
- keyword, Qnil);
+ add_to_log ("Invalid attribute %s in face property",
+ keyword, Qnil);
prop = XCDR (XCDR (prop));
}
/* PROP ought to be a face name. */
Lisp_Object lface = lface_from_face_name (f, prop, 0);
if (NILP (lface))
- display_message (f, "Invalid face text property value: %s",
- prop, Qnil);
+ add_to_log ("Invalid face text property value: %s", prop, Qnil);
else
merge_face_vectors (XVECTOR (lface)->contents, to);
}
CHECK_SYMBOL (face, 0);
CHECK_SYMBOL (attr, 1);
+ face = resolve_face_name (face);
+
/* Set lface to the Lisp attribute vector of FACE. */
if (EQ (frame, Qt))
lface = lface_from_face_name (NULL, face, 1);
else
{
if (NILP (frame))
- XSETFRAME (frame, selected_frame);
+ frame = selected_frame;
CHECK_LIVE_FRAME (frame, 3);
lface = lface_from_face_name (XFRAME (frame), face, 0);
#ifdef HAVE_X_WINDOWS
if (!UNSPECIFIEDP (value)
&& !NILP (value)
- && NILP (Fpixmap_spec_p (value)))
+ && NILP (Fbitmap_spec_p (value)))
signal_error ("Invalid stipple attribute", value);
old_value = LFACE_STIPPLE (lface);
LFACE_STIPPLE (lface) = value;
CHECK_STRING (value, 3);
if (EQ (frame, Qt))
- f = selected_frame;
+ f = SELECTED_FRAME ();
else
f = check_x_frame (frame);
}
#ifdef HAVE_X_WINDOWS
- /* Changed font-related attributes of the `default' face are
- reflected in changed `font' frame parameters. */
- if (EQ (face, Qdefault)
- && !EQ (frame, Qt)
- && font_related_attr_p
- && lface_fully_specified_p (XVECTOR (lface)->contents)
+
+ if (!EQ (frame, Qt)
+ && !UNSPECIFIEDP (value)
&& NILP (Fequal (old_value, value)))
- set_font_frame_param (frame, lface);
+ {
+ Lisp_Object param;
+
+ param = Qnil;
+
+ if (EQ (face, Qdefault))
+ {
+ /* Changed font-related attributes of the `default' face are
+ reflected in changed `font' frame parameters. */
+ if (font_related_attr_p
+ && lface_fully_specified_p (XVECTOR (lface)->contents))
+ set_font_frame_param (frame, lface);
+ else if (EQ (attr, QCforeground))
+ param = Qforeground_color;
+ else if (EQ (attr, QCbackground))
+ param = Qbackground_color;
+ }
+ else if (EQ (face, Qscroll_bar))
+ {
+ /* Changing the colors of `scroll-bar' sets frame parameters
+ `scroll-bar-foreground' and `scroll-bar-background'. */
+ if (EQ (attr, QCforeground))
+ param = Qscroll_bar_foreground;
+ else if (EQ (attr, QCbackground))
+ param = Qscroll_bar_background;
+ }
+ else if (EQ (face, Qborder))
+ {
+ /* Changing background color of `border' sets frame parameter
+ `border-color'. */
+ if (EQ (attr, QCbackground))
+ param = Qborder_color;
+ }
+ else if (EQ (face, Qcursor))
+ {
+ /* Changing background color of `cursor' sets frame parameter
+ `cursor-color'. */
+ if (EQ (attr, QCbackground))
+ param = Qcursor_color;
+ }
+ else if (EQ (face, Qmouse))
+ {
+ /* Changing background color of `mouse' sets frame parameter
+ `mouse-color'. */
+ if (EQ (attr, QCbackground))
+ param = Qmouse_color;
+ }
+
+ if (SYMBOLP (param))
+ Fmodify_frame_parameters (frame, Fcons (Fcons (param, value), Qnil));
+ }
#endif /* HAVE_X_WINDOWS */
}
+/* Update the corresponding face when frame parameter PARAM on frame F
+ has been assigned the value NEW_VALUE. */
+
+void
+update_face_from_frame_parameter (f, param, new_value)
+ struct frame *f;
+ Lisp_Object param, new_value;
+{
+ Lisp_Object lface;
+
+ /* If there are no faces yet, give up. This is the case when called
+ from Fx_create_frame, and we do the necessary things later in
+ face-set-after-frame-defaults. */
+ if (NILP (f->face_alist))
+ return;
+
+ if (EQ (param, Qforeground_color))
+ {
+ lface = lface_from_face_name (f, Qdefault, 1);
+ LFACE_FOREGROUND (lface) = (STRINGP (new_value)
+ ? new_value : Qunspecified);
+ realize_basic_faces (f);
+ }
+ else if (EQ (param, Qbackground_color))
+ {
+ Lisp_Object frame;
+
+ /* Changing the background color might change the background
+ mode, so that we have to load new defface specs. Call
+ frame-update-face-colors to do that. */
+ XSETFRAME (frame, f);
+ call1 (Qframe_update_face_colors, frame);
+
+ lface = lface_from_face_name (f, Qdefault, 1);
+ LFACE_BACKGROUND (lface) = (STRINGP (new_value)
+ ? new_value : Qunspecified);
+ realize_basic_faces (f);
+ }
+ if (EQ (param, Qborder_color))
+ {
+ lface = lface_from_face_name (f, Qborder, 1);
+ LFACE_BACKGROUND (lface) = (STRINGP (new_value)
+ ? new_value : Qunspecified);
+ }
+ else if (EQ (param, Qcursor_color))
+ {
+ lface = lface_from_face_name (f, Qcursor, 1);
+ LFACE_BACKGROUND (lface) = (STRINGP (new_value)
+ ? new_value : Qunspecified);
+ }
+ else if (EQ (param, Qmouse_color))
+ {
+ lface = lface_from_face_name (f, Qmouse, 1);
+ LFACE_BACKGROUND (lface) = (STRINGP (new_value)
+ ? new_value : Qunspecified);
+ }
+}
+
+
/* Get the value of X resource RESOURCE, class CLASS for the display
of frame FRAME. This is here because ordinary `x-get-resource'
doesn't take a frame argument. */
}
+\f
+/***********************************************************************
+ Menu face
+ ***********************************************************************/
+
+#ifdef USE_X_TOOLKIT
+
+/* Structure used to pass X resources to functions called via
+ XtApplyToWidgets. */
+
+struct x_resources
+{
+ Arg *av;
+ int ac;
+};
+
+
+#ifdef USE_MOTIF
+
+static void xm_apply_resources P_ ((Widget, XtPointer));
+static void xm_set_menu_resources_from_menu_face P_ ((struct frame *, Widget));
+
+
+/* Set widget W's X resources from P which points to an x_resources
+ structure. If W is a cascade button, apply resources to W's
+ submenu. */
+
+static void
+xm_apply_resources (w, p)
+ Widget w;
+ XtPointer p;
+{
+ Widget submenu = 0;
+ struct x_resources *res = (struct x_resources *) p;
+
+ XtSetValues (w, res->av, res->ac);
+ XtVaGetValues (w, XmNsubMenuId, &submenu, NULL);
+ if (submenu)
+ {
+ XtSetValues (submenu, res->av, res->ac);
+ XtApplyToWidgets (submenu, xm_apply_resources, p);
+ }
+}
+
+
+/* Set X resources of menu-widget WIDGET on frame F from face `menu'.
+ This is the LessTif/Motif version. As of LessTif 0.88 it has the
+ following problems:
+
+ 1. Setting the XmNfontList resource leads to an infinite loop
+ somewhere in LessTif. */
+
+static void
+xm_set_menu_resources_from_menu_face (f, widget)
+ struct frame *f;
+ Widget widget;
+{
+ struct face *face;
+ Lisp_Object lface;
+ Arg av[3];
+ int ac = 0;
+ XmFontList fl = 0;
+
+ lface = lface_from_face_name (f, Qmenu, 1);
+ face = FACE_FROM_ID (f, MENU_FACE_ID);
+
+ if (!UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
+ {
+ XtSetArg (av[ac], XmNforeground, face->foreground);
+ ++ac;
+ }
+
+ if (!UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
+ {
+ XtSetArg (av[ac], XmNbackground, face->background);
+ ++ac;
+ }
+
+ /* If any font-related attribute of `menu' is set, set the font. */
+ if (face->font
+ && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
+ || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
+ || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
+ || !UNSPECIFIEDP (LFACE_SLANT (lface))
+ || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
+ {
+#if 0 /* Setting the font leads to an infinite loop somewhere
+ in LessTif during geometry computation. */
+ XmFontListEntry fe;
+ fe = XmFontListEntryCreate ("menu_font", XmFONT_IS_FONT, face->font);
+ fl = XmFontListAppendEntry (NULL, fe);
+ XtSetArg (av[ac], XmNfontList, fl);
+ ++ac;
+#endif
+ }
+
+ xassert (ac <= sizeof av / sizeof *av);
+
+ if (ac)
+ {
+ struct x_resources res;
+
+ XtSetValues (widget, av, ac);
+ res.av = av, res.ac = ac;
+ XtApplyToWidgets (widget, xm_apply_resources, &res);
+ if (fl)
+ XmFontListFree (fl);
+ }
+}
+
+
+#endif /* USE_MOTIF */
+
+#ifdef USE_LUCID
+
+static void xl_apply_resources P_ ((Widget, XtPointer));
+static void xl_set_menu_resources_from_menu_face P_ ((struct frame *, Widget));
+
+
+/* Set widget W's resources from P which points to an x_resources
+ structure. */
+
+static void
+xl_apply_resources (widget, p)
+ Widget widget;
+ XtPointer p;
+{
+ struct x_resources *res = (struct x_resources *) p;
+ XtSetValues (widget, res->av, res->ac);
+}
+
+
+/* On frame F, set X resources of menu-widget WIDGET from face `menu'.
+ This is the Lucid version. */
+
+static void
+xl_set_menu_resources_from_menu_face (f, widget)
+ struct frame *f;
+ Widget widget;
+{
+ struct face *face;
+ Lisp_Object lface;
+ Arg av[3];
+ int ac = 0;
+
+ lface = lface_from_face_name (f, Qmenu, 1);
+ face = FACE_FROM_ID (f, MENU_FACE_ID);
+
+ if (!UNSPECIFIEDP (LFACE_FOREGROUND (lface)))
+ {
+ XtSetArg (av[ac], XtNforeground, face->foreground);
+ ++ac;
+ }
+
+ if (!UNSPECIFIEDP (LFACE_BACKGROUND (lface)))
+ {
+ XtSetArg (av[ac], XtNbackground, face->background);
+ ++ac;
+ }
+
+ if (face->font
+ && (!UNSPECIFIEDP (LFACE_FAMILY (lface))
+ || !UNSPECIFIEDP (LFACE_SWIDTH (lface))
+ || !UNSPECIFIEDP (LFACE_WEIGHT (lface))
+ || !UNSPECIFIEDP (LFACE_SLANT (lface))
+ || !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
+ {
+ XtSetArg (av[ac], XtNfont, face->font);
+ ++ac;
+ }
+
+ if (ac)
+ {
+ struct x_resources res;
+
+ XtSetValues (widget, av, ac);
+
+ /* We must do children here in case we're handling a pop-up menu
+ in which case WIDGET is a popup shell. XtApplyToWidgets
+ is a function from lwlib. */
+ res.av = av, res.ac = ac;
+ XtApplyToWidgets (widget, xl_apply_resources, &res);
+ }
+}
+
+#endif /* USE_LUCID */
+
+
+/* On frame F, set X resources of menu-widget WIDGET from face `menu'. */
+
+void
+x_set_menu_resources_from_menu_face (f, widget)
+ struct frame *f;
+ Widget widget;
+{
+#ifdef USE_LUCID
+ xl_set_menu_resources_from_menu_face (f, widget);
+#endif
+#ifdef USE_MOTIF
+ xm_set_menu_resources_from_menu_face (f, widget);
+#endif
+}
+
+#endif /* USE_X_TOOLKIT */
+
#endif /* HAVE_X_WINDOWS */
else
{
if (NILP (frame))
- XSETFRAME (frame, selected_frame);
+ frame = selected_frame;
CHECK_LIVE_FRAME (frame, 2);
lface = lface_from_face_name (XFRAME (frame), symbol, 1);
}
int i;
if (NILP (frame))
- f = selected_frame;
- else
- {
- CHECK_LIVE_FRAME (frame, 0);
- f = XFRAME (frame);
- }
+ frame = selected_frame;
+ CHECK_LIVE_FRAME (frame, 0);
+ f = XFRAME (frame);
if (EQ (frame, Qt))
lface = lface_from_face_name (NULL, face, 1);
for (face = c->buckets[i]; face; face = face->next)
if (face->hash == hash
- && (FRAME_TERMCAP_P (f)
+ && (!FRAME_WINDOW_P (f)
|| FACE_SUITABLE_FOR_CHARSET_P (face, charset))
&& lface_equal_p (face->lface, attr))
break;
return face_id;
}
+/* Return the face id of the realized face for named face SYMBOL on
+ frame F suitable for displaying characters from CHARSET (CHARSET <
+ 0 means unibyte text), and use attributes of the face FACE_ID for
+ attributes that aren't completely specified by SYMBOL. This is
+ like lookup_named_face, except that the default attributes come
+ from FACE_ID, not from the default face. FACE_ID is assumed to
+ be already realized. */
+
+int
+lookup_derived_face (f, symbol, charset, face_id)
+ struct frame *f;
+ Lisp_Object symbol;
+ int charset;
+ int face_id;
+{
+ Lisp_Object attrs[LFACE_VECTOR_SIZE];
+ Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
+ struct face *default_face = FACE_FROM_ID (f, face_id);
+
+ if (!default_face)
+ abort ();
+
+ get_lface_attributes (f, symbol, symbol_attrs, 1);
+ bcopy (default_face->lface, attrs, sizeof attrs);
+ merge_face_vectors (symbol_attrs, attrs);
+ return lookup_face (f, attrs, charset);
+}
+
\f
/***********************************************************************
if (realize_default_face (f))
{
- realize_named_face (f, Qmodeline, MODE_LINE_FACE_ID);
- realize_named_face (f, Qtoolbar, TOOLBAR_FACE_ID);
- realize_named_face (f, Qbitmap_area, BITMAP_AREA_FACE_ID);
- realize_named_face (f, Qtop_line, TOP_LINE_FACE_ID);
+ realize_named_face (f, Qmode_line, MODE_LINE_FACE_ID);
+ realize_named_face (f, Qtool_bar, TOOL_BAR_FACE_ID);
+ realize_named_face (f, Qfringe, BITMAP_AREA_FACE_ID);
+ realize_named_face (f, Qheader_line, HEADER_LINE_FACE_ID);
+ realize_named_face (f, Qscroll_bar, SCROLL_BAR_FACE_ID);
+ realize_named_face (f, Qborder, BORDER_FACE_ID);
+ realize_named_face (f, Qcursor, CURSOR_FACE_ID);
+ realize_named_face (f, Qmouse, MOUSE_FACE_ID);
+ realize_named_face (f, Qmenu, MENU_FACE_ID);
success_p = 1;
}
}
#endif /* HAVE_X_WINDOWS */
- if (FRAME_TERMCAP_P (f))
+ if (!FRAME_WINDOW_P (f))
{
LFACE_FAMILY (lface) = build_string ("default");
LFACE_SWIDTH (lface) = Qnormal;
LFACE_FOREGROUND (lface) = XCDR (color);
else if (FRAME_X_P (f))
return 0;
- else if (FRAME_TERMCAP_P (f))
+ else if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
/* Frame parameters for terminal frames usually don't contain
a color. Use an empty string to indicate that the face
should use the (unknown) default color of the terminal. */
LFACE_BACKGROUND (lface) = XCDR (color);
else if (FRAME_X_P (f))
return 0;
- else if (FRAME_TERMCAP_P (f))
+ else if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
/* Frame parameters for terminal frames usually don't contain
a color. Use an empty string to indicate that the face
should use the (unknown) default color of the terminal. */
if (FRAME_X_P (c->f))
face = realize_x_face (c, attrs, charset);
- else if (FRAME_TERMCAP_P (c->f))
+ else if (FRAME_TERMCAP_P (c->f) || FRAME_MSDOS_P (c->f))
face = realize_tty_face (c, attrs, charset);
else
abort ();
Lisp_Object color;
/* Frame must be a termcap frame. */
- xassert (FRAME_TERMCAP_P (c->f));
+ xassert (FRAME_TERMCAP_P (c->f) || FRAME_MSDOS_P (c->f));
/* Allocate a new realized face. */
face = make_realized_face (attrs, charset, Qnil);
- face->font_name = "tty";
+ face->font_name = FRAME_MSDOS_P (c->f) ? "ms-dos" : "tty";
/* Map face attributes to TTY appearances. We map slant to
dimmed text because we want italic text to appear differently
CONSP (color)))
face->foreground = XINT (XCDR (color));
+#ifdef MSDOS
+ if (FRAME_MSDOS_P (c->f) && face->foreground == FACE_TTY_DEFAULT_COLOR)
+ {
+ face->foreground = load_color (c->f, face,
+ attrs[LFACE_FOREGROUND_INDEX],
+ LFACE_FOREGROUND_INDEX);
+ /* If the foreground of the default face is the default color,
+ use the foreground color defined by the frame. */
+ if (face->foreground == FACE_TTY_DEFAULT_COLOR)
+ {
+ face->foreground = FRAME_FOREGROUND_PIXEL (f);
+ attrs[LFACE_FOREGROUND_INDEX] =
+ build_string (msdos_stdcolor_name (face->foreground));
+ }
+ }
+#endif
+
color = attrs[LFACE_BACKGROUND_INDEX];
if (XSTRING (color)->size
&& (color = Fassoc (color, Vface_tty_color_alist),
CONSP (color)))
face->background = XINT (XCDR (color));
+#ifdef MSDOS
+ if (FRAME_MSDOS_P (c->f) && face->background == FACE_TTY_DEFAULT_COLOR)
+ {
+ face->background = load_color (c->f, face,
+ attrs[LFACE_BACKGROUND_INDEX],
+ LFACE_BACKGROUND_INDEX);
+ /* If the background of the default face is the default color,
+ use the background color defined by the frame. */
+ if (face->background == FACE_TTY_DEFAULT_COLOR)
+ {
+ face->background = FRAME_BACKGROUND_PIXEL (f);
+ attrs[LFACE_BACKGROUND_INDEX] =
+ build_string (msdos_stdcolor_name (face->background));
+ }
+ }
+
+ /* Swap colors if face is inverse-video. */
+ if (face->tty_reverse_p)
+ {
+ unsigned long tem = face->foreground;
+
+ face->foreground = face->background;
+ face->background = tem;
+ }
+#endif
+
return face;
}
/* W must display the current buffer. We could write this function
to use the frame and buffer of W, but right now it doesn't. */
- xassert (XBUFFER (w->buffer) == current_buffer);
+ /* xassert (XBUFFER (w->buffer) == current_buffer); */
XSETFRAME (frame, f);
XSETFASTINT (position, pos);
REGION_BEG and REGION_END give the start and end positions of the
region; both are -1 if no region is visible. BASE_FACE_ID is the
id of the basic face to merge with. It is usually equal to
- DEFAULT_FACE_ID but can be MODE_LINE_FACE_ID or TOP_LINE_FACE_ID
+ DEFAULT_FACE_ID but can be MODE_LINE_FACE_ID or HEADER_LINE_FACE_ID
for strings displayed in the mode or top line.
Set *ENDPTR to the next position where to check for faces in
debug_print (Vface_alternative_font_family_alist);
fprintf (stderr, "\n");
- for (i = 0; i < FRAME_FACE_CACHE (selected_frame)->used; ++i)
+ for (i = 0; i < FRAME_FACE_CACHE (SELECTED_FRAME ())->used; ++i)
Fdump_face (make_number (i));
}
else
{
struct face *face;
CHECK_NUMBER (n, 0);
- face = FACE_FROM_ID (selected_frame, XINT (n));
+ face = FACE_FROM_ID (SELECTED_FRAME (), XINT (n));
if (face == NULL)
error ("Not a valid face");
dump_realized_face (face);
{
Qface = intern ("face");
staticpro (&Qface);
- Qpixmap_spec_p = intern ("pixmap-spec-p");
- staticpro (&Qpixmap_spec_p);
-
+ Qbitmap_spec_p = intern ("bitmap-spec-p");
+ staticpro (&Qbitmap_spec_p);
+ Qframe_update_face_colors = intern ("frame-update-face-colors");
+ staticpro (&Qframe_update_face_colors);
+
/* Lisp face attribute keywords. */
QCfamily = intern (":family");
staticpro (&QCfamily);
Qx_charset_registry = intern ("x-charset-registry");
staticpro (&Qx_charset_registry);
+ Qface_alias = intern ("face-alias");
+ staticpro (&Qface_alias);
Qdefault = intern ("default");
staticpro (&Qdefault);
- Qmodeline = intern ("modeline");
- staticpro (&Qmodeline);
- Qtoolbar = intern ("toolbar");
- staticpro (&Qtoolbar);
+ Qmode_line = intern ("mode-line");
+ staticpro (&Qmode_line);
+ Qtool_bar = intern ("tool-bar");
+ staticpro (&Qtool_bar);
Qregion = intern ("region");
staticpro (&Qregion);
- Qbitmap_area = intern ("bitmap-area");
- staticpro (&Qbitmap_area);
- Qtop_line = intern ("top-line");
- staticpro (&Qtop_line);
+ Qfringe = intern ("fringe");
+ staticpro (&Qfringe);
+ Qheader_line = intern ("header-line");
+ staticpro (&Qheader_line);
+ Qscroll_bar = intern ("scroll-bar");
+ staticpro (&Qscroll_bar);
+ Qmenu = intern ("menu");
+ staticpro (&Qmenu);
+ Qcursor = intern ("cursor");
+ staticpro (&Qcursor);
+ Qborder = intern ("border");
+ staticpro (&Qborder);
+ Qmouse = intern ("mouse");
+ staticpro (&Qmouse);
defsubr (&Sinternal_make_lisp_face);
defsubr (&Sinternal_lisp_face_p);
#endif /* GLYPH_DEBUG */
defsubr (&Sclear_face_cache);
+ DEFVAR_LISP ("font-list-limit", &Vfont_list_limit,
+ "*Limit for font matching.\n\
+If an integer > 0, font matching functions won't load more than\n\
+that number of fonts when searching for a matching font.");
+ Vfont_list_limit = make_number (DEFAULT_FONT_LIST_LIMIT);
+
DEFVAR_LISP ("face-new-frame-defaults", &Vface_new_frame_defaults,
"List of global face definitions (for internal use only.)");
Vface_new_frame_defaults = Qnil;
#endif /* SCALABLE_FONTS */
#ifdef HAVE_X_WINDOWS
- defsubr (&Spixmap_spec_p);
+ defsubr (&Sbitmap_spec_p);
defsubr (&Sx_list_fonts);
defsubr (&Sinternal_face_x_get_resource);
- defsubr (&Sx_font_list);
+ defsubr (&Sx_family_fonts);
defsubr (&Sx_font_family_list);
#endif /* HAVE_X_WINDOWS */