1/**************************************************************************** 2 * Copyright 2018,2020 Thomas E. Dickey * 3 * Copyright 1998-2011,2017 Free Software Foundation, Inc. * 4 * * 5 * Permission is hereby granted, free of charge, to any person obtaining a * 6 * copy of this software and associated documentation files (the * 7 * "Software"), to deal in the Software without restriction, including * 8 * without limitation the rights to use, copy, modify, merge, publish, * 9 * distribute, distribute with modifications, sublicense, and/or sell * 10 * copies of the Software, and to permit persons to whom the Software is * 11 * furnished to do so, subject to the following conditions: * 12 * * 13 * The above copyright notice and this permission notice shall be included * 14 * in all copies or substantial portions of the Software. * 15 * * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 19 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 23 * * 24 * Except as contained in this notice, the name(s) of the above copyright * 25 * holders shall not be used in advertising or otherwise to promote the * 26 * sale, use or other dealings in this Software without prior written * 27 * authorization. * 28 ****************************************************************************/ 29 30/**************************************************************************** 31 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 32 * and: Eric S. Raymond <esr@snark.thyrsus.com> * 33 ****************************************************************************/ 34 35/* 36** lib_getstr.c 37** 38** The routine wgetstr(). 39** 40*/ 41 42#define NEED_KEY_EVENT 43#include <curses.priv.h> 44 45MODULE_ID("$Id: lib_getstr.c,v 1.35 2020/07/18 20:02:24 tom Exp $") 46 47/* 48 * This wipes out the last character, no matter whether it was a tab, control 49 * or other character, and handles reverse wraparound. 50 */ 51static char * 52WipeOut(WINDOW *win, int y, int x, char *first, char *last, int echoed) 53{ 54 if (last > first) { 55 *--last = '\0'; 56 if (echoed) { 57 int y1 = win->_cury; 58 int x1 = win->_curx; 59 60 wmove(win, y, x); 61 waddstr(win, first); 62 getyx(win, y, x); 63 while (win->_cury < y1 64 || (win->_cury == y1 && win->_curx < x1)) 65 waddch(win, (chtype) ' '); 66 67 wmove(win, y, x); 68 } 69 } 70 return last; 71} 72 73NCURSES_EXPORT(int) 74wgetnstr_events(WINDOW *win, 75 char *str, 76 int maxlen, 77 EVENTLIST_1st(_nc_eventlist * evl)) 78{ 79 SCREEN *sp = _nc_screen_of(win); 80 TTY buf; 81 bool oldnl, oldecho, oldraw, oldcbreak; 82 char erasec; 83 char killc; 84 char *oldstr; 85 int ch; 86 int y, x; 87 88 T((T_CALLED("wgetnstr(%p,%p,%d)"), (void *) win, (void *) str, maxlen)); 89 90 if (!win || !str) 91 returnCode(ERR); 92 93 maxlen = _nc_getstr_limit(maxlen); 94 95 NCURSES_SP_NAME(_nc_get_tty_mode) (NCURSES_SP_ARGx &buf); 96 97 oldnl = sp->_nl; 98 oldecho = sp->_echo; 99 oldraw = sp->_raw; 100 oldcbreak = sp->_cbreak; 101 NCURSES_SP_NAME(nl) (NCURSES_SP_ARG); 102 NCURSES_SP_NAME(noecho) (NCURSES_SP_ARG); 103 NCURSES_SP_NAME(noraw) (NCURSES_SP_ARG); 104 NCURSES_SP_NAME(cbreak) (NCURSES_SP_ARG); 105 106 erasec = NCURSES_SP_NAME(erasechar) (NCURSES_SP_ARG); 107 killc = NCURSES_SP_NAME(killchar) (NCURSES_SP_ARG); 108 109 oldstr = str; 110 getyx(win, y, x); 111 112 if (is_wintouched(win) || (win->_flags & _HASMOVED)) 113 wrefresh(win); 114 115 while ((ch = wgetch_events(win, evl)) != ERR) { 116 /* 117 * Some terminals (the Wyse-50 is the most common) generate 118 * a \n from the down-arrow key. With this logic, it's the 119 * user's choice whether to set kcud=\n for wgetch(); 120 * terminating *getstr() with \n should work either way. 121 */ 122 if (ch == '\n' 123 || ch == '\r' 124 || ch == KEY_DOWN 125 || ch == KEY_ENTER) { 126 if (oldecho == TRUE 127 && win->_cury == win->_maxy 128 && win->_scroll) 129 wechochar(win, (chtype) '\n'); 130 break; 131 } 132#ifdef KEY_EVENT 133 if (ch == KEY_EVENT) 134 break; 135#endif 136#ifdef KEY_RESIZE 137 if (ch == KEY_RESIZE) 138 break; 139#endif 140 if (ch == erasec || ch == KEY_LEFT || ch == KEY_BACKSPACE) { 141 if (str > oldstr) { 142 str = WipeOut(win, y, x, oldstr, str, oldecho); 143 } 144 } else if (ch == killc) { 145 while (str > oldstr) { 146 str = WipeOut(win, y, x, oldstr, str, oldecho); 147 } 148 } else if (ch >= KEY_MIN 149 || (str - oldstr >= maxlen)) { 150 NCURSES_SP_NAME(beep) (NCURSES_SP_ARG); 151 } else { 152 *str++ = (char) ch; 153 if (oldecho == TRUE) { 154 int oldy = win->_cury; 155 if (waddch(win, (chtype) ch) == ERR) { 156 /* 157 * We can't really use the lower-right 158 * corner for input, since it'll mess 159 * up bookkeeping for erases. 160 */ 161 win->_flags &= ~_WRAPPED; 162 waddch(win, (chtype) ' '); 163 str = WipeOut(win, y, x, oldstr, str, oldecho); 164 continue; 165 } else if (win->_flags & _WRAPPED) { 166 /* 167 * If the last waddch forced a wrap & 168 * scroll, adjust our reference point 169 * for erasures. 170 */ 171 if (win->_scroll 172 && oldy == win->_maxy 173 && win->_cury == win->_maxy) { 174 if (--y <= 0) { 175 y = 0; 176 } 177 } 178 win->_flags &= ~_WRAPPED; 179 } 180 wrefresh(win); 181 } 182 } 183 } 184 185 win->_curx = 0; 186 win->_flags &= ~_WRAPPED; 187 if (win->_cury < win->_maxy) 188 win->_cury++; 189 wrefresh(win); 190 191 /* Restore with a single I/O call, to fix minor asymmetry between 192 * raw/noraw, etc. 193 */ 194 sp->_nl = oldnl; 195 sp->_echo = oldecho; 196 sp->_raw = oldraw; 197 sp->_cbreak = oldcbreak; 198 199 NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf); 200 201 *str = '\0'; 202 if (ch == ERR) 203 returnCode(ch); 204 205 T(("wgetnstr returns %s", _nc_visbuf(oldstr))); 206 207#ifdef KEY_EVENT 208 if (ch == KEY_EVENT) 209 returnCode(ch); 210#endif 211#ifdef KEY_RESIZE 212 if (ch == KEY_RESIZE) 213 returnCode(ch); 214#endif 215 216 returnCode(OK); 217} 218 219#ifdef NCURSES_WGETCH_EVENTS 220NCURSES_EXPORT(int) 221wgetnstr(WINDOW *win, char *str, int maxlen) 222{ 223 returnCode(wgetnstr_events(win, 224 str, 225 maxlen, 226 EVENTLIST_1st((_nc_eventlist *) 0))); 227} 228#endif 229