Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Color Pairs in ncurses not using correct colors

I'm trying to use ncursesw6.1 (linked to PicoLisp). As far as I know, PicoLisp directly passes through values in such a way that the fact that I'm calling ncurses through a non-C language shouldn't be a factor[1]. However, when I try to use color pairs (defined like this):

(curses "init_pair" NIL 1 *COLOR-SCHEME-TEXT *COLOR-SCHEME-BACKGROUND-DARK)
(curses "init_pair" NIL 2 *COLOR-SCHEME-COMMENT *COLOR-SCHEME-BACKGROUND-DARK)
(curses "init_pair" NIL 3 *COLOR-SCHEME-FUNCTION *COLOR-SCHEME-BACKGROUND-DARK)
(curses "init_pair" NIL 4 *COLOR-SCHEME-VALUE *COLOR-SCHEME-BACKGROUND-DARK)
(curses "init_pair" NIL 5 *COLOR-SCHEME-BACKGROUND-DARK *COLOR-SCHEME-COMMENT)
(curses "init_pair" NIL 6 *COLOR-SCHEME-BACKGROUND-DARK *COLOR-SCHEME-FUNCTION)
(curses "init_pair" NIL 7 *COLOR-SCHEME-BACKGROUND-DARK *COLOR-SCHEME-VALUE)

It doesn't work. Instead, color pair 1, 2, and 3 are all displayed as the same color pair. Then 4 and 6 are displayed as *COLOR-SCHEME-COMMENT over top of *COLOR-SCHEME-BACKGROUND-DARK and 5 and 7 are displayed as the reverse of 4 and 6. This seems to have no logical relation whatever to what I've entered. Even more strangely, when I use non-custom colors (colors 0-7) it doesn't work either, so having defined these color scheme colors through init_color has nothing to do with it.

I've individually tested the colors with color pair 1, so I know that the colors are being initialized correctly.

What exactly is going on with init_pair?

P.S. I've genuinely sorry if the fact that I'm using Lisp makes this harder, I know its not a common language. It seemed like a good idea at the time, and its been fine so far...

Edit: I've receompiled libncursesw6.1 with --with-trace enabled, and this is the pertinent info from the trace file:

called {init_pair(0x1d74d00,1,10,8)
+ return }0
+ called {init_pair(0x1d74d00,2,12,8)
+ return }0
+ called {init_pair(0x1d74d00,3,11,8)
+ return }0
+ called {init_pair(0x1d74d00,4,13,8)
+ return }0
+ called {init_pair(0x1d74d00,5,8,12)
+ return }0
+ called {init_pair(0x1d74d00,6,8,11)
+ return }0
+ called {init_pair(0x1d74d00,7,8,13)
+ return }0

These are indeed the correct values, so the right values are being passed to init_pair. Although the custom colors are not the issue, for those who want to know, here's the trace file's info on the *COLOR-SCHEME colors:

started color: COLORS = 256, COLOR_PAIRS = 65536
+ return }0
+ called {init_color(0x1d74d00,8,216,228,252)
+ + called {tparm("\e]4;%p1%d;rgb:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\e\\", 8, 216, 228, 252)
+ + return }"\e]4;8;rgb:37/3A/40\e\\"
+ return }0
+ called {init_color(0x1d74d00,9,908,956,896)
+ + called {tparm("\e]4;%p1%d;rgb:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\e\\", 9, 908, 956, 896)
+ + return }"\e]4;9;rgb:E7/F3/E4\e\\"
+ return }0
+ called {init_color(0x1d74d00,10,968,968,968)
+ + called {tparm("\e]4;%p1%d;rgb:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\e\\", 10, 968, 968, 968)
+ + return }"\e]4;10;rgb:F6/F6/F6\e\\"
+ return }0
+ called {init_color(0x1d74d00,11,612,748,1000)
+ + called {tparm("\e]4;%p1%d;rgb:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\e\\", 11, 612, 748, 1000)
+ + return }"\e]4;11;rgb:9C/BE/FF\e\\"
+ return }0
+ called {init_color(0x1d74d00,12,508,252,340)
+ + called {tparm("\e]4;%p1%d;rgb:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\e\\", 12, 508, 252, 340)
+ + return }"\e]4;12;rgb:81/40/56\e\\"
+ return }0
+ called {init_color(0x1d74d00,13,612,136,272)
+ + called {tparm("\e]4;%p1%d;rgb:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\e\\", 13, 612, 136, 272)
+ + return }"\e]4;13;rgb:9C/22/45\e\\"
+ return }0

In addition, although I set the wborder function to use color pair 7, which according to the debug info should be color 8 over color 13 (which matches what I have in my code), the trace file says that it is actually using color pair five, which I don't use anywhere in the code:

+ called {wborder(0x1da6cd0,{' ' = 040},{' ' = 040},{' ' = 040},{' ' = 040},{' ' = 040},{' ' = 040},{' ' = 040},{' ' = 040})
using {' ' = 040 | {A_BOLD|A_COLOR{5 = {color8, color12}}}}, {' ' = 040 | {A_BOLD|A_COLOR{5 = {color8, color12}}}}, {' ' = 040 | {A_BOLD|A_COLOR{5 = {color8, color12}}}}, {' ' = 040 | {A_BOLD|A_COLOR{5 = {color8, color12}}}}, {' ' = 040 | {A_BOLD|A_COLOR{5 = {color8, color12}}}}, {' ' = 040 | {A_BOLD|A_COLOR{5 = {color8, color12}}}}, {' ' = 040 | {A_BOLD|A_COLOR{5 = {color8, color12}}}}, {' ' = 040 | {A_BOLD|A_COLOR{5 = {color8, color12}}}}
+ return }0

So, what I conjectured above is what is, indeed, happening. Color pairs 5 and 7 are being displayed the same, even though the colors and the pairs are being passed correctly to ncurses.

like image 683
Alexis Dumas Avatar asked Nov 07 '22 22:11

Alexis Dumas


1 Answers

According to @christopher-dumas, the problem was an error in PicoLisp:

Okay I figured out what the problem was
color-pairs was implemented incorrectly, because Picolisp only has a right-shift operation, and the operand order is the oppsite of what C uses. Apparently, the source where I took the origional implementation of color-pairs was wrong. For the new implementation, I copied it from lib_gen.c in the ncurses source code. The new implementation is:

   (de color-pair (n)
       (& (>> -8 n) (>> -8 (- (>> -8 1) 1))))

In ncurses, the color-pair value is an 8-bit field in chtype or attr_t, defined in the curses.h header. Here's a quote from the template (the @cf_cv_1UL@ is substituted to handle very old compilers which did not permit a UL suffix for numbers):

#define NCURSES_ATTR_SHIFT       8
#define NCURSES_BITS(mask,shift) (NCURSES_CAST(chtype,(mask)) << ((shift) + NCURSES_ATTR_SHIFT))
...
#define A_COLOR     NCURSES_BITS(((@cf_cv_1UL@) << 8) - @cf_cv_1UL@,0)
like image 65
Thomas Dickey Avatar answered Nov 13 '22 06:11

Thomas Dickey