aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMiles Bader2004-06-07 07:02:20 +0000
committerMiles Bader2004-06-07 07:02:20 +0000
commita0a2334679b7278ca0577a733c8ba8d0362a1a38 (patch)
tree6c55eff94f4f7d1c37cfe1fbeba367f443517904 /src
parent12d5b1856c718a114ae75901ec34e0e9b16455c0 (diff)
downloademacs-a0a2334679b7278ca0577a733c8ba8d0362a1a38.tar.gz
emacs-a0a2334679b7278ca0577a733c8ba8d0362a1a38.zip
Revision: miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-381
Face merging cleanups The only user-visible changes should be: * The priority order of faces in a face :inherit attribute is now reversed (for consistency with face lists in `face' text properties) * An :inherit loop is halted immediately, instead of being applied several times first; this should only matters when a relative attribute such as a :height scale is used.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog20
-rw-r--r--src/xfaces.c289
2 files changed, 182 insertions, 127 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 88f4a5c68ca..0770eaeff69 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,23 @@
12004-06-07 Miles Bader <miles@gnu.org>
2
3 * (struct named_merge_point): New type.
4 (push_named_merge_point): New function.
5 (merge_named_face): New function.
6 (merge_face_ref, face_at_buffer_position, face_at_string_position):
7 Use `merge_named_face'.
8 (merge_face_inheritance): Function removed.
9 (merge_face_ref): Renamed from `merge_face_vector_with_property'.
10 Add new `err_msgs' and `named_merge_points' args. Return error
11 status. Only print error messages if ERR_MSGS is true. Don't try to
12 do :inherit attribute validation.
13 (merge_face_heights): Handle `unspecified' in both directions.
14 (merge_face_vectors): Rename `cycle_check' arg to `named_merge_points'.
15 Call `merge_face_ref' instead of `merge_face_inheritance'.
16 (Fdisplay_supports_face_attributes_p, Fface_attributes_as_vector)
17 (compute_char_face, face_at_buffer_position)
18 (face_at_string_position): Call `merge_face_ref' instead of
19 `merge_face_vector_with_property'.
20
12004-06-07 Kenichi Handa <handa@m17n.org> 212004-06-07 Kenichi Handa <handa@m17n.org>
2 22
3 * coding.c (find_safe_codings): Check NILP (safe_codings) only at 23 * coding.c (find_safe_codings): Check NILP (safe_codings) only at
diff --git a/src/xfaces.c b/src/xfaces.c
index d2cf2e24d08..afe352267d3 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -460,6 +460,7 @@ int menu_face_changed_default;
460 460
461struct font_name; 461struct font_name;
462struct table_entry; 462struct table_entry;
463struct named_merge_point;
463 464
464static void map_tty_color P_ ((struct frame *, struct face *, 465static void map_tty_color P_ ((struct frame *, struct face *,
465 enum lface_attribute_index, int *)); 466 enum lface_attribute_index, int *));
@@ -518,11 +519,10 @@ static int face_numeric_slant P_ ((Lisp_Object));
518static int face_numeric_swidth P_ ((Lisp_Object)); 519static int face_numeric_swidth P_ ((Lisp_Object));
519static int face_fontset P_ ((Lisp_Object *)); 520static int face_fontset P_ ((Lisp_Object *));
520static char *choose_face_font P_ ((struct frame *, Lisp_Object *, int, int, int*)); 521static char *choose_face_font P_ ((struct frame *, Lisp_Object *, int, int, int*));
521static void merge_face_vectors P_ ((struct frame *, Lisp_Object *, Lisp_Object*, Lisp_Object)); 522static void merge_face_vectors P_ ((struct frame *, Lisp_Object *, Lisp_Object*,
522static void merge_face_inheritance P_ ((struct frame *f, Lisp_Object, 523 struct named_merge_point *));
523 Lisp_Object *, Lisp_Object)); 524static int merge_face_ref P_ ((struct frame *, Lisp_Object, Lisp_Object *,
524static void merge_face_vector_with_property P_ ((struct frame *, Lisp_Object *, 525 int, struct named_merge_point *));
525 Lisp_Object));
526static int set_lface_from_font_name P_ ((struct frame *, Lisp_Object, 526static int set_lface_from_font_name P_ ((struct frame *, Lisp_Object,
527 Lisp_Object, int, int)); 527 Lisp_Object, int, int));
528static Lisp_Object lface_from_face_name P_ ((struct frame *, Lisp_Object, int)); 528static Lisp_Object lface_from_face_name P_ ((struct frame *, Lisp_Object, int));
@@ -3151,6 +3151,49 @@ check_lface (lface)
3151#endif /* GLYPH_DEBUG == 0 */ 3151#endif /* GLYPH_DEBUG == 0 */
3152 3152
3153 3153
3154
3155/* Face-merge cycle checking. */
3156
3157/* A `named merge point' is simply a point during face-merging where we
3158 look up a face by name. We keep a stack of which named lookups we're
3159 currently processing so that we can easily detect cycles, using a
3160 linked- list of struct named_merge_point structures, typically
3161 allocated on the stack frame of the named lookup functions which are
3162 active (so no consing is required). */
3163struct named_merge_point
3164{
3165 Lisp_Object face_name;
3166 struct named_merge_point *prev;
3167};
3168
3169
3170/* If a face merging cycle is detected for FACE_NAME, return 0,
3171 otherwise add NEW_NAMED_MERGE_POINT, which is initialized using
3172 FACE_NAME, as the head of the linked list
3173 pointed to by NAMED_MERGE_POINTS, and return 1. */
3174
3175static INLINE int
3176push_named_merge_point (struct named_merge_point *new_named_merge_point,
3177 Lisp_Object face_name,
3178 struct named_merge_point **named_merge_points)
3179{
3180 struct named_merge_point *prev;
3181
3182 for (prev = *named_merge_points; prev; prev = prev->prev)
3183 if (EQ (face_name, prev->face_name))
3184 break;
3185
3186 new_named_merge_point->face_name = face_name;
3187 new_named_merge_point->prev = *named_merge_points;
3188
3189 *named_merge_points = new_named_merge_point;
3190
3191 return 1;
3192}
3193
3194
3195
3196
3154/* Resolve face name FACE_NAME. If FACE_NAME is a string, intern it 3197/* Resolve face name FACE_NAME. If FACE_NAME is a string, intern it
3155 to make it a symvol. If FACE_NAME is an alias for another face, 3198 to make it a symvol. If FACE_NAME is an alias for another face,
3156 return that face's name. */ 3199 return that face's name. */
@@ -3401,6 +3444,8 @@ merge_face_heights (from, to, invalid, gcpro)
3401 else if (FLOATP (to)) 3444 else if (FLOATP (to))
3402 /* relative X relative => relative */ 3445 /* relative X relative => relative */
3403 result = make_float (XFLOAT_DATA (from) * XFLOAT_DATA (to)); 3446 result = make_float (XFLOAT_DATA (from) * XFLOAT_DATA (to));
3447 else if (UNSPECIFIEDP (to))
3448 result = from;
3404 } 3449 }
3405 else if (FUNCTIONP (from)) 3450 else if (FUNCTIONP (from))
3406 /* FROM is a function, which use to adjust TO. */ 3451 /* FROM is a function, which use to adjust TO. */
@@ -3432,14 +3477,15 @@ merge_face_heights (from, to, invalid, gcpro)
3432 completely specified and contain only absolute attributes. Every 3477 completely specified and contain only absolute attributes. Every
3433 specified attribute of FROM overrides the corresponding attribute of 3478 specified attribute of FROM overrides the corresponding attribute of
3434 TO; relative attributes in FROM are merged with the absolute value in 3479 TO; relative attributes in FROM are merged with the absolute value in
3435 TO and replace it. CYCLE_CHECK is used internally to detect loops in 3480 TO and replace it. NAMED_MERGE_POINTS is used internally to detect
3436 face inheritance; it should be Qnil when called from other places. */ 3481 loops in face inheritance; it should be 0 when called from other
3482 places. */
3437 3483
3438static INLINE void 3484static INLINE void
3439merge_face_vectors (f, from, to, cycle_check) 3485merge_face_vectors (f, from, to, named_merge_points)
3440 struct frame *f; 3486 struct frame *f;
3441 Lisp_Object *from, *to; 3487 Lisp_Object *from, *to;
3442 Lisp_Object cycle_check; 3488 struct named_merge_point *named_merge_points;
3443{ 3489{
3444 int i; 3490 int i;
3445 3491
@@ -3450,7 +3496,7 @@ merge_face_vectors (f, from, to, cycle_check)
3450 other code uses `unspecified' as a generic value for face attributes. */ 3496 other code uses `unspecified' as a generic value for face attributes. */
3451 if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX]) 3497 if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX])
3452 && !NILP (from[LFACE_INHERIT_INDEX])) 3498 && !NILP (from[LFACE_INHERIT_INDEX]))
3453 merge_face_inheritance (f, from[LFACE_INHERIT_INDEX], to, cycle_check); 3499 merge_face_ref (f, from[LFACE_INHERIT_INDEX], to, 0, named_merge_points);
3454 3500
3455 /* If TO specifies a :font attribute, and FROM specifies some 3501 /* If TO specifies a :font attribute, and FROM specifies some
3456 font-related attribute, we need to clear TO's :font attribute 3502 font-related attribute, we need to clear TO's :font attribute
@@ -3469,7 +3515,8 @@ merge_face_vectors (f, from, to, cycle_check)
3469 if (!UNSPECIFIEDP (from[i])) 3515 if (!UNSPECIFIEDP (from[i]))
3470 { 3516 {
3471 if (i == LFACE_HEIGHT_INDEX && !INTEGERP (from[i])) 3517 if (i == LFACE_HEIGHT_INDEX && !INTEGERP (from[i]))
3472 to[i] = merge_face_heights (from[i], to[i], to[i], cycle_check); 3518 to[i] = merge_face_heights (from[i], to[i], to[i],
3519 named_merge_points);
3473 else 3520 else
3474 to[i] = from[i]; 3521 to[i] = from[i];
3475 } 3522 }
@@ -3479,61 +3526,45 @@ merge_face_vectors (f, from, to, cycle_check)
3479 to[LFACE_INHERIT_INDEX] = Qnil; 3526 to[LFACE_INHERIT_INDEX] = Qnil;
3480} 3527}
3481 3528
3482/* Merge face attributes from the face on frame F whose name is 3529/* Merge the named face FACE_NAME on frame F, into the vector of face
3483 INHERITS, into the vector of face attributes TO; INHERITS may also be 3530 attributes TO. NAMED_MERGE_POINTS is used to detect loops in face
3484 a list of face names, in which case they are applied in order. 3531 inheritance. Returns true if FACE_NAME is a valid face name and
3485 CYCLE_CHECK is used to detect loops in face inheritance. 3532 merging succeeded. */
3486 Returns true if any of the inherited attributes are `font-related'. */
3487 3533
3488static void 3534static int
3489merge_face_inheritance (f, inherit, to, cycle_check) 3535merge_named_face (f, face_name, to, named_merge_points)
3490 struct frame *f; 3536 struct frame *f;
3491 Lisp_Object inherit; 3537 Lisp_Object face_name;
3492 Lisp_Object *to; 3538 Lisp_Object *to;
3493 Lisp_Object cycle_check; 3539 struct named_merge_point *named_merge_points;
3494{ 3540{
3495 if (SYMBOLP (inherit) && !EQ (inherit, Qunspecified)) 3541 struct named_merge_point named_merge_point;
3496 /* Inherit from the named face INHERIT. */
3497 {
3498 Lisp_Object lface;
3499 3542
3500 /* Make sure we're not in an inheritance loop. */ 3543 if (push_named_merge_point (&named_merge_point,
3501 cycle_check = CYCLE_CHECK (cycle_check, inherit, 15); 3544 face_name, &named_merge_points))
3502 if (NILP (cycle_check))
3503 /* Cycle detected, ignore any further inheritance. */
3504 return;
3505
3506 lface = lface_from_face_name (f, inherit, 0);
3507 if (!NILP (lface))
3508 merge_face_vectors (f, XVECTOR (lface)->contents, to, cycle_check);
3509 }
3510 else if (CONSP (inherit))
3511 /* Handle a list of inherited faces by calling ourselves recursively
3512 on each element. Note that we only do so for symbol elements, so
3513 it's not possible to infinitely recurse. */
3514 { 3545 {
3515 while (CONSP (inherit)) 3546 Lisp_Object from[LFACE_VECTOR_SIZE];
3516 { 3547 int ok = get_lface_attributes (f, face_name, from, 0);
3517 if (SYMBOLP (XCAR (inherit)))
3518 merge_face_inheritance (f, XCAR (inherit), to, cycle_check);
3519 3548
3520 /* Check for a circular inheritance list. */ 3549 if (ok)
3521 cycle_check = CYCLE_CHECK (cycle_check, inherit, 15); 3550 merge_face_vectors (f, from, to, named_merge_points);
3522 if (NILP (cycle_check))
3523 /* Cycle detected. */
3524 break;
3525 3551
3526 inherit = XCDR (inherit); 3552 return ok;
3527 }
3528 } 3553 }
3554 else
3555 return 0;
3529} 3556}
3530 3557
3531 3558
3532/* Given a Lisp face attribute vector TO and a Lisp object PROP that 3559/* Merge face attributes from the lisp `face reference' FACE_REF on
3533 is a face property, determine the resulting face attributes on 3560 frame F into the face attribute vector TO. If ERR_MSGS is non-zero,
3534 frame F, and store them in TO. PROP may be a single face 3561 problems with FACE_REF cause an error message to be shown. Return
3535 specification or a list of such specifications. Each face 3562 non-zero if no errors occurred (regardless of the value of ERR_MSGS).
3536 specification can be 3563 NAMED_MERGE_POINTS is used to detect loops in face inheritance or
3564 list structure; it may be 0 for most callers.
3565
3566 FACE_REF may be a single face specification or a list of such
3567 specifications. Each face specification can be:
3537 3568
3538 1. A symbol or string naming a Lisp face. 3569 1. A symbol or string naming a Lisp face.
3539 3570
@@ -3548,22 +3579,26 @@ merge_face_inheritance (f, inherit, to, cycle_check)
3548 Face specifications earlier in lists take precedence over later 3579 Face specifications earlier in lists take precedence over later
3549 specifications. */ 3580 specifications. */
3550 3581
3551static void 3582static int
3552merge_face_vector_with_property (f, to, prop) 3583merge_face_ref (f, face_ref, to, err_msgs, named_merge_points)
3553 struct frame *f; 3584 struct frame *f;
3585 Lisp_Object face_ref;
3554 Lisp_Object *to; 3586 Lisp_Object *to;
3555 Lisp_Object prop; 3587 int err_msgs;
3588 struct named_merge_point *named_merge_points;
3556{ 3589{
3557 if (CONSP (prop)) 3590 int ok = 1; /* Succeed without an error? */
3591
3592 if (CONSP (face_ref))
3558 { 3593 {
3559 Lisp_Object first = XCAR (prop); 3594 Lisp_Object first = XCAR (face_ref);
3560 3595
3561 if (EQ (first, Qforeground_color) 3596 if (EQ (first, Qforeground_color)
3562 || EQ (first, Qbackground_color)) 3597 || EQ (first, Qbackground_color))
3563 { 3598 {
3564 /* One of (FOREGROUND-COLOR . COLOR) or (BACKGROUND-COLOR 3599 /* One of (FOREGROUND-COLOR . COLOR) or (BACKGROUND-COLOR
3565 . COLOR). COLOR must be a string. */ 3600 . COLOR). COLOR must be a string. */
3566 Lisp_Object color_name = XCDR (prop); 3601 Lisp_Object color_name = XCDR (face_ref);
3567 Lisp_Object color = first; 3602 Lisp_Object color = first;
3568 3603
3569 if (STRINGP (color_name)) 3604 if (STRINGP (color_name))
@@ -3574,23 +3609,28 @@ merge_face_vector_with_property (f, to, prop)
3574 to[LFACE_BACKGROUND_INDEX] = color_name; 3609 to[LFACE_BACKGROUND_INDEX] = color_name;
3575 } 3610 }
3576 else 3611 else
3577 add_to_log ("Invalid face color", color_name, Qnil); 3612 {
3613 if (err_msgs)
3614 add_to_log ("Invalid face color", color_name, Qnil);
3615 ok = 0;
3616 }
3578 } 3617 }
3579 else if (SYMBOLP (first) 3618 else if (SYMBOLP (first)
3580 && *SDATA (SYMBOL_NAME (first)) == ':') 3619 && *SDATA (SYMBOL_NAME (first)) == ':')
3581 { 3620 {
3582 /* Assume this is the property list form. */ 3621 /* Assume this is the property list form. */
3583 while (CONSP (prop) && CONSP (XCDR (prop))) 3622 while (CONSP (face_ref) && CONSP (XCDR (face_ref)))
3584 { 3623 {
3585 Lisp_Object keyword = XCAR (prop); 3624 Lisp_Object keyword = XCAR (face_ref);
3586 Lisp_Object value = XCAR (XCDR (prop)); 3625 Lisp_Object value = XCAR (XCDR (face_ref));
3626 int err = 0;
3587 3627
3588 if (EQ (keyword, QCfamily)) 3628 if (EQ (keyword, QCfamily))
3589 { 3629 {
3590 if (STRINGP (value)) 3630 if (STRINGP (value))
3591 to[LFACE_FAMILY_INDEX] = value; 3631 to[LFACE_FAMILY_INDEX] = value;
3592 else 3632 else
3593 add_to_log ("Invalid face font family", value, Qnil); 3633 err = 1;
3594 } 3634 }
3595 else if (EQ (keyword, QCheight)) 3635 else if (EQ (keyword, QCheight))
3596 { 3636 {
@@ -3598,10 +3638,10 @@ merge_face_vector_with_property (f, to, prop)
3598 merge_face_heights (value, to[LFACE_HEIGHT_INDEX], 3638 merge_face_heights (value, to[LFACE_HEIGHT_INDEX],
3599 Qnil, Qnil); 3639 Qnil, Qnil);
3600 3640
3601 if (NILP (new_height)) 3641 if (! NILP (new_height))
3602 add_to_log ("Invalid face font height", value, Qnil);
3603 else
3604 to[LFACE_HEIGHT_INDEX] = new_height; 3642 to[LFACE_HEIGHT_INDEX] = new_height;
3643 else
3644 err = 1;
3605 } 3645 }
3606 else if (EQ (keyword, QCweight)) 3646 else if (EQ (keyword, QCweight))
3607 { 3647 {
@@ -3609,7 +3649,7 @@ merge_face_vector_with_property (f, to, prop)
3609 && face_numeric_weight (value) >= 0) 3649 && face_numeric_weight (value) >= 0)
3610 to[LFACE_WEIGHT_INDEX] = value; 3650 to[LFACE_WEIGHT_INDEX] = value;
3611 else 3651 else
3612 add_to_log ("Invalid face weight", value, Qnil); 3652 err = 1;
3613 } 3653 }
3614 else if (EQ (keyword, QCslant)) 3654 else if (EQ (keyword, QCslant))
3615 { 3655 {
@@ -3617,7 +3657,7 @@ merge_face_vector_with_property (f, to, prop)
3617 && face_numeric_slant (value) >= 0) 3657 && face_numeric_slant (value) >= 0)
3618 to[LFACE_SLANT_INDEX] = value; 3658 to[LFACE_SLANT_INDEX] = value;
3619 else 3659 else
3620 add_to_log ("Invalid face slant", value, Qnil); 3660 err = 1;
3621 } 3661 }
3622 else if (EQ (keyword, QCunderline)) 3662 else if (EQ (keyword, QCunderline))
3623 { 3663 {
@@ -3626,7 +3666,7 @@ merge_face_vector_with_property (f, to, prop)
3626 || STRINGP (value)) 3666 || STRINGP (value))
3627 to[LFACE_UNDERLINE_INDEX] = value; 3667 to[LFACE_UNDERLINE_INDEX] = value;
3628 else 3668 else
3629 add_to_log ("Invalid face underline", value, Qnil); 3669 err = 1;
3630 } 3670 }
3631 else if (EQ (keyword, QCoverline)) 3671 else if (EQ (keyword, QCoverline))
3632 { 3672 {
@@ -3635,7 +3675,7 @@ merge_face_vector_with_property (f, to, prop)
3635 || STRINGP (value)) 3675 || STRINGP (value))
3636 to[LFACE_OVERLINE_INDEX] = value; 3676 to[LFACE_OVERLINE_INDEX] = value;
3637 else 3677 else
3638 add_to_log ("Invalid face overline", value, Qnil); 3678 err = 1;
3639 } 3679 }
3640 else if (EQ (keyword, QCstrike_through)) 3680 else if (EQ (keyword, QCstrike_through))
3641 { 3681 {
@@ -3644,7 +3684,7 @@ merge_face_vector_with_property (f, to, prop)
3644 || STRINGP (value)) 3684 || STRINGP (value))
3645 to[LFACE_STRIKE_THROUGH_INDEX] = value; 3685 to[LFACE_STRIKE_THROUGH_INDEX] = value;
3646 else 3686 else
3647 add_to_log ("Invalid face strike-through", value, Qnil); 3687 err = 1;
3648 } 3688 }
3649 else if (EQ (keyword, QCbox)) 3689 else if (EQ (keyword, QCbox))
3650 { 3690 {
@@ -3656,7 +3696,7 @@ merge_face_vector_with_property (f, to, prop)
3656 || NILP (value)) 3696 || NILP (value))
3657 to[LFACE_BOX_INDEX] = value; 3697 to[LFACE_BOX_INDEX] = value;
3658 else 3698 else
3659 add_to_log ("Invalid face box", value, Qnil); 3699 err = 1;
3660 } 3700 }
3661 else if (EQ (keyword, QCinverse_video) 3701 else if (EQ (keyword, QCinverse_video)
3662 || EQ (keyword, QCreverse_video)) 3702 || EQ (keyword, QCreverse_video))
@@ -3664,21 +3704,21 @@ merge_face_vector_with_property (f, to, prop)
3664 if (EQ (value, Qt) || NILP (value)) 3704 if (EQ (value, Qt) || NILP (value))
3665 to[LFACE_INVERSE_INDEX] = value; 3705 to[LFACE_INVERSE_INDEX] = value;
3666 else 3706 else
3667 add_to_log ("Invalid face inverse-video", value, Qnil); 3707 err = 1;
3668 } 3708 }
3669 else if (EQ (keyword, QCforeground)) 3709 else if (EQ (keyword, QCforeground))
3670 { 3710 {
3671 if (STRINGP (value)) 3711 if (STRINGP (value))
3672 to[LFACE_FOREGROUND_INDEX] = value; 3712 to[LFACE_FOREGROUND_INDEX] = value;
3673 else 3713 else
3674 add_to_log ("Invalid face foreground", value, Qnil); 3714 err = 1;
3675 } 3715 }
3676 else if (EQ (keyword, QCbackground)) 3716 else if (EQ (keyword, QCbackground))
3677 { 3717 {
3678 if (STRINGP (value)) 3718 if (STRINGP (value))
3679 to[LFACE_BACKGROUND_INDEX] = value; 3719 to[LFACE_BACKGROUND_INDEX] = value;
3680 else 3720 else
3681 add_to_log ("Invalid face background", value, Qnil); 3721 err = 1;
3682 } 3722 }
3683 else if (EQ (keyword, QCstipple)) 3723 else if (EQ (keyword, QCstipple))
3684 { 3724 {
@@ -3687,7 +3727,7 @@ merge_face_vector_with_property (f, to, prop)
3687 if (!NILP (pixmap_p)) 3727 if (!NILP (pixmap_p))
3688 to[LFACE_STIPPLE_INDEX] = value; 3728 to[LFACE_STIPPLE_INDEX] = value;
3689 else 3729 else
3690 add_to_log ("Invalid face stipple", value, Qnil); 3730 err = 1;
3691#endif 3731#endif
3692 } 3732 }
3693 else if (EQ (keyword, QCwidth)) 3733 else if (EQ (keyword, QCwidth))
@@ -3696,52 +3736,51 @@ merge_face_vector_with_property (f, to, prop)
3696 && face_numeric_swidth (value) >= 0) 3736 && face_numeric_swidth (value) >= 0)
3697 to[LFACE_SWIDTH_INDEX] = value; 3737 to[LFACE_SWIDTH_INDEX] = value;
3698 else 3738 else
3699 add_to_log ("Invalid face width", value, Qnil); 3739 err = 1;
3700 } 3740 }
3701 else if (EQ (keyword, QCinherit)) 3741 else if (EQ (keyword, QCinherit))
3702 { 3742 {
3703 if (SYMBOLP (value)) 3743 /* This is not really very useful; it's just like a
3704 to[LFACE_INHERIT_INDEX] = value; 3744 normal face reference. */
3705 else 3745 if (! merge_face_ref (f, value, to,
3706 { 3746 err_msgs, named_merge_points))
3707 Lisp_Object tail; 3747 err = 1;
3708 for (tail = value; CONSP (tail); tail = XCDR (tail))
3709 if (!SYMBOLP (XCAR (tail)))
3710 break;
3711 if (NILP (tail))
3712 to[LFACE_INHERIT_INDEX] = value;
3713 else
3714 add_to_log ("Invalid face inherit", value, Qnil);
3715 }
3716 } 3748 }
3717 else 3749 else
3718 add_to_log ("Invalid attribute %s in face property", 3750 err = 1;
3719 keyword, Qnil); 3751
3752 if (err)
3753 {
3754 add_to_log ("Invalid face attribute %S %S", keyword, value);
3755 ok = 0;
3756 }
3720 3757
3721 prop = XCDR (XCDR (prop)); 3758 face_ref = XCDR (XCDR (face_ref));
3722 } 3759 }
3723 } 3760 }
3724 else 3761 else
3725 { 3762 {
3726 /* This is a list of face specs. Specifications at the 3763 /* This is a list of face refs. Those at the beginning of the
3727 beginning of the list take precedence over later 3764 list take precedence over what follows, so we have to merge
3728 specifications, so we have to merge starting with the 3765 from the end backwards. */
3729 last specification. */ 3766 Lisp_Object next = XCDR (face_ref);
3730 Lisp_Object next = XCDR (prop); 3767
3731 if (!NILP (next)) 3768 if (! NILP (next))
3732 merge_face_vector_with_property (f, to, next); 3769 ok = merge_face_ref (f, next, to, err_msgs, named_merge_points);
3733 merge_face_vector_with_property (f, to, first); 3770
3771 if (! merge_face_ref (f, first, to, err_msgs, named_merge_points))
3772 ok = 0;
3734 } 3773 }
3735 } 3774 }
3736 else 3775 else
3737 { 3776 {
3738 /* PROP ought to be a face name. */ 3777 /* FACE_REF ought to be a face name. */
3739 Lisp_Object lface = lface_from_face_name (f, prop, 0); 3778 ok = merge_named_face (f, face_ref, to, named_merge_points);
3740 if (NILP (lface)) 3779 if (!ok && err_msgs)
3741 add_to_log ("Invalid face text property value: %s", prop, Qnil); 3780 add_to_log ("Invalid face reference: %s", face_ref, Qnil);
3742 else
3743 merge_face_vectors (f, XVECTOR (lface)->contents, to, Qnil);
3744 } 3781 }
3782
3783 return ok;
3745} 3784}
3746 3785
3747 3786
@@ -5569,7 +5608,8 @@ lookup_named_face (f, symbol, c)
5569 5608
5570 get_lface_attributes (f, symbol, symbol_attrs, 1); 5609 get_lface_attributes (f, symbol, symbol_attrs, 1);
5571 bcopy (default_face->lface, attrs, sizeof attrs); 5610 bcopy (default_face->lface, attrs, sizeof attrs);
5572 merge_face_vectors (f, symbol_attrs, attrs, Qnil); 5611 merge_face_vectors (f, symbol_attrs, attrs, 0);
5612
5573 return lookup_face (f, attrs, c, NULL); 5613 return lookup_face (f, attrs, c, NULL);
5574} 5614}
5575 5615
@@ -5708,7 +5748,7 @@ lookup_derived_face (f, symbol, c, face_id)
5708 5748
5709 get_lface_attributes (f, symbol, symbol_attrs, 1); 5749 get_lface_attributes (f, symbol, symbol_attrs, 1);
5710 bcopy (default_face->lface, attrs, sizeof attrs); 5750 bcopy (default_face->lface, attrs, sizeof attrs);
5711 merge_face_vectors (f, symbol_attrs, attrs, Qnil); 5751 merge_face_vectors (f, symbol_attrs, attrs, 0);
5712 return lookup_face (f, attrs, c, default_face); 5752 return lookup_face (f, attrs, c, default_face);
5713} 5753}
5714 5754
@@ -5721,9 +5761,8 @@ DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector,
5721 Lisp_Object lface; 5761 Lisp_Object lface;
5722 lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE), 5762 lface = Fmake_vector (make_number (LFACE_VECTOR_SIZE),
5723 Qunspecified); 5763 Qunspecified);
5724 merge_face_vector_with_property (XFRAME (selected_frame), 5764 merge_face_ref (XFRAME (selected_frame), plist, XVECTOR (lface)->contents,
5725 XVECTOR (lface)->contents, 5765 1, 0);
5726 plist);
5727 return lface; 5766 return lface;
5728} 5767}
5729 5768
@@ -5802,7 +5841,7 @@ x_supports_face_attributes_p (f, attrs, def_face)
5802 5841
5803 bcopy (def_attrs, merged_attrs, sizeof merged_attrs); 5842 bcopy (def_attrs, merged_attrs, sizeof merged_attrs);
5804 5843
5805 merge_face_vectors (f, attrs, merged_attrs, Qnil); 5844 merge_face_vectors (f, attrs, merged_attrs, 0);
5806 5845
5807 face = FACE_FROM_ID (f, lookup_face (f, merged_attrs, 0, 0)); 5846 face = FACE_FROM_ID (f, lookup_face (f, merged_attrs, 0, 0));
5808 5847
@@ -6058,7 +6097,7 @@ face for italic. */)
6058 6097
6059 for (i = 0; i < LFACE_VECTOR_SIZE; i++) 6098 for (i = 0; i < LFACE_VECTOR_SIZE; i++)
6060 attrs[i] = Qunspecified; 6099 attrs[i] = Qunspecified;
6061 merge_face_vector_with_property (f, attrs, attributes); 6100 merge_face_ref (f, attributes, attrs, 1, 0);
6062 6101
6063 def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID); 6102 def_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
6064 if (def_face == NULL) 6103 if (def_face == NULL)
@@ -6934,7 +6973,7 @@ realize_named_face (f, symbol, id)
6934 6973
6935 /* Merge SYMBOL's face with the default face. */ 6974 /* Merge SYMBOL's face with the default face. */
6936 get_lface_attributes (f, symbol, symbol_attrs, 1); 6975 get_lface_attributes (f, symbol, symbol_attrs, 1);
6937 merge_face_vectors (f, symbol_attrs, attrs, Qnil); 6976 merge_face_vectors (f, symbol_attrs, attrs, 0);
6938 6977
6939 /* Realize the face. */ 6978 /* Realize the face. */
6940 new_face = realize_face (c, attrs, 0, NULL, id); 6979 new_face = realize_face (c, attrs, 0, NULL, id);
@@ -7399,7 +7438,7 @@ compute_char_face (f, ch, prop)
7399 Lisp_Object attrs[LFACE_VECTOR_SIZE]; 7438 Lisp_Object attrs[LFACE_VECTOR_SIZE];
7400 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID); 7439 struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID);
7401 bcopy (default_face->lface, attrs, sizeof attrs); 7440 bcopy (default_face->lface, attrs, sizeof attrs);
7402 merge_face_vector_with_property (f, attrs, prop); 7441 merge_face_ref (f, prop, attrs, 1, 0);
7403 face_id = lookup_face (f, attrs, ch, NULL); 7442 face_id = lookup_face (f, attrs, ch, NULL);
7404 } 7443 }
7405 7444
@@ -7485,7 +7524,7 @@ face_at_buffer_position (w, pos, region_beg, region_end,
7485 7524
7486 /* Merge in attributes specified via text properties. */ 7525 /* Merge in attributes specified via text properties. */
7487 if (!NILP (prop)) 7526 if (!NILP (prop))
7488 merge_face_vector_with_property (f, attrs, prop); 7527 merge_face_ref (f, prop, attrs, 1, 0);
7489 7528
7490 /* Now merge the overlay data. */ 7529 /* Now merge the overlay data. */
7491 noverlays = sort_overlays (overlay_vec, noverlays, w); 7530 noverlays = sort_overlays (overlay_vec, noverlays, w);
@@ -7496,7 +7535,7 @@ face_at_buffer_position (w, pos, region_beg, region_end,
7496 7535
7497 prop = Foverlay_get (overlay_vec[i], propname); 7536 prop = Foverlay_get (overlay_vec[i], propname);
7498 if (!NILP (prop)) 7537 if (!NILP (prop))
7499 merge_face_vector_with_property (f, attrs, prop); 7538 merge_face_ref (f, prop, attrs, 1, 0);
7500 7539
7501 oend = OVERLAY_END (overlay_vec[i]); 7540 oend = OVERLAY_END (overlay_vec[i]);
7502 oendpos = OVERLAY_POSITION (oend); 7541 oendpos = OVERLAY_POSITION (oend);
@@ -7507,8 +7546,7 @@ face_at_buffer_position (w, pos, region_beg, region_end,
7507 /* If in the region, merge in the region face. */ 7546 /* If in the region, merge in the region face. */
7508 if (pos >= region_beg && pos < region_end) 7547 if (pos >= region_beg && pos < region_end)
7509 { 7548 {
7510 Lisp_Object region_face = lface_from_face_name (f, Qregion, 0); 7549 merge_named_face (f, Qregion, attrs, 0);
7511 merge_face_vectors (f, XVECTOR (region_face)->contents, attrs, Qnil);
7512 7550
7513 if (region_end < endpos) 7551 if (region_end < endpos)
7514 endpos = region_end; 7552 endpos = region_end;
@@ -7604,16 +7642,13 @@ face_at_string_position (w, string, pos, bufpos, region_beg,
7604 7642
7605 /* Merge in attributes specified via text properties. */ 7643 /* Merge in attributes specified via text properties. */
7606 if (!NILP (prop)) 7644 if (!NILP (prop))
7607 merge_face_vector_with_property (f, attrs, prop); 7645 merge_face_ref (f, prop, attrs, 1, 0);
7608 7646
7609 /* If in the region, merge in the region face. */ 7647 /* If in the region, merge in the region face. */
7610 if (bufpos 7648 if (bufpos
7611 && bufpos >= region_beg 7649 && bufpos >= region_beg
7612 && bufpos < region_end) 7650 && bufpos < region_end)
7613 { 7651 merge_named_face (f, Qregion, attrs, 0);
7614 Lisp_Object region_face = lface_from_face_name (f, Qregion, 0);
7615 merge_face_vectors (f, XVECTOR (region_face)->contents, attrs, Qnil);
7616 }
7617 7652
7618 /* Look up a realized face with the given face attributes, 7653 /* Look up a realized face with the given face attributes,
7619 or realize a new one for ASCII characters. */ 7654 or realize a new one for ASCII characters. */