all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Ergus <spacibba@aol.com>
To: rudalics@gmx.at
Cc: eliz@gnu.org, emacs-devel@gnu.org
Subject: Re: Question about display engine
Date: Thu, 5 Sep 2019 19:26:09 +0000 (UTC)	[thread overview]
Message-ID: <318675867.1913640.1567711569517@mail.yahoo.com> (raw)
In-Reply-To: 318675867.1913640.1567711569517.ref@mail.yahoo.com


[-- Attachment #1.1: Type: text/plain, Size: 5169 bytes --]

Hi Eli and Martin:

I attach here a new patch with all the changes I have just made. After fixing the latest Martin's issue there was exposed a new issue maybe related with the initialization per line. (picture attached) 
The issue is actually related with the fact that extend_face_id is never restarted to face_id when going back from an extend to a non_extend face between lines (for example when mark is active and the iterator crosses the pointer to outside the selected region like in the  picture). 
I made all the  updates of the extend_face_id in the same places where face_id was updated (even when uneeded for now.) But I don't see any special function that is called before display_line. I can set extend_face_id = face_id at the beginning of display_line... but I am not sure if this is consistent or the right to do. 
In some face_id merges I ignored the merge for extend_face_id because Qnobreak_space, Qglyphless_char or Qescape_glyph I don't think are expected to be :extend t in any case. 
So the conditional merge is only called in next_element_from_display_vector and the conditionals there seems to be the key for this. 
The rest of the times the extend_face_id is only saved and restored so as there were no merges I just asign to convenient values (caches, saved or face_id). But maybe this last could be also the problem.
I am not convinced that I am doing this right. maybe some experts eyes could help. Lets expect this time marting can execute it ;p 
Thanks in advance,Ergus.


-----Original Message-----
From: Ergus <spacibba@aol.com>
To: rudalics <rudalics@gmx.at>
Cc: eliz <eliz@gnu.org>; emacs-devel <emacs-devel@gnu.org>
Sent: Thu, Sep 5, 2019 3:55 pm
Subject: Re: Question about display engine

For some reason I was not facing this; but it was actually a bug I just fixed. I'll send a patch in a while because this exposed an issue somewhere else.


-----Original Message-----
From: martin rudalics <rudalics@gmx.at>
To: Ergus <spacibba@aol.com>
Cc: Eli Zaretskii <eliz@gnu.org>; emacs-devel <emacs-devel@gnu.org>
Sent: Thu, Sep 5, 2019 11:24 am
Subject: Re: Question about display engine

> Here is the diff of the latest commit. (Patch attached anyway).

Thanks.  I tried with the patch.patch you attached.  When trying a gtk
build I get:

../../src/xfaces.c:5434: Emacs fatal error: assertion failed: lface_fully_specified_p (XVECTOR (lface)->contents)
Fatal error 6: Aborted
Backtrace:
../src/bootstrap-emacs[0x67e32f]
../src/bootstrap-emacs[0x6344c8]
../src/bootstrap-emacs[0x74fb6f]
../src/bootstrap-emacs[0x5a8e43]
../src/bootstrap-emacs[0x5a83f8]
../src/bootstrap-emacs[0x59bccf]
../src/bootstrap-emacs[0x436ad1]
../src/bootstrap-emacs[0x4fd0ad]
../src/bootstrap-emacs[0x76376c]
../src/bootstrap-emacs[0x63530c]
../src/bootstrap-emacs[0x635860]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7f68217952e1]
../src/bootstrap-emacs[0x4151aa]
/bin/bash: Zeile 2: 12088 Abgebrochen            EMACSLOADPATH= '../src/bootstrap-emacs' -batch --no-site-file --no-site-lisp --eval '(setq load-prefer-newer t)' -l bytecomp -f byte-compile-refresh-preloaded -f batch-byte-compile ../../lisp/cus-face.el
Makefile:280: die Regel für Ziel „../../lisp/cus-face.elc“ scheiterte
make[2]: *** [../../lisp/cus-face.elc] Fehler 134
Makefile:784: die Regel für Ziel „../../lisp/cus-face.elc“ scheiterte
make[1]: *** [../../lisp/cus-face.elc] Fehler 2
make[1]: *** Es wird auf noch nicht beendete Prozesse gewartet...

../../src/xfaces.c:5434: Emacs fatal error: assertion failed: lface_fully_specified_p (XVECTOR (lface)->contents)
Backtrace:
../src/bootstrap-emacs[0x67e32f]
../src/bootstrap-emacs[0x6344c8]
../src/bootstrap-emacs[0x74fb6f]
../src/bootstrap-emacs[0x5a8e43]
../src/bootstrap-emacs[0x5a83f8]
../src/bootstrap-emacs[0x59bccf]
../src/bootstrap-emacs[0x436ad1]
../src/bootstrap-emacs[0x4fd0ad]
../src/bootstrap-emacs[0x76376c]
../src/bootstrap-emacs[0x63530c]
../src/bootstrap-emacs[0x635860]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7f0e8f3a32e1]
../src/bootstrap-emacs[0x4151aa]
/bin/bash: Zeile 2: 12090 Abgebrochen            EMACSLOADPATH= '../src/bootstrap-emacs' -batch --no-site-file --no-site-lisp --eval '(setq load-prefer-newer t)' -l bytecomp -f byte-compile-refresh-preloaded -f batch-byte-compile ../../lisp/faces.el
Makefile:280: die Regel für Ziel „../../lisp/faces.elc“ scheiterte
make[2]: *** [../../lisp/faces.elc] Fehler 134
Makefile:784: die Regel für Ziel „../../lisp/faces.elc“ scheiterte
make[1]: *** [../../lisp/faces.elc] Fehler 2
make[1]: Verzeichnis „/home/martin/emacs-git/trunk/obj-gtk/src“ wird verlassen
Makefile:424: die Regel für Ziel „src“ scheiterte
make: *** [src] Fehler 2

and a similar crash on Windows.  Before proceeding to dig into this
I'd like to hear your ideas.

 > https://github.com/Ergus/Emacs/commit/4943087027acd3f2c7a54a092b64bc839ef8850e

Is there any way to get the diffs wrt current master on that site?  I
never use github for such a thing and my browser settings are quite
restrictive.

Thanks, martin

[-- Attachment #1.2: Type: text/html, Size: 7578 bytes --]

[-- Attachment #2: Screenshot_2019-09-05_20-49-41.png --]
[-- Type: image/png, Size: 29280 bytes --]

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: patch.patch --]
[-- Type: text/x-patch, Size: 45844 bytes --]

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))
 
 \f
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -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..c11a3a7b54 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;
 
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..62730903fd 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3120,6 +3120,7 @@ init_iterator (struct it *it, struct window *w,
       struct face *face;
 
       it->face_id = remapped_base_face_id;
+      it->extend_face_id = remapped_base_face_id;
 
       /* If we have a boxed mode line, make the first character appear
 	 with a left box line.  */
@@ -3141,6 +3142,8 @@ init_iterator (struct it *it, struct window *w,
       /* We will rely on `reseat' to set this up properly, via
 	 handle_face_prop.  */
       it->face_id = it->base_face_id;
+      it->extend_face_id = it->base_face_id;  // ERGUS: FIX_THIS
+
 
       it->start = it->current;
       /* Do we need to reorder bidirectional text?  Not if this is a
@@ -3536,7 +3539,10 @@ handle_stop (struct it *it)
 
   /* Use face of preceding text for ellipsis (if invisible) */
   if (it->selective_display_ellipsis_p)
-    it->saved_face_id = it->face_id;
+    {
+      it->saved_face_id = it->face_id;
+      it->saved_extend_face_id = it->extend_face_id;
+    }
 
   /* Here's the description of the semantics of, and the logic behind,
      the various HANDLED_* statuses:
@@ -4154,7 +4160,15 @@ handle_face_prop (struct it *it)
 	  it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
 				    && (old_face == NULL || !old_face->box));
 	  it->face_box_p = new_face->box != FACE_NO_BOX;
+
+	  /* Update the faces id and extend.  */
+	  it->face_id = new_face_id;
+
+	  if (FACE_EXTENSIBLE_P (new_face))
+	    it->extend_face_id = new_face_id;
+
 	}
+
     }
   else
     {
@@ -4250,13 +4264,19 @@ handle_face_prop (struct it *it)
 	  /* 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
 	     shadow on the left side.  */
-	  it->start_of_box_run_p
-	    = new_face->box && (old_face == NULL || !old_face->box);
+	  it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
+	                            && (old_face == NULL || !old_face->box));
 	  it->face_box_p = new_face->box != FACE_NO_BOX;
+
+	  /* Update the faces id and extend.  */
+	  it->face_id = new_face_id;
+
+	  if (FACE_EXTENSIBLE_P (new_face))
+	    it->extend_face_id = new_face_id;
+
 	}
     }
 
-  it->face_id = new_face_id;
   return HANDLED_NORMALLY;
 }
 
@@ -4854,6 +4874,9 @@ setup_for_ellipsis (struct it *it, int len)
   if (it->saved_face_id >= 0)
     it->face_id = it->saved_face_id;
 
+  if (it->saved_extend_face_id >= 0)
+    it->extend_face_id = it->saved_extend_face_id;
+
   /* If the ellipsis represents buffer text, it means we advanced in
      the buffer, so we should no longer ignore overlay strings.  */
   if (it->method == GET_FROM_BUFFER)
@@ -5063,7 +5086,8 @@ display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
    of buffer or string text.  */
 
 static int
-handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
+handle_single_display_spec (struct it *it, Lisp_Object spec,
+                            Lisp_Object object,
 			    Lisp_Object overlay, struct text_pos *position,
 			    ptrdiff_t bufpos, int display_replaced,
 			    bool frame_window_p, bool enable_eval_p)
@@ -5137,7 +5161,11 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
 		  int steps = XFIXNUM (XCAR (XCDR (it->font_height)));
 		  if (EQ (XCAR (it->font_height), Qplus))
 		    steps = - steps;
+
 		  it->face_id = smaller_face (it->f, it->face_id, steps);
+		  it->extend_face_id
+		    = smaller_face (it->f, it->extend_face_id, steps);
+
 		}
 	      else if (FUNCTIONP (it->font_height) && enable_eval_p)
 		{
@@ -5180,7 +5208,12 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
 		}
 
 	      if (new_height > 0)
-		it->face_id = face_with_height (it->f, it->face_id, new_height);
+		{
+		  it->face_id
+		    = face_with_height (it->f, it->face_id, new_height);
+		  it->extend_face_id
+		    = face_with_height (it->f, it->extend_face_id, new_height);
+		}
 	    }
 	}
 
@@ -5370,6 +5403,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
 	  it->method = GET_FROM_IMAGE;
 	  it->from_overlay = Qnil;
 	  it->face_id = face_id;
+	  it->extend_face_id = face_id; // ERGUS: FIX_THIS
 	  it->from_disp_prop_p = true;
 
 	  /* Say that we haven't consumed the characters with
@@ -6263,6 +6297,7 @@ push_it (struct it *it, struct text_pos *position)
   p->cmp_it = it->cmp_it;
   eassert (it->face_id >= 0);
   p->face_id = it->face_id;
+  p->extend_face_id = it->extend_face_id;
   p->string = it->string;
   p->method = it->method;
   p->from_overlay = it->from_overlay;
@@ -6366,6 +6401,7 @@ pop_it (struct it *it)
   it->base_level_stop = p->base_level_stop;
   it->cmp_it = p->cmp_it;
   it->face_id = p->face_id;
+  it->extend_face_id = p->extend_face_id;
   it->current = p->current;
   it->position = p->position;
   it->string = p->string;
@@ -7142,17 +7178,32 @@ lookup_glyphless_char_display (int c, struct it *it)
 
 /* Merge escape glyph face and cache the result.  */
 
+static int
+merge_extend_glyph_face (struct it *it, int lface_id)
+{
+
+  struct face *lface = FACE_FROM_ID (it->f, lface_id);
+
+  if (lface && FACE_EXTENSIBLE_P (lface))
+    return merge_faces (it->w, Qt, lface_id, it->extend_face_id);
+
+  return it->extend_face_id;
+}
+
+/* Merge escape glyph face and cache the result.  */
 static struct frame *last_escape_glyph_frame = NULL;
 static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
 static int last_escape_glyph_merged_face_id = 0;
 
 static int
-merge_escape_glyph_face (struct it *it)
+merge_escape_glyph_face (struct it *it, int lface_id)
 {
   int face_id;
 
-  if (it->f == last_escape_glyph_frame
-      && it->face_id == last_escape_glyph_face_id)
+  if (lface_id)
+    face_id = merge_faces (it->w, Qt, lface_id, it->face_id);
+  else if (it->f == last_escape_glyph_frame
+           && it->face_id == last_escape_glyph_face_id)
     face_id = last_escape_glyph_merged_face_id;
   else
     {
@@ -7162,6 +7213,7 @@ merge_escape_glyph_face (struct it *it)
       last_escape_glyph_face_id = it->face_id;
       last_escape_glyph_merged_face_id = face_id;
     }
+
   return face_id;
 }
 
@@ -7190,6 +7242,7 @@ merge_glyphless_glyph_face (struct it *it)
   return face_id;
 }
 
+
 /* Forget the `escape-glyph' and `glyphless-char' faces.  This should
    be called before redisplaying windows, and when the frame's face
    cache is freed.  */
@@ -7275,6 +7328,7 @@ get_next_display_element (struct it *it)
 		  it->current.dpvec_index = 0;
 		  it->dpvec_face_id = -1;
 		  it->saved_face_id = it->face_id;
+		  it->saved_extend_face_id = it->extend_face_id;
 		  it->method = GET_FROM_DISPLAY_VECTOR;
 		  it->ellipsis_p = false;
 		}
@@ -7355,9 +7409,7 @@ get_next_display_element (struct it *it)
 		      lface_id = GLYPH_CODE_FACE (gc);
 		    }
 
-		  face_id = (lface_id
-			     ? merge_faces (it->w, Qt, lface_id, it->face_id)
-			     : merge_escape_glyph_face (it));
+		  face_id = merge_escape_glyph_face (it, lface_id);
 
 		  XSETINT (it->ctl_chars[0], g);
 		  XSETINT (it->ctl_chars[1], c ^ 0100);
@@ -7373,6 +7425,7 @@ get_next_display_element (struct it *it)
 		  /* Merge `nobreak-space' into the current face.  */
 		  face_id = merge_faces (it->w, Qnobreak_space, 0,
 					 it->face_id);
+
 		  XSETINT (it->ctl_chars[0], ' ');
 		  ctl_len = 1;
 		  goto display_control;
@@ -7385,7 +7438,8 @@ get_next_display_element (struct it *it)
 		{
 		  /* Merge `nobreak-space' into the current face.  */
 		  face_id = merge_faces (it->w, Qnobreak_hyphen, 0,
-					 it->face_id);
+		                         it->face_id);
+
 		  XSETINT (it->ctl_chars[0], '-');
 		  ctl_len = 1;
 		  goto display_control;
@@ -7403,12 +7457,9 @@ get_next_display_element (struct it *it)
 		  lface_id = GLYPH_CODE_FACE (gc);
 		}
 
-	      face_id = (lface_id
-			 ? merge_faces (it->w, Qt, lface_id, it->face_id)
-			 : merge_escape_glyph_face (it));
+	      face_id = merge_escape_glyph_face (it, lface_id);
 
 	      /* Draw non-ASCII space/hyphen with escape glyph: */
-
 	      if (nonascii_space_p || nonascii_hyphen_p)
 		{
 		  XSETINT (it->ctl_chars[0], escape_glyph);
@@ -7443,6 +7494,7 @@ get_next_display_element (struct it *it)
 	      it->current.dpvec_index = 0;
 	      it->dpvec_face_id = face_id;
 	      it->saved_face_id = it->face_id;
+	      it->saved_extend_face_id = it->extend_face_id;
 	      it->method = GET_FROM_DISPLAY_VECTOR;
 	      it->ellipsis_p = false;
 	      goto get_next;
@@ -7778,6 +7830,7 @@ set_iterator_to_next (struct it *it, bool reseat_p)
       /* Restore face of the iterator to what they were before the
          display vector entry (these entries may contain faces).  */
       it->face_id = it->saved_face_id;
+      it->extend_face_id = it->saved_extend_face_id;
 
       if (it->dpvec + it->current.dpvec_index >= it->dpend)
 	{
@@ -8012,6 +8065,7 @@ next_element_from_display_vector (struct it *it)
   eassert (it->dpvec && it->current.dpvec_index >= 0);
 
   it->face_id = it->saved_face_id;
+  it->extend_face_id = it->saved_extend_face_id;
 
   /* KFS: This code used to check ip->dpvec[0] instead of the current element.
      That seemed totally bogus - so I changed it...  */
@@ -8027,13 +8081,21 @@ next_element_from_display_vector (struct it *it)
 	 the id of a Lisp face, not a realized face.  A face id of
 	 zero means no face is specified.  */
       if (it->dpvec_face_id >= 0)
-	it->face_id = it->dpvec_face_id;
+	{
+	  it->face_id = it->dpvec_face_id;
+	  it->extend_face_id = it->dpvec_face_id; // ERGUS: FIX_THIS
+	}
       else
 	{
 	  int lface_id = GLYPH_CODE_FACE (gc);
 	  if (lface_id > 0)
-	    it->face_id = merge_faces (it->w, Qt, lface_id,
-				       it->saved_face_id);
+	    {
+	      it->face_id = merge_faces (it->w, Qt, lface_id,
+	                                 it->saved_face_id);
+
+	      it->extend_face_id =
+		merge_extend_glyph_face (it, lface_id);
+	    }
 	}
 
       /* Glyphs in the display vector could have the box face, so we
@@ -8061,8 +8123,12 @@ next_element_from_display_vector (struct it *it)
 		GLYPH_CODE_FACE (it->dpvec[it->current.dpvec_index + 1]);
 
 	      if (lface_id > 0)
-		next_face_id = merge_faces (it->w, Qt, lface_id,
-					    it->saved_face_id);
+		{
+		  next_face_id = merge_faces (it->w, Qt, lface_id,
+		                              it->saved_face_id);
+		  it->extend_face_id =
+		    merge_extend_glyph_face (it, lface_id);
+		}
 	    }
 	}
       next_face = FACE_FROM_ID_OR_NULL (it->f, next_face_id);
@@ -8411,6 +8477,7 @@ next_element_from_ellipsis (struct it *it)
 	 was in IT->saved_face_id, and signal that it's there by
 	 setting face_before_selective_p.  */
       it->saved_face_id = it->face_id;
+      it->saved_extend_face_id = it->extend_face_id;
       it->method = GET_FROM_BUFFER;
       it->object = it->w->contents;
       reseat_at_next_visible_line_start (it, true);
@@ -12848,7 +12915,10 @@ display_tool_bar_line (struct it *it, int height)
      use the tool-bar face for the border too.  */
   if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
       && !EQ (Vauto_resize_tool_bars, Qgrow_only))
-    it->face_id = DEFAULT_FACE_ID;
+    {
+      it->face_id = DEFAULT_FACE_ID;
+      it->extend_face_id = DEFAULT_FACE_ID;
+    }
 
   extend_face_to_end_of_line (it);
   last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
@@ -20301,7 +20371,7 @@ append_space_for_newline (struct it *it, bool default_face_p)
 
 	  /* Corner case for when display-fill-column-indicator-mode
 	     is active and the extra character should be added in the
-	     same place than the line.  */
+	     same place than the space.  */
 	  int indicator_column = (it->w->pseudo_window_p == 0
 				  ? fill_column_indicator_column (it)
 				  : -1);
@@ -20325,7 +20395,7 @@ append_space_for_newline (struct it *it, bool default_face_p)
 		     = XFIXNAT (Vdisplay_fill_column_indicator_character);
 	           it->face_id
 		     = merge_faces (it->w, Qfill_column_indicator,
-				    0, saved_face_id);
+		                    0, it->face_id);
 	           face = FACE_FROM_ID (it->f, it->face_id);
 	           goto produce_glyphs;
 	         }
@@ -20337,7 +20407,7 @@ append_space_for_newline (struct it *it, bool default_face_p)
 	  if (default_face_p)
 	    it->face_id = local_default_face_id;
 	  else if (it->face_before_selective_p)
-	    it->face_id = it->saved_face_id;
+	    it->face_id = it->face_id;
 
 	  face = FACE_FROM_ID (it->f, it->face_id);
 	  it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
@@ -20472,33 +20542,35 @@ extend_face_to_end_of_line (struct it *it)
      1-``pixel'' wide, so they hit the equality too early.  This grace
      is needed only for R2L rows that are not continued, to produce
      one extra blank where we could display the cursor.  */
-  if ((it->current_x >= it->last_visible_x
-       + (!FRAME_WINDOW_P (f)
-	  && it->glyph_row->reversed_p
-	  && !it->glyph_row->continued_p))
-      /* If the window has display margins, we will need to extend
-	 their face even if the text area is filled.  */
-      && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
-	   || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
-    return;
-
-  /* Face extension extends the background and box of IT->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));
-
-  if (FRAME_WINDOW_P (f)
-      && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
-      && face->box == FACE_NO_BOX
-      && FACE_COLOR_TO_PIXEL (face->background, f) == FRAME_BACKGROUND_PIXEL (f)
-#ifdef HAVE_WINDOW_SYSTEM
-      && !face->stipple
-#endif
-      && !it->glyph_row->reversed_p
-      && !Vdisplay_fill_column_indicator)
-    return;
+/*   if ((it->current_x >= it->last_visible_x */
+/*        + (!FRAME_WINDOW_P (f) */
+/*           && it->glyph_row->reversed_p */
+/*           && !it->glyph_row->continued_p)) */
+/*       /\* If the window has display margins, we will need to extend */
+/* 	 their face even if the text area is filled.  *\/ */
+/*       && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0 */
+/* 	   || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)) */
+/*     return; */
+
+/*   /\* Face extension extends the background and box of IT->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_extend_face_id */
+  /* 			   : it->extend_face_id)); */
+
+  face = FACE_FROM_ID (f, it->extend_face_id);
+
+/*   if (FRAME_WINDOW_P (f) */
+/*       && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row) */
+/*       && face->box == FACE_NO_BOX */
+/*       && FACE_COLOR_TO_PIXEL (face->background, f) == FRAME_BACKGROUND_PIXEL (f) */
+/* #ifdef HAVE_WINDOW_SYSTEM */
+/*       && !face->stipple */
+/* #endif */
+/*       && !it->glyph_row->reversed_p */
+/*       && !Vdisplay_fill_column_indicator) */
+/*     return; */
 
   /* Set the glyph row flag indicating that the face of the last glyph
      in the text area has to be drawn to the end of the text area.  */
@@ -20561,79 +20633,88 @@ 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.  */
+	  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;
+
+	  it->avoid_cursor_p = true;
+	  it->object = Qnil;
+	  memset (&it->position, 0, sizeof it->position);
+
 	  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
+
+	  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);
-		    }
+	  const int char_width = (font->average_width
+	                          ? font->average_width
+	                          : font->space_width);
+	  int column_x;
+
+	  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)
+	    {
+
+	      /* The stretch width needs to considet the latter
+		 added glyph.  */
+	      const int stretch_width
+		= column_x - it->current_x - char_width;
+
+	      /* Only generate a stretch glyph if there is distance
+		 between current_x and and the indicator position.  */
+	      if (stretch_width > 0)
+		{
+		  it->face_id = it->extend_face_id;
 
-	          /* 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;
-	        }
-            }
+		  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, it->extend_face_id);
+		  PRODUCE_GLYPHS (it);
+		  it->char_to_display = saved_char;
+		}
+
+	    }
+
+	  const int stretch_width = it->last_visible_x - it->current_x;
+
+	  if (stretch_width > 0)
+	    {
+	      it->face_id = it->extend_face_id;
+
+	      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);
+	    }
+
+	  it->char_to_display = saved_char;
+	  it->position = saved_pos;
+	  it->avoid_cursor_p = saved_avoid_cursor;
+	  it->face_id = saved_face_id;
+	  it->start_of_box_run_p = saved_box_start;
+	  it->object = save_object;
 	}
       if (it->glyph_row->reversed_p)
 	{
@@ -20679,10 +20760,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);
@@ -20719,7 +20799,7 @@ extend_face_to_end_of_line (struct it *it)
       it->len = 1;
 
       if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
-	  && (it->glyph_row->used[LEFT_MARGIN_AREA]
+          && (it->glyph_row->used[LEFT_MARGIN_AREA]
 	      < WINDOW_LEFT_MARGIN_WIDTH (it->w))
 	  && !it->glyph_row->mode_line_p
 	  && FACE_COLOR_TO_PIXEL (face->background, f) != FRAME_BACKGROUND_PIXEL (f))
@@ -20750,10 +20830,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 +20841,25 @@ 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);
 
@@ -25423,7 +25502,8 @@ display_count_lines (ptrdiff_t start_byte,
    Value is the number of columns displayed.  */
 
 static int
-display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_string,
+display_string (const char *string, Lisp_Object lisp_string,
+                Lisp_Object face_string,
 		ptrdiff_t face_string_pos, ptrdiff_t start, struct it *it,
 		int field_width, int precision, int max_x, int multibyte)
 {
@@ -25446,12 +25526,13 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st
   if (STRINGP (face_string))
     {
       ptrdiff_t endptr;
-      struct face *face;
 
       it->face_id
 	= face_at_string_position (it->w, face_string, face_string_pos,
 				   0, &endptr, it->base_face_id, false);
-      face = FACE_FROM_ID (it->f, it->face_id);
+
+      struct face *face = FACE_FROM_ID (it->f, it->face_id);
+
       it->face_box_p = face->box != FACE_NO_BOX;
     }
 
@@ -27355,7 +27436,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;
     }
 
diff --git a/src/xfaces.c b/src/xfaces.c
index c3cae7e2a6..9c58e3e51a 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -1209,7 +1209,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 +1590,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 +1634,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])
@@ -2512,6 +2517,13 @@ merge_face_ref (struct window *w,
 					err_msgs, named_merge_points))
 		    err = true;
 		}
+	      else if (EQ (keyword, QCextend))
+		{
+		  if (EQ (value, Qt) || NILP (value))
+		    to[LFACE_EXTEND_INDEX] = value;
+		  else
+		    err = true;
+		}
 	      else
 		err = true;
 
@@ -3030,6 +3042,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 +3526,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 +3752,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 +3781,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;
@@ -4782,6 +4811,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]))
@@ -5358,6 +5390,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 +5729,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 +5744,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 +5752,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 +5787,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;
             }
         }
     }
@@ -6292,9 +6324,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;
 
@@ -6319,12 +6350,14 @@ merge_faces (struct window *w, Lisp_Object face_name, int 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 +6445,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 +6570,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;

       reply	other threads:[~2019-09-05 19:26 UTC|newest]

Thread overview: 183+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <318675867.1913640.1567711569517.ref@mail.yahoo.com>
2019-09-05 19:26 ` Ergus [this message]
2019-09-06  8:22   ` Question about display engine martin rudalics
2019-09-06  9:31     ` Ergus
2019-09-07  6:52       ` martin rudalics
2019-09-07  7:37         ` Eli Zaretskii
2019-09-07  7:55           ` Eli Zaretskii
2019-09-08  0:51             ` Ergus via Emacs development discussions.
2019-09-08  8:40               ` martin rudalics
2019-09-08 12:53                 ` Ergus
2019-09-09  7:39                   ` martin rudalics
2019-09-09 13:56                     ` Ergus
2019-09-09 16:00                     ` Eli Zaretskii
2019-09-09 17:08                       ` Ergus
2019-09-09 18:08                         ` Eli Zaretskii
2019-09-09 19:29                           ` Ergus
2019-09-10  2:27                             ` Eli Zaretskii
2019-09-12  3:37                               ` Ergus
2019-09-13  8:50                                 ` Eli Zaretskii
2019-09-08 17:51               ` Eli Zaretskii
2019-09-08 18:23                 ` Ergus
2019-09-14 20:42                   ` Ergus
2019-09-15  8:25                     ` martin rudalics
2019-09-15 11:26                       ` Ergus
2019-09-15 12:22                         ` martin rudalics
2019-09-15 14:28                           ` Stefan Monnier
2019-09-16  9:05                             ` martin rudalics
2019-09-15 15:32                     ` Eli Zaretskii
2019-09-15 21:42                       ` Ergus
2019-09-17  2:17                         ` Ergus
2019-09-17  9:48                           ` Eli Zaretskii
2019-09-21  8:20                             ` Eli Zaretskii
2019-09-21 13:57                               ` Ergus
2019-09-21 21:55                               ` Ergus
2019-09-26 16:32                                 ` Ergus
2019-09-28 10:35                                   ` Eli Zaretskii
2019-09-29 10:30                                     ` Ergus
2019-09-29 10:57                                       ` Eli Zaretskii
2019-10-07 15:40                                         ` Ergus
2019-10-09  9:02                                           ` Eli Zaretskii
2019-10-12 18:16                                             ` Ergus
2019-10-12 18:29                                               ` Eli Zaretskii
2019-09-06  8:55   ` Eli Zaretskii
2019-09-06 10:30     ` Ergus
2019-09-06 13:28       ` Eli Zaretskii
2019-09-06 16:34         ` Ergus
2019-09-06 18:12           ` Eli Zaretskii
2019-09-07  2:35             ` Ergus
2019-09-07  6:41               ` Eli Zaretskii
     [not found] <20191012222305.jpjinkd5y2lz6xiv@Ergus>
     [not found] ` <83mue5kmfx.fsf@gnu.org>
2019-10-13 15:40   ` Ergus
2019-10-13 16:06     ` Eli Zaretskii
2019-10-13 16:44       ` Ergus
2019-10-13 17:04         ` Eli Zaretskii
2019-10-13 18:11           ` Ergus
2019-10-13 18:25           ` Ergus
2019-10-13 18:53             ` Eli Zaretskii
2019-10-13 19:38               ` Ergus
2019-10-13 21:01                 ` Eli Zaretskii
2019-10-13 22:27                   ` Ergus
2019-10-14  8:26                     ` Eli Zaretskii
2019-10-20 22:20                       ` Ergus
2019-10-21  6:38                         ` Eli Zaretskii
2019-10-13 19:41               ` Ergus
2019-10-13 16:11     ` Eli Zaretskii
2019-08-27 16:01 Keith David Bershatsky
  -- strict thread matches above, loose matches on Subject: below --
2019-08-07  0:54 Ergus
2019-08-07 15:01 ` Eli Zaretskii
2019-08-07 15:32   ` Ergus
2019-08-07 15:45     ` Eli Zaretskii
2019-08-07 15:57       ` Ergus
2019-08-07 16:12         ` Eli Zaretskii
2019-08-07 16:25           ` martin rudalics
2019-08-07 16:41             ` Eli Zaretskii
2019-08-08  7:25               ` martin rudalics
2019-08-08  8:38                 ` Ergus
2019-08-08  8:45                   ` martin rudalics
2019-08-08  9:29                     ` Ergus
2019-08-08 13:05                       ` martin rudalics
2019-08-08 13:59                         ` Eli Zaretskii
2019-08-08 16:43                           ` Ergus
2019-08-08 17:50                             ` Eli Zaretskii
2019-08-08 22:37                               ` Ergus
2019-08-09  6:28                                 ` Eli Zaretskii
2019-08-09  9:08                                   ` Ergus
2019-08-09  9:40                                     ` Eli Zaretskii
2019-08-09 11:31                                       ` Ergus
2019-08-09 14:04                                         ` Eli Zaretskii
2019-08-09 15:09                                           ` Ergus
2019-08-09  8:59                             ` martin rudalics
2019-08-09  9:31                               ` Ergus
2019-08-09  9:38                               ` Ergus
2019-08-10 11:42                             ` Eli Zaretskii
2019-08-11  8:14                               ` martin rudalics
2019-08-09  8:59                           ` martin rudalics
2019-08-08 14:50                         ` Ergus
2019-08-09  8:59                           ` martin rudalics
2019-08-10 11:30                             ` Eli Zaretskii
2019-08-11  8:14                               ` martin rudalics
2019-08-11 14:13                                 ` Eli Zaretskii
2019-08-12  8:59                                   ` martin rudalics
2019-08-12 15:29                                     ` Eli Zaretskii
2019-08-12 22:18                                       ` Stefan Monnier
2019-08-13  8:17                                         ` martin rudalics
2019-08-13 15:32                                           ` Eli Zaretskii
2019-08-13 22:33                                             ` Stefan Monnier
2019-08-14  8:58                                             ` martin rudalics
2019-08-13  8:17                                       ` martin rudalics
2019-08-13 15:31                                         ` Eli Zaretskii
2019-08-14  8:58                                           ` martin rudalics
2019-08-14 15:14                                             ` Eli Zaretskii
2019-08-15  8:13                                               ` martin rudalics
2019-08-15 15:18                                                 ` Eli Zaretskii
2019-08-16  7:29                                                   ` martin rudalics
2019-08-16  8:34                                                     ` Eli Zaretskii
2019-08-17  8:25                                                       ` martin rudalics
2019-08-19 16:13                                                         ` Ergus
2019-08-19 16:50                                                           ` Eli Zaretskii
2019-08-19 21:30                                                             ` Ergus
2019-08-20 14:09                                                               ` Eli Zaretskii
2019-08-25 10:22                                                                 ` Ergus
2019-08-25 10:44                                                                   ` Eli Zaretskii
2019-08-26  4:31                                                                     ` Ergus
2019-08-26  7:45                                                                       ` Eli Zaretskii
2019-08-26  8:18                                                                         ` Ergus
2019-08-26  9:49                                                                           ` Eli Zaretskii
2019-08-27 22:20                                                                             ` Ergus
2019-08-28  8:35                                                                               ` martin rudalics
2019-08-28  9:07                                                                                 ` Eli Zaretskii
2019-08-28 12:19                                                                                   ` martin rudalics
2019-08-28 16:31                                                                                     ` Ergus
2019-08-28 17:24                                                                                       ` Eli Zaretskii
2019-08-28 18:19                                                                                         ` Ergus
2019-08-29 18:28                                                                                           ` Eli Zaretskii
2019-08-30  7:02                                                                                             ` martin rudalics
2019-08-30  7:26                                                                                               ` Eli Zaretskii
2019-08-30  9:34                                                                                             ` Ergus
2019-08-29  7:45                                                                                       ` martin rudalics
2019-08-28 17:21                                                                                     ` Eli Zaretskii
2019-08-29  7:45                                                                                       ` martin rudalics
2019-08-29 18:36                                                                                         ` Eli Zaretskii
2019-08-30  7:03                                                                                           ` martin rudalics
2019-08-30  8:48                                                                                             ` Eli Zaretskii
2019-08-31  7:29                                                                                               ` martin rudalics
2019-08-31  7:57                                                                                                 ` Eli Zaretskii
2019-09-01  8:14                                                                                                   ` martin rudalics
2019-09-01 12:26                                                                                                     ` Ergus
2019-09-02  8:36                                                                                                       ` martin rudalics
2019-09-02 11:05                                                                                                         ` Ergus
2019-09-02 16:18                                                                                                           ` Eli Zaretskii
2019-09-03  5:33                                                                                                             ` Ergus
2019-09-03  8:45                                                                                                               ` martin rudalics
2019-09-03 11:23                                                                                                                 ` Ergus
2019-09-03 12:17                                                                                                                   ` martin rudalics
2019-09-03 14:56                                                                                                                   ` Eli Zaretskii
2019-09-03  5:35                                                                                                             ` Ergus via Emacs development discussions.
2019-09-03  8:45                                                                                                             ` martin rudalics
2019-09-03 14:53                                                                                                               ` Eli Zaretskii
2019-09-03 16:41                                                                                                                 ` martin rudalics
2019-09-03 17:31                                                                                                                   ` Eli Zaretskii
2019-09-03 18:59                                                                                                                     ` martin rudalics
2019-09-04 18:33                                                                                                                       ` Ergus
2019-09-04 20:04                                                                                                                         ` martin rudalics
2019-09-04 20:19                                                                                                                           ` Ergus via Emacs development discussions.
2019-09-05  7:32                                                                                                                             ` martin rudalics
2019-09-05 13:54                                                                                                                               ` Ergus
2019-09-05 19:31                                                                                                                                 ` Ergus
     [not found]                                                                                                                           ` <1826922767.1725310.1567682307734@mail.yahoo.com>
2019-09-05 11:18                                                                                                                             ` Ergus
2019-08-21  7:37                                                           ` martin rudalics
2019-08-08 17:37                   ` Eli Zaretskii
2019-08-09 12:46                     ` martin rudalics
2019-08-10 11:25                       ` Eli Zaretskii
2019-08-10 23:04                         ` Stefan Monnier
2019-08-11  2:43                           ` Eli Zaretskii
2019-08-11  8:17                             ` martin rudalics
2019-08-11  8:11                         ` martin rudalics
2019-08-08 17:38                   ` Eli Zaretskii
2019-08-08  8:15               ` Ergus
2019-08-08  8:45                 ` martin rudalics
2019-08-08  9:17                   ` Ergus
2019-08-08 17:35                 ` Eli Zaretskii
2019-08-08 20:37                 ` Juri Linkov
2019-08-08 22:24                   ` Ergus
2019-08-09  6:42                     ` Eli Zaretskii
2019-08-09 17:54                     ` Juri Linkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=318675867.1913640.1567711569517@mail.yahoo.com \
    --to=spacibba@aol.com \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@gnu.org \
    --cc=rudalics@gmx.at \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.