2 /***************************************************************************
4 ****************************************************************************
5 * ncurses is copyright (C) 1992-1995 *
7 * zmbenhal@netcom.com *
9 * esr@snark.thyrsus.com *
11 * Permission is hereby granted to reproduce and distribute ncurses *
12 * by any means and for any fee, whether alone or as part of a *
13 * larger distribution, in source or in binary form, PROVIDED *
14 * this notice is included with any such distribution, and is not *
15 * removed from any of its header files. Mention of ncurses in any *
16 * applications linked with it is highly appreciated. *
18 * ncurses comes AS IS with no warranty, implied or expressed. *
20 ***************************************************************************/
24 * Handles color emulation of SYS V curses
28 #include <curses.priv.h>
32 MODULE_ID("$Id: lib_color.c,v 1.17 1997/05/03 19:16:05 tom Exp $")
35 * These should be screen structure members. They need to be globals for
36 * hystorical reasons. So we assign them in start_color() and also in
37 * set_term()'s screen-switching logic.
42 static const color_t cga_palette[] =
45 {0, 0, 0}, /* COLOR_BLACK */
46 {1000, 0, 0}, /* COLOR_RED */
47 {0, 1000, 0}, /* COLOR_GREEN */
48 {1000, 1000, 0}, /* COLOR_YELLOW */
49 {0, 0, 1000}, /* COLOR_BLUE */
50 {1000, 0, 1000}, /* COLOR_MAGENTA */
51 {0, 1000, 1000}, /* COLOR_CYAN */
52 {1000, 1000, 1000}, /* COLOR_WHITE */
54 static const color_t hls_palette[] =
57 {0, 0, 0}, /* COLOR_BLACK */
58 {120, 50, 100}, /* COLOR_RED */
59 {240, 50, 100}, /* COLOR_GREEN */
60 {180, 50, 100}, /* COLOR_YELLOW */
61 {330, 50, 100}, /* COLOR_BLUE */
62 {60, 50, 100}, /* COLOR_MAGENTA */
63 {300, 50, 100}, /* COLOR_CYAN */
64 {0, 50, 100}, /* COLOR_WHITE */
69 T((T_CALLED("start_color()")));
72 if (orig_pair != NULL)
74 TPUTS_TRACE("orig_pair");
77 #endif /* orig_pair */
79 if (orig_colors != NULL)
81 TPUTS_TRACE("orig_colors");
84 #endif /* orig_colors */
85 #if defined(orig_pair) && defined(orig_colors)
86 if (!orig_pair && !orig_colors)
88 #endif /* defined(orig_pair) && defined(orig_colors) */
90 COLOR_PAIRS = SP->_pair_count = max_pairs;
93 SP->_color_pairs = typeCalloc(unsigned short, max_pairs);
94 SP->_color_pairs[0] = PAIR_OF(COLOR_WHITE, COLOR_BLACK);
96 COLORS = SP->_color_count = max_colors;
101 SP->_color_table = malloc(sizeof(color_t) * COLORS);
102 #ifdef hue_lightness_saturation
103 if (hue_lightness_saturation)
104 memcpy(SP->_color_table, hls_palette, sizeof(color_t) * COLORS);
106 #endif /* hue_lightness_saturation */
107 memcpy(SP->_color_table, cga_palette, sizeof(color_t) * COLORS);
111 TPUTS_TRACE("orig_colors");
115 T(("started color: COLORS = %d, COLOR_PAIRS = %d", COLORS, COLOR_PAIRS));
120 #ifdef hue_lightness_saturation
121 static void rgb2hls(short r, short g, short b, short *h, short *l, short *s)
122 /* convert RGB to HLS system */
126 if ((min = g < r ? g : r) > b) min = b;
127 if ((max = g > r ? g : r) < b) max = b;
129 /* calculate lightness */
130 *l = (min + max) / 20;
132 if (min == max) /* black, white and all shades of gray */
139 /* calculate saturation */
141 *s = ((max - min) * 100) / (max + min);
142 else *s = ((max - min) * 100) / (2000 - max - min);
146 t = 120 + ((g - b) * 60) / (max - min);
149 t = 240 + ((b - r) * 60) / (max - min);
151 t = 360 + ((r - g) * 60) / (max - min);
155 #endif /* hue_lightness_saturation */
158 * Extension (1997/1/18) - Allow negative f/b values to set default color
161 int init_pair(short pair, short f, short b)
163 T((T_CALLED("init_pair(%d,%d,%d)"), pair, f, b));
165 if ((pair < 1) || (pair >= COLOR_PAIRS))
167 if (SP->_default_color)
173 if (f >= COLORS && f != C_MASK)
175 if (b >= COLORS && b != C_MASK)
179 if ((f < 0) || (f >= COLORS)
180 || (b < 0) || (b >= COLORS))
184 * FIXME: when a pair's content is changed, replace its colors
185 * (if pair was initialized before a screen update is performed
186 * replacing original pair colors with the new ones)
189 SP->_color_pairs[pair] = PAIR_OF(f,b);
193 const color_t *tp = hue_lightness_saturation ? hls_palette : cga_palette;
195 T(("initializing pair: pair = %d, fg=(%d,%d,%d), bg=(%d,%d,%d)",
197 tp[f].red, tp[f].green, tp[f].blue,
198 tp[b].red, tp[b].green, tp[b].blue));
202 TPUTS_TRACE("initialize_pair");
203 putp(tparm(initialize_pair,
205 tp[f].red, tp[f].green, tp[f].blue,
206 tp[b].red, tp[b].green, tp[b].blue));
213 int init_color(short color, short r, short g, short b)
215 T((T_CALLED("init_color(%d,%d,%d,%d)"), color, r, g, b));
216 #ifdef initialize_color
217 if (initialize_color == NULL)
219 #endif /* initialize_color */
221 if (color < 0 || color >= COLORS)
223 #ifdef hue_lightness_saturation
224 if (hue_lightness_saturation == TRUE)
225 if (r < 0 || r > 360 || g < 0 || g > 100 || b < 0 || b > 100)
227 if (hue_lightness_saturation == FALSE)
228 #endif /* hue_lightness_saturation */
229 if (r < 0 || r > 1000 || g < 0 || g > 1000 || b < 0 || b > 1000)
232 #ifdef hue_lightness_saturation
233 if (hue_lightness_saturation)
235 &SP->_color_table[color].red,
236 &SP->_color_table[color].green,
237 &SP->_color_table[color].blue);
239 #endif /* hue_lightness_saturation */
241 SP->_color_table[color].red = r;
242 SP->_color_table[color].green = g;
243 SP->_color_table[color].blue = b;
246 #ifdef initialize_color
247 if (initialize_color)
249 TPUTS_TRACE("initialize_color");
250 putp(tparm(initialize_color, color, r, g, b));
252 #endif /* initialize_color */
256 bool can_change_color(void)
258 T((T_CALLED("can_change_color()")));
259 returnCode(can_change != 0);
262 bool has_colors(void)
264 T((T_CALLED("has_colors()")));
265 returnCode((orig_pair != NULL || orig_colors != NULL)
266 && (max_colors != -1) && (max_pairs != -1)
268 (((set_foreground != NULL) && (set_background != NULL))
269 || ((set_a_foreground != NULL) && (set_a_background != NULL))
274 int color_content(short color, short *r, short *g, short *b)
276 T((T_CALLED("color_content(%d,%p,%p,%p)"), color, r, g, b));
277 if (color < 0 || color > COLORS)
280 *r = SP->_color_table[color].red;
281 *g = SP->_color_table[color].green;
282 *b = SP->_color_table[color].blue;
286 int pair_content(short pair, short *f, short *b)
288 T((T_CALLED("pair_content(%d,%p,%p)"), pair, f, b));
290 if ((pair < 0) || (pair > COLOR_PAIRS))
292 *f = ((SP->_color_pairs[pair] >> C_SHIFT) & C_MASK);
293 *b = (SP->_color_pairs[pair] & C_MASK);
299 * SVr4 curses is known to interchange color codes (1,4) and (3,6), possibly
300 * to maintain compatibility with a pre-ANSI scheme. The same scheme is
301 * also used in the FreeBSD syscons.
303 static int toggled_colors(int c)
306 static const int table[] =
307 { 0, 4, 2, 6, 1, 5, 3, 7,
308 8, 12, 10, 14, 9, 13, 11, 15};
314 void _nc_do_color(int pair, int (*outc)(int))
322 TPUTS_TRACE("orig_pair");
323 tputs(orig_pair, 1, outc);
330 TPUTS_TRACE("set_color_pair");
331 tputs(tparm(set_color_pair, pair), 1, outc);
335 pair_content(pair, &fg, &bg);
337 T(("setting colors: pair = %d, fg = %d, bg = %d", pair, fg, bg));
339 if (fg == C_MASK || bg == C_MASK)
343 TPUTS_TRACE("orig_pair");
344 tputs(orig_pair, 1, outc);
348 TPUTS_TRACE("orig_colors");
349 tputs(orig_colors, 1, outc);
354 if (set_a_foreground)
356 TPUTS_TRACE("set_a_foreground");
357 tputs(tparm(set_a_foreground, fg), 1, outc);
361 TPUTS_TRACE("set_foreground");
362 tputs(tparm(set_foreground, toggled_colors(fg)), 1, outc);
367 if (set_a_background)
369 TPUTS_TRACE("set_a_background");
370 tputs(tparm(set_a_background, bg), 1, outc);
374 TPUTS_TRACE("set_background");
375 tputs(tparm(set_background, toggled_colors(bg)), 1, outc);