aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniel Colascione2018-06-07 16:20:06 -0700
committerDaniel Colascione2018-06-07 21:03:30 -0700
commit9d447fa1562c69f2224bdefc37703c0eb0f7d7cf (patch)
treedd1d64edecb820298d433f5537e12835058db362 /src
parente2a98002020369cf0c09c7acf8557290e867705f (diff)
downloademacs-9d447fa1562c69f2224bdefc37703c0eb0f7d7cf.tar.gz
emacs-9d447fa1562c69f2224bdefc37703c0eb0f7d7cf.zip
Add support for per-window face remapping
Extend face specifications to support the notion of filtering to a specific context and add a filter that limits a face specification to windows having a certain parameter. * src/xfaces.c: (evaluate_face_filter,filter_face_ref): New functions. (merge_face_ref): Ignore filtered face specifications. (Fx_list_fonts,get_lface_attributes,merge_face_vectors) (merge_named_face,merge_face_ref,merge_face_ref) (Finternal_merge_in_global_face,Fface_font,lookup_named_face) (lookup_basic_face,Fface_attributes_as_vector) (x_supports_face_attributes_p) (Fdisplay_supports_face_attributes_p,realize_named_face) (compute_char_face,face_at_buffer_position) (face_at_buffer_position,face_at_buffer_position) (face_at_buffer_position) (face_for_overlay_string,face_at_string_position,merge_faces): Pass window to face machinery. (syms_of_xfaces): Add :window and :filtered * src/xdisp.c (init_iterator, handle_face_prop) (handle_single_display_spec, merge_escape_glyph_face) (merge_glyphless_glyph_face, get_next_display_element) (next_element_from_display_vector, append_space_for_newline) (extend_face_to_end_of_line,highlight_trailing_whitespace) (maybe_produce_line_number) (display_line, calc_line_height_property): Pass window to face machinery. * src/term.c (tty_menu_activate): Adjust to new face core function signature. * src/msdos.c (XMenuActivate): Adjust to new face core function signature. * src/fringe.c (draw_fringe_bitmap_1, Fset_fringe_bitmap_face): Pass window to face machinery. * src/font.c (font_range, Finternal_char_font): Pass window to face machinery. * src/dispnew.c (spec_glyph_lookup_face): Pass window to face machinery. * src/dispextern.h: (lookup_named_face,lookup_basic_face) (lookup_derived_face,merge_faces): Add struct window arguments to prototypes.
Diffstat (limited to 'src')
-rw-r--r--src/dispextern.h9
-rw-r--r--src/dispnew.c3
-rw-r--r--src/font.c4
-rw-r--r--src/fringe.c22
-rw-r--r--src/msdos.c8
-rw-r--r--src/term.c8
-rw-r--r--src/xdisp.c51
-rw-r--r--src/xfaces.c304
8 files changed, 286 insertions, 123 deletions
diff --git a/src/dispextern.h b/src/dispextern.h
index bc2a76f1e02..2180c9ae63f 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3429,11 +3429,12 @@ char *choose_face_font (struct frame *, Lisp_Object *, Lisp_Object,
3429#ifdef HAVE_WINDOW_SYSTEM 3429#ifdef HAVE_WINDOW_SYSTEM
3430void prepare_face_for_display (struct frame *, struct face *); 3430void prepare_face_for_display (struct frame *, struct face *);
3431#endif 3431#endif
3432int lookup_named_face (struct frame *, Lisp_Object, bool); 3432int lookup_named_face (struct window *, struct frame *, Lisp_Object, bool);
3433int lookup_basic_face (struct frame *, int); 3433int lookup_basic_face (struct window *, struct frame *, int);
3434int smaller_face (struct frame *, int, int); 3434int smaller_face (struct frame *, int, int);
3435int face_with_height (struct frame *, int, int); 3435int face_with_height (struct frame *, int, int);
3436int lookup_derived_face (struct frame *, Lisp_Object, int, bool); 3436int lookup_derived_face (struct window *, struct frame *,
3437 Lisp_Object, int, bool);
3437void init_frame_faces (struct frame *); 3438void init_frame_faces (struct frame *);
3438void free_frame_faces (struct frame *); 3439void free_frame_faces (struct frame *);
3439void recompute_basic_faces (struct frame *); 3440void recompute_basic_faces (struct frame *);
@@ -3443,7 +3444,7 @@ int face_for_overlay_string (struct window *, ptrdiff_t, ptrdiff_t *, ptrdiff_t,
3443 bool, Lisp_Object); 3444 bool, Lisp_Object);
3444int face_at_string_position (struct window *, Lisp_Object, ptrdiff_t, ptrdiff_t, 3445int face_at_string_position (struct window *, Lisp_Object, ptrdiff_t, ptrdiff_t,
3445 ptrdiff_t *, enum face_id, bool); 3446 ptrdiff_t *, enum face_id, bool);
3446int merge_faces (struct frame *, Lisp_Object, int, int); 3447int merge_faces (struct window *, Lisp_Object, int, int);
3447int compute_char_face (struct frame *, int, Lisp_Object); 3448int compute_char_face (struct frame *, int, Lisp_Object);
3448void free_all_realized_faces (Lisp_Object); 3449void free_all_realized_faces (Lisp_Object);
3449extern char unspecified_fg[], unspecified_bg[]; 3450extern char unspecified_fg[], unspecified_bg[];
diff --git a/src/dispnew.c b/src/dispnew.c
index b854d179d51..46e0c83ef6a 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -2508,8 +2508,7 @@ spec_glyph_lookup_face (struct window *w, GLYPH *glyph)
2508 /* Convert the glyph's specified face to a realized (cache) face. */ 2508 /* Convert the glyph's specified face to a realized (cache) face. */
2509 if (lface_id > 0) 2509 if (lface_id > 0)
2510 { 2510 {
2511 int face_id = merge_faces (XFRAME (w->frame), 2511 int face_id = merge_faces (w, Qt, lface_id, DEFAULT_FACE_ID);
2512 Qt, lface_id, DEFAULT_FACE_ID);
2513 SET_GLYPH_FACE (*glyph, face_id); 2512 SET_GLYPH_FACE (*glyph, face_id);
2514 } 2513 }
2515} 2514}
diff --git a/src/font.c b/src/font.c
index 305bb14576a..c886c299d19 100644
--- a/src/font.c
+++ b/src/font.c
@@ -3810,7 +3810,7 @@ font_range (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t *limit,
3810 face_id = 3810 face_id =
3811 NILP (Vface_remapping_alist) 3811 NILP (Vface_remapping_alist)
3812 ? DEFAULT_FACE_ID 3812 ? DEFAULT_FACE_ID
3813 : lookup_basic_face (f, DEFAULT_FACE_ID); 3813 : lookup_basic_face (w, f, DEFAULT_FACE_ID);
3814 3814
3815 face_id = face_at_string_position (w, string, pos, 0, &ignore, 3815 face_id = face_at_string_position (w, string, pos, 0, &ignore,
3816 face_id, false); 3816 face_id, false);
@@ -4559,7 +4559,7 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
4559 CHECK_CHARACTER (ch); 4559 CHECK_CHARACTER (ch);
4560 c = XINT (ch); 4560 c = XINT (ch);
4561 f = XFRAME (selected_frame); 4561 f = XFRAME (selected_frame);
4562 face_id = lookup_basic_face (f, DEFAULT_FACE_ID); 4562 face_id = lookup_basic_face (NULL, f, DEFAULT_FACE_ID);
4563 pos = -1; 4563 pos = -1;
4564 } 4564 }
4565 else 4565 else
diff --git a/src/fringe.c b/src/fringe.c
index 85aa14da727..60691846814 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -587,8 +587,8 @@ draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int o
587 if (face_id == DEFAULT_FACE_ID) 587 if (face_id == DEFAULT_FACE_ID)
588 { 588 {
589 Lisp_Object face = fringe_faces[which]; 589 Lisp_Object face = fringe_faces[which];
590 face_id = NILP (face) ? lookup_named_face (f, Qfringe, false) 590 face_id = NILP (face) ? lookup_named_face (w, f, Qfringe, false)
591 : lookup_derived_face (f, face, FRINGE_FACE_ID, 0); 591 : lookup_derived_face (w, f, face, FRINGE_FACE_ID, 0);
592 if (face_id < 0) 592 if (face_id < 0)
593 face_id = FRINGE_FACE_ID; 593 face_id = FRINGE_FACE_ID;
594 } 594 }
@@ -1633,20 +1633,10 @@ If FACE is nil, reset face to default fringe face. */)
1633 if (!n) 1633 if (!n)
1634 error ("Undefined fringe bitmap"); 1634 error ("Undefined fringe bitmap");
1635 1635
1636 /* The purpose of the following code is to signal an error if FACE 1636 /* We used to check, as a convenience to callers, for basic face
1637 is not a face. This is for the caller's convenience only; the 1637 validity here, but since validity can depend on the specific
1638 redisplay code should be able to fail gracefully. Skip the check 1638 _window_ in which this buffer is being displayed, defer the check
1639 if FRINGE_FACE_ID is unrealized (as in batch mode and during 1639 to redisplay, which can cope with bad face specifications. */
1640 daemon startup). */
1641 if (!NILP (face))
1642 {
1643 struct frame *f = SELECTED_FRAME ();
1644
1645 if (FACE_FROM_ID_OR_NULL (f, FRINGE_FACE_ID)
1646 && lookup_derived_face (f, face, FRINGE_FACE_ID, 1) < 0)
1647 error ("No such face");
1648 }
1649
1650 fringe_faces[n] = face; 1640 fringe_faces[n] = face;
1651 return Qnil; 1641 return Qnil;
1652} 1642}
diff --git a/src/msdos.c b/src/msdos.c
index eedbf7b1a6c..6c0dfa0c46a 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -3063,15 +3063,15 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
3063 state = alloca (menu->panecount * sizeof (struct IT_menu_state)); 3063 state = alloca (menu->panecount * sizeof (struct IT_menu_state));
3064 screensize = screen_size * 2; 3064 screensize = screen_size * 2;
3065 faces[0] 3065 faces[0]
3066 = lookup_derived_face (sf, intern ("msdos-menu-passive-face"), 3066 = lookup_derived_face (NULL, sf, intern ("msdos-menu-passive-face"),
3067 DEFAULT_FACE_ID, 1); 3067 DEFAULT_FACE_ID, 1);
3068 faces[1] 3068 faces[1]
3069 = lookup_derived_face (sf, intern ("msdos-menu-active-face"), 3069 = lookup_derived_face (NULL, sf, intern ("msdos-menu-active-face"),
3070 DEFAULT_FACE_ID, 1); 3070 DEFAULT_FACE_ID, 1);
3071 selectface = intern ("msdos-menu-select-face"); 3071 selectface = intern ("msdos-menu-select-face");
3072 faces[2] = lookup_derived_face (sf, selectface, 3072 faces[2] = lookup_derived_face (NULL, sf, selectface,
3073 faces[0], 1); 3073 faces[0], 1);
3074 faces[3] = lookup_derived_face (sf, selectface, 3074 faces[3] = lookup_derived_face (NULL, sf, selectface,
3075 faces[1], 1); 3075 faces[1], 1);
3076 3076
3077 /* Make sure the menu title is always displayed with 3077 /* Make sure the menu title is always displayed with
diff --git a/src/term.c b/src/term.c
index 08d483f4fa0..bcd7dd82d6f 100644
--- a/src/term.c
+++ b/src/term.c
@@ -3132,15 +3132,15 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
3132 SAFE_NALLOCA (state, 1, menu->panecount); 3132 SAFE_NALLOCA (state, 1, menu->panecount);
3133 memset (state, 0, sizeof (*state)); 3133 memset (state, 0, sizeof (*state));
3134 faces[0] 3134 faces[0]
3135 = lookup_derived_face (sf, intern ("tty-menu-disabled-face"), 3135 = lookup_derived_face (NULL, sf, intern ("tty-menu-disabled-face"),
3136 DEFAULT_FACE_ID, 1); 3136 DEFAULT_FACE_ID, 1);
3137 faces[1] 3137 faces[1]
3138 = lookup_derived_face (sf, intern ("tty-menu-enabled-face"), 3138 = lookup_derived_face (NULL, sf, intern ("tty-menu-enabled-face"),
3139 DEFAULT_FACE_ID, 1); 3139 DEFAULT_FACE_ID, 1);
3140 selectface = intern ("tty-menu-selected-face"); 3140 selectface = intern ("tty-menu-selected-face");
3141 faces[2] = lookup_derived_face (sf, selectface, 3141 faces[2] = lookup_derived_face (NULL, sf, selectface,
3142 faces[0], 1); 3142 faces[0], 1);
3143 faces[3] = lookup_derived_face (sf, selectface, 3143 faces[3] = lookup_derived_face (NULL, sf, selectface,
3144 faces[1], 1); 3144 faces[1], 1);
3145 3145
3146 /* Make sure the menu title is always displayed with 3146 /* Make sure the menu title is always displayed with
diff --git a/src/xdisp.c b/src/xdisp.c
index ad1c044557d..a2b6513e571 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2809,7 +2809,7 @@ init_iterator (struct it *it, struct window *w,
2809 /* Perhaps remap BASE_FACE_ID to a user-specified alternative. */ 2809 /* Perhaps remap BASE_FACE_ID to a user-specified alternative. */
2810 if (! NILP (Vface_remapping_alist)) 2810 if (! NILP (Vface_remapping_alist))
2811 remapped_base_face_id 2811 remapped_base_face_id
2812 = lookup_basic_face (XFRAME (w->frame), base_face_id); 2812 = lookup_basic_face (w, XFRAME (w->frame), base_face_id);
2813 2813
2814 /* Use one of the mode line rows of W's desired matrix if 2814 /* Use one of the mode line rows of W's desired matrix if
2815 appropriate. */ 2815 appropriate. */
@@ -4060,7 +4060,7 @@ handle_face_prop (struct it *it)
4060 might be a big deal. */ 4060 might be a big deal. */
4061 base_face_id = it->string_from_prefix_prop_p 4061 base_face_id = it->string_from_prefix_prop_p
4062 ? (!NILP (Vface_remapping_alist) 4062 ? (!NILP (Vface_remapping_alist)
4063 ? lookup_basic_face (it->f, DEFAULT_FACE_ID) 4063 ? lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
4064 : DEFAULT_FACE_ID) 4064 : DEFAULT_FACE_ID)
4065 : underlying_face_id (it); 4065 : underlying_face_id (it);
4066 } 4066 }
@@ -4988,7 +4988,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
4988 struct face *f; 4988 struct face *f;
4989 4989
4990 f = FACE_FROM_ID (it->f, 4990 f = FACE_FROM_ID (it->f,
4991 lookup_basic_face (it->f, DEFAULT_FACE_ID)); 4991 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID));
4992 new_height = (XFLOATINT (it->font_height) 4992 new_height = (XFLOATINT (it->font_height)
4993 * XINT (f->lface[LFACE_HEIGHT_INDEX])); 4993 * XINT (f->lface[LFACE_HEIGHT_INDEX]));
4994 } 4994 }
@@ -5175,12 +5175,12 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5175 5175
5176 if (it) 5176 if (it)
5177 { 5177 {
5178 int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID); 5178 int face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
5179 5179
5180 if (CONSP (XCDR (XCDR (spec)))) 5180 if (CONSP (XCDR (XCDR (spec))))
5181 { 5181 {
5182 Lisp_Object face_name = XCAR (XCDR (XCDR (spec))); 5182 Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
5183 int face_id2 = lookup_derived_face (it->f, face_name, 5183 int face_id2 = lookup_derived_face (it->w, it->f, face_name,
5184 FRINGE_FACE_ID, false); 5184 FRINGE_FACE_ID, false);
5185 if (face_id2 >= 0) 5185 if (face_id2 >= 0)
5186 face_id = face_id2; 5186 face_id = face_id2;
@@ -6985,7 +6985,7 @@ merge_escape_glyph_face (struct it *it)
6985 else 6985 else
6986 { 6986 {
6987 /* Merge the `escape-glyph' face into the current face. */ 6987 /* Merge the `escape-glyph' face into the current face. */
6988 face_id = merge_faces (it->f, Qescape_glyph, 0, it->face_id); 6988 face_id = merge_faces (it->w, Qescape_glyph, 0, it->face_id);
6989 last_escape_glyph_frame = it->f; 6989 last_escape_glyph_frame = it->f;
6990 last_escape_glyph_face_id = it->face_id; 6990 last_escape_glyph_face_id = it->face_id;
6991 last_escape_glyph_merged_face_id = face_id; 6991 last_escape_glyph_merged_face_id = face_id;
@@ -7010,7 +7010,7 @@ merge_glyphless_glyph_face (struct it *it)
7010 else 7010 else
7011 { 7011 {
7012 /* Merge the `glyphless-char' face into the current face. */ 7012 /* Merge the `glyphless-char' face into the current face. */
7013 face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id); 7013 face_id = merge_faces (it->w, Qglyphless_char, 0, it->face_id);
7014 last_glyphless_glyph_frame = it->f; 7014 last_glyphless_glyph_frame = it->f;
7015 last_glyphless_glyph_face_id = it->face_id; 7015 last_glyphless_glyph_face_id = it->face_id;
7016 last_glyphless_glyph_merged_face_id = face_id; 7016 last_glyphless_glyph_merged_face_id = face_id;
@@ -7184,7 +7184,7 @@ get_next_display_element (struct it *it)
7184 } 7184 }
7185 7185
7186 face_id = (lface_id 7186 face_id = (lface_id
7187 ? merge_faces (it->f, Qt, lface_id, it->face_id) 7187 ? merge_faces (it->w, Qt, lface_id, it->face_id)
7188 : merge_escape_glyph_face (it)); 7188 : merge_escape_glyph_face (it));
7189 7189
7190 XSETINT (it->ctl_chars[0], g); 7190 XSETINT (it->ctl_chars[0], g);
@@ -7199,7 +7199,7 @@ get_next_display_element (struct it *it)
7199 if (nonascii_space_p && EQ (Vnobreak_char_display, Qt)) 7199 if (nonascii_space_p && EQ (Vnobreak_char_display, Qt))
7200 { 7200 {
7201 /* Merge `nobreak-space' into the current face. */ 7201 /* Merge `nobreak-space' into the current face. */
7202 face_id = merge_faces (it->f, Qnobreak_space, 0, 7202 face_id = merge_faces (it->w, Qnobreak_space, 0,
7203 it->face_id); 7203 it->face_id);
7204 XSETINT (it->ctl_chars[0], ' '); 7204 XSETINT (it->ctl_chars[0], ' ');
7205 ctl_len = 1; 7205 ctl_len = 1;
@@ -7212,7 +7212,7 @@ get_next_display_element (struct it *it)
7212 if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt)) 7212 if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
7213 { 7213 {
7214 /* Merge `nobreak-space' into the current face. */ 7214 /* Merge `nobreak-space' into the current face. */
7215 face_id = merge_faces (it->f, Qnobreak_hyphen, 0, 7215 face_id = merge_faces (it->w, Qnobreak_hyphen, 0,
7216 it->face_id); 7216 it->face_id);
7217 XSETINT (it->ctl_chars[0], '-'); 7217 XSETINT (it->ctl_chars[0], '-');
7218 ctl_len = 1; 7218 ctl_len = 1;
@@ -7232,7 +7232,7 @@ get_next_display_element (struct it *it)
7232 } 7232 }
7233 7233
7234 face_id = (lface_id 7234 face_id = (lface_id
7235 ? merge_faces (it->f, Qt, lface_id, it->face_id) 7235 ? merge_faces (it->w, Qt, lface_id, it->face_id)
7236 : merge_escape_glyph_face (it)); 7236 : merge_escape_glyph_face (it));
7237 7237
7238 /* Draw non-ASCII space/hyphen with escape glyph: */ 7238 /* Draw non-ASCII space/hyphen with escape glyph: */
@@ -7860,7 +7860,7 @@ next_element_from_display_vector (struct it *it)
7860 { 7860 {
7861 int lface_id = GLYPH_CODE_FACE (gc); 7861 int lface_id = GLYPH_CODE_FACE (gc);
7862 if (lface_id > 0) 7862 if (lface_id > 0)
7863 it->face_id = merge_faces (it->f, Qt, lface_id, 7863 it->face_id = merge_faces (it->w, Qt, lface_id,
7864 it->saved_face_id); 7864 it->saved_face_id);
7865 } 7865 }
7866 7866
@@ -7889,7 +7889,7 @@ next_element_from_display_vector (struct it *it)
7889 GLYPH_CODE_FACE (it->dpvec[it->current.dpvec_index + 1]); 7889 GLYPH_CODE_FACE (it->dpvec[it->current.dpvec_index + 1]);
7890 7890
7891 if (lface_id > 0) 7891 if (lface_id > 0)
7892 next_face_id = merge_faces (it->f, Qt, lface_id, 7892 next_face_id = merge_faces (it->w, Qt, lface_id,
7893 it->saved_face_id); 7893 it->saved_face_id);
7894 } 7894 }
7895 } 7895 }
@@ -20084,7 +20084,7 @@ append_space_for_newline (struct it *it, bool default_face_p)
20084 /* If the default face was remapped, be sure to use the 20084 /* If the default face was remapped, be sure to use the
20085 remapped face for the appended newline. */ 20085 remapped face for the appended newline. */
20086 if (default_face_p) 20086 if (default_face_p)
20087 it->face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID); 20087 it->face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
20088 else if (it->face_before_selective_p) 20088 else if (it->face_before_selective_p)
20089 it->face_id = it->saved_face_id; 20089 it->face_id = it->saved_face_id;
20090 face = FACE_FROM_ID (it->f, it->face_id); 20090 face = FACE_FROM_ID (it->f, it->face_id);
@@ -20231,8 +20231,9 @@ extend_face_to_end_of_line (struct it *it)
20231 return; 20231 return;
20232 20232
20233 /* The default face, possibly remapped. */ 20233 /* The default face, possibly remapped. */
20234 default_face = FACE_FROM_ID_OR_NULL (f, 20234 default_face = FACE_FROM_ID_OR_NULL (
20235 lookup_basic_face (f, DEFAULT_FACE_ID)); 20235 f,
20236 lookup_basic_face (it->w, f, DEFAULT_FACE_ID));
20236 20237
20237 /* Face extension extends the background and box of IT->face_id 20238 /* Face extension extends the background and box of IT->face_id
20238 to the end of the line. If the background equals the background 20239 to the end of the line. If the background equals the background
@@ -20486,11 +20487,12 @@ trailing_whitespace_p (ptrdiff_t charpos)
20486} 20487}
20487 20488
20488 20489
20489/* Highlight trailing whitespace, if any, in ROW. */ 20490/* Highlight trailing whitespace, if any, in row at IT. */
20490 20491
20491static void 20492static void
20492highlight_trailing_whitespace (struct frame *f, struct glyph_row *row) 20493highlight_trailing_whitespace (struct it *it)
20493{ 20494{
20495 struct glyph_row *row = it->glyph_row;
20494 int used = row->used[TEXT_AREA]; 20496 int used = row->used[TEXT_AREA];
20495 20497
20496 if (used) 20498 if (used)
@@ -20535,7 +20537,7 @@ highlight_trailing_whitespace (struct frame *f, struct glyph_row *row)
20535 && glyph->u.ch == ' ')) 20537 && glyph->u.ch == ' '))
20536 && trailing_whitespace_p (glyph->charpos)) 20538 && trailing_whitespace_p (glyph->charpos))
20537 { 20539 {
20538 int face_id = lookup_named_face (f, Qtrailing_whitespace, false); 20540 int face_id = lookup_named_face (it->w, it->f, Qtrailing_whitespace, false);
20539 if (face_id < 0) 20541 if (face_id < 0)
20540 return; 20542 return;
20541 20543
@@ -21107,9 +21109,9 @@ maybe_produce_line_number (struct it *it)
21107 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1]; 21109 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
21108 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false; 21110 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
21109 ptrdiff_t lnum_offset = -1; /* to produce 1-based line numbers */ 21111 ptrdiff_t lnum_offset = -1; /* to produce 1-based line numbers */
21110 int lnum_face_id = merge_faces (it->f, Qline_number, 0, DEFAULT_FACE_ID); 21112 int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID);
21111 int current_lnum_face_id 21113 int current_lnum_face_id
21112 = merge_faces (it->f, Qline_number_current_line, 0, DEFAULT_FACE_ID); 21114 = merge_faces (it->w, Qline_number_current_line, 0, DEFAULT_FACE_ID);
21113 /* Compute point's line number if needed. */ 21115 /* Compute point's line number if needed. */
21114 if ((EQ (Vdisplay_line_numbers, Qrelative) 21116 if ((EQ (Vdisplay_line_numbers, Qrelative)
21115 || EQ (Vdisplay_line_numbers, Qvisual) 21117 || EQ (Vdisplay_line_numbers, Qvisual)
@@ -21559,7 +21561,8 @@ display_line (struct it *it, int cursor_vpos)
21559 portions of the screen will clear with the default face's 21561 portions of the screen will clear with the default face's
21560 background color. */ 21562 background color. */
21561 if (row->reversed_p 21563 if (row->reversed_p
21562 || lookup_basic_face (it->f, DEFAULT_FACE_ID) != DEFAULT_FACE_ID) 21564 || lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
21565 != DEFAULT_FACE_ID)
21563 extend_face_to_end_of_line (it); 21566 extend_face_to_end_of_line (it);
21564 break; 21567 break;
21565 } 21568 }
@@ -22192,7 +22195,7 @@ display_line (struct it *it, int cursor_vpos)
22192 22195
22193 /* Highlight trailing whitespace. */ 22196 /* Highlight trailing whitespace. */
22194 if (!NILP (Vshow_trailing_whitespace)) 22197 if (!NILP (Vshow_trailing_whitespace))
22195 highlight_trailing_whitespace (it->f, it->glyph_row); 22198 highlight_trailing_whitespace (it);
22196 22199
22197 /* Compute pixel dimensions of this line. */ 22200 /* Compute pixel dimensions of this line. */
22198 compute_line_metrics (it); 22201 compute_line_metrics (it);
@@ -27862,7 +27865,7 @@ calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
27862 int face_id; 27865 int face_id;
27863 struct face *face; 27866 struct face *face;
27864 27867
27865 face_id = lookup_named_face (it->f, face_name, false); 27868 face_id = lookup_named_face (it->w, it->f, face_name, false);
27866 face = FACE_FROM_ID_OR_NULL (it->f, face_id); 27869 face = FACE_FROM_ID_OR_NULL (it->f, face_id);
27867 if (face == NULL || ((font = face->font) == NULL)) 27870 if (face == NULL || ((font = face->font) == NULL))
27868 return make_number (-1); 27871 return make_number (-1);
diff --git a/src/xfaces.c b/src/xfaces.c
index a9c2f37e9f2..1654f8610e8 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -350,7 +350,8 @@ static bool realize_default_face (struct frame *);
350static void realize_named_face (struct frame *, Lisp_Object, int); 350static void realize_named_face (struct frame *, Lisp_Object, int);
351static struct face_cache *make_face_cache (struct frame *); 351static struct face_cache *make_face_cache (struct frame *);
352static void free_face_cache (struct face_cache *); 352static void free_face_cache (struct face_cache *);
353static bool merge_face_ref (struct frame *, Lisp_Object, Lisp_Object *, 353static bool merge_face_ref (struct window *w,
354 struct frame *, Lisp_Object, Lisp_Object *,
354 bool, struct named_merge_point *); 355 bool, struct named_merge_point *);
355static int color_distance (XColor *x, XColor *y); 356static int color_distance (XColor *x, XColor *y);
356 357
@@ -1551,7 +1552,7 @@ the WIDTH times as wide as FACE on FRAME. */)
1551 { 1552 {
1552 /* This is of limited utility since it works with character 1553 /* This is of limited utility since it works with character
1553 widths. Keep it for compatibility. --gerd. */ 1554 widths. Keep it for compatibility. --gerd. */
1554 int face_id = lookup_named_face (f, face, false); 1555 int face_id = lookup_named_face (NULL, f, face, false);
1555 struct face *width_face = FACE_FROM_ID_OR_NULL (f, face_id); 1556 struct face *width_face = FACE_FROM_ID_OR_NULL (f, face_id);
1556 1557
1557 if (width_face && width_face->font) 1558 if (width_face && width_face->font)
@@ -1907,19 +1908,22 @@ get_lface_attributes_no_remap (struct frame *f, Lisp_Object face_name,
1907 return !NILP (lface); 1908 return !NILP (lface);
1908} 1909}
1909 1910
1910/* Get face attributes of face FACE_NAME from frame-local faces on frame 1911/* Get face attributes of face FACE_NAME from frame-local faces on
1911 F. Store the resulting attributes in ATTRS which must point to a 1912 frame F. Store the resulting attributes in ATTRS which must point
1912 vector of Lisp_Objects of size LFACE_VECTOR_SIZE. If FACE_NAME is an 1913 to a vector of Lisp_Objects of size LFACE_VECTOR_SIZE.
1913 alias for another face, use that face's definition. 1914 If FACE_NAME is an alias for another face, use that face's
1914 If SIGNAL_P, signal an error if FACE_NAME does not name a face. 1915 definition. If SIGNAL_P, signal an error if FACE_NAME does not
1915 Otherwise, return true iff FACE_NAME is a face. */ 1916 name a face. Otherwise, return true iff FACE_NAME is a face. If W
1916 1917 is non-NULL, also consider remappings attached to the window.
1918 */
1917static bool 1919static bool
1918get_lface_attributes (struct frame *f, Lisp_Object face_name, 1920get_lface_attributes (struct window *w,
1921 struct frame *f, Lisp_Object face_name,
1919 Lisp_Object attrs[LFACE_VECTOR_SIZE], bool signal_p, 1922 Lisp_Object attrs[LFACE_VECTOR_SIZE], bool signal_p,
1920 struct named_merge_point *named_merge_points) 1923 struct named_merge_point *named_merge_points)
1921{ 1924{
1922 Lisp_Object face_remapping; 1925 Lisp_Object face_remapping;
1926 eassert (w == NULL || WINDOW_XFRAME (w) == f);
1923 1927
1924 face_name = resolve_face_name (face_name, signal_p); 1928 face_name = resolve_face_name (face_name, signal_p);
1925 1929
@@ -1939,7 +1943,7 @@ get_lface_attributes (struct frame *f, Lisp_Object face_name,
1939 for (i = 1; i < LFACE_VECTOR_SIZE; ++i) 1943 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
1940 attrs[i] = Qunspecified; 1944 attrs[i] = Qunspecified;
1941 1945
1942 return merge_face_ref (f, XCDR (face_remapping), attrs, 1946 return merge_face_ref (w, f, XCDR (face_remapping), attrs,
1943 signal_p, named_merge_points); 1947 signal_p, named_merge_points);
1944 } 1948 }
1945 } 1949 }
@@ -2072,15 +2076,16 @@ merge_face_heights (Lisp_Object from, Lisp_Object to, Lisp_Object invalid)
2072 2076
2073/* Merge two Lisp face attribute vectors on frame F, FROM and TO, and 2077/* Merge two Lisp face attribute vectors on frame F, FROM and TO, and
2074 store the resulting attributes in TO, which must be already be 2078 store the resulting attributes in TO, which must be already be
2075 completely specified and contain only absolute attributes. Every 2079 completely specified and contain only absolute attributes.
2076 specified attribute of FROM overrides the corresponding attribute of 2080 Every specified attribute of FROM overrides the corresponding
2077 TO; relative attributes in FROM are merged with the absolute value in 2081 attribute of TO; relative attributes in FROM are merged with the
2078 TO and replace it. NAMED_MERGE_POINTS is used internally to detect 2082 absolute value in TO and replace it. NAMED_MERGE_POINTS is used
2079 loops in face inheritance/remapping; it should be 0 when called from 2083 internally to detect loops in face inheritance/remapping; it should
2080 other places. */ 2084 be 0 when called from other places. If window W is non-NULL, use W
2081 2085 to interpret face specifications. */
2082static void 2086static void
2083merge_face_vectors (struct frame *f, Lisp_Object *from, Lisp_Object *to, 2087merge_face_vectors (struct window *w,
2088 struct frame *f, Lisp_Object *from, Lisp_Object *to,
2084 struct named_merge_point *named_merge_points) 2089 struct named_merge_point *named_merge_points)
2085{ 2090{
2086 int i; 2091 int i;
@@ -2093,7 +2098,8 @@ merge_face_vectors (struct frame *f, Lisp_Object *from, Lisp_Object *to,
2093 other code uses `unspecified' as a generic value for face attributes. */ 2098 other code uses `unspecified' as a generic value for face attributes. */
2094 if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX]) 2099 if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX])
2095 && !NILP (from[LFACE_INHERIT_INDEX])) 2100 && !NILP (from[LFACE_INHERIT_INDEX]))
2096 merge_face_ref (f, from[LFACE_INHERIT_INDEX], to, false, named_merge_points); 2101 merge_face_ref (w, f, from[LFACE_INHERIT_INDEX],
2102 to, false, named_merge_points);
2097 2103
2098 if (FONT_SPEC_P (from[LFACE_FONT_INDEX])) 2104 if (FONT_SPEC_P (from[LFACE_FONT_INDEX]))
2099 { 2105 {
@@ -2153,10 +2159,12 @@ merge_face_vectors (struct frame *f, Lisp_Object *from, Lisp_Object *to,
2153/* Merge the named face FACE_NAME on frame F, into the vector of face 2159/* Merge the named face FACE_NAME on frame F, into the vector of face
2154 attributes TO. Use NAMED_MERGE_POINTS to detect loops in face 2160 attributes TO. Use NAMED_MERGE_POINTS to detect loops in face
2155 inheritance. Return true if FACE_NAME is a valid face name and 2161 inheritance. Return true if FACE_NAME is a valid face name and
2156 merging succeeded. */ 2162 merging succeeded. Window W, if non-NULL, is used to filter face
2163 specifications. */
2157 2164
2158static bool 2165static bool
2159merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to, 2166merge_named_face (struct window *w,
2167 struct frame *f, Lisp_Object face_name, Lisp_Object *to,
2160 struct named_merge_point *named_merge_points) 2168 struct named_merge_point *named_merge_points)
2161{ 2169{
2162 struct named_merge_point named_merge_point; 2170 struct named_merge_point named_merge_point;
@@ -2166,11 +2174,11 @@ merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to,
2166 &named_merge_points)) 2174 &named_merge_points))
2167 { 2175 {
2168 Lisp_Object from[LFACE_VECTOR_SIZE]; 2176 Lisp_Object from[LFACE_VECTOR_SIZE];
2169 bool ok = get_lface_attributes (f, face_name, from, false, 2177 bool ok = get_lface_attributes (w, f, face_name, from, false,
2170 named_merge_points); 2178 named_merge_points);
2171 2179
2172 if (ok) 2180 if (ok)
2173 merge_face_vectors (f, from, to, named_merge_points); 2181 merge_face_vectors (w, f, from, to, named_merge_points);
2174 2182
2175 return ok; 2183 return ok;
2176 } 2184 }
@@ -2178,6 +2186,111 @@ merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to,
2178 return false; 2186 return false;
2179} 2187}
2180 2188
2189/* Determine whether the face filter FILTER evaluated in window W
2190 matches. W can be NULL if the window context is unknown.
2191
2192 A face filter is either nil, which always matches, or a list
2193 (:window PARAMETER VALUE), which matches if the current window has
2194 a PARAMETER EQ to VALUE.
2195
2196 If the filter is invalid, set *OK to false and, if ERR_MSGS is
2197 true, log an error message. */
2198static bool
2199evaluate_face_filter (Lisp_Object filter, struct window *w,
2200 bool *ok, bool err_msgs)
2201{
2202 Lisp_Object orig_filter = filter;
2203
2204 {
2205 if (NILP (filter))
2206 return true;
2207
2208 if (face_filters_always_match)
2209 return true;
2210
2211 if (!CONSP (filter))
2212 goto err;
2213
2214 if (!EQ (XCAR (filter), Qwindow_kw))
2215 goto err;
2216 filter = XCDR (filter);
2217
2218 Lisp_Object parameter = XCAR (filter);
2219 filter = XCDR (filter);
2220 if (!CONSP (filter))
2221 goto err;
2222
2223 Lisp_Object value = XCAR (filter);
2224 filter = XCDR (filter);
2225 if (!NILP (filter))
2226 goto err;
2227
2228 bool match = false;
2229 if (w) {
2230 Lisp_Object found = assq_no_quit (parameter, w->window_parameters);
2231 if (!NILP (found) && EQ (XCDR (found), value))
2232 match = true;
2233 }
2234
2235 return match;
2236 }
2237
2238 err:
2239 if (err_msgs)
2240 add_to_log ("Invalid face filter %S", orig_filter);
2241 *ok = false;
2242 return false;
2243}
2244
2245/* Determine whether FACE_REF is a "filter" face specification (case
2246 #4 in merge_face_ref). If it is, evaluate the filter, and if the
2247 filter matches, return the filtered expression. Otherwise, return
2248 the original expression.
2249
2250 On error, set *OK to false, having logged an error message if
2251 ERR_MSGS is true, with return value unspecified.
2252
2253 W is either NULL or a window used to evaluate filters. If W is
2254 null, no window-based face specification filter matches.
2255*/
2256static Lisp_Object
2257filter_face_ref (Lisp_Object face_ref,
2258 struct window *w,
2259 bool *ok,
2260 bool err_msgs)
2261{
2262 Lisp_Object orig_face_ref = face_ref;
2263 if (!CONSP (face_ref))
2264 return face_ref;
2265
2266 {
2267 if (!EQ (XCAR (face_ref), Qfiltered_kw))
2268 return face_ref;
2269 face_ref = XCDR (face_ref);
2270
2271 if (!CONSP (face_ref))
2272 goto err;
2273 Lisp_Object filter = XCAR (face_ref);
2274 face_ref = XCDR (face_ref);
2275
2276 if (!CONSP (face_ref))
2277 goto err;
2278 Lisp_Object filtered_face_ref = XCAR (face_ref);
2279 face_ref = XCDR (face_ref);
2280
2281 if (!NILP (face_ref))
2282 goto err;
2283
2284 return evaluate_face_filter (filter, w, ok, err_msgs)
2285 ? filtered_face_ref : Qnil;
2286 }
2287
2288 err:
2289 if (err_msgs)
2290 add_to_log ("Invalid face ref %S", orig_face_ref);
2291 *ok = false;
2292 return Qnil;
2293}
2181 2294
2182/* Merge face attributes from the lisp `face reference' FACE_REF on 2295/* Merge face attributes from the lisp `face reference' FACE_REF on
2183 frame F into the face attribute vector TO. If ERR_MSGS, 2296 frame F into the face attribute vector TO. If ERR_MSGS,
@@ -2199,21 +2312,44 @@ merge_named_face (struct frame *f, Lisp_Object face_name, Lisp_Object *to,
2199 (BACKGROUND-COLOR . COLOR) where COLOR is a color name. This is 2312 (BACKGROUND-COLOR . COLOR) where COLOR is a color name. This is
2200 for compatibility with 20.2. 2313 for compatibility with 20.2.
2201 2314
2315 4. Conses of the form
2316 (:filter (:window PARAMETER VALUE) FACE-SPECIFICATION),
2317 which applies FACE-SPECIFICATION only if the
2318 given face attributes are being evaluated in the context of a
2319 window with a parameter named PARAMETER being EQ VALUE.
2320
2321 5. nil, which means to merge nothing.
2322
2202 Face specifications earlier in lists take precedence over later 2323 Face specifications earlier in lists take precedence over later
2203 specifications. */ 2324 specifications. */
2204 2325
2205static bool 2326static bool
2206merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to, 2327merge_face_ref (struct window *w,
2328 struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
2207 bool err_msgs, struct named_merge_point *named_merge_points) 2329 bool err_msgs, struct named_merge_point *named_merge_points)
2208{ 2330{
2209 bool ok = true; /* Succeed without an error? */ 2331 bool ok = true; /* Succeed without an error? */
2332 Lisp_Object filtered_face_ref;
2333
2334 filtered_face_ref = face_ref;
2335 do
2336 {
2337 face_ref = filtered_face_ref;
2338 filtered_face_ref = filter_face_ref (face_ref, w, &ok, err_msgs);
2339 } while (ok && !EQ (face_ref, filtered_face_ref));
2340
2341 if (!ok)
2342 return false;
2343
2344 if (NILP (face_ref))
2345 return true;
2210 2346
2211 if (CONSP (face_ref)) 2347 if (CONSP (face_ref))
2212 { 2348 {
2213 Lisp_Object first = XCAR (face_ref); 2349 Lisp_Object first = XCAR (face_ref);
2214 2350
2215 if (EQ (first, Qforeground_color) 2351 if (EQ (first, Qforeground_color)
2216 || EQ (first, Qbackground_color)) 2352 || EQ (first, Qbackground_color))
2217 { 2353 {
2218 /* One of (FOREGROUND-COLOR . COLOR) or (BACKGROUND-COLOR 2354 /* One of (FOREGROUND-COLOR . COLOR) or (BACKGROUND-COLOR
2219 . COLOR). COLOR must be a string. */ 2355 . COLOR). COLOR must be a string. */
@@ -2400,7 +2536,7 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
2400 { 2536 {
2401 /* This is not really very useful; it's just like a 2537 /* This is not really very useful; it's just like a
2402 normal face reference. */ 2538 normal face reference. */
2403 if (! merge_face_ref (f, value, to, 2539 if (! merge_face_ref (w, f, value, to,
2404 err_msgs, named_merge_points)) 2540 err_msgs, named_merge_points))
2405 err = true; 2541 err = true;
2406 } 2542 }
@@ -2424,16 +2560,16 @@ merge_face_ref (struct frame *f, Lisp_Object face_ref, Lisp_Object *to,
2424 Lisp_Object next = XCDR (face_ref); 2560 Lisp_Object next = XCDR (face_ref);
2425 2561
2426 if (! NILP (next)) 2562 if (! NILP (next))
2427 ok = merge_face_ref (f, next, to, err_msgs, named_merge_points); 2563 ok = merge_face_ref (w, f, next, to, err_msgs, named_merge_points);
2428 2564
2429 if (! merge_face_ref (f, first, to, err_msgs, named_merge_points)) 2565 if (! merge_face_ref (w, f, first, to, err_msgs, named_merge_points))
2430 ok = false; 2566 ok = false;
2431 } 2567 }
2432 } 2568 }
2433 else 2569 else
2434 { 2570 {
2435 /* FACE_REF ought to be a face name. */ 2571 /* FACE_REF ought to be a face name. */
2436 ok = merge_named_face (f, face_ref, to, named_merge_points); 2572 ok = merge_named_face (w, f, face_ref, to, named_merge_points);
2437 if (!ok && err_msgs) 2573 if (!ok && err_msgs)
2438 add_to_log ("Invalid face reference: %s", face_ref); 2574 add_to_log ("Invalid face reference: %s", face_ref);
2439 } 2575 }
@@ -3701,7 +3837,7 @@ Default face attributes override any local face attributes. */)
3701 /* Ensure that the face vector is fully specified by merging 3837 /* Ensure that the face vector is fully specified by merging
3702 the previously-cached vector. */ 3838 the previously-cached vector. */
3703 memcpy (attrs, oldface->lface, sizeof attrs); 3839 memcpy (attrs, oldface->lface, sizeof attrs);
3704 merge_face_vectors (f, lvec, attrs, 0); 3840 merge_face_vectors (NULL, f, lvec, attrs, 0);
3705 vcopy (local_lface, 0, attrs, LFACE_VECTOR_SIZE); 3841 vcopy (local_lface, 0, attrs, LFACE_VECTOR_SIZE);
3706 newface = realize_face (c, lvec, DEFAULT_FACE_ID); 3842 newface = realize_face (c, lvec, DEFAULT_FACE_ID);
3707 3843
@@ -3774,7 +3910,7 @@ return the font name used for CHARACTER. */)
3774 else 3910 else
3775 { 3911 {
3776 struct frame *f = decode_live_frame (frame); 3912 struct frame *f = decode_live_frame (frame);
3777 int face_id = lookup_named_face (f, face, true); 3913 int face_id = lookup_named_face (NULL, f, face, true);
3778 struct face *fface = FACE_FROM_ID_OR_NULL (f, face_id); 3914 struct face *fface = FACE_FROM_ID_OR_NULL (f, face_id);
3779 3915
3780 if (! fface) 3916 if (! fface)
@@ -4432,10 +4568,12 @@ face_for_font (struct frame *f, Lisp_Object font_object, struct face *base_face)
4432/* Return the face id of the realized face for named face SYMBOL on 4568/* Return the face id of the realized face for named face SYMBOL on
4433 frame F suitable for displaying ASCII characters. Value is -1 if 4569 frame F suitable for displaying ASCII characters. Value is -1 if
4434 the face couldn't be determined, which might happen if the default 4570 the face couldn't be determined, which might happen if the default
4435 face isn't realized and cannot be realized. */ 4571 face isn't realized and cannot be realized. If window W is given,
4436 4572 consider face remappings specified for W or for W's buffer. If W is
4573 NULL, consider only frame-level face configuration. */
4437int 4574int
4438lookup_named_face (struct frame *f, Lisp_Object symbol, bool signal_p) 4575lookup_named_face (struct window *w, struct frame *f,
4576 Lisp_Object symbol, bool signal_p)
4439{ 4577{
4440 Lisp_Object attrs[LFACE_VECTOR_SIZE]; 4578 Lisp_Object attrs[LFACE_VECTOR_SIZE];
4441 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE]; 4579 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
@@ -4448,11 +4586,11 @@ lookup_named_face (struct frame *f, Lisp_Object symbol, bool signal_p)
4448 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID); 4586 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
4449 } 4587 }
4450 4588
4451 if (! get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0)) 4589 if (! get_lface_attributes (w, f, symbol, symbol_attrs, signal_p, 0))
4452 return -1; 4590 return -1;
4453 4591
4454 memcpy (attrs, default_face->lface, sizeof attrs); 4592 memcpy (attrs, default_face->lface, sizeof attrs);
4455 merge_face_vectors (f, symbol_attrs, attrs, 0); 4593 merge_face_vectors (w, f, symbol_attrs, attrs, 0);
4456 4594
4457 return lookup_face (f, attrs); 4595 return lookup_face (f, attrs);
4458} 4596}
@@ -4462,10 +4600,10 @@ lookup_named_face (struct frame *f, Lisp_Object symbol, bool signal_p)
4462 is FACE_ID. The return value will usually simply be FACE_ID, unless that 4600 is FACE_ID. The return value will usually simply be FACE_ID, unless that
4463 basic face has bee remapped via Vface_remapping_alist. This function is 4601 basic face has bee remapped via Vface_remapping_alist. This function is
4464 conservative: if something goes wrong, it will simply return FACE_ID 4602 conservative: if something goes wrong, it will simply return FACE_ID
4465 rather than signal an error. */ 4603 rather than signal an error. Window W, if non-NULL, is used to filter
4466 4604 face specifications for remapping. */
4467int 4605int
4468lookup_basic_face (struct frame *f, int face_id) 4606lookup_basic_face (struct window *w, struct frame *f, int face_id)
4469{ 4607{
4470 Lisp_Object name, mapping; 4608 Lisp_Object name, mapping;
4471 int remapped_face_id; 4609 int remapped_face_id;
@@ -4505,7 +4643,7 @@ lookup_basic_face (struct frame *f, int face_id)
4505 4643
4506 /* If there is a remapping entry, lookup the face using NAME, which will 4644 /* If there is a remapping entry, lookup the face using NAME, which will
4507 handle the remapping too. */ 4645 handle the remapping too. */
4508 remapped_face_id = lookup_named_face (f, name, false); 4646 remapped_face_id = lookup_named_face (w, f, name, false);
4509 if (remapped_face_id < 0) 4647 if (remapped_face_id < 0)
4510 return face_id; /* Give up. */ 4648 return face_id; /* Give up. */
4511 4649
@@ -4603,22 +4741,23 @@ face_with_height (struct frame *f, int face_id, int height)
4603 attributes of the face FACE_ID for attributes that aren't 4741 attributes of the face FACE_ID for attributes that aren't
4604 completely specified by SYMBOL. This is like lookup_named_face, 4742 completely specified by SYMBOL. This is like lookup_named_face,
4605 except that the default attributes come from FACE_ID, not from the 4743 except that the default attributes come from FACE_ID, not from the
4606 default face. FACE_ID is assumed to be already realized. */ 4744 default face. FACE_ID is assumed to be already realized.
4607 4745 Window W, if non-NULL, filters face specifications. */
4608int 4746int
4609lookup_derived_face (struct frame *f, Lisp_Object symbol, int face_id, 4747lookup_derived_face (struct window *w,
4748 struct frame *f, Lisp_Object symbol, int face_id,
4610 bool signal_p) 4749 bool signal_p)
4611{ 4750{
4612 Lisp_Object attrs[LFACE_VECTOR_SIZE]; 4751 Lisp_Object attrs[LFACE_VECTOR_SIZE];
4613 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE]; 4752 Lisp_Object symbol_attrs[LFACE_VECTOR_SIZE];
4614 struct face *default_face; 4753 struct face *default_face;
4615 4754
4616 if (!get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0)) 4755 if (!get_lface_attributes (w, f, symbol, symbol_attrs, signal_p, 0))
4617 return -1; 4756 return -1;
4618 4757
4619 default_face = FACE_FROM_ID (f, face_id); 4758 default_face = FACE_FROM_ID (f, face_id);
4620 memcpy (attrs, default_face->lface, sizeof attrs); 4759 memcpy (attrs, default_face->lface, sizeof attrs);
4621 merge_face_vectors (f, symbol_attrs, attrs, 0); 4760 merge_face_vectors (w, f, symbol_attrs, attrs, 0);
4622 return lookup_face (f, attrs); 4761 return lookup_face (f, attrs);
4623} 4762}
4624 4763
@@ -4630,7 +4769,8 @@ DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector,
4630 Lisp_Object lface; 4769 Lisp_Object lface;
4631 lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE), 4770 lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
4632 Qunspecified); 4771 Qunspecified);
4633 merge_face_ref (XFRAME (selected_frame), plist, XVECTOR (lface)->contents, 4772 merge_face_ref (NULL, XFRAME (selected_frame),
4773 plist, XVECTOR (lface)->contents,
4634 true, 0); 4774 true, 0);
4635 return lface; 4775 return lface;
4636} 4776}
@@ -4714,7 +4854,7 @@ x_supports_face_attributes_p (struct frame *f,
4714 4854
4715 memcpy (merged_attrs, def_attrs, sizeof merged_attrs); 4855 memcpy (merged_attrs, def_attrs, sizeof merged_attrs);
4716 4856
4717 merge_face_vectors (f, attrs, merged_attrs, 0); 4857 merge_face_vectors (NULL, f, attrs, merged_attrs, 0);
4718 4858
4719 face_id = lookup_face (f, merged_attrs); 4859 face_id = lookup_face (f, merged_attrs);
4720 face = FACE_FROM_ID_OR_NULL (f, face_id); 4860 face = FACE_FROM_ID_OR_NULL (f, face_id);
@@ -4985,7 +5125,7 @@ face for italic. */)
4985 5125
4986 for (i = 0; i < LFACE_VECTOR_SIZE; i++) 5126 for (i = 0; i < LFACE_VECTOR_SIZE; i++)
4987 attrs[i] = Qunspecified; 5127 attrs[i] = Qunspecified;
4988 merge_face_ref (f, attributes, attrs, true, 0); 5128 merge_face_ref (NULL, f, attributes, attrs, true, 0);
4989 5129
4990 def_face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID); 5130 def_face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
4991 if (def_face == NULL) 5131 if (def_face == NULL)
@@ -5354,7 +5494,7 @@ realize_named_face (struct frame *f, Lisp_Object symbol, int id)
5354 5494
5355 /* Merge SYMBOL's face with the default face. */ 5495 /* Merge SYMBOL's face with the default face. */
5356 get_lface_attributes_no_remap (f, symbol, symbol_attrs, true); 5496 get_lface_attributes_no_remap (f, symbol, symbol_attrs, true);
5357 merge_face_vectors (f, symbol_attrs, attrs, 0); 5497 merge_face_vectors (NULL, f, symbol_attrs, attrs, 0);
5358 5498
5359 /* Realize the face. */ 5499 /* Realize the face. */
5360 realize_face (c, attrs, id); 5500 realize_face (c, attrs, id);
@@ -5869,7 +6009,7 @@ compute_char_face (struct frame *f, int ch, Lisp_Object prop)
5869 Lisp_Object attrs[LFACE_VECTOR_SIZE]; 6009 Lisp_Object attrs[LFACE_VECTOR_SIZE];
5870 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID); 6010 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
5871 memcpy (attrs, default_face->lface, sizeof attrs); 6011 memcpy (attrs, default_face->lface, sizeof attrs);
5872 merge_face_ref (f, prop, attrs, true, 0); 6012 merge_face_ref (NULL, f, prop, attrs, true, 0);
5873 face_id = lookup_face (f, attrs); 6013 face_id = lookup_face (f, attrs);
5874 } 6014 }
5875 6015
@@ -5948,7 +6088,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
5948 else if (NILP (Vface_remapping_alist)) 6088 else if (NILP (Vface_remapping_alist))
5949 face_id = DEFAULT_FACE_ID; 6089 face_id = DEFAULT_FACE_ID;
5950 else 6090 else
5951 face_id = lookup_basic_face (f, DEFAULT_FACE_ID); 6091 face_id = lookup_basic_face (w, f, DEFAULT_FACE_ID);
5952 6092
5953 default_face = FACE_FROM_ID (f, face_id); 6093 default_face = FACE_FROM_ID (f, face_id);
5954 } 6094 }
@@ -5966,7 +6106,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
5966 6106
5967 /* Merge in attributes specified via text properties. */ 6107 /* Merge in attributes specified via text properties. */
5968 if (!NILP (prop)) 6108 if (!NILP (prop))
5969 merge_face_ref (f, prop, attrs, true, 0); 6109 merge_face_ref (w, f, prop, attrs, true, 0);
5970 6110
5971 /* Now merge the overlay data. */ 6111 /* Now merge the overlay data. */
5972 noverlays = sort_overlays (overlay_vec, noverlays, w); 6112 noverlays = sort_overlays (overlay_vec, noverlays, w);
@@ -5986,7 +6126,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
5986 so discard the mouse-face text property, if any, and 6126 so discard the mouse-face text property, if any, and
5987 use the overlay property instead. */ 6127 use the overlay property instead. */
5988 memcpy (attrs, default_face->lface, sizeof attrs); 6128 memcpy (attrs, default_face->lface, sizeof attrs);
5989 merge_face_ref (f, prop, attrs, true, 0); 6129 merge_face_ref (w, f, prop, attrs, true, 0);
5990 } 6130 }
5991 6131
5992 oend = OVERLAY_END (overlay_vec[i]); 6132 oend = OVERLAY_END (overlay_vec[i]);
@@ -6004,7 +6144,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
6004 6144
6005 prop = Foverlay_get (overlay_vec[i], propname); 6145 prop = Foverlay_get (overlay_vec[i], propname);
6006 if (!NILP (prop)) 6146 if (!NILP (prop))
6007 merge_face_ref (f, prop, attrs, true, 0); 6147 merge_face_ref (w, f, prop, attrs, true, 0);
6008 6148
6009 oend = OVERLAY_END (overlay_vec[i]); 6149 oend = OVERLAY_END (overlay_vec[i]);
6010 oendpos = OVERLAY_POSITION (oend); 6150 oendpos = OVERLAY_POSITION (oend);
@@ -6065,12 +6205,12 @@ face_for_overlay_string (struct window *w, ptrdiff_t pos,
6065 return DEFAULT_FACE_ID; 6205 return DEFAULT_FACE_ID;
6066 6206
6067 /* Begin with attributes from the default face. */ 6207 /* Begin with attributes from the default face. */
6068 default_face = FACE_FROM_ID (f, lookup_basic_face (f, DEFAULT_FACE_ID)); 6208 default_face = FACE_FROM_ID (f, lookup_basic_face (w, f, DEFAULT_FACE_ID));
6069 memcpy (attrs, default_face->lface, sizeof attrs); 6209 memcpy (attrs, default_face->lface, sizeof attrs);
6070 6210
6071 /* Merge in attributes specified via text properties. */ 6211 /* Merge in attributes specified via text properties. */
6072 if (!NILP (prop)) 6212 if (!NILP (prop))
6073 merge_face_ref (f, prop, attrs, true, 0); 6213 merge_face_ref (w, f, prop, attrs, true, 0);
6074 6214
6075 *endptr = endpos; 6215 *endptr = endpos;
6076 6216
@@ -6149,7 +6289,7 @@ face_at_string_position (struct window *w, Lisp_Object string,
6149 6289
6150 /* Merge in attributes specified via text properties. */ 6290 /* Merge in attributes specified via text properties. */
6151 if (!NILP (prop)) 6291 if (!NILP (prop))
6152 merge_face_ref (f, prop, attrs, true, 0); 6292 merge_face_ref (w, f, prop, attrs, true, 0);
6153 6293
6154 /* Look up a realized face with the given face attributes, 6294 /* Look up a realized face with the given face attributes,
6155 or realize a new one for ASCII characters. */ 6295 or realize a new one for ASCII characters. */
@@ -6159,7 +6299,7 @@ face_at_string_position (struct window *w, Lisp_Object string,
6159 6299
6160/* Merge a face into a realized face. 6300/* Merge a face into a realized face.
6161 6301
6162 F is frame where faces are (to be) realized. 6302 W is a window in the frame where faces are (to be) realized.
6163 6303
6164 FACE_NAME is named face to merge. 6304 FACE_NAME is named face to merge.
6165 6305
@@ -6173,9 +6313,10 @@ face_at_string_position (struct window *w, Lisp_Object string,
6173*/ 6313*/
6174 6314
6175int 6315int
6176merge_faces (struct frame *f, Lisp_Object face_name, int face_id, 6316merge_faces (struct window *w, Lisp_Object face_name, int face_id,
6177 int base_face_id) 6317 int base_face_id)
6178{ 6318{
6319 struct frame *f = WINDOW_XFRAME (w);
6179 Lisp_Object attrs[LFACE_VECTOR_SIZE]; 6320 Lisp_Object attrs[LFACE_VECTOR_SIZE];
6180 struct face *base_face; 6321 struct face *base_face;
6181 6322
@@ -6190,7 +6331,7 @@ merge_faces (struct frame *f, Lisp_Object face_name, int face_id,
6190 face_name = lface_id_to_name[face_id]; 6331 face_name = lface_id_to_name[face_id];
6191 /* When called during make-frame, lookup_derived_face may fail 6332 /* When called during make-frame, lookup_derived_face may fail
6192 if the faces are uninitialized. Don't signal an error. */ 6333 if the faces are uninitialized. Don't signal an error. */
6193 face_id = lookup_derived_face (f, face_name, base_face_id, 0); 6334 face_id = lookup_derived_face (w, f, face_name, base_face_id, 0);
6194 return (face_id >= 0 ? face_id : base_face_id); 6335 return (face_id >= 0 ? face_id : base_face_id);
6195 } 6336 }
6196 6337
@@ -6199,7 +6340,7 @@ merge_faces (struct frame *f, Lisp_Object face_name, int face_id,
6199 6340
6200 if (!NILP (face_name)) 6341 if (!NILP (face_name))
6201 { 6342 {
6202 if (!merge_named_face (f, face_name, attrs, 0)) 6343 if (!merge_named_face (w, f, face_name, attrs, 0))
6203 return base_face_id; 6344 return base_face_id;
6204 } 6345 }
6205 else 6346 else
@@ -6210,7 +6351,7 @@ merge_faces (struct frame *f, Lisp_Object face_name, int face_id,
6210 face = FACE_FROM_ID_OR_NULL (f, face_id); 6351 face = FACE_FROM_ID_OR_NULL (f, face_id);
6211 if (!face) 6352 if (!face)
6212 return base_face_id; 6353 return base_face_id;
6213 merge_face_vectors (f, face->lface, attrs, 0); 6354 merge_face_vectors (w, f, face->lface, attrs, 0);
6214 } 6355 }
6215 6356
6216 /* Look up a realized face with the given face attributes, 6357 /* Look up a realized face with the given face attributes,
@@ -6421,6 +6562,11 @@ syms_of_xfaces (void)
6421 DEFSYM (Qunspecified, "unspecified"); 6562 DEFSYM (Qunspecified, "unspecified");
6422 DEFSYM (QCignore_defface, ":ignore-defface"); 6563 DEFSYM (QCignore_defface, ":ignore-defface");
6423 6564
6565 /* Used for limiting character attributes to windows with specific
6566 characteristics. */
6567 DEFSYM (Qwindow_kw, ":window");
6568 DEFSYM (Qfiltered_kw, ":filtered");
6569
6424 /* The symbol `face-alias'. A symbol having that property is an 6570 /* The symbol `face-alias'. A symbol having that property is an
6425 alias for another face. Value of the property is the name of 6571 alias for another face. Value of the property is the name of
6426 the aliased face. */ 6572 the aliased face. */
@@ -6496,6 +6642,10 @@ syms_of_xfaces (void)
6496 defsubr (&Sdump_colors); 6642 defsubr (&Sdump_colors);
6497#endif 6643#endif
6498 6644
6645 DEFVAR_BOOL ("face-filters-always-match", face_filters_always_match,
6646 doc: /* Non-nil means that face filters are always deemed to
6647match. Use only when evaluating face attributes. */);
6648
6499 DEFVAR_LISP ("face-new-frame-defaults", Vface_new_frame_defaults, 6649 DEFVAR_LISP ("face-new-frame-defaults", Vface_new_frame_defaults,
6500 doc: /* List of global face definitions (for internal use only.) */); 6650 doc: /* List of global face definitions (for internal use only.) */);
6501 Vface_new_frame_defaults = Qnil; 6651 Vface_new_frame_defaults = Qnil;
@@ -6544,7 +6694,8 @@ REPLACEMENT is a face specification, i.e. one of the following:
6544 6694
6545 (1) a face name 6695 (1) a face name
6546 (2) a property list of attribute/value pairs, or 6696 (2) a property list of attribute/value pairs, or
6547 (3) a list in which each element has the form of (1) or (2). 6697 (3)
6698 (3) a list in which each element has one of the above forms.
6548 6699
6549List values for REPLACEMENT are merged to form the final face 6700List values for REPLACEMENT are merged to form the final face
6550specification, with earlier entries taking precedence, in the same way 6701specification, with earlier entries taking precedence, in the same way
@@ -6564,13 +6715,32 @@ causes EXTRA-FACE... or (FACE-ATTR VAL ...) to be _merged_ with the
6564existing definition of FACE. Note that this isn't necessary for the 6715existing definition of FACE. Note that this isn't necessary for the
6565default face, since every face inherits from the default face. 6716default face, since every face inherits from the default face.
6566 6717
6567If this variable is made buffer-local, the face remapping takes effect 6718An entry in the list can also be a filtered face expression of the
6568only in that buffer. For instance, the mode my-mode could define a 6719form:
6569face `my-mode-default', and then in the mode setup function, do: 6720
6721 (:filtered FILTER FACE-SPECIFICATION)
6722
6723This construct applies FACE-SPECIFICATION (which can have any of the
6724forms allowed for face specifications generally) only if FILTER
6725matches at the moment Emacs wants to draw text with the combined face.
6726
6727The only filters currently defined are NIL (which always matches) and
6728(:window PARAMETER VALUE), which matches only in the context of a
6729window with a parameter EQ-equal to VALUE.
6730
6731An entry in the face list can also be nil, which does nothing.
6732
6733If `face-remapping-alist' is made buffer-local, the face remapping
6734takes effect only in that buffer. For instance, the mode my-mode
6735could define a face `my-mode-default', and then in the mode setup
6736function, do:
6570 6737
6571 (set (make-local-variable \\='face-remapping-alist) 6738 (set (make-local-variable \\='face-remapping-alist)
6572 \\='((default my-mode-default)))). 6739 \\='((default my-mode-default)))).
6573 6740
6741You probably want to use the face-remap package included in Emacs
6742instead of manipulating face-remapping-alist directly.
6743
6574Because Emacs normally only redraws screen areas when the underlying 6744Because Emacs normally only redraws screen areas when the underlying
6575buffer contents change, you may need to call `redraw-display' after 6745buffer contents change, you may need to call `redraw-display' after
6576changing this variable for it to take effect. */); 6746changing this variable for it to take effect. */);