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