GNU bug report logs - #77452
31.0.50; Wide characters in left margin on ttys

Previous Next

Package: emacs;

Reported by: Gerd Möllmann <gerd.moellmann <at> gmail.com>

Date: Wed, 2 Apr 2025 09:53:01 UTC

Severity: normal

Found in version 31.0.50

Done: Eli Zaretskii <eliz <at> gnu.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 77452 in the body.
You can then email your comments to 77452 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#77452; Package emacs. (Wed, 02 Apr 2025 09:53:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Gerd Möllmann <gerd.moellmann <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Wed, 02 Apr 2025 09:53:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: 31.0.50; Wide characters in left margin on ttys
Date: Wed, 02 Apr 2025 11:52:46 +0200
in emacs -Q -nw, eval 

  (defun foo ()
    (interactive)
    (with-current-buffer (get-buffer-create "*foo*")
      (setq left-margin-width 2)
      (erase-buffer)
      (insert "abc")
      (insert (propertize "def" 'display '((margin left-margin) "1💡")))))

and M-x foo.

This creates a buffer "*foo*" displaying a string in a left
margin area of width 2. The string consists of 2 characters but has a display
width of 3 since the light bulb character has a display width of 2.

  (char-width ?💡)
   => 2

So, writing the left margin string to the terminal advances the output
cursor by 3 not 2. This confuses the display engine, as one can witness
by editing in the *foo* buffer, adding new lines etc.


In GNU Emacs 31.0.50 (build 1, aarch64-apple-darwin24.3.0, NS
 appkit-2575.40 Version 15.3.2 (Build 24D81)) of 2025-04-02 built on
 pro2
Repository revision: 71b3298c0e813ba1432e75370c460eea5caf72d5
Repository branch: master
System Description:  macOS 15.3.2




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77452; Package emacs. (Wed, 02 Apr 2025 12:39:02 GMT) Full text and rfc822 format available.

Message #8 received at 77452 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: 77452 <at> debbugs.gnu.org
Subject: Re: bug#77452: 31.0.50; Wide characters in left margin on ttys
Date: Wed, 02 Apr 2025 15:38:02 +0300
> From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
> Date: Wed, 02 Apr 2025 11:52:46 +0200
> 
> in emacs -Q -nw, eval 
> 
>   (defun foo ()
>     (interactive)
>     (with-current-buffer (get-buffer-create "*foo*")
>       (setq left-margin-width 2)
>       (erase-buffer)
>       (insert "abc")
>       (insert (propertize "def" 'display '((margin left-margin) "1💡")))))
> 
> and M-x foo.
> 
> This creates a buffer "*foo*" displaying a string in a left
> margin area of width 2. The string consists of 2 characters but has a display
> width of 3 since the light bulb character has a display width of 2.
> 
>   (char-width ?💡)
>    => 2
> 
> So, writing the left margin string to the terminal advances the output
> cursor by 3 not 2. This confuses the display engine, as one can witness
> by editing in the *foo* buffer, adding new lines etc.

The problem is not the char-width of 💡 nor with advancement of the
cursor, the problem is that the string "1💡" doesn't fit in the
2-column wide margin, and Emacs should have displayed only "1", since
we cannot clip glyphs on TTY frames.

Are you going to work on fixing this long-time problem?  Or should I?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77452; Package emacs. (Wed, 02 Apr 2025 13:06:02 GMT) Full text and rfc822 format available.

Message #11 received at 77452 <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 77452 <at> debbugs.gnu.org
Subject: Re: bug#77452: 31.0.50; Wide characters in left margin on ttys
Date: Wed, 02 Apr 2025 15:04:55 +0200
Eli Zaretskii <eliz <at> gnu.org> writes:

>> From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
>> Date: Wed, 02 Apr 2025 11:52:46 +0200
>> 
>> in emacs -Q -nw, eval 
>> 
>>   (defun foo ()
>>     (interactive)
>>     (with-current-buffer (get-buffer-create "*foo*")
>>       (setq left-margin-width 2)
>>       (erase-buffer)
>>       (insert "abc")
>>       (insert (propertize "def" 'display '((margin left-margin) "1💡")))))
>> 
>> and M-x foo.
>> 
>> This creates a buffer "*foo*" displaying a string in a left
>> margin area of width 2. The string consists of 2 characters but has a display
>> width of 3 since the light bulb character has a display width of 2.
>> 
>>   (char-width ?💡)
>>    => 2
>> 
>> So, writing the left margin string to the terminal advances the output
>> cursor by 3 not 2. This confuses the display engine, as one can witness
>> by editing in the *foo* buffer, adding new lines etc.
>
> The problem is not the char-width of 💡 nor with advancement of the
> cursor, the problem is that the string "1💡" doesn't fit in the
> 2-column wide margin, and Emacs should have displayed only "1", since
> we cannot clip glyphs on TTY frames.

Exactly, that pretty much what I meant :-). The wide character may not
be output to the terminal, otherwise display and matrices get out of
sync.

> Are you going to work on fixing this long-time problem?  Or should I?

I tried to read and understand display_line etc. this morning, but I'm afraid
there is too much going on there for me to find the cause of this in
reasonable time.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77452; Package emacs. (Wed, 02 Apr 2025 14:49:01 GMT) Full text and rfc822 format available.

Message #14 received at 77452 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: 77452 <at> debbugs.gnu.org
Subject: Re: bug#77452: 31.0.50; Wide characters in left margin on ttys
Date: Wed, 02 Apr 2025 17:47:47 +0300
> From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
> Cc: 77452 <at> debbugs.gnu.org
> Date: Wed, 02 Apr 2025 15:04:55 +0200
> 
> Eli Zaretskii <eliz <at> gnu.org> writes:
> 
> > The problem is not the char-width of 💡 nor with advancement of the
> > cursor, the problem is that the string "1💡" doesn't fit in the
> > 2-column wide margin, and Emacs should have displayed only "1", since
> > we cannot clip glyphs on TTY frames.
> 
> Exactly, that pretty much what I meant :-). The wide character may not
> be output to the terminal, otherwise display and matrices get out of
> sync.
> 
> > Are you going to work on fixing this long-time problem?  Or should I?
> 
> I tried to read and understand display_line etc. this morning, but I'm afraid
> there is too much going on there for me to find the cause of this in
> reasonable time.

Does the below look right to you?

diff --git a/src/xdisp.c b/src/xdisp.c
index 2c676c0..1c54e7c 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -25685,7 +25685,7 @@ #define RECORD_MAX_MIN_POS(IT)					\
 
       /* Now, get the metrics of what we want to display.  This also
 	 generates glyphs in `row' (which is IT->glyph_row).  */
-      n_glyphs_before = row->used[TEXT_AREA];
+      n_glyphs_before = row->used[it->area];
       x = it->current_x;
 
       /* Remember the line height so far in case the next element doesn't
@@ -25732,6 +25732,7 @@ #define RECORD_MAX_MIN_POS(IT)					\
 	 the next one.  */
       if (it->area != TEXT_AREA)
 	{
+	  enum glyph_row_area area = it->area;
 	  row->ascent = max (row->ascent, it->max_ascent);
 	  row->height = max (row->height, it->max_ascent + it->max_descent);
 	  row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
@@ -25740,6 +25741,14 @@ #define RECORD_MAX_MIN_POS(IT)					\
 	  row->extra_line_spacing = max (row->extra_line_spacing,
 					 it->max_extra_line_spacing);
 	  set_iterator_to_next (it, true);
+	  /* If we exhausted the glyphs of the marginal area...	 */
+	  if (it->area != area
+	      /* ...and the last character was multi-column...	*/
+	      && it->nglyphs > 1
+	      /* ...and not all of its glyphs fit in the marginal area... */
+	      && row->used[area] < n_glyphs_before + it->nglyphs)
+	      /* ...then reset back to the previous character.	*/
+	    row->used[area] = n_glyphs_before;
 	  /* If we didn't handle the line/wrap prefix above, and the
 	     call to set_iterator_to_next just switched to TEXT_AREA,
 	     process the prefix now.  */




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77452; Package emacs. (Wed, 02 Apr 2025 14:53:05 GMT) Full text and rfc822 format available.

Message #17 received at 77452 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: gerd.moellmann <at> gmail.com
Cc: 77452 <at> debbugs.gnu.org
Subject: Re: bug#77452: 31.0.50; Wide characters in left margin on ttys
Date: Wed, 02 Apr 2025 17:52:27 +0300
> Cc: 77452 <at> debbugs.gnu.org
> Date: Wed, 02 Apr 2025 17:47:47 +0300
> From: Eli Zaretskii <eliz <at> gnu.org>
> 
> > I tried to read and understand display_line etc. this morning, but I'm afraid
> > there is too much going on there for me to find the cause of this in
> > reasonable time.
> 
> Does the below look right to you?

Sorry, please try the slightly more safe change below:

diff --git a/src/xdisp.c b/src/xdisp.c
index 2c676c0..33d7314 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -25685,7 +25685,7 @@ #define RECORD_MAX_MIN_POS(IT)					\
 
       /* Now, get the metrics of what we want to display.  This also
 	 generates glyphs in `row' (which is IT->glyph_row).  */
-      n_glyphs_before = row->used[TEXT_AREA];
+      n_glyphs_before = row->used[it->area];
       x = it->current_x;
 
       /* Remember the line height so far in case the next element doesn't
@@ -25732,6 +25732,7 @@ #define RECORD_MAX_MIN_POS(IT)					\
 	 the next one.  */
       if (it->area != TEXT_AREA)
 	{
+	  enum glyph_row_area area = it->area;
 	  row->ascent = max (row->ascent, it->max_ascent);
 	  row->height = max (row->height, it->max_ascent + it->max_descent);
 	  row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
@@ -25740,6 +25741,15 @@ #define RECORD_MAX_MIN_POS(IT)					\
 	  row->extra_line_spacing = max (row->extra_line_spacing,
 					 it->max_extra_line_spacing);
 	  set_iterator_to_next (it, true);
+	  if (!FRAME_WINDOW_P (it->f)
+	      /* If we exhausted the glyphs of the marginal area...	 */
+	      it->area != area
+	      /* ...and the last character was multi-column...	*/
+	      && it->nglyphs > 1
+	      /* ...and not all of its glyphs fit in the marginalk area... */
+	      && row->used[area] < n_glyphs_before + it->nglyphs)
+	      /* ...then reset back to the previous character.	*/
+	    row->used[area] = n_glyphs_before;
 	  /* If we didn't handle the line/wrap prefix above, and the
 	     call to set_iterator_to_next just switched to TEXT_AREA,
 	     process the prefix now.  */




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77452; Package emacs. (Wed, 02 Apr 2025 15:23:02 GMT) Full text and rfc822 format available.

Message #20 received at 77452 <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 77452 <at> debbugs.gnu.org
Subject: Re: bug#77452: 31.0.50; Wide characters in left margin on ttys
Date: Wed, 02 Apr 2025 17:22:24 +0200
Eli Zaretskii <eliz <at> gnu.org> writes:

>> Cc: 77452 <at> debbugs.gnu.org
>> Date: Wed, 02 Apr 2025 17:47:47 +0300
>> From: Eli Zaretskii <eliz <at> gnu.org>
>>
>> > I tried to read and understand display_line etc. this morning, but I'm afraid
>> > there is too much going on there for me to find the cause of this in
>> > reasonable time.
>>
>> Does the below look right to you?
>
> Sorry, please try the slightly more safe change below:

Thanks! LGTM, and it fixes the problem.

> @@ -25740,6 +25741,15 @@ #define RECORD_MAX_MIN_POS(IT)					\
>  	  row->extra_line_spacing = max (row->extra_line_spacing,
>  					 it->max_extra_line_spacing);
>  	  set_iterator_to_next (it, true);
> +	  if (!FRAME_WINDOW_P (it->f)
> +	      /* If we exhausted the glyphs of the marginal area...	 */
> +	      it->area != area
              ^^^
              && missing




Reply sent to Eli Zaretskii <eliz <at> gnu.org>:
You have taken responsibility. (Wed, 02 Apr 2025 17:30:02 GMT) Full text and rfc822 format available.

Notification sent to Gerd Möllmann <gerd.moellmann <at> gmail.com>:
bug acknowledged by developer. (Wed, 02 Apr 2025 17:30:02 GMT) Full text and rfc822 format available.

Message #25 received at 77452-done <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: 77452-done <at> debbugs.gnu.org
Subject: Re: bug#77452: 31.0.50; Wide characters in left margin on ttys
Date: Wed, 02 Apr 2025 20:29:48 +0300
> From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
> Cc: 77452 <at> debbugs.gnu.org
> Date: Wed, 02 Apr 2025 17:22:24 +0200
> 
> Eli Zaretskii <eliz <at> gnu.org> writes:
> 
> >> Cc: 77452 <at> debbugs.gnu.org
> >> Date: Wed, 02 Apr 2025 17:47:47 +0300
> >> From: Eli Zaretskii <eliz <at> gnu.org>
> >>
> >> > I tried to read and understand display_line etc. this morning, but I'm afraid
> >> > there is too much going on there for me to find the cause of this in
> >> > reasonable time.
> >>
> >> Does the below look right to you?
> >
> > Sorry, please try the slightly more safe change below:
> 
> Thanks! LGTM, and it fixes the problem.

Thanks, installed on master, and closing the bug.




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Thu, 01 May 2025 11:24:11 GMT) Full text and rfc822 format available.

This bug report was last modified 49 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.