• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  * Copyright 2020-2021,2022 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.15 2022/12/11 00:03:10 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 >= 20090906) && NCURSES_EXT_FUNCS && NCURSES_OPAQUE
59 
60 static bool
Quit(int ch)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
test_opaque_cleared(WINDOW * win,int mode)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
test_opaque_idcok(WINDOW * win,int mode)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
test_opaque_idlok(WINDOW * win,int mode)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
test_opaque_immedok(WINDOW * win,int mode)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
test_opaque_keypad(WINDOW * win,int mode)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
test_opaque_leaveok(WINDOW * win,int mode)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
test_opaque_nodelay(WINDOW * win,int mode)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
test_opaque_notimeout(WINDOW * win,int mode)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
test_opaque_scrollok(WINDOW * win,int mode)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
test_opaque_syncok(WINDOW * win,int mode)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
status_y(WINDOW * stswin,int cell)160 status_y(WINDOW *stswin, int cell)
161 {
162     return (cell % getmaxy(stswin));
163 }
164 
165 static int
status_x(WINDOW * stswin,int cell)166 status_x(WINDOW *stswin, int cell)
167 {
168     return (15 * (cell / getmaxy(stswin)));
169 }
170 
171 static void
to_keyword(WINDOW * stswin,int cell)172 to_keyword(WINDOW *stswin, int cell)
173 {
174     wmove(stswin, status_y(stswin, cell), status_x(stswin, cell));
175 }
176 
177 static void
to_result(WINDOW * stswin,int cell,bool before)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
show_keyword(WINDOW * stswin,int cell,int active,const char * name)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
show_opaque(WINDOW * stswin,WINDOW * txtwin,bool before,int active)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
test_opaque(int level,char ** argv,WINDOW * stswin)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
test_set_escdelay(void)421 test_set_escdelay(void)
422 {
423     set_escdelay((100 + ESCDELAY) / 2);
424 }
425 
426 static void
test_set_tabsize(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 static void
usage(int ok)458 usage(int ok)
459 {
460     static const char *msg[] =
461     {
462 	"Usage: test_opaque [options] file1 [file2 [...]]"
463 	,""
464 	,USAGE_COMMON
465     };
466     size_t n;
467 
468     for (n = 0; n < SIZEOF(msg); n++)
469 	fprintf(stderr, "%s\n", msg[n]);
470 
471     ExitProgram(ok ? EXIT_SUCCESS : EXIT_FAILURE);
472 }
473 /* *INDENT-OFF* */
VERSION_COMMON()474 VERSION_COMMON()
475 /* *INDENT-ON* */
476 
477 int
478 main(int argc, char *argv[])
479 {
480     WINDOW *stsbox;
481     WINDOW *stswin;
482     int ch;
483 
484     while ((ch = getopt(argc, argv, OPTS_COMMON)) != -1) {
485 	switch (ch) {
486 	case OPTS_VERSION:
487 	    show_version(argv);
488 	    ExitProgram(EXIT_SUCCESS);
489 	default:
490 	    usage(ch == OPTS_USAGE);
491 	    /* NOTREACHED */
492 	}
493     }
494 
495     setlocale(LC_ALL, "");
496 
497     if (optind + 1 > argc)
498 	usage(FALSE);
499 
500     initscr();
501 
502     test_set_escdelay();
503     test_set_tabsize();
504 
505     stsbox = derwin(stdscr, BASE_Y, COLS, 0, 0);
506     box(stsbox, 0, 0);
507     wnoutrefresh(stsbox);
508 
509     stswin = derwin(stsbox, BASE_Y - 2, COLS - 2, 1, 1);
510     keypad(stswin, TRUE);
511 
512     test_opaque(optind, argv, stswin);
513 
514     endwin();
515     ExitProgram(EXIT_SUCCESS);
516 }
517 #else
518 int
main(void)519 main(void)
520 {
521     printf("This program requires the ncurses library\n");
522     ExitProgram(EXIT_FAILURE);
523 }
524 #endif
525