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