diff options
| author | Miles Bader | 2004-06-07 07:02:20 +0000 |
|---|---|---|
| committer | Miles Bader | 2004-06-07 07:02:20 +0000 |
| commit | a0a2334679b7278ca0577a733c8ba8d0362a1a38 (patch) | |
| tree | 6c55eff94f4f7d1c37cfe1fbeba367f443517904 /src | |
| parent | 12d5b1856c718a114ae75901ec34e0e9b16455c0 (diff) | |
| download | emacs-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/ChangeLog | 20 | ||||
| -rw-r--r-- | src/xfaces.c | 289 |
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 @@ | |||
| 1 | 2004-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 | |||
| 1 | 2004-06-07 Kenichi Handa <handa@m17n.org> | 21 | 2004-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 | ||
| 461 | struct font_name; | 461 | struct font_name; |
| 462 | struct table_entry; | 462 | struct table_entry; |
| 463 | struct named_merge_point; | ||
| 463 | 464 | ||
| 464 | static void map_tty_color P_ ((struct frame *, struct face *, | 465 | static 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)); | |||
| 518 | static int face_numeric_swidth P_ ((Lisp_Object)); | 519 | static int face_numeric_swidth P_ ((Lisp_Object)); |
| 519 | static int face_fontset P_ ((Lisp_Object *)); | 520 | static int face_fontset P_ ((Lisp_Object *)); |
| 520 | static char *choose_face_font P_ ((struct frame *, Lisp_Object *, int, int, int*)); | 521 | static char *choose_face_font P_ ((struct frame *, Lisp_Object *, int, int, int*)); |
| 521 | static void merge_face_vectors P_ ((struct frame *, Lisp_Object *, Lisp_Object*, Lisp_Object)); | 522 | static void merge_face_vectors P_ ((struct frame *, Lisp_Object *, Lisp_Object*, |
| 522 | static void merge_face_inheritance P_ ((struct frame *f, Lisp_Object, | 523 | struct named_merge_point *)); |
| 523 | Lisp_Object *, Lisp_Object)); | 524 | static int merge_face_ref P_ ((struct frame *, Lisp_Object, Lisp_Object *, |
| 524 | static void merge_face_vector_with_property P_ ((struct frame *, Lisp_Object *, | 525 | int, struct named_merge_point *)); |
| 525 | Lisp_Object)); | ||
| 526 | static int set_lface_from_font_name P_ ((struct frame *, Lisp_Object, | 526 | static int set_lface_from_font_name P_ ((struct frame *, Lisp_Object, |
| 527 | Lisp_Object, int, int)); | 527 | Lisp_Object, int, int)); |
| 528 | static Lisp_Object lface_from_face_name P_ ((struct frame *, Lisp_Object, int)); | 528 | static 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). */ | ||
| 3163 | struct 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 | |||
| 3175 | static INLINE int | ||
| 3176 | push_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 | ||
| 3438 | static INLINE void | 3484 | static INLINE void |
| 3439 | merge_face_vectors (f, from, to, cycle_check) | 3485 | merge_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 | ||
| 3488 | static void | 3534 | static int |
| 3489 | merge_face_inheritance (f, inherit, to, cycle_check) | 3535 | merge_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 | ||
| 3551 | static void | 3582 | static int |
| 3552 | merge_face_vector_with_property (f, to, prop) | 3583 | merge_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. */ |