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