2002-12-17 Miles Bader * xfaces.c (Vrealize_face_filter): New variable. (realize_face): If Vrealize_face_filter has a non-nil value, use it to filter the face attributes before realization. Use new calling conventsions for realize_x_face, realize_tty_face, and load_face_font. (realize_x_face, realize_tty_face): Add new argument FACE, and change return type to void. Use FACE instead of creating our own. (load_face_font): Add a new argument ATTRS, and use it instead of FACE->lface. (syms_of_xfaces): Initialize Vrealize_face_filter. Index: src/xfaces.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/xfaces.c,v retrieving revision 1.266 diff -u -r1.266 xfaces.c --- src/xfaces.c 17 Nov 2002 23:51:19 -0000 1.266 +++ src/xfaces.c 17 Dec 2002 07:01:09 -0000 @@ -422,6 +422,13 @@ Lisp_Object Vtty_defined_color_alist; +/* If non-nil, a function called to perturb faces before final realization. + It is passed a lisp-vector containing all the attributes of the + fully-specified face, and can change any that it wishes. */ + +Lisp_Object Vrealize_face_filter; + + /* Counter for calls to clear_face_cache. If this counter reaches CLEAR_FONT_TABLE_COUNT, and a frame has more than CLEAR_FONT_TABLE_NFONTS load, unused fonts are freed. */ @@ -481,7 +488,7 @@ 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 void load_face_font P_ ((struct frame *, struct face *, int)); +static void load_face_font P_ ((struct frame *, struct face *, Lisp_Object *, int)); 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 *)); @@ -502,10 +509,10 @@ static int cmp_font_names P_ ((const void *, const void *)); static struct face *realize_face P_ ((struct face_cache *, Lisp_Object *, int, struct face *, int)); -static struct face *realize_x_face P_ ((struct face_cache *, - Lisp_Object *, int, struct face *)); -static struct face *realize_tty_face P_ ((struct face_cache *, - Lisp_Object *, int)); +static void realize_x_face P_ ((struct face *, struct face_cache *, + Lisp_Object *, int, struct face *)); +static void realize_tty_face P_ ((struct face *, struct face_cache *, + Lisp_Object *, int)); static int realize_basic_faces P_ ((struct frame *)); static int realize_default_face P_ ((struct frame *)); static void realize_named_face P_ ((struct frame *, Lisp_Object, int)); @@ -1245,14 +1252,15 @@ #ifdef HAVE_WINDOW_SYSTEM -/* Load font of face FACE which is used on frame F to display - character C. The name of the font to load is determined by lface - and fontset of FACE. */ +/* Load font of face FACE with attributes ATTRS which is used on frame F to + display character C. The name of the font to load is determined by + lface and fontset of FACE. */ static void -load_face_font (f, face, c) +load_face_font (f, face, attrs, c) struct frame *f; struct face *face; + Lisp_Object *attrs; int c; { struct font_info *font_info = NULL; @@ -1262,7 +1270,7 @@ face->font_info_id = -1; face->font = NULL; - font_name = choose_face_font (f, face->lface, face->fontset, c, + font_name = choose_face_font (f, attrs, face->fontset, c, &needs_overstrike); if (!font_name) return; @@ -6678,6 +6686,11 @@ int former_face_id; { struct face *face; + /* The set of attributes this face is know by to the user, as opposed to + the set actually used to render the face. They're usually the same + as, but may be different if some attribute is changed by + realize-face-filter. */ + Lisp_Object *orig_attrs = attrs; /* LFACE must be fully specified. */ xassert (cache != NULL); @@ -6691,41 +6704,59 @@ free_realized_face (cache->f, former_face); } + if (! NILP (Vrealize_face_filter)) + { + /* Call a user-defined function to perturb the face attributes + before realization. */ + Lisp_Object lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE), + Qunspecified); + bcopy (attrs, XVECTOR (lface)->contents, + LFACE_VECTOR_SIZE * (sizeof *attrs)); + + safe_call1 (Vrealize_face_filter, lface); + + attrs = XVECTOR (lface)->contents; + } + + /* Allocate a new realized face. */ + face = make_realized_face (orig_attrs); + + /* Fill it in. */ if (FRAME_WINDOW_P (cache->f)) - face = realize_x_face (cache, attrs, c, base_face); + realize_x_face (face, cache, attrs, c, base_face); else if (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f)) - face = realize_tty_face (cache, attrs, c); + realize_tty_face (face, cache, attrs, c); else abort (); /* Insert the new face. */ - cache_face (cache, face, lface_hash (attrs)); + cache_face (cache, face, lface_hash (orig_attrs)); #ifdef HAVE_WINDOW_SYSTEM if (FRAME_WINDOW_P (cache->f) && face->font == NULL) - load_face_font (cache->f, face, c); + load_face_font (cache->f, face, attrs, 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 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. */ +/* Realize into FACE 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 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) +static void +realize_x_face (face, cache, attrs, c, base_face) + struct face *face; struct face_cache *cache; Lisp_Object *attrs; int c; struct face *base_face; { #ifdef HAVE_WINDOW_SYSTEM - struct face *face, *default_face; + struct face *default_face; struct frame *f; Lisp_Object stipple, overline, strike_through, box; @@ -6733,9 +6764,6 @@ xassert (SINGLE_BYTE_CHAR_P (c) || base_face); - /* Allocate a new realized face. */ - face = make_realized_face (attrs); - f = cache->f; /* If C is a multibyte character, we share all face attirbutes with @@ -6751,7 +6779,7 @@ /* to force realize_face to load font */ face->font = NULL; - return face; + return; } /* Now we are realizing a face for ASCII (and unibyte) characters. */ @@ -6921,7 +6949,6 @@ face->stipple = load_pixmap (f, stipple, &face->pixmap_w, &face->pixmap_h); xassert (FACE_SUITABLE_FOR_CHAR_P (face, c)); - return face; #endif /* HAVE_WINDOW_SYSTEM */ } @@ -7012,17 +7039,16 @@ } -/* Realize the fully-specified face with attributes ATTRS in face - cache CACHE for character C. Do it for TTY frame CACHE->f. Value is a - pointer to the newly created realized face. */ +/* Realize into FACE the fully-specified face with attributes ATTRS in face + cache CACHE for character C. Do it for TTY frame CACHE->f. */ -static struct face * -realize_tty_face (cache, attrs, c) +static void +realize_tty_face (face, cache, attrs, c) + struct face *face; struct face_cache *cache; Lisp_Object *attrs; int c; { - struct face *face; int weight, slant; int face_colors_defaulted = 0; struct frame *f = cache->f; @@ -7030,8 +7056,6 @@ /* Frame must be a termcap frame. */ xassert (FRAME_TERMCAP_P (cache->f) || FRAME_MSDOS_P (cache->f)); - /* Allocate a new realized face. */ - face = make_realized_face (attrs); face->font_name = FRAME_MSDOS_P (cache->f) ? "ms-dos" : "tty"; /* Map face attributes to TTY appearances. We map slant to @@ -7068,8 +7092,6 @@ && face->background == FACE_TTY_DEFAULT_FG_COLOR && face->foreground == FACE_TTY_DEFAULT_BG_COLOR) face->tty_bold_p = 0; - - return face; } @@ -7670,6 +7692,13 @@ Each element is a regular expression that matches names of fonts to ignore. */); Vface_ignored_fonts = Qnil; + + DEFVAR_LISP ("realize-face-filter", &Vrealize_face_filter, + doc: /* If non-nil, a function called to perturb faces before final realization. +It is passed a lisp-vector containing all the attributes of the +fully-specified face, and can change any that it wishes. */); + Vrealize_face_filter = Qnil; + #ifdef HAVE_WINDOW_SYSTEM defsubr (&Sbitmap_spec_p);