From: Ergus via "Emacs development discussions." <emacs-devel@gnu.org>
To: Eli Zaretskii <eliz@gnu.org>
Cc: rudalics@gmx.at, emacs-devel@gnu.org
Subject: Re: Question about display engine
Date: Sun, 8 Sep 2019 02:51:10 +0200 [thread overview]
Message-ID: <20190908005109.s7hhcczkrcbzewdc@Ergus> (raw)
In-Reply-To: <83mufg5yn1.fsf@gnu.org>
[-- Attachment #1: Type: text/plain, Size: 2064 bytes --]
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 <eliz@gnu.org>
>> 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.
>
[-- Attachment #2: test.patch --]
[-- Type: text/plain, Size: 46270 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..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;
next prev parent reply other threads:[~2019-09-08 0:51 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 ` Question about display engine Ergus
2019-09-06 8:22 ` 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. [this message]
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
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190908005109.s7hhcczkrcbzewdc@Ergus \
--to=emacs-devel@gnu.org \
--cc=eliz@gnu.org \
--cc=rudalics@gmx.at \
--cc=spacibba@aol.com \
/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 public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).