1 /* Public Domain Curses */
2 
3 #include <curspriv.h>
4 
5 RCSID("$Id: getstr.c,v 1.51 2008/07/14 04:24:51 wmcbrine Exp $")
6 
7 /*man-start**************************************************************
8 
9   Name:                                                         getstr
10 
11   Synopsis:
12         int getstr(char *str);
13         int wgetstr(WINDOW *win, char *str);
14         int mvgetstr(int y, int x, char *str);
15         int mvwgetstr(WINDOW *win, int y, int x, char *str);
16         int getnstr(char *str, int n);
17         int wgetnstr(WINDOW *win, char *str, int n);
18         int mvgetnstr(int y, int x, char *str, int n);
19         int mvwgetnstr(WINDOW *win, int y, int x, char *str, int n);
20 
21         int get_wstr(wint_t *wstr);
22         int wget_wstr(WINDOW *win, wint_t *wstr);
23         int mvget_wstr(int y, int x, wint_t *wstr);
24         int mvwget_wstr(WINDOW *win, int, int, wint_t *wstr);
25         int getn_wstr(wint_t *wstr, int n);
26         int wgetn_wstr(WINDOW *win, wint_t *wstr, int n);
27         int mvgetn_wstr(int y, int x, wint_t *wstr, int n);
28         int mvwgetn_wstr(WINDOW *win, int y, int x, wint_t *wstr, int n);
29 
30   Description:
31         These routines call wgetch() repeatedly to build a string,
32         interpreting erase and kill characters along the way, until a
33         newline or carriage return is received. When PDCurses is built
34         with wide-character support enabled, the narrow-character
35         functions convert the wgetch()'d values into a multibyte string
36         in the current locale before returning it. The resulting string
37         is placed in the area pointed to by *str. The routines with n as
38         the last argument read at most n characters.
39 
40         Note that there's no way to know how long the buffer passed to
41         wgetstr() is, so use wgetnstr() to avoid buffer overflows.
42 
43   Return Value:
44         This functions return ERR on failure or any other value on
45         success.
46 
47   Portability                                X/Open    BSD    SYS V
48         getstr                                  Y       Y       Y
49         wgetstr                                 Y       Y       Y
50         mvgetstr                                Y       Y       Y
51         mvwgetstr                               Y       Y       Y
52         getnstr                                 Y       -      4.0
53         wgetnstr                                Y       -      4.0
54         mvgetnstr                               Y       -       -
55         mvwgetnstr                              Y       -       -
56         get_wstr                                Y
57         wget_wstr                               Y
58         mvget_wstr                              Y
59         mvwget_wstr                             Y
60         getn_wstr                               Y
61         wgetn_wstr                              Y
62         mvgetn_wstr                             Y
63         mvwgetn_wstr                            Y
64 
65 **man-end****************************************************************/
66 
67 #define MAXLINE 255
68 
wgetnstr(WINDOW * win,char * str,int n)69 int wgetnstr(WINDOW *win, char *str, int n)
70 {
71 #ifdef PDC_WIDE
72     wchar_t wstr[MAXLINE + 1];
73 
74     if (n < 0 || n > MAXLINE)
75         n = MAXLINE;
76 
77     if (wgetn_wstr(win, (wint_t *)wstr, n) == ERR)
78         return ERR;
79 
80     return PDC_wcstombs(str, wstr, n);
81 #else
82     int ch, i, num, x, chars;
83     char *p;
84     bool stop, oldecho, oldcbreak, oldnodelay;
85 
86     PDC_LOG(("wgetnstr() - called\n"));
87 
88     if (!win || !str)
89         return ERR;
90 
91     chars = 0;
92     p = str;
93     stop = FALSE;
94 
95     x = win->_curx;
96 
97     oldcbreak = SP->cbreak; /* remember states */
98     oldecho = SP->echo;
99     oldnodelay = win->_nodelay;
100 
101     SP->echo = FALSE;       /* we do echo ourselves */
102     cbreak();               /* ensure each key is returned immediately */
103     win->_nodelay = FALSE;  /* don't return -1 */
104 
105     wrefresh(win);
106 
107     while (!stop)
108     {
109         ch = wgetch(win);
110 
111         switch (ch)
112         {
113 
114         case '\t':
115             ch = ' ';
116             num = TABSIZE - (win->_curx - x) % TABSIZE;
117             for (i = 0; i < num; i++)
118             {
119                 if (chars < n)
120                 {
121                     if (oldecho)
122                         waddch(win, ch);
123                     *p++ = ch;
124                     ++chars;
125                 }
126                 else
127                     beep();
128             }
129             break;
130 
131         case _ECHAR:        /* CTRL-H -- Delete character */
132             if (p > str)
133             {
134                 if (oldecho)
135                     waddstr(win, "\b \b");
136                 ch = (unsigned char)(*--p);
137                 if ((ch < ' ') && (oldecho))
138                     waddstr(win, "\b \b");
139                 chars--;
140             }
141             break;
142 
143         case _DLCHAR:       /* CTRL-U -- Delete line */
144             while (p > str)
145             {
146                 if (oldecho)
147                     waddstr(win, "\b \b");
148                 ch = (unsigned char)(*--p);
149                 if ((ch < ' ') && (oldecho))
150                     waddstr(win, "\b \b");
151             }
152             chars = 0;
153             break;
154 
155         case _DWCHAR:       /* CTRL-W -- Delete word */
156 
157             while ((p > str) && (*(p - 1) == ' '))
158             {
159                 if (oldecho)
160                     waddstr(win, "\b \b");
161 
162                 --p;        /* remove space */
163                 chars--;
164             }
165             while ((p > str) && (*(p - 1) != ' '))
166             {
167                 if (oldecho)
168                     waddstr(win, "\b \b");
169 
170                 ch = (unsigned char)(*--p);
171                 if ((ch < ' ') && (oldecho))
172                     waddstr(win, "\b \b");
173                 chars--;
174             }
175             break;
176 
177         case '\n':
178         case '\r':
179             stop = TRUE;
180             if (oldecho)
181                 waddch(win, '\n');
182             break;
183 
184         default:
185             if (chars < n)
186             {
187                 if (!SP->key_code && ch < 0x100)
188                 {
189                     *p++ = ch;
190                     if (oldecho)
191                         waddch(win, ch);
192                     chars++;
193                 }
194             }
195             else
196                 beep();
197 
198             break;
199 
200         }
201 
202         wrefresh(win);
203     }
204 
205     *p = '\0';
206 
207     SP->echo = oldecho;     /* restore old settings */
208     SP->cbreak = oldcbreak;
209     win->_nodelay = oldnodelay;
210 
211     return OK;
212 #endif
213 }
214 
getstr(char * str)215 int getstr(char *str)
216 {
217     PDC_LOG(("getstr() - called\n"));
218 
219     return wgetnstr(stdscr, str, MAXLINE);
220 }
221 
wgetstr(WINDOW * win,char * str)222 int wgetstr(WINDOW *win, char *str)
223 {
224     PDC_LOG(("wgetstr() - called\n"));
225 
226     return wgetnstr(win, str, MAXLINE);
227 }
228 
mvgetstr(int y,int x,char * str)229 int mvgetstr(int y, int x, char *str)
230 {
231     PDC_LOG(("mvgetstr() - called\n"));
232 
233     if (move(y, x) == ERR)
234         return ERR;
235 
236     return wgetnstr(stdscr, str, MAXLINE);
237 }
238 
mvwgetstr(WINDOW * win,int y,int x,char * str)239 int mvwgetstr(WINDOW *win, int y, int x, char *str)
240 {
241     PDC_LOG(("mvwgetstr() - called\n"));
242 
243     if (wmove(win, y, x) == ERR)
244         return ERR;
245 
246     return wgetnstr(win, str, MAXLINE);
247 }
248 
getnstr(char * str,int n)249 int getnstr(char *str, int n)
250 {
251     PDC_LOG(("getnstr() - called\n"));
252 
253     return wgetnstr(stdscr, str, n);
254 }
255 
mvgetnstr(int y,int x,char * str,int n)256 int mvgetnstr(int y, int x, char *str, int n)
257 {
258     PDC_LOG(("mvgetnstr() - called\n"));
259 
260     if (move(y, x) == ERR)
261         return ERR;
262 
263     return wgetnstr(stdscr, str, n);
264 }
265 
mvwgetnstr(WINDOW * win,int y,int x,char * str,int n)266 int mvwgetnstr(WINDOW *win, int y, int x, char *str, int n)
267 {
268     PDC_LOG(("mvwgetnstr() - called\n"));
269 
270     if (wmove(win, y, x) == ERR)
271         return ERR;
272 
273     return wgetnstr(win, str, n);
274 }
275 
276 #ifdef PDC_WIDE
wgetn_wstr(WINDOW * win,wint_t * wstr,int n)277 int wgetn_wstr(WINDOW *win, wint_t *wstr, int n)
278 {
279     int ch, i, num, x, chars;
280     wint_t *p;
281     bool stop, oldecho, oldcbreak, oldnodelay;
282 
283     PDC_LOG(("wgetn_wstr() - called\n"));
284 
285     if (!win || !wstr)
286         return ERR;
287 
288     chars = 0;
289     p = wstr;
290     stop = FALSE;
291 
292     x = win->_curx;
293 
294     oldcbreak = SP->cbreak; /* remember states */
295     oldecho = SP->echo;
296     oldnodelay = win->_nodelay;
297 
298     SP->echo = FALSE;       /* we do echo ourselves */
299     cbreak();               /* ensure each key is returned immediately */
300     win->_nodelay = FALSE;  /* don't return -1 */
301 
302     wrefresh(win);
303 
304     while (!stop)
305     {
306         ch = wgetch(win);
307 
308         switch (ch)
309         {
310 
311         case '\t':
312             ch = ' ';
313             num = TABSIZE - (win->_curx - x) % TABSIZE;
314             for (i = 0; i < num; i++)
315             {
316                 if (chars < n)
317                 {
318                     if (oldecho)
319                         waddch(win, ch);
320                     *p++ = ch;
321                     ++chars;
322                 }
323                 else
324                     beep();
325             }
326             break;
327 
328         case _ECHAR:        /* CTRL-H -- Delete character */
329             if (p > wstr)
330             {
331                 if (oldecho)
332                     waddstr(win, "\b \b");
333                 ch = *--p;
334                 if ((ch < ' ') && (oldecho))
335                     waddstr(win, "\b \b");
336                 chars--;
337             }
338             break;
339 
340         case _DLCHAR:       /* CTRL-U -- Delete line */
341             while (p > wstr)
342             {
343                 if (oldecho)
344                     waddstr(win, "\b \b");
345                 ch = *--p;
346                 if ((ch < ' ') && (oldecho))
347                     waddstr(win, "\b \b");
348             }
349             chars = 0;
350             break;
351 
352         case _DWCHAR:       /* CTRL-W -- Delete word */
353 
354             while ((p > wstr) && (*(p - 1) == ' '))
355             {
356                 if (oldecho)
357                     waddstr(win, "\b \b");
358 
359                 --p;        /* remove space */
360                 chars--;
361             }
362             while ((p > wstr) && (*(p - 1) != ' '))
363             {
364                 if (oldecho)
365                     waddstr(win, "\b \b");
366 
367                 ch = *--p;
368                 if ((ch < ' ') && (oldecho))
369                     waddstr(win, "\b \b");
370                 chars--;
371             }
372             break;
373 
374         case '\n':
375         case '\r':
376             stop = TRUE;
377             if (oldecho)
378                 waddch(win, '\n');
379             break;
380 
381         default:
382             if (chars < n)
383             {
384                 if (!SP->key_code)
385                 {
386                     *p++ = ch;
387                     if (oldecho)
388                         waddch(win, ch);
389                     chars++;
390                 }
391             }
392             else
393                 beep();
394 
395             break;
396 
397         }
398 
399         wrefresh(win);
400     }
401 
402     *p = '\0';
403 
404     SP->echo = oldecho;     /* restore old settings */
405     SP->cbreak = oldcbreak;
406     win->_nodelay = oldnodelay;
407 
408     return OK;
409 }
410 
get_wstr(wint_t * wstr)411 int get_wstr(wint_t *wstr)
412 {
413     PDC_LOG(("get_wstr() - called\n"));
414 
415     return wgetn_wstr(stdscr, wstr, MAXLINE);
416 }
417 
wget_wstr(WINDOW * win,wint_t * wstr)418 int wget_wstr(WINDOW *win, wint_t *wstr)
419 {
420     PDC_LOG(("wget_wstr() - called\n"));
421 
422     return wgetn_wstr(win, wstr, MAXLINE);
423 }
424 
mvget_wstr(int y,int x,wint_t * wstr)425 int mvget_wstr(int y, int x, wint_t *wstr)
426 {
427     PDC_LOG(("mvget_wstr() - called\n"));
428 
429     if (move(y, x) == ERR)
430         return ERR;
431 
432     return wgetn_wstr(stdscr, wstr, MAXLINE);
433 }
434 
mvwget_wstr(WINDOW * win,int y,int x,wint_t * wstr)435 int mvwget_wstr(WINDOW *win, int y, int x, wint_t *wstr)
436 {
437     PDC_LOG(("mvwget_wstr() - called\n"));
438 
439     if (wmove(win, y, x) == ERR)
440         return ERR;
441 
442     return wgetn_wstr(win, wstr, MAXLINE);
443 }
444 
getn_wstr(wint_t * wstr,int n)445 int getn_wstr(wint_t *wstr, int n)
446 {
447     PDC_LOG(("getn_wstr() - called\n"));
448 
449     return wgetn_wstr(stdscr, wstr, n);
450 }
451 
mvgetn_wstr(int y,int x,wint_t * wstr,int n)452 int mvgetn_wstr(int y, int x, wint_t *wstr, int n)
453 {
454     PDC_LOG(("mvgetn_wstr() - called\n"));
455 
456     if (move(y, x) == ERR)
457         return ERR;
458 
459     return wgetn_wstr(stdscr, wstr, n);
460 }
461 
mvwgetn_wstr(WINDOW * win,int y,int x,wint_t * wstr,int n)462 int mvwgetn_wstr(WINDOW *win, int y, int x, wint_t *wstr, int n)
463 {
464     PDC_LOG(("mvwgetn_wstr() - called\n"));
465 
466     if (wmove(win, y, x) == ERR)
467         return ERR;
468 
469     return wgetn_wstr(win, wstr, n);
470 }
471 #endif
472