ncurses 6.2 - patch 20200212
[ncurses.git] / test / color_content.c
1 /****************************************************************************
2  * Copyright 2018-2019,2020 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.12 2020/02/02 23:34:34 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 #if HAVE_GETTIMEOFDAY
62 static struct timeval initial_time;
63 static struct timeval finish_time;
64 #endif
65
66 static void
67 failed(const char *msg)
68 {
69     printw("%s", msg);
70     getch();
71     endwin();
72     ExitProgram(EXIT_FAILURE);
73 }
74
75 #if USE_EXTENDED_COLOR
76 static int
77 InitColor(int pair, int r, int g, int b)
78 {
79     int rc;
80     if (x_opt) {
81         rc = init_extended_color(pair, r, g, b);
82     } else {
83         rc = init_color((NCURSES_PAIRS_T) pair,
84                         (NCURSES_COLOR_T) r,
85                         (NCURSES_COLOR_T) g,
86                         (NCURSES_COLOR_T) b);
87     }
88     return rc;
89 }
90
91 static int
92 ColorContent(int color, int *rp, int *gp, int *bp)
93 {
94     int rc;
95     if (x_opt) {
96         rc = extended_color_content(color, rp, gp, bp);
97     } else {
98         NCURSES_COLOR_T r, g, b;
99         if ((rc = color_content((NCURSES_COLOR_T) color, &r, &g, &b)) == OK) {
100             *rp = r;
101             *gp = g;
102             *bp = b;
103         }
104     }
105     return rc;
106 }
107 #else
108 #define InitColor(color,r,g,b)       init_color((NCURSES_COLOR_T)color,(NCURSES_COLOR_T)r,(NCURSES_COLOR_T)g,(NCURSES_COLOR_T)b)
109 #define ColorContent(color,rp,gp,bp) color_content((NCURSES_COLOR_T)color,rp,gp,bp)
110 #endif
111
112 static my_color_t
113 random_color(void)
114 {
115     return (my_color_t) (rand() % 1000);
116 }
117
118 static void
119 setup_test(void)
120 {
121     initscr();
122     cbreak();
123     noecho();
124     scrollok(stdscr, TRUE);
125     if (has_colors()) {
126         start_color();
127         if (!can_change_color() && !p_opt)
128             failed("this terminal cannot initialize colors");
129
130         if (!f_opt)
131             f_opt = 0;
132         if (!l_opt)
133             l_opt = COLORS;
134         if (l_opt <= 0)
135             failed("color limit must be greater than zero");
136
137         if (!n_opt) {
138             int color;
139             size_t need = (size_t) ((l_opt > COLORS) ? l_opt : COLORS) + 1;
140
141             expected = typeCalloc(MYCOLOR, need);
142             if (s_opt) {
143                 int r;
144                 int g;
145                 int b;
146                 color = f_opt;
147                 for (r = 0; r < 1000; ++r) {
148                     for (g = 0; g < 1000; ++g) {
149                         for (b = 0; b < 1000; ++b) {
150                             if (color < l_opt) {
151                                 InitColor(color, r, g, b);
152                                 expected[color].r = (my_color_t) r;
153                                 expected[color].g = (my_color_t) g;
154                                 expected[color].b = (my_color_t) b;
155                                 ++color;
156                             } else {
157                                 break;
158                             }
159                         }
160                     }
161                 }
162             } else {
163                 for (color = f_opt; color < l_opt; ++color) {
164                     expected[color].r = random_color();
165                     expected[color].g = random_color();
166                     expected[color].b = random_color();
167                     InitColor(color,
168                               expected[color].r,
169                               expected[color].g,
170                               expected[color].b);
171                 }
172             }
173         }
174     } else {
175         failed("This demo requires a color terminal");
176     }
177 #if HAVE_GETTIMEOFDAY
178     gettimeofday(&initial_time, 0);
179 #endif
180 }
181
182 static void
183 run_test(void)
184 {
185     int color;
186     bool success = TRUE;
187     for (color = f_opt; color < l_opt; ++color) {
188         my_color_t r;
189         my_color_t g;
190         my_color_t b;
191         if (ColorContent(color, &r, &g, &b) == OK) {
192             if (expected != 0) {
193                 if (r != expected[color].r)
194                     success = FALSE;
195                 if (g != expected[color].g)
196                     success = FALSE;
197                 if (b != expected[color].b)
198                     success = FALSE;
199             }
200         }
201     }
202     if (i_opt) {
203         addch(success ? '.' : '?');
204         refresh();
205     }
206 }
207
208 static void
209 finish_test(void)
210 {
211     getch();
212     endwin();
213 }
214
215 #if HAVE_GETTIMEOFDAY
216 static double
217 seconds(struct timeval *mark)
218 {
219     double result = (double) mark->tv_sec;
220     result += ((double) mark->tv_usec / 1e6);
221     return result;
222 }
223 #endif
224
225 static void
226 usage(void)
227 {
228     static const char *msg[] =
229     {
230         "Usage: color_content [options]"
231         ,""
232         ,"Options:"
233         ," -f COLOR first color value to test (default: 0)"
234         ," -i       interactive, showing test-progress"
235         ," -l COLOR last color value to test (default: max_colors-1)"
236         ," -n       do not initialize color pairs"
237         ," -p       print data for color content instead of testing"
238         ," -r COUNT repeat for given count"
239         ," -s       initialize pairs sequentially rather than random"
240 #if USE_EXTENDED_COLOR
241         ," -x       use extended color pairs/values"
242 #endif
243     };
244     size_t n;
245     for (n = 0; n < SIZEOF(msg); n++)
246         fprintf(stderr, "%s\n", msg[n]);
247     ExitProgram(EXIT_FAILURE);
248 }
249
250 int
251 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
252 {
253     int i;
254
255     while ((i = getopt(argc, argv, "f:il:npr:sx")) != -1) {
256         switch (i) {
257         case 'f':
258             if ((f_opt = atoi(optarg)) <= 0)
259                 usage();
260             break;
261         case 'i':
262             i_opt = 1;
263             break;
264         case 'l':
265             if ((l_opt = atoi(optarg)) <= 0)
266                 usage();
267             break;
268         case 'n':
269             n_opt = 1;
270             break;
271         case 'p':
272             p_opt = 1;
273             break;
274         case 'r':
275             if ((r_opt = atoi(optarg)) <= 0)
276                 usage();
277             break;
278         case 's':
279             s_opt = 1;
280             break;
281 #if USE_EXTENDED_COLOR
282         case 'x':
283             x_opt = 1;
284             break;
285 #endif
286         default:
287             usage();
288         }
289     }
290     if (optind < argc)
291         usage();
292     if (r_opt <= 0)
293         r_opt = 1;
294
295     setup_test();
296     if (p_opt) {
297         endwin();
298         for (i = 0; i < COLORS; ++i) {
299             my_color_t r, g, b;
300             if (ColorContent(i, &r, &g, &b) == OK) {
301                 printf("%d: %d %d %d\n", i, r, g, b);
302             } else {
303                 printf("%d: ? ?\n", i);
304             }
305         }
306     } else {
307         int repeat;
308
309         for (repeat = 0; repeat < r_opt; ++repeat) {
310             run_test();
311             if (i_opt) {
312                 addch('.');
313                 refresh();
314             }
315         }
316
317         if (i_opt) {
318             addch('\n');
319         }
320         printw("DONE: ");
321 #if HAVE_GETTIMEOFDAY
322         gettimeofday(&finish_time, 0);
323         printw("%.03f seconds",
324                seconds(&finish_time)
325                - seconds(&initial_time));
326 #endif
327         finish_test();
328     }
329
330     ExitProgram(EXIT_SUCCESS);
331 }