* Why Emacs doesn't touch the bottom-right corner of terminal @ 2022-09-03 17:39 Akib Azmain Turja 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 0 siblings, 1 reply; 27+ messages in thread From: Akib Azmain Turja @ 2022-09-03 17:39 UTC (permalink / raw) To: emacs-devel [-- Attachment #1: Type: text/plain, Size: 570 bytes --] 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] 27+ messages in thread
* bug#57607: Feature request: Use the character cell on bottom-right corner of a terminal 2022-09-03 17:39 Why Emacs doesn't touch the bottom-right corner of terminal Akib Azmain Turja @ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ 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; 27+ 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] 27+ messages in thread
end of thread, other threads:[~2022-10-07 19:30 UTC | newest] Thread overview: 27+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-09-03 17:39 Why Emacs doesn't touch the bottom-right corner of terminal Akib Azmain Turja 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 external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.