1 /* Public Domain Curses */
2
3 #include <curspriv.h>
4
5 /*man-start**************************************************************
6
7 color
8 -----
9
10 ### Synopsis
11
12 int start_color(void);
13 int init_pair(short pair, short fg, short bg);
14 int init_color(short color, short red, short green, short blue);
15 bool has_colors(void);
16 bool can_change_color(void);
17 int color_content(short color, short *red, short *green, short *blue);
18 int pair_content(short pair, short *fg, short *bg);
19
20 int assume_default_colors(int f, int b);
21 int use_default_colors(void);
22
23 int PDC_set_line_color(short color);
24
25 ### Description
26
27 To use these routines, start_color() must be called, usually
28 immediately after initscr(). Colors are always used in pairs,
29 referred to as color-pairs. A color-pair consists of a
30 foreground color and a background color. A color-pair is
31 initialized via init_pair(). After initialization, COLOR_PAIR(n)
32 can be used like any other video attribute.
33
34 start_color() initializes eight basic colors (black, red, green,
35 yellow, blue, magenta, cyan, and white), and two global
36 variables; COLORS and COLOR_PAIRS (respectively defining the
37 maximum number of colors and color-pairs the terminal is capable
38 of displaying).
39
40 init_pair() changes the definition of a color-pair. It takes
41 three arguments: the number of the color-pair to be redefined,
42 and the new values of the foreground and background colors. The
43 pair number must be between 0 and COLOR_PAIRS - 1, inclusive.
44 The foreground and background must be between 0 and COLORS - 1,
45 inclusive. If the color pair was previously initialized, the
46 screen is refreshed, and all occurrences of that color-pair are
47 changed to the new definition.
48
49 has_colors() indicates if the terminal supports, and can
50 maniplulate color. It returns TRUE or FALSE.
51
52 can_change_color() indicates if the terminal has the capability
53 to change the definition of its colors.
54
55 pair_content() is used to determine what the colors of a given
56 color-pair consist of.
57
58 assume_default_colors() and use_default_colors() emulate the
59 ncurses extensions of the same names. assume_default_colors(f,
60 b) is essentially the same as init_pair(0, f, b) (which isn't
61 allowed); it redefines the default colors. use_default_colors()
62 allows the use of -1 as a foreground or background color with
63 init_pair(), and calls assume_default_colors(-1, -1); -1
64 represents the foreground or background color that the terminal
65 had at startup. If the environment variable PDC_ORIGINAL_COLORS
66 is set at the time start_color() is called, that's equivalent to
67 calling use_default_colors().
68
69 PDC_set_line_color() is used to set the color, globally, for
70 the color of the lines drawn for the attributes: A_UNDERLINE,
71 A_OVERLINE, A_LEFTLINE and A_RIGHTLINE. A value of -1 (the
72 default) indicates that the current foreground color should be
73 used.
74
75 NOTE: COLOR_PAIR() and PAIR_NUMBER() are implemented as macros.
76
77 ### Return Value
78
79 All functions return OK on success and ERR on error, except for
80 has_colors() and can_change_colors(), which return TRUE or FALSE.
81
82 ### Portability
83 X/Open BSD SYS V
84 start_color Y - 3.2
85 init_pair Y - 3.2
86 init_color Y - 3.2
87 has_colors Y - 3.2
88 can_change_color Y - 3.2
89 color_content Y - 3.2
90 pair_content Y - 3.2
91 assume_default_colors - - -
92 use_default_colors - - -
93 PDC_set_line_color - - -
94
95 **man-end****************************************************************/
96
97 #include <stdlib.h>
98 #include <string.h>
99
100 int COLORS = 0;
101 int COLOR_PAIRS = PDC_COLOR_PAIRS;
102
103 bool pdc_color_started = FALSE;
104
105 /* pair_set[] tracks whether a pair has been set via init_pair() */
106
107 static bool pair_set[PDC_COLOR_PAIRS];
108 static bool default_colors = FALSE;
109 static short first_col = 0;
110
start_color(void)111 int start_color(void)
112 {
113 PDC_LOG(("start_color() - called\n"));
114
115 if (SP->mono)
116 return ERR;
117
118 pdc_color_started = TRUE;
119
120 PDC_set_blink(FALSE); /* Also sets COLORS */
121
122 if (!default_colors && SP->orig_attr && getenv("PDC_ORIGINAL_COLORS"))
123 default_colors = TRUE;
124
125 PDC_init_atrtab();
126
127 memset(pair_set, 0, PDC_COLOR_PAIRS);
128
129 return OK;
130 }
131
_normalize(short * fg,short * bg)132 static void _normalize(short *fg, short *bg)
133 {
134 if (*fg == -1)
135 *fg = SP->orig_attr ? SP->orig_fore : COLOR_WHITE;
136
137 if (*bg == -1)
138 *bg = SP->orig_attr ? SP->orig_back : COLOR_BLACK;
139 }
140
init_pair(short pair,short fg,short bg)141 int init_pair(short pair, short fg, short bg)
142 {
143 PDC_LOG(("init_pair() - called: pair %d fg %d bg %d\n", pair, fg, bg));
144
145 if (!pdc_color_started || pair < 1 || pair >= COLOR_PAIRS ||
146 fg < first_col || fg >= COLORS || bg < first_col || bg >= COLORS)
147 return ERR;
148
149 _normalize(&fg, &bg);
150
151 /* To allow the PDC_PRESERVE_SCREEN option to work, we only reset
152 curscr if this call to init_pair() alters a color pair created by
153 the user. */
154
155 if (pair_set[pair])
156 {
157 short oldfg, oldbg;
158
159 PDC_pair_content(pair, &oldfg, &oldbg);
160
161 if (oldfg != fg || oldbg != bg)
162 curscr->_clear = TRUE;
163 }
164
165 PDC_init_pair(pair, fg, bg);
166
167 pair_set[pair] = TRUE;
168
169 return OK;
170 }
171
has_colors(void)172 bool has_colors(void)
173 {
174 PDC_LOG(("has_colors() - called\n"));
175
176 return !(SP->mono);
177 }
178
init_color(short color,short red,short green,short blue)179 int init_color(short color, short red, short green, short blue)
180 {
181 PDC_LOG(("init_color() - called\n"));
182
183 if (color < 0 || color >= COLORS || !PDC_can_change_color() ||
184 red < 0 || red > 1000 || green < 0 || green > 1000 ||
185 blue < 0 || blue > 1000)
186 return ERR;
187
188 return PDC_init_color(color, red, green, blue);
189 }
190
color_content(short color,short * red,short * green,short * blue)191 int color_content(short color, short *red, short *green, short *blue)
192 {
193 PDC_LOG(("color_content() - called\n"));
194
195 if (color < 0 || color >= COLORS || !red || !green || !blue)
196 return ERR;
197
198 if (PDC_can_change_color())
199 return PDC_color_content(color, red, green, blue);
200 else
201 {
202 /* Simulated values for platforms that don't support palette
203 changing */
204
205 short maxval = (color & 8) ? 1000 : 680;
206
207 *red = (color & COLOR_RED) ? maxval : 0;
208 *green = (color & COLOR_GREEN) ? maxval : 0;
209 *blue = (color & COLOR_BLUE) ? maxval : 0;
210
211 return OK;
212 }
213 }
214
can_change_color(void)215 bool can_change_color(void)
216 {
217 PDC_LOG(("can_change_color() - called\n"));
218
219 return PDC_can_change_color();
220 }
221
pair_content(short pair,short * fg,short * bg)222 int pair_content(short pair, short *fg, short *bg)
223 {
224 PDC_LOG(("pair_content() - called\n"));
225
226 if (pair < 0 || pair >= COLOR_PAIRS || !fg || !bg)
227 return ERR;
228
229 return PDC_pair_content(pair, fg, bg);
230 }
231
assume_default_colors(int f,int b)232 int assume_default_colors(int f, int b)
233 {
234 PDC_LOG(("assume_default_colors() - called: f %d b %d\n", f, b));
235
236 if (f < -1 || f >= COLORS || b < -1 || b >= COLORS)
237 return ERR;
238
239 if (pdc_color_started)
240 {
241 short fg, bg, oldfg, oldbg;
242
243 fg = f;
244 bg = b;
245
246 _normalize(&fg, &bg);
247
248 PDC_pair_content(0, &oldfg, &oldbg);
249
250 if (oldfg != fg || oldbg != bg)
251 curscr->_clear = TRUE;
252
253 PDC_init_pair(0, fg, bg);
254 }
255
256 return OK;
257 }
258
use_default_colors(void)259 int use_default_colors(void)
260 {
261 PDC_LOG(("use_default_colors() - called\n"));
262
263 default_colors = TRUE;
264 first_col = -1;
265
266 return assume_default_colors(-1, -1);
267 }
268
PDC_set_line_color(short color)269 int PDC_set_line_color(short color)
270 {
271 PDC_LOG(("PDC_set_line_color() - called: %d\n", color));
272
273 if (color < -1 || color >= COLORS)
274 return ERR;
275
276 SP->line_color = color;
277
278 return OK;
279 }
280
PDC_init_atrtab(void)281 void PDC_init_atrtab(void)
282 {
283 short i, fg, bg;
284
285 if (pdc_color_started && !default_colors)
286 {
287 fg = COLOR_WHITE;
288 bg = COLOR_BLACK;
289 }
290 else
291 fg = bg = -1;
292
293 _normalize(&fg, &bg);
294
295 for (i = 0; i < PDC_COLOR_PAIRS; i++)
296 PDC_init_pair(i, fg, bg);
297 }
298