1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-22 20:42:26 -08:00

Initial implementation of column-based margin indicators (bug#80025)

* src/dispextern.h (it): Add 'margin_column' field.

* src/xdisp.c (handle_single_display_spec): Parse margin column
specification '(margin left-margin COLUMN)' and set the column
to 'it->margin_column'.
(append_glyph): Support random-access indexing of margin column,
padding with spaces when the required column is beyond the used area.
This commit is contained in:
Juri Linkov 2025-12-21 09:32:32 +02:00
parent 040374be2d
commit 1c55ea07fa
2 changed files with 79 additions and 7 deletions

View file

@ -2876,6 +2876,12 @@ struct it
/* Face of the right fringe glyph. */
unsigned right_user_fringe_face_id : FACE_ID_BITS;
/* Target column position for margin indicators.
-1 means no specific column requested (use sequential filling).
>= 0 specifies the column (0-based) where the margin indicator
should be placed, with spaces padding unused columns. */
int margin_column;
/* True means we need to reorder bidirectional text for display
in the visual order. */
bool_bf bidi_p : 1;

View file

@ -6381,8 +6381,11 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
/* Prepare to handle `((margin left-margin) ...)',
`((margin right-margin) ...)' and `((margin nil) ...)'
prefixes for display specifications. */
prefixes for display specifications.
Also handle `((margin left-margin COLUMN) ...)' where COLUMN
specifies the column position (0-based) in the margin. */
location = Qunbound;
int margin_column = -1; /* -1 means no specific column requested */
if (CONSP (spec) && CONSP (XCAR (spec)))
{
Lisp_Object tem;
@ -6398,7 +6401,16 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
(NILP (tem)
|| EQ (tem, Qleft_margin)
|| EQ (tem, Qright_margin))))
location = tem;
{
location = tem;
/* Check a column specification after the margin type. */
tem = XCDR (XCAR (spec));
if (CONSP (tem)
&& (tem = XCDR (tem), CONSP (tem))
&& (tem = XCAR (tem), FIXNUMP (tem))
&& XFIXNUM (tem) >= 0)
margin_column = (int) XFIXNUM (tem);
}
}
if (BASE_EQ (location, Qunbound))
@ -6450,11 +6462,20 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
it->from_disp_prop_p = true;
if (NILP (location))
it->area = TEXT_AREA;
{
it->area = TEXT_AREA;
it->margin_column = -1;
}
else if (EQ (location, Qleft_margin))
it->area = LEFT_MARGIN_AREA;
{
it->area = LEFT_MARGIN_AREA;
it->margin_column = margin_column;
}
else
it->area = RIGHT_MARGIN_AREA;
{
it->area = RIGHT_MARGIN_AREA;
it->margin_column = margin_column;
}
if (STRINGP (value))
{
@ -31863,7 +31884,44 @@ append_glyph (struct it *it)
eassert (it->glyph_row);
eassert (it->char_to_display != '\n' && it->char_to_display != '\t');
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
int margin_column = -1;
if ((area == LEFT_MARGIN_AREA || area == RIGHT_MARGIN_AREA)
&& it->margin_column >= 0)
{
margin_column = it->margin_column;
}
if (margin_column >= 0
&& margin_column < (area == LEFT_MARGIN_AREA
? WINDOW_LEFT_MARGIN_WIDTH (it->w)
: WINDOW_RIGHT_MARGIN_WIDTH (it->w)))
{
/* Fill gaps between current position and target column with spaces. */
int face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
while (it->glyph_row->used[area] < margin_column
&& it->glyph_row->glyphs[area] + it->glyph_row->used[area]
< it->glyph_row->glyphs[area + 1])
{
struct glyph *fill_glyph =
it->glyph_row->glyphs[area] + it->glyph_row->used[area];
*fill_glyph = space_glyph;
fill_glyph->pixel_width = FRAME_COLUMN_WIDTH (it->f);
fill_glyph->face_id = face_id;
fill_glyph->frame = it->f;
++it->glyph_row->used[area];
}
glyph = it->glyph_row->glyphs[area] + margin_column;
/* Increment used counter only after filling with spaces,
but not when changing existing column value. */
if (margin_column >= it->glyph_row->used[area])
it->glyph_row->used[area] = margin_column + 1;
}
else
/* Fall back to the default sequential appending. */
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
if (glyph < it->glyph_row->glyphs[area + 1])
{
/* If the glyph row is reversed, we need to prepend the glyph
@ -31928,10 +31986,18 @@ append_glyph (struct it *it)
glyph->resolved_level = 0;
glyph->bidi_type = UNKNOWN_BT;
}
++it->glyph_row->used[area];
/* Increment used counter if not using column-based positioning,
since it already updated the counter above, but only after
filling with spaces, not when changing existing column value. */
if (margin_column < 0)
++it->glyph_row->used[area];
}
else
IT_EXPAND_MATRIX_WIDTH (it, area);
/* Reset the margin column for next use. */
if (margin_column >= 0)
it->margin_column = -1;
}
/* Store one glyph for the composition IT->cmp_it.id in IT->glyph_row.