aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Ingebrigtsen2021-11-24 11:55:53 +0100
committerLars Ingebrigtsen2021-11-24 11:55:58 +0100
commita13b437c81f1f2e54555e7281480ea7e8eee8753 (patch)
tree602c0751912e81fef3113bd47720bdad4d649e9e /src
parent8efee422e1915a000f7220e680e3165407171388 (diff)
downloademacs-a13b437c81f1f2e54555e7281480ea7e8eee8753.tar.gz
emacs-a13b437c81f1f2e54555e7281480ea7e8eee8753.zip
Add support for the min-width display property
* doc/lispref/display.texi (Display Property): Document get-display-property. (Other Display Specs): Document min-width property. * src/dispextern.h (struct it): Add fields for min-width handling. * src/xdisp.c (find_display_property, get_display_property): New helper functions. (display_min_width): Insert stretch glyphs based on the min width. (Fget_display_property): New defun. (handle_display_prop): Handle min-width ends. (handle_single_display_spec): Handle min-width starts.
Diffstat (limited to 'src')
-rw-r--r--src/dispextern.h6
-rw-r--r--src/xdisp.c172
2 files changed, 175 insertions, 3 deletions
diff --git a/src/dispextern.h b/src/dispextern.h
index a698f6546b1..088297157ac 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2746,6 +2746,12 @@ struct it
2746 /* For iterating over bidirectional text. */ 2746 /* For iterating over bidirectional text. */
2747 struct bidi_it bidi_it; 2747 struct bidi_it bidi_it;
2748 bidi_dir_t paragraph_embedding; 2748 bidi_dir_t paragraph_embedding;
2749
2750 /* For handling the :min-width property. The object is the text
2751 property we're testing the `eq' of (nil if none), and the integer
2752 is the x position of the start of the run of glyphs. */
2753 Lisp_Object min_width_property;
2754 int min_width_start;
2749}; 2755};
2750 2756
2751 2757
diff --git a/src/xdisp.c b/src/xdisp.c
index 11ea8360343..4d3b4878058 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -822,6 +822,9 @@ bool help_echo_showing_p;
822/* Functions to mark elements as needing redisplay. */ 822/* Functions to mark elements as needing redisplay. */
823enum { REDISPLAY_SOME = 2}; /* Arbitrary choice. */ 823enum { REDISPLAY_SOME = 2}; /* Arbitrary choice. */
824 824
825static bool calc_pixel_width_or_height (double *, struct it *, Lisp_Object,
826 struct font *, bool, int *);
827
825void 828void
826redisplay_other_windows (void) 829redisplay_other_windows (void)
827{ 830{
@@ -5141,6 +5144,149 @@ setup_for_ellipsis (struct it *it, int len)
5141 it->ellipsis_p = true; 5144 it->ellipsis_p = true;
5142} 5145}
5143 5146
5147
5148static Lisp_Object
5149find_display_property (Lisp_Object disp, Lisp_Object prop)
5150{
5151 if (NILP (disp))
5152 return Qnil;
5153 /* We have a vector of display specs. */
5154 if (VECTORP (disp))
5155 {
5156 for (ptrdiff_t i = 0; i < ASIZE (disp); i++)
5157 {
5158 Lisp_Object elem = AREF (disp, i);
5159 if (CONSP (elem)
5160 && CONSP (XCDR (elem))
5161 && EQ (XCAR (elem), prop))
5162 return XCAR (XCDR (elem));
5163 }
5164 return Qnil;
5165 }
5166 /* We have a list of display specs. */
5167 else if (CONSP (disp)
5168 && CONSP (XCAR (disp)))
5169 {
5170 while (!NILP (disp))
5171 {
5172 Lisp_Object elem = XCAR (disp);
5173 if (CONSP (elem)
5174 && CONSP (XCDR (elem))
5175 && EQ (XCAR (elem), prop))
5176 return XCAR (XCDR (elem));
5177
5178 /* Check that we have a proper list before going to the next
5179 element. */
5180 if (CONSP (XCDR (disp)))
5181 disp = XCDR (disp);
5182 else
5183 disp = Qnil;
5184 }
5185 return Qnil;
5186 }
5187 /* A simple display spec. */
5188 else if (CONSP (disp)
5189 && CONSP (XCDR (disp))
5190 && EQ (XCAR (disp), prop))
5191 return XCAR (XCDR (disp));
5192 else
5193 return Qnil;
5194}
5195
5196static Lisp_Object get_display_property (ptrdiff_t bufpos, Lisp_Object prop,
5197 Lisp_Object object)
5198{
5199 return find_display_property (Fget_text_property (make_fixnum (bufpos),
5200
5201 Qdisplay, object),
5202 prop);
5203}
5204
5205static void
5206display_min_width (struct it *it, ptrdiff_t bufpos,
5207 Lisp_Object object, Lisp_Object width_spec)
5208{
5209 /* We're being called at the end of the `min-width' sequence,
5210 probably. */
5211 if (!NILP (it->min_width_property)
5212 && !EQ (width_spec, it->min_width_property))
5213 {
5214 if (!it->glyph_row)
5215 return;
5216
5217 /* Check that we're really right after the sequence of
5218 characters covered by this `min-width'. */
5219 if (bufpos > BEGV
5220 && EQ (it->min_width_property,
5221 get_display_property (bufpos - 1, Qmin_width, object)))
5222 {
5223 Lisp_Object w = Qnil;
5224 double width;
5225#ifdef HAVE_WINDOW_SYSTEM
5226 if (FRAME_WINDOW_P (it->f))
5227 {
5228 struct font *font = NULL;
5229 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5230 font = face->font ? face->font : FRAME_FONT (it->f);
5231 calc_pixel_width_or_height (&width, it,
5232 XCAR (it->min_width_property),
5233 font, true, NULL);
5234 width -= it->current_x - it->min_width_start;
5235 w = list1 (make_int (width));
5236 }
5237 else
5238#endif
5239 {
5240 calc_pixel_width_or_height (&width, it,
5241 XCAR (it->min_width_property),
5242 NULL, true, NULL);
5243 width -= (it->current_x - it->min_width_start) /
5244 FRAME_COLUMN_WIDTH (it->f);
5245 w = make_int (width);
5246 }
5247
5248 /* Insert the stretch glyph. */
5249 it->object = list3 (Qspace, QCwidth, w);
5250 produce_stretch_glyph (it);
5251 it->min_width_property = Qnil;
5252 }
5253 }
5254
5255 /* We're at the start of a `min-width' sequence -- record the
5256 position and the property, so that we can later see if we're at
5257 the end. */
5258 if (CONSP (width_spec))
5259 {
5260 if (bufpos == BEGV
5261 || (bufpos > BEGV
5262 && !EQ (width_spec,
5263 get_display_property (bufpos - 1, Qmin_width, object))))
5264 {
5265 it->min_width_property = width_spec;
5266 it->min_width_start = it->current_x;
5267 }
5268 }
5269}
5270
5271DEFUN ("get-display-property", Fget_display_property,
5272 Sget_display_property, 2, 4, 0,
5273 doc: /* Get the `display' property PROP at POSITION.
5274If OBJECT, this should be a buffer or string where the property is
5275fetched from. This defaults to the current buffer.
5276
5277If PROPERTIES, use those properties instead of the properties at
5278POSITION. */)
5279 (Lisp_Object position, Lisp_Object prop, Lisp_Object object,
5280 Lisp_Object properties)
5281{
5282 if (NILP (properties))
5283 properties = Fget_text_property (position, Qdisplay, object);
5284 else
5285 CHECK_LIST (properties);
5286
5287 return find_display_property (properties, prop);
5288}
5289
5144 5290
5145 5291
5146/*********************************************************************** 5292/***********************************************************************
@@ -5187,16 +5333,22 @@ handle_display_prop (struct it *it)
5187 if (!it->string_from_display_prop_p) 5333 if (!it->string_from_display_prop_p)
5188 it->area = TEXT_AREA; 5334 it->area = TEXT_AREA;
5189 5335
5336 if (!STRINGP (it->string))
5337 object = it->w->contents;
5338
5190 propval = get_char_property_and_overlay (make_fixnum (position->charpos), 5339 propval = get_char_property_and_overlay (make_fixnum (position->charpos),
5191 Qdisplay, object, &overlay); 5340 Qdisplay, object, &overlay);
5341
5342 /* Handle min-width ends. */
5343 if (! NILP (it->min_width_property)
5344 && NILP (find_display_property (propval, Qmin_width)))
5345 display_min_width (it, bufpos, object, Qnil);
5346
5192 if (NILP (propval)) 5347 if (NILP (propval))
5193 return HANDLED_NORMALLY; 5348 return HANDLED_NORMALLY;
5194 /* Now OVERLAY is the overlay that gave us this property, or nil 5349 /* Now OVERLAY is the overlay that gave us this property, or nil
5195 if it was a text property. */ 5350 if it was a text property. */
5196 5351
5197 if (!STRINGP (it->string))
5198 object = it->w->contents;
5199
5200 display_replaced = handle_display_spec (it, propval, object, overlay, 5352 display_replaced = handle_display_spec (it, propval, object, overlay,
5201 position, bufpos, 5353 position, bufpos,
5202 FRAME_WINDOW_P (it->f)); 5354 FRAME_WINDOW_P (it->f));
@@ -5250,6 +5402,7 @@ handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5250 && !(CONSP (XCAR (spec)) && EQ (XCAR (XCAR (spec)), Qmargin)) 5402 && !(CONSP (XCAR (spec)) && EQ (XCAR (XCAR (spec)), Qmargin))
5251 && !EQ (XCAR (spec), Qleft_fringe) 5403 && !EQ (XCAR (spec), Qleft_fringe)
5252 && !EQ (XCAR (spec), Qright_fringe) 5404 && !EQ (XCAR (spec), Qright_fringe)
5405 && !EQ (XCAR (spec), Qmin_width)
5253 && !NILP (XCAR (spec))) 5406 && !NILP (XCAR (spec)))
5254 { 5407 {
5255 for (; CONSP (spec); spec = XCDR (spec)) 5408 for (; CONSP (spec); spec = XCDR (spec))
@@ -5483,6 +5636,17 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5483 return 0; 5636 return 0;
5484 } 5637 }
5485 5638
5639 /* Handle `(min-width (WIDTH))'. */
5640 if (CONSP (spec)
5641 && EQ (XCAR (spec), Qmin_width)
5642 && CONSP (XCDR (spec))
5643 && CONSP (XCAR (XCDR (spec))))
5644 {
5645 if (it)
5646 display_min_width (it, bufpos, object, XCAR (XCDR (spec)));
5647 return 0;
5648 }
5649
5486 /* Handle `(slice X Y WIDTH HEIGHT)'. */ 5650 /* Handle `(slice X Y WIDTH HEIGHT)'. */
5487 if (CONSP (spec) 5651 if (CONSP (spec)
5488 && EQ (XCAR (spec), Qslice)) 5652 && EQ (XCAR (spec), Qslice))
@@ -7186,6 +7350,7 @@ reseat_1 (struct it *it, struct text_pos pos, bool set_stop_p)
7186 } 7350 }
7187 /* This make the information stored in it->cmp_it invalidate. */ 7351 /* This make the information stored in it->cmp_it invalidate. */
7188 it->cmp_it.id = -1; 7352 it->cmp_it.id = -1;
7353 it->min_width_property = Qnil;
7189} 7354}
7190 7355
7191 7356
@@ -35121,6 +35286,7 @@ be let-bound around code that needs to disable messages temporarily. */);
35121 defsubr (&Smove_point_visually); 35286 defsubr (&Smove_point_visually);
35122 defsubr (&Sbidi_find_overridden_directionality); 35287 defsubr (&Sbidi_find_overridden_directionality);
35123 defsubr (&Sdisplay__line_is_continued_p); 35288 defsubr (&Sdisplay__line_is_continued_p);
35289 defsubr (&Sget_display_property);
35124 35290
35125 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook"); 35291 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
35126 DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map"); 35292 DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");