ncurses 4.1
[ncurses.git] / ncurses / lib_getstr.c
1
2 /***************************************************************************
3 *                            COPYRIGHT NOTICE                              *
4 ****************************************************************************
5 *                ncurses is copyright (C) 1992-1995                        *
6 *                          Zeyd M. Ben-Halim                               *
7 *                          zmbenhal@netcom.com                             *
8 *                          Eric S. Raymond                                 *
9 *                          esr@snark.thyrsus.com                           *
10 *                                                                          *
11 *        Permission is hereby granted to reproduce and distribute ncurses  *
12 *        by any means and for any fee, whether alone or as part of a       *
13 *        larger distribution, in source or in binary form, PROVIDED        *
14 *        this notice is included with any such distribution, and is not    *
15 *        removed from any of its header files. Mention of ncurses in any   *
16 *        applications linked with it is highly appreciated.                *
17 *                                                                          *
18 *        ncurses comes AS IS with no warranty, implied or expressed.       *
19 *                                                                          *
20 ***************************************************************************/
21
22
23 /*
24 **      lib_getstr.c
25 **
26 **      The routine wgetstr().
27 **
28 */
29
30 #include <curses.priv.h>
31 #include <term.h>
32
33 MODULE_ID("$Id: lib_getstr.c,v 1.11 1997/02/01 23:22:54 tom Exp $")
34
35 /*
36  * This wipes out the last character, no matter whether it was a tab, control
37  * or other character, and handles reverse wraparound.
38  */
39 static char *WipeOut(WINDOW *win, int y, int x, char *first, char *last, bool echoed)
40 {
41         if (last > first) {
42                 *--last = '\0';
43                 if (echoed) {
44                         int y1 = win->_cury;
45                         int x1 = win->_curx;
46
47                         wmove(win, y, x);
48                         waddstr(win, first);
49                         getyx(win, y, x);
50                         while (win->_cury < y1
51                            || (win->_cury == y1 && win->_curx < x1))
52                                 waddch(win, ' ');
53
54                         wmove(win, y, x);
55                 }
56         }
57         return last;
58 }
59
60 int wgetnstr(WINDOW *win, char *str, int maxlen)
61 {
62 TTY     buf;
63 bool    oldnl, oldecho, oldraw, oldcbreak, oldkeypad;
64 char    erasec;
65 char    killc;
66 char    *oldstr;
67 int ch;
68 int     y, x;
69
70         T((T_CALLED("wgetnstr(%p,%p, %d)"), win, str, maxlen));
71
72         GET_TTY(cur_term->Filedes, &buf);
73
74         oldnl = SP->_nl;
75         oldecho = SP->_echo;
76         oldraw = SP->_raw;
77         oldcbreak = SP->_cbreak;
78         oldkeypad = win->_use_keypad;
79         nl();
80         noecho();
81         noraw();
82         cbreak();
83         keypad(win, TRUE);
84
85         erasec = erasechar();
86         killc = killchar();
87
88         oldstr = str;
89         getyx(win, y, x);
90
91         if (is_wintouched(win) || (win->_flags & _HASMOVED))
92                 wrefresh(win);
93
94         while ((ch = wgetch(win)) != ERR) {
95                 /*
96                  * Some terminals (the Wyse-50 is the most common) generate
97                  * a \n from the down-arrow key.  With this logic, it's the
98                  * user's choice whether to set kcud=\n for wgetch();
99                  * terminating *getstr() with \n should work either way.
100                  */
101                 if (ch == '\n'
102                  || ch == '\r'
103                  || ch == KEY_DOWN
104                  || ch == KEY_ENTER)
105                         break;
106                 if (ch == erasec || ch == KEY_LEFT || ch == KEY_BACKSPACE) {
107                         if (str > oldstr) {
108                                 str = WipeOut(win, y, x, oldstr, str, oldecho);
109                         }
110                 } else if (ch == killc) {
111                         while (str > oldstr) {
112                                 str = WipeOut(win, y, x, oldstr, str, oldecho);
113                         }
114                 } else if (ch >= KEY_MIN
115                            || (maxlen >= 0 && str - oldstr >= maxlen)) {
116                         beep();
117                 } else {
118                         *str++ = ch;
119                         if (oldecho == TRUE) {
120                                 if (waddch(win, ch) == ERR) {
121                                         /*
122                                          * We can't really use the lower-right
123                                          * corner for input, since it'll mess
124                                          * up bookkeeping for erases.
125                                          */
126                                         win->_flags &= ~_WRAPPED;
127                                         waddch(win, ' ');
128                                         str = WipeOut(win, y, x, oldstr, str, oldecho);
129                                         continue;
130                                 }
131                                 wrefresh(win);
132                         }
133                 }
134         }
135
136         win->_curx = 0;
137         win->_flags &= ~_WRAPPED;
138         if (win->_cury < win->_maxy)
139                 win->_cury++;
140         wrefresh(win);
141
142         /* Restore with a single I/O call, to fix minor asymmetry between
143          * raw/noraw, etc.
144          */
145         SP->_nl = oldnl;
146         SP->_echo = oldecho;
147         SP->_raw = oldraw;
148         SP->_cbreak = oldcbreak;
149
150         SET_TTY(cur_term->Filedes, &buf);
151
152         if (oldkeypad == FALSE)
153                 keypad(win, FALSE);
154
155         *str = '\0';
156         if (ch == ERR)
157                 returnCode(ERR);
158
159         T(("wgetnstr returns %s", _nc_visbuf(oldstr)));
160
161         returnCode(OK);
162 }