blob: 09b98c009019f0110366bbffb3b5bf2cdb83b2b4 [file] [log] [blame]
Steve Kondikae271bc2015-11-15 02:50:53 +01001/****************************************************************************
micky3879b9f5e72025-07-08 18:04:53 -04002 * Copyright 2020-2021,2022 Thomas E. Dickey *
3 * Copyright 2007-2008,2009 Free Software Foundation, Inc. *
Steve Kondikae271bc2015-11-15 02:50:53 +01004 * *
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/*
micky3879b9f5e72025-07-08 18:04:53 -040030 * $Id: test_opaque.c,v 1.15 2022/12/11 00:03:10 tom Exp $
Steve Kondikae271bc2015-11-15 02:50:53 +010031 *
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 *);
micky3879b9f5e72025-07-08 18:04:53 -040048 bool is_pad(const WINDOW *win);
49 bool is_subwin(const WINDOW *win);
50 int wgetdelay(const WINDOW *win);
Steve Kondikae271bc2015-11-15 02:50:53 +010051 */
52
53#include <test.priv.h>
54
55#define BASE_Y 6
56#define MAX_COLS 1024
57
micky3879b9f5e72025-07-08 18:04:53 -040058#if defined(NCURSES_VERSION_PATCH) && (NCURSES_VERSION_PATCH >= 20090906) && NCURSES_EXT_FUNCS && NCURSES_OPAQUE
Steve Kondikae271bc2015-11-15 02:50:53 +010059
60static bool
61Quit(int ch)
62{
63 return (ch == 'q' || ch == QUIT || ch == ESCAPE);
64}
65
66typedef bool(*BoolOpaque) (WINDOW *, int);
67
68static bool
69test_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
78static bool
79test_opaque_idcok(WINDOW *win, int mode)
80{
81 if (mode >= 0) {
82 idcok(win, mode);
83 }
84 return is_idcok(win);
85}
86
87static bool
88test_opaque_idlok(WINDOW *win, int mode)
89{
90 if (mode >= 0) {
91 idlok(win, mode);
92 }
93 return is_idlok(win);
94}
95
96static bool
97test_opaque_immedok(WINDOW *win, int mode)
98{
99 if (mode >= 0) {
100 immedok(win, mode);
101 }
102 return is_immedok(win);
103}
104
105static bool
106test_opaque_keypad(WINDOW *win, int mode)
107{
108 if (mode >= 0) {
109 keypad(win, mode);
110 }
111 return is_keypad(win);
112}
113
114static bool
115test_opaque_leaveok(WINDOW *win, int mode)
116{
117 if (mode >= 0) {
118 leaveok(win, mode);
119 }
120 return is_leaveok(win);
121}
122
123static bool
124test_opaque_nodelay(WINDOW *win, int mode)
125{
126 if (mode >= 0) {
127 nodelay(win, mode);
128 }
129 return is_nodelay(win);
130}
131
132static bool
133test_opaque_notimeout(WINDOW *win, int mode)
134{
135 if (mode >= 0) {
136 notimeout(win, mode);
137 }
138 return is_notimeout(win);
139}
140
141static bool
142test_opaque_scrollok(WINDOW *win, int mode)
143{
144 if (mode >= 0) {
145 scrollok(win, mode);
146 }
147 return is_scrollok(win);
148}
149
150static bool
151test_opaque_syncok(WINDOW *win, int mode)
152{
153 if (mode >= 0) {
154 syncok(win, mode);
155 }
156 return is_syncok(win);
157}
158
159static int
160status_y(WINDOW *stswin, int cell)
161{
162 return (cell % getmaxy(stswin));
163}
164
165static int
166status_x(WINDOW *stswin, int cell)
167{
168 return (15 * (cell / getmaxy(stswin)));
169}
170
171static void
172to_keyword(WINDOW *stswin, int cell)
173{
174 wmove(stswin, status_y(stswin, cell), status_x(stswin, cell));
175}
176
177static void
178to_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
187static void
188show_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* */
198static 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
micky3879b9f5e72025-07-08 18:04:53 -0400215#define bool2c(c) ((c) ? 'T' : 'F')
216
Steve Kondikae271bc2015-11-15 02:50:53 +0100217/*
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 */
222static int
223show_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);
micky3879b9f5e72025-07-08 18:04:53 -0400235 wprintw(stswin, "%c", bool2c(bool_funcs[n].func(txtwin, -1)));
Steve Kondikae271bc2015-11-15 02:50:53 +0100236 }
237
micky3879b9f5e72025-07-08 18:04:53 -0400238 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;
Steve Kondikae271bc2015-11-15 02:50:53 +0100248 show_keyword(stswin, n, active, "wgetparent");
249 to_result(stswin, n, TRUE);
250 wprintw(stswin, "%p", (void *) wgetparent(txtwin));
251
252 ++n;
micky3879b9f5e72025-07-08 18:04:53 -0400253 show_keyword(stswin, n, active, "wgetdelay");
254 to_result(stswin, n, TRUE);
255 wprintw(stswin, "%d", wgetdelay(txtwin));
256
257 ++n;
Steve Kondikae271bc2015-11-15 02:50:53 +0100258 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);
micky3879b9f5e72025-07-08 18:04:53 -0400262 else
263 wprintw(stswin, "none");
Steve Kondikae271bc2015-11-15 02:50:53 +0100264
265 wnoutrefresh(stswin);
266 return active;
267}
268
269static int
270test_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
420static void
421test_set_escdelay(void)
422{
423 set_escdelay((100 + ESCDELAY) / 2);
424}
425
426static void
427test_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
micky3879b9f5e72025-07-08 18:04:53 -0400457static void
458usage(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* */
474VERSION_COMMON()
475/* *INDENT-ON* */
476
Steve Kondikae271bc2015-11-15 02:50:53 +0100477int
478main(int argc, char *argv[])
479{
480 WINDOW *stsbox;
481 WINDOW *stswin;
micky3879b9f5e72025-07-08 18:04:53 -0400482 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 }
Steve Kondikae271bc2015-11-15 02:50:53 +0100494
495 setlocale(LC_ALL, "");
496
micky3879b9f5e72025-07-08 18:04:53 -0400497 if (optind + 1 > argc)
498 usage(FALSE);
Steve Kondikae271bc2015-11-15 02:50:53 +0100499
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
micky3879b9f5e72025-07-08 18:04:53 -0400512 test_opaque(optind, argv, stswin);
Steve Kondikae271bc2015-11-15 02:50:53 +0100513
514 endwin();
515 ExitProgram(EXIT_SUCCESS);
516}
517#else
518int
519main(void)
520{
521 printf("This program requires the ncurses library\n");
522 ExitProgram(EXIT_FAILURE);
523}
524#endif