1/****************************************************************************
2 * Copyright (c) 1998-2000,2002 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/****************************************************************************
30 *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
31 *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
32 ****************************************************************************/
33
34/*
35**	lib_getstr.c
36**
37**	The routine wgetstr().
38**
39*/
40
41#include <curses.priv.h>
42#include <term.h>
43
44MODULE_ID("$Id: lib_getstr.c,v 1.24 2002/09/01 17:31:12 tom Exp $")
45
46/*
47 * This wipes out the last character, no matter whether it was a tab, control
48 * or other character, and handles reverse wraparound.
49 */
50static char *
51WipeOut(WINDOW *win, int y, int x, char *first, char *last, bool echoed)
52{
53    if (last > first) {
54	*--last = '\0';
55	if (echoed) {
56	    int y1 = win->_cury;
57	    int x1 = win->_curx;
58
59	    wmove(win, y, x);
60	    waddstr(win, first);
61	    getyx(win, y, x);
62	    while (win->_cury < y1
63		   || (win->_cury == y1 && win->_curx < x1))
64		waddch(win, (chtype) ' ');
65
66	    wmove(win, y, x);
67	}
68    }
69    return last;
70}
71
72NCURSES_EXPORT(int)
73wgetnstr_events(WINDOW *win,
74		char *str,
75		int maxlen,
76		EVENTLIST_1st(_nc_eventlist * evl))
77{
78    TTY buf;
79    bool oldnl, oldecho, oldraw, oldcbreak;
80    char erasec;
81    char killc;
82    char *oldstr;
83    int ch;
84    int y, x;
85
86    T((T_CALLED("wgetnstr(%p,%p, %d)"), win, str, maxlen));
87
88    if (!win)
89	returnCode(ERR);
90
91    _nc_get_tty_mode(&buf);
92
93    oldnl = SP->_nl;
94    oldecho = SP->_echo;
95    oldraw = SP->_raw;
96    oldcbreak = SP->_cbreak;
97    nl();
98    noecho();
99    noraw();
100    cbreak();
101
102    erasec = erasechar();
103    killc = killchar();
104
105    oldstr = str;
106    getyx(win, y, x);
107
108    if (is_wintouched(win) || (win->_flags & _HASMOVED))
109	wrefresh(win);
110
111    while ((ch = wgetch_events(win, evl)) != ERR) {
112	/*
113	 * Some terminals (the Wyse-50 is the most common) generate
114	 * a \n from the down-arrow key.  With this logic, it's the
115	 * user's choice whether to set kcud=\n for wgetch();
116	 * terminating *getstr() with \n should work either way.
117	 */
118	if (ch == '\n'
119	    || ch == '\r'
120	    || ch == KEY_DOWN
121	    || ch == KEY_ENTER) {
122	    if (oldecho == TRUE
123		&& win->_cury == win->_maxy
124		&& win->_scroll)
125		wechochar(win, (chtype) '\n');
126	    break;
127	}
128#ifdef KEY_EVENT
129	if (ch == KEY_EVENT)
130	    break;
131#endif
132	if (ch == erasec || ch == KEY_LEFT || ch == KEY_BACKSPACE) {
133	    if (str > oldstr) {
134		str = WipeOut(win, y, x, oldstr, str, oldecho);
135	    }
136	} else if (ch == killc) {
137	    while (str > oldstr) {
138		str = WipeOut(win, y, x, oldstr, str, oldecho);
139	    }
140	} else if (ch >= KEY_MIN
141		   || (maxlen >= 0 && str - oldstr >= maxlen)) {
142	    beep();
143	} else {
144	    *str++ = ch;
145	    if (oldecho == TRUE) {
146		int oldy = win->_cury;
147		if (waddch(win, (chtype) ch) == ERR) {
148		    /*
149		     * We can't really use the lower-right
150		     * corner for input, since it'll mess
151		     * up bookkeeping for erases.
152		     */
153		    win->_flags &= ~_WRAPPED;
154		    waddch(win, (chtype) ' ');
155		    str = WipeOut(win, y, x, oldstr, str, oldecho);
156		    continue;
157		} else if (win->_flags & _WRAPPED) {
158		    /*
159		     * If the last waddch forced a wrap &
160		     * scroll, adjust our reference point
161		     * for erasures.
162		     */
163		    if (win->_scroll
164			&& oldy == win->_maxy
165			&& win->_cury == win->_maxy) {
166			if (--y <= 0) {
167			    y = 0;
168			}
169		    }
170		    win->_flags &= ~_WRAPPED;
171		}
172		wrefresh(win);
173	    }
174	}
175    }
176
177    win->_curx = 0;
178    win->_flags &= ~_WRAPPED;
179    if (win->_cury < win->_maxy)
180	win->_cury++;
181    wrefresh(win);
182
183    /* Restore with a single I/O call, to fix minor asymmetry between
184     * raw/noraw, etc.
185     */
186    SP->_nl = oldnl;
187    SP->_echo = oldecho;
188    SP->_raw = oldraw;
189    SP->_cbreak = oldcbreak;
190
191    _nc_set_tty_mode(&buf);
192
193    *str = '\0';
194    if (ch == ERR)
195	returnCode(ch);
196#ifdef KEY_EVENT
197    if (ch == KEY_EVENT)
198	returnCode(ch);
199#endif
200
201    T(("wgetnstr returns %s", _nc_visbuf(oldstr)));
202
203    returnCode(OK);
204}
205
206#ifdef NCURSES_WGETCH_EVENTS
207NCURSES_EXPORT(int)
208wgetnstr(WINDOW *win, char *str, int maxlen)
209{
210    returnCode(wgetnstr_events(win,
211			       str,
212			       maxlen,
213			       EVENTLIST_1st((_nc_eventlist *) 0)));
214}
215#endif
216