From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Ergus via "Emacs development discussions." Newsgroups: gmane.emacs.devel Subject: Re: Question about display engine Date: Sun, 8 Sep 2019 02:51:10 +0200 Message-ID: <20190908005109.s7hhcczkrcbzewdc@Ergus> References: <318675867.1913640.1567711569517.ref@mail.yahoo.com> <318675867.1913640.1567711569517@mail.yahoo.com> <97f66744-8481-084a-ef23-2c50444e1f05@gmx.at> <20190906093117.25qfim4kcrmiqunk@Ergus> <83o8zw5zh8.fsf@gnu.org> <83mufg5yn1.fsf@gnu.org> Reply-To: Ergus Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="cufrroyz6lahogak" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="240462"; mail-complaints-to="usenet@blaine.gmane.org" User-Agent: NeoMutt/20180716 Cc: rudalics@gmx.at, emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sun Sep 08 02:51:45 2019 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1i6lQd-0010N5-Og for ged-emacs-devel@m.gmane.org; Sun, 08 Sep 2019 02:51:44 +0200 Original-Received: from localhost ([::1]:46454 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i6lQc-00053c-Md for ged-emacs-devel@m.gmane.org; Sat, 07 Sep 2019 20:51:42 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:47797) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1i6lQQ-00053O-Qn for emacs-devel@gnu.org; Sat, 07 Sep 2019 20:51:35 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1i6lQL-0002jO-Il for emacs-devel@gnu.org; Sat, 07 Sep 2019 20:51:30 -0400 Original-Received: from sonic309-26.consmr.mail.ir2.yahoo.com ([77.238.179.84]:46170) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1i6lQK-0002hm-U2 for emacs-devel@gnu.org; Sat, 07 Sep 2019 20:51:25 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aol.com; s=a2048; t=1567903883; bh=zORxs2r+UUzINZbp1sYRIizNYy7JBuEGn/nAahqT+R0=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From:Subject; b=r+0Pno6Q9Xn4VHQ1iCJq68bEjSGu4c4Mcv16JntKYx+Q01UI0CphtMKIkb8zqLqOhUC6Y0Z+KvXRmYFUw4DcaGRcQhCLz3wmWyGsCUIhloYewhTsRTc9Yh1aNUMHFqqMy10dv7CPIgvlD60idlKKx6F7qncQeAgO7faHMITQcmyfeuDatBZ5I65zDqRUj7Nledzn05dVWz95zbdZ7Pb2Derop9npYgTduDxOPwYCO5UrtF88XZfwBRVwaH5GqTc4oicz8X3dmrpJHyby/nIlHQiPtvQ5g3mZkFwKxZrWjZNU8/jGeymbZnBpqMSZiZk14EH5ovru3kfC7pyDqkq7Zg== X-YMail-OSG: h1jgsBsVM1n79LU55Cdx_OHObC34_t6ATm8koigh2D8QODtm6soL7UroSciKK1t eph.n52YrqntHkyZ3E.M_1GktuPYLfl9rGKaTpDUB5SpGoJY0_vayY6xh24XNproGgR4kiynn8JR yCw90GIUgA8iIdKytEwd2XgYC.3GuodFJmecwt8F_o4vwRY2ud37seasqvlwqiVNLPjK5ebY3H1Z 6FaaVBu8pO6tiuvMyeCvt4PADOf1WAOZH9N5tSjDgiQDU.yza74qyY5ei.SRLtVwazqorjT_OX.z C0ob2FGe7OWCzcWfvuEblWxuT1tladDp2hMudZ9X9bvD2FUipNrpvgVaYXPTnIDFwSDINiNVHfAp 7JUJ5PBwRWCTejuOuviP23BjAFZjf0y5mAN47Ozc0CJX6yHMUW1veVdRG_jfSvkANqlS2iH1qoBi xmSwiTRqJc28N7IQ4mGI9lDjmZCH0GRDH4n5PnRV1xjrs5yddXKePTAILPDmd7P1_w4gt0f27Nz. S7T8Xd.CIPBDFsKEffOY2NKY6WmJMi6vgXE78tXspE_DKHP_iuNEEJdxFge36GrpTR1AET1bUIoM XFUyne.KIU79S26OCL9KSW.sgc8WUwTBgY0qpnkeUHyy6WD8NyVT8S_vOBRKpZB05xPaBfRs2NxQ dsULEgSAvud96ONafM3YeRIC7KB62nCAzeYAp6G3UIvb.w5sCGYIP89sxBBP7YSxXPVeo5Mguie2 r4dZcEH10Uwk0RswiYq2tSV2FIpTMsZq3fU39xQcmcurH4a4NAR5lyzIsYfSoh5FgrvQqePDBu2q Za_ei_oFkhtlgKuHNp1uLuTug1QWXrTu4nIfYJiuUl Original-Received: from sonic.gate.mail.ne1.yahoo.com by sonic309.consmr.mail.ir2.yahoo.com with HTTP; Sun, 8 Sep 2019 00:51:23 +0000 Original-Received: by smtp419.mail.ir2.yahoo.com (Oath Hermes SMTP Server) with ESMTPA ID 2c78f4146581504d17ff74558e7401d1; Sun, 08 Sep 2019 00:51:18 +0000 (UTC) Content-Disposition: inline In-Reply-To: <83mufg5yn1.fsf@gnu.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 77.238.179.84 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:239933 Archived-At: --cufrroyz6lahogak Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline Hi Eli and Martin: Please give a look to the attached patch and check if it is working fine for you. (I added a new branch "extend_face_id" in savannah too) I tried to make it as optimized and less changes as possible from the beginning. In general I added a parameter to handle_face_prop renamed to handle_face_prop_general (keeping the original name as a wrapper with the same signature.) And the extra parameter is an enum lface_attribute_index. The parameter is passed from function to function until merge_named_face which checks: (attr_filter == 0 || (!NILP (from[attr_filter]) && !UNSPECIFIEDP (from[attr_filter]))) So if we pass zero as the parameter then the merge is unconditional; else the attribute needs to be non-nil and specified to merge. I made it in this way because it is general enough and with low overhead in case we want to condition the merge for different conditions in the future. Right now only region is extensible by default. So you can try with region and hl-line-mode for example. I added also the commands to change extensibility set-face-extend and the internal lisp commands to get/set extend as usual. Now the only annoying thing is that when extend is disabled for the region, the extra space after eol has the same face than the text before (which for me is fine) but in the terminal it is not added... so I should ask if you consider correct to add the space in terminal or remove the extra "colored" space in gui? I vote for the first... but you say. (I made some changes in the extend_face_to_end_of_line code related with fill column indicator to reuse part of the code and avoid unneeded duplication. On Sat, Sep 07, 2019 at 10:55:14AM +0300, Eli Zaretskii wrote: >> Date: Sat, 07 Sep 2019 10:37:07 +0300 >> From: Eli Zaretskii >> Cc: spacibba@aol.com, emacs-devel@gnu.org >> >> The default face should always be merged into the face used for line >> extension, that goes without saying. > >IOW, the default face should always be treated as having the :extend >attribute by default. > --cufrroyz6lahogak Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="test.patch" diff --git a/lisp/cus-face.el b/lisp/cus-face.el index d73bce42c3..5a49a81043 100644 --- a/lisp/cus-face.el +++ b/lisp/cus-face.el @@ -233,7 +233,11 @@ custom-face-attributes (file :tag "File" :help-echo "Name of bitmap file." :must-match t))) - + (:extend + (choice :tag "Extend" + :help-echo "Control whether attributes should be extended after EOL." + (const :tag "Off" nil) + (const :tag "On" t))) (:inherit (repeat :tag "Inherit" :help-echo "List of faces to inherit attributes from." diff --git a/lisp/faces.el b/lisp/faces.el index 5193c216d0..814a4b2c9a 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -342,6 +342,7 @@ face-x-resources (:box (".attributeBox" . "Face.AttributeBox")) (:underline (".attributeUnderline" . "Face.AttributeUnderline")) (:inverse-video (".attributeInverse" . "Face.AttributeInverse")) + (:extend (".attributeExtend" . "Face.AttributeExtend")) (:stipple (".attributeStipple" . "Face.AttributeStipple") (".attributeBackgroundPixmap" . "Face.AttributeBackgroundPixmap")) @@ -594,6 +595,13 @@ face-italic-p (let ((italic (face-attribute face :slant frame inherit))) (memq italic '(italic oblique)))) +(defun face-extend-p (face &optional frame inherit) + "Return non-nil if FACE specifies a non-nil extend. +If the optional argument FRAME is given, report on face FACE in that frame. +If FRAME is t, report on the defaults for face FACE (for new frames). +If FRAME is omitted or nil, use the selected frame. +Optional argument INHERIT is passed to `face-attribute'." + (eq (face-attribute face :extend frame inherit) t)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -760,6 +768,11 @@ set-face-attribute `:height', `:weight', and `:slant' may also be set in one step from an X font name: +`:extend' + +VALUE specifies whether the FACE should be extended after EOL. +VALUE must be one of t or nil. + `:font' Set font-related face attributes from VALUE. @@ -979,6 +992,18 @@ set-face-italic (define-obsolete-function-alias 'set-face-italic-p 'set-face-italic "24.4") +(defun set-face-extend (face extend-p &optional frame) + "Specify whether face FACE should be extended. +EXTEND-P nil means FACE explicitly doesn't extend after EOL. +EXTEND-P t means FACE extends after EOL. + +FRAME nil or not specified means change face on all frames. +Use `set-face-attribute' to \"unspecify\" underlining." + (interactive + (let ((list (read-face-and-attribute :extend))) + (list (car list) (if (cadr list) t)))) + (set-face-attribute face frame :extend extend-p)) + (defalias 'set-face-background-pixmap 'set-face-stipple) @@ -1102,7 +1127,7 @@ face-valid-attribute-values (:slant (mapcar #'(lambda (x) (cons (symbol-name (aref x 1)) (aref x 1))) font-slant-table)) - (:inverse-video + ((or :inverse-video :extend) (mapcar #'(lambda (x) (cons (symbol-name x) x)) (internal-lisp-face-attribute-values attribute))) ((or :underline :overline :strike-through :box) @@ -1147,6 +1172,7 @@ face-attribute-name-alist (:slant . "slant") (:underline . "underline") (:overline . "overline") + (:extend . "extend") (:strike-through . "strike-through") (:box . "box") (:inverse-video . "inverse-video display") @@ -1448,6 +1474,7 @@ describe-face (:stipple . "Stipple") (:font . "Font") (:fontset . "Fontset") + (:extend . "Extend") (:inherit . "Inherit"))) (max-width (apply #'max (mapcar #'(lambda (x) (length (cdr x))) attrs)))) @@ -1667,7 +1694,8 @@ face-spec-reset-face ;; (see also realize_default_face in xfaces.c). (append '(:underline nil :overline nil :strike-through nil - :box nil :inverse-video nil :stipple nil :inherit nil) + :box nil :inverse-video nil :stipple nil :inherit nil + :extend nil) ;; `display-graphic-p' is unavailable when running ;; temacs, prior to loading frame.el. (when (fboundp 'display-graphic-p) @@ -2432,24 +2460,24 @@ highlight ;; if background is light. (defface region '((((class color) (min-colors 88) (background dark)) - :background "blue3") + :background "blue3" :extend t) (((class color) (min-colors 88) (background light) (type gtk)) :distant-foreground "gtk_selection_fg_color" - :background "gtk_selection_bg_color") + :background "gtk_selection_bg_color" :extend t) (((class color) (min-colors 88) (background light) (type ns)) :distant-foreground "ns_selection_fg_color" - :background "ns_selection_bg_color") + :background "ns_selection_bg_color" :extend t) (((class color) (min-colors 88) (background light)) - :background "lightgoldenrod2") + :background "lightgoldenrod2" :extend t) (((class color) (min-colors 16) (background dark)) - :background "blue3") + :background "blue3" :extend t) (((class color) (min-colors 16) (background light)) - :background "lightgoldenrod2") + :background "lightgoldenrod2" :extend t) (((class color) (min-colors 8)) - :background "blue" :foreground "white") + :background "blue" :foreground "white" :extend t) (((type tty) (class mono)) :inverse-video t) - (t :background "gray")) + (t :background "gray" :extend t)) "Basic face for highlighting the region." :version "21.1" :group 'basic-faces) diff --git a/src/dispextern.h b/src/dispextern.h index 05f199ff35..de438e069e 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -1564,6 +1564,7 @@ #define FONT_TOO_HIGH(ft) \ LFACE_INHERIT_INDEX, LFACE_FONTSET_INDEX, LFACE_DISTANT_FOREGROUND_INDEX, + LFACE_EXTEND_INDEX, LFACE_VECTOR_SIZE }; @@ -1589,6 +1590,7 @@ #define FONT_TOO_HIGH(ft) \ enum face_underline_type { + FACE_NO_UNDERLINE = 0, FACE_UNDER_LINE, FACE_UNDER_WAVE }; @@ -1632,11 +1634,9 @@ #define FONT_TOO_HIGH(ft) \ /* Pixel value or color index of background color. */ unsigned long background; - /* Pixel value or color index of underline color. */ + /* Pixel value or color index of underline, overlined, + strike-through, or box color. */ unsigned long underline_color; - - /* Pixel value or color index of overlined, strike-through, or box - color. */ unsigned long overline_color; unsigned long strike_through_color; unsigned long box_color; @@ -1663,7 +1663,7 @@ #define FONT_TOO_HIGH(ft) \ ENUM_BF (face_box_type) box : 2; /* Style of underlining. */ - ENUM_BF (face_underline_type) underline_type : 1; + ENUM_BF (face_underline_type) underline : 2; /* If `box' above specifies a 3D type, true means use box_color for drawing shadows. */ @@ -1671,7 +1671,6 @@ #define FONT_TOO_HIGH(ft) \ /* Non-zero if text in this face should be underlined, overlined, strike-through or have a box drawn around it. */ - bool_bf underline_p : 1; bool_bf overline_p : 1; bool_bf strike_through_p : 1; @@ -1681,14 +1680,10 @@ #define FONT_TOO_HIGH(ft) \ bool_bf foreground_defaulted_p : 1; bool_bf background_defaulted_p : 1; - /* True means that either no color is specified for underlining or that - the specified color couldn't be loaded. Use the foreground - color when drawing in that case. */ - bool_bf underline_defaulted_p : 1; - /* True means that either no color is specified for the corresponding attribute or that the specified color couldn't be loaded. Use the foreground color when drawing in that case. */ + bool_bf underline_defaulted_p : 1; bool_bf overline_color_defaulted_p : 1; bool_bf strike_through_color_defaulted_p : 1; bool_bf box_color_defaulted_p : 1; @@ -1822,6 +1817,9 @@ #define FACE_FROM_ID_OR_NULL(F, ID) \ ? FRAME_FACE_CACHE (F)->faces_by_id[ID] \ : NULL) +#define FACE_EXTENSIBLE_P(F) \ + (!NILP (F->lface[LFACE_EXTEND_INDEX])) + /* True if FACE is suitable for displaying ASCII characters. */ INLINE bool FACE_SUITABLE_FOR_ASCII_CHAR_P (struct face *face) @@ -2328,7 +2326,7 @@ #define IT_STACK_SIZE 5 /* Face id of the iterator saved in case a glyph from dpvec contains a face. The face is restored when all glyphs from dpvec have been delivered. */ - int saved_face_id; + int saved_face_id, saved_extend_face_id; /* Vector of glyphs for control character translation. The pointer dpvec is set to ctl_chars when a control character is translated. @@ -2390,7 +2388,7 @@ #define OVERLAY_STRING_CHUNK_SIZE 16 ptrdiff_t prev_stop; ptrdiff_t base_level_stop; struct composition_it cmp_it; - int face_id; + int face_id, extend_face_id; /* Save values specific to a given method. */ union { @@ -2448,6 +2446,9 @@ #define OVERLAY_STRING_CHUNK_SIZE 16 /* Face to use. */ int face_id; + /* Face to extend at EOL/ */ + int extend_face_id; + /* Setting of buffer-local variable selective-display-ellipses. */ bool_bf selective_display_ellipsis_p : 1; @@ -3458,8 +3459,8 @@ #define RGB_PIXEL_COLOR COLORREF void init_frame_faces (struct frame *); void free_frame_faces (struct frame *); void recompute_basic_faces (struct frame *); -int face_at_buffer_position (struct window *, ptrdiff_t, ptrdiff_t *, ptrdiff_t, - bool, int); +int face_at_buffer_position (struct window *, ptrdiff_t, ptrdiff_t *, + ptrdiff_t, bool, int, enum lface_attribute_index); int face_for_overlay_string (struct window *, ptrdiff_t, ptrdiff_t *, ptrdiff_t, bool, Lisp_Object); int face_at_string_position (struct window *, Lisp_Object, ptrdiff_t, ptrdiff_t, diff --git a/src/font.c b/src/font.c index 935dd64e64..2b16839bba 100644 --- a/src/font.c +++ b/src/font.c @@ -3781,10 +3781,10 @@ font_at (int c, ptrdiff_t pos, struct face *face, struct window *w, if (STRINGP (string)) face_id = face_at_string_position (w, string, pos, 0, &endptr, - DEFAULT_FACE_ID, false); + DEFAULT_FACE_ID, 0); else face_id = face_at_buffer_position (w, pos, &endptr, - pos + 100, false, -1); + pos + 100, false, -1, 0); face = FACE_FROM_ID (f, face_id); } if (multibyte) @@ -3828,7 +3828,7 @@ font_range (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t *limit, if (NILP (string)) face_id = face_at_buffer_position (w, pos, &ignore, *limit, - false, -1); + false, -1, 0); else { face_id = @@ -4614,7 +4614,7 @@ DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 2, 0, w = XWINDOW (window); f = XFRAME (w->frame); face_id = face_at_buffer_position (w, pos, &dummy, - pos + 100, false, -1); + pos + 100, false, -1, 0); } if (! CHAR_VALID_P (c)) return Qnil; diff --git a/src/nsterm.m b/src/nsterm.m index 42ef4dd010..99b621533a 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -3404,9 +3404,9 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. return; /* Do underline. */ - if (face->underline_p) + if (face->underline) { - if (s->face->underline_type == FACE_UNDER_WAVE) + if (s->face->underline == FACE_UNDER_WAVE) { if (face->underline_defaulted_p) [defaultCol set]; @@ -3415,15 +3415,15 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. ns_draw_underwave (s, width, x); } - else if (s->face->underline_type == FACE_UNDER_LINE) + else if (s->face->underline == FACE_UNDER_LINE) { NSRect r; unsigned long thickness, position; /* If the prev was underlined, match its appearance. */ - if (s->prev && s->prev->face->underline_p - && s->prev->face->underline_type == FACE_UNDER_LINE + if (s->prev + && s->prev->face->underline == FACE_UNDER_LINE && s->prev->underline_thickness > 0) { thickness = s->prev->underline_thickness; diff --git a/src/w32term.c b/src/w32term.c index e5874f2d36..99a1db5784 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -2479,9 +2479,9 @@ w32_draw_glyph_string (struct glyph_string *s) if (!s->for_overlaps) { /* Draw underline. */ - if (s->face->underline_p) + if (s->face->underline) { - if (s->face->underline_type == FACE_UNDER_WAVE) + if (s->face->underline == FACE_UNDER_WAVE) { COLORREF color; @@ -2492,13 +2492,13 @@ w32_draw_glyph_string (struct glyph_string *s) w32_draw_underwave (s, color); } - else if (s->face->underline_type == FACE_UNDER_LINE) + else if (s->face->underline == FACE_UNDER_LINE) { unsigned long thickness, position; int y; - if (s->prev && s->prev->face->underline_p - && s->prev->face->underline_type == FACE_UNDER_LINE) + if (s->prev + && s->prev->face->underline == FACE_UNDER_LINE) { /* We use the same underline style as the previous one. */ thickness = s->prev->underline_thickness; @@ -2512,7 +2512,7 @@ w32_draw_glyph_string (struct glyph_string *s) BOOL use_underline_position_properties; Lisp_Object val = buffer_local_value (Qunderline_minimum_offset, - s->w->contents); + s->w->contents); if (FIXNUMP (val)) minimum_offset = max (0, XFIXNUM (val)); else diff --git a/src/xdisp.c b/src/xdisp.c index 94f969f37c..9fb4f6be58 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -4105,15 +4105,18 @@ handle_fontified_prop (struct it *it) Faces ***********************************************************************/ -/* Set up iterator IT from face properties at its current position. - Called from handle_stop. */ - static enum prop_handled -handle_face_prop (struct it *it) +handle_face_prop_general (struct it *it, + enum lface_attribute_index attr_filter) { - int new_face_id; + int new_face_id, *face_id_ptr; ptrdiff_t next_stop; + if (attr_filter == LFACE_EXTEND_INDEX) + face_id_ptr = &(it->extend_face_id); + else + face_id_ptr = &(it->face_id); + if (!STRINGP (it->string)) { new_face_id @@ -4122,7 +4125,7 @@ handle_face_prop (struct it *it) &next_stop, (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT), - false, it->base_face_id); + false, it->base_face_id, attr_filter); /* Is this a start of a run of characters with box face? Caveat: this can be called for a freshly initialized @@ -4130,13 +4133,13 @@ handle_face_prop (struct it *it) face will not change until limit, i.e. if the new face has a box, all characters up to limit will have one. But, as usual, we don't know whether limit is really the end. */ - if (new_face_id != it->face_id) + if (new_face_id != *face_id_ptr) { struct face *new_face = FACE_FROM_ID (it->f, new_face_id); /* If it->face_id is -1, old_face below will be NULL, see the definition of FACE_FROM_ID_OR_NULL. This will happen if this is the initial call that gets the face. */ - struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id); + struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, *face_id_ptr); /* If the value of face_id of the iterator is -1, we have to look in front of IT's position and see whether there is a @@ -4242,10 +4245,10 @@ handle_face_prop (struct it *it) box, all characters up to that position will have a box. But, as usual, we don't know whether that position is really the end. */ - if (new_face_id != it->face_id) + if (new_face_id != *face_id_ptr) { struct face *new_face = FACE_FROM_ID (it->f, new_face_id); - struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id); + struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, *face_id_ptr); /* If new face has a box but old face hasn't, this is the start of a run of characters with box, i.e. it has a @@ -4256,11 +4259,21 @@ handle_face_prop (struct it *it) } } - it->face_id = new_face_id; + *face_id_ptr = new_face_id; return HANDLED_NORMALLY; } +/* Set up iterator IT from face properties at its current position. + Called from handle_stop. */ + +static enum prop_handled +handle_face_prop (struct it *it) +{ + return handle_face_prop_general (it, 0); +} + + /* Return the ID of the face ``underlying'' IT's current position, which is in a string. If the iterator is associated with a buffer, return the face at IT's current buffer position. @@ -4474,7 +4487,7 @@ face_before_or_after_it_pos (struct it *it, bool before_p) face_id = face_at_buffer_position (it->w, CHARPOS (pos), &next_check_charpos, - limit, false, -1); + limit, false, -1, 0); /* Correct the face for charsets different from ASCII. Do it for the multibyte case only. The face returned above is @@ -7596,10 +7609,11 @@ get_next_display_element (struct it *it) else { next_face_id = - face_at_buffer_position (it->w, CHARPOS (pos), &ignore, + face_at_buffer_position (it->w, CHARPOS (pos), + &ignore, CHARPOS (pos) + TEXT_PROP_DISTANCE_LIMIT, - false, -1); + false, -1, 0); it->end_of_box_run_p = (FACE_FROM_ID (it->f, next_face_id)->box == FACE_NO_BOX); @@ -20482,12 +20496,14 @@ extend_face_to_end_of_line (struct it *it) || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)) return; - /* Face extension extends the background and box of IT->face_id + handle_face_prop_general (it, LFACE_EXTEND_INDEX); + + /* Face extension extends the background and box of IT->extend_face_id to the end of the line. If the background equals the background of the frame, we don't have to do anything. */ face = FACE_FROM_ID (f, (it->face_before_selective_p ? it->saved_face_id - : it->face_id)); + : it->extend_face_id)); if (FRAME_WINDOW_P (f) && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row) @@ -20510,9 +20526,7 @@ extend_face_to_end_of_line (struct it *it) that the character will always be single byte in unibyte text. */ if (!ASCII_CHAR_P (it->c)) - { it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil); - } /* The default face, possibly remapped. */ struct face *default_face = @@ -20561,79 +20575,86 @@ extend_face_to_end_of_line (struct it *it) /* Display fill column indicator if not in modeline or toolbar and display fill column indicator mode is active. */ - int indicator_column = (it->w->pseudo_window_p == 0 + const int indicator_column = (it->w->pseudo_window_p == 0 ? fill_column_indicator_column (it) : -1); - if (indicator_column >= 0) + + struct font *font = (default_face->font + ? default_face->font + : FRAME_FONT (f)); + + const int char_width = (font->average_width + ? font->average_width + : font->space_width); + int column_x; + + const char saved_char = it->char_to_display; + const struct text_pos saved_pos = it->position; + const bool saved_avoid_cursor = it->avoid_cursor_p; + const bool saved_box_start = it->start_of_box_run_p; + Lisp_Object save_object = it->object; + const int saved_face_id = it->face_id; + + it->face_id = it->extend_face_id; + + if (indicator_column >= 0 + && !INT_MULTIPLY_WRAPV (indicator_column, char_width, &column_x) + && !INT_ADD_WRAPV (it->lnum_pixel_width, column_x, &column_x) + && column_x >= it->current_x + && column_x <= it->last_visible_x) { - struct font *font = (default_face->font - ? default_face->font - : FRAME_FONT (f)); - const int char_width = (font->average_width - ? font->average_width - : font->space_width); - int column_x; - - if (!INT_MULTIPLY_WRAPV (indicator_column, char_width, &column_x) - && !INT_ADD_WRAPV (it->lnum_pixel_width, column_x, &column_x) - && column_x >= it->current_x - && column_x <= it->last_visible_x) - { - const char saved_char = it->char_to_display; - const struct text_pos saved_pos = it->position; - const bool saved_avoid_cursor = it->avoid_cursor_p; - const int saved_face_id = it->face_id; - const bool saved_box_start = it->start_of_box_run_p; - Lisp_Object save_object = it->object; - - /* The stretch width needs to considet the latter - added glyph. */ - const int stretch_width - = column_x - it->current_x - char_width; - - memset (&it->position, 0, sizeof it->position); - it->avoid_cursor_p = true; - it->object = Qnil; - - /* Only generate a stretch glyph if there is distance - between current_x and and the indicator position. */ - if (stretch_width > 0) - { - int stretch_ascent = (((it->ascent + it->descent) - * FONT_BASE (font)) / FONT_HEIGHT (font)); - append_stretch_glyph (it, Qnil, stretch_width, - it->ascent + it->descent, - stretch_ascent); - } - /* Generate the glyph indicator only if - append_space_for_newline didn't already. */ - if (it->current_x < column_x) - { - it->char_to_display - = XFIXNAT (Vdisplay_fill_column_indicator_character); - it->face_id - = merge_faces (it->w, Qfill_column_indicator, - 0, saved_face_id); - PRODUCE_GLYPHS (it); - } - - /* Restore the face after the indicator was generated. */ - it->face_id = saved_face_id; - - /* If there is space after the indicator generate an - extra empty glyph to restore the face. Issue was - observed in X systems. */ - it->char_to_display = ' '; - PRODUCE_GLYPHS (it); - - it->char_to_display = saved_char; - it->position = saved_pos; - it->avoid_cursor_p = saved_avoid_cursor; - it->start_of_box_run_p = saved_box_start; - it->object = save_object; - } + /* The stretch width needs to considet the latter + added glyph. */ + const int stretch_width + = column_x - it->current_x - char_width; + + memset (&it->position, 0, sizeof it->position); + it->avoid_cursor_p = true; + it->object = Qnil; + + /* Only generate a stretch glyph if there is distance + between current_x and and the indicator position. */ + if (stretch_width > 0) + { + int stretch_ascent = (((it->ascent + it->descent) + * FONT_BASE (font)) / FONT_HEIGHT (font)); + append_stretch_glyph (it, Qnil, stretch_width, + it->ascent + it->descent, + stretch_ascent); + } + + /* Generate the glyph indicator only if + append_space_for_newline didn't already. */ + if (it->current_x < column_x) + { + const int save_face_id = it->face_id; + it->char_to_display + = XFIXNAT (Vdisplay_fill_column_indicator_character); + it->face_id + = merge_faces (it->w, Qfill_column_indicator, + 0, it->extend_face_id); + PRODUCE_GLYPHS (it); + it->face_id = save_face_id; + + } } + + /* Restore the face after the indicator was generated. */ + + /* If there is space after the indicator generate an + extra empty glyph to restore the face. Issue was + observed in X systems. */ + it->char_to_display = ' '; + PRODUCE_GLYPHS (it); + + it->char_to_display = saved_char; + it->position = saved_pos; + it->avoid_cursor_p = saved_avoid_cursor; + it->start_of_box_run_p = saved_box_start; + it->object = save_object; + it->face_id = saved_face_id; + } if (it->glyph_row->reversed_p) { @@ -20679,10 +20700,9 @@ extend_face_to_end_of_line (struct it *it) /* The last row's stretch glyph should get the default face, to avoid painting the rest of the window with the region face, if the region ends at ZV. */ - if (it->glyph_row->ends_at_zv_p) - it->face_id = default_face->id; - else - it->face_id = face->id; + it->face_id = (it->glyph_row->ends_at_zv_p ? + default_face->id : face->id); + it->start_of_box_run_p = false; append_stretch_glyph (it, Qnil, stretch_width, it->ascent + it->descent, stretch_ascent); @@ -20704,14 +20724,11 @@ extend_face_to_end_of_line (struct it *it) { /* Save some values that must not be changed. */ int saved_x = it->current_x; - struct text_pos saved_pos; - Lisp_Object saved_object; + struct text_pos saved_pos = it->position; + Lisp_Object saved_object = it->object;; enum display_element_type saved_what = it->what; int saved_face_id = it->face_id; - saved_object = it->object; - saved_pos = it->position; - it->what = IT_CHARACTER; memset (&it->position, 0, sizeof it->position); it->object = Qnil; @@ -20750,10 +20767,8 @@ extend_face_to_end_of_line (struct it *it) /* The last row's blank glyphs should get the default face, to avoid painting the rest of the window with the region face, if the region ends at ZV. */ - if (it->glyph_row->ends_at_zv_p) - it->face_id = default_face->id; - else - it->face_id = face->id; + it->face_id = (it->glyph_row->ends_at_zv_p ? + default_face->id : face->id); /* Display fill-column indicator if needed. */ int indicator_column = fill_column_indicator_column (it); @@ -20763,24 +20778,21 @@ extend_face_to_end_of_line (struct it *it) indicator_column = -1; do { - int saved_face_id; - bool indicate = it->current_x == indicator_column; - if (indicate) + if (it->current_x == indicator_column) { - saved_face_id = it->face_id; + int saved_face_id = it->face_id; it->face_id - = merge_faces (it->w, Qfill_column_indicator, 0, saved_face_id); + = merge_faces (it->w, Qfill_column_indicator, 0, it->extend_face_id); it->c = it->char_to_display = XFIXNAT (Vdisplay_fill_column_indicator_character); - } - PRODUCE_GLYPHS (it); + PRODUCE_GLYPHS (it); - if (indicate) - { it->face_id = saved_face_id; it->c = it->char_to_display = ' '; } + else + PRODUCE_GLYPHS (it); } while (it->current_x <= it->last_visible_x); @@ -27355,7 +27367,7 @@ font_for_underline_metrics (struct glyph_string *s) for (g = s->first_glyph - 1; g >= g0; g--) { struct face *prev_face = FACE_FROM_ID (s->f, g->face_id); - if (!(prev_face && prev_face->underline_p)) + if (!(prev_face && prev_face->underline != FACE_NO_UNDERLINE)) break; } @@ -30919,7 +30931,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, hlinfo->mouse_face_face_id = face_at_buffer_position (w, mouse_charpos, &ignore, mouse_charpos + 1, - !hlinfo->mouse_face_hidden, -1); + !hlinfo->mouse_face_hidden, -1, 0); show_mouse_face (hlinfo, DRAW_MOUSE_FACE); } diff --git a/src/xfaces.c b/src/xfaces.c index c3cae7e2a6..7c5a0858bb 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -347,7 +347,8 @@ #define CLEAR_FONT_TABLE_NFONTS 10 static void free_face_cache (struct face_cache *); static bool merge_face_ref (struct window *w, struct frame *, Lisp_Object, Lisp_Object *, - bool, struct named_merge_point *); + bool, struct named_merge_point *, + enum lface_attribute_index); static int color_distance (Emacs_Color *x, Emacs_Color *y); #ifdef HAVE_WINDOW_SYSTEM @@ -1209,7 +1210,7 @@ free_face_colors (struct frame *f, struct face *face) IF_DEBUG (--ncolors_allocated); } - if (face->underline_p + if (face->underline && !face->underline_defaulted_p) { x_free_colors (f, &face->underline_color, 1); @@ -1590,6 +1591,7 @@ #define LFACE_BOX(LFACE) AREF ((LFACE), LFACE_BOX_INDEX) #define LFACE_FONT(LFACE) AREF ((LFACE), LFACE_FONT_INDEX) #define LFACE_INHERIT(LFACE) AREF ((LFACE), LFACE_INHERIT_INDEX) #define LFACE_FONTSET(LFACE) AREF ((LFACE), LFACE_FONTSET_INDEX) +#define LFACE_EXTEND(LFACE) AREF ((LFACE), LFACE_EXTEND_INDEX) #define LFACE_DISTANT_FOREGROUND(LFACE) \ AREF ((LFACE), LFACE_DISTANT_FOREGROUND_INDEX) @@ -1633,6 +1635,10 @@ check_lface_attrs (Lisp_Object attrs[LFACE_VECTOR_SIZE]) || SYMBOLP (attrs[LFACE_UNDERLINE_INDEX]) || STRINGP (attrs[LFACE_UNDERLINE_INDEX]) || CONSP (attrs[LFACE_UNDERLINE_INDEX])); + eassert (UNSPECIFIEDP (attrs[LFACE_EXTEND_INDEX]) + || IGNORE_DEFFACE_P (attrs[LFACE_EXTEND_INDEX]) + || SYMBOLP (attrs[LFACE_EXTEND_INDEX]) + || STRINGP (attrs[LFACE_EXTEND_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_OVERLINE_INDEX]) || SYMBOLP (attrs[LFACE_OVERLINE_INDEX]) @@ -1905,7 +1911,8 @@ get_lface_attributes (struct window *w, attrs[i] = Qunspecified; return merge_face_ref (w, f, XCDR (face_remapping), attrs, - signal_p, named_merge_points); + signal_p, named_merge_points, + 0); } } @@ -2060,7 +2067,8 @@ merge_face_vectors (struct window *w, if (!UNSPECIFIEDP (from[LFACE_INHERIT_INDEX]) && !NILP (from[LFACE_INHERIT_INDEX])) merge_face_ref (w, f, from[LFACE_INHERIT_INDEX], - to, false, named_merge_points); + to, false, named_merge_points, + 0); if (FONT_SPEC_P (from[LFACE_FONT_INDEX])) { @@ -2126,7 +2134,8 @@ merge_face_vectors (struct window *w, static bool merge_named_face (struct window *w, struct frame *f, Lisp_Object face_name, Lisp_Object *to, - struct named_merge_point *named_merge_points) + struct named_merge_point *named_merge_points, + enum lface_attribute_index attr_filter) { struct named_merge_point named_merge_point; @@ -2136,9 +2145,13 @@ merge_named_face (struct window *w, { Lisp_Object from[LFACE_VECTOR_SIZE]; bool ok = get_lface_attributes (w, f, face_name, from, false, - named_merge_points); + named_merge_points); - if (ok) + eassert (attr_filter < LFACE_VECTOR_SIZE); + + if (ok && (attr_filter == 0 + || (!NILP (from[attr_filter]) + && !UNSPECIFIEDP (from[attr_filter])))) merge_face_vectors (w, f, from, to, named_merge_points); return ok; @@ -2269,6 +2282,11 @@ filter_face_ref (Lisp_Object face_ref, of ERR_MSGS). Use NAMED_MERGE_POINTS to detect loops in face inheritance or list structure; it may be 0 for most callers. + attr_filter is the index of a parameter that conditions the merging + for named faces (case 1) to only the face_ref where + lface[merge_face_ref] is non-nil. To merge unconditionally set this + value to 0. + FACE_REF may be a single face specification or a list of such specifications. Each face specification can be: @@ -2297,7 +2315,8 @@ filter_face_ref (Lisp_Object face_ref, static bool merge_face_ref (struct window *w, struct frame *f, Lisp_Object face_ref, Lisp_Object *to, - bool err_msgs, struct named_merge_point *named_merge_points) + bool err_msgs, struct named_merge_point *named_merge_points, + enum lface_attribute_index attr_filter) { bool ok = true; /* Succeed without an error? */ Lisp_Object filtered_face_ref; @@ -2509,7 +2528,15 @@ merge_face_ref (struct window *w, /* This is not really very useful; it's just like a normal face reference. */ if (! merge_face_ref (w, f, value, to, - err_msgs, named_merge_points)) + err_msgs, named_merge_points, + 0)) + err = true; + } + else if (EQ (keyword, QCextend)) + { + if (EQ (value, Qt) || NILP (value)) + to[LFACE_EXTEND_INDEX] = value; + else err = true; } else @@ -2532,16 +2559,19 @@ merge_face_ref (struct window *w, Lisp_Object next = XCDR (face_ref); if (! NILP (next)) - ok = merge_face_ref (w, f, next, to, err_msgs, named_merge_points); + ok = merge_face_ref (w, f, next, to, err_msgs, + named_merge_points, 0); - if (! merge_face_ref (w, f, first, to, err_msgs, named_merge_points)) + if (! merge_face_ref (w, f, first, to, err_msgs, + named_merge_points, 0)) ok = false; } } else { /* FACE_REF ought to be a face name. */ - ok = merge_named_face (w, f, face_ref, to, named_merge_points); + ok = merge_named_face (w, f, face_ref, to, named_merge_points, + attr_filter); if (!ok && err_msgs) add_to_log ("Invalid face reference: %s", face_ref); } @@ -3030,6 +3060,17 @@ DEFUN ("internal-set-lisp-face-attribute", Finternal_set_lisp_face_attribute, old_value = LFACE_INVERSE (lface); ASET (lface, LFACE_INVERSE_INDEX, value); } + else if (EQ (attr, QCextend)) + { + if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + { + CHECK_SYMBOL (value); + if (!EQ (value, Qt) && !NILP (value)) + signal_error ("Invalid extend face attribute value", value); + } + old_value = LFACE_EXTEND (lface); + ASET (lface, LFACE_EXTEND_INDEX, value); + } else if (EQ (attr, QCforeground)) { /* Compatibility with 20.x. */ @@ -3503,7 +3544,9 @@ DEFUN ("internal-set-lisp-face-attribute-from-resource", value = face_boolean_x_resource_value (value, true); else if (EQ (attr, QCweight) || EQ (attr, QCslant) || EQ (attr, QCwidth)) value = intern (SSDATA (value)); - else if (EQ (attr, QCreverse_video) || EQ (attr, QCinverse_video)) + else if (EQ (attr, QCreverse_video) + || EQ (attr, QCinverse_video) + || EQ (attr, QCextend)) value = face_boolean_x_resource_value (value, true); else if (EQ (attr, QCunderline) || EQ (attr, QCoverline) @@ -3727,6 +3770,8 @@ DEFUN ("internal-get-lisp-face-attribute", Finternal_get_lisp_face_attribute, value = LFACE_SWIDTH (lface); else if (EQ (keyword, QCinherit)) value = LFACE_INHERIT (lface); + else if (EQ (keyword, QCextend)) + value = LFACE_EXTEND (lface); else if (EQ (keyword, QCfont)) value = LFACE_FONT (lface); else if (EQ (keyword, QCfontset)) @@ -3754,7 +3799,9 @@ DEFUN ("internal-lisp-face-attribute-values", if (EQ (attr, QCunderline) || EQ (attr, QCoverline) || EQ (attr, QCstrike_through) - || EQ (attr, QCinverse_video) || EQ (attr, QCreverse_video)) + || EQ (attr, QCinverse_video) + || EQ (attr, QCreverse_video) + || EQ (attr, QCextend)) result = list2 (Qt, Qnil); return result; @@ -4505,7 +4552,8 @@ lookup_face (struct frame *f, Lisp_Object *attr) suitable face is found, realize a new one. */ int -face_for_font (struct frame *f, Lisp_Object font_object, struct face *base_face) +face_for_font (struct frame *f, Lisp_Object font_object, + struct face *base_face) { struct face_cache *cache = FRAME_FACE_CACHE (f); unsigned hash; @@ -4738,7 +4786,7 @@ DEFUN ("face-attributes-as-vector", Fface_attributes_as_vector, Lisp_Object lface = make_vector (LFACE_VECTOR_SIZE, Qunspecified); merge_face_ref (NULL, XFRAME (selected_frame), plist, XVECTOR (lface)->contents, - true, 0); + true, NULL, 0); return lface; } @@ -4782,6 +4830,9 @@ gui_supports_face_attributes_p (struct frame *f, || (!UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX]) && face_attr_equal_p (attrs[LFACE_INVERSE_INDEX], def_attrs[LFACE_INVERSE_INDEX])) + || (!UNSPECIFIEDP (attrs[LFACE_EXTEND_INDEX]) + && face_attr_equal_p (attrs[LFACE_EXTEND_INDEX], + def_attrs[LFACE_EXTEND_INDEX])) || (!UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX]) && face_attr_equal_p (attrs[LFACE_FOREGROUND_INDEX], def_attrs[LFACE_FOREGROUND_INDEX])) @@ -5092,7 +5143,7 @@ Point (2) implies that a `:weight black' attribute will be satisfied by for (i = 0; i < LFACE_VECTOR_SIZE; i++) attrs[i] = Qunspecified; - merge_face_ref (NULL, f, attributes, attrs, true, 0); + merge_face_ref (NULL, f, attributes, attrs, true, NULL, 0); def_face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID); if (def_face == NULL) @@ -5358,6 +5409,9 @@ realize_default_face (struct frame *f) ASET (lface, LFACE_FONTSET_INDEX, Qnil); } + if (UNSPECIFIEDP (LFACE_EXTEND (lface))) + ASET (lface, LFACE_EXTEND_INDEX, Qnil); + if (UNSPECIFIEDP (LFACE_UNDERLINE (lface))) ASET (lface, LFACE_UNDERLINE_INDEX, Qnil); @@ -5694,16 +5748,14 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE] if (EQ (underline, Qt)) { /* Use default color (same as foreground color). */ - face->underline_p = true; - face->underline_type = FACE_UNDER_LINE; + face->underline = FACE_UNDER_LINE; face->underline_defaulted_p = true; face->underline_color = 0; } else if (STRINGP (underline)) { /* Use specified color. */ - face->underline_p = true; - face->underline_type = FACE_UNDER_LINE; + face->underline = FACE_UNDER_LINE; face->underline_defaulted_p = false; face->underline_color = load_color (f, face, underline, @@ -5711,7 +5763,7 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE] } else if (NILP (underline)) { - face->underline_p = false; + face->underline = FACE_NO_UNDERLINE; face->underline_defaulted_p = false; face->underline_color = 0; } @@ -5719,10 +5771,9 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE] { /* `(:color COLOR :style STYLE)'. STYLE being one of `line' or `wave'. */ - face->underline_p = true; + face->underline = FACE_UNDER_LINE; face->underline_color = 0; face->underline_defaulted_p = true; - face->underline_type = FACE_UNDER_LINE; /* FIXME? This is also not robust about checking the precise form. See comments in Finternal_set_lisp_face_attribute. */ @@ -5755,9 +5806,9 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE] else if (EQ (keyword, QCstyle)) { if (EQ (value, Qline)) - face->underline_type = FACE_UNDER_LINE; + face->underline = FACE_UNDER_LINE; else if (EQ (value, Qwave)) - face->underline_type = FACE_UNDER_WAVE; + face->underline = FACE_UNDER_WAVE; } } } @@ -5976,7 +6027,7 @@ compute_char_face (struct frame *f, int ch, Lisp_Object prop) Lisp_Object attrs[LFACE_VECTOR_SIZE]; struct face *default_face = FACE_FROM_ID (f, DEFAULT_FACE_ID); memcpy (attrs, default_face->lface, sizeof attrs); - merge_face_ref (NULL, f, prop, attrs, true, 0); + merge_face_ref (NULL, f, prop, attrs, true, NULL, 0); face_id = lookup_face (f, attrs); } @@ -5988,6 +6039,8 @@ compute_char_face (struct frame *f, int ch, Lisp_Object prop) which a different face is needed, as far as text properties and overlays are concerned. W is a window displaying current_buffer. + attr_filter is passed merge_face_ref. + REGION_BEG, REGION_END delimit the region, so it can be highlighted. @@ -6007,7 +6060,8 @@ compute_char_face (struct frame *f, int ch, Lisp_Object prop) int face_at_buffer_position (struct window *w, ptrdiff_t pos, ptrdiff_t *endptr, ptrdiff_t limit, - bool mouse, int base_face_id) + bool mouse, int base_face_id, + enum lface_attribute_index attr_filter) { struct frame *f = XFRAME (w->frame); Lisp_Object attrs[LFACE_VECTOR_SIZE]; @@ -6068,8 +6122,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos, } /* Optimize common cases where we can use the default face. */ - if (noverlays == 0 - && NILP (prop)) + if (noverlays == 0 && NILP (prop)) { SAFE_FREE (); return default_face->id; @@ -6080,7 +6133,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos, /* Merge in attributes specified via text properties. */ if (!NILP (prop)) - merge_face_ref (w, f, prop, attrs, true, 0); + merge_face_ref (w, f, prop, attrs, true, NULL, 0); /* Now merge the overlay data. */ noverlays = sort_overlays (overlay_vec, noverlays, w); @@ -6100,7 +6153,7 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos, so discard the mouse-face text property, if any, and use the overlay property instead. */ memcpy (attrs, default_face->lface, sizeof attrs); - merge_face_ref (w, f, prop, attrs, true, 0); + merge_face_ref (w, f, prop, attrs, true, NULL, attr_filter); } oend = OVERLAY_END (overlay_vec[i]); @@ -6117,8 +6170,9 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos, ptrdiff_t oendpos; prop = Foverlay_get (overlay_vec[i], propname); + if (!NILP (prop)) - merge_face_ref (w, f, prop, attrs, true, 0); + merge_face_ref (w, f, prop, attrs, true, NULL, attr_filter); oend = OVERLAY_END (overlay_vec[i]); oendpos = OVERLAY_POSITION (oend); @@ -6184,7 +6238,7 @@ face_for_overlay_string (struct window *w, ptrdiff_t pos, /* Merge in attributes specified via text properties. */ if (!NILP (prop)) - merge_face_ref (w, f, prop, attrs, true, 0); + merge_face_ref (w, f, prop, attrs, true, NULL, 0); *endptr = endpos; @@ -6219,7 +6273,7 @@ face_for_overlay_string (struct window *w, ptrdiff_t pos, face_at_string_position (struct window *w, Lisp_Object string, ptrdiff_t pos, ptrdiff_t bufpos, ptrdiff_t *endptr, enum face_id base_face_id, - bool mouse_p) + bool mouse_p) { Lisp_Object prop, position, end, limit; struct frame *f = XFRAME (WINDOW_FRAME (w)); @@ -6263,7 +6317,7 @@ face_at_string_position (struct window *w, Lisp_Object string, /* Merge in attributes specified via text properties. */ if (!NILP (prop)) - merge_face_ref (w, f, prop, attrs, true, 0); + merge_face_ref (w, f, prop, attrs, true, NULL, 0); /* Look up a realized face with the given face attributes, or realize a new one for ASCII characters. */ @@ -6292,9 +6346,8 @@ merge_faces (struct window *w, Lisp_Object face_name, int face_id, { struct frame *f = WINDOW_XFRAME (w); Lisp_Object attrs[LFACE_VECTOR_SIZE]; - struct face *base_face; + struct face *base_face = FACE_FROM_ID_OR_NULL (f, base_face_id); - base_face = FACE_FROM_ID_OR_NULL (f, base_face_id); if (!base_face) return base_face_id; @@ -6314,17 +6367,19 @@ merge_faces (struct window *w, Lisp_Object face_name, int face_id, if (!NILP (face_name)) { - if (!merge_named_face (w, f, face_name, attrs, 0)) + if (!merge_named_face (w, f, face_name, attrs, NULL, 0)) return base_face_id; } else { - struct face *face; if (face_id < 0) return base_face_id; - face = FACE_FROM_ID_OR_NULL (f, face_id); + + struct face *face = FACE_FROM_ID_OR_NULL (f, face_id); + if (!face) return base_face_id; + merge_face_vectors (w, f, face->lface, attrs, 0); } @@ -6412,7 +6467,7 @@ dump_realized_face (struct face *face) #endif fprintf (stderr, "fontset: %d\n", face->fontset); fprintf (stderr, "underline: %d (%s)\n", - face->underline_p, + face->underline, SDATA (Fsymbol_name (face->lface[LFACE_UNDERLINE_INDEX]))); fprintf (stderr, "hash: %" PRIuPTR "\n", face->hash); } @@ -6537,6 +6592,7 @@ syms_of_xfaces (void) DEFSYM (QCstrike_through, ":strike-through"); DEFSYM (QCbox, ":box"); DEFSYM (QCinherit, ":inherit"); + DEFSYM (QCextend, ":extend"); /* Symbols used for Lisp face attribute values. */ DEFSYM (QCcolor, ":color"); diff --git a/src/xterm.c b/src/xterm.c index b761eaf4d1..b8f8db56a7 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3798,9 +3798,9 @@ x_draw_glyph_string (struct glyph_string *s) if (!s->for_overlaps) { /* Draw underline. */ - if (s->face->underline_p) + if (s->face->underline) { - if (s->face->underline_type == FACE_UNDER_WAVE) + if (s->face->underline == FACE_UNDER_WAVE) { if (s->face->underline_defaulted_p) x_draw_underwave (s); @@ -3814,13 +3814,13 @@ x_draw_glyph_string (struct glyph_string *s) XSetForeground (display, s->gc, xgcv.foreground); } } - else if (s->face->underline_type == FACE_UNDER_LINE) + else if (s->face->underline == FACE_UNDER_LINE) { unsigned long thickness, position; int y; - if (s->prev && s->prev->face->underline_p - && s->prev->face->underline_type == FACE_UNDER_LINE) + if (s->prev && + s->prev->face->underline == FACE_UNDER_LINE) { /* We use the same underline style as the previous one. */ thickness = s->prev->underline_thickness; --cufrroyz6lahogak--