Subject: Re: bug#69598: 29.2; colour support based on $TERM value not terminfo database

From: [email-masked]
Date: Fri, 08 Mar 2024 11:36:18 +0000

Eli Zaretskii writes:
> > From: [email-masked]
> > cc: [email-masked], [email-masked]
> > Comments: In-reply-to Eli Zaretskii <[email-masked]>
> >    message dated "Thu, 07 Mar 2024 22:10:30 +0200."
> > Date: Thu, 07 Mar 2024 21:45:44 +0000
>
> Thanks.  These results AFAIU indicate that there's no problem with the
> terminfo level: the number of colors known to term.c (printed as max:)
> is the same no matter how you start Emacs.  Do you agree with this
> conclusion?

That does appear to be the case. In fact the number of colours is
set by 'tty->TN_max_colors = tgetnum ("Co")' and then set again
when the RGB or other direct-colour capability is detected.

Unfortunately the information from terminfo is sometimes ignored.

> I think the problem is that if the terminal's name doesn't begin with
> "xterm", Emacs does not load lisp/term/xterm.el, which defines the
> colors that will be available.  So please copy lisp/term/xterm.el to a
> file named lisp/term/notworking.el, and then start Emacs with
> TERM=notworking and see if that solves the problem.  That is, arrange
> for a lisp/term/NAME.el file to be a copy of xterm.el when you invoke
> Emacs with TERM=NAME.

If we're at the point where the terminal's name matters one jot,
that is to say when the value of $TERM is used for _anything_ other
than selecting a terminfo entry, that is a bug.

I don't know how emacs finds files when it's not installed so I
will be thorough:

        $ cd ~/src/emacs-29.2
        $ cp lisp/term/xterm.el lisp/term/notworking.el
        $ gmake
        $ ls -l lisp/term/{xterm,notworking}*
        -rw-r--r--  1 mking  mking  46048 Mar  8 10:46 lisp/term/notworking.el
        -rw-r--r--  1 mking  mking  32368 Mar  8 10:46 lisp/term/notworking.elc
        -rw-r--r--  1 mking  mking  46048 Jan  6 12:56 lisp/term/xterm.el
        -rw-r--r--  1 mking  mking  32368 Jan 18 10:06 lisp/term/xterm.elc
        $ infocmp -x notworking xterm-direct    # to confirm they're identical
        comparing notworking to xterm-direct.
            comparing booleans.
            comparing numbers.
            comparing strings.
        $ export TERM=notworking
        $ ./src/emacs -nw                       # confirm 8 colours
        $ export TERM=xterm-direct
        $ ./src/emacs -nw                       # confirm 256 named colours

While I was setting up this test I'd forgotten that I changed the
value in each of the three assignments to TN_max_colors in order
to confirm which condition inside the TERMINFO block was satisfied.

Before correcting that, running with TERM=notworking reported 8
colours but with TERM=xterm-direct reported 16 (the extra 8 are all
black) and said in *Messages*: xterm-register-default-colors:
Unsupported number of xterm colors (16777214).

The value ending in 4 pointed to the tigetflag("RGB") block which
reminded me of the -x option to tic telling it to accept non-standard
capabilities (of which RGB is one) and I thought perhaps the option
was also necessary when creating an entry which uses an entry
which has non-standard capabilities. It turns out that it is and
that notworking was lacking the extra capabilities.

So I got excited that maybe I'd found the problem and it was in
fact bad terminfo data. I did the whole round of tests again but
this time using "tic -x new.info" instead of plain tic (confirmed
with infocmp -x that the extended capabilities exist in the new
terminfo entries notworking and xterm-working).

The result was identical.

Summary:

My generated terminfo files were wrong. I needed to use tic -x.

That doesn't matter though because whether or not emacs detects
"RGB", direct colour availability depends on the $TERM value beginning
with "xterm-" (and, curiously, that TN_max_colors is valid --- if
TERM=notworking an invalid TN_max_colors is ignored).

Creating the file lisp/term/notworking.el had no apparent effect.

That's it. Nothing important follows.

> > Notably TS_orig_pair is printed here as an empty string in all cases
> > (NULL would print as "(null)"? and there there are no extra spaces),
> > created by requesting the op capability which *is* defined in
> > xterm-direct.
> > 
> >         $ infocmp dumb xterm-direct | grep op: 
> >                 op: NULL, '\E[39;49m'.
>
> I don't think I see why TS_orig_pair's value is relevant to the issue
> at hand.  Can you explain why you are interested in it?

Immediately prior to the TERMINFO block is this code:

          /* SVr4/ANSI color support.  If "op" isn't available, don't support
             color because we can't switch back to the default foreground and
             background.  */
          tty->TS_orig_pair = tgetstr ("op", address);
          if (tty->TS_orig_pair)
            {
              tty->TS_set_foreground = tgetstr ("AF", address);
              tty->TS_set_background = tgetstr ("AB", address);
              if (!tty->TS_set_foreground)
        	{
        	  /* SVr4.  */
        	  tty->TS_set_foreground = tgetstr ("Sf", address);
        	  tty->TS_set_background = tgetstr ("Sb", address);
        	}

              tty->TN_max_colors = tgetnum ("Co");

        #ifdef TERMINFO
              {
                ...
              }
        #endif

When I originally patched term.c (I've had enough of using one
terminal to debug another terminal that is running its own terminal)
I included the print statements at the end of the TERMINFO block
and the debug file did not get created. I moved it down to above
the next '}' line which appears to correspond to the test of
tty->TS_orig_pair to no avail (the combination of C, CPP and
indentation is hard to follow) then I moved it out of that block
and began the test which got the results I sent last night.

Probing it again with coffee it appears that TS_orig_pair is given
a value and the block is entered so I expect I misread something
when writing the patch.

That reveals a misunderstanding, again because I assumed a cat would
be enough. The pair line (printing tty->TS_orig_pair) does in fact
have a value: 1b 5b 33 39 3b 34 39 6d which is the correct SGR
control and would obviously not have an appearance when sent to a
terminal. It is in the debug file.

Focusing on tty->termcap_strings_buffer appears to be another red
herring. I was trying to figure out where tgetstr is getting its
data from and address née area née tty->termcap_strings_buffer was
the obvious candidate.

Cheers,

Matthew