1 /****************************************************************************
2 * Copyright 2018-2022,2023 Thomas E. Dickey *
3 * *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
11 * *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
14 * *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
22 * *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
26 * authorization. *
27 ****************************************************************************/
28 /*
29 * $Id: color_content.c,v 1.19 2023/02/25 16:48:02 tom Exp $
30 */
31
32 #define NEED_TIME_H
33 #include <test.priv.h>
34
35 #if USE_EXTENDED_COLOR
36 typedef int my_color_t;
37 #else
38 typedef NCURSES_COLOR_T my_color_t;
39 #endif
40
41 typedef struct {
42 my_color_t r;
43 my_color_t g;
44 my_color_t b;
45 } MYCOLOR;
46
47 static int f_opt;
48 static int i_opt;
49 static int l_opt;
50 static int n_opt;
51 static int p_opt;
52 static int r_opt;
53 static int s_opt;
54
55 #if USE_EXTENDED_COLOR
56 static int x_opt;
57 #endif
58
59 static MYCOLOR *expected;
60
61 static TimeType initial_time;
62 static TimeType finish_time;
63
64 static void
failed(const char * msg)65 failed(const char *msg)
66 {
67 printw("%s", msg);
68 getch();
69 endwin();
70 ExitProgram(EXIT_FAILURE);
71 }
72
73 #if USE_EXTENDED_COLOR
74 static int
InitColor(int pair,int r,int g,int b)75 InitColor(int pair, int r, int g, int b)
76 {
77 int rc;
78 if (x_opt) {
79 rc = init_extended_color(pair, r, g, b);
80 } else {
81 rc = init_color((NCURSES_PAIRS_T) pair,
82 (NCURSES_COLOR_T) r,
83 (NCURSES_COLOR_T) g,
84 (NCURSES_COLOR_T) b);
85 }
86 return rc;
87 }
88
89 static int
ColorContent(int color,int * rp,int * gp,int * bp)90 ColorContent(int color, int *rp, int *gp, int *bp)
91 {
92 int rc;
93 if (x_opt) {
94 rc = extended_color_content(color, rp, gp, bp);
95 } else {
96 NCURSES_COLOR_T r, g, b;
97 if ((rc = color_content((NCURSES_COLOR_T) color, &r, &g, &b)) == OK) {
98 *rp = r;
99 *gp = g;
100 *bp = b;
101 }
102 }
103 return rc;
104 }
105 #else
106 #define InitColor(color,r,g,b) init_color((NCURSES_COLOR_T)color,(NCURSES_COLOR_T)r,(NCURSES_COLOR_T)g,(NCURSES_COLOR_T)b)
107 #define ColorContent(color,rp,gp,bp) color_content((NCURSES_COLOR_T)color,rp,gp,bp)
108 #endif
109
110 static my_color_t
random_color(void)111 random_color(void)
112 {
113 return (my_color_t) (rand() % 1000);
114 }
115
116 static void
setup_test(void)117 setup_test(void)
118 {
119 setlocale(LC_ALL, "");
120 initscr();
121 cbreak();
122 noecho();
123 scrollok(stdscr, TRUE);
124 if (has_colors()) {
125 start_color();
126 if (!can_change_color() && !p_opt)
127 failed("this terminal cannot initialize colors");
128
129 if (!f_opt)
130 f_opt = 0;
131 if (!l_opt)
132 l_opt = COLORS;
133 if (l_opt <= 0)
134 failed("color limit must be greater than zero");
135
136 if (!n_opt) {
137 int color;
138 size_t need = (size_t) ((l_opt > COLORS) ? l_opt : COLORS) + 1;
139
140 expected = typeCalloc(MYCOLOR, need);
141 if (s_opt) {
142 int r;
143 int g;
144 int b;
145 color = f_opt;
146 for (r = 0; r < 1000; ++r) {
147 for (g = 0; g < 1000; ++g) {
148 for (b = 0; b < 1000; ++b) {
149 if (color < l_opt) {
150 InitColor(color, r, g, b);
151 expected[color].r = (my_color_t) r;
152 expected[color].g = (my_color_t) g;
153 expected[color].b = (my_color_t) b;
154 ++color;
155 } else {
156 break;
157 }
158 }
159 }
160 }
161 } else {
162 for (color = f_opt; color < l_opt; ++color) {
163 expected[color].r = random_color();
164 expected[color].g = random_color();
165 expected[color].b = random_color();
166 InitColor(color,
167 expected[color].r,
168 expected[color].g,
169 expected[color].b);
170 }
171 }
172 }
173 } else {
174 failed("This demo requires a color terminal");
175 }
176 GetClockTime(&initial_time);
177 }
178
179 static void
run_test(void)180 run_test(void)
181 {
182 int color;
183 bool success = TRUE;
184 for (color = f_opt; color < l_opt; ++color) {
185 my_color_t r;
186 my_color_t g;
187 my_color_t b;
188 if (ColorContent(color, &r, &g, &b) == OK) {
189 if (expected != 0) {
190 if (r != expected[color].r)
191 success = FALSE;
192 if (g != expected[color].g)
193 success = FALSE;
194 if (b != expected[color].b)
195 success = FALSE;
196 }
197 }
198 }
199 if (i_opt) {
200 addch(success ? '.' : '?');
201 refresh();
202 }
203 }
204
205 static void
finish_test(void)206 finish_test(void)
207 {
208 getch();
209 endwin();
210 }
211
212 static void
usage(int ok)213 usage(int ok)
214 {
215 static const char *msg[] =
216 {
217 "Usage: color_content [options]"
218 ,""
219 ,USAGE_COMMON
220 ,"Options:"
221 ," -f COLOR first color value to test (default: 0)"
222 ," -i interactive, showing test-progress"
223 ," -l COLOR last color value to test (default: max_colors-1)"
224 ," -n do not initialize color pairs"
225 ," -p print data for color content instead of testing"
226 ," -r COUNT repeat for given count"
227 ," -s initialize pairs sequentially rather than random"
228 #if USE_EXTENDED_COLOR
229 ," -x use extended color pairs/values"
230 #endif
231 };
232 size_t n;
233 for (n = 0; n < SIZEOF(msg); n++)
234 fprintf(stderr, "%s\n", msg[n]);
235 ExitProgram(ok ? EXIT_SUCCESS : EXIT_FAILURE);
236 }
237 /* *INDENT-OFF* */
VERSION_COMMON()238 VERSION_COMMON()
239 /* *INDENT-ON* */
240
241 int
242 main(int argc, char *argv[])
243 {
244 int ch;
245
246 while ((ch = getopt(argc, argv, OPTS_COMMON "f:il:npr:sx")) != -1) {
247 switch (ch) {
248 case 'f':
249 if ((f_opt = atoi(optarg)) <= 0)
250 usage(FALSE);
251 break;
252 case 'i':
253 i_opt = 1;
254 break;
255 case 'l':
256 if ((l_opt = atoi(optarg)) <= 0)
257 usage(FALSE);
258 break;
259 case 'n':
260 n_opt = 1;
261 break;
262 case 'p':
263 p_opt = 1;
264 break;
265 case 'r':
266 if ((r_opt = atoi(optarg)) <= 0)
267 usage(FALSE);
268 break;
269 case 's':
270 s_opt = 1;
271 break;
272 #if USE_EXTENDED_COLOR
273 case 'x':
274 x_opt = 1;
275 break;
276 #endif
277 case OPTS_VERSION:
278 show_version(argv);
279 ExitProgram(EXIT_SUCCESS);
280 default:
281 usage(ch == OPTS_USAGE);
282 /* NOTREACHED */
283 }
284 }
285 if (optind < argc)
286 usage(FALSE);
287 if (r_opt <= 0)
288 r_opt = 1;
289
290 setup_test();
291 if (p_opt) {
292 int i;
293 endwin();
294 for (i = 0; i < COLORS; ++i) {
295 my_color_t r, g, b;
296 if (ColorContent(i, &r, &g, &b) == OK) {
297 printf("%d: %d %d %d\n", i, r, g, b);
298 } else {
299 printf("%d: ? ?\n", i);
300 }
301 }
302 } else {
303 int repeat;
304
305 for (repeat = 0; repeat < r_opt; ++repeat) {
306 run_test();
307 if (i_opt) {
308 addch('.');
309 refresh();
310 }
311 }
312
313 if (i_opt) {
314 addch('\n');
315 }
316 printw("DONE: ");
317 GetClockTime(&finish_time);
318 printw("%.03f seconds", ElapsedSeconds(&finish_time, &initial_time));
319 finish_test();
320 }
321
322 free(expected);
323 ExitProgram(EXIT_SUCCESS);
324 }
325