color not ended in curses

久未见 提交于 2019-12-08 07:39:00

问题


I am recently working on a game project using the curses library, and I used color-related functions like start_color(), init_color() and init_pair(). The color works well in my project, but once its used, the colors in other TUI applications like vim will go wrong.

For example: When I first edit some part of my code, it is like this:

This is vim with colorscheme slate, and it looks good.

However, when I run my code and exit and edit the code again, it become something like this:

Note: I did not change anything when I did this, and I thought that it is because I have changed the color definitions when I run my code. Also, if I use other functions, it will also go wrong, like:

But the original one should look like this:

I wanna know why this is happening, I thought there may be some ending functions of color I am not using, just like initscr() and endwin(), there should be another one for start_color(). Can anyone tell me why? Thanks a lot.


回答1:


For terminals that support it, init_color() has a different effect than the other color-related functions in ncurses. It changes the palette of colors used by any application:

If a terminal is capable of redefining colors, the programmer can use the routine init_color to change the definition of a color.

The palette is stored in the terminal emulator; every application which uses colors will use the same set of colors unless it modifies the palette via escape sequences. Those escape sequences are documented in XTerm Control Sequences.

ncurses has no way to determine what the palette of colors is at the start; it cannot restore the palette to its initial state on exit (e.g., in endwin). Unlike the color pair (default 0), there is no predefined palette used by all terminals which can produce color. To see this, compare the initc capability for these variations:

  • xterm (256 colors)
   initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\,
  • Linux console (16 colors)
   initc=\E]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x,

Because the only information that ncurses has is how to change the color, it cannot set the palette back to its original state on exit.

Further reading:

  • How to determine the current color of the console output?
  • ANSI/ECMA 48 color codes: getting background rendition



回答2:


Yes it's possible if you use the extension function color_content. This is not a complete program but this demonstrates how it can be done.

Note that I check first that the terminal has colours but then I also test if the terminal can change colours (I am not 100% certain that the can_change_color is a needed test before using color_pair but it seems like it might be so I do).

Note also that I do not do any error checking so you'll have to do that yourself. In the below code I redefine three colour pairs. There might be redundant/unneeded code but I'm extracting this from a project of mine that I did in sequence and having only done this part I haven't tested beyond. Anyway:

short i, r, g, b;
r = g = b = 0;
if ((z=has_colors()))
{
start_color();
init_pair(1, COLOR_GREEN, COLOR_BLACK);
init_pair(2, COLOR_RED, COLOR_BLACK);
init_pair(3, COLOR_YELLOW, COLOR_YELLOW);
}

#define COLOURS 3
short colours[COLOURS][3] = { 
        { 0, 0, 0 },
        { 0, 0, 0 },
        { 0, 0, 0 },
};

if (z && can_change_color())
{
    z = 2; /* N.B. If curses TRUE was actually set to 2 this wouldn't be right but I've not seen that and I'm not changing it for demonstration purposes */

    for (i = 0; i < COLOURS; ++i)
    {
        color_content(i+1, &r, &g, &b);
        colours[i][0]=r;
        colours[i][1]=g;
        colours[i][2]=b;
    }

    init_color(1, 0, 175, 0);
    init_color(2, 255, 0, 0);
    init_color(3, 150, 75, 0);
}
/* ... */
getch();
if (z == 2)
{
    for (i = 0; i < COLOURS; ++i)
        init_color(i+1, colours[i][0], colours[i][1], colours[i][2]);
}
endwin();

/* ... */

N.B. I did the copy/paste in several goes so if there's an error that would be why. I'll fix it if necessary. Oh and if any of the ncurses functions above refer to 'colour' it's because of the device I'm on currently. The names for constants/variables I have chosen I do use colour but ncurses does not.

Anyway this saves the colour definitions and then before calling endwin() I restore the colours (if colours can be changed). It seems that can_change_color() is not an extension and neither are the init_ functions. However it does seem that color_content is an extension. In other words I don't know if I have all the tests right but what I do know is that this saves and then restores the colours (though as I said I did not test for errors in any of the function calls - I leave that up to you).



来源:https://stackoverflow.com/questions/36051061/color-not-ended-in-curses

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!