• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  * Copyright 2020,2022 Thomas E. Dickey                                     *
3  * Copyright 2007-2012,2017 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_getstr.c,v 1.16 2022/12/10 23:58:37 tom Exp $
31  *
32  * Author: Thomas E Dickey
33  *
34  * Demonstrate the getstr functions from the curses library.
35 
36        int getstr(char *str);
37        int getnstr(char *str, int n);
38        int wgetstr(WINDOW *win, char *str);
39        int wgetnstr(WINDOW *win, char *str, int n);
40        int mvgetstr(int y, int x, char *str);
41        int mvwgetstr(WINDOW *win, int y, int x, char *str);
42        int mvgetnstr(int y, int x, char *str, int n);
43        int mvwgetnstr(WINDOW *, int y, int x, char *str, int n);
44  */
45 
46 #include <test.priv.h>
47 #include <popup_msg.h>
48 
49 #if HAVE_CHGAT
50 /* Solaris SVr4 curses lacks wchgat, mvgetnstr, mvwgetnstr */
51 
52 #define BASE_Y 6
53 #define MAX_COLS 1024
54 
55 typedef enum {
56     eGetStr = 0,
57     eGetNStr,
58     eMvGetStr,
59     eMvGetNStr,
60     eMaxFlavor
61 } Flavors;
62 
63 /*
64  * Return-code is OK/ERR or a keyname.
65  */
66 static const char *
ok_keyname(int code)67 ok_keyname(int code)
68 {
69     return ((code == OK) ? "OK" : ((code == ERR) ? "ERR" : keyname(code)));
70 }
71 
72 static bool
Quit(int ch)73 Quit(int ch)
74 {
75     return (ch == ERR || ch == 'q' || ch == QUIT || ch == ESCAPE);
76 }
77 
78 static int
Remainder(WINDOW * txtwin)79 Remainder(WINDOW *txtwin)
80 {
81     int result = getmaxx(txtwin) - getcurx(txtwin);
82     return (result > 0) ? result : 0;
83 }
84 
85 /*
86  * Show a highlighted line in the place where input will happen.
87  */
88 static void
ShowPrompt(WINDOW * txtwin,int limit)89 ShowPrompt(WINDOW *txtwin, int limit)
90 {
91     wchgat(txtwin, limit, WA_REVERSE, 0, NULL);
92     wnoutrefresh(txtwin);
93 }
94 
95 static void
MovePrompt(WINDOW * txtwin,int limit,int y,int x)96 MovePrompt(WINDOW *txtwin, int limit, int y, int x)
97 {
98     wchgat(txtwin, Remainder(txtwin), WA_NORMAL, 0, NULL);
99     wmove(txtwin, y, x);
100     ShowPrompt(txtwin, limit);
101 }
102 
103 static int
ShowFlavor(WINDOW * strwin,WINDOW * txtwin,int flavor,int limit)104 ShowFlavor(WINDOW *strwin, WINDOW *txtwin, int flavor, int limit)
105 {
106     const char *name = "?";
107     bool limited = FALSE;
108     bool wins = (txtwin != stdscr);
109     int result;
110 
111     switch (flavor) {
112     case eGetStr:
113 	name = wins ? "wgetstr" : "getstr";
114 	break;
115     case eGetNStr:
116 	limited = TRUE;
117 	name = wins ? "wgetnstr" : "getnstr";
118 	break;
119     case eMvGetStr:
120 	name = wins ? "mvwgetstr" : "mvgetstr";
121 	break;
122     case eMvGetNStr:
123 	limited = TRUE;
124 	name = wins ? "mvwgetnstr" : "mvgetnstr";
125 	break;
126     case eMaxFlavor:
127 	break;
128     }
129 
130     wmove(strwin, 0, 0);
131     werase(strwin);
132 
133     if (limited) {
134 	wprintw(strwin, "%s(%d):", name, limit);
135     } else {
136 	wprintw(strwin, "%s:", name);
137     }
138     result = limited ? limit : Remainder(txtwin);
139     ShowPrompt(txtwin, result);
140 
141     wnoutrefresh(strwin);
142     return result;
143 }
144 
145 static int
recursive_test(int level,char ** argv,WINDOW * strwin)146 recursive_test(int level, char **argv, WINDOW *strwin)
147 {
148     static const char *help[] =
149     {
150 	"Commands:",
151 	"  q,^Q,ESC       - quit this program",
152 	"  ^Q,ESC         - quit help-screen",
153 	"",
154 	"  p,<Up>         - move beginning of prompt one up row",
155 	"  j,<Down>       - move beginning of prompt one down row",
156 	"  h,<Left>       - move beginning of prompt one left column",
157 	"  l,<Right>      - move beginning of prompt one right column",
158 	"",
159 	"  -              - reduce getnstr buffer-size one column",
160 	"  +              - increase getnstr buffer-size one column",
161 	"  :              - prompt for input-text",
162 	"",
163 	"  <              - scroll \"left\" through getstr-functions",
164 	"  >              - scroll \"right\" through getstr-functions",
165 	"",
166 	"  w              - recur to subwindow",
167 	"  ?,<F1>         - show help-screen",
168 	0
169     };
170     WINDOW *txtbox = 0;
171     WINDOW *txtwin = 0;
172     FILE *fp;
173     int ch;
174     int rc;
175     int txt_x = 0, txt_y = 0;
176     int base_y;
177     int flavor = 0;
178     int limit = getmaxx(strwin) - 5;
179     int actual;
180 
181     char buffer[MAX_COLS];
182 
183     if (argv[level] == 0) {
184 	beep();
185 	return FALSE;
186     }
187 
188     if (level > 1) {
189 	txtbox = newwin(LINES - BASE_Y, COLS - level, BASE_Y, level);
190 	box(txtbox, 0, 0);
191 	wnoutrefresh(txtbox);
192 
193 	txtwin = derwin(txtbox,
194 			getmaxy(txtbox) - 2,
195 			getmaxx(txtbox) - 2,
196 			1, 1);
197 	base_y = 0;
198     } else {
199 	txtwin = stdscr;
200 	base_y = BASE_Y;
201     }
202 
203     keypad(txtwin, TRUE);	/* enable keyboard mapping */
204     (void) cbreak();		/* take input chars one at a time, no wait for \n */
205     (void) noecho();		/* don't echo input */
206 
207     txt_y = base_y;
208     txt_x = 0;
209     wmove(txtwin, txt_y, txt_x);
210 
211     if ((fp = fopen(argv[level], "r")) != 0) {
212 	while ((ch = fgetc(fp)) != EOF) {
213 	    if (waddch(txtwin, UChar(ch)) != OK) {
214 		break;
215 	    }
216 	}
217 	fclose(fp);
218     } else {
219 	wprintw(txtwin, "Cannot open:\n%s", argv[1]);
220     }
221 
222     wmove(txtwin, txt_y, txt_x);
223     actual = ShowFlavor(strwin, txtwin, flavor, limit);
224     while (!Quit(ch = mvwgetch(txtwin, txt_y, txt_x))) {
225 	switch (ch) {
226 	case KEY_DOWN:
227 	case 'j':
228 	    if (txt_y < getmaxy(txtwin) - 1) {
229 		MovePrompt(txtwin, actual, ++txt_y, txt_x);
230 	    } else {
231 		beep();
232 	    }
233 	    break;
234 	case KEY_UP:
235 	case 'k':
236 	    if (txt_y > base_y) {
237 		MovePrompt(txtwin, actual, --txt_y, txt_x);
238 	    } else {
239 		beep();
240 	    }
241 	    break;
242 	case KEY_LEFT:
243 	case 'h':
244 	    if (txt_x > 0) {
245 		MovePrompt(txtwin, actual, txt_y, --txt_x);
246 	    } else {
247 		beep();
248 	    }
249 	    break;
250 	case KEY_RIGHT:
251 	case 'l':
252 	    if (txt_x < getmaxx(txtwin) - 1) {
253 		MovePrompt(txtwin, actual, txt_y, ++txt_x);
254 	    } else {
255 		beep();
256 	    }
257 	    break;
258 
259 	case 'w':
260 	    recursive_test(level + 1, argv, strwin);
261 	    if (txtbox != 0) {
262 		touchwin(txtbox);
263 		wnoutrefresh(txtbox);
264 	    } else {
265 		touchwin(txtwin);
266 		wnoutrefresh(txtwin);
267 	    }
268 	    break;
269 
270 	case '-':
271 	    if (limit > 0) {
272 		actual = ShowFlavor(strwin, txtwin, flavor, --limit);
273 		MovePrompt(txtwin, actual, txt_y, txt_x);
274 	    } else {
275 		beep();
276 	    }
277 	    break;
278 
279 	case '+':
280 	    actual = ShowFlavor(strwin, txtwin, flavor, ++limit);
281 	    MovePrompt(txtwin, actual, txt_y, txt_x);
282 	    break;
283 
284 	case '<':
285 	    if (flavor > 0) {
286 		actual = ShowFlavor(strwin, txtwin, --flavor, limit);
287 		MovePrompt(txtwin, actual, txt_y, txt_x);
288 	    } else {
289 		beep();
290 	    }
291 	    break;
292 
293 	case '>':
294 	    if (flavor + 1 < eMaxFlavor) {
295 		actual = ShowFlavor(strwin, txtwin, ++flavor, limit);
296 		MovePrompt(txtwin, actual, txt_y, txt_x);
297 	    } else {
298 		beep();
299 	    }
300 	    break;
301 
302 	case ':':
303 	    actual = ShowFlavor(strwin, txtwin, flavor, limit);
304 	    *buffer = '\0';
305 	    rc = ERR;
306 	    echo();
307 	    (void) wattrset(txtwin, A_REVERSE);
308 	    switch (flavor) {
309 	    case eGetStr:
310 		if (txtwin != stdscr) {
311 		    wmove(txtwin, txt_y, txt_x);
312 		    rc = wgetstr(txtwin, buffer);
313 		} else {
314 		    move(txt_y, txt_x);
315 		    rc = getstr(buffer);
316 		}
317 		break;
318 	    case eGetNStr:
319 		if (txtwin != stdscr) {
320 		    wmove(txtwin, txt_y, txt_x);
321 		    rc = wgetnstr(txtwin, buffer, limit);
322 		} else {
323 		    move(txt_y, txt_x);
324 		    rc = getnstr(buffer, limit);
325 		}
326 		break;
327 	    case eMvGetStr:
328 		if (txtwin != stdscr) {
329 		    rc = mvwgetstr(txtwin, txt_y, txt_x, buffer);
330 		} else {
331 		    rc = mvgetstr(txt_y, txt_x, buffer);
332 		}
333 		break;
334 	    case eMvGetNStr:
335 		if (txtwin != stdscr) {
336 		    rc = mvwgetnstr(txtwin, txt_y, txt_x, buffer, limit);
337 		} else {
338 		    rc = mvgetnstr(txt_y, txt_x, buffer, limit);
339 		}
340 		break;
341 	    case eMaxFlavor:
342 		break;
343 	    }
344 	    noecho();
345 	    (void) wattrset(txtwin, A_NORMAL);
346 	    wprintw(strwin, "%s:%s", ok_keyname(rc), buffer);
347 	    wnoutrefresh(strwin);
348 	    break;
349 	case HELP_KEY_1:
350 	    popup_msg(stdscr, help);
351 	    break;
352 	default:
353 	    beep();
354 	    break;
355 	}
356 	doupdate();
357     }
358     if (level > 1) {
359 	delwin(txtwin);
360 	delwin(txtbox);
361     }
362     return TRUE;
363 }
364 
365 static void
usage(int ok)366 usage(int ok)
367 {
368     static const char *msg[] =
369     {
370 	"Usage: test_getstr [options] [file1 [...]]"
371 	,""
372 	,USAGE_COMMON
373     };
374     size_t n;
375 
376     for (n = 0; n < SIZEOF(msg); n++)
377 	fprintf(stderr, "%s\n", msg[n]);
378 
379     ExitProgram(ok ? EXIT_SUCCESS : EXIT_FAILURE);
380 }
381 /* *INDENT-OFF* */
VERSION_COMMON()382 VERSION_COMMON()
383 /* *INDENT-ON* */
384 
385 int
386 main(int argc, char *argv[])
387 {
388     WINDOW *chrbox;
389     WINDOW *strwin;
390     int ch;
391 
392     while ((ch = getopt(argc, argv, OPTS_COMMON)) != -1) {
393 	switch (ch) {
394 	case OPTS_VERSION:
395 	    show_version(argv);
396 	    ExitProgram(EXIT_SUCCESS);
397 	default:
398 	    usage(ch == OPTS_USAGE);
399 	    /* NOTREACHED */
400 	}
401     }
402 
403     setlocale(LC_ALL, "");
404 
405     if (optind + 1 > argc)
406 	usage(FALSE);
407 
408     initscr();
409 
410     chrbox = derwin(stdscr, BASE_Y, COLS, 0, 0);
411     box(chrbox, 0, 0);
412     wnoutrefresh(chrbox);
413 
414     strwin = derwin(chrbox, 4, COLS - 2, 1, 1);
415 
416     recursive_test(optind, argv, strwin);
417 
418     endwin();
419     ExitProgram(EXIT_SUCCESS);
420 }
421 
422 #else
423 int
main(void)424 main(void)
425 {
426     printf("This program requires the curses chgat function\n");
427     ExitProgram(EXIT_FAILURE);
428 }
429 #endif
430