TUI programs that want to use features that are not
backwards-compatible can do so by querying for support (via XTGETTCAP
for example) and awaiting the terminals reply.

A terminal that doesn't support a certain feature may fail to reply.
A good workaround is to follow-up the initial query with another
query that is expected to get a reply.

Primary DA is the de-facto standard query to use.  It is implemented
by every terminal I know, including Terminal.app, st, Putty.

In absence of a reply,
- TUI framework [notcurses] will hang forever
- TUI framwork [libvaxis] will block with a 1 second timeout
- fish shell will do either (currently hangs until ctrl-c is pressed)

So far, among relevant terminal-like programs, I found only dvtm
(and pexpect) to be missing Primary DA.

Pretend we are a VT102 (see
https://invisible-island.net/xterm/ctlseqs/ctlseqs.html) because
that's what st uses.  I believe this should be fine in practice but
if there are concerns that programs might make invalid assumptions
based on that, we can invent a new user agent.

st allows to configure this string; that would be fine too although
I have not found out why one would want to.

Alternatively, we could forward the request to stdout (i.e. do
"printf '\033[0c'") which would cause dvtm's parent terminal to reply.
I think this would be more technically-correct, but since it doesn't
look like we directly forward any other query, I'd stick to this
safer option for now.

[notcurses]: 
https://github.com/dankamongmen/notcurses/blob/da7151929d9f87a73cabb4c5b54668b3a42cfcaf/TERMINALS.md?plain=1#L35-L37
[libvaxis]: https://github.com/rockorager/libvaxis
---
 vt.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/vt.c b/vt.c
index 15dabc1..3a2afe3 100644
--- a/vt.c
+++ b/vt.c
@@ -1078,6 +1078,13 @@ static void interpret_csi(Vt *t)
        case 'Z': /* CBT: cursor backward tabulation */
                puttab(t, param_count ? -csiparam[0] : -1);
                break;
+       case 'c':
+               if (param_count == 0 || (param_count == 1 && csiparam[0] == 0)) 
{
+                       // Primary Device Attribute.
+                       const char* vtiden = "\033[?6c";
+                       vt_write(t, vtiden, strlen(vtiden));
+               }
+               break;
        case 'g': /* TBC: tabulation clear */
                switch (param_count ? csiparam[0] : 0) {
                case 0:
-- 
2.48.1


Reply via email to