blob: 744e5e65fe715125491b2b9c41f39f70b6ebd1ba [file] [log] [blame]
Patrick Georgi3b77b722011-07-07 15:41:53 +02001/* Public Domain Curses */
2
3#include <curspriv.h>
4
5RCSID("$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:
Stefan Reinauere11835e2011-10-31 12:54:00 -070031 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
Patrick Georgi3b77b722011-07-07 15:41:53 +020038 the last argument read at most n characters.
39
Stefan Reinauere11835e2011-10-31 12:54:00 -070040 Note that there's no way to know how long the buffer passed to
Patrick Georgi3b77b722011-07-07 15:41:53 +020041 wgetstr() is, so use wgetnstr() to avoid buffer overflows.
42
43 Return Value:
Stefan Reinauere11835e2011-10-31 12:54:00 -070044 This functions return ERR on failure or any other value on
Patrick Georgi3b77b722011-07-07 15:41:53 +020045 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
69int 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 {
Stefan Reinauere11835e2011-10-31 12:54:00 -0700121 if (oldecho)
Patrick Georgi3b77b722011-07-07 15:41:53 +0200122 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 {
Stefan Reinauere11835e2011-10-31 12:54:00 -0700134 if (oldecho)
Patrick Georgi3b77b722011-07-07 15:41:53 +0200135 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 {
Stefan Reinauere11835e2011-10-31 12:54:00 -0700146 if (oldecho)
Patrick Georgi3b77b722011-07-07 15:41:53 +0200147 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 {
Stefan Reinauere11835e2011-10-31 12:54:00 -0700159 if (oldecho)
Patrick Georgi3b77b722011-07-07 15:41:53 +0200160 waddstr(win, "\b \b");
161
162 --p; /* remove space */
163 chars--;
164 }
165 while ((p > str) && (*(p - 1) != ' '))
166 {
Stefan Reinauere11835e2011-10-31 12:54:00 -0700167 if (oldecho)
Patrick Georgi3b77b722011-07-07 15:41:53 +0200168 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;
Stefan Reinauere11835e2011-10-31 12:54:00 -0700180 if (oldecho)
Patrick Georgi3b77b722011-07-07 15:41:53 +0200181 waddch(win, '\n');
182 break;
183
184 default:
185 if (chars < n)
186 {
187 if (!SP->key_code && ch < 0x100)
188 {
189 *p++ = ch;
Stefan Reinauere11835e2011-10-31 12:54:00 -0700190 if (oldecho)
Patrick Georgi3b77b722011-07-07 15:41:53 +0200191 waddch(win, ch);
192 chars++;
193 }
194 }
195 else
196 beep();
197
198 break;
Stefan Reinauere11835e2011-10-31 12:54:00 -0700199
Patrick Georgi3b77b722011-07-07 15:41:53 +0200200 }
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
215int getstr(char *str)
216{
217 PDC_LOG(("getstr() - called\n"));
218
219 return wgetnstr(stdscr, str, MAXLINE);
220}
221
222int wgetstr(WINDOW *win, char *str)
223{
224 PDC_LOG(("wgetstr() - called\n"));
225
226 return wgetnstr(win, str, MAXLINE);
227}
228
229int 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
239int 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
249int getnstr(char *str, int n)
250{
251 PDC_LOG(("getnstr() - called\n"));
252
253 return wgetnstr(stdscr, str, n);
254}
255
256int 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
266int 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
277int 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 {
Stefan Reinauere11835e2011-10-31 12:54:00 -0700318 if (oldecho)
Patrick Georgi3b77b722011-07-07 15:41:53 +0200319 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 {
Stefan Reinauere11835e2011-10-31 12:54:00 -0700331 if (oldecho)
Patrick Georgi3b77b722011-07-07 15:41:53 +0200332 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 {
Stefan Reinauere11835e2011-10-31 12:54:00 -0700343 if (oldecho)
Patrick Georgi3b77b722011-07-07 15:41:53 +0200344 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 {
Stefan Reinauere11835e2011-10-31 12:54:00 -0700356 if (oldecho)
Patrick Georgi3b77b722011-07-07 15:41:53 +0200357 waddstr(win, "\b \b");
358
359 --p; /* remove space */
360 chars--;
361 }
362 while ((p > wstr) && (*(p - 1) != ' '))
363 {
Stefan Reinauere11835e2011-10-31 12:54:00 -0700364 if (oldecho)
Patrick Georgi3b77b722011-07-07 15:41:53 +0200365 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;
Stefan Reinauere11835e2011-10-31 12:54:00 -0700377 if (oldecho)
Patrick Georgi3b77b722011-07-07 15:41:53 +0200378 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;
Stefan Reinauere11835e2011-10-31 12:54:00 -0700396
Patrick Georgi3b77b722011-07-07 15:41:53 +0200397 }
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
411int get_wstr(wint_t *wstr)
412{
413 PDC_LOG(("get_wstr() - called\n"));
414
415 return wgetn_wstr(stdscr, wstr, MAXLINE);
416}
417
418int 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
425int 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
435int 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
445int 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
452int 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
462int 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