1

I found an old game I wrote using ncurses. I noticed that after closing the game and running another ncurses based program, the colours had changed for that program as well. This is entirely expected behaviour that I wasn't aware of when I wrote the game several years ago.

Since ncurses doesn't know the initial palette, there is no way to reset the palette to its initial values after quitting the game. With this in mind, what is the best way to deal with colours in ncurses?

Here's what I've considered:

  1. Only override colours that are higher up in the palette. If you start changing colours from position 0, it's very likely that you will change colours that other programs are using. If you start at 100 (for instance), it's much less likely that your changes will interfere with another program. I suppose not changing the 16 colour ANSI palette is the key here.
  2. Manually inspect the default palette and choose default colours that fit the game. Besides being cumbersome and perhaps not letting you set the exact colour you want, there is no guarantee that the default palette will be the same on all systems. There might be a library to automatically get the corresponding xterm colour. It seems like https://github.com/vim-scripts/CSApprox is doing something like that. I would assume that most modern systems will run terminals with the same palette, so it might be fine, depending on what systems you are targeting. The default palette of xterm is available here: https://jonasjacek.github.io/colors/
  3. Use color_content to get the original colour. I tried it and it didn't work. ncurses can only get the colour content of colours that were set by init_color.
  4. Restore the palette to the default xterm palette. I suppose if the terminal supports 256 colours, there's a good chance that it is using the default xterm palette. However, the user might have changed it, so it might still interfere with the users configuration.
  5. Use API specific to xterm or other terminal emulator for getting colours. I don't know if any such API exists, but it would be a potential solution, with the major drawback that it will only support that specific terminal emulator.

I might implement both 1 and 2, and let the user choose the behaviour by passing a flag. I don't know of any terminal programs that use rich colours, so not sure how many programs out there actually face this problem, but there's bound to be at least a few. If you have any examples of how other programs deal with this, that would be very helpful.

Erik B
  • 40,889
  • 25
  • 119
  • 135
  • If you are targetting xterm you can use 24-bit colour instead of modifying the palette. That also works on many other terminal emulators. – rici Jul 13 '20 at 01:45
  • @rici Could you provide some more information on how to do that? – Erik B Jul 13 '20 at 15:18
  • *`tput oc`* should reset the palette. By the way, this is not a programmiing question. – Thomas Dickey Jul 13 '20 at 18:27
  • @ThomasDickey How is this not a programming question? I'm asking how to get nice colours in an `ncurses` program without changing the colours for other programs. I'm looking for APIs (or ways to use APIs) that let me do that so that I can program my program. Sounds like a programming question to me. I'm not asking for a command to run afterwards to compensate for a poorly programmed program, although that is also of interest. `man tput` didn't explain what `oc` is, would you mind elaborating? :) – Erik B Jul 13 '20 at 18:57
  • You're asking for opinions on how to proceed. By the way, I already noted the recommended approach, which was none of the options you considered. – Thomas Dickey Jul 13 '20 at 19:26
  • For **oc**, see man *terminfo(5)* – Thomas Dickey Jul 13 '20 at 19:27
  • @ThomasDickey What is the recommended approach? Using 24-bit colours? I don't know how to do that. If you know how to implement the recommended approach, I'd be very grateful if you would put that in an answer. :) – Erik B Jul 13 '20 at 20:48
  • @ThomasDickey By the way, I tried `tput oc` and it didn't fix the colours for me. Also, `man terminfo(5)` generates the following output: _-bash: syntax error near unexpected token `('_ – Erik B Jul 13 '20 at 21:03
  • That could be "man 5 terminfo", "man -s 5 terminfo", etc. It's also [here](https://invisible-island.net/ncurses/man/terminfo.5.html): "Set all color pairs to the original ones". Whether it works or not depends on the terminal vs the terminal description (some don't support [OSC 104](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Operating-System-Commands:OSC-Ps;Pt-ST:Ps-=-1-0-4;c.1114). If you've found one of those setting `TERM=xterm`, you're best off deleting it. – Thomas Dickey Jul 13 '20 at 22:09

1 Answers1

0

From https://invisible-island.net/ncurses/ncurses.faq.html:

If your terminal description does not contain the orig_pair or orig_colors capability, you will be unable to reset colors to the pre-curses state. This happens, for example, with aixterm.

However, if your terminal does support resetting colors to a default state, ncurses will use this when exiting Curses mode. Terminal types that do this include the Linux console, rxvt and the XFree86 xterm.

To find out if your terminal can reset the colors, run:

infocmp -L | grep orig

Mine can only reset pairs and not colors. I haven't found an API to check this from the program itself, but there's no real reason to check it unless you've implemented multiple ways of dealing with colors. I have, by the way, and I'm not happy with either.

I tried overriding colors higher up in the palette and I still managed to change colors for other programs. I still think it's sensible to avoid the 16 first colors, but it seems like there are no colors that you can safely change.

I also tried using the default colors from https://jonasjacek.github.io/colors/, but I couldn't get the effect I wanted. I could probably simplify the theme and still make it look nice, but I couldn't replicate the look I was going for.

It seems like the best solution is to make a nice looking theme with the default colors, unless that isn't possible, in which case you will just have to accept that other programs might not look great as a result. It's not too difficult to open a new terminal anyway, and that will get your colors sorted again.

Erik B
  • 40,889
  • 25
  • 119
  • 135