URL:
  <https://savannah.gnu.org/bugs/?67349>

                 Summary: screen implements 256-color support but can't
effectively use it (fix included)
                   Group: GNU Screen
               Submitter: enveezee
               Submitted: Wed 23 Jul 2025 04:51:54 AM GMT
                Category: Program Logic
                Severity: 3 - Normal
                Priority: 5 - Normal
                  Status: None
                 Privacy: Public
             Assigned to: None
             Open/Closed: Open
         Discussion Lock: Any
                 Release: 5.0.0
           Fixed Release: None
         Planned Release: None
           Work Required: None


    _______________________________________________________

Follow-up Comments:


-------------------------------------------------------
Date: Wed 23 Jul 2025 04:51:54 AM GMT By: nvz <enveezee>
This problem was discovered running gemini-cli inside screen running on a
mate-terminal on arch linux, the subsequent fix and bug report were generated
by gemini-cli who with a little help from me, ran this issue down and resolved
it to where all themes in gemini-cli now appear with color in screen on
mate-terminal. I am neither familiar with screen source nor did I write this
code, however it seems a trivial fix and I can confirm it works as I have
built and tested the code and verified it fixes the issue.

The issue existed in both the 5.0.1 in arch as well as the 5.0 gemini and I
pulled from git, we fixed the issue in 5.0.0

This bug report seems a bit nonsensical in the portion related to reproducing
the steps but I'm just gonna slap gemini's work below regardless cause it
includes the diff to address the problem.

Problem Description:

When running applications that utilize 256-color or True Color themes (e.g.,
`gemini-cli`, or a simple `node` script using `chalk.hex()`) inside a `GNU
Screen` session, the colors are downgraded to grayscale or a basic 8-color
palette. This occurs even when the `TERM` environment variable is set to
`screen.xterm-256color` (or `xterm-256color`) and `FORCE_COLOR=3` is
exported.

This behavior is observed despite the `screen-256color` terminfo entry
explicitly advertising `colors#256`.

Reproduction Steps:

1.  **System Information:** Arch Linux (or any Linux distribution with `GNU
Screen` and `ncurses`/`terminfo` installed).
2.  **Prerequisites:** `node`, `npm`, `git`, `gcc`, `gdb`.
3.  **Clone `GNU Screen` source:**
    ```bash
    git clone https://git.savannah.gnu.org/git/screen.git screen-source
    ```
4.  **Navigate to source directory:**
    ```bash
    cd screen-source/src
    ```
5.  **Generate build files:**
    ```bash
    autoreconf -fi
    ```
6.  **Configure `screen` (without the fix applied):**
    ```bash
    ./configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-pam --enable-rxvt_osc --enable-telnet
--with-pty-group=5 --with-socket-dir=/run/screens
--with-sys-screenrc=/etc/screenrc
    ```
    *(Note: The `--enable-colors256` flag is not recognized by `configure`,
which is part of the problem's root cause.)*
7.  **Compile `screen`:**
    ```bash
    make
    ```
8.  **Create `test_colors.js`:**
    ```javascript
    // Save this as /home/nvz/Desktop/test_colors.js
    import chalk from 'chalk';

    // Explicitly set chalk.level to 3 (256 colors) for this test
    chalk.level = 3;

    console.log('--- Basic Named Colors (should work in screen) ---');
    console.log(chalk.red('This is red.'));
    console.log(chalk.green('This is green.'));
    console.log(chalk.blue('This is blue.'));
    console.log(chalk.yellow('This is yellow.'));
    console.log(chalk.cyan('This is cyan.'));
    console.log(chalk.magenta('This is magenta.'));
    console.log(chalk.white('This is white.'));
    console.log(chalk.gray('This is gray.'));

    console.log('\n--- Hex Colors (may fail in screen) ---');
    console.log(chalk.hex('#FF0000')('This is hex red.'));
    console.log(chalk.hex('#00FF00')('This is hex green.'));
    console.log(chalk.hex('#0000FF')('This is hex blue.'));
    console.log(chalk.hex('#FFA500')('This is hex orange.'));
    console.log(chalk.hex('#800080')('This is hex purple.'));
    console.log(chalk.hex('#ADD8E6')('This is hex light blue.'));
    ```
9.  **Install `chalk` for the test script:**
    ```bash
    npm install chalk # Run in /home/nvz/Desktop
    ```
10. **Run `test_colors.js` outside `screen`:**
    ```bash
    node /home/nvz/Desktop/test_colors.js
    ```
    *Expected:* All colors (named and hex) display correctly.
11. **Run `test_colors.js` inside `screen`:**
    ```bash
    /home/nvz/Desktop/screen-source/src/screen
    # Inside screen:
    node /home/nvz/Desktop/test_colors.js
    ```
    *Observed:* Hex colors display in grayscale or incorrect colors. Named
colors display correctly.

Analysis of the Bug:

1.  **`terminfo` reports 256 colors:**
    Running `test_tgetnum` (a simple C program that calls `tgetnum("Co")`)
with `TERM=screen.xterm-256color` confirms that the system's
`ncurses`/`terminfo` library correctly reports `256` for the `Co` (colors)
capability.
    ```
    TERM=screen.xterm-256color, tgetnum("Co") returns: 256
    ```
    This indicates the `screen-256color` terminfo entry itself is correct.

2.  **`screen` internally downgrades color capability:**
    Despite `tgetnum("Co")` returning `256`, `screen`'s internal `dumptermcap`
command reports `:Co#8:`. This means `screen` is internally setting its `Co`
capability to `8`, leading to a color downgrade.

3.  **Root Cause:**
    The bug lies in `screen`'s `src/termcap.c`, specifically in the
`InitTermcap` function. While `screen` correctly retrieves the `Co` value from
`terminfo` (which is 256), its logic for setting `D_hascolor` and
`hastruecolor` (which influence the `SetColor` function in `src/display.c`)
does not fully account for the 256-color capability. The `SetColor` function
then downgrades colors if `D_CCO` (which is `D_tcs[68].num`, the `Co` value)
is not `256`. The problem is that `D_tcs[68].num` is being implicitly set to
`8` somewhere, or `screen` is not correctly using the `256` value it
retrieves.

Proposed Fix:

The fix involves modifying `src/termcap.c` to ensure `D_hascolor` and
`hastruecolor` are correctly set based on the `Co` capability.

Diff for `src/termcap.c`:

```diff
diff --git a/src/termcap.c b/src/termcap.c
index b49818b..3267d2c 100644
--- a/src/termcap.c
+++ b/src/termcap.c
@@ -271,8 +271,15 @@ int InitTermcap(int width, int height)
                        t = D_attrtyp[i];
                }
        }
-+      if (D_CAF || D_CAB || D_CSF || D_CSB)
-+              D_hascolor = 1;
+           if (D_tcs[55].num >= 8) {
+               D_hascolor = 1;
+           }
+           if (D_tcs[55].num >= 256) {
+               D_hascolor = 1;
+           }
+           if (D_tcs[55].num >= 16000000) { /* True Color */
+               hastruecolor = true;
+           }
        if (D_UT)
                D_BE = 1;       /* screen erased with background color */








    _______________________________________________________

Reply to this item at:

  <https://savannah.gnu.org/bugs/?67349>

_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/

Attachment: signature.asc
Description: PGP signature

Reply via email to