| /* PDCurses */ |
| |
| #include <curspriv.h> |
| |
| /*man-start************************************************************** |
| |
| color |
| ----- |
| |
| ### Synopsis |
| |
| bool has_colors(void); |
| int start_color(void); |
| int init_pair(short pair, short fg, short bg); |
| int pair_content(short pair, short *fg, short *bg); |
| bool can_change_color(void); |
| int init_color(short color, short red, short green, short blue); |
| int color_content(short color, short *red, short *green, short *blue); |
| |
| int alloc_pair(int fg, int bg); |
| int assume_default_colors(int f, int b); |
| int find_pair(int fg, int bg); |
| int free_pair(int pair); |
| int use_default_colors(void); |
| |
| int PDC_set_line_color(short color); |
| |
| ### Description |
| |
| To use these routines, first, call start_color(). Colors are always |
| used in pairs, referred to as color-pairs. A color-pair is created by |
| init_pair(), and consists of a foreground color and a background |
| color. After initialization, COLOR_PAIR(n) can be used like any other |
| video attribute. |
| |
| has_colors() reports whether the terminal supports color. |
| |
| start_color() initializes eight basic colors (black, red, green, |
| yellow, blue, magenta, cyan, and white), and two global variables: |
| COLORS and COLOR_PAIRS (respectively defining the maximum number of |
| colors and color-pairs the terminal is capable of displaying). |
| |
| init_pair() changes the definition of a color-pair. It takes three |
| arguments: the number of the color-pair to be redefined, and the new |
| values of the foreground and background colors. The pair number must |
| be between 0 and COLOR_PAIRS - 1, inclusive. The foreground and |
| background must be between 0 and COLORS - 1, inclusive. If the color |
| pair was previously initialized, the screen is refreshed, and all |
| occurrences of that color-pair are changed to the new definition. |
| |
| pair_content() is used to determine what the colors of a given color- |
| pair consist of. |
| |
| can_change_color() indicates if the terminal has the capability to |
| change the definition of its colors. |
| |
| init_color() is used to redefine a color, if possible. Each of the |
| components -- red, green, and blue -- is specified in a range from 0 |
| to 1000, inclusive. |
| |
| color_content() reports the current definition of a color in the same |
| format as used by init_color(). |
| |
| assume_default_colors() and use_default_colors() emulate the ncurses |
| extensions of the same names. assume_default_colors(f, b) is |
| essentially the same as init_pair(0, f, b) (which isn't allowed); it |
| redefines the default colors. use_default_colors() allows the use of |
| -1 as a foreground or background color with init_pair(), and calls |
| assume_default_colors(-1, -1); -1 represents the foreground or |
| background color that the terminal had at startup. If the environment |
| variable PDC_ORIGINAL_COLORS is set at the time start_color() is |
| called, that's equivalent to calling use_default_colors(). |
| |
| alloc_pair(), find_pair() and free_pair() are also from ncurses. |
| free_pair() marks a pair as unused; find_pair() returns an existing |
| pair with the specified foreground and background colors, if one |
| exists. And alloc_pair() returns such a pair whether or not it was |
| previously set, overwriting the oldest initialized pair if there are |
| no free pairs. |
| |
| PDC_set_line_color() is used to set the color, globally, for the |
| color of the lines drawn for the attributes: A_UNDERLINE, A_LEFT and |
| A_RIGHT. A value of -1 (the default) indicates that the current |
| foreground color should be used. |
| |
| NOTE: COLOR_PAIR() and PAIR_NUMBER() are implemented as macros. |
| |
| ### Return Value |
| |
| Most functions return OK on success and ERR on error. has_colors() |
| and can_change_colors() return TRUE or FALSE. alloc_pair() and |
| find_pair() return a pair number, or -1 on error. |
| |
| ### Portability |
| X/Open ncurses NetBSD |
| has_colors Y Y Y |
| start_color Y Y Y |
| init_pair Y Y Y |
| pair_content Y Y Y |
| can_change_color Y Y Y |
| init_color Y Y Y |
| color_content Y Y Y |
| alloc_pair - Y - |
| assume_default_colors - Y Y |
| find_pair - Y - |
| free_pair - Y - |
| use_default_colors - Y Y |
| PDC_set_line_color - - - |
| |
| **man-end****************************************************************/ |
| |
| #include <stdlib.h> |
| #include <string.h> |
| |
| int COLORS = 0; |
| int COLOR_PAIRS = PDC_COLOR_PAIRS; |
| |
| static bool default_colors = FALSE; |
| static short first_col = 0; |
| static int allocnum = 0; |
| |
| int start_color(void) |
| { |
| PDC_LOG(("start_color() - called\n")); |
| |
| if (!SP || SP->mono) |
| return ERR; |
| |
| SP->color_started = TRUE; |
| |
| PDC_set_blink(FALSE); /* Also sets COLORS */ |
| |
| if (!default_colors && SP->orig_attr && getenv("PDC_ORIGINAL_COLORS")) |
| default_colors = TRUE; |
| |
| PDC_init_atrtab(); |
| |
| return OK; |
| } |
| |
| static void _normalize(short *fg, short *bg) |
| { |
| if (*fg == -1) |
| *fg = SP->orig_attr ? SP->orig_fore : COLOR_WHITE; |
| |
| if (*bg == -1) |
| *bg = SP->orig_attr ? SP->orig_back : COLOR_BLACK; |
| } |
| |
| static void _init_pair_core(short pair, short fg, short bg) |
| { |
| PDC_PAIR *p = SP->atrtab + pair; |
| |
| _normalize(&fg, &bg); |
| |
| /* To allow the PDC_PRESERVE_SCREEN option to work, we only reset |
| curscr if this call to init_pair() alters a color pair created by |
| the user. */ |
| |
| if (p->set) |
| { |
| if (p->f != fg || p->b != bg) |
| curscr->_clear = TRUE; |
| } |
| |
| p->f = fg; |
| p->b = bg; |
| p->count = allocnum++; |
| p->set = TRUE; |
| } |
| |
| int init_pair(short pair, short fg, short bg) |
| { |
| PDC_LOG(("init_pair() - called: pair %d fg %d bg %d\n", pair, fg, bg)); |
| |
| if (!SP || !SP->color_started || pair < 1 || pair >= COLOR_PAIRS || |
| fg < first_col || fg >= COLORS || bg < first_col || bg >= COLORS) |
| return ERR; |
| |
| _init_pair_core(pair, fg, bg); |
| |
| return OK; |
| } |
| |
| bool has_colors(void) |
| { |
| PDC_LOG(("has_colors() - called\n")); |
| |
| return SP ? !(SP->mono) : FALSE; |
| } |
| |
| int init_color(short color, short red, short green, short blue) |
| { |
| PDC_LOG(("init_color() - called\n")); |
| |
| if (!SP || color < 0 || color >= COLORS || !PDC_can_change_color() || |
| red < -1 || red > 1000 || green < -1 || green > 1000 || |
| blue < -1 || blue > 1000) |
| return ERR; |
| |
| SP->dirty = TRUE; |
| |
| return PDC_init_color(color, red, green, blue); |
| } |
| |
| int color_content(short color, short *red, short *green, short *blue) |
| { |
| PDC_LOG(("color_content() - called\n")); |
| |
| if (color < 0 || color >= COLORS || !red || !green || !blue) |
| return ERR; |
| |
| if (PDC_can_change_color()) |
| return PDC_color_content(color, red, green, blue); |
| else |
| { |
| /* Simulated values for platforms that don't support palette |
| changing */ |
| |
| short maxval = (color & 8) ? 1000 : 680; |
| |
| *red = (color & COLOR_RED) ? maxval : 0; |
| *green = (color & COLOR_GREEN) ? maxval : 0; |
| *blue = (color & COLOR_BLUE) ? maxval : 0; |
| |
| return OK; |
| } |
| } |
| |
| bool can_change_color(void) |
| { |
| PDC_LOG(("can_change_color() - called\n")); |
| |
| return PDC_can_change_color(); |
| } |
| |
| int pair_content(short pair, short *fg, short *bg) |
| { |
| PDC_LOG(("pair_content() - called\n")); |
| |
| if (pair < 0 || pair >= COLOR_PAIRS || !fg || !bg) |
| return ERR; |
| |
| *fg = SP->atrtab[pair].f; |
| *bg = SP->atrtab[pair].b; |
| |
| return OK; |
| } |
| |
| int assume_default_colors(int f, int b) |
| { |
| PDC_LOG(("assume_default_colors() - called: f %d b %d\n", f, b)); |
| |
| if (f < -1 || f >= COLORS || b < -1 || b >= COLORS) |
| return ERR; |
| |
| if (SP->color_started) |
| _init_pair_core(0, f, b); |
| |
| return OK; |
| } |
| |
| int use_default_colors(void) |
| { |
| PDC_LOG(("use_default_colors() - called\n")); |
| |
| default_colors = TRUE; |
| first_col = -1; |
| |
| return assume_default_colors(-1, -1); |
| } |
| |
| int PDC_set_line_color(short color) |
| { |
| PDC_LOG(("PDC_set_line_color() - called: %d\n", color)); |
| |
| if (!SP || color < -1 || color >= COLORS) |
| return ERR; |
| |
| SP->line_color = color; |
| |
| return OK; |
| } |
| |
| void PDC_init_atrtab(void) |
| { |
| PDC_PAIR *p = SP->atrtab; |
| short i, fg, bg; |
| |
| if (SP->color_started && !default_colors) |
| { |
| fg = COLOR_WHITE; |
| bg = COLOR_BLACK; |
| } |
| else |
| fg = bg = -1; |
| |
| _normalize(&fg, &bg); |
| |
| for (i = 0; i < PDC_COLOR_PAIRS; i++) |
| { |
| p[i].f = fg; |
| p[i].b = bg; |
| p[i].set = FALSE; |
| } |
| } |
| |
| int free_pair(int pair) |
| { |
| if (pair < 1 || pair >= PDC_COLOR_PAIRS || !(SP->atrtab[pair].set)) |
| return ERR; |
| |
| SP->atrtab[pair].set = FALSE; |
| return OK; |
| } |
| |
| int find_pair(int fg, int bg) |
| { |
| int i; |
| PDC_PAIR *p = SP->atrtab; |
| |
| for (i = 0; i < PDC_COLOR_PAIRS; i++) |
| if (p[i].set && p[i].f == fg && p[i].b == bg) |
| return i; |
| |
| return -1; |
| } |
| |
| static int _find_oldest() |
| { |
| int i, lowind = 0, lowval = 0; |
| PDC_PAIR *p = SP->atrtab; |
| |
| for (i = 1; i < PDC_COLOR_PAIRS; i++) |
| { |
| if (!p[i].set) |
| return i; |
| |
| if (!lowval || (p[i].count < lowval)) |
| { |
| lowind = i; |
| lowval = p[i].count; |
| } |
| } |
| |
| return lowind; |
| } |
| |
| int alloc_pair(int fg, int bg) |
| { |
| int i = find_pair(fg, bg); |
| |
| if (-1 == i) |
| { |
| i = _find_oldest(); |
| |
| if (ERR == init_pair(i, fg, bg)) |
| return -1; |
| } |
| |
| return i; |
| } |