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/
signature.asc
Description: PGP signature
