Fix 'current-column' in the presence of display strings

* src/indent.c (check_display_width): Support calculation of width
of 'display' properties whose values are strings.  This fixes the
value returned by 'current-column' when display strings are
present between BOL and point.  (Bug#53795)
This commit is contained in:
Eli Zaretskii 2022-02-05 13:01:24 +02:00
parent 9029212c86
commit 4243747b1b

View file

@ -468,31 +468,40 @@ check_display_width (ptrdiff_t pos, ptrdiff_t col, ptrdiff_t *endpos)
{
Lisp_Object val, overlay;
if (CONSP (val = get_char_property_and_overlay
(make_fixnum (pos), Qdisplay, Qnil, &overlay))
&& EQ (Qspace, XCAR (val)))
{ /* FIXME: Use calc_pixel_width_or_height. */
Lisp_Object plist = XCDR (val), prop;
if (!NILP (val = get_char_property_and_overlay (make_fixnum (pos), Qdisplay,
Qnil, &overlay)))
{
int width = -1;
EMACS_INT align_to_max =
(col < MOST_POSITIVE_FIXNUM - INT_MAX
? (EMACS_INT) INT_MAX + col
: MOST_POSITIVE_FIXNUM);
Lisp_Object plist = Qnil;
if ((prop = Fplist_get (plist, QCwidth),
RANGED_FIXNUMP (0, prop, INT_MAX))
|| (prop = Fplist_get (plist, QCrelative_width),
RANGED_FIXNUMP (0, prop, INT_MAX)))
width = XFIXNUM (prop);
else if (FLOATP (prop) && 0 <= XFLOAT_DATA (prop)
&& XFLOAT_DATA (prop) <= INT_MAX)
width = (int)(XFLOAT_DATA (prop) + 0.5);
else if ((prop = Fplist_get (plist, QCalign_to),
RANGED_FIXNUMP (col, prop, align_to_max)))
width = XFIXNUM (prop) - col;
else if (FLOATP (prop) && col <= XFLOAT_DATA (prop)
&& (XFLOAT_DATA (prop) <= align_to_max))
width = (int)(XFLOAT_DATA (prop) + 0.5) - col;
/* Handle '(space ...)' display specs. */
if (CONSP (val) && EQ (Qspace, XCAR (val)))
{ /* FIXME: Use calc_pixel_width_or_height. */
Lisp_Object prop;
EMACS_INT align_to_max =
(col < MOST_POSITIVE_FIXNUM - INT_MAX
? (EMACS_INT) INT_MAX + col
: MOST_POSITIVE_FIXNUM);
plist = XCDR (val);
if ((prop = Fplist_get (plist, QCwidth),
RANGED_FIXNUMP (0, prop, INT_MAX))
|| (prop = Fplist_get (plist, QCrelative_width),
RANGED_FIXNUMP (0, prop, INT_MAX)))
width = XFIXNUM (prop);
else if (FLOATP (prop) && 0 <= XFLOAT_DATA (prop)
&& XFLOAT_DATA (prop) <= INT_MAX)
width = (int)(XFLOAT_DATA (prop) + 0.5);
else if ((prop = Fplist_get (plist, QCalign_to),
RANGED_FIXNUMP (col, prop, align_to_max)))
width = XFIXNUM (prop) - col;
else if (FLOATP (prop) && col <= XFLOAT_DATA (prop)
&& (XFLOAT_DATA (prop) <= align_to_max))
width = (int)(XFLOAT_DATA (prop) + 0.5) - col;
}
/* Handle 'display' strings. */
else if (STRINGP (val))
width = XFIXNUM (Fstring_width (val, Qnil, Qnil));
if (width >= 0)
{
@ -504,7 +513,8 @@ check_display_width (ptrdiff_t pos, ptrdiff_t col, ptrdiff_t *endpos)
/* For :relative-width, we need to multiply by the column
width of the character at POS, if it is greater than 1. */
if (!NILP (Fplist_get (plist, QCrelative_width))
if (!NILP (plist)
&& !NILP (Fplist_get (plist, QCrelative_width))
&& !NILP (BVAR (current_buffer, enable_multibyte_characters)))
{
int b, wd;
@ -516,6 +526,7 @@ check_display_width (ptrdiff_t pos, ptrdiff_t col, ptrdiff_t *endpos)
return width;
}
}
return -1;
}