ncurses 6.2 - patch 20210522
[ncurses.git] / test / test_opaque.c
1 /****************************************************************************
2  * Copyright 2020,2021 Thomas E. Dickey                                     *
3  * Copyright 2007-2008,2009 Free Software Foundation, Inc.                  *
4  *                                                                          *
5  * Permission is hereby granted, free of charge, to any person obtaining a  *
6  * copy of this software and associated documentation files (the            *
7  * "Software"), to deal in the Software without restriction, including      *
8  * without limitation the rights to use, copy, modify, merge, publish,      *
9  * distribute, distribute with modifications, sublicense, and/or sell       *
10  * copies of the Software, and to permit persons to whom the Software is    *
11  * furnished to do so, subject to the following conditions:                 *
12  *                                                                          *
13  * The above copyright notice and this permission notice shall be included  *
14  * in all copies or substantial portions of the Software.                   *
15  *                                                                          *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23  *                                                                          *
24  * Except as contained in this notice, the name(s) of the above copyright   *
25  * holders shall not be used in advertising or otherwise to promote the     *
26  * sale, use or other dealings in this Software without prior written       *
27  * authorization.                                                           *
28  ****************************************************************************/
29 /*
30  * $Id: test_opaque.c,v 1.12 2021/03/06 23:53:34 tom Exp $
31  *
32  * Author: Thomas E Dickey
33  *
34  * Demonstrate the opaque functions from the curses library.
35
36        WINDOW * wgetparent (const WINDOW *);
37        bool is_cleared(const WINDOW *win);
38        bool is_idcok(const WINDOW *win);
39        bool is_idlok(const WINDOW *win);
40        bool is_immedok(const WINDOW *win);
41        bool is_keypad(const WINDOW *win);
42        bool is_leaveok(const WINDOW *win);
43        bool is_nodelay(const WINDOW *win);
44        bool is_notimeout(const WINDOW *win);
45        bool is_scrollok(const WINDOW *win);
46        bool is_syncok(const WINDOW *win);
47        int wgetscrreg (const WINDOW *, int *, int *);
48        bool is_pad(const WINDOW *win);
49        bool is_subwin(const WINDOW *win);
50        int wgetdelay(const WINDOW *win);
51  */
52
53 #include <test.priv.h>
54
55 #define BASE_Y 6
56 #define MAX_COLS 1024
57
58 #if defined(NCURSES_VERSION_PATCH) && (NCURSES_VERSION_PATCH >= 20080119) && NCURSES_EXT_FUNCS
59
60 static bool
61 Quit(int ch)
62 {
63     return (ch == 'q' || ch == QUIT || ch == ESCAPE);
64 }
65
66 typedef bool(*BoolOpaque) (WINDOW *, int);
67
68 static bool
69 test_opaque_cleared(WINDOW *win, int mode)
70 {
71     if (mode >= 0) {
72         if (mode)
73             wclear(win);
74     }
75     return is_cleared(win);
76 }
77
78 static bool
79 test_opaque_idcok(WINDOW *win, int mode)
80 {
81     if (mode >= 0) {
82         idcok(win, mode);
83     }
84     return is_idcok(win);
85 }
86
87 static bool
88 test_opaque_idlok(WINDOW *win, int mode)
89 {
90     if (mode >= 0) {
91         idlok(win, mode);
92     }
93     return is_idlok(win);
94 }
95
96 static bool
97 test_opaque_immedok(WINDOW *win, int mode)
98 {
99     if (mode >= 0) {
100         immedok(win, mode);
101     }
102     return is_immedok(win);
103 }
104
105 static bool
106 test_opaque_keypad(WINDOW *win, int mode)
107 {
108     if (mode >= 0) {
109         keypad(win, mode);
110     }
111     return is_keypad(win);
112 }
113
114 static bool
115 test_opaque_leaveok(WINDOW *win, int mode)
116 {
117     if (mode >= 0) {
118         leaveok(win, mode);
119     }
120     return is_leaveok(win);
121 }
122
123 static bool
124 test_opaque_nodelay(WINDOW *win, int mode)
125 {
126     if (mode >= 0) {
127         nodelay(win, mode);
128     }
129     return is_nodelay(win);
130 }
131
132 static bool
133 test_opaque_notimeout(WINDOW *win, int mode)
134 {
135     if (mode >= 0) {
136         notimeout(win, mode);
137     }
138     return is_notimeout(win);
139 }
140
141 static bool
142 test_opaque_scrollok(WINDOW *win, int mode)
143 {
144     if (mode >= 0) {
145         scrollok(win, mode);
146     }
147     return is_scrollok(win);
148 }
149
150 static bool
151 test_opaque_syncok(WINDOW *win, int mode)
152 {
153     if (mode >= 0) {
154         syncok(win, mode);
155     }
156     return is_syncok(win);
157 }
158
159 static int
160 status_y(WINDOW *stswin, int cell)
161 {
162     return (cell % getmaxy(stswin));
163 }
164
165 static int
166 status_x(WINDOW *stswin, int cell)
167 {
168     return (15 * (cell / getmaxy(stswin)));
169 }
170
171 static void
172 to_keyword(WINDOW *stswin, int cell)
173 {
174     wmove(stswin, status_y(stswin, cell), status_x(stswin, cell));
175 }
176
177 static void
178 to_result(WINDOW *stswin, int cell, bool before)
179 {
180     int y = status_y(stswin, cell);
181     int x = status_x(stswin, cell) + 11;
182     if (!before)
183         ++x;
184     wmove(stswin, y, x);
185 }
186
187 static void
188 show_keyword(WINDOW *stswin, int cell, int active, const char *name)
189 {
190     to_keyword(stswin, cell);
191     if (active == cell)
192         (void) wstandout(stswin);
193     wprintw(stswin, "%s:", name);
194     if (active == cell)
195         (void) wstandend(stswin);
196 }
197 /* *INDENT-OFF* */
198 static struct {
199     const char *name;
200     BoolOpaque func;
201 } bool_funcs[] = {
202     { "cleared",   test_opaque_cleared },
203     { "idcok",     test_opaque_idcok },
204     { "idlok",     test_opaque_idlok },
205     { "immedok",   test_opaque_immedok },
206     { "keypad",    test_opaque_keypad },
207     { "leaveok",   test_opaque_leaveok },
208     { "nodelay",   test_opaque_nodelay },
209     { "notimeout", test_opaque_notimeout },
210     { "scrollok",  test_opaque_scrollok },
211     { "syncok",    test_opaque_syncok }
212 };
213 /* *INDENT-ON* */
214
215 #define bool2c(c) ((c) ? 'T' : 'F')
216
217 /*
218  * Display and/or allow update for the properties accessed in the opaque
219  * window.  Some may change state after refreshing the window, so we
220  * distinguish between them using the 'before' parameter.
221  */
222 static int
223 show_opaque(WINDOW *stswin, WINDOW *txtwin, bool before, int active)
224 {
225     int n;
226     int top, bottom;
227
228     if (before) {
229         werase(stswin);
230     }
231     for (n = 0; n < (int) SIZEOF(bool_funcs); ++n) {
232         show_keyword(stswin, n, active, bool_funcs[n].name);
233
234         to_result(stswin, n, before);
235         wprintw(stswin, "%c", bool2c(bool_funcs[n].func(txtwin, -1)));
236     }
237
238     show_keyword(stswin, n, active, "is_pad");
239     to_result(stswin, n, TRUE);
240     wprintw(stswin, "%c", bool2c(is_pad(txtwin)));
241
242     ++n;
243     show_keyword(stswin, n, active, "is_subwin");
244     to_result(stswin, n, TRUE);
245     wprintw(stswin, "%c", bool2c(is_subwin(txtwin)));
246
247     ++n;
248     show_keyword(stswin, n, active, "wgetparent");
249     to_result(stswin, n, TRUE);
250     wprintw(stswin, "%p", (void *) wgetparent(txtwin));
251
252     ++n;
253     show_keyword(stswin, n, active, "wgetdelay");
254     to_result(stswin, n, TRUE);
255     wprintw(stswin, "%d", wgetdelay(txtwin));
256
257     ++n;
258     show_keyword(stswin, n, active, "wgetscrreg");
259     to_result(stswin, n, TRUE);
260     if (wgetscrreg(txtwin, &top, &bottom) == OK)
261         wprintw(stswin, "%d,%d", top, bottom);
262     else
263         wprintw(stswin, "none");
264
265     wnoutrefresh(stswin);
266     return active;
267 }
268
269 static int
270 test_opaque(int level, char **argv, WINDOW *stswin)
271 {
272     WINDOW *txtbox = 0;
273     WINDOW *txtwin = 0;
274     FILE *fp;
275     int ch;
276     int txt_x = 0, txt_y = 0;
277     int base_y;
278     bool in_status = FALSE;
279     int active = 0;
280
281     if (argv[level] == 0) {
282         beep();
283         return FALSE;
284     }
285
286     if (level > 1) {
287         txtbox = newwin(LINES - BASE_Y, COLS - level, BASE_Y, level);
288         box(txtbox, 0, 0);
289         wnoutrefresh(txtbox);
290
291         txtwin = derwin(txtbox,
292                         getmaxy(txtbox) - 2,
293                         getmaxx(txtbox) - 2,
294                         1, 1);
295         base_y = 0;
296     } else {
297         txtwin = stdscr;
298         base_y = BASE_Y;
299     }
300
301     keypad(txtwin, TRUE);       /* enable keyboard mapping */
302     (void) cbreak();            /* take input chars one at a time, no wait for \n */
303     (void) noecho();            /* don't echo input */
304
305     txt_y = base_y;
306     txt_x = 0;
307     wmove(txtwin, txt_y, txt_x);
308
309     if ((fp = fopen(argv[level], "r")) != 0) {
310         while ((ch = fgetc(fp)) != EOF) {
311             if (waddch(txtwin, UChar(ch)) != OK) {
312                 break;
313             }
314         }
315         fclose(fp);
316     } else {
317         wprintw(txtwin, "Cannot open:\n%s", argv[1]);
318     }
319
320     for (;;) {
321         if (in_status) {
322             to_keyword(stswin, active);
323
324             ch = wgetch(stswin);
325             show_opaque(stswin, txtwin, TRUE, active);
326             if (Quit(ch))
327                 break;
328
329             switch (ch) {
330             case '\t':
331                 in_status = FALSE;
332                 break;
333             case KEY_DOWN:
334             case 'j':
335                 if (active < (int) SIZEOF(bool_funcs) - 1)
336                     active++;
337                 else
338                     beep();
339                 break;
340             case KEY_UP:
341             case 'k':
342                 if (active > 0)
343                     active--;
344                 else
345                     beep();
346                 break;
347             case ' ':
348                 bool_funcs[active].func(txtwin,
349                                         !bool_funcs[active].func(txtwin, -1));
350                 break;
351             default:
352                 beep();
353                 break;
354             }
355             show_opaque(stswin, txtwin, FALSE, in_status ? active : -1);
356         } else {
357             ch = mvwgetch(txtwin, txt_y, txt_x);
358             show_opaque(stswin, txtwin, TRUE, -1);
359             if (Quit(ch))
360                 break;
361
362             switch (ch) {
363             case '\t':
364                 in_status = TRUE;
365                 break;
366             case KEY_DOWN:
367             case 'j':
368                 if (txt_y < getmaxy(txtwin) - 1)
369                     txt_y++;
370                 else
371                     beep();
372                 break;
373             case KEY_UP:
374             case 'k':
375                 if (txt_y > base_y)
376                     txt_y--;
377                 else
378                     beep();
379                 break;
380             case KEY_LEFT:
381             case 'h':
382                 if (txt_x > 0)
383                     txt_x--;
384                 else
385                     beep();
386                 break;
387             case KEY_RIGHT:
388             case 'l':
389                 if (txt_x < getmaxx(txtwin) - 1)
390                     txt_x++;
391                 else
392                     beep();
393                 break;
394             case 'w':
395                 test_opaque(level + 1, argv, stswin);
396                 if (txtbox != 0) {
397                     touchwin(txtbox);
398                     wnoutrefresh(txtbox);
399                 } else {
400                     touchwin(txtwin);
401                     wnoutrefresh(txtwin);
402                 }
403                 break;
404             default:
405                 beep();
406                 napms(100);
407                 break;
408             }
409
410             show_opaque(stswin, txtwin, FALSE, -1);
411         }
412     }
413     if (level > 1) {
414         delwin(txtwin);
415         delwin(txtbox);
416     }
417     return TRUE;
418 }
419
420 static void
421 test_set_escdelay(void)
422 {
423     set_escdelay((100 + ESCDELAY) / 2);
424 }
425
426 static void
427 test_set_tabsize(void)
428 {
429     int y0, x0;
430     int y, x;
431     int save_tabsize = TABSIZE;
432
433     (void) cbreak();            /* take input chars one at a time, no wait for \n */
434     (void) noecho();            /* don't echo input */
435
436     for (y = 0; y < LINES; ++y) {
437         set_tabsize(y + 1);
438         if (move(y, 0) == ERR)
439             break;
440         for (x = 0; x < COLS;) {
441             addch('\t');
442             if (addch('*') == ERR) {
443                 break;
444             }
445             getyx(stdscr, y0, x0);
446             if (y0 != y || x0 == x) {
447                 break;
448             }
449         }
450     }
451     getch();
452     erase();
453
454     set_tabsize(save_tabsize);
455 }
456
457 int
458 main(int argc, char *argv[])
459 {
460     WINDOW *stsbox;
461     WINDOW *stswin;
462
463     setlocale(LC_ALL, "");
464
465     if (argc < 2) {
466         fprintf(stderr, "usage: %s file\n", argv[0]);
467         return EXIT_FAILURE;
468     }
469
470     initscr();
471
472     test_set_escdelay();
473     test_set_tabsize();
474
475     stsbox = derwin(stdscr, BASE_Y, COLS, 0, 0);
476     box(stsbox, 0, 0);
477     wnoutrefresh(stsbox);
478
479     stswin = derwin(stsbox, BASE_Y - 2, COLS - 2, 1, 1);
480     keypad(stswin, TRUE);
481
482     test_opaque(1, argv, stswin);
483
484     endwin();
485     ExitProgram(EXIT_SUCCESS);
486 }
487 #else
488 int
489 main(void)
490 {
491     printf("This program requires the ncurses library\n");
492     ExitProgram(EXIT_FAILURE);
493 }
494 #endif