ElectorNikles
ElectorNikles

Reputation: 41

NCurses: Why does init_color return OK but still not set the color?

I am attempting to set the background of a block of text to red by setting the value COLOR_BLUE to the rgb values of: (1000, 0, 0). The background is correct (RED) if I use Gnome's "Terminal" application, but incorrect (BLUE) if I use KDE's "Konsole". Why is this? The following code will compile on Linux with the compile line:

g++ filename.cpp -lcurses

I set my TERM type to xterm-256color via:

export TERM=xterm-256color

here's the code:

#include <ncurses.h>
#include <cassert>
#include <csignal>

static bool stop = false;

void sigAbortHandler(int _sig)
{
    stop = true;
}

int main(int _argc, char **_argv)
{
    signal(SIGABRT, &sigAbortHandler);

    WINDOW *window = initscr();

    if (!has_colors())
    {
        delwin(window);
        endwin();
        perror("You must enable colors in your console");
    }

    if (!can_change_color())
    {
        delwin(window);
        endwin();
        perror("Error: unable to change colors, "
               "trying setting your TERM type to enable colors");
    }

    assert(start_color() == OK);
    keypad(stdscr, TRUE);
    cbreak();
    noecho();
    curs_set(0);
    nodelay(window, true);

    int background = COLOR_BLUE;
    assert(init_color(background, 1000, 0, 0) == OK);
    int foreground = 2;
    assert(init_color(foreground, 0, 0, 0) == OK);
    int pair = 1;
    assert(init_pair(pair, foreground, background) == OK);
    assert(wattron(window, COLOR_PAIR(pair)) == OK);

    short r, g, b;
    color_content(background, &r, &g, &b);
    assert(mvwprintw(window, 10, 10, "color content: %d, %d, %d", r, g, b) == OK);
    assert(wrefresh(window) == OK);
    assert(wattroff(window, COLOR_PAIR(pair)) == OK);

    while (!stop)
    {
    }

    delwin(window);
    endwin();

    return 0;
}

Upvotes: 4

Views: 3342

Answers (3)

Thomas Dickey
Thomas Dickey

Reputation: 54524

The problem is that Konsole does not implement the feature you are expecting. ncurses only knows what is in the terminal description which you have configured. There is no general-purpose method for checking that it is correct. The RETURN-VALUE section of init_color says

init_color
returns an error if the terminal does not support this feature, e.g., if the initialize_color capability is absent from the terminal description.

Presumably you have something like TERM=xterm-256color. The ncurses terminal database has a correct konsole-256color, which (using infocmp to compare with xterm-256color) differs in many respects:

comparing xterm-256color to konsole-256color.
    comparing booleans.
    ccc: T:F.
    km: T:F.
    mc5i: T:F.
    comparing numbers.
    comparing strings.
    bel: '^G', NULL.
    cbt: '\E[Z', NULL.
    cnorm: '\E[?12l\E[?25h', '\E[?25h'.
    cvvis: '\E[?12;25h', NULL.
    dim: '\E[2m', NULL.
    el1: '\E[1K', NULL.
    enacs: NULL, '\E)0'.
    ich: '\E[%p1%d@', NULL.
    initc: '\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\', NULL.
    invis: '\E[8m', NULL.
    is2: '\E[!p\E[?3;4l\E[4l\E>', '\E[m\E[?7h\E[4l\E>\E7\E[r\E[?1;3;4;6l\E8'.
    kDC: '\E[3;2~', NULL.
    kEND: '\E[1;2F', NULL.
    kHOM: '\E[1;2H', NULL.
    kIC: '\E[2;2~', NULL.
    kLFT: '\E[1;2D', NULL.
    kNXT: '\E[6;2~', NULL.
    kPRV: '\E[5;2~', NULL.
    kRIT: '\E[1;2C', NULL.
    kb2: '\EOE', NULL.
    kent: '\EOM', NULL.
    kf13: '\E[1;2P', '\EO2P'.
    kf14: '\E[1;2Q', '\EO2Q'.
    kf15: '\E[1;2R', '\EO2R'.
    kf16: '\E[1;2S', '\EO2S'.
    kf25: '\E[1;5P', '\EO5P'.
    kf26: '\E[1;5Q', '\EO5Q'.
    kf27: '\E[1;5R', '\EO5R'.
    kf28: '\E[1;5S', '\EO5S'.
    kf37: '\E[1;6P', '\EO6P'.
    kf38: '\E[1;6Q', '\EO6Q'.
    kf39: '\E[1;6R', '\EO6R'.
    kf40: '\E[1;6S', '\EO6S'.
    kf49: '\E[1;3P', '\EO3P'.
    kf50: '\E[1;3Q', '\EO3Q'.
    kf51: '\E[1;3R', '\EO3R'.
    kf52: '\E[1;3S', '\EO3S'.
    kf61: '\E[1;4P', '\EO4P'.
    kf62: '\E[1;4Q', '\EO4Q'.
    kf63: '\E[1;4R', '\EO4R'.
    kind: '\E[1;2B', NULL.
    kri: '\E[1;2A', NULL.
    mc0: '\E[i', NULL.
    mc4: '\E[4i', NULL.
    mc5: '\E[5i', NULL.
    rmacs: '\E(B', '^O'.
    rmcup: '\E[?1049l', '\E[2J\E[?47l\E8'.
    rmm: '\E[?1034l', NULL.
    rs1: '\Ec', NULL.
    rs2: '\E[!p\E[?3;4l\E[4l\E>', '\E7\E[r\E8\E[m\E[?7h\E[?1;3;4;6l\E[4l\E>\E[?1000l\E[?25h'.
    sgr: '%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p5%t;2%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m', '\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t\016%e\017%;'.
    sgr0: '\E(B\E[m', '\E[0m\017'.
    smacs: '\E(0', '^N'.
    smcup: '\E[?1049h', '\E7\E[?47h'.
    smm: '\E[?1034h', NULL.

Where you see NULL, Konsole did not implement the feature at all. In particular, it did nothing for initc (the feature you are asking about).

Further reading:

Upvotes: 3

xaizek
xaizek

Reputation: 5252

Seemingly relevant excerpt from man init_color:

The init_color routine changes the definition of a color.  ... The first
argument must be a legal color value; **default colors are not allowed here**.
(See the section Colors for the default color index.)
...
Colors
...
In <curses.h> the following macros are defined.  These are the default colors.
...
             COLOR_BLUE

So these lines are doing something that shouldn't work according to the documentation, but might and do work in some terminals:

int background = COLOR_BLUE;
assert(init_color(background, 1000, 0, 0) == OK);
int foreground = 2;
assert(init_color(foreground, 0, 0, 0) == OK);

There should be 16 predefined color pairs (if we count bold colors), so using pairs 16 and 17 instead of COLOR_BLUE and 2 might work.

(Don't have Konsole to check this, but this might be the reason or at least is worth pointing out.)

Upvotes: 1

cdated
cdated

Reputation: 1773

Did you mean to set background to COLOR_BLUE? Despite checking can_change_color, it appears that init color doesn't have an affect on Konsole, and the background is staying COLOR_BLUE at init_pair.

int background = COLOR_BLUE;
assert(init_color(background, 1000, 0, 0) == OK);
...
assert(init_pair(pair, foreground, background) == OK);
assert(wattron(window, COLOR_PAIR(pair)) == OK);

Upvotes: 1

Related Questions