]> ncurses.scripts.mit.edu Git - ncurses.git/blob - test/demo_new_pair.c
ncurses 6.0 - patch 20170617
[ncurses.git] / test / demo_new_pair.c
1 /****************************************************************************
2  * Copyright (c) 2017 Free Software Foundation, Inc.                        *
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: demo_new_pair.c,v 1.14 2017/06/17 19:48:45 tom Exp $
30  *
31  * Demonstrate the alloc_pair() function.
32  */
33
34 #include <test.priv.h>
35 #include <time.h>
36 #include <popup_msg.h>
37
38 #if HAVE_ALLOC_PAIR && USE_WIDEC_SUPPORT
39
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <fcntl.h>
43
44 #define MAX_BITS 8              /* all but A_ALTCHARSET */
45 #define MAX_ATTR ((1<<MAX_BITS)-1)
46
47 static bool
48 valid_cap(NCURSES_CONST char *name)
49 {
50     char *value = tigetstr(name);
51     return (value != 0 && value != (char *) -1) ? TRUE : FALSE;
52 }
53
54 static attr_t
55 next_attr(int now)
56 {
57     static bool init = FALSE;
58     static attr_t table[MAX_BITS * MAX_BITS];
59     static int limit = 0;
60
61     if (!init) {
62         int j, k;
63         attr_t bits[MAX_BITS];
64
65         init = TRUE;
66         bits[limit++] = A_NORMAL;
67         if (valid_cap("smso"))
68             bits[limit++] = A_STANDOUT;
69         if (valid_cap("smul"))
70             bits[limit++] = A_UNDERLINE;
71         if (valid_cap("rev"))
72             bits[limit++] = A_REVERSE;
73         if (valid_cap("blink"))
74             bits[limit++] = A_BLINK;
75         if (valid_cap("dim"))
76             bits[limit++] = A_DIM;
77         if (valid_cap("bold"))
78             bits[limit++] = A_BOLD;
79         for (j = 0; j < limit; ++j) {
80             for (k = 0; k < limit; ++k) {
81                 table[j * limit + k] = bits[j] | bits[k];
82             }
83         }
84     }
85     return table[now % limit];
86 }
87
88 static void
89 our_content(int pair, int *fg, int *bg)
90 {
91     pair %= COLOR_PAIRS;
92     *fg = (pair / COLORS) % COLORS;
93     *bg = (pair % COLORS);
94 }
95
96 static int
97 make_color(int now)
98 {
99     int fg, bg;
100     our_content(now, &fg, &bg);
101     return alloc_pair(fg, bg);
102 }
103
104 static int
105 next_color(int now)
106 {
107     int result = 0;
108     if ((short) now > 0) {
109         if (now < COLOR_PAIRS) {
110             int fg, bg;
111             our_content(now, &fg, &bg);
112             if (init_pair((short) now, (short) fg, (short) bg) != OK)
113                 now = ERR;
114         } else {
115             now %= COLOR_PAIRS;
116         }
117         result = now;
118     }
119     return result;
120 }
121
122 static time_t
123 now(void)
124 {
125     return time((time_t *) 0);
126 }
127
128 static void
129 usage(void)
130 {
131     static const char *msg[] =
132     {
133         "Usage: demo_new_pair [options]",
134         "",
135         "Repeatedly print using all possible color combinations.",
136         "",
137         "Options:",
138         " -i       use init_pair rather than alloc_pair",
139         " -p       start in paged-mode",
140         " -s       start in single-step mode",
141         " -w       print a wide-character cell",
142     };
143     unsigned n;
144     for (n = 0; n < SIZEOF(msg); ++n) {
145         fprintf(stderr, "%s\n", msg[n]);
146     }
147     ExitProgram(EXIT_FAILURE);
148 }
149
150 #define use_pages() \
151         paged_mode = TRUE, single_mode = TRUE
152
153 #define use_single() \
154         paged_mode = FALSE, single_mode = TRUE
155
156 #define update_modes() \
157             scrollok(stdscr, !paged_mode); \
158             nodelay(stdscr, !single_mode || paged_mode)
159
160 int
161 main(int argc, char *argv[])
162 {
163     static const char *help[] =
164     {
165         "This program iterates over the possible color combinations,",
166         "allocating or initializing color pairs.  For best results,",
167         "choose screen-width dividing evenly into the number of colors,",
168         "e.g.,",
169         "",
170         "  32x64,32x128  256 colors",
171         "  24x44,24x88   88 colors",
172         "  32x64,24x128  16 colors",
173         "",
174         "Keys:",
175         "  c      toggle between coloring and de-coloring cells",
176         "  p      show one page at a time",
177         "  s      show one character at a time",
178         " <space> display char/page without pausing",
179         "  v/V    cycle through video attributes",
180         "  w      toggle between \"#\" and a double-width equivalent",
181         "  ?      print this screen (exit on any character).",
182         "",
183         "To exit this program, press ^Q, ^[ or \"q\".",
184         0
185     };
186
187     bool done = FALSE;
188     bool clobber = FALSE;
189     bool hascolor = FALSE;
190     bool use_init = FALSE;
191     bool use_wide = FALSE;
192     bool paged_mode = FALSE;
193     bool single_mode = FALSE;
194     int video_mode = 0;
195     int current;
196     int ch;
197     wchar_t wch[2];
198     time_t start = now();
199     long total_cells = 0;
200     FILE *output = 0;
201
202     setlocale(LC_ALL, "");
203
204     while ((ch = getopt(argc, argv, "ipsw")) != -1) {
205         switch (ch) {
206         case 'i':
207             use_init = TRUE;
208             break;
209         case 'p':
210             use_pages();
211             break;
212         case 's':
213             use_single();
214             break;
215         case 'w':
216             use_wide = TRUE;
217             break;
218         default:
219             usage();
220             break;
221         }
222     }
223
224     if (isatty(fileno(stderr))) {
225         output = stderr;
226     } else if ((ch = open("/dev/tty", O_WRONLY)) != 0) {
227         output = fdopen(ch, "w");
228     } else {
229         fprintf(stderr, "cannot open terminal for output\n");
230         ExitProgram(EXIT_FAILURE);
231     }
232     if (newterm(NULL, output, stdin) == 0) {
233         fprintf(stderr, "Cannot initialize terminal\n");
234         ExitProgram(EXIT_FAILURE);
235     }
236     (void) cbreak();            /* read chars without wait for \n */
237     (void) noecho();            /* don't echo input */
238     update_modes();
239     curs_set(0);
240
241     keypad(stdscr, TRUE);
242
243     if ((hascolor = has_colors())) {
244         start_color();
245         current = 1;
246     } else {
247         current = 0;
248     }
249
250     /*
251      * Repeatedly cycle through all colors, initializing pairs as needed.
252      * Provide for single-stepping, or page-at-a-time, as well as quitting.
253      */
254     while (!done) {
255         cchar_t temp;
256         attr_t my_attrs;
257         int my_pair;
258
259         switch (getch()) {
260         case HELP_KEY_1:
261             popup_msg(stdscr, help);
262             break;
263         case 'p':
264             /* step-by-page */
265             use_pages();
266             update_modes();
267             break;
268         case 's':
269             /* step-by-char */
270             use_single();
271             update_modes();
272             break;
273         case ' ':
274             single_mode = FALSE;
275             update_modes();
276             break;
277         case QUIT:
278         case ESCAPE:
279         case 'q':
280             done = TRUE;
281             continue;
282         case 'c':
283             clobber = !clobber;
284             continue;
285         case 'v':
286             if (--video_mode < 0)
287                 video_mode = MAX_ATTR;
288             continue;
289         case 'V':
290             if (video_mode > MAX_ATTR)
291                 video_mode = 0;
292             continue;
293         case 'w':
294             use_wide = !use_wide;
295             continue;
296         case ERR:
297             break;
298         default:
299             beep();
300             break;
301         }
302         if (hascolor) {
303             my_attrs = next_attr(video_mode);
304             if (clobber) {
305                 int fg, bg;
306                 our_content(current, &fg, &bg);
307                 my_pair = find_pair(fg, bg);
308                 if (my_pair > 0) {
309                     free_pair(my_pair);
310                 }
311                 my_pair = 0;
312             } else {
313                 my_pair = (use_init
314                            ? next_color(current)
315                            : make_color(current));
316             }
317         } else {
318             my_attrs = next_attr(current);
319             my_pair = 0;
320         }
321         if (my_pair < 0)
322             break;
323         wch[0] = use_wide ? 0xff03 : '#';
324         wch[1] = 0;
325         setcchar(&temp, wch, my_attrs, (short) my_pair, NULL);
326         /*
327          * At the end of a page, move the cursor to the home position.
328          */
329         if ((add_wch(&temp) == ERR) && paged_mode) {
330             nodelay(stdscr, !single_mode);
331             move(0, 0);
332         }
333         total_cells += 1 + (use_wide ? 1 : 0);
334         ++current;
335     }
336     endwin();
337     fclose(output);
338
339     printf("%.1f cells/second\n",
340            (double) (total_cells) / (double) (now() - start));
341
342     ExitProgram(EXIT_SUCCESS);
343 }
344
345 #else
346 int
347 main(void)
348 {
349     printf("This program requires the ncurses alloc_pair function\n");
350     ExitProgram(EXIT_FAILURE);
351 }
352 #endif