diff options
| author | Eli Zaretskii | 2024-08-25 10:24:35 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2024-08-25 10:24:35 +0300 |
| commit | 71505b723c9fb9de20f6d38be7c73d595e9be3ce (patch) | |
| tree | 020a27270c21cedae068b09d9d0adb5a914785bb /src | |
| parent | 8a94cee3b58a59eac6ca24c001769f0fe12bf020 (diff) | |
| download | emacs-71505b723c9fb9de20f6d38be7c73d595e9be3ce.tar.gz emacs-71505b723c9fb9de20f6d38be7c73d595e9be3ce.zip | |
Fix handling of 'min-width' display property
* src/xdisp.c (get_display_property, display_min_width): Rename
BUFPOS to CHARPOS, to avoid confusion (it is not necessarily a
buffer position). Suggested by Jim Porter <jporterbugs@gmail.com>.
(get_display_property): Call 'Fget_char_property' to support
'min-width' properties of overlays as well.
(display_min_width): Handle the buffer and string cases more
accurately, without relying only on the values of positions.
(handle_display_prop, handle_single_display_spec): Pass correct
position to 'display_min_width', when iterating over a string.
(handle_display_prop): When OBJECT is a window, pass it to
display_min_width.
(set_iterator_to_next): Call 'display_min_width' when at end of a
display or overlay string. (Bug#72721)
* etc/NEWS: Announce the support for overlays.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xdisp.c | 75 |
1 files changed, 60 insertions, 15 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index 30771a1c83d..f9a10267bad 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -5632,16 +5632,25 @@ find_display_property (Lisp_Object disp, Lisp_Object prop) | |||
| 5632 | return XCDR (elem); | 5632 | return XCDR (elem); |
| 5633 | } | 5633 | } |
| 5634 | 5634 | ||
| 5635 | /* Return the value of 'display' text or overlay property PROP of | ||
| 5636 | character at CHARPOS in OBJECT. Return nil if character at CHARPOS | ||
| 5637 | has no 'display' property or if the 'display' property of that | ||
| 5638 | character does not include PROP. OBJECT can be a buffer or a window | ||
| 5639 | or a string. */ | ||
| 5635 | static Lisp_Object | 5640 | static Lisp_Object |
| 5636 | get_display_property (ptrdiff_t bufpos, Lisp_Object prop, Lisp_Object object) | 5641 | get_display_property (ptrdiff_t charpos, Lisp_Object prop, Lisp_Object object) |
| 5637 | { | 5642 | { |
| 5638 | return find_display_property (Fget_text_property (make_fixnum (bufpos), | 5643 | return find_display_property (Fget_char_property (make_fixnum (charpos), |
| 5639 | Qdisplay, object), | 5644 | Qdisplay, object), |
| 5640 | prop); | 5645 | prop); |
| 5641 | } | 5646 | } |
| 5642 | 5647 | ||
| 5648 | /* Handle 'display' property '(min-width (WIDTH))' at CHARPOS in OBJECT. | ||
| 5649 | OBJECT can be a buffer (or nil, which means the current buffer) or a | ||
| 5650 | string. MIN_WIDTH is the value of min-width spec that we expect to | ||
| 5651 | process. */ | ||
| 5643 | static void | 5652 | static void |
| 5644 | display_min_width (struct it *it, ptrdiff_t bufpos, | 5653 | display_min_width (struct it *it, ptrdiff_t charpos, |
| 5645 | Lisp_Object object, Lisp_Object width_spec) | 5654 | Lisp_Object object, Lisp_Object width_spec) |
| 5646 | { | 5655 | { |
| 5647 | /* We're being called at the end of the `min-width' sequence, | 5656 | /* We're being called at the end of the `min-width' sequence, |
| @@ -5652,15 +5661,21 @@ display_min_width (struct it *it, ptrdiff_t bufpos, | |||
| 5652 | /* When called from display_string (i.e., the mode line), | 5661 | /* When called from display_string (i.e., the mode line), |
| 5653 | we're being called with a string as the object, and we | 5662 | we're being called with a string as the object, and we |
| 5654 | may be called with many sub-strings belonging to the same | 5663 | may be called with many sub-strings belonging to the same |
| 5655 | :propertize run. */ | 5664 | :propertize run. */ |
| 5656 | if ((bufpos == 0 | 5665 | if ((STRINGP (object) |
| 5657 | && !EQ (it->min_width_property, | 5666 | && ((charpos == 0 |
| 5658 | get_display_property (0, Qmin_width, object))) | 5667 | && !EQ (it->min_width_property, |
| 5668 | get_display_property (0, Qmin_width, object))) | ||
| 5669 | || (charpos > 0 | ||
| 5670 | && EQ (it->min_width_property, | ||
| 5671 | get_display_property (charpos - 1, Qmin_width, | ||
| 5672 | object))))) | ||
| 5659 | /* In a buffer -- check that we're really right after the | 5673 | /* In a buffer -- check that we're really right after the |
| 5660 | sequence of characters covered by this `min-width'. */ | 5674 | sequence of characters covered by this `min-width'. */ |
| 5661 | || (bufpos > BEGV | 5675 | || (!STRINGP (object) |
| 5676 | && charpos > BEGV | ||
| 5662 | && EQ (it->min_width_property, | 5677 | && EQ (it->min_width_property, |
| 5663 | get_display_property (bufpos - 1, Qmin_width, object)))) | 5678 | get_display_property (charpos - 1, Qmin_width, object)))) |
| 5664 | { | 5679 | { |
| 5665 | Lisp_Object w = Qnil; | 5680 | Lisp_Object w = Qnil; |
| 5666 | double width; | 5681 | double width; |
| @@ -5707,15 +5722,18 @@ display_min_width (struct it *it, ptrdiff_t bufpos, | |||
| 5707 | the end. */ | 5722 | the end. */ |
| 5708 | if (CONSP (width_spec)) | 5723 | if (CONSP (width_spec)) |
| 5709 | { | 5724 | { |
| 5710 | if (bufpos == BEGV | 5725 | if ((!STRINGP (object) |
| 5726 | && charpos == BEGV) | ||
| 5711 | /* Mode line (see above). */ | 5727 | /* Mode line (see above). */ |
| 5712 | || (bufpos == 0 | 5728 | || (STRINGP (object) |
| 5729 | && charpos == 0 | ||
| 5713 | && !EQ (it->min_width_property, | 5730 | && !EQ (it->min_width_property, |
| 5714 | get_display_property (0, Qmin_width, object))) | 5731 | get_display_property (0, Qmin_width, object))) |
| 5715 | /* Buffer. */ | 5732 | /* Buffer. */ |
| 5716 | || (bufpos > BEGV | 5733 | || (!STRINGP (object) |
| 5734 | && charpos > BEGV | ||
| 5717 | && !EQ (width_spec, | 5735 | && !EQ (width_spec, |
| 5718 | get_display_property (bufpos - 1, Qmin_width, object)))) | 5736 | get_display_property (charpos - 1, Qmin_width, object)))) |
| 5719 | { | 5737 | { |
| 5720 | it->min_width_property = width_spec; | 5738 | it->min_width_property = width_spec; |
| 5721 | it->min_width_start = it->current_x; | 5739 | it->min_width_start = it->current_x; |
| @@ -5792,13 +5810,24 @@ handle_display_prop (struct it *it) | |||
| 5792 | Qdisplay, object, &overlay); | 5810 | Qdisplay, object, &overlay); |
| 5793 | 5811 | ||
| 5794 | /* Rest of the code must have OBJECT be either a string or a buffer. */ | 5812 | /* Rest of the code must have OBJECT be either a string or a buffer. */ |
| 5813 | Lisp_Object objwin = object; | ||
| 5795 | if (!STRINGP (it->string)) | 5814 | if (!STRINGP (it->string)) |
| 5796 | object = it->w->contents; | 5815 | object = it->w->contents; |
| 5797 | 5816 | ||
| 5798 | /* Handle min-width ends. */ | 5817 | /* Handle min-width ends. */ |
| 5799 | if (!NILP (it->min_width_property) | 5818 | if (!NILP (it->min_width_property) |
| 5800 | && NILP (find_display_property (propval, Qmin_width))) | 5819 | && NILP (find_display_property (propval, Qmin_width))) |
| 5801 | display_min_width (it, bufpos, object, Qnil); | 5820 | { |
| 5821 | ptrdiff_t pos = bufpos, start = BEGV; | ||
| 5822 | |||
| 5823 | if (STRINGP (object)) | ||
| 5824 | { | ||
| 5825 | pos = IT_STRING_CHARPOS (*it); | ||
| 5826 | start = 0; | ||
| 5827 | } | ||
| 5828 | if (pos > start) | ||
| 5829 | display_min_width (it, pos, objwin, Qnil); | ||
| 5830 | } | ||
| 5802 | 5831 | ||
| 5803 | if (NILP (propval)) | 5832 | if (NILP (propval)) |
| 5804 | return HANDLED_NORMALLY; | 5833 | return HANDLED_NORMALLY; |
| @@ -6099,7 +6128,13 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, | |||
| 6099 | && CONSP (XCAR (XCDR (spec)))) | 6128 | && CONSP (XCAR (XCDR (spec)))) |
| 6100 | { | 6129 | { |
| 6101 | if (it) | 6130 | if (it) |
| 6102 | display_min_width (it, bufpos, object, XCAR (XCDR (spec))); | 6131 | { |
| 6132 | ptrdiff_t pos = bufpos; | ||
| 6133 | |||
| 6134 | if (STRINGP (object)) | ||
| 6135 | pos = IT_STRING_CHARPOS (*it); | ||
| 6136 | display_min_width (it, pos, object, XCAR (XCDR (spec))); | ||
| 6137 | } | ||
| 6103 | return 0; | 6138 | return 0; |
| 6104 | } | 6139 | } |
| 6105 | 6140 | ||
| @@ -9004,6 +9039,10 @@ set_iterator_to_next (struct it *it, bool reseat_p) | |||
| 9004 | next, if there is one. */ | 9039 | next, if there is one. */ |
| 9005 | if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)) | 9040 | if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)) |
| 9006 | { | 9041 | { |
| 9042 | /* Maybe add a stretch glyph if the string had 'min-width' | ||
| 9043 | display spec. */ | ||
| 9044 | display_min_width (it, IT_STRING_CHARPOS (*it), it->string, | ||
| 9045 | Qnil); | ||
| 9007 | it->ellipsis_p = false; | 9046 | it->ellipsis_p = false; |
| 9008 | next_overlay_string (it); | 9047 | next_overlay_string (it); |
| 9009 | if (it->ellipsis_p) | 9048 | if (it->ellipsis_p) |
| @@ -9019,6 +9058,12 @@ set_iterator_to_next (struct it *it, bool reseat_p) | |||
| 9019 | if (IT_STRING_CHARPOS (*it) == SCHARS (it->string) | 9058 | if (IT_STRING_CHARPOS (*it) == SCHARS (it->string) |
| 9020 | && it->sp > 0) | 9059 | && it->sp > 0) |
| 9021 | { | 9060 | { |
| 9061 | /* Maybe add a stretch glyph if the string had 'min-width' | ||
| 9062 | display spec. We only do this if it->sp > 0 because | ||
| 9063 | mode-line strings are handled differently, see | ||
| 9064 | display_min_width. */ | ||
| 9065 | display_min_width (it, IT_STRING_CHARPOS (*it), it->string, | ||
| 9066 | Qnil); | ||
| 9022 | pop_it (it); | 9067 | pop_it (it); |
| 9023 | if (it->method == GET_FROM_STRING) | 9068 | if (it->method == GET_FROM_STRING) |
| 9024 | goto consider_string_end; | 9069 | goto consider_string_end; |