aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMiles Bader2008-06-01 05:04:24 +0000
committerMiles Bader2008-06-01 05:04:24 +0000
commitf2cec7a9907796d97bbe4f99ce00d1866b773dfb (patch)
tree24b0e99f39a2da47cc60d4f8c3848c01f7f0bf99 /src
parent70583cb56977d91d94bff77cb2fb93922c44876c (diff)
downloademacs-f2cec7a9907796d97bbe4f99ce00d1866b773dfb.tar.gz
emacs-f2cec7a9907796d97bbe4f99ce00d1866b773dfb.zip
Implement face-remapping-alist feature
Revision: emacs@sv.gnu.org/emacs--devo--0--patch-1195
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog34
-rw-r--r--src/dispextern.h3
-rw-r--r--src/fontset.c2
-rw-r--r--src/xdisp.c16
-rw-r--r--src/xfaces.c253
5 files changed, 268 insertions, 40 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index c8cbaf174dd..526d0c07bb0 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,37 @@
12008-06-01 Miles Bader <miles@gnu.org>
2
3 * xfaces.c (Vface_remapping_alist): New variable.
4 (syms_of_xfaces): Initialize it.
5 (enum named_merge_point_kind): New type.
6 (struct named_merge_point): Add `named_merge_point_kind' field.
7 (push_named_merge_point): Make cycle detection respect different
8 named-merge-point kinds.
9 (lface_from_face_name_no_resolve): Renamed from `lface_from_face_name'.
10 Remove face-name alias resolution.
11 (lface_from_face_name): New definition using
12 `lface_from_face_name_no_resolve'.
13 (get_lface_attributes_no_remap): Renamed from `get_lface_attributes'.
14 Call lface_from_face_name_no_resolve instead of lface_from_face_name.
15 (get_lface_attributes): New definition that layers face-remapping on
16 top of get_lface_attributes_no_remap. New arg `named_merge_points'.
17 (lookup_basic_face): New function.
18 (lookup_derived_face): Pass new last arg to `get_lface_attributes'.
19 (realize_named_face): Call `get_lface_attributes_no_remap' instead of
20 `get_lface_attributes'.
21 (face_at_buffer_position): Use `lookup_basic_face' to lookup
22 DEFAULT_FACE_ID if necessary. When optimizing the default-face case,
23 return default_face's face-id instead of the constant DEFAULT_FACE_ID.
24
25 * xdisp.c (init_iterator): Pass base_face_id through
26 `lookup_basic_face' when we actually use it as a face-id.
27 (handle_single_display_prop): Use `lookup_basic_face' to lookup
28 DEFAULT_FACE_ID.
29
30 * fontset.c (Finternal_char_font): Use `lookup_basic_face' to
31 lookup the initial face-id.
32
33 * dispextern.h (lookup_basic_face, Vface_remapping_alist): New decls.
34
12008-06-01 Juanma Barranquero <lekktu@gmail.com> 352008-06-01 Juanma Barranquero <lekktu@gmail.com>
2 36
3 * textprop.c (syms_of_textprop) <text-property-default-nonsticky>: 37 * textprop.c (syms_of_textprop) <text-property-default-nonsticky>:
diff --git a/src/dispextern.h b/src/dispextern.h
index 2101d70478f..4a4c731748b 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2852,6 +2852,7 @@ int xstrcasecmp P_ ((const unsigned char *, const unsigned char *));
2852int lookup_face P_ ((struct frame *, Lisp_Object *)); 2852int lookup_face P_ ((struct frame *, Lisp_Object *));
2853int lookup_non_ascii_face P_ ((struct frame *, int, struct face *)); 2853int lookup_non_ascii_face P_ ((struct frame *, int, struct face *));
2854int lookup_named_face P_ ((struct frame *, Lisp_Object, int)); 2854int lookup_named_face P_ ((struct frame *, Lisp_Object, int));
2855int lookup_basic_face P_ ((struct frame *, int));
2855int smaller_face P_ ((struct frame *, int, int)); 2856int smaller_face P_ ((struct frame *, int, int));
2856int face_with_height P_ ((struct frame *, int, int)); 2857int face_with_height P_ ((struct frame *, int, int));
2857int lookup_derived_face P_ ((struct frame *, Lisp_Object, int, int)); 2858int lookup_derived_face P_ ((struct frame *, Lisp_Object, int, int));
@@ -2880,6 +2881,8 @@ extern char unspecified_fg[], unspecified_bg[];
2880extern Lisp_Object split_font_name_into_vector P_ ((Lisp_Object)); 2881extern Lisp_Object split_font_name_into_vector P_ ((Lisp_Object));
2881extern Lisp_Object build_font_name_from_vector P_ ((Lisp_Object)); 2882extern Lisp_Object build_font_name_from_vector P_ ((Lisp_Object));
2882 2883
2884extern Lisp_Object Vface_remapping_alist;
2885
2883/* Defined in xfns.c */ 2886/* Defined in xfns.c */
2884 2887
2885#ifdef HAVE_X_WINDOWS 2888#ifdef HAVE_X_WINDOWS
diff --git a/src/fontset.c b/src/fontset.c
index d384dd41345..fbc6b866f31 100644
--- a/src/fontset.c
+++ b/src/fontset.c
@@ -1677,7 +1677,7 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0,
1677 CHECK_CHARACTER (ch); 1677 CHECK_CHARACTER (ch);
1678 c = XINT (ch); 1678 c = XINT (ch);
1679 f = XFRAME (selected_frame); 1679 f = XFRAME (selected_frame);
1680 face_id = DEFAULT_FACE_ID; 1680 face_id = lookup_basic_face (f, DEFAULT_FACE_ID);
1681 pos = -1; 1681 pos = -1;
1682 cs_id = -1; 1682 cs_id = -1;
1683 } 1683 }
diff --git a/src/xdisp.c b/src/xdisp.c
index 9b934c8803d..8d87123934b 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2491,6 +2491,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
2491 enum face_id base_face_id; 2491 enum face_id base_face_id;
2492{ 2492{
2493 int highlight_region_p; 2493 int highlight_region_p;
2494 enum face_id remapped_base_face_id = base_face_id;
2494 2495
2495 /* Some precondition checks. */ 2496 /* Some precondition checks. */
2496 xassert (w != NULL && it != NULL); 2497 xassert (w != NULL && it != NULL);
@@ -2507,6 +2508,10 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
2507 free_all_realized_faces (Qnil); 2508 free_all_realized_faces (Qnil);
2508 } 2509 }
2509 2510
2511 /* Perhaps remap BASE_FACE_ID to a user-specified alternative. */
2512 if (! NILP (Vface_remapping_alist))
2513 remapped_base_face_id = lookup_basic_face (XFRAME (w->frame), base_face_id);
2514
2510 /* Use one of the mode line rows of W's desired matrix if 2515 /* Use one of the mode line rows of W's desired matrix if
2511 appropriate. */ 2516 appropriate. */
2512 if (row == NULL) 2517 if (row == NULL)
@@ -2522,7 +2527,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
2522 bzero (it, sizeof *it); 2527 bzero (it, sizeof *it);
2523 it->current.overlay_string_index = -1; 2528 it->current.overlay_string_index = -1;
2524 it->current.dpvec_index = -1; 2529 it->current.dpvec_index = -1;
2525 it->base_face_id = base_face_id; 2530 it->base_face_id = remapped_base_face_id;
2526 it->string = Qnil; 2531 it->string = Qnil;
2527 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1; 2532 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
2528 2533
@@ -2707,11 +2712,11 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
2707 { 2712 {
2708 struct face *face; 2713 struct face *face;
2709 2714
2710 it->face_id = base_face_id; 2715 it->face_id = remapped_base_face_id;
2711 2716
2712 /* If we have a boxed mode line, make the first character appear 2717 /* If we have a boxed mode line, make the first character appear
2713 with a left box line. */ 2718 with a left box line. */
2714 face = FACE_FROM_ID (it->f, base_face_id); 2719 face = FACE_FROM_ID (it->f, remapped_base_face_id);
2715 if (face->box != FACE_NO_BOX) 2720 if (face->box != FACE_NO_BOX)
2716 it->start_of_box_run_p = 1; 2721 it->start_of_box_run_p = 1;
2717 } 2722 }
@@ -4077,7 +4082,8 @@ handle_single_display_spec (it, spec, object, overlay, position,
4077 /* Value is a multiple of the canonical char height. */ 4082 /* Value is a multiple of the canonical char height. */
4078 struct face *face; 4083 struct face *face;
4079 4084
4080 face = FACE_FROM_ID (it->f, DEFAULT_FACE_ID); 4085 face = FACE_FROM_ID (it->f,
4086 lookup_basic_face (it->f, DEFAULT_FACE_ID));
4081 new_height = (XFLOATINT (it->font_height) 4087 new_height = (XFLOATINT (it->font_height)
4082 * XINT (face->lface[LFACE_HEIGHT_INDEX])); 4088 * XINT (face->lface[LFACE_HEIGHT_INDEX]));
4083 } 4089 }
@@ -4187,7 +4193,7 @@ handle_single_display_spec (it, spec, object, overlay, position,
4187 || EQ (XCAR (spec), Qright_fringe)) 4193 || EQ (XCAR (spec), Qright_fringe))
4188 && CONSP (XCDR (spec))) 4194 && CONSP (XCDR (spec)))
4189 { 4195 {
4190 int face_id = DEFAULT_FACE_ID; 4196 int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);
4191 int fringe_bitmap; 4197 int fringe_bitmap;
4192 4198
4193 if (!FRAME_WINDOW_P (it->f)) 4199 if (!FRAME_WINDOW_P (it->f))
diff --git a/src/xfaces.c b/src/xfaces.c
index b5704ab6174..074b71b13c1 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -422,6 +422,23 @@ Lisp_Object Qbitmap_spec_p;
422 422
423Lisp_Object Vface_new_frame_defaults; 423Lisp_Object Vface_new_frame_defaults;
424 424
425/* Alist of face remappings. Each element is of the form:
426 (FACE REPLACEMENT...) which causes display of the face FACE to use
427 REPLACEMENT... instead. REPLACEMENT... is interpreted the same way
428 the value of a `face' text property is: it may be (1) A face name,
429 (2) A list of face names, (3) A property-list of face attribute/value
430 pairs, or (4) A list of face names intermixed with lists containing
431 face attribute/value pairs.
432
433 Multiple entries in REPLACEMENT... are merged together to form the final
434 result, with faces or attributes earlier in the list taking precedence
435 over those that are later.
436
437 Face-name remapping cycles are suppressed; recursive references use
438 the underlying face instead of the remapped face. */
439
440Lisp_Object Vface_remapping_alist;
441
425/* The next ID to assign to Lisp faces. */ 442/* The next ID to assign to Lisp faces. */
426 443
427static int next_lface_id; 444static int next_lface_id;
@@ -493,7 +510,8 @@ static void map_tty_color P_ ((struct frame *, struct face *,
493static Lisp_Object resolve_face_name P_ ((Lisp_Object, int)); 510static Lisp_Object resolve_face_name P_ ((Lisp_Object, int));
494static int may_use_scalable_font_p P_ ((const char *)); 511static int may_use_scalable_font_p P_ ((const char *));
495static void set_font_frame_param P_ ((Lisp_Object, Lisp_Object)); 512static void set_font_frame_param P_ ((Lisp_Object, Lisp_Object));
496static int get_lface_attributes P_ ((struct frame *, Lisp_Object, Lisp_Object *, int)); 513static int get_lface_attributes P_ ((struct frame *, Lisp_Object, Lisp_Object *,
514 int, struct named_merge_point *));
497static int load_pixmap P_ ((struct frame *, Lisp_Object, unsigned *, unsigned *)); 515static int load_pixmap P_ ((struct frame *, Lisp_Object, unsigned *, unsigned *));
498static unsigned char *xstrlwr P_ ((unsigned char *)); 516static unsigned char *xstrlwr P_ ((unsigned char *));
499static struct frame *frame_or_selected_frame P_ ((Lisp_Object, int)); 517static struct frame *frame_or_selected_frame P_ ((Lisp_Object, int));
@@ -2063,6 +2081,12 @@ check_lface (lface)
2063 2081
2064/* Face-merge cycle checking. */ 2082/* Face-merge cycle checking. */
2065 2083
2084enum named_merge_point_kind
2085{
2086 NAMED_MERGE_POINT_NORMAL,
2087 NAMED_MERGE_POINT_REMAP
2088};
2089
2066/* A `named merge point' is simply a point during face-merging where we 2090/* A `named merge point' is simply a point during face-merging where we
2067 look up a face by name. We keep a stack of which named lookups we're 2091 look up a face by name. We keep a stack of which named lookups we're
2068 currently processing so that we can easily detect cycles, using a 2092 currently processing so that we can easily detect cycles, using a
@@ -2072,27 +2096,40 @@ check_lface (lface)
2072struct named_merge_point 2096struct named_merge_point
2073{ 2097{
2074 Lisp_Object face_name; 2098 Lisp_Object face_name;
2099 enum named_merge_point_kind named_merge_point_kind;
2075 struct named_merge_point *prev; 2100 struct named_merge_point *prev;
2076}; 2101};
2077 2102
2078 2103
2079/* If a face merging cycle is detected for FACE_NAME, return 0, 2104/* If a face merging cycle is detected for FACE_NAME, return 0,
2080 otherwise add NEW_NAMED_MERGE_POINT, which is initialized using 2105 otherwise add NEW_NAMED_MERGE_POINT, which is initialized using
2081 FACE_NAME, as the head of the linked list pointed to by 2106 FACE_NAME and NAMED_MERGE_POINT_KIND, as the head of the linked list
2082 NAMED_MERGE_POINTS, and return 1. */ 2107 pointed to by NAMED_MERGE_POINTS, and return 1. */
2083 2108
2084static INLINE int 2109static INLINE int
2085push_named_merge_point (struct named_merge_point *new_named_merge_point, 2110push_named_merge_point (struct named_merge_point *new_named_merge_point,
2086 Lisp_Object face_name, 2111 Lisp_Object face_name,
2112 enum named_merge_point_kind named_merge_point_kind,
2087 struct named_merge_point **named_merge_points) 2113 struct named_merge_point **named_merge_points)
2088{ 2114{
2089 struct named_merge_point *prev; 2115 struct named_merge_point *prev;
2090 2116
2091 for (prev = *named_merge_points; prev; prev = prev->prev) 2117 for (prev = *named_merge_points; prev; prev = prev->prev)
2092 if (EQ (face_name, prev->face_name)) 2118 if (EQ (face_name, prev->face_name))
2093 return 0; 2119 {
2120 if (prev->named_merge_point_kind == named_merge_point_kind)
2121 /* A cycle, so fail. */
2122 return 0;
2123 else if (prev->named_merge_point_kind == NAMED_MERGE_POINT_REMAP)
2124 /* A remap `hides ' any previous normal merge points
2125 (because the remap means that it's actually different face),
2126 so as we know the current merge point must be normal, we
2127 can just assume it's OK. */
2128 break;
2129 }
2094 2130
2095 new_named_merge_point->face_name = face_name; 2131 new_named_merge_point->face_name = face_name;
2132 new_named_merge_point->named_merge_point_kind = named_merge_point_kind;
2096 new_named_merge_point->prev = *named_merge_points; 2133 new_named_merge_point->prev = *named_merge_points;
2097 2134
2098 *named_merge_points = new_named_merge_point; 2135 *named_merge_points = new_named_merge_point;
@@ -2170,22 +2207,17 @@ resolve_face_name (face_name, signal_p)
2170/* Return the face definition of FACE_NAME on frame F. F null means 2207/* Return the face definition of FACE_NAME on frame F. F null means
2171 return the definition for new frames. FACE_NAME may be a string or 2208 return the definition for new frames. FACE_NAME may be a string or
2172 a symbol (apparently Emacs 20.2 allowed strings as face names in 2209 a symbol (apparently Emacs 20.2 allowed strings as face names in
2173 face text properties; Ediff uses that). If FACE_NAME is an alias 2210 face text properties; Ediff uses that). If SIGNAL_P is non-zero,
2174 for another face, return that face's definition. If SIGNAL_P is 2211 signal an error if FACE_NAME is not a valid face name. If SIGNAL_P
2175 non-zero, signal an error if FACE_NAME is not a valid face name. 2212 is zero, value is nil if FACE_NAME is not a valid face name. */
2176 If SIGNAL_P is zero, value is nil if FACE_NAME is not a valid face
2177 name. */
2178
2179static INLINE Lisp_Object 2213static INLINE Lisp_Object
2180lface_from_face_name (f, face_name, signal_p) 2214lface_from_face_name_no_resolve (f, face_name, signal_p)
2181 struct frame *f; 2215 struct frame *f;
2182 Lisp_Object face_name; 2216 Lisp_Object face_name;
2183 int signal_p; 2217 int signal_p;
2184{ 2218{
2185 Lisp_Object lface; 2219 Lisp_Object lface;
2186 2220
2187 face_name = resolve_face_name (face_name, signal_p);
2188
2189 if (f) 2221 if (f)
2190 lface = assq_no_quit (face_name, f->face_alist); 2222 lface = assq_no_quit (face_name, f->face_alist);
2191 else 2223 else
@@ -2197,9 +2229,28 @@ lface_from_face_name (f, face_name, signal_p)
2197 signal_error ("Invalid face", face_name); 2229 signal_error ("Invalid face", face_name);
2198 2230
2199 check_lface (lface); 2231 check_lface (lface);
2232
2200 return lface; 2233 return lface;
2201} 2234}
2202 2235
2236/* Return the face definition of FACE_NAME on frame F. F null means
2237 return the definition for new frames. FACE_NAME may be a string or
2238 a symbol (apparently Emacs 20.2 allowed strings as face names in
2239 face text properties; Ediff uses that). If FACE_NAME is an alias
2240 for another face, return that face's definition. If SIGNAL_P is
2241 non-zero, signal an error if FACE_NAME is not a valid face name.
2242 If SIGNAL_P is zero, value is nil if FACE_NAME is not a valid face
2243 name. */
2244static INLINE Lisp_Object
2245lface_from_face_name (f, face_name, signal_p)
2246 struct frame *f;
2247 Lisp_Object face_name;
2248 int signal_p;
2249{
2250 face_name = resolve_face_name (face_name, signal_p);
2251 return lface_from_face_name_no_resolve (f, face_name, signal_p);
2252}
2253
2203 2254
2204/* Get face attributes of face FACE_NAME from frame-local faces on 2255/* Get face attributes of face FACE_NAME from frame-local faces on
2205 frame F. Store the resulting attributes in ATTRS which must point 2256 frame F. Store the resulting attributes in ATTRS which must point
@@ -2208,26 +2259,65 @@ lface_from_face_name (f, face_name, signal_p)
2208 Otherwise, value is zero if FACE_NAME is not a face. */ 2259 Otherwise, value is zero if FACE_NAME is not a face. */
2209 2260
2210static INLINE int 2261static INLINE int
2211get_lface_attributes (f, face_name, attrs, signal_p) 2262get_lface_attributes_no_remap (f, face_name, attrs, signal_p)
2212 struct frame *f; 2263 struct frame *f;
2213 Lisp_Object face_name; 2264 Lisp_Object face_name;
2214 Lisp_Object *attrs; 2265 Lisp_Object *attrs;
2215 int signal_p; 2266 int signal_p;
2216{ 2267{
2217 Lisp_Object lface; 2268 Lisp_Object lface;
2218 int success_p;
2219 2269
2220 lface = lface_from_face_name (f, face_name, signal_p); 2270 lface = lface_from_face_name_no_resolve (f, face_name, signal_p);
2221 if (!NILP (lface)) 2271
2272 if (! NILP (lface))
2273 bcopy (XVECTOR (lface)->contents, attrs,
2274 LFACE_VECTOR_SIZE * sizeof *attrs);
2275
2276 return !NILP (lface);
2277}
2278
2279/* Get face attributes of face FACE_NAME from frame-local faces on frame
2280 F. Store the resulting attributes in ATTRS which must point to a
2281 vector of Lisp_Objects of size LFACE_VECTOR_SIZE. If FACE_NAME is an
2282 alias for another face, use that face's definition. If SIGNAL_P is
2283 non-zero, signal an error if FACE_NAME does not name a face.
2284 Otherwise, value is zero if FACE_NAME is not a face. */
2285
2286static INLINE int
2287get_lface_attributes (f, face_name, attrs, signal_p, named_merge_points)
2288 struct frame *f;
2289 Lisp_Object face_name;
2290 Lisp_Object *attrs;
2291 int signal_p;
2292 struct named_merge_point *named_merge_points;
2293{
2294 Lisp_Object face_remapping;
2295
2296 face_name = resolve_face_name (face_name, signal_p);
2297
2298 /* See if SYMBOL has been remapped to some other face (usually this
2299 is done buffer-locally). */
2300 face_remapping = assq_no_quit (face_name, Vface_remapping_alist);
2301 if (CONSP (face_remapping))
2222 { 2302 {
2223 bcopy (XVECTOR (lface)->contents, attrs, 2303 struct named_merge_point named_merge_point;
2224 LFACE_VECTOR_SIZE * sizeof *attrs); 2304
2225 success_p = 1; 2305 if (push_named_merge_point (&named_merge_point,
2306 face_name, NAMED_MERGE_POINT_REMAP,
2307 &named_merge_points))
2308 {
2309 int i;
2310
2311 for (i = 1; i < LFACE_VECTOR_SIZE; ++i)
2312 attrs[i] = Qunspecified;
2313
2314 return merge_face_ref (f, XCDR (face_remapping), attrs,
2315 signal_p, named_merge_points);
2316 }
2226 } 2317 }
2227 else
2228 success_p = 0;
2229 2318
2230 return success_p; 2319 /* Default case, no remapping. */
2320 return get_lface_attributes_no_remap (f, face_name, attrs, signal_p);
2231} 2321}
2232 2322
2233 2323
@@ -2383,8 +2473,8 @@ merge_face_heights (from, to, invalid)
2383 specified attribute of FROM overrides the corresponding attribute of 2473 specified attribute of FROM overrides the corresponding attribute of
2384 TO; relative attributes in FROM are merged with the absolute value in 2474 TO; relative attributes in FROM are merged with the absolute value in
2385 TO and replace it. NAMED_MERGE_POINTS is used internally to detect 2475 TO and replace it. NAMED_MERGE_POINTS is used internally to detect
2386 loops in face inheritance; it should be 0 when called from other 2476 loops in face inheritance/remapping; it should be 0 when called from
2387 places. */ 2477 other places. */
2388 2478
2389static INLINE void 2479static INLINE void
2390merge_face_vectors (f, from, to, named_merge_points) 2480merge_face_vectors (f, from, to, named_merge_points)
@@ -2459,11 +2549,12 @@ merge_named_face (f, face_name, to, named_merge_points)
2459 struct named_merge_point named_merge_point; 2549 struct named_merge_point named_merge_point;
2460 2550
2461 if (push_named_merge_point (&named_merge_point, 2551 if (push_named_merge_point (&named_merge_point,
2462 face_name, &named_merge_points)) 2552 face_name, NAMED_MERGE_POINT_NORMAL,
2553 &named_merge_points))
2463 { 2554 {
2464 struct gcpro gcpro1; 2555 struct gcpro gcpro1;
2465 Lisp_Object from[LFACE_VECTOR_SIZE]; 2556 Lisp_Object from[LFACE_VECTOR_SIZE];
2466 int ok = get_lface_attributes (f, face_name, from, 0); 2557 int ok = get_lface_attributes (f, face_name, from, 0, named_merge_points);
2467 2558
2468 if (ok) 2559 if (ok)
2469 { 2560 {
@@ -3441,7 +3532,7 @@ update_face_from_frame_parameter (f, param, new_value)
3441 3532
3442 /* Changing the background color might change the background 3533 /* Changing the background color might change the background
3443 mode, so that we have to load new defface specs. 3534 mode, so that we have to load new defface specs.
3444 Call frame-set-background-mode to do that. */ 3535 Call frame-update-face-colors to do that. */
3445 XSETFRAME (frame, f); 3536 XSETFRAME (frame, f);
3446 call1 (Qframe_set_background_mode, frame); 3537 call1 (Qframe_set_background_mode, frame);
3447 3538
@@ -4647,7 +4738,7 @@ lookup_named_face (f, symbol, signal_p)
4647 abort (); /* realize_basic_faces must have set it up */ 4738 abort (); /* realize_basic_faces must have set it up */
4648 } 4739 }
4649 4740
4650 if (!get_lface_attributes (f, symbol, symbol_attrs, signal_p)) 4741 if (! get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0))
4651 return -1; 4742 return -1;
4652 4743
4653 bcopy (default_face->lface, attrs, sizeof attrs); 4744 bcopy (default_face->lface, attrs, sizeof attrs);
@@ -4657,6 +4748,58 @@ lookup_named_face (f, symbol, signal_p)
4657} 4748}
4658 4749
4659 4750
4751/* Return the display face-id of the basic face who's canonical face-id
4752 is FACE_ID. The return value will usually simply be FACE_ID, unless that
4753 basic face has bee remapped via Vface_remapping_alist. This function is
4754 conservative: if something goes wrong, it will simply return FACE_ID
4755 rather than signal an error. */
4756
4757int
4758lookup_basic_face (f, face_id)
4759 struct frame *f;
4760 int face_id;
4761{
4762 Lisp_Object name, mapping;
4763 int remapped_face_id;
4764
4765 if (NILP (Vface_remapping_alist))
4766 return face_id; /* Nothing to do. */
4767
4768 switch (face_id)
4769 {
4770 case DEFAULT_FACE_ID: name = Qdefault; break;
4771 case MODE_LINE_FACE_ID: name = Qmode_line; break;
4772 case MODE_LINE_INACTIVE_FACE_ID: name = Qmode_line_inactive; break;
4773 case HEADER_LINE_FACE_ID: name = Qheader_line; break;
4774 case TOOL_BAR_FACE_ID: name = Qtool_bar; break;
4775 case FRINGE_FACE_ID: name = Qfringe; break;
4776 case SCROLL_BAR_FACE_ID: name = Qscroll_bar; break;
4777 case BORDER_FACE_ID: name = Qborder; break;
4778 case CURSOR_FACE_ID: name = Qcursor; break;
4779 case MOUSE_FACE_ID: name = Qmouse; break;
4780 case MENU_FACE_ID: name = Qmenu; break;
4781
4782 default:
4783 abort (); /* the caller is supposed to pass us a basic face id */
4784 }
4785
4786 /* Do a quick scan through Vface_remapping_alist, and return immediately
4787 if there is no remapping for face NAME. This is just an optimization
4788 for the very common no-remapping case. */
4789 mapping = assq_no_quit (name, Vface_remapping_alist);
4790 if (NILP (mapping))
4791 return face_id; /* Give up. */
4792
4793 /* If there is a remapping entry, lookup the face using NAME, which will
4794 handle the remapping too. */
4795 remapped_face_id = lookup_named_face (f, name, 0);
4796 if (remapped_face_id < 0)
4797 return face_id; /* Give up. */
4798
4799 return remapped_face_id;
4800}
4801
4802
4660/* Return the ID of the realized ASCII face of Lisp face with ID 4803/* Return the ID of the realized ASCII face of Lisp face with ID
4661 LFACE_ID on frame F. Value is -1 if LFACE_ID isn't valid. */ 4804 LFACE_ID on frame F. Value is -1 if LFACE_ID isn't valid. */
4662 4805
@@ -4789,7 +4932,7 @@ lookup_derived_face (f, symbol, face_id, signal_p)
4789 if (!default_face) 4932 if (!default_face)
4790 abort (); 4933 abort ();
4791 4934
4792 get_lface_attributes (f, symbol, symbol_attrs, signal_p); 4935 get_lface_attributes (f, symbol, symbol_attrs, signal_p, 0);
4793 bcopy (default_face->lface, attrs, sizeof attrs); 4936 bcopy (default_face->lface, attrs, sizeof attrs);
4794 merge_face_vectors (f, symbol_attrs, attrs, 0); 4937 merge_face_vectors (f, symbol_attrs, attrs, 0);
4795 return lookup_face (f, attrs); 4938 return lookup_face (f, attrs);
@@ -5498,7 +5641,7 @@ realize_named_face (f, symbol, id)
5498 struct face *new_face; 5641 struct face *new_face;
5499 5642
5500 /* The default face must exist and be fully specified. */ 5643 /* The default face must exist and be fully specified. */
5501 get_lface_attributes (f, Qdefault, attrs, 1); 5644 get_lface_attributes_no_remap (f, Qdefault, attrs, 1);
5502 check_lface_attrs (attrs); 5645 check_lface_attrs (attrs);
5503 xassert (lface_fully_specified_p (attrs)); 5646 xassert (lface_fully_specified_p (attrs));
5504 5647
@@ -5511,7 +5654,7 @@ realize_named_face (f, symbol, id)
5511 } 5654 }
5512 5655
5513 /* Merge SYMBOL's face with the default face. */ 5656 /* Merge SYMBOL's face with the default face. */
5514 get_lface_attributes (f, symbol, symbol_attrs, 1); 5657 get_lface_attributes_no_remap (f, symbol, symbol_attrs, 1);
5515 merge_face_vectors (f, symbol_attrs, attrs, 0); 5658 merge_face_vectors (f, symbol_attrs, attrs, 0);
5516 5659
5517 /* Realize the face. */ 5660 /* Realize the face. */
@@ -6068,13 +6211,18 @@ face_at_buffer_position (w, pos, region_beg, region_end,
6068 6211
6069 *endptr = endpos; 6212 *endptr = endpos;
6070 6213
6071 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID); 6214
6215 /* Perhaps remap BASE_FACE_ID to a user-specified alternative. */
6216 if (NILP (Vface_remapping_alist))
6217 default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
6218 else
6219 default_face = FACE_FROM_ID (f, lookup_basic_face (f, DEFAULT_FACE_ID));
6072 6220
6073 /* Optimize common cases where we can use the default face. */ 6221 /* Optimize common cases where we can use the default face. */
6074 if (noverlays == 0 6222 if (noverlays == 0
6075 && NILP (prop) 6223 && NILP (prop)
6076 && !(pos >= region_beg && pos < region_end)) 6224 && !(pos >= region_beg && pos < region_end))
6077 return DEFAULT_FACE_ID; 6225 return default_face->id;
6078 6226
6079 /* Begin with attributes from the default face. */ 6227 /* Begin with attributes from the default face. */
6080 bcopy (default_face->lface, attrs, sizeof attrs); 6228 bcopy (default_face->lface, attrs, sizeof attrs);
@@ -6673,6 +6821,43 @@ Each element is a regular expression that matches names of fonts to
6673ignore. */); 6821ignore. */);
6674 Vface_ignored_fonts = Qnil; 6822 Vface_ignored_fonts = Qnil;
6675 6823
6824 DEFVAR_LISP ("face-remapping-alist", &Vface_remapping_alist,
6825 doc: /* Alist of face remappings.
6826Each element is of the form:
6827
6828 (FACE REPLACEMENT...),
6829
6830which causes display of the face FACE to use REPLACEMENT... instead.
6831REPLACEMENT... is interpreted the same way the value of a `face' text
6832property is: it may be (1) A face name, (2) A list of face names, (3) A
6833property-list of face attribute/value pairs, or (4) A list of face names
6834intermixed with lists containing face attribute/value pairs.
6835
6836Multiple entries in REPLACEMENT... are merged together to form the final
6837result, with faces or attributes earlier in the list taking precedence
6838over those that are later.
6839
6840Face-name remapping cycles are suppressed; recursive references use the
6841underlying face instead of the remapped face. So a remapping of the form:
6842
6843 (FACE EXTRA-FACE... FACE)
6844
6845or:
6846
6847 (FACE (FACE-ATTR VAL ...) FACE)
6848
6849will cause EXTRA-FACE... or (FACE-ATTR VAL ...) to be _merged_ with the
6850existing definition of FACE. Note that for the default face, this isn't
6851necessary, as every face inherits from the default face.
6852
6853Making this variable buffer-local is a good way to allow buffer-specific
6854face definitions. For instance, the mode my-mode could define a face
6855`my-mode-default', and then in the mode setup function, do:
6856
6857 (set (make-local-variable 'face-remapping-alist)
6858 '((default my-mode-default)))). */);
6859 Vface_remapping_alist = Qnil;
6860
6676 DEFVAR_LISP ("face-font-rescale-alist", &Vface_font_rescale_alist, 6861 DEFVAR_LISP ("face-font-rescale-alist", &Vface_font_rescale_alist,
6677 doc: /* Alist of fonts vs the rescaling factors. 6862 doc: /* Alist of fonts vs the rescaling factors.
6678Each element is a cons (FONT-NAME-PATTERN . RESCALE-RATIO), where 6863Each element is a cons (FONT-NAME-PATTERN . RESCALE-RATIO), where