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