* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
[not found] <87wnakl5md.fsf@disroot.org>
@ 2022-09-06 6:59 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-06 8:03 ` Gerd Möllmann
0 siblings, 1 reply; 26+ messages in thread
From: Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-09-06 6:59 UTC (permalink / raw)
To: 57607
[-- Attachment #1: Type: text/plain, Size: 665 bytes --]
Forwarding to bug-gnu-emacs list.
Akib Azmain Turja <akib@disroot.org> writes:
> Emacs never writes to the bottom-right corner of a terminal, because the
> terminal might open a new line at bottom of screen. But terminals
> having any of 'ich', 'ich1' and 'smir' capabilities can write to the
> bottom-right corner of the terminal. Almost all terminals have at least
> one of the aforementioned capabilities. Why doesn't Emacs make use of
> that?
--
Akib Azmain Turja
Find me on Mastodon at @akib@hostux.social.
This message is signed by me with my GnuPG key. Its fingerprint is:
7001 8CE5 819F 17A3 BBA6 66AF E74F 0EFA 922A E7F5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-06 6:59 ` bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-09-06 8:03 ` Gerd Möllmann
2022-09-06 10:07 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
0 siblings, 1 reply; 26+ messages in thread
From: Gerd Möllmann @ 2022-09-06 8:03 UTC (permalink / raw)
To: Akib Azmain Turja; +Cc: 57607
Akib Azmain Turja <akib@disroot.org> writes:
> Forwarding to bug-gnu-emacs list.
>
> Akib Azmain Turja <akib@disroot.org> writes:
>
>> Emacs never writes to the bottom-right corner of a terminal, because the
>> terminal might open a new line at bottom of screen. But terminals
>> having any of 'ich', 'ich1' and 'smir' capabilities can write to the
>> bottom-right corner of the terminal. Almost all terminals have at least
>> one of the aforementioned capabilities. Why doesn't Emacs make use of
>> that?
I don't know. And I don't know if that would work, it would require
investigation.
Emacs already writes to the bottom-right corner in case neither "am" nor
"xn" are defined for the terminal in question. vt100 and xterm, for
instance, have "am" defined here, so Emacs doesn't write to the
bottom-right corner.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-06 8:03 ` Gerd Möllmann
@ 2022-09-06 10:07 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-06 12:00 ` Gerd Möllmann
0 siblings, 1 reply; 26+ messages in thread
From: Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-09-06 10:07 UTC (permalink / raw)
To: Gerd Möllmann; +Cc: 57607
[-- Attachment #1: Type: text/plain, Size: 6915 bytes --]
Gerd Möllmann <gerd.moellmann@gmail.com> writes:
> Akib Azmain Turja <akib@disroot.org> writes:
>
>> Forwarding to bug-gnu-emacs list.
>>
>> Akib Azmain Turja <akib@disroot.org> writes:
>>
>>> Emacs never writes to the bottom-right corner of a terminal, because the
>>> terminal might open a new line at bottom of screen. But terminals
>>> having any of 'ich', 'ich1' and 'smir' capabilities can write to the
>>> bottom-right corner of the terminal. Almost all terminals have at least
>>> one of the aforementioned capabilities. Why doesn't Emacs make use of
>>> that?
>
> I don't know. And I don't know if that would work, it would require
> investigation.
There must be a way reliably way to do so, because ncurses can write to
the last character cell on terminal on linux console and xterm-like
terminal emulators.
>
> Emacs already writes to the bottom-right corner in case neither "am" nor
> "xn" are defined for the terminal in question. vt100 and xterm, for
> instance, have "am" defined here, so Emacs doesn't write to the
> bottom-right corner.
I repeat: vt100 and xterm-like terminal having any of 'ich', 'ich1',
'il' and 'il1' or both 'smir' and 'rmir' can write to the last character
cell reliably without scrolling.
Here is what Emacs can do IMHO:
Glyph matrix (or whatever):
+------------------------+
|foo |
|bar |
|baz |
| --- *scratch* ---------|
|A very looooong message.|
+------------------------+
* Case: Any of 'ich', 'ich1', or both 'smir' and 'rmir' defined.
*Note*: Won't work on displays with only a single column.
Write to all character cells except the last two:
+------------------------+
|foo |
|bar |
|baz |
| --- *scratch* ---------|
|A very looooong messag | <-- cursor
+------------------------+
^
|
cursor
* Case: 'ich1' defined.
Write the glyph to be placed on the last character cell.
+------------------------+
|foo |
|bar |
|baz |
| --- *scratch* ---------|
|A very looooong messag. | <-- cursor
+------------------------+
^
|
cursor
Move to the character cell on the left side (cub1):
+------------------------+
|foo |
|bar |
|baz |
| --- *scratch* ---------|
|A very looooong messag. | <-- cursor
+------------------------+
^
|
cursor
Invoke (or write or whatever) 'ich1':
+------------------------+
|foo |
|bar |
|baz |
| --- *scratch* ---------|
|A very looooong messag .| <-- cursor
+------------------------+
^
|
cursor
Write the glyph to be placed on the character cell before the last
character cell:
+------------------------+
|foo |
|bar |
|baz |
| --- *scratch* ---------|
|A very looooong message.| <-- cursor
+------------------------+
^
|
cursor
* Case: 'ich' defined.
Same as the 'ich1' case, but invoke 'ich' with parameter '1' instead
of 'ich1'.
* Case: 'smir' and 'rmir' defined.
Write the glyph to be placed on the last character cell.
+------------------------+
|foo |
|bar |
|baz |
| --- *scratch* ---------|
|A very looooong messag. | <-- cursor
+------------------------+
^
|
cursor
Move to the character cell on the left side (cub1):
+------------------------+
|foo |
|bar |
|baz |
| --- *scratch* ---------|
|A very looooong messag. | <-- cursor
+------------------------+
^
|
cursor
Invoke 'smir'.
Write the glyph to be placed on the character cell before the last
character cell:
+------------------------+
|foo |
|bar |
|baz |
| --- *scratch* ---------|
|A very looooong message.| <-- cursor
+------------------------+
^
|
cursor
Invoke 'rmir'.
* Case: 'il' or 'il1' defined.
*Note*: Won't work on displays with only a single line.
Write to all lines except the last two:
+------------------------+
|foo |
|bar |
|baz |
| | <-- cursor
| |
+------------------------+
^
|
cursor
Write the glyphs to be placed on the last line.
+------------------------+
|foo |
|bar |
|baz |
|A very looooong message.|
| | <-- cursor
+------------------------+
^
|
cursor
Move to the character cell above (cuu1):
+------------------------+
|foo |
|bar |
|baz |
|A very looooong message.| <-- cursor
| |
+------------------------+
^
|
cursor
* Case: 'il1' defined.
Invoke 'il1'.
* Case: 'il' defined.
Invoke 'il1' with parameter '1'.
+------------------------+
|foo |
|bar |
|baz |
| | <-- cursor
|A very looooong message.|
+------------------------+
^
|
cursor
Insert the glyphs to be placed on the line before the last line:
+------------------------+
|foo |
|bar |
|baz |
| --- *scratch* ---------|
|A very looooong message.| <-- cursor
+------------------------+
^
|
cursor
--
Akib Azmain Turja
Find me on Mastodon at @akib@hostux.social.
This message is signed by me with my GnuPG key. Its fingerprint is:
7001 8CE5 819F 17A3 BBA6 66AF E74F 0EFA 922A E7F5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-06 10:07 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-09-06 12:00 ` Gerd Möllmann
2022-09-06 15:10 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
0 siblings, 1 reply; 26+ messages in thread
From: Gerd Möllmann @ 2022-09-06 12:00 UTC (permalink / raw)
To: Akib Azmain Turja; +Cc: 57607
Akib Azmain Turja <akib@disroot.org> writes:
> Gerd Möllmann <gerd.moellmann@gmail.com> writes:
>
>> Emacs already writes to the bottom-right corner in case neither "am" nor
>> "xn" are defined for the terminal in question. vt100 and xterm, for
>> instance, have "am" defined here, so Emacs doesn't write to the
>> bottom-right corner.
>
> I repeat: vt100 and xterm-like terminal having any of 'ich', 'ich1',
> 'il' and 'il1' or both 'smir' and 'rmir' can write to the last character
> cell reliably without scrolling.
>
> Here is what Emacs can do IMHO:
>
I know that, I can edit text :-).
I guess no-one else before felt motifvated enough to implement this. Do
you feel motivated? I could show you where to look, if you like.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-06 12:00 ` Gerd Möllmann
@ 2022-09-06 15:10 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-07 4:58 ` Gerd Möllmann
0 siblings, 1 reply; 26+ messages in thread
From: Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-09-06 15:10 UTC (permalink / raw)
To: Gerd Möllmann; +Cc: 57607
[-- Attachment #1: Type: text/plain, Size: 1118 bytes --]
Gerd Möllmann <gerd.moellmann@gmail.com> writes:
> Akib Azmain Turja <akib@disroot.org> writes:
>
>> Gerd Möllmann <gerd.moellmann@gmail.com> writes:
>>
>>> Emacs already writes to the bottom-right corner in case neither "am" nor
>>> "xn" are defined for the terminal in question. vt100 and xterm, for
>>> instance, have "am" defined here, so Emacs doesn't write to the
>>> bottom-right corner.
>>
>> I repeat: vt100 and xterm-like terminal having any of 'ich', 'ich1',
>> 'il' and 'il1' or both 'smir' and 'rmir' can write to the last character
>> cell reliably without scrolling.
>>
>> Here is what Emacs can do IMHO:
>>
>
> I know that, I can edit text :-).
>
> I guess no-one else before felt motifvated enough to implement this. Do
> you feel motivated?
A little.
> I could show you where to look, if you like.
It's good to know, in case I (or someone else) try to do this.
--
Akib Azmain Turja
Find me on Mastodon at @akib@hostux.social.
This message is signed by me with my GnuPG key. Its fingerprint is:
7001 8CE5 819F 17A3 BBA6 66AF E74F 0EFA 922A E7F5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-06 15:10 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-09-07 4:58 ` Gerd Möllmann
2022-09-07 12:46 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
` (2 more replies)
0 siblings, 3 replies; 26+ messages in thread
From: Gerd Möllmann @ 2022-09-07 4:58 UTC (permalink / raw)
To: Akib Azmain Turja; +Cc: 57607
Akib Azmain Turja <akib@disroot.org> writes:
>> I guess no-one else before felt motifvated enough to implement this. Do
>> you feel motivated?
>
> A little.
I've added something to etc/TODO.
I guess there's not much else to do, so I'm closing this for now.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-07 4:58 ` Gerd Möllmann
@ 2022-09-07 12:46 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-07 12:58 ` Gerd Möllmann
2022-09-07 15:39 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-07 17:26 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2 siblings, 1 reply; 26+ messages in thread
From: Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-09-07 12:46 UTC (permalink / raw)
To: Gerd Möllmann; +Cc: 57607
[-- Attachment #1: Type: text/plain, Size: 587 bytes --]
Gerd Möllmann <gerd.moellmann@gmail.com> writes:
> Akib Azmain Turja <akib@disroot.org> writes:
>
>>> I guess no-one else before felt motifvated enough to implement this. Do
>>> you feel motivated?
>>
>> A little.
>
> I've added something to etc/TODO.
>
> I guess there's not much else to do, so I'm closing this for now.
>
>
>
OK, but what to change in Emacs???
--
Akib Azmain Turja
Find me on Mastodon at @akib@hostux.social.
This message is signed by me with my GnuPG key. Its fingerprint is:
7001 8CE5 819F 17A3 BBA6 66AF E74F 0EFA 922A E7F5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-07 12:46 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-09-07 12:58 ` Gerd Möllmann
0 siblings, 0 replies; 26+ messages in thread
From: Gerd Möllmann @ 2022-09-07 12:58 UTC (permalink / raw)
To: Akib Azmain Turja; +Cc: 57607
Akib Azmain Turja <akib@disroot.org> writes:
> OK, but what to change in Emacs???
I guess I'm missing something. What do you mean?
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-07 4:58 ` Gerd Möllmann
2022-09-07 12:46 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-09-07 15:39 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-07 17:26 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2 siblings, 0 replies; 26+ messages in thread
From: Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-09-07 15:39 UTC (permalink / raw)
To: Gerd Möllmann; +Cc: 57607
[-- Attachment #1: Type: text/plain, Size: 567 bytes --]
Gerd Möllmann <gerd.moellmann@gmail.com> writes:
> Akib Azmain Turja <akib@disroot.org> writes:
>
>>> I guess no-one else before felt motifvated enough to implement this. Do
>>> you feel motivated?
>>
>> A little.
>
> I've added something to etc/TODO.
>
> I guess there's not much else to do, so I'm closing this for now.
OK, but what to change?
--
Akib Azmain Turja
Find me on Mastodon at @akib@hostux.social.
This message is signed by me with my GnuPG key. Its fingerprint is:
7001 8CE5 819F 17A3 BBA6 66AF E74F 0EFA 922A E7F5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-07 4:58 ` Gerd Möllmann
2022-09-07 12:46 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-07 15:39 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-09-07 17:26 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-08 5:49 ` Gerd Möllmann
2 siblings, 1 reply; 26+ messages in thread
From: Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-09-07 17:26 UTC (permalink / raw)
To: Gerd Möllmann; +Cc: 57607
[-- Attachment #1: Type: text/plain, Size: 381 bytes --]
Gerd Möllmann <gerd.moellmann@gmail.com> writes:
I mean, what files to change in order to do this? I think it's
tty_write_glyphs and tty_write_glyphs_with_face in term.c.
--
Akib Azmain Turja
Find me on Mastodon at @akib@hostux.social.
This message is signed by me with my GnuPG key. Its fingerprint is:
7001 8CE5 819F 17A3 BBA6 66AF E74F 0EFA 922A E7F5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-07 17:26 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-09-08 5:49 ` Gerd Möllmann
2022-09-08 11:28 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
0 siblings, 1 reply; 26+ messages in thread
From: Gerd Möllmann @ 2022-09-08 5:49 UTC (permalink / raw)
To: Akib Azmain Turja; +Cc: 57607
Akib Azmain Turja <akib@disroot.org> writes:
> Gerd Möllmann <gerd.moellmann@gmail.com> writes:
>
> I mean, what files to change in order to do this? I think it's
> tty_write_glyphs and tty_write_glyphs_with_face in term.c.
Are you interested in implementing something? You could re-open this
bug then, no problem. Or are you maybe just evaluating if you'd like to
do it? Please give a hint.
The places you mention sound right. It's probably all in term.c. But
I'd like to add, that in principle all places writing to the terminal
have to be checked at least.
And corner cases have to be taken into consideration :-). Pulling
something out of thin air: What happens if we write RGRG to the
bottom-right corner, where R is one red char, and G is 1 green char,
say.
And maybe we have to check for characters that are more than 1 column
wide? I don't remember something like that from when I last worked in
this area, but I'd check what the situation is nowadays.
That's all I can say without studying the code more in detail, which I'm
trying to avoid :-).
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-08 5:49 ` Gerd Möllmann
@ 2022-09-08 11:28 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-08 12:35 ` Gerd Möllmann
2022-10-03 8:31 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
0 siblings, 2 replies; 26+ messages in thread
From: Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-09-08 11:28 UTC (permalink / raw)
To: Gerd Möllmann; +Cc: 57607
[-- Attachment #1: Type: text/plain, Size: 1988 bytes --]
Gerd Möllmann <gerd.moellmann@gmail.com> writes:
> Akib Azmain Turja <akib@disroot.org> writes:
>
>> Gerd Möllmann <gerd.moellmann@gmail.com> writes:
>>
>> I mean, what files to change in order to do this? I think it's
>> tty_write_glyphs and tty_write_glyphs_with_face in term.c.
>
> Are you interested in implementing something? You could re-open this
> bug then, no problem. Or are you maybe just evaluating if you'd like to
> do it? Please give a hint.
Yes, I'm interested, because I think it would help me understand how
Emacs renders text in terminal, which would help me to implement child
frame in terminal. But I don't have the time to do it right now. I
hope I can start doing this by late October.
>
> The places you mention sound right. It's probably all in term.c. But
> I'd like to add, that in principle all places writing to the terminal
> have to be checked at least.
>
> And corner cases have to be taken into consideration :-). Pulling
> something out of thin air: What happens if we write RGRG to the
> bottom-right corner, where R is one red char, and G is 1 green char,
> say.
I think you meant the following in Bash:
--8<---------------cut here---------------start------------->8---
printf "%$((COLUMNS - 4))s\e[31mr\e[32mg\e7\e[32mg\e8\e[@\e[31mr\e[m" "" ; sleep 1 ; printf '\n'
--8<---------------cut here---------------end--------------->8---
And it works on St, Kitty, Coterm, Term, etc.
>
> And maybe we have to check for characters that are more than 1 column
> wide? I don't remember something like that from when I last worked in
> this area, but I'd check what the situation is nowadays.
>
> That's all I can say without studying the code more in detail, which I'm
> trying to avoid :-).
>
--
Akib Azmain Turja
Find me on Mastodon at @akib@hostux.social.
This message is signed by me with my GnuPG key. Its fingerprint is:
7001 8CE5 819F 17A3 BBA6 66AF E74F 0EFA 922A E7F5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-08 11:28 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-09-08 12:35 ` Gerd Möllmann
2022-09-08 14:47 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-03 8:31 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
1 sibling, 1 reply; 26+ messages in thread
From: Gerd Möllmann @ 2022-09-08 12:35 UTC (permalink / raw)
To: Akib Azmain Turja; +Cc: 57607
Akib Azmain Turja <akib@disroot.org> writes:
> Yes, I'm interested, because I think it would help me understand how
> Emacs renders text in terminal, which would help me to implement child
> frame in terminal. But I don't have the time to do it right now. I
> hope I can start doing this by late October.
Great! I've re-opened this issue.
>
>>
>> The places you mention sound right. It's probably all in term.c. But
>> I'd like to add, that in principle all places writing to the terminal
>> have to be checked at least.
>>
>> And corner cases have to be taken into consideration :-). Pulling
>> something out of thin air: What happens if we write RGRG to the
>> bottom-right corner, where R is one red char, and G is 1 green char,
>> say.
>
> I think you meant the following in Bash:
>
> printf "%$((COLUMNS - 4))s\e[31mr\e[32mg\e7\e[32mg\e8\e[@\e[31mr\e[m" "" ; sleep 1 ; printf '\n'
>
> And it works on St, Kitty, Coterm, Term, etc.
What I was thinking of is the Emacs side of things, i.e. can we always
do our magic locally in tty_write... etc., or is it sometimes necessary
to reorder writes at the caller.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-08 12:35 ` Gerd Möllmann
@ 2022-09-08 14:47 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-11 9:00 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
0 siblings, 1 reply; 26+ messages in thread
From: Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-09-08 14:47 UTC (permalink / raw)
To: Gerd Möllmann; +Cc: 57607
[-- Attachment #1: Type: text/plain, Size: 1598 bytes --]
Gerd Möllmann <gerd.moellmann@gmail.com> writes:
> Akib Azmain Turja <akib@disroot.org> writes:
>
>> Yes, I'm interested, because I think it would help me understand how
>> Emacs renders text in terminal, which would help me to implement child
>> frame in terminal. But I don't have the time to do it right now. I
>> hope I can start doing this by late October.
>
> Great! I've re-opened this issue.
>
>>
>>>
>>> The places you mention sound right. It's probably all in term.c. But
>>> I'd like to add, that in principle all places writing to the terminal
>>> have to be checked at least.
>>>
>>> And corner cases have to be taken into consideration :-). Pulling
>>> something out of thin air: What happens if we write RGRG to the
>>> bottom-right corner, where R is one red char, and G is 1 green char,
>>> say.
>>
>> I think you meant the following in Bash:
>>
>> printf "%$((COLUMNS - 4))s\e[31mr\e[32mg\e7\e[32mg\e8\e[@\e[31mr\e[m" "" ; sleep 1 ; printf '\n'
>>
>> And it works on St, Kitty, Coterm, Term, etc.
>
> What I was thinking of is the Emacs side of things, i.e. can we always
> do our magic locally in tty_write... etc., or is it sometimes necessary
> to reorder writes at the caller.
We would need to remember the glyph in the character cell before the
last one, because modifying the last character cell needs to rewrite to
that cell.
--
Akib Azmain Turja
Find me on Mastodon at @akib@hostux.social.
This message is signed by me with my GnuPG key. Its fingerprint is:
7001 8CE5 819F 17A3 BBA6 66AF E74F 0EFA 922A E7F5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-08 14:47 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-09-11 9:00 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-11 10:08 ` Gerd Möllmann
0 siblings, 1 reply; 26+ messages in thread
From: Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-09-11 9:00 UTC (permalink / raw)
To: Gerd Möllmann; +Cc: 57607
[-- Attachment #1: Type: text/plain, Size: 2399 bytes --]
Akib Azmain Turja <akib@disroot.org> writes:
> Gerd Möllmann <gerd.moellmann@gmail.com> writes:
>
>> Akib Azmain Turja <akib@disroot.org> writes:
>>
>>> Yes, I'm interested, because I think it would help me understand how
>>> Emacs renders text in terminal, which would help me to implement child
>>> frame in terminal. But I don't have the time to do it right now. I
>>> hope I can start doing this by late October.
>>
>> Great! I've re-opened this issue.
>>
>>>
>>>>
>>>> The places you mention sound right. It's probably all in term.c. But
>>>> I'd like to add, that in principle all places writing to the terminal
>>>> have to be checked at least.
>>>>
>>>> And corner cases have to be taken into consideration :-). Pulling
>>>> something out of thin air: What happens if we write RGRG to the
>>>> bottom-right corner, where R is one red char, and G is 1 green char,
>>>> say.
>>>
>>> I think you meant the following in Bash:
>>>
>>> printf "%$((COLUMNS - 4))s\e[31mr\e[32mg\e7\e[32mg\e8\e[@\e[31mr\e[m" "" ; sleep 1 ; printf '\n'
>>>
>>> And it works on St, Kitty, Coterm, Term, etc.
>>
>> What I was thinking of is the Emacs side of things, i.e. can we always
>> do our magic locally in tty_write... etc., or is it sometimes necessary
>> to reorder writes at the caller.
>
> We would need to remember the glyph in the character cell before the
> last one, because modifying the last character cell needs to rewrite to
> that cell.
Just to add, terminal is with 'smam' (enable automatic margin) and
'rmam' (disable automatic margin) can disable automatic margin, thus can
write the last character cell.
And, Emacs currently often writes to the last character possibly by
mistake. I'm not sure whether this is a bug or not. To reproduce, run
emacs -Q, hit M-: (eval-expression), write some garbage until the
minibuffer window scrolls (I used (+ (% (random) 26) ?a) to generate
the garbage), and hit C-p until you scroll down a line. You should now
see that the last character cell contains a continuation ('\') glyph. I
think this is probably due to the use of 'il' or 'il1' or 'rin'
capability. Should I report this as a bug?
--
Akib Azmain Turja
Find me on Mastodon at @akib@hostux.social.
This message is signed by me with my GnuPG key. Its fingerprint is:
7001 8CE5 819F 17A3 BBA6 66AF E74F 0EFA 922A E7F5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-11 9:00 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-09-11 10:08 ` Gerd Möllmann
2022-09-11 10:39 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
0 siblings, 1 reply; 26+ messages in thread
From: Gerd Möllmann @ 2022-09-11 10:08 UTC (permalink / raw)
To: Akib Azmain Turja; +Cc: 57607
On 22-09-11 11:00 , Akib Azmain Turja wrote:
> Should I report this as a bug?
Yes, please. Someone should take a look at this.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-11 10:08 ` Gerd Möllmann
@ 2022-09-11 10:39 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
0 siblings, 0 replies; 26+ messages in thread
From: Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-09-11 10:39 UTC (permalink / raw)
To: Gerd Möllmann; +Cc: 57607
[-- Attachment #1: Type: text/plain, Size: 422 bytes --]
Gerd Möllmann <gerd.moellmann@gmail.com> writes:
> On 22-09-11 11:00 , Akib Azmain Turja wrote:
>> Should I report this as a bug?
>
> Yes, please. Someone should take a look at this.
>
Done, see bug#57728.
--
Akib Azmain Turja
Find me on Mastodon at @akib@hostux.social.
This message is signed by me with my GnuPG key. Its fingerprint is:
7001 8CE5 819F 17A3 BBA6 66AF E74F 0EFA 922A E7F5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-09-08 11:28 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-08 12:35 ` Gerd Möllmann
@ 2022-10-03 8:31 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-03 19:41 ` Eli Zaretskii
1 sibling, 1 reply; 26+ messages in thread
From: Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-10-03 8:31 UTC (permalink / raw)
To: 57607; +Cc: gerd.moellmann
[-- Attachment #1.1: Type: text/plain, Size: 978 bytes --]
Akib Azmain Turja via "Bug reports for GNU Emacs, the Swiss army knife
of text editors" <bug-gnu-emacs@gnu.org> writes:
> Gerd Möllmann <gerd.moellmann@gmail.com> writes:
>
>> Akib Azmain Turja <akib@disroot.org> writes:
>>
>>> Gerd Möllmann <gerd.moellmann@gmail.com> writes:
>>>
>>> I mean, what files to change in order to do this? I think it's
>>> tty_write_glyphs and tty_write_glyphs_with_face in term.c.
>>
>> Are you interested in implementing something? You could re-open this
>> bug then, no problem. Or are you maybe just evaluating if you'd like to
>> do it? Please give a hint.
>
> Yes, I'm interested, because I think it would help me understand how
> Emacs renders text in terminal, which would help me to implement child
> frame in terminal. But I don't have the time to do it right now. I
> hope I can start doing this by late October.
>
I have implemented it. Implementing it was easier than I thought. Here
is the patch:
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: Patch --]
[-- Type: text/x-patch, Size: 11656 bytes --]
From 72af00d8610bdc194062b246aab0e38f22174aeb Mon Sep 17 00:00:00 2001
From: Akib Azmain Turja <akib@disroot.org>
Date: Mon, 3 Oct 2022 14:18:59 +0600
Subject: [PATCH] Write on the bottom-right character cell on terminal
Correctly write on the bottom-right character cell on text terminals
if the terminal allows to do this. Also fixes bug#57728.
* src/term.c (tty_write_glyphs, tty_write_glyphs_with_face): Write on
the bottom-right character cell if the terminal supports it.
* src/term.c (glyph_on_char_cell_before_last): New static variable to
hold the current glyph on the character cell before the cell on the
bottom-right corner.
---
src/term.c | 266 ++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 225 insertions(+), 41 deletions(-)
diff --git a/src/term.c b/src/term.c
index 2e43d892..283a65c4 100644
--- a/src/term.c
+++ b/src/term.c
@@ -718,7 +718,7 @@ encode_terminal_code (struct glyph *src, int src_len,
return (encode_terminal_dst);
}
-
+static struct glyph glyph_on_char_cell_before_last;
/* An implementation of write_glyphs for termcap frames. */
@@ -727,7 +727,7 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
{
unsigned char *conversion_buffer;
struct coding_system *coding;
- int n, stringlen;
+ int n, stringlen, write_on_last_cell;
struct tty_display_info *tty = FRAME_TTY (f);
@@ -737,55 +737,158 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
/* Don't dare write in last column of bottom line, if Auto-Wrap,
since that would scroll the whole frame on some terminals. */
- if (AutoWrap (tty)
- && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
- && (curX (tty) + len) == FRAME_COLS (f))
+ write_on_last_cell = (AutoWrap (tty)
+ && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
+ && (curX (tty) + len) == FRAME_COLS (f));
+ if (write_on_last_cell)
len --;
- if (len <= 0)
- return;
- cmplus (tty, len);
+ if (FRAME_COLS (f) == 1
+ || !(tty->TS_ins_char || tty->TS_ins_multi_chars
+ || (tty->TS_insert_mode && tty->TS_end_insert_mode)))
+ write_on_last_cell = false;
+
+ if (len <= 0 && !write_on_last_cell)
+ return;
/* If terminal_coding does any conversion, use it, otherwise use
safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
because it always return 1 if the member src_multibyte is 1. */
- coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
+ coding = ((FRAME_TERMINAL_CODING (f)->common_flags
+ & CODING_REQUIRE_ENCODING_MASK)
? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
/* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
the tail. */
coding->mode &= ~CODING_MODE_LAST_BLOCK;
- for (stringlen = len; stringlen != 0; stringlen -= n)
+ if (len > 0)
{
- /* Identify a run of glyphs with the same face. */
- int face_id = string->face_id;
+ cmplus (tty, len);
+
+ if (write_on_last_cell)
+ glyph_on_char_cell_before_last = string[len - 1];
+
+ for (stringlen = len; stringlen != 0; stringlen -= n)
+ {
+ /* Identify a run of glyphs with the same face. */
+ int face_id = string->face_id;
+
+ for (n = 1; n < stringlen; ++n)
+ if (string[n].face_id != face_id)
+ break;
+
+ /* Turn appearance modes of the face of the run on. */
+ tty_highlight_if_desired (tty);
+ turn_on_face (f, face_id);
- for (n = 1; n < stringlen; ++n)
- if (string[n].face_id != face_id)
- break;
+ if (n == stringlen && !write_on_last_cell)
+ /* This is the last run. */
+ coding->mode |= CODING_MODE_LAST_BLOCK;
+ conversion_buffer = encode_terminal_code (string, n,
+ coding);
+ if (coding->produced > 0)
+ {
+ block_input ();
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->output);
+ clearerr (tty->output);
+ if (tty->termscript)
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->termscript);
+ unblock_input ();
+ }
+ string += n;
- /* Turn appearance modes of the face of the run on. */
+ /* Turn appearance modes off. */
+ turn_off_face (f, face_id);
+ tty_turn_off_highlight (tty);
+ }
+ }
+
+ /* Write on the bottom-right corner. */
+ if (write_on_last_cell)
+ {
+ /* Go to the previous position. */
+ cmgoto (tty, curY (tty), curX (tty) - 1);
+ cmplus (tty, 1);
+
+ int face_id = string->face_id;
+
+ /* Turn appearance modes of the face. */
tty_highlight_if_desired (tty);
turn_on_face (f, face_id);
- if (n == stringlen)
- /* This is the last run. */
- coding->mode |= CODING_MODE_LAST_BLOCK;
- conversion_buffer = encode_terminal_code (string, n, coding);
+ conversion_buffer = encode_terminal_code (string, 1, coding);
if (coding->produced > 0)
{
block_input ();
- fwrite (conversion_buffer, 1, coding->produced, tty->output);
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->output);
clearerr (tty->output);
if (tty->termscript)
- fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->termscript);
+ unblock_input ();
+ }
+
+ /* Go to the previous position. */
+ cmgoto (tty, curY (tty), curX (tty) - 1);
+ cmplus (tty, 1);
+
+ /* Arrange that after writing the next glyph, the glyph on the
+ current character cell is somehow pushed to the bottom-right
+ corner. */
+ if (tty->TS_ins_char)
+ {
+ OUTPUT1 (tty, tty->TS_ins_char);
+ }
+ else if (tty->TS_ins_multi_chars)
+ {
+ char *buf = tparam (tty->TS_ins_multi_chars, 0, 0, 1, 0,
+ 0, 0);
+ OUTPUT1 (tty, buf);
+ xfree (buf);
+ }
+ else
+ {
+ tty_turn_on_insert (tty);
+ }
+
+ if (face_id != glyph_on_char_cell_before_last.face_id)
+ {
+
+ /* Turn appearance modes of the face. */
+ turn_off_face (f, face_id);
+ tty_turn_off_highlight (tty);
+
+ face_id = glyph_on_char_cell_before_last.face_id;
+
+ tty_highlight_if_desired (tty);
+ turn_on_face (f, face_id);
+ }
+
+ /* This is the last run. */
+ coding->mode |= CODING_MODE_LAST_BLOCK;
+ conversion_buffer
+ = encode_terminal_code (&glyph_on_char_cell_before_last, 1,
+ coding);
+ if (coding->produced > 0)
+ {
+ block_input ();
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->output);
+ clearerr (tty->output);
+ if (tty->termscript)
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->termscript);
unblock_input ();
}
- string += n;
/* Turn appearance modes off. */
turn_off_face (f, face_id);
tty_turn_off_highlight (tty);
+
+ tty_turn_off_insert (tty);
}
cmcheckmagic (tty);
@@ -799,6 +902,7 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str
{
unsigned char *conversion_buffer;
struct coding_system *coding;
+ int write_on_last_cell;
struct tty_display_info *tty = FRAME_TTY (f);
@@ -808,38 +912,118 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str
/* Don't dare write in last column of bottom line, if Auto-Wrap,
since that would scroll the whole frame on some terminals. */
- if (AutoWrap (tty)
- && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
- && (curX (tty) + len) == FRAME_COLS (f))
+ write_on_last_cell = (AutoWrap (tty)
+ && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
+ && (curX (tty) + len) == FRAME_COLS (f));
+ if (write_on_last_cell)
len --;
- if (len <= 0)
- return;
- cmplus (tty, len);
+ if (FRAME_COLS (f) == 1
+ || !(tty->TS_ins_char || tty->TS_ins_multi_chars
+ || (tty->TS_insert_mode && tty->TS_end_insert_mode)))
+ write_on_last_cell = false;
+
+ if (len <= 0 && !write_on_last_cell)
+ return;
/* If terminal_coding does any conversion, use it, otherwise use
safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
because it always return 1 if the member src_multibyte is 1. */
- coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
+ coding = ((FRAME_TERMINAL_CODING (f)->common_flags
+ & CODING_REQUIRE_ENCODING_MASK)
? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
- /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
- the tail. */
+
+ /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only
+ at the tail. */
coding->mode &= ~CODING_MODE_LAST_BLOCK;
/* Turn appearance modes of the face. */
tty_highlight_if_desired (tty);
turn_on_face (f, face_id);
- coding->mode |= CODING_MODE_LAST_BLOCK;
- conversion_buffer = encode_terminal_code (string, len, coding);
- if (coding->produced > 0)
+ if (len > 0)
+ {
+ cmplus (tty, len);
+ if (write_on_last_cell)
+ glyph_on_char_cell_before_last = string[len - 1];
+ else
+ coding->mode |= CODING_MODE_LAST_BLOCK;
+
+ conversion_buffer = encode_terminal_code (string, len, coding);
+ if (coding->produced > 0)
+ {
+ block_input ();
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->output);
+ clearerr (tty->output);
+ if (tty->termscript)
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->termscript);
+ unblock_input ();
+ }
+ }
+
+ /* Write on the bottom-right corner. */
+ if (write_on_last_cell)
{
- block_input ();
- fwrite (conversion_buffer, 1, coding->produced, tty->output);
- clearerr (tty->output);
- if (tty->termscript)
- fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
- unblock_input ();
+ /* Go to the previous position. */
+ cmgoto (tty, curY (tty), curX (tty) - 1);
+ cmplus (tty, 1);
+
+ conversion_buffer = encode_terminal_code (string, 1, coding);
+ if (coding->produced > 0)
+ {
+ block_input ();
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->output);
+ clearerr (tty->output);
+ if (tty->termscript)
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->termscript);
+ unblock_input ();
+ }
+
+ /* Go to the previous position. */
+ cmgoto (tty, curY (tty), curX (tty) - 1);
+ cmplus (tty, 1);
+
+ /* Arrange that after writing the next glyph, the glyph on the
+ current character cell is somehow pushed to the bottom-right
+ corner. */
+ if (tty->TS_ins_char)
+ {
+ OUTPUT1 (tty, tty->TS_ins_char);
+ }
+ else if (tty->TS_ins_multi_chars)
+ {
+ char *buf = tparam (tty->TS_ins_multi_chars, 0, 0, 1,
+ 0, 0, 0);
+ OUTPUT1 (tty, buf);
+ xfree (buf);
+ }
+ else
+ {
+ tty_turn_on_insert (tty);
+ }
+
+ /* This is the last run. */
+ coding->mode |= CODING_MODE_LAST_BLOCK;
+ conversion_buffer
+ = encode_terminal_code (&glyph_on_char_cell_before_last, 1,
+ coding);
+ if (coding->produced > 0)
+ {
+ block_input ();
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->output);
+ clearerr (tty->output);
+ if (tty->termscript)
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->termscript);
+ unblock_input ();
+ }
+
+ tty_turn_off_insert (tty);
}
/* Turn appearance modes off. */
--
2.37.1
[-- Attachment #1.3: Type: text/plain, Size: 757 bytes --]
>>
>> The places you mention sound right. It's probably all in term.c. But
>> I'd like to add, that in principle all places writing to the terminal
>> have to be checked at least.
>>
>> And corner cases have to be taken into consideration :-). Pulling
>> something out of thin air: What happens if we write RGRG to the
>> bottom-right corner, where R is one red char, and G is 1 green char,
>> say.
I tried "RGRG\", where "R" is red, "G" is green, and "\" is the (white)
continuation glyph. Looks like this patch also fixes bug#57728.
--
Akib Azmain Turja
Find me on Mastodon at @akib@hostux.social.
This message is signed by me with my GnuPG key. Its fingerprint is:
7001 8CE5 819F 17A3 BBA6 66AF E74F 0EFA 922A E7F5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply related [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-10-03 8:31 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-10-03 19:41 ` Eli Zaretskii
2022-10-04 7:22 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
0 siblings, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2022-10-03 19:41 UTC (permalink / raw)
To: Akib Azmain Turja; +Cc: gerd.moellmann, 57607
> Cc: gerd.moellmann@gmail.com
> Date: Mon, 03 Oct 2022 14:31:53 +0600
> From: Akib Azmain Turja via "Bug reports for GNU Emacs,
> the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
>
> I have implemented it. Implementing it was easier than I thought. Here
> is the patch:
Thanks. But could you please describe the idea of the patch in some
comment? It is hard to follow the code, especially since the diff has
many pure whitespace changes.
Also, this:
> + /* Go to the previous position. */
> + cmgoto (tty, curY (tty), curX (tty) - 1);
> + cmplus (tty, 1);
Seem to assume the last character takes just one column? What about
characters whose width is 2 columns?
And finally, it would be nice to avoid so much code duplication
between tty_write_glyphs and tty_write_glyphs_with_face. Is that
feasible?
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-10-03 19:41 ` Eli Zaretskii
@ 2022-10-04 7:22 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-04 8:07 ` Eli Zaretskii
0 siblings, 1 reply; 26+ messages in thread
From: Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-10-04 7:22 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gerd.moellmann, 57607
[-- Attachment #1: Type: text/plain, Size: 2568 bytes --]
Eli Zaretskii <eliz@gnu.org> writes:
>> Cc: gerd.moellmann@gmail.com
>> Date: Mon, 03 Oct 2022 14:31:53 +0600
>> From: Akib Azmain Turja via "Bug reports for GNU Emacs,
>> the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
>>
>> I have implemented it. Implementing it was easier than I thought. Here
>> is the patch:
>
> Thanks. But could you please describe the idea of the patch in some
> comment? It is hard to follow the code, especially since the diff has
> many pure whitespace changes.
The idea is that you write the string just like before (for example, you
want to write "hello" in a five columns width terminal, so you write
only "hell", so that the line shows "hell "), then move a character
backward and write the last glyph (write "o", so that the line shows
"helo "), move a character backward again and arrange that after writing
the next glyph, the character on the current position will be pushed
towards right and write the glyph before the last one (write "l", now
the line shows "hello").
Should I add the explanation to the function as comment?
>
> Also, this:
>
>> + /* Go to the previous position. */
>> + cmgoto (tty, curY (tty), curX (tty) - 1);
>> + cmplus (tty, 1);
>
> Seem to assume the last character takes just one column? What about
> characters whose width is 2 columns?
Yes, I assume that. I don't think any multi-char width glyph reach this
function (I think they are converted to single column width glyphs, for
example "^L" is converted to "^" and "L"). The reason of the assumption
is the following code:
--8<---------------cut here---------------start------------->8---
if (AutoWrap (tty)
&& curY (tty) + 1 == FRAME_TOTAL_LINES (f)
&& (curX (tty) + len) == FRAME_COLS (f))
len --;
--8<---------------cut here---------------end--------------->8---
Which also assumes the same.
>
> And finally, it would be nice to avoid so much code duplication
> between tty_write_glyphs and tty_write_glyphs_with_face. Is that
> feasible?
Yes, I think so. I think it possible to just add a new argument
"face_id" to tty_write_glyphs would the trick. tty_write_glyph will try
to use "face_id" if it is specified, otherwise fallback to the face_id
in the string. But how to "not" specify a face_id? Would a NULL work?
--
Akib Azmain Turja
Find me on Mastodon at @akib@hostux.social.
This message is signed by me with my GnuPG key. Its fingerprint is:
7001 8CE5 819F 17A3 BBA6 66AF E74F 0EFA 922A E7F5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-10-04 7:22 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-10-04 8:07 ` Eli Zaretskii
2022-10-04 12:00 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
0 siblings, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2022-10-04 8:07 UTC (permalink / raw)
To: Akib Azmain Turja; +Cc: gerd.moellmann, 57607
> From: Akib Azmain Turja <akib@disroot.org>
> Cc: 57607@debbugs.gnu.org, gerd.moellmann@gmail.com
> Date: Tue, 04 Oct 2022 13:22:51 +0600
>
> > Thanks. But could you please describe the idea of the patch in some
> > comment? It is hard to follow the code, especially since the diff has
> > many pure whitespace changes.
>
> The idea is that you write the string just like before (for example, you
> want to write "hello" in a five columns width terminal, so you write
> only "hell", so that the line shows "hell "), then move a character
> backward and write the last glyph (write "o", so that the line shows
> "helo "), move a character backward again and arrange that after writing
> the next glyph, the character on the current position will be pushed
> towards right and write the glyph before the last one (write "l", now
> the line shows "hello").
>
> Should I add the explanation to the function as comment?
Yes, please. It would also help if the respective parts of the code
were annotated with comments that explain their role in the algorithm.
> > Also, this:
> >
> >> + /* Go to the previous position. */
> >> + cmgoto (tty, curY (tty), curX (tty) - 1);
> >> + cmplus (tty, 1);
> >
> > Seem to assume the last character takes just one column? What about
> > characters whose width is 2 columns?
>
> Yes, I assume that. I don't think any multi-char width glyph reach this
> function (I think they are converted to single column width glyphs, for
> example "^L" is converted to "^" and "L"). The reason of the assumption
> is the following code:
>
> --8<---------------cut here---------------start------------->8---
> if (AutoWrap (tty)
> && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
> && (curX (tty) + len) == FRAME_COLS (f))
> len --;
> --8<---------------cut here---------------end--------------->8---
>
> Which also assumes the same.
Please try with some 2-column CJK characters, I'm not sure the example
with ^L is relevant here. You can find the list of wide characters in
characters.el (search for "width"); for example, characters in the
U+FF00 block can be useful. (And the existing code could have bugs,
no need to assume it is always correct.)
> > And finally, it would be nice to avoid so much code duplication
> > between tty_write_glyphs and tty_write_glyphs_with_face. Is that
> > feasible?
>
> Yes, I think so. I think it possible to just add a new argument
> "face_id" to tty_write_glyphs would the trick. tty_write_glyph will try
> to use "face_id" if it is specified, otherwise fallback to the face_id
> in the string. But how to "not" specify a face_id? Would a NULL work?
face_id is an integer, and zero is a valid value (it means the default
face), so NULL won't do. But you can use -1 to mean "no face ID".
Just make sure you never pass it to FACE_FROM_ID etc.
Thanks.
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-10-04 8:07 ` Eli Zaretskii
@ 2022-10-04 12:00 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-04 12:54 ` Eli Zaretskii
2022-10-04 13:05 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
0 siblings, 2 replies; 26+ messages in thread
From: Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-10-04 12:00 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gerd.moellmann, 57607
[-- Attachment #1: Type: text/plain, Size: 3489 bytes --]
Eli Zaretskii <eliz@gnu.org> writes:
>> From: Akib Azmain Turja <akib@disroot.org>
>> Cc: 57607@debbugs.gnu.org, gerd.moellmann@gmail.com
>> Date: Tue, 04 Oct 2022 13:22:51 +0600
>>
>> > Thanks. But could you please describe the idea of the patch in some
>> > comment? It is hard to follow the code, especially since the diff has
>> > many pure whitespace changes.
>>
>> The idea is that you write the string just like before (for example, you
>> want to write "hello" in a five columns width terminal, so you write
>> only "hell", so that the line shows "hell "), then move a character
>> backward and write the last glyph (write "o", so that the line shows
>> "helo "), move a character backward again and arrange that after writing
>> the next glyph, the character on the current position will be pushed
>> towards right and write the glyph before the last one (write "l", now
>> the line shows "hello").
>>
>> Should I add the explanation to the function as comment?
>
> Yes, please. It would also help if the respective parts of the code
> were annotated with comments that explain their role in the algorithm.
OK.
>
>> > Also, this:
>> >
>> >> + /* Go to the previous position. */
>> >> + cmgoto (tty, curY (tty), curX (tty) - 1);
>> >> + cmplus (tty, 1);
>> >
>> > Seem to assume the last character takes just one column? What about
>> > characters whose width is 2 columns?
>>
>> Yes, I assume that. I don't think any multi-char width glyph reach this
>> function (I think they are converted to single column width glyphs, for
>> example "^L" is converted to "^" and "L"). The reason of the assumption
>> is the following code:
>>
>> --8<---------------cut here---------------start------------->8---
>> if (AutoWrap (tty)
>> && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
>> && (curX (tty) + len) == FRAME_COLS (f))
>> len --;
>> --8<---------------cut here---------------end--------------->8---
>>
>> Which also assumes the same.
>
> Please try with some 2-column CJK characters, I'm not sure the example
> with ^L is relevant here. You can find the list of wide characters in
> characters.el (search for "width"); for example, characters in the
> U+FF00 block can be useful.
Thanks, "CJK STROKE D" doesn't work as expected, and the result depends
on terminal in use. How can I determine the width of a glyph?
> (And the existing code could have bugs,
> no need to assume it is always correct.)
Yes, it can, but in most cases, my brain has more bugs.
>
>> > And finally, it would be nice to avoid so much code duplication
>> > between tty_write_glyphs and tty_write_glyphs_with_face. Is that
>> > feasible?
>>
>> Yes, I think so. I think it possible to just add a new argument
>> "face_id" to tty_write_glyphs would the trick. tty_write_glyph will try
>> to use "face_id" if it is specified, otherwise fallback to the face_id
>> in the string. But how to "not" specify a face_id? Would a NULL work?
>
> face_id is an integer, and zero is a valid value (it means the default
> face), so NULL won't do. But you can use -1 to mean "no face ID".
> Just make sure you never pass it to FACE_FROM_ID etc.
>
> Thanks.
OK, I'll try that. Thanks.
--
Akib Azmain Turja
Find me on Mastodon at @akib@hostux.social.
This message is signed by me with my GnuPG key. Its fingerprint is:
7001 8CE5 819F 17A3 BBA6 66AF E74F 0EFA 922A E7F5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-10-04 12:00 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-10-04 12:54 ` Eli Zaretskii
2022-10-07 13:10 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-04 13:05 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
1 sibling, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2022-10-04 12:54 UTC (permalink / raw)
To: Akib Azmain Turja; +Cc: gerd.moellmann, 57607
> From: Akib Azmain Turja <akib@disroot.org>
> Cc: 57607@debbugs.gnu.org, gerd.moellmann@gmail.com
> Date: Tue, 04 Oct 2022 18:00:57 +0600
>
> > Please try with some 2-column CJK characters, I'm not sure the example
> > with ^L is relevant here. You can find the list of wide characters in
> > characters.el (search for "width"); for example, characters in the
> > U+FF00 block can be useful.
>
> Thanks, "CJK STROKE D" doesn't work as expected, and the result depends
> on terminal in use. How can I determine the width of a glyph?
Like this:
(char-width CHAR)
where CHAR is the character you are interested in. For example:
(char-width #x31D4)
=> 2
From C, you can call char_width, like Fchar_width (which see) does.
One other subtle point: the argument STRING to tty_write_glyphs is a
string of 'struct glyph' objects, not a string of characters. Each
struct glyph has the code of the character to display in its u.ch
member, if the glyph is a simple character glyph; for the full story
see encode_terminal_code.
> > (And the existing code could have bugs,
> > no need to assume it is always correct.)
>
> Yes, it can, but in most cases, my brain has more bugs.
Indeed, that the existing code has bugs should not be our first
hypothesis. But it shouldn't be axiomatic that there are no bugs
there ;-)
> > face_id is an integer, and zero is a valid value (it means the default
> > face), so NULL won't do. But you can use -1 to mean "no face ID".
> > Just make sure you never pass it to FACE_FROM_ID etc.
> >
> > Thanks.
>
> OK, I'll try that. Thanks.
TIA
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-10-04 12:00 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-04 12:54 ` Eli Zaretskii
@ 2022-10-04 13:05 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
1 sibling, 0 replies; 26+ messages in thread
From: Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-10-04 13:05 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gerd.moellmann, 57607
[-- Attachment #1.1: Type: text/plain, Size: 3496 bytes --]
Akib Azmain Turja <akib@disroot.org> writes:
> Eli Zaretskii <eliz@gnu.org> writes:
>
>>> From: Akib Azmain Turja <akib@disroot.org>
>>> Cc: 57607@debbugs.gnu.org, gerd.moellmann@gmail.com
>>> Date: Tue, 04 Oct 2022 13:22:51 +0600
>>>
>>> > Thanks. But could you please describe the idea of the patch in some
>>> > comment? It is hard to follow the code, especially since the diff has
>>> > many pure whitespace changes.
>>>
>>> The idea is that you write the string just like before (for example, you
>>> want to write "hello" in a five columns width terminal, so you write
>>> only "hell", so that the line shows "hell "), then move a character
>>> backward and write the last glyph (write "o", so that the line shows
>>> "helo "), move a character backward again and arrange that after writing
>>> the next glyph, the character on the current position will be pushed
>>> towards right and write the glyph before the last one (write "l", now
>>> the line shows "hello").
>>>
>>> Should I add the explanation to the function as comment?
>>
>> Yes, please. It would also help if the respective parts of the code
>> were annotated with comments that explain their role in the algorithm.
>
> OK.
Done.
>
>>
>>> > Also, this:
>>> >
>>> >> + /* Go to the previous position. */
>>> >> + cmgoto (tty, curY (tty), curX (tty) - 1);
>>> >> + cmplus (tty, 1);
>>> >
>>> > Seem to assume the last character takes just one column? What about
>>> > characters whose width is 2 columns?
>>>
>>> Yes, I assume that. I don't think any multi-char width glyph reach this
>>> function (I think they are converted to single column width glyphs, for
>>> example "^L" is converted to "^" and "L"). The reason of the assumption
>>> is the following code:
>>>
>>> --8<---------------cut here---------------start------------->8---
>>> if (AutoWrap (tty)
>>> && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
>>> && (curX (tty) + len) == FRAME_COLS (f))
>>> len --;
>>> --8<---------------cut here---------------end--------------->8---
>>>
>>> Which also assumes the same.
>>
>> Please try with some 2-column CJK characters, I'm not sure the example
>> with ^L is relevant here. You can find the list of wide characters in
>> characters.el (search for "width"); for example, characters in the
>> U+FF00 block can be useful.
>
> Thanks, "CJK STROKE D" doesn't work as expected, and the result depends
> on terminal in use. How can I determine the width of a glyph?
>
>> (And the existing code could have bugs,
>> no need to assume it is always correct.)
>
> Yes, it can, but in most cases, my brain has more bugs.
>
>>
>>> > And finally, it would be nice to avoid so much code duplication
>>> > between tty_write_glyphs and tty_write_glyphs_with_face. Is that
>>> > feasible?
>>>
>>> Yes, I think so. I think it possible to just add a new argument
>>> "face_id" to tty_write_glyphs would the trick. tty_write_glyph will try
>>> to use "face_id" if it is specified, otherwise fallback to the face_id
>>> in the string. But how to "not" specify a face_id? Would a NULL work?
>>
>> face_id is an integer, and zero is a valid value (it means the default
>> face), so NULL won't do. But you can use -1 to mean "no face ID".
>> Just make sure you never pass it to FACE_FROM_ID etc.
>>
>> Thanks.
>
> OK, I'll try that. Thanks.
Done. Looks like Emacs still works. Here are the patches:
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: PATCH 1/2 --]
[-- Type: text/x-patch, Size: 11660 bytes --]
From 72af00d8610bdc194062b246aab0e38f22174aeb Mon Sep 17 00:00:00 2001
From: Akib Azmain Turja <akib@disroot.org>
Date: Mon, 3 Oct 2022 14:18:59 +0600
Subject: [PATCH 1/2] Write on the bottom-right character cell on terminal
Correctly write on the bottom-right character cell on text terminals
if the terminal allows to do this. Also fixes bug#57728.
* src/term.c (tty_write_glyphs, tty_write_glyphs_with_face): Write on
the bottom-right character cell if the terminal supports it.
* src/term.c (glyph_on_char_cell_before_last): New static variable to
hold the current glyph on the character cell before the cell on the
bottom-right corner.
---
src/term.c | 266 ++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 225 insertions(+), 41 deletions(-)
diff --git a/src/term.c b/src/term.c
index 2e43d892..283a65c4 100644
--- a/src/term.c
+++ b/src/term.c
@@ -718,7 +718,7 @@ encode_terminal_code (struct glyph *src, int src_len,
return (encode_terminal_dst);
}
-
+static struct glyph glyph_on_char_cell_before_last;
/* An implementation of write_glyphs for termcap frames. */
@@ -727,7 +727,7 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
{
unsigned char *conversion_buffer;
struct coding_system *coding;
- int n, stringlen;
+ int n, stringlen, write_on_last_cell;
struct tty_display_info *tty = FRAME_TTY (f);
@@ -737,55 +737,158 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
/* Don't dare write in last column of bottom line, if Auto-Wrap,
since that would scroll the whole frame on some terminals. */
- if (AutoWrap (tty)
- && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
- && (curX (tty) + len) == FRAME_COLS (f))
+ write_on_last_cell = (AutoWrap (tty)
+ && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
+ && (curX (tty) + len) == FRAME_COLS (f));
+ if (write_on_last_cell)
len --;
- if (len <= 0)
- return;
- cmplus (tty, len);
+ if (FRAME_COLS (f) == 1
+ || !(tty->TS_ins_char || tty->TS_ins_multi_chars
+ || (tty->TS_insert_mode && tty->TS_end_insert_mode)))
+ write_on_last_cell = false;
+
+ if (len <= 0 && !write_on_last_cell)
+ return;
/* If terminal_coding does any conversion, use it, otherwise use
safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
because it always return 1 if the member src_multibyte is 1. */
- coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
+ coding = ((FRAME_TERMINAL_CODING (f)->common_flags
+ & CODING_REQUIRE_ENCODING_MASK)
? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
/* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
the tail. */
coding->mode &= ~CODING_MODE_LAST_BLOCK;
- for (stringlen = len; stringlen != 0; stringlen -= n)
+ if (len > 0)
{
- /* Identify a run of glyphs with the same face. */
- int face_id = string->face_id;
+ cmplus (tty, len);
+
+ if (write_on_last_cell)
+ glyph_on_char_cell_before_last = string[len - 1];
+
+ for (stringlen = len; stringlen != 0; stringlen -= n)
+ {
+ /* Identify a run of glyphs with the same face. */
+ int face_id = string->face_id;
+
+ for (n = 1; n < stringlen; ++n)
+ if (string[n].face_id != face_id)
+ break;
+
+ /* Turn appearance modes of the face of the run on. */
+ tty_highlight_if_desired (tty);
+ turn_on_face (f, face_id);
- for (n = 1; n < stringlen; ++n)
- if (string[n].face_id != face_id)
- break;
+ if (n == stringlen && !write_on_last_cell)
+ /* This is the last run. */
+ coding->mode |= CODING_MODE_LAST_BLOCK;
+ conversion_buffer = encode_terminal_code (string, n,
+ coding);
+ if (coding->produced > 0)
+ {
+ block_input ();
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->output);
+ clearerr (tty->output);
+ if (tty->termscript)
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->termscript);
+ unblock_input ();
+ }
+ string += n;
- /* Turn appearance modes of the face of the run on. */
+ /* Turn appearance modes off. */
+ turn_off_face (f, face_id);
+ tty_turn_off_highlight (tty);
+ }
+ }
+
+ /* Write on the bottom-right corner. */
+ if (write_on_last_cell)
+ {
+ /* Go to the previous position. */
+ cmgoto (tty, curY (tty), curX (tty) - 1);
+ cmplus (tty, 1);
+
+ int face_id = string->face_id;
+
+ /* Turn appearance modes of the face. */
tty_highlight_if_desired (tty);
turn_on_face (f, face_id);
- if (n == stringlen)
- /* This is the last run. */
- coding->mode |= CODING_MODE_LAST_BLOCK;
- conversion_buffer = encode_terminal_code (string, n, coding);
+ conversion_buffer = encode_terminal_code (string, 1, coding);
if (coding->produced > 0)
{
block_input ();
- fwrite (conversion_buffer, 1, coding->produced, tty->output);
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->output);
clearerr (tty->output);
if (tty->termscript)
- fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->termscript);
+ unblock_input ();
+ }
+
+ /* Go to the previous position. */
+ cmgoto (tty, curY (tty), curX (tty) - 1);
+ cmplus (tty, 1);
+
+ /* Arrange that after writing the next glyph, the glyph on the
+ current character cell is somehow pushed to the bottom-right
+ corner. */
+ if (tty->TS_ins_char)
+ {
+ OUTPUT1 (tty, tty->TS_ins_char);
+ }
+ else if (tty->TS_ins_multi_chars)
+ {
+ char *buf = tparam (tty->TS_ins_multi_chars, 0, 0, 1, 0,
+ 0, 0);
+ OUTPUT1 (tty, buf);
+ xfree (buf);
+ }
+ else
+ {
+ tty_turn_on_insert (tty);
+ }
+
+ if (face_id != glyph_on_char_cell_before_last.face_id)
+ {
+
+ /* Turn appearance modes of the face. */
+ turn_off_face (f, face_id);
+ tty_turn_off_highlight (tty);
+
+ face_id = glyph_on_char_cell_before_last.face_id;
+
+ tty_highlight_if_desired (tty);
+ turn_on_face (f, face_id);
+ }
+
+ /* This is the last run. */
+ coding->mode |= CODING_MODE_LAST_BLOCK;
+ conversion_buffer
+ = encode_terminal_code (&glyph_on_char_cell_before_last, 1,
+ coding);
+ if (coding->produced > 0)
+ {
+ block_input ();
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->output);
+ clearerr (tty->output);
+ if (tty->termscript)
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->termscript);
unblock_input ();
}
- string += n;
/* Turn appearance modes off. */
turn_off_face (f, face_id);
tty_turn_off_highlight (tty);
+
+ tty_turn_off_insert (tty);
}
cmcheckmagic (tty);
@@ -799,6 +902,7 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str
{
unsigned char *conversion_buffer;
struct coding_system *coding;
+ int write_on_last_cell;
struct tty_display_info *tty = FRAME_TTY (f);
@@ -808,38 +912,118 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str
/* Don't dare write in last column of bottom line, if Auto-Wrap,
since that would scroll the whole frame on some terminals. */
- if (AutoWrap (tty)
- && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
- && (curX (tty) + len) == FRAME_COLS (f))
+ write_on_last_cell = (AutoWrap (tty)
+ && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
+ && (curX (tty) + len) == FRAME_COLS (f));
+ if (write_on_last_cell)
len --;
- if (len <= 0)
- return;
- cmplus (tty, len);
+ if (FRAME_COLS (f) == 1
+ || !(tty->TS_ins_char || tty->TS_ins_multi_chars
+ || (tty->TS_insert_mode && tty->TS_end_insert_mode)))
+ write_on_last_cell = false;
+
+ if (len <= 0 && !write_on_last_cell)
+ return;
/* If terminal_coding does any conversion, use it, otherwise use
safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
because it always return 1 if the member src_multibyte is 1. */
- coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
+ coding = ((FRAME_TERMINAL_CODING (f)->common_flags
+ & CODING_REQUIRE_ENCODING_MASK)
? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
- /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
- the tail. */
+
+ /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only
+ at the tail. */
coding->mode &= ~CODING_MODE_LAST_BLOCK;
/* Turn appearance modes of the face. */
tty_highlight_if_desired (tty);
turn_on_face (f, face_id);
- coding->mode |= CODING_MODE_LAST_BLOCK;
- conversion_buffer = encode_terminal_code (string, len, coding);
- if (coding->produced > 0)
+ if (len > 0)
+ {
+ cmplus (tty, len);
+ if (write_on_last_cell)
+ glyph_on_char_cell_before_last = string[len - 1];
+ else
+ coding->mode |= CODING_MODE_LAST_BLOCK;
+
+ conversion_buffer = encode_terminal_code (string, len, coding);
+ if (coding->produced > 0)
+ {
+ block_input ();
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->output);
+ clearerr (tty->output);
+ if (tty->termscript)
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->termscript);
+ unblock_input ();
+ }
+ }
+
+ /* Write on the bottom-right corner. */
+ if (write_on_last_cell)
{
- block_input ();
- fwrite (conversion_buffer, 1, coding->produced, tty->output);
- clearerr (tty->output);
- if (tty->termscript)
- fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
- unblock_input ();
+ /* Go to the previous position. */
+ cmgoto (tty, curY (tty), curX (tty) - 1);
+ cmplus (tty, 1);
+
+ conversion_buffer = encode_terminal_code (string, 1, coding);
+ if (coding->produced > 0)
+ {
+ block_input ();
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->output);
+ clearerr (tty->output);
+ if (tty->termscript)
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->termscript);
+ unblock_input ();
+ }
+
+ /* Go to the previous position. */
+ cmgoto (tty, curY (tty), curX (tty) - 1);
+ cmplus (tty, 1);
+
+ /* Arrange that after writing the next glyph, the glyph on the
+ current character cell is somehow pushed to the bottom-right
+ corner. */
+ if (tty->TS_ins_char)
+ {
+ OUTPUT1 (tty, tty->TS_ins_char);
+ }
+ else if (tty->TS_ins_multi_chars)
+ {
+ char *buf = tparam (tty->TS_ins_multi_chars, 0, 0, 1,
+ 0, 0, 0);
+ OUTPUT1 (tty, buf);
+ xfree (buf);
+ }
+ else
+ {
+ tty_turn_on_insert (tty);
+ }
+
+ /* This is the last run. */
+ coding->mode |= CODING_MODE_LAST_BLOCK;
+ conversion_buffer
+ = encode_terminal_code (&glyph_on_char_cell_before_last, 1,
+ coding);
+ if (coding->produced > 0)
+ {
+ block_input ();
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->output);
+ clearerr (tty->output);
+ if (tty->termscript)
+ fwrite (conversion_buffer, 1, coding->produced,
+ tty->termscript);
+ unblock_input ();
+ }
+
+ tty_turn_off_insert (tty);
}
/* Turn appearance modes off. */
--
2.37.1
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: PATCH 2/2 --]
[-- Type: text/x-patch, Size: 10963 bytes --]
From b090cba28981d7a0e40f87211e9b8b065bfdf3e3 Mon Sep 17 00:00:00 2001
From: Akib Azmain Turja <akib@disroot.org>
Date: Tue, 4 Oct 2022 18:54:58 +0600
Subject: [PATCH 2/2] Merge tty_write_glyphs and tty_write_glyphs_with_face
* src/term.c (tty_write_glyphs_1, tty_write_glyphs)
(tty_write_glyphs_with_face): Merge tty_write_glyphs and
tty_write_glyphs_with_face into tty_write_glyphs_1. Define
tty_write_glyphs as a wrapper of tty_write_glyphs_1.
---
src/term.c | 243 +++++++++++++++++------------------------------------
1 file changed, 79 insertions(+), 164 deletions(-)
diff --git a/src/term.c b/src/term.c
index 283a65c4..db1dd2a4 100644
--- a/src/term.c
+++ b/src/term.c
@@ -723,7 +723,8 @@ encode_terminal_code (struct glyph *src, int src_len,
/* An implementation of write_glyphs for termcap frames. */
static void
-tty_write_glyphs (struct frame *f, struct glyph *string, int len)
+tty_write_glyphs_1 (struct frame *f, struct glyph *string, int len,
+ int face_id)
{
unsigned char *conversion_buffer;
struct coding_system *coding;
@@ -761,6 +762,13 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
the tail. */
coding->mode &= ~CODING_MODE_LAST_BLOCK;
+ if (face_id >= 0)
+ {
+ /* Turn appearance modes of the face. */
+ tty_highlight_if_desired (tty);
+ turn_on_face (f, face_id);
+ }
+
if (len > 0)
{
cmplus (tty, len);
@@ -770,16 +778,27 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
for (stringlen = len; stringlen != 0; stringlen -= n)
{
- /* Identify a run of glyphs with the same face. */
- int face_id = string->face_id;
+ int local_face_id;
- for (n = 1; n < stringlen; ++n)
- if (string[n].face_id != face_id)
- break;
+ if (face_id >= 0)
+ {
+ /* This will be a problem when we run the loop another
+ time, but this is the only iteration. */
+ n = stringlen;
+ }
+ else
+ {
+ /* Identify a run of glyphs with the same face. */
+ local_face_id = string->face_id;
- /* Turn appearance modes of the face of the run on. */
- tty_highlight_if_desired (tty);
- turn_on_face (f, face_id);
+ for (n = 1; n < stringlen; ++n)
+ if (string[n].face_id != local_face_id)
+ break;
+
+ /* Turn appearance modes of the face of the run on. */
+ tty_highlight_if_desired (tty);
+ turn_on_face (f, local_face_id);
+ }
if (n == stringlen && !write_on_last_cell)
/* This is the last run. */
@@ -799,24 +818,41 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
}
string += n;
- /* Turn appearance modes off. */
- turn_off_face (f, face_id);
- tty_turn_off_highlight (tty);
+ if (face_id < 0)
+ {
+ /* Turn appearance modes off. */
+ turn_off_face (f, local_face_id);
+ tty_turn_off_highlight (tty);
+ }
}
}
/* Write on the bottom-right corner. */
if (write_on_last_cell)
{
- /* Go to the previous position. */
+ /* The algorithm here is: we write the whole string except the
+ last glyph, then move back to the beginning of previous
+ glyph, write the last glyph, move back again, and insert the
+ glyph before the last glyph in such a way that last glyph at
+ cursor' position gets pushed to the corner. */
+
+ /* Go to the beginning of previous glyph. */
+ /* BUG: This assume the previous glyph is a single column width
+ glyph, so this won't work for multi column width, and the
+ result is terminal-dependent. */
cmgoto (tty, curY (tty), curX (tty) - 1);
cmplus (tty, 1);
- int face_id = string->face_id;
+ int local_face_id;
- /* Turn appearance modes of the face. */
- tty_highlight_if_desired (tty);
- turn_on_face (f, face_id);
+ if (face_id < 0)
+ {
+ local_face_id = string->face_id;
+
+ /* Turn appearance modes of the face. */
+ tty_highlight_if_desired (tty);
+ turn_on_face (f, local_face_id);
+ }
conversion_buffer = encode_terminal_code (string, 1, coding);
if (coding->produced > 0)
@@ -831,12 +867,15 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
unblock_input ();
}
- /* Go to the previous position. */
+ /* Go to the beginning of previous glyph. */
+ /* BUG: This assume the previous glyph is a single column width
+ glyph, so this won't work for multi column width, and the
+ result is terminal-dependent. */
cmgoto (tty, curY (tty), curX (tty) - 1);
cmplus (tty, 1);
/* Arrange that after writing the next glyph, the glyph on the
- current character cell is somehow pushed to the bottom-right
+ current character cell gets pushed to the bottom-right
corner. */
if (tty->TS_ins_char)
{
@@ -854,17 +893,18 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
tty_turn_on_insert (tty);
}
- if (face_id != glyph_on_char_cell_before_last.face_id)
+ if (face_id < 0
+ && local_face_id != glyph_on_char_cell_before_last.face_id)
{
/* Turn appearance modes of the face. */
- turn_off_face (f, face_id);
+ turn_off_face (f, local_face_id);
tty_turn_off_highlight (tty);
- face_id = glyph_on_char_cell_before_last.face_id;
+ local_face_id = glyph_on_char_cell_before_last.face_id;
tty_highlight_if_desired (tty);
- turn_on_face (f, face_id);
+ turn_on_face (f, local_face_id);
}
/* This is the last run. */
@@ -884,157 +924,32 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
unblock_input ();
}
+ if (face_id < 0)
+ {
+ /* Turn appearance modes off. */
+ turn_off_face (f, local_face_id);
+ tty_turn_off_highlight (tty);
+ }
+
+ tty_turn_off_insert (tty);
+ }
+
+ if (face_id >= 0)
+ {
/* Turn appearance modes off. */
turn_off_face (f, face_id);
tty_turn_off_highlight (tty);
-
- tty_turn_off_insert (tty);
}
cmcheckmagic (tty);
}
-#ifndef DOS_NT
-
static void
-tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
- register int len, register int face_id)
+tty_write_glyphs (struct frame *f, struct glyph *string, int len)
{
- unsigned char *conversion_buffer;
- struct coding_system *coding;
- int write_on_last_cell;
-
- struct tty_display_info *tty = FRAME_TTY (f);
-
- tty_turn_off_insert (tty);
- tty_hide_cursor (tty);
-
- /* Don't dare write in last column of bottom line, if Auto-Wrap,
- since that would scroll the whole frame on some terminals. */
-
- write_on_last_cell = (AutoWrap (tty)
- && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
- && (curX (tty) + len) == FRAME_COLS (f));
- if (write_on_last_cell)
- len --;
-
- if (FRAME_COLS (f) == 1
- || !(tty->TS_ins_char || tty->TS_ins_multi_chars
- || (tty->TS_insert_mode && tty->TS_end_insert_mode)))
- write_on_last_cell = false;
-
- if (len <= 0 && !write_on_last_cell)
- return;
-
- /* If terminal_coding does any conversion, use it, otherwise use
- safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here
- because it always return 1 if the member src_multibyte is 1. */
- coding = ((FRAME_TERMINAL_CODING (f)->common_flags
- & CODING_REQUIRE_ENCODING_MASK)
- ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
-
- /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only
- at the tail. */
- coding->mode &= ~CODING_MODE_LAST_BLOCK;
-
- /* Turn appearance modes of the face. */
- tty_highlight_if_desired (tty);
- turn_on_face (f, face_id);
-
- if (len > 0)
- {
- cmplus (tty, len);
- if (write_on_last_cell)
- glyph_on_char_cell_before_last = string[len - 1];
- else
- coding->mode |= CODING_MODE_LAST_BLOCK;
-
- conversion_buffer = encode_terminal_code (string, len, coding);
- if (coding->produced > 0)
- {
- block_input ();
- fwrite (conversion_buffer, 1, coding->produced,
- tty->output);
- clearerr (tty->output);
- if (tty->termscript)
- fwrite (conversion_buffer, 1, coding->produced,
- tty->termscript);
- unblock_input ();
- }
- }
-
- /* Write on the bottom-right corner. */
- if (write_on_last_cell)
- {
- /* Go to the previous position. */
- cmgoto (tty, curY (tty), curX (tty) - 1);
- cmplus (tty, 1);
-
- conversion_buffer = encode_terminal_code (string, 1, coding);
- if (coding->produced > 0)
- {
- block_input ();
- fwrite (conversion_buffer, 1, coding->produced,
- tty->output);
- clearerr (tty->output);
- if (tty->termscript)
- fwrite (conversion_buffer, 1, coding->produced,
- tty->termscript);
- unblock_input ();
- }
-
- /* Go to the previous position. */
- cmgoto (tty, curY (tty), curX (tty) - 1);
- cmplus (tty, 1);
-
- /* Arrange that after writing the next glyph, the glyph on the
- current character cell is somehow pushed to the bottom-right
- corner. */
- if (tty->TS_ins_char)
- {
- OUTPUT1 (tty, tty->TS_ins_char);
- }
- else if (tty->TS_ins_multi_chars)
- {
- char *buf = tparam (tty->TS_ins_multi_chars, 0, 0, 1,
- 0, 0, 0);
- OUTPUT1 (tty, buf);
- xfree (buf);
- }
- else
- {
- tty_turn_on_insert (tty);
- }
-
- /* This is the last run. */
- coding->mode |= CODING_MODE_LAST_BLOCK;
- conversion_buffer
- = encode_terminal_code (&glyph_on_char_cell_before_last, 1,
- coding);
- if (coding->produced > 0)
- {
- block_input ();
- fwrite (conversion_buffer, 1, coding->produced,
- tty->output);
- clearerr (tty->output);
- if (tty->termscript)
- fwrite (conversion_buffer, 1, coding->produced,
- tty->termscript);
- unblock_input ();
- }
-
- tty_turn_off_insert (tty);
- }
-
- /* Turn appearance modes off. */
- turn_off_face (f, face_id);
- tty_turn_off_highlight (tty);
-
- cmcheckmagic (tty);
+ tty_write_glyphs_1 (f, string, len, -1);
}
-#endif
-
/* An implementation of insert_glyphs for termcap frames. */
static void
@@ -2615,8 +2530,8 @@ tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
cursor_to (f, pos_y, pos_x);
if (draw == DRAW_MOUSE_FACE)
- tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
- nglyphs, face_id);
+ tty_write_glyphs_1 (f, row->glyphs[TEXT_AREA] + start_hpos,
+ nglyphs, face_id);
else if (draw == DRAW_NORMAL_TEXT)
write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
--
2.37.1
[-- Attachment #1.4: Type: text/plain, Size: 203 bytes --]
--
Akib Azmain Turja
Find me on Mastodon at @akib@hostux.social.
This message is signed by me with my GnuPG key. Its fingerprint is:
7001 8CE5 819F 17A3 BBA6 66AF E74F 0EFA 922A E7F5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply related [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-10-04 12:54 ` Eli Zaretskii
@ 2022-10-07 13:10 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-07 19:30 ` Eli Zaretskii
0 siblings, 1 reply; 26+ messages in thread
From: Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-10-07 13:10 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gerd.moellmann, 57607
[-- Attachment #1: Type: text/plain, Size: 2162 bytes --]
Eli Zaretskii <eliz@gnu.org> writes:
>> From: Akib Azmain Turja <akib@disroot.org>
>> Cc: 57607@debbugs.gnu.org, gerd.moellmann@gmail.com
>> Date: Tue, 04 Oct 2022 18:00:57 +0600
>>
>> > Please try with some 2-column CJK characters, I'm not sure the example
>> > with ^L is relevant here. You can find the list of wide characters in
>> > characters.el (search for "width"); for example, characters in the
>> > U+FF00 block can be useful.
>>
>> Thanks, "CJK STROKE D" doesn't work as expected, and the result depends
>> on terminal in use. How can I determine the width of a glyph?
>
> Like this:
>
> (char-width CHAR)
>
> where CHAR is the character you are interested in. For example:
>
> (char-width #x31D4)
> => 2
>
> From C, you can call char_width, like Fchar_width (which see) does.
>
> One other subtle point: the argument STRING to tty_write_glyphs is a
> string of 'struct glyph' objects, not a string of characters. Each
> struct glyph has the code of the character to display in its u.ch
> member, if the glyph is a simple character glyph; for the full story
> see encode_terminal_code.
Thanks.
I just discovered new type of glyph: padding glyph. What's this? Is
this a nop glyph? I guess it's used to make string of width N use N
numbers of glyph. But how? Is this like [CJK PAD] or [PAD CJK]?
>
>> > (And the existing code could have bugs,
>> > no need to assume it is always correct.)
>>
>> Yes, it can, but in most cases, my brain has more bugs.
>
> Indeed, that the existing code has bugs should not be our first
> hypothesis. But it shouldn't be axiomatic that there are no bugs
> there ;-)
>
>> > face_id is an integer, and zero is a valid value (it means the default
>> > face), so NULL won't do. But you can use -1 to mean "no face ID".
>> > Just make sure you never pass it to FACE_FROM_ID etc.
>> >
>> > Thanks.
>>
>> OK, I'll try that. Thanks.
>
> TIA
--
Akib Azmain Turja
Find me on Mastodon at @akib@hostux.social.
This message is signed by me with my GnuPG key. Its fingerprint is:
7001 8CE5 819F 17A3 BBA6 66AF E74F 0EFA 922A E7F5
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal
2022-10-07 13:10 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-10-07 19:30 ` Eli Zaretskii
0 siblings, 0 replies; 26+ messages in thread
From: Eli Zaretskii @ 2022-10-07 19:30 UTC (permalink / raw)
To: Akib Azmain Turja; +Cc: gerd.moellmann, 57607
> From: Akib Azmain Turja <akib@disroot.org>
> Cc: 57607@debbugs.gnu.org, gerd.moellmann@gmail.com
> Date: Fri, 07 Oct 2022 19:10:08 +0600
>
> I just discovered new type of glyph: padding glyph. What's this?
See the commentary in dispextern.h for the padding_p flag of 'struct
glyph'.
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2022-10-07 19:30 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <87wnakl5md.fsf@disroot.org>
2022-09-06 6:59 ` bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-06 8:03 ` Gerd Möllmann
2022-09-06 10:07 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-06 12:00 ` Gerd Möllmann
2022-09-06 15:10 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-07 4:58 ` Gerd Möllmann
2022-09-07 12:46 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-07 12:58 ` Gerd Möllmann
2022-09-07 15:39 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-07 17:26 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-08 5:49 ` Gerd Möllmann
2022-09-08 11:28 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-08 12:35 ` Gerd Möllmann
2022-09-08 14:47 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-11 9:00 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-09-11 10:08 ` Gerd Möllmann
2022-09-11 10:39 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-03 8:31 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-03 19:41 ` Eli Zaretskii
2022-10-04 7:22 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-04 8:07 ` Eli Zaretskii
2022-10-04 12:00 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-04 12:54 ` Eli Zaretskii
2022-10-07 13:10 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-07 19:30 ` Eli Zaretskii
2022-10-04 13:05 ` Akib Azmain Turja via Bug reports for GNU Emacs, the Swiss army knife of text editors
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).