ncurses 6.2 - patch 20210306
[ncurses.git] / test / test_opaque.c
1 /****************************************************************************
2  * Copyright 2020 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.10 2020/02/02 23:34: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  */
49
50 #include <test.priv.h>
51
52 #define BASE_Y 6
53 #define MAX_COLS 1024
54
55 #if defined(NCURSES_VERSION_PATCH) && (NCURSES_VERSION_PATCH >= 20080119) && NCURSES_EXT_FUNCS
56
57 static bool
58 Quit(int ch)
59 {
60     return (ch == 'q' || ch == QUIT || ch == ESCAPE);
61 }
62
63 typedef bool(*BoolOpaque) (WINDOW *, int);
64
65 static bool
66 test_opaque_cleared(WINDOW *win, int mode)
67 {
68     if (mode >= 0) {
69         if (mode)
70             wclear(win);
71     }
72     return is_cleared(win);
73 }
74
75 static bool
76 test_opaque_idcok(WINDOW *win, int mode)
77 {
78     if (mode >= 0) {
79         idcok(win, mode);
80     }
81     return is_idcok(win);
82 }
83
84 static bool
85 test_opaque_idlok(WINDOW *win, int mode)
86 {
87     if (mode >= 0) {
88         idlok(win, mode);
89     }
90     return is_idlok(win);
91 }
92
93 static bool
94 test_opaque_immedok(WINDOW *win, int mode)
95 {
96     if (mode >= 0) {
97         immedok(win, mode);
98     }
99     return is_immedok(win);
100 }
101
102 static bool
103 test_opaque_keypad(WINDOW *win, int mode)
104 {
105     if (mode >= 0) {
106         keypad(win, mode);
107     }
108     return is_keypad(win);
109 }
110
111 static bool
112 test_opaque_leaveok(WINDOW *win, int mode)
113 {
114     if (mode >= 0) {
115         leaveok(win, mode);
116     }
117     return is_leaveok(win);
118 }
119
120 static bool
121 test_opaque_nodelay(WINDOW *win, int mode)
122 {
123     if (mode >= 0) {
124         nodelay(win, mode);
125     }
126     return is_nodelay(win);
127 }
128
129 static bool
130 test_opaque_notimeout(WINDOW *win, int mode)
131 {
132     if (mode >= 0) {
133         notimeout(win, mode);
134     }
135     return is_notimeout(win);
136 }
137
138 static bool
139 test_opaque_scrollok(WINDOW *win, int mode)
140 {
141     if (mode >= 0) {
142         scrollok(win, mode);
143     }
144     return is_scrollok(win);
145 }
146
147 static bool
148 test_opaque_syncok(WINDOW *win, int mode)
149 {
150     if (mode >= 0) {
151         syncok(win, mode);
152     }
153     return is_syncok(win);
154 }
155
156 static int
157 status_y(WINDOW *stswin, int cell)
158 {
159     return (cell % getmaxy(stswin));
160 }
161
162 static int
163 status_x(WINDOW *stswin, int cell)
164 {
165     return (15 * (cell / getmaxy(stswin)));
166 }
167
168 static void
169 to_keyword(WINDOW *stswin, int cell)
170 {
171     wmove(stswin, status_y(stswin, cell), status_x(stswin, cell));
172 }
173
174 static void
175 to_result(WINDOW *stswin, int cell, bool before)
176 {
177     int y = status_y(stswin, cell);
178     int x = status_x(stswin, cell) + 11;
179     if (!before)
180         ++x;
181     wmove(stswin, y, x);
182 }
183
184 static void
185 show_keyword(WINDOW *stswin, int cell, int active, const char *name)
186 {
187     to_keyword(stswin, cell);
188     if (active == cell)
189         (void) wstandout(stswin);
190     wprintw(stswin, "%s:", name);
191     if (active == cell)
192         (void) wstandend(stswin);
193 }
194 /* *INDENT-OFF* */
195 static struct {
196     const char *name;
197     BoolOpaque func;
198 } bool_funcs[] = {
199     { "cleared",   test_opaque_cleared },
200     { "idcok",     test_opaque_idcok },
201     { "idlok",     test_opaque_idlok },
202     { "immedok",   test_opaque_immedok },
203     { "keypad",    test_opaque_keypad },
204     { "leaveok",   test_opaque_leaveok },
205     { "nodelay",   test_opaque_nodelay },
206     { "notimeout", test_opaque_notimeout },
207     { "scrollok",  test_opaque_scrollok },
208     { "syncok",    test_opaque_syncok }
209 };
210 /* *INDENT-ON* */
211
212 /*
213  * Display and/or allow update for the properties accessed in the opaque
214  * window.  Some may change state after refreshing the window, so we
215  * distinguish between them using the 'before' parameter.
216  */
217 static int
218 show_opaque(WINDOW *stswin, WINDOW *txtwin, bool before, int active)
219 {
220     int n;
221     int top, bottom;
222
223     if (before) {
224         werase(stswin);
225     }
226     for (n = 0; n < (int) SIZEOF(bool_funcs); ++n) {
227         show_keyword(stswin, n, active, bool_funcs[n].name);
228
229         to_result(stswin, n, before);
230         wprintw(stswin, "%c", bool_funcs[n].func(txtwin, -1) ? 'T' : 'F');
231     }
232
233     show_keyword(stswin, n, active, "wgetparent");
234     to_result(stswin, n, TRUE);
235     wprintw(stswin, "%p", (void *) wgetparent(txtwin));
236
237     ++n;
238     show_keyword(stswin, n, active, "wgetscrreg");
239     to_result(stswin, n, TRUE);
240     if (wgetscrreg(txtwin, &top, &bottom) == OK)
241         wprintw(stswin, "%d,%d", top, bottom);
242
243     wnoutrefresh(stswin);
244     return active;
245 }
246
247 static int
248 test_opaque(int level, char **argv, WINDOW *stswin)
249 {
250     WINDOW *txtbox = 0;
251     WINDOW *txtwin = 0;
252     FILE *fp;
253     int ch;
254     int txt_x = 0, txt_y = 0;
255     int base_y;
256     bool in_status = FALSE;
257     int active = 0;
258
259     if (argv[level] == 0) {
260         beep();
261         return FALSE;
262     }
263
264     if (level > 1) {
265         txtbox = newwin(LINES - BASE_Y, COLS - level, BASE_Y, level);
266         box(txtbox, 0, 0);
267         wnoutrefresh(txtbox);
268
269         txtwin = derwin(txtbox,
270                         getmaxy(txtbox) - 2,
271                         getmaxx(txtbox) - 2,
272                         1, 1);
273         base_y = 0;
274     } else {
275         txtwin = stdscr;
276         base_y = BASE_Y;
277     }
278
279     keypad(txtwin, TRUE);       /* enable keyboard mapping */
280     (void) cbreak();            /* take input chars one at a time, no wait for \n */
281     (void) noecho();            /* don't echo input */
282
283     txt_y = base_y;
284     txt_x = 0;
285     wmove(txtwin, txt_y, txt_x);
286
287     if ((fp = fopen(argv[level], "r")) != 0) {
288         while ((ch = fgetc(fp)) != EOF) {
289             if (waddch(txtwin, UChar(ch)) != OK) {
290                 break;
291             }
292         }
293         fclose(fp);
294     } else {
295         wprintw(txtwin, "Cannot open:\n%s", argv[1]);
296     }
297
298     for (;;) {
299         if (in_status) {
300             to_keyword(stswin, active);
301
302             ch = wgetch(stswin);
303             show_opaque(stswin, txtwin, TRUE, active);
304             if (Quit(ch))
305                 break;
306
307             switch (ch) {
308             case '\t':
309                 in_status = FALSE;
310                 break;
311             case KEY_DOWN:
312             case 'j':
313                 if (active < (int) SIZEOF(bool_funcs) - 1)
314                     active++;
315                 else
316                     beep();
317                 break;
318             case KEY_UP:
319             case 'k':
320                 if (active > 0)
321                     active--;
322                 else
323                     beep();
324                 break;
325             case ' ':
326                 bool_funcs[active].func(txtwin,
327                                         !bool_funcs[active].func(txtwin, -1));
328                 break;
329             default:
330                 beep();
331                 break;
332             }
333             show_opaque(stswin, txtwin, FALSE, in_status ? active : -1);
334         } else {
335             ch = mvwgetch(txtwin, txt_y, txt_x);
336             show_opaque(stswin, txtwin, TRUE, -1);
337             if (Quit(ch))
338                 break;
339
340             switch (ch) {
341             case '\t':
342                 in_status = TRUE;
343                 break;
344             case KEY_DOWN:
345             case 'j':
346                 if (txt_y < getmaxy(txtwin) - 1)
347                     txt_y++;
348                 else
349                     beep();
350                 break;
351             case KEY_UP:
352             case 'k':
353                 if (txt_y > base_y)
354                     txt_y--;
355                 else
356                     beep();
357                 break;
358             case KEY_LEFT:
359             case 'h':
360                 if (txt_x > 0)
361                     txt_x--;
362                 else
363                     beep();
364                 break;
365             case KEY_RIGHT:
366             case 'l':
367                 if (txt_x < getmaxx(txtwin) - 1)
368                     txt_x++;
369                 else
370                     beep();
371                 break;
372             case 'w':
373                 test_opaque(level + 1, argv, stswin);
374                 if (txtbox != 0) {
375                     touchwin(txtbox);
376                     wnoutrefresh(txtbox);
377                 } else {
378                     touchwin(txtwin);
379                     wnoutrefresh(txtwin);
380                 }
381                 break;
382             default:
383                 beep();
384                 napms(100);
385                 break;
386             }
387
388             show_opaque(stswin, txtwin, FALSE, -1);
389         }
390     }
391     if (level > 1) {
392         delwin(txtwin);
393         delwin(txtbox);
394     }
395     return TRUE;
396 }
397
398 static void
399 test_set_escdelay(void)
400 {
401     set_escdelay((100 + ESCDELAY) / 2);
402 }
403
404 static void
405 test_set_tabsize(void)
406 {
407     int y0, x0;
408     int y, x;
409     int save_tabsize = TABSIZE;
410
411     (void) cbreak();            /* take input chars one at a time, no wait for \n */
412     (void) noecho();            /* don't echo input */
413
414     for (y = 0; y < LINES; ++y) {
415         set_tabsize(y + 1);
416         if (move(y, 0) == ERR)
417             break;
418         for (x = 0; x < COLS;) {
419             addch('\t');
420             if (addch('*') == ERR) {
421                 break;
422             }
423             getyx(stdscr, y0, x0);
424             if (y0 != y || x0 == x) {
425                 break;
426             }
427         }
428     }
429     getch();
430     erase();
431
432     set_tabsize(save_tabsize);
433 }
434
435 int
436 main(int argc, char *argv[])
437 {
438     WINDOW *stsbox;
439     WINDOW *stswin;
440
441     setlocale(LC_ALL, "");
442
443     if (argc < 2) {
444         fprintf(stderr, "usage: %s file\n", argv[0]);
445         return EXIT_FAILURE;
446     }
447
448     initscr();
449
450     test_set_escdelay();
451     test_set_tabsize();
452
453     stsbox = derwin(stdscr, BASE_Y, COLS, 0, 0);
454     box(stsbox, 0, 0);
455     wnoutrefresh(stsbox);
456
457     stswin = derwin(stsbox, BASE_Y - 2, COLS - 2, 1, 1);
458     keypad(stswin, TRUE);
459
460     test_opaque(1, argv, stswin);
461
462     endwin();
463     ExitProgram(EXIT_SUCCESS);
464 }
465 #else
466 int
467 main(void)
468 {
469     printf("This program requires the ncurses library\n");
470     ExitProgram(EXIT_FAILURE);
471 }
472 #endif