Merge branch 'feature/extend_face_id'

New face attribute :extend to control the face extension after
EOL.

necessary, # especially if it merges an updated upstream into a topic
branch.  # # Lines starting with '#' will be ignored, and an empty
message aborts # the commit.
This commit is contained in:
Jimmy Aguilar Mena 2019-10-14 14:29:47 +02:00
commit 3d6075e3ee
14 changed files with 489 additions and 375 deletions

View file

@ -23,6 +23,11 @@ When the mark is active, we say also that the region is active; Emacs
indicates its extent by highlighting the text within it, using the
@code{region} face (@pxref{Face Customization}).
This is one of the few faces that has the @code{:extend t} attribute
by default, which implies that the same face is used to highlight the
text and space between end of line and the window border. To
highlight only the text you could set this attribute to @code{nil}.
@cindex deactivating the mark
After certain non-motion commands, including any command that
changes the text in the buffer, Emacs automatically @dfn{deactivates}

View file

@ -2482,6 +2482,17 @@ faces (@pxref{Displaying Faces}). If the face to inherit from is
never merges @code{:inherit} attributes. If a list of faces is used,
attributes from faces earlier in the list override those from later
faces.
@item :extend
Whether or not this face will be extended until the end of the window.
The value should be @code{t} to extend until end of the window using
this face or @code{nil} fill the space between the end of the line and
the end of the window with the default face. When a face is conformed
by merging multiple other faces; only those with @code{:extend t} will
be merged to conform a new face to extend until end of window. By
default only @code{region} and @code{hl-line} have this attribute set
to @code{t}.
@end table
@defun font-family-list &optional frame
@ -2840,6 +2851,11 @@ This sets the @code{:inverse-video} attribute of @var{face} to
@deffn Command invert-face face &optional frame
This swaps the foreground and background colors of face @var{face}.
@end deffn
@deffn Command set-face-extend face extend &optional frame
This sets the @code{:extend} attribute of @var{face} to
@var{extend}.
@end deffn
The following functions examine the attributes of a face. They
@ -2900,6 +2916,12 @@ This function returns non-@code{nil} if face @var{face} specifies
a non-@code{nil} @code{:inverse-video} attribute.
@end defun
@defun face-extend-p face &optional frame
This function returns non-@code{nil} if face @var{face} specifies
a non-@code{nil} @code{:extend} attribute.
@end defun
@node Displaying Faces
@subsection Displaying Faces
@cindex displaying faces

View file

@ -384,6 +384,13 @@ matches strings where the pattern appears as a subsequence. Put
simply, makes "foo" complete to both "barfoo" and "frodo". Add 'flex'
to 'completion-styles' or 'completion-category-overrides' to use it.
+++
** New face attribute ':extend' to control face extension at EOL.
There is a new face attribute :extend to use the face attributes to
extend after the end of the line until the end of the window. Such
:extend is set to nil by default in all faces except for 'hl-line' and
'region' because those extend until the end of the window by default.
** Connection-local variables
+++

View file

@ -233,7 +233,11 @@
(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."

View file

@ -342,6 +342,7 @@ is either `foreground-color', `background-color', or a keyword."
(: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 @@ Use `face-attribute' for finer control."
(let ((italic (face-attribute face :slant frame inherit)))
(memq italic '(italic oblique))))
(defun face-extend-p (face &optional frame inherit)
"Return non-nil if FACE specifies a non-nil extend.
If the optional argument FRAME is given, report on face FACE in that frame.
If FRAME is t, report on the defaults for face FACE (for new frames).
If FRAME is omitted or nil, use the selected frame.
Optional argument INHERIT is passed to `face-attribute'."
(eq (face-attribute face :extend frame inherit) t))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -760,6 +768,11 @@ For convenience, attributes `:family', `:foundry', `:width',
`: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 @@ Use `set-face-attribute' or `modify-face' for finer control."
(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 @@ an integer value."
(: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 @@ an integer value."
(:slant . "slant")
(:underline . "underline")
(:overline . "overline")
(:extend . "extend")
(:strike-through . "strike-through")
(:box . "box")
(:inverse-video . "inverse-video display")
@ -1549,7 +1575,8 @@ is given, in which case return its value instead."
;; (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)
@ -2314,24 +2341,24 @@ If you set `term-file-prefix' to nil, this function does nothing."
;; 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)

View file

@ -1385,6 +1385,7 @@ If FRAME is omitted or nil, use the selected frame."
(:stipple . "Stipple")
(:font . "Font")
(:fontset . "Fontset")
(:extend . "Extend")
(:inherit . "Inherit")))
(max-width (apply #'max (mapcar #'(lambda (x) (length (cdr x)))
attrs))))

View file

@ -78,7 +78,7 @@ when `global-hl-line-sticky-flag' is non-nil.")
:group 'convenience)
(defface hl-line
'((t :inherit highlight))
'((t :inherit highlight :extend t))
"Default face for highlighting the current line in Hl-Line mode."
:version "22.1"
:group 'hl-line)

View file

@ -1607,6 +1607,7 @@ enum lface_attribute_index
LFACE_INHERIT_INDEX,
LFACE_FONTSET_INDEX,
LFACE_DISTANT_FOREGROUND_INDEX,
LFACE_EXTEND_INDEX,
LFACE_VECTOR_SIZE
};
@ -1632,6 +1633,7 @@ enum face_box_type
enum face_underline_type
{
FACE_NO_UNDERLINE = 0,
FACE_UNDER_LINE,
FACE_UNDER_WAVE
};
@ -1675,11 +1677,9 @@ struct face
/* 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;
@ -1706,7 +1706,7 @@ struct face
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. */
@ -1714,7 +1714,6 @@ struct face
/* 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;
@ -1724,14 +1723,10 @@ struct face
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;
@ -1867,6 +1862,9 @@ struct face_cache
? 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)
@ -3553,12 +3551,13 @@ int lookup_derived_face (struct window *, struct frame *,
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,
ptrdiff_t *, enum face_id, bool);
ptrdiff_t *, enum face_id, bool,
enum lface_attribute_index);
int merge_faces (struct window *, Lisp_Object, int, int);
int compute_char_face (struct frame *, int, Lisp_Object);
void free_all_realized_faces (Lisp_Object);

View file

@ -3785,10 +3785,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, false, 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)
@ -3832,7 +3832,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 =
@ -3841,7 +3841,7 @@ font_range (ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t *limit,
: lookup_basic_face (w, f, DEFAULT_FACE_ID);
face_id = face_at_string_position (w, string, pos, 0, &ignore,
face_id, false);
face_id, false, 0);
}
face = FACE_FROM_ID (f, face_id);
}
@ -4618,7 +4618,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;

View file

@ -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;

View file

@ -2481,9 +2481,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;
@ -2494,13 +2494,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;
@ -2514,7 +2514,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

View file

@ -431,17 +431,26 @@ static Lisp_Object list_of_error;
met, return the (nonnegative) column number, else return a negative
value. */
static int
fill_column_indicator_column (struct it *it)
fill_column_indicator_column (struct it *it, int char_width)
{
if (Vdisplay_fill_column_indicator
&& !it->w->pseudo_window_p
&& it->continuation_lines_width == 0
&& CHARACTERP (Vdisplay_fill_column_indicator_character))
{
Lisp_Object col = (EQ (Vdisplay_fill_column_indicator_column, Qt)
? BVAR (current_buffer, fill_column)
: Vdisplay_fill_column_indicator_column);
/* The stretch width needs to consider the latter
added glyph in append_space_for_newline. */
if (RANGED_FIXNUMP (0, col, INT_MAX))
return XFIXNUM (col);
{
int icol = XFIXNUM (col);
if (!INT_MULTIPLY_WRAPV (char_width, icol, &icol)
&& !INT_ADD_WRAPV (it->lnum_pixel_width, icol, &icol))
return icol;
}
}
return -1;
}
@ -984,7 +993,7 @@ static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object,
static int handle_single_display_spec (struct it *, Lisp_Object, Lisp_Object,
Lisp_Object, struct text_pos *,
ptrdiff_t, int, bool, bool);
static int underlying_face_id (struct it *);
static int underlying_face_id (const struct it *);
#define face_before_it_pos(IT) face_before_or_after_it_pos (IT, true)
#define face_after_it_pos(IT) face_before_or_after_it_pos (IT, false)
@ -4148,56 +4157,20 @@ 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)
static int
face_at_pos (const struct it *it, enum lface_attribute_index attr_filter)
{
int new_face_id;
ptrdiff_t next_stop;
if (!STRINGP (it->string))
{
new_face_id
= face_at_buffer_position (it->w,
IT_CHARPOS (*it),
&next_stop,
(IT_CHARPOS (*it)
+ TEXT_PROP_DISTANCE_LIMIT),
false, it->base_face_id);
/* Is this a start of a run of characters with box face?
Caveat: this can be called for a freshly initialized
iterator; face_id is -1 in this case. We know that the new
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)
{
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);
/* 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
face there that's different from new_face_id. */
if (!old_face && IT_CHARPOS (*it) > BEG)
{
int prev_face_id = face_before_it_pos (it);
old_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
}
/* If the new face has a box, but the old face does not,
this is the start of a run of characters with box face,
i.e. this character has a shadow on the left side. */
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;
}
return face_at_buffer_position (it->w,
IT_CHARPOS (*it),
&next_stop,
(IT_CHARPOS (*it)
+ TEXT_PROP_DISTANCE_LIMIT),
false, it->base_face_id,
attr_filter);
}
else
{
@ -4207,7 +4180,7 @@ handle_face_prop (struct it *it)
Lisp_Object from_overlay
= (it->current.overlay_string_index >= 0
? it->string_overlays[it->current.overlay_string_index
% OVERLAY_STRING_CHUNK_SIZE]
% OVERLAY_STRING_CHUNK_SIZE]
: Qnil);
/* See if we got to this string directly or indirectly from
@ -4222,7 +4195,7 @@ handle_face_prop (struct it *it)
if (it->stack[i].current.overlay_string_index >= 0)
from_overlay
= it->string_overlays[it->stack[i].current.overlay_string_index
% OVERLAY_STRING_CHUNK_SIZE];
% OVERLAY_STRING_CHUNK_SIZE];
else if (! NILP (it->stack[i].from_overlay))
from_overlay = it->stack[i].from_overlay;
@ -4237,12 +4210,12 @@ handle_face_prop (struct it *it)
only on text properties and ignores overlays. */
base_face_id
= face_for_overlay_string (it->w,
IT_CHARPOS (*it),
&next_stop,
(IT_CHARPOS (*it)
+ TEXT_PROP_DISTANCE_LIMIT),
false,
from_overlay);
IT_CHARPOS (*it),
&next_stop,
(IT_CHARPOS (*it)
+ TEXT_PROP_DISTANCE_LIMIT),
false,
from_overlay);
}
else
{
@ -4271,35 +4244,60 @@ handle_face_prop (struct it *it)
: underlying_face_id (it);
}
new_face_id = face_at_string_position (it->w,
it->string,
IT_STRING_CHARPOS (*it),
bufpos,
&next_stop,
base_face_id, false);
return face_at_string_position (it->w,
it->string,
IT_STRING_CHARPOS (*it),
bufpos,
&next_stop,
base_face_id, false,
attr_filter);
} // !STRINGP (it->string))
}
/* Is this a start of a run of characters with box? Caveat:
this can be called for a freshly allocated iterator; face_id
is -1 is this case. We know that the new face will not
change until the next check pos, i.e. if the new face has a
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)
/* 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)
{
const int new_face_id = face_at_pos (it, 0);
/* Is this a start of a run of characters with box face?
Caveat: this can be called for a freshly initialized
iterator; face_id is -1 in this case. We know that the new
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)
{
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);
/* 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
face there that's different from new_face_id. */
if (!STRINGP (it->string)
&& !old_face
&& IT_CHARPOS (*it) > BEG)
{
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);
const int prev_face_id = face_before_it_pos (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->face_box_p = new_face->box != FACE_NO_BOX;
old_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
}
/* If the new face has a box, but the old face does not,
this is the start of a run of characters with box face,
i.e. this character has a shadow on the left side. */
it->face_id = new_face_id;
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;
}
it->face_id = new_face_id;
return HANDLED_NORMALLY;
}
@ -4310,7 +4308,7 @@ handle_face_prop (struct it *it)
Otherwise, use the iterator's base_face_id. */
static int
underlying_face_id (struct it *it)
underlying_face_id (const struct it *it)
{
int face_id = it->base_face_id, i;
@ -4423,12 +4421,9 @@ face_before_or_after_it_pos (struct it *it, bool before_p)
base_face_id = underlying_face_id (it);
/* Get the face for ASCII, or unibyte. */
face_id = face_at_string_position (it->w,
it->string,
charpos,
bufpos,
&next_check_charpos,
base_face_id, false);
face_id = face_at_string_position (it->w, it->string, charpos,
bufpos, &next_check_charpos,
base_face_id, false, 0);
/* Correct the face for charsets different from ASCII. Do it
for the multibyte case only. The face returned above is
@ -4527,7 +4522,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
@ -7638,7 +7633,8 @@ get_next_display_element (struct it *it)
next_face_id
= face_at_string_position (it->w, base_string,
CHARPOS (pos), 0,
&ignore, face_id, false);
&ignore, face_id,
false, 0);
it->end_of_box_run_p
= (FACE_FROM_ID (it->f, next_face_id)->box
== FACE_NO_BOX);
@ -7649,10 +7645,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);
@ -21366,80 +21363,78 @@ compute_line_metrics (struct it *it)
static bool
append_space_for_newline (struct it *it, bool default_face_p)
{
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (it->f))
int n = it->glyph_row->used[TEXT_AREA];
if (it->glyph_row->glyphs[TEXT_AREA] + n
< it->glyph_row->glyphs[1 + TEXT_AREA])
{
int n = it->glyph_row->used[TEXT_AREA];
/* Save some values that must not be changed.
Must save IT->c and IT->len because otherwise
ITERATOR_AT_END_P wouldn't work anymore after
append_space_for_newline has been called. */
enum display_element_type saved_what = it->what;
int saved_c = it->c, saved_len = it->len;
int saved_char_to_display = it->char_to_display;
int saved_x = it->current_x;
const int saved_face_id = it->face_id;
bool saved_box_end = it->end_of_box_run_p;
struct text_pos saved_pos = it->position;
Lisp_Object saved_object = it->object;
struct face *face;
if (it->glyph_row->glyphs[TEXT_AREA] + n
< it->glyph_row->glyphs[1 + TEXT_AREA])
it->what = IT_CHARACTER;
memset (&it->position, 0, sizeof it->position);
it->object = Qnil;
it->len = 1;
int char_width = 1;
if (default_face_p
#ifdef HAVE_WINDOW_SYSTEM
|| FRAME_WINDOW_P (it->f)
#endif
)
{
/* Save some values that must not be changed.
Must save IT->c and IT->len because otherwise
ITERATOR_AT_END_P wouldn't work anymore after
append_space_for_newline has been called. */
enum display_element_type saved_what = it->what;
int saved_c = it->c, saved_len = it->len;
int saved_char_to_display = it->char_to_display;
int saved_x = it->current_x;
int saved_face_id = it->face_id;
bool saved_box_end = it->end_of_box_run_p;
struct text_pos saved_pos;
Lisp_Object saved_object;
struct face *face;
saved_object = it->object;
saved_pos = it->position;
it->what = IT_CHARACTER;
memset (&it->position, 0, sizeof it->position);
it->object = Qnil;
it->len = 1;
int local_default_face_id =
const int local_default_face_id =
lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
struct face* default_face =
FACE_FROM_ID_OR_NULL (it->f, local_default_face_id);
/* 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. */
int indicator_column = (it->w->pseudo_window_p == 0
? fill_column_indicator_column (it)
: -1);
if (indicator_column >= 0)
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (it->f))
{
struct font *font = (default_face->font
? default_face->font
: FRAME_FONT (it->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)
&& it->current_x == column_x)
{
it->c = it->char_to_display
= XFIXNAT (Vdisplay_fill_column_indicator_character);
it->face_id
= merge_faces (it->w, Qfill_column_indicator,
0, saved_face_id);
face = FACE_FROM_ID (it->f, it->face_id);
goto produce_glyphs;
}
struct font *font = (default_face->font
? default_face->font
: FRAME_FONT (it->f));
char_width = (font->average_width
? font->average_width
: font->space_width);
}
#endif
if (default_face_p)
it->face_id = local_default_face_id;
}
/* 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. */
const int indicator_column =
fill_column_indicator_column (it, char_width);
if (it->current_x == indicator_column)
{
it->c = it->char_to_display
= XFIXNAT (Vdisplay_fill_column_indicator_character);
it->face_id
= merge_faces (it->w, Qfill_column_indicator,
0, saved_face_id);
face = FACE_FROM_ID (it->f, it->face_id);
}
else
{
it->c = it->char_to_display = ' ';
/* If the default face was remapped, be sure to use the
remapped face for the appended newline. */
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;
face = FACE_FROM_ID (it->f, it->face_id);
it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
@ -21453,10 +21448,11 @@ append_space_for_newline (struct it *it, bool default_face_p)
so leave the box flag set. */
&& saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x)
it->end_of_box_run_p = false;
produce_glyphs:
PRODUCE_GLYPHS (it);
}
PRODUCE_GLYPHS (it);
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (it->f))
{
/* Make sure this space glyph has the right ascent and
descent values, or else cursor at end of line will look
funny, and height of empty lines will be incorrect. */
@ -21477,8 +21473,8 @@ append_space_for_newline (struct it *it, bool default_face_p)
gui_produce_glyph for newline characters. */
height = get_it_property (it, Qline_height);
if (CONSP (height)
&& CONSP (XCDR (height))
&& NILP (XCDR (XCDR (height))))
&& CONSP (XCDR (height))
&& NILP (XCDR (XCDR (height))))
{
total_height = XCAR (XCDR (height));
height = XCAR (height);
@ -21507,12 +21503,12 @@ append_space_for_newline (struct it *it, bool default_face_p)
if (!NILP (total_height))
spacing = calc_line_height_property (it, total_height, font,
boff, false);
boff, false);
else
{
spacing = get_it_property (it, Qline_spacing);
spacing = calc_line_height_property (it, spacing, font,
boff, false);
boff, false);
}
if (FIXNUMP (spacing))
{
@ -21535,22 +21531,21 @@ append_space_for_newline (struct it *it, bool default_face_p)
g->ascent = it->max_ascent;
g->descent = it->max_descent;
it->override_ascent = -1;
it->constrain_row_ascent_descent_p = false;
it->current_x = saved_x;
it->object = saved_object;
it->position = saved_pos;
it->what = saved_what;
it->face_id = saved_face_id;
it->len = saved_len;
it->c = saved_c;
it->char_to_display = saved_char_to_display;
it->end_of_box_run_p = saved_box_end;
return true;
}
#endif /* HAVE_WINDOW_SYSTEM */
it->override_ascent = -1;
it->constrain_row_ascent_descent_p = false;
it->current_x = saved_x;
it->object = saved_object;
it->position = saved_pos;
it->what = saved_what;
it->face_id = saved_face_id;
it->len = saved_len;
it->c = saved_c;
it->char_to_display = saved_char_to_display;
it->end_of_box_run_p = saved_box_end;
return true;
}
#endif
return false;
}
@ -21566,7 +21561,6 @@ append_space_for_newline (struct it *it, bool default_face_p)
static void
extend_face_to_end_of_line (struct it *it)
{
struct face *face;
struct frame *f = it->f;
/* If line is already filled, do nothing. Non window-system frames
@ -21584,12 +21578,17 @@ 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
const int extend_face_id = (it->face_id == DEFAULT_FACE_ID
|| it->s != NULL)
? DEFAULT_FACE_ID
: face_at_pos (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));
struct face *face = FACE_FROM_ID (f, (it->face_before_selective_p
? it->saved_face_id
: extend_face_id));
if (FRAME_WINDOW_P (f)
&& MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
@ -21612,9 +21611,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 =
@ -21665,79 +21662,81 @@ 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
? 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);
const int indicator_column =
fill_column_indicator_column (it, char_width);
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 = extend_face_id;
it->avoid_cursor_p = true;
it->object = Qnil;
if (indicator_column >= 0
&& indicator_column > it->current_x
&& indicator_column < 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;
/* Here we substract char_width because we want the
column indicator in the column INDICATOR_COLUMN, not
after it. */
const int stretch_width =
indicator_column - it->current_x - char_width;
/* 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);
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);
}
/* 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;
}
/* Generate the glyph indicator only if
append_space_for_newline didn't already. */
if (it->current_x < indicator_column)
{
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, extend_face_id);
PRODUCE_GLYPHS (it);
it->face_id = save_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;
it->face_id = saved_face_id;
}
if (it->glyph_row->reversed_p)
{
@ -21783,10 +21782,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);
@ -21808,14 +21806,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;
@ -21854,34 +21849,31 @@ 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);
if (indicator_column >= 0
&& INT_ADD_WRAPV (it->lnum_pixel_width, indicator_column,
&indicator_column))
indicator_column = -1;
/* We need to subtract 1 to the indicator_column here because we
will add the indicator IN the column indicator number, not
after it. We compare the variable it->current_x before
producing the glyph. When FRAME_WINDOW_P we substract
CHAR_WIDTH calculating STRETCH_WIDTH for the same reason. */
const int indicator_column =
fill_column_indicator_column (it, 1) - 1;
do
{
int saved_face_id;
bool indicate = it->current_x == indicator_column;
if (indicate)
if (it->current_x != indicator_column)
PRODUCE_GLYPHS (it);
else
{
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, 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 = ' ';
}
@ -26581,8 +26573,8 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st
/* Initialize the iterator IT for iteration over STRING beginning
with index START. */
reseat_to_string (it, NILP (lisp_string) ? string : NULL, lisp_string, start,
precision, field_width, multibyte);
reseat_to_string (it, NILP (lisp_string) ? string : NULL, lisp_string,
start, precision, field_width, multibyte);
if (string && STRINGP (lisp_string))
/* LISP_STRING is the one returned by decode_mode_spec. We should
ignore its text properties. */
@ -26597,7 +26589,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st
it->face_id
= face_at_string_position (it->w, face_string, face_string_pos,
0, &endptr, it->base_face_id, false);
0, &endptr, it->base_face_id, false, 0);
face = FACE_FROM_ID (it->f, it->face_id);
it->face_box_p = face->box != FACE_NO_BOX;
}
@ -28502,7 +28494,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;
}
@ -32068,7 +32060,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);
}
@ -32757,11 +32749,10 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
hlinfo->mouse_face_past_end = false;
hlinfo->mouse_face_window = window;
hlinfo->mouse_face_face_id = face_at_string_position (w, string,
charpos,
0, &ignore,
glyph->face_id,
true);
hlinfo->mouse_face_face_id =
face_at_string_position (w, string, charpos, 0, &ignore,
glyph->face_id, true, 0);
show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
mouse_face_shown = true;
@ -33187,7 +33178,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
hlinfo->mouse_face_window = window;
hlinfo->mouse_face_face_id
= face_at_string_position (w, object, pos, 0, &ignore,
glyph->face_id, true);
glyph->face_id, true, 0);
show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
cursor = No_Cursor;
}

View file

@ -347,7 +347,8 @@ static struct face_cache *make_face_cache (struct frame *);
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 @@ the WIDTH times as wide as FACE on FRAME. */)
#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,
attr_filter))
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, attr_filter);
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, attr_filter))
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 @@ FRAME 0 means change the face on all frames, and change the default
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 @@ frames). If FRAME is omitted or nil, use the selected frame. */)
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 @@ Value is nil if ATTR doesn't have a discrete set of valid 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;
@ -4740,7 +4788,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;
}
@ -4784,6 +4832,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]))
@ -5094,7 +5145,7 @@ face for italic. */)
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)
@ -5362,6 +5413,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);
@ -5698,16 +5752,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,
@ -5715,7 +5767,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;
}
@ -5723,10 +5775,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. */
@ -5759,9 +5810,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;
}
}
}
@ -5980,7 +6031,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);
}
@ -5992,6 +6043,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.
@ -6011,7 +6064,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];
@ -6080,11 +6134,11 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos,
}
/* Begin with attributes from the default face. */
memcpy (attrs, default_face->lface, sizeof attrs);
memcpy (attrs, default_face->lface, sizeof(attrs));
/* 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, attr_filter);
/* Now merge the overlay data. */
noverlays = sort_overlays (overlay_vec, noverlays, w);
@ -6104,7 +6158,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]);
@ -6121,8 +6175,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);
@ -6188,7 +6243,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;
@ -6221,9 +6276,10 @@ face_for_overlay_string (struct window *w, ptrdiff_t pos,
int
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)
ptrdiff_t pos, ptrdiff_t bufpos,
ptrdiff_t *endptr, enum face_id base_face_id,
bool mouse_p,
enum lface_attribute_index attr_filter)
{
Lisp_Object prop, position, end, limit;
struct frame *f = XFRAME (WINDOW_FRAME (w));
@ -6267,7 +6323,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, attr_filter);
/* Look up a realized face with the given face attributes,
or realize a new one for ASCII characters. */
@ -6296,9 +6352,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;
@ -6318,17 +6373,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);
}
@ -6416,7 +6473,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);
}
@ -6541,6 +6598,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");

View file

@ -3813,9 +3813,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);
@ -3829,13 +3829,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;