/* xfaces.c -- "Face" primitives.
- Copyright (C) 1993, 1994, 1998, 1999, 2000 Free Software Foundation.
+ Copyright (C) 1993, 1994, 1998, 1999, 2000, 2001
+ Free Software Foundation.
This file is part of GNU Emacs.
width---tries to find a best match for the specified font height,
etc.
- 2. Setting face-alternative-font-family-alist allows the user to
+ 2. Setting face-font-family-alternatives allows the user to
specify alternative font families to try if a family specified by a
face doesn't exist.
+ 3. Setting face-font-registry-alternatives allows the user to
+ specify all alternative font registries to try for a face
+ specifying a registry.
+
+ 4. Setting face-ignored-fonts allows the user to ignore specific
+ fonts.
+
Character compositition.
basic faces are realized for CHARSET_ASCII. Frame parameters are
used to fill in unspecified attributes of the default face. */
-/* Define SCALABLE_FONTS to a non-zero value to enable scalable
- font use. Define it to zero to disable scalable font use.
-
- Use of too many or too large scalable fonts can crash XFree86
- servers. That's why I've put the code dealing with scalable fonts
- in #if's. */
-
-#define SCALABLE_FONTS 1
-
#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_WINDOW_SYSTEM
#include "fontset.h"
-#endif
+#endif /* HAVE_WINDOW_SYSTEM */
+
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#ifdef USE_MOTIF
#include <Xm/Xm.h>
#include <Xm/XmStrDefs.h>
#endif /* USE_MOTIF */
-#endif
+#endif /* HAVE_X_WINDOWS */
#ifdef MSDOS
#include "dosfns.h"
/* For historic reasons, FONT_WIDTH refers to average width on W32,
not maximum as on X. Redefine here. */
#define FONT_WIDTH FONT_MAX_WIDTH
+#endif /* WINDOWSNT */
+
+#ifdef macintosh
+#include "macterm.h"
+#define x_display_info mac_display_info
+#define check_x check_mac
+
+extern XGCValues *XCreateGC (void *, WindowPtr, unsigned long, XGCValues *);
+
+static INLINE GC
+x_create_gc (f, mask, xgcv)
+ struct frame *f;
+ unsigned long mask;
+ XGCValues *xgcv;
+{
+ GC gc;
+ gc = XCreateGC (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), mask, xgcv);
+ return gc;
+}
+
+static INLINE void
+x_free_gc (f, gc)
+ struct frame *f;
+ GC gc;
+{
+ XFreeGC (FRAME_MAC_DISPLAY (f), gc);
+}
#endif
#include "buffer.h"
#define abs(X) ((X) < 0 ? -(X) : (X))
#endif
+/* Number of pt per inch (from the TeXbook). */
+
+#define PT_PER_INCH 72.27
+
/* Non-zero if face attribute ATTR is unspecified. */
#define UNSPECIFIEDP(ATTR) EQ ((ATTR), Qunspecified)
Lisp_Object Vface_alternative_font_family_alist;
+/* Alist of alternative font registries. Each element is of the form
+ (REGISTRY REGISTRY1 REGISTRY2...). If fonts of REGISTRY can't be
+ loaded, try REGISTRY1, then REGISTRY2, ... */
+
+Lisp_Object Vface_alternative_font_registry_alist;
+
/* Allowed scalable fonts. A value of nil means don't allow any
scalable fonts. A value of t means allow the use of any scalable
font. Otherwise, value must be a list of regular expressions. A
font may be scaled if its name matches a regular expression in the
list. */
-#if SCALABLE_FONTS
Lisp_Object Vscalable_fonts_allowed;
-#endif
+
+/* List of regular expressions that matches names of fonts to ignore. */
+
+Lisp_Object Vface_ignored_fonts;
/* Maximum number of fonts to consider in font_list. If not an
integer > 0, DEFAULT_FONT_LIST_LIMIT is used instead. */
int face_change_count;
+/* Incremented for every change in the `menu' face. */
+
+int menu_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
int tty_suppress_bold_inverse_default_colors_p;
+/* A list of the form `((x . y))' used to avoid consing in
+ Finternal_set_lisp_face_attribute. */
+
+static Lisp_Object Vparam_value_alist;
+
/* The total number of colors currently allocated. */
#if GLYPH_DEBUG
static int sorted_font_list P_ ((struct frame *, char *,
int (*cmpfn) P_ ((const void *, const void *)),
struct font_name **));
+static int font_list_1 P_ ((struct frame *, Lisp_Object, Lisp_Object,
+ Lisp_Object, struct font_name **));
static int font_list P_ ((struct frame *, Lisp_Object, Lisp_Object,
Lisp_Object, struct font_name **));
static int try_font_list P_ ((struct frame *, Lisp_Object *, Lisp_Object,
return Qnil;
}
-
#endif /* DEBUG_X_COLORS */
+
/* 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. */
necessary and some servers don't allow it. So don't do it. */
if (class != StaticColor && class != StaticGray && class != TrueColor)
{
- XFreeColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
- pixels, npixels, 0);
#ifdef DEBUG_X_COLORS
unregister_colors (pixels, npixels);
#endif
+ XFreeColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+ pixels, npixels, 0);
}
}
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);
#endif
+ XFreeColors (dpy, cmap, pixels, npixels, 0);
}
}
#endif
#ifdef macintosh
else if (FRAME_MAC_P (f))
- /* FIXME: mac_defined_color doesn't exist! */
return mac_defined_color (f, color_name, color_def, alloc);
#endif
else
{"black", XLFD_WEIGHT_ULTRA_BOLD, &Qultra_bold},
{"bold", XLFD_WEIGHT_BOLD, &Qbold},
{"book", XLFD_WEIGHT_SEMI_LIGHT, &Qsemi_light},
+ {"demi", XLFD_WEIGHT_SEMI_BOLD, &Qsemi_bold},
{"demibold", XLFD_WEIGHT_SEMI_BOLD, &Qsemi_bold},
{"extralight", XLFD_WEIGHT_EXTRA_LIGHT, &Qextra_light},
{"extrabold", XLFD_WEIGHT_EXTRA_BOLD, &Qextra_bold},
/* Numeric values for those fields that interest us. See
split_font_name for which these are. */
int numeric[XLFD_LAST];
+
+ /* Lower value mean higher priority. */
+ int registry_priority;
};
/* The frame in effect when sorting font names. Set temporarily in
font height, then for weight, then for slant.' This variable can be
set via set-face-font-sort-order. */
+#ifdef macintosh
+static int font_sort_order[4] = { XLFD_SWIDTH, XLFD_POINT_SIZE, XLFD_WEIGHT, XLFD_SLANT };
+#else
static int font_sort_order[4];
-
+#endif
/* Look up FONT.fields[FIELD_INDEX] in TABLE which has DIM entries.
TABLE must be sorted by TABLE[i]->name in ascending order. Value
struct font_name *font;
{
double resy = FRAME_X_DISPLAY_INFO (f)->resy;
- double font_resy = atoi (font->fields[XLFD_RESY]);
- double font_pt = atoi (font->fields[XLFD_POINT_SIZE]);
+ double font_pixel = atoi (font->fields[XLFD_PIXEL_SIZE]);
int real_pt;
- if (font_resy == 0 || font_pt == 0)
+ if (font_pixel == 0)
real_pt = 0;
else
- real_pt = (font_resy / resy) * font_pt + 0.5;
+ real_pt = PT_PER_INCH * 10.0 * font_pixel / resy + 0.5;
return real_pt;
}
double real_pt;
int int_pt;
- /* As one inch is 72 points, 72/RESY gives the point size of one dot. */
- real_pt = pixel * 72 / resy;
+ /* As one inch is PT_PER_INCH points, PT_PER_INCH/RESY gives the
+ point size of one dot. */
+ real_pt = pixel * PT_PER_INCH / resy;
int_pt = real_pt + 0.5;
return int_pt;
font->numeric[XLFD_SWIDTH] = xlfd_numeric_swidth (font);
}
+ /* Initialize it to zero. It will be overridden by font_list while
+ trying alternate registries. */
+ font->registry_priority = 0;
+
return success_p;
}
For all fonts found, set FONTS[i].name to the name of the font,
allocated via xmalloc, and split font names into fields. Ignore
- fonts that we can't parse. Value is the number of fonts found.
-
- This is similar to x_list_fonts. The differences are:
-
- 1. It avoids consing.
- 2. It never calls XLoadQueryFont. */
+ fonts that we can't parse. Value is the number of fonts found. */
static int
x_face_list_fonts (f, pattern, fonts, nfonts, try_alternatives_p,
int nfonts, try_alternatives_p;
int scalable_fonts_p;
{
- int n, i, j;
- char **names;
-#ifdef HAVE_X_WINDOWS
- Display *dpy = f ? FRAME_X_DISPLAY (f) : x_display_list->display;
+ int n;
- /* Get the list of fonts matching PATTERN from the X server. */
- BLOCK_INPUT;
- names = XListFonts (dpy, pattern, nfonts, &n);
- UNBLOCK_INPUT;
-#endif
-#ifdef WINDOWSNT
/* NTEMACS_TODO : currently this uses w32_list_fonts, but it may be
better to do it the other way around. */
Lisp_Object lfonts;
Lisp_Object lpattern, tem;
- n = 0;
- names = NULL;
-
lpattern = build_string (pattern);
/* Get the list of fonts matching PATTERN. */
+#ifdef WINDOWSNT
BLOCK_INPUT;
lfonts = w32_list_fonts (f, lpattern, 0, nfonts);
UNBLOCK_INPUT;
+#else
+ lfonts = x_list_fonts (f, lpattern, scalable_fonts_p ? -1 : 0, nfonts);
+#endif
- /* Count fonts returned */
+ /* Make a copy of the font names we got from X, and
+ split them into fields. */
+ n = 0;
for (tem = lfonts; CONSP (tem); tem = XCDR (tem))
- n++;
-
- /* Allocate array. */
- if (n)
- names = (char **) xmalloc (n * sizeof (char *));
-
- /* Extract font names into char * array. */
- tem = lfonts;
- for (i = 0; i < n; i++)
{
- names[i] = XSTRING (XCAR (tem))->data;
- tem = XCDR (tem);
- }
-#endif
+ Lisp_Object elt, tail;
+ char *name = XSTRING (XCAR (tem))->data;
- if (names)
- {
- /* Make a copy of the font names we got from X, and
- split them into fields. */
- for (i = j = 0; i < n; ++i)
+ for (tail = Vface_ignored_fonts; CONSP (tail); tail = XCDR (tail))
{
- /* Make a copy of the font name. */
- fonts[j].name = xstrdup (names[i]);
-
- /* Ignore fonts having a name that we can't parse. */
- if (!split_font_name (f, fonts + j, 1))
- xfree (fonts[j].name);
- else if (font_scalable_p (fonts + j))
- {
-#if SCALABLE_FONTS
- if (!scalable_fonts_p
- || !may_use_scalable_font_p (fonts + j, names[i]))
- xfree (fonts[j].name);
- else
- ++j;
-#else /* !SCALABLE_FONTS */
- /* Always ignore scalable fonts. */
- xfree (fonts[j].name);
-#endif /* !SCALABLE_FONTS */
- }
- else
- ++j;
+ elt = XCAR (tail);
+ if (STRINGP (elt)
+ && fast_c_string_match_ignore_case (elt, name) >= 0)
+ break;
}
+ if (!NILP (tail))
+ continue;
- n = j;
+ /* Make a copy of the font name. */
+ fonts[n].name = xstrdup (name);
-#ifdef HAVE_X_WINDOWS
- /* Free font names. */
- BLOCK_INPUT;
- XFreeFontNames (names);
- UNBLOCK_INPUT;
-#endif
+ /* Ignore fonts having a name that we can't parse. */
+ if (!split_font_name (f, fonts + n, 1))
+ xfree (fonts[n].name);
+ else if (font_scalable_p (fonts + n))
+ {
+ if (!scalable_fonts_p
+ || !may_use_scalable_font_p (fonts + n, name))
+ xfree (fonts[n].name);
+ else
+ ++n;
+ }
+ else
+ ++n;
}
-
/* If no fonts found, try patterns from Valternate_fontname_alist. */
if (n == 0 && try_alternatives_p)
{
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);
-#else
- nfonts = x_face_list_fonts (f, pattern, *fonts, nfonts, 1, 0);
-#endif
/* Sort the resulting array and return it in *FONTS. If no
fonts were found, make sure to set *FONTS to null. */
Value is the number of fonts found. */
static int
-font_list (f, pattern, family, registry, fonts)
+font_list_1 (f, pattern, family, registry, fonts)
struct frame *f;
Lisp_Object pattern, family, registry;
struct font_name **fonts;
}
+/* Concatenate font list FONTS1 and FONTS2. FONTS1 and FONTS2
+ contains NFONTS1 fonts and NFONTS2 fonts respectively. Return a
+ pointer to a newly allocated font list. FONTS1 and FONTS2 are
+ freed. */
+
+static struct font_name *
+concat_font_list (fonts1, nfonts1, fonts2, nfonts2)
+ struct font_name *fonts1, *fonts2;
+ int nfonts1, nfonts2;
+{
+ int new_nfonts = nfonts1 + nfonts2;
+ struct font_name *new_fonts;
+
+ new_fonts = (struct font_name *) xmalloc (sizeof *new_fonts * new_nfonts);
+ bcopy (fonts1, new_fonts, sizeof *new_fonts * nfonts1);
+ bcopy (fonts2, new_fonts + nfonts1, sizeof *new_fonts * nfonts2);
+ xfree (fonts1);
+ xfree (fonts2);
+ return new_fonts;
+}
+
+
+/* Get a sorted list of fonts of family FAMILY on frame F.
+
+ If PATTERN is non-nil list fonts matching that pattern.
+
+ If REGISTRY is non-nil, return fonts with that registry and the
+ alternative registries from Vface_alternative_font_registry_alist.
+
+ If REGISTRY is nil return fonts of any registry.
+
+ Set *FONTS to a vector of font_name structures allocated from the
+ heap containing the fonts found. Value is the number of fonts
+ found. */
+
+static int
+font_list (f, pattern, family, registry, fonts)
+ struct frame *f;
+ Lisp_Object pattern, family, registry;
+ struct font_name **fonts;
+{
+ int nfonts = font_list_1 (f, pattern, family, registry, fonts);
+
+ if (!NILP (registry)
+ && CONSP (Vface_alternative_font_registry_alist))
+ {
+ Lisp_Object alter;
+
+ alter = Fassoc (registry, Vface_alternative_font_registry_alist);
+ if (CONSP (alter))
+ {
+ int reg_prio, i;
+
+ for (alter = XCDR (alter), reg_prio = 1;
+ CONSP (alter);
+ alter = XCDR (alter), reg_prio++)
+ if (STRINGP (XCAR (alter)))
+ {
+ int nfonts2;
+ struct font_name *fonts2;
+
+ nfonts2 = font_list_1 (f, pattern, family, XCAR (alter),
+ &fonts2);
+ for (i = 0; i < nfonts2; i++)
+ fonts2[i].registry_priority = reg_prio;
+ *fonts = (nfonts > 0
+ ? concat_font_list (*fonts, nfonts, fonts2, nfonts2)
+ : fonts2);
+ nfonts += nfonts2;
+ }
+ }
+ }
+
+ return nfonts;
+}
+
+
/* Remove elements from LIST whose cars are `equal'. Called from
x-family-fonts and x-font-family-list to remove duplicate font
entries. */
/* This is of limited utility since it works with character
widths. Keep it for compatibility. --gerd. */
int face_id = lookup_named_face (f, face, 0);
- struct face *face = FACE_FROM_ID (f, face_id);
+ struct face *face = (face_id < 0
+ ? NULL
+ : FACE_FROM_ID (f, face_id));
- if (face->font)
+ if (face && face->font)
size = FONT_WIDTH (face->font);
else
size = FONT_WIDTH (FRAME_FONT (f));
if (STRINGP (face_name))
face_name = intern (XSTRING (face_name)->data);
- for (;;)
+ while (SYMBOLP (face_name))
{
aliased = Fget (face_name, Qface_alias);
if (NILP (aliased))
/* 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 FACE_NAME is an alias for
- another face, return that face's definition. If SIGNAL_P is
+ return the definition for new frames. FACE_NAME may be a string or
+ a symbol (apparently Emacs 20.2 allowed strings as face names in
+ face 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. */
return 1;
}
+
#endif /* HAVE_WINDOW_SYSTEM */
args[0] = from;
args[1] = to;
- height = call_function (2, args);
+ height = safe_call (2, args);
UNGCPRO;
/* Merge two Lisp face attribute vectors on frame F, FROM and TO, and
- store the resulting attributes in TO. Every non-nil attribute of
- FROM overrides the corresponding attribute of TO. CYCLE_CHECK is
- used internally to detect loops in face inheritance; it should be
- Qnil when called from other places. */
+ store the resulting attributes in TO, which must be already be
+ completely specified and contain only absolute attributes. Every
+ specified attribute of FROM overrides the corresponding attribute of
+ TO; relative attributes in FROM are merged with the absolute value in
+ TO and replace it. CYCLE_CHECK is used internally to detect loops in
+ face inheritance; it should be Qnil when called from other places. */
static INLINE void
merge_face_vectors (f, from, to, cycle_check)
&& !NILP (from[LFACE_INHERIT_INDEX]))
merge_face_inheritance (f, from[LFACE_INHERIT_INDEX], to, cycle_check);
+ /* If TO specifies a :font attribute, and FROM specifies some
+ font-related attribute, we need to clear TO's :font attribute
+ (because it will be inconsistent with whatever FROM specifies, and
+ FROM takes precedence). */
+ if (!NILP (to[LFACE_FONT_INDEX])
+ && (!UNSPECIFIEDP (from[LFACE_FAMILY_INDEX])
+ || !UNSPECIFIEDP (from[LFACE_HEIGHT_INDEX])
+ || !UNSPECIFIEDP (from[LFACE_WEIGHT_INDEX])
+ || !UNSPECIFIEDP (from[LFACE_SLANT_INDEX])
+ || !UNSPECIFIEDP (from[LFACE_SWIDTH_INDEX])))
+ to[LFACE_FONT_INDEX] = Qnil;
+
for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
if (!UNSPECIFIEDP (from[i]))
if (i == LFACE_HEIGHT_INDEX && !INTEGERP (from[i]))
CHECK is evaluated multiple times, EL and SUSPICIOUS 0 or 1 times, so
the caller should make sure that's ok. */
-#define CYCLE_CHECK(check, el, suspicious) \
- (NILP (check) \
- ? make_number (0) \
- : INTEGERP (check) \
- ? (XFASTINT (check) < (suspicious) \
- ? make_number (XFASTINT (check) + 1) \
- : Fcons (el, Qnil)) \
- : Fmemq ((el), (check)) \
- ? Qnil \
- : Fcons ((el), (check)))
+#define CYCLE_CHECK(check, el, suspicious) \
+ (NILP (check) \
+ ? make_number (0) \
+ : (INTEGERP (check) \
+ ? (XFASTINT (check) < (suspicious) \
+ ? make_number (XFASTINT (check) + 1) \
+ : Fcons (el, Qnil)) \
+ : (!NILP (Fmemq ((el), (check))) \
+ ? Qnil \
+ : Fcons ((el), (check)))))
+
+
+/* Merge face attributes from the face on frame F whose name is
+ INHERITS, into the vector of face attributes TO; INHERITS may also be
+ a list of face names, in which case they are applied in order.
+ CYCLE_CHECK is used to detect loops in face inheritance.
+ Returns true if any of the inherited attributes are `font-related'. */
static void
merge_face_inheritance (f, inherit, to, cycle_check)
DEFUN ("internal-set-lisp-face-attribute", Finternal_set_lisp_face_attribute,
Sinternal_set_lisp_face_attribute, 3, 4, 0,
"Set attribute ATTR of FACE to VALUE.\n\
-If optional argument FRAME is given, set the face attribute of face FACE\n\
-on that frame. If FRAME is t, set the attribute of the default for face\n\
-FACE (for new frames). If FRAME is omitted or nil, use the selected\n\
-frame.")
+FRAME being a frame means change the face on that frame.\n\
+FRAME nil means change change the face of the selected frame.\n\
+FRAME t means change the default for new frames.\n\
+FRAME 0 means change the face on all frames, and change the default\n\
+ for new frames.")
(face, attr, value, frame)
Lisp_Object face, attr, value, frame;
{
face = resolve_face_name (face);
+ /* If FRAME is 0, change face on all frames, and change the
+ default for new frames. */
+ if (INTEGERP (frame) && XINT (frame) == 0)
+ {
+ Lisp_Object tail;
+ Finternal_set_lisp_face_attribute (face, attr, value, Qt);
+ FOR_EACH_FRAME (tail, frame)
+ Finternal_set_lisp_face_attribute (face, attr, value, frame);
+ return face;
+ }
+
/* Set lface to the Lisp attribute vector of FACE. */
if (EQ (frame, Qt))
lface = lface_from_face_name (NULL, face, 1);
{
if (!UNSPECIFIEDP (value))
{
- Lisp_Object test = Qnil;
-
- if (!EQ (face, Qdefault))
- /* The default face must have an absolute size, otherwise, we do
- a test merge with a random height to see if VALUE's ok. */
- test = merge_face_heights (value, make_number(10), Qnil, Qnil);
+ Lisp_Object test =
+ (EQ (face, Qdefault) ? value :
+ /* The default face must have an absolute size, otherwise, we do
+ a test merge with a random height to see if VALUE's ok. */
+ merge_face_heights (value, make_number(10), Qnil, Qnil));
if (!INTEGERP(test) || XINT(test) <= 0)
signal_error ("Invalid face height", value);
#ifdef HAVE_WINDOW_SYSTEM
- if (!EQ (frame, Qt)
- && !UNSPECIFIEDP (value)
+ if (!UNSPECIFIEDP (value)
&& NILP (Fequal (old_value, value)))
{
Lisp_Object param;
else if (EQ (attr, QCbackground))
param = Qscroll_bar_background;
}
-#endif
+#endif /* not WINDOWSNT */
else if (EQ (face, Qborder))
{
/* Changing background color of `border' sets frame parameter
if (EQ (attr, QCbackground))
param = Qmouse_color;
}
+ else if (EQ (face, Qmenu))
+ ++menu_face_change_count;
if (!NILP (param))
- Fmodify_frame_parameters (frame, Fcons (Fcons (param, value), Qnil));
+ if (EQ (frame, Qt))
+ /* Update `default-frame-alist', which is used for new frames. */
+ {
+ store_in_alist (&Vdefault_frame_alist, param, value);
+ }
+ else
+ /* Update the current frame's parameters. */
+ {
+ Lisp_Object cons;
+ cons = XCAR (Vparam_value_alist);
+ XCAR (cons) = param;
+ XCDR (cons) = value;
+ Fmodify_frame_parameters (frame, Vparam_value_alist);
+ }
}
#endif /* HAVE_WINDOW_SYSTEM */
Lisp_Object frame, lface;
{
struct frame *f = XFRAME (frame);
- Lisp_Object font_name;
- char *font;
- if (STRINGP (LFACE_FONT (lface)))
- font_name = LFACE_FONT (lface);
- else
+ if (FRAME_WINDOW_P (f))
{
- /* Choose a font name that reflects LFACE's attributes and has
- the registry and encoding pattern specified in the default
- fontset (3rd arg: -1) for ASCII characters (4th arg: 0). */
- font = choose_face_font (f, XVECTOR (lface)->contents, -1, 0);
- if (!font)
- error ("No font matches the specified attribute");
- font_name = build_string (font);
- xfree (font);
+ Lisp_Object font_name;
+ char *font;
+
+ if (STRINGP (LFACE_FONT (lface)))
+ font_name = LFACE_FONT (lface);
+ else
+ {
+ /* Choose a font name that reflects LFACE's attributes and has
+ the registry and encoding pattern specified in the default
+ fontset (3rd arg: -1) for ASCII characters (4th arg: 0). */
+ font = choose_face_font (f, XVECTOR (lface)->contents, -1, 0);
+ if (!font)
+ error ("No font matches the specified attribute");
+ font_name = build_string (font);
+ xfree (font);
+ }
+
+ Fmodify_frame_parameters (frame, Fcons (Fcons (Qfont, font_name), Qnil));
}
- store_frame_param (f, Qfont, font_name);
}
{
Lisp_Object value = Qnil;
#ifndef WINDOWSNT
+#ifndef macintosh
CHECK_STRING (resource, 0);
CHECK_STRING (class, 1);
CHECK_LIVE_FRAME (frame, 2);
value = display_x_get_resource (FRAME_X_DISPLAY_INFO (XFRAME (frame)),
resource, class, Qnil, Qnil);
UNBLOCK_INPUT;
-#endif
+#endif /* not macintosh */
+#endif /* not WINDOWSNT */
return value;
}
}
}
-
#endif /* USE_MOTIF */
#ifdef USE_LUCID
if (f->face_cache->used == 0)
recompute_basic_faces (f);
+ BLOCK_INPUT;
#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
+ UNBLOCK_INPUT;
}
#endif /* USE_X_TOOLKIT */
DEFUN ("internal-merge-in-global-face", Finternal_merge_in_global_face,
Sinternal_merge_in_global_face, 2, 2, 0,
- "Add attributes from frame-default definition of FACE to FACE on FRAME.")
+ "Add attributes from frame-default definition of FACE to FACE on FRAME.\n\
+Default face attributes override any local face attributes.")
(face, frame)
Lisp_Object face, frame;
{
- Lisp_Object global_lface, local_lface;
+ int i;
+ Lisp_Object global_lface, local_lface, *gvec, *lvec;
+
CHECK_LIVE_FRAME (frame, 1);
global_lface = lface_from_face_name (NULL, face, 1);
local_lface = lface_from_face_name (XFRAME (frame), face, 0);
if (NILP (local_lface))
local_lface = Finternal_make_lisp_face (face, frame);
- merge_face_vectors (XFRAME (frame),
- XVECTOR (global_lface)->contents,
- XVECTOR (local_lface)->contents,
- Qnil);
- return face;
+
+ /* Make every specified global attribute override the local one.
+ BEWARE!! This is only used from `face-set-after-frame-default' where
+ the local frame is defined from default specs in `face-defface-spec'
+ and those should be overridden by global settings. Hence the strange
+ "global before local" priority. */
+ lvec = XVECTOR (local_lface)->contents;
+ gvec = XVECTOR (global_lface)->contents;
+ for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
+ if (! UNSPECIFIEDP (gvec[i]))
+ lvec[i] = gvec[i];
+
+ return Qnil;
}
struct frame *f = frame_or_selected_frame (frame, 1);
int face_id = lookup_named_face (f, face, 0);
struct face *face = FACE_FROM_ID (f, face_id);
- return build_string (face->font_name);
+ return face ? build_string (face->font_name) : Qnil;
}
}
#endif
#ifdef WINDOWSNT
xgcv.font = face->font;
+#endif
+#ifdef macintosh
+ xgcv.font = face->font;
#endif
mask |= GCFont;
}
/* Return the face id of the realized face for named face SYMBOL on
- frame F suitable for displaying character C. */
+ frame F suitable for displaying character C. Value is -1 if the
+ face couldn't be determined, which might happen if the default face
+ isn't realized and cannot be realized. */
int
lookup_named_face (f, symbol, c)
Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+ if (default_face == NULL)
+ {
+ if (!realize_basic_faces (f))
+ return -1;
+ default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
+ }
+
get_lface_attributes (f, symbol, symbol_attrs, 1);
bcopy (default_face->lface, attrs, sizeof attrs);
merge_face_vectors (f, symbol_attrs, attrs, Qnil);
new_face = FACE_FROM_ID (f, new_face_id);
/* If height changes, count that as one step. */
- if (FONT_HEIGHT (new_face->font) != last_height)
+ if ((delta < 0 && FONT_HEIGHT (new_face->font) < last_height)
+ || (delta > 0 && FONT_HEIGHT (new_face->font) > last_height))
{
--steps;
last_height = FONT_HEIGHT (new_face->font);
return face_id;
}
+
/* Return the face id of the realized face for named face SYMBOL on
frame F suitable for displaying character C, and use attributes of
the face FACE_ID for attributes that aren't completely specified by
}
+DEFUN ("internal-set-alternative-font-registry-alist",
+ Finternal_set_alternative_font_registry_alist,
+ Sinternal_set_alternative_font_registry_alist, 1, 1, 0,
+ "Define alternative font registries to try in face font selection.\n\
+ALIST is an alist of (REGISTRY ALTERNATIVE1 ALTERNATIVE2 ...) entries.\n\
+Each ALTERNATIVE is tried in order if no fonts of font registry REGISTRY can\n\
+be found. Value is ALIST.")
+ (alist)
+ Lisp_Object alist;
+{
+ CHECK_LIST (alist, 0);
+ Vface_alternative_font_registry_alist = alist;
+ free_all_realized_faces (Qnil);
+ return alist;
+}
+
+
#ifdef HAVE_WINDOW_SYSTEM
/* Value is non-zero if FONT is the name of a scalable font. The
}
+/* Ignore the difference of font point size less than this value. */
+
+#define FONT_POINT_SIZE_QUANTUM 5
+
/* Value is non-zero if FONT1 is a better match for font attributes
VALUES than FONT2. VALUES is an array of face attribute values in
font sort order. COMPARE_PT_P zero means don't compare point
int delta1 = abs (values[i] - font1->numeric[xlfd_idx]);
int delta2 = abs (values[i] - font2->numeric[xlfd_idx]);
+ if (xlfd_idx == XLFD_POINT_SIZE
+ && abs (delta1 - delta2) < FONT_POINT_SIZE_QUANTUM)
+ continue;
if (delta1 > delta2)
return 0;
else if (delta1 < delta2)
}
}
- return 0;
+ return (font1->registry_priority < font2->registry_priority);
}
-#if SCALABLE_FONTS
-
/* Value is non-zero if FONT is an exact match for face attributes in
SPECIFIED. SPECIFIED is an array of face attribute values in font
sort order. */
if (font->numeric[XLFD_RESY] != 0)
{
pt = resy / font->numeric[XLFD_RESY] * specified_pt + 0.5;
- pixel_value = font->numeric[XLFD_RESY] / 720.0 * pt;
+ pixel_value = font->numeric[XLFD_RESY] / (PT_PER_INCH * 10.0) * pt;
}
else
{
pt = specified_pt;
- pixel_value = resy / 720.0 * pt;
+ pixel_value = resy / (PT_PER_INCH * 10.0) * pt;
}
/* Set point size of the font. */
return 0;
}
-#endif /* SCALABLE_FONTS != 0 */
/* Return the name of the best matching font for face attributes
{
char *font_name;
struct font_name *best;
- int i, pt;
+ int i, pt = 0;
int specified[4];
int exact_p;
abort ();
}
-#if SCALABLE_FONTS
-
- /* Set to 1 */
exact_p = 0;
/* Start with the first non-scalable font in the list. */
else
font_name = build_font_name (best);
-#else /* !SCALABLE_FONTS */
-
- /* Find the best non-scalable font. */
- best = fonts;
-
- for (i = 1; i < nfonts; ++i)
- {
- xassert (!font_scalable_p (fonts + i));
- if (better_font_p (specified, fonts + i, best, 1))
- best = fonts + i;
- }
-
- font_name = build_font_name (best);
-
-#endif /* !SCALABLE_FONTS */
-
/* Free font_name structures. */
free_font_names (fonts, nfonts);
family = attrs[LFACE_FAMILY_INDEX];
nfonts = font_list (f, pattern, family, registry, fonts);
-
if (nfonts == 0 && !NILP (family))
{
Lisp_Object alter;
- /* Try alternative font families from
- Vface_alternative_font_family_alist. */
+ /* Try alternative font families. */
alter = Fassoc (family, Vface_alternative_font_family_alist);
if (CONSP (alter))
for (alter = XCDR (alter);
Lisp_Object *attrs;
{
Lisp_Object name;
- int fontset;
name = attrs[LFACE_FONT_INDEX];
if (!STRINGP (name))
realize_named_face (f, Qcursor, CURSOR_FACE_ID);
realize_named_face (f, Qmouse, MOUSE_FACE_ID);
realize_named_face (f, Qmenu, MENU_FACE_ID);
+
+ /* Reflect changes in the `menu' face in menu bars. */
+ if (menu_face_change_count)
+ {
+ menu_face_change_count = 0;
+
+#ifdef USE_X_TOOLKIT
+ if (FRAME_X_P (f))
+ {
+ Widget menu = f->output_data.x->menubar_widget;
+ if (menu)
+ x_set_menu_resources_from_menu_face (f, menu);
+ }
+#endif /* USE_X_TOOLKIT */
+ }
+
success_p = 1;
}
Lisp_Object attrs[LFACE_VECTOR_SIZE];
Lisp_Object frame_font;
struct face *face;
- int fontset;
/* If the `default' face is not yet known, create it. */
lface = lface_from_face_name (f, Qdefault, 0);
frame_font = Fassq (Qfont, f->param_alist);
xassert (CONSP (frame_font) && STRINGP (XCDR (frame_font)));
frame_font = XCDR (frame_font);
- set_lface_from_font_name (f, lface, frame_font, 0, 1);
+ set_lface_from_font_name (f, lface, frame_font, 1, 1);
}
#endif /* HAVE_WINDOW_SYSTEM */
LFACE_FOREGROUND (lface) = XCDR (color);
else if (FRAME_WINDOW_P (f))
return 0;
- else if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
+ else if (FRAME_TERMCAP_P (f)
+ || FRAME_MSDOS_P (f)
+ || FRAME_W32_CONSOLE_P (f))
LFACE_FOREGROUND (lface) = build_string (unspecified_fg);
else
abort ();
LFACE_BACKGROUND (lface) = XCDR (color);
else if (FRAME_WINDOW_P (f))
return 0;
- else if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
+ else if (FRAME_TERMCAP_P (f)
+ || FRAME_MSDOS_P (f)
+ || FRAME_W32_CONSOLE_P (f))
LFACE_BACKGROUND (lface) = build_string (unspecified_bg);
else
abort ();
if (FRAME_WINDOW_P (cache->f))
face = realize_x_face (cache, attrs, c, base_face);
- else if (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f))
+ else if (FRAME_TERMCAP_P (cache->f)
+ || FRAME_MSDOS_P (cache->f)
+ || FRAME_W32_CONSOLE_P (cache->f))
face = realize_tty_face (cache, attrs, c);
else
abort ();
fontset = default_face->fontset;
face->fontset = make_fontset_for_ascii_face (f, fontset);
face->font = NULL; /* to force realize_face to load font */
+
+#ifdef macintosh
+ /* Load the font if it is specified in ATTRS. This fixes
+ changing frame font on the Mac. */
+ if (STRINGP (attrs[LFACE_FONT_INDEX]))
+ {
+ struct font_info *font_info =
+ FS_LOAD_FONT (f, 0, XSTRING (attrs[LFACE_FONT_INDEX])->data, -1);
+ if (font_info)
+ face->font = font_info->font;
+ }
+#endif
}
/* Load colors, and set remaining attributes. */
struct frame *f = cache->f;
/* Frame must be a termcap frame. */
- xassert (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f));
+ xassert (FRAME_TERMCAP_P (cache->f)
+ || FRAME_MSDOS_P (cache->f)
+ || FRAME_W32_CONSOLE_P (cache->f));
/* Allocate a new realized face. */
face = make_realized_face (attrs);
- face->font_name = FRAME_MSDOS_P (cache->f) ? "ms-dos" : "tty";
+ face->font_name = FRAME_MSDOS_P (cache->f) ? "ms-dos"
+ : FRAME_W32_CONSOLE_P (cache->f) ? "w32console" : "tty";
/* Map face attributes to TTY appearances. We map slant to
dimmed text because we want italic text to appear differently
Lisp_Object propname = mouse ? Qmouse_face : Qface;
Lisp_Object limit1, end;
struct face *default_face;
- int multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
/* 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. */
current_buffer, otherwise BUFPOS is zero to indicate that STRING is
not an overlay string. W must display the current buffer.
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 HEADER_LINE_FACE_ID
- for strings displayed in the mode or top line.
+ region; both are -1 if no region is visible.
+
+ BASE_FACE_ID is the id of a face to merge with. For strings coming
+ from overlays or the `display' property it is the face at BUFPOS.
Set *ENDPTR to the next position where to check for faces in
STRING; -1 if the face is constant from POS to the end of the
Qtty_color_alist = intern ("tty-color-alist");
staticpro (&Qtty_color_alist);
+ Vparam_value_alist = Fcons (Fcons (Qnil, Qnil), Qnil);
+ staticpro (&Vparam_value_alist);
Vface_alternative_font_family_alist = Qnil;
staticpro (&Vface_alternative_font_family_alist);
+ Vface_alternative_font_registry_alist = Qnil;
+ staticpro (&Vface_alternative_font_registry_alist);
defsubr (&Sinternal_make_lisp_face);
defsubr (&Sinternal_lisp_face_p);
defsubr (&Sframe_face_alist);
defsubr (&Sinternal_set_font_selection_order);
defsubr (&Sinternal_set_alternative_font_family_alist);
+ defsubr (&Sinternal_set_alternative_font_registry_alist);
#if GLYPH_DEBUG
defsubr (&Sdump_face);
defsubr (&Sshow_face_resources);
"An alist of defined terminal colors and their RGB values.");
Vtty_defined_color_alist = Qnil;
-#if SCALABLE_FONTS
-
DEFVAR_LISP ("scalable-fonts-allowed", &Vscalable_fonts_allowed,
"Allowed scalable fonts.\n\
A value of nil means don't allow any scalable fonts.\n\
A value of t means allow any scalable font.\n\
Otherwise, value must be a list of regular expressions. A font may be\n\
scaled if its name matches a regular expression in the list.");
-#ifdef WINDOWSNT
+#if defined (WINDOWSNT) || defined (macintosh)
/* Windows uses mainly truetype fonts, so disallowing scalable fonts
by default limits the fonts available severely. */
Vscalable_fonts_allowed = Qt;
#else
Vscalable_fonts_allowed = Qnil;
#endif
-#endif /* SCALABLE_FONTS */
+
+ DEFVAR_LISP ("face-ignored-fonts", &Vface_ignored_fonts,
+ "List of ignored fonts.\n\
+Each element is a regular expression that matches names of fonts to ignore.");
+ Vface_ignored_fonts = Qnil;
#ifdef HAVE_WINDOW_SYSTEM
defsubr (&Sbitmap_spec_p);