• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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