/* PDCurses */12#include <curspriv.h>34/*man-start**************************************************************56color7-----89### Synopsis1011bool has_colors(void);12int start_color(void);13int init_pair(short pair, short fg, short bg);14int pair_content(short pair, short *fg, short *bg);15bool can_change_color(void);16int init_color(short color, short red, short green, short blue);17int color_content(short color, short *red, short *green, short *blue);1819int alloc_pair(int fg, int bg);20int assume_default_colors(int f, int b);21int find_pair(int fg, int bg);22int free_pair(int pair);23int use_default_colors(void);2425int PDC_set_line_color(short color);2627### Description2829To use these routines, first, call start_color(). Colors are always30used in pairs, referred to as color-pairs. A color-pair is created by31init_pair(), and consists of a foreground color and a background32color. After initialization, COLOR_PAIR(n) can be used like any other33video attribute.3435has_colors() reports whether the terminal supports color.3637start_color() initializes eight basic colors (black, red, green,38yellow, blue, magenta, cyan, and white), and two global variables:39COLORS and COLOR_PAIRS (respectively defining the maximum number of40colors and color-pairs the terminal is capable of displaying).4142init_pair() changes the definition of a color-pair. It takes three43arguments: the number of the color-pair to be redefined, and the new44values of the foreground and background colors. The pair number must45be between 0 and COLOR_PAIRS - 1, inclusive. The foreground and46background must be between 0 and COLORS - 1, inclusive. If the color47pair was previously initialized, the screen is refreshed, and all48occurrences of that color-pair are changed to the new definition.4950pair_content() is used to determine what the colors of a given color-51pair consist of.5253can_change_color() indicates if the terminal has the capability to54change the definition of its colors.5556init_color() is used to redefine a color, if possible. Each of the57components -- red, green, and blue -- is specified in a range from 058to 1000, inclusive.5960color_content() reports the current definition of a color in the same61format as used by init_color().6263assume_default_colors() and use_default_colors() emulate the ncurses64extensions of the same names. assume_default_colors(f, b) is65essentially the same as init_pair(0, f, b) (which isn't allowed); it66redefines the default colors. use_default_colors() allows the use of67-1 as a foreground or background color with init_pair(), and calls68assume_default_colors(-1, -1); -1 represents the foreground or69background color that the terminal had at startup. If the environment70variable PDC_ORIGINAL_COLORS is set at the time start_color() is71called, that's equivalent to calling use_default_colors().7273alloc_pair(), find_pair() and free_pair() are also from ncurses.74free_pair() marks a pair as unused; find_pair() returns an existing75pair with the specified foreground and background colors, if one76exists. And alloc_pair() returns such a pair whether or not it was77previously set, overwriting the oldest initialized pair if there are78no free pairs.7980PDC_set_line_color() is used to set the color, globally, for the81color of the lines drawn for the attributes: A_UNDERLINE, A_LEFT and82A_RIGHT. A value of -1 (the default) indicates that the current83foreground color should be used.8485NOTE: COLOR_PAIR() and PAIR_NUMBER() are implemented as macros.8687### Return Value8889Most functions return OK on success and ERR on error. has_colors()90and can_change_colors() return TRUE or FALSE. alloc_pair() and91find_pair() return a pair number, or -1 on error.9293### Portability94X/Open ncurses NetBSD95has_colors Y Y Y96start_color Y Y Y97init_pair Y Y Y98pair_content Y Y Y99can_change_color Y Y Y100init_color Y Y Y101color_content Y Y Y102alloc_pair - Y -103assume_default_colors - Y Y104find_pair - Y -105free_pair - Y -106use_default_colors - Y Y107PDC_set_line_color - - -108109**man-end****************************************************************/110111#include <stdlib.h>112#include <string.h>113114int COLORS = 0;115int COLOR_PAIRS = PDC_COLOR_PAIRS;116117static bool default_colors = FALSE;118static short first_col = 0;119static int allocnum = 0;120121int start_color(void)122{123PDC_LOG(("start_color() - called\n"));124125if (!SP || SP->mono)126return ERR;127128SP->color_started = TRUE;129130PDC_set_blink(FALSE); /* Also sets COLORS */131132if (!default_colors && SP->orig_attr && getenv("PDC_ORIGINAL_COLORS"))133default_colors = TRUE;134135PDC_init_atrtab();136137return OK;138}139140static void _normalize(short *fg, short *bg)141{142if (*fg == -1)143*fg = SP->orig_attr ? SP->orig_fore : COLOR_WHITE;144145if (*bg == -1)146*bg = SP->orig_attr ? SP->orig_back : COLOR_BLACK;147}148149static void _init_pair_core(short pair, short fg, short bg)150{151PDC_PAIR *p = SP->atrtab + pair;152153_normalize(&fg, &bg);154155/* To allow the PDC_PRESERVE_SCREEN option to work, we only reset156curscr if this call to init_pair() alters a color pair created by157the user. */158159if (p->set)160{161if (p->f != fg || p->b != bg)162curscr->_clear = TRUE;163}164165p->f = fg;166p->b = bg;167p->count = allocnum++;168p->set = TRUE;169}170171int init_pair(short pair, short fg, short bg)172{173PDC_LOG(("init_pair() - called: pair %d fg %d bg %d\n", pair, fg, bg));174175if (!SP || !SP->color_started || pair < 1 || pair >= COLOR_PAIRS ||176fg < first_col || fg >= COLORS || bg < first_col || bg >= COLORS)177return ERR;178179_init_pair_core(pair, fg, bg);180181return OK;182}183184bool has_colors(void)185{186PDC_LOG(("has_colors() - called\n"));187188return SP ? !(SP->mono) : FALSE;189}190191int init_color(short color, short red, short green, short blue)192{193PDC_LOG(("init_color() - called\n"));194195if (!SP || color < 0 || color >= COLORS || !PDC_can_change_color() ||196red < -1 || red > 1000 || green < -1 || green > 1000 ||197blue < -1 || blue > 1000)198return ERR;199200SP->dirty = TRUE;201202return PDC_init_color(color, red, green, blue);203}204205int color_content(short color, short *red, short *green, short *blue)206{207PDC_LOG(("color_content() - called\n"));208209if (color < 0 || color >= COLORS || !red || !green || !blue)210return ERR;211212if (PDC_can_change_color())213return PDC_color_content(color, red, green, blue);214else215{216/* Simulated values for platforms that don't support palette217changing */218219short maxval = (color & 8) ? 1000 : 680;220221*red = (color & COLOR_RED) ? maxval : 0;222*green = (color & COLOR_GREEN) ? maxval : 0;223*blue = (color & COLOR_BLUE) ? maxval : 0;224225return OK;226}227}228229bool can_change_color(void)230{231PDC_LOG(("can_change_color() - called\n"));232233return PDC_can_change_color();234}235236int pair_content(short pair, short *fg, short *bg)237{238PDC_LOG(("pair_content() - called\n"));239240if (pair < 0 || pair >= COLOR_PAIRS || !fg || !bg)241return ERR;242243*fg = SP->atrtab[pair].f;244*bg = SP->atrtab[pair].b;245246return OK;247}248249int assume_default_colors(int f, int b)250{251PDC_LOG(("assume_default_colors() - called: f %d b %d\n", f, b));252253if (f < -1 || f >= COLORS || b < -1 || b >= COLORS)254return ERR;255256if (SP->color_started)257_init_pair_core(0, f, b);258259return OK;260}261262int use_default_colors(void)263{264PDC_LOG(("use_default_colors() - called\n"));265266default_colors = TRUE;267first_col = -1;268269return assume_default_colors(-1, -1);270}271272int PDC_set_line_color(short color)273{274PDC_LOG(("PDC_set_line_color() - called: %d\n", color));275276if (!SP || color < -1 || color >= COLORS)277return ERR;278279SP->line_color = color;280281return OK;282}283284void PDC_init_atrtab(void)285{286PDC_PAIR *p = SP->atrtab;287short i, fg, bg;288289if (SP->color_started && !default_colors)290{291fg = COLOR_WHITE;292bg = COLOR_BLACK;293}294else295fg = bg = -1;296297_normalize(&fg, &bg);298299for (i = 0; i < PDC_COLOR_PAIRS; i++)300{301p[i].f = fg;302p[i].b = bg;303p[i].set = FALSE;304}305}306307int free_pair(int pair)308{309if (pair < 1 || pair >= PDC_COLOR_PAIRS || !(SP->atrtab[pair].set))310return ERR;311312SP->atrtab[pair].set = FALSE;313return OK;314}315316int find_pair(int fg, int bg)317{318int i;319PDC_PAIR *p = SP->atrtab;320321for (i = 0; i < PDC_COLOR_PAIRS; i++)322if (p[i].set && p[i].f == fg && p[i].b == bg)323return i;324325return -1;326}327328static int _find_oldest()329{330int i, lowind = 0, lowval = 0;331PDC_PAIR *p = SP->atrtab;332333for (i = 1; i < PDC_COLOR_PAIRS; i++)334{335if (!p[i].set)336return i;337338if (!lowval || (p[i].count < lowval))339{340lowind = i;341lowval = p[i].count;342}343}344345return lowind;346}347348int alloc_pair(int fg, int bg)349{350int i = find_pair(fg, bg);351352if (-1 == i)353{354i = _find_oldest();355356if (ERR == init_pair(i, fg, bg))357return -1;358}359360return i;361}362363364