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:
commit
3d6075e3ee
14 changed files with 489 additions and 375 deletions
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
7
etc/NEWS
7
etc/NEWS
|
@ -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
|
||||
|
||||
+++
|
||||
|
|
|
@ -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."
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
10
src/font.c
10
src/font.c
|
@ -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;
|
||||
|
|
10
src/nsterm.m
10
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;
|
||||
|
|
|
@ -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
|
||||
|
|
561
src/xdisp.c
561
src/xdisp.c
|
@ -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;
|
||||
}
|
||||
|
|
144
src/xfaces.c
144
src/xfaces.c
|
@ -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");
|
||||
|
|
10
src/xterm.c
10
src/xterm.c
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue