1 /**************************************************************************** 2 * Copyright (c) 2002-2009,2011 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: Thomas E. Dickey * 31 ****************************************************************************/ 32 33 /* 34 ** lib_get_wstr.c 35 ** 36 ** The routine wgetn_wstr(). 37 ** 38 */ 39 40 #include <curses.priv.h> 41 42 MODULE_ID("$Id: lib_get_wstr.c,v 1.13 2011/10/22 16:31:35 tom Exp $") 43 44 static int 45 wadd_wint(WINDOW *win, wint_t *src) 46 { 47 cchar_t tmp; 48 wchar_t wch[2]; 49 50 wch[0] = (wchar_t) (*src); 51 wch[1] = 0; 52 setcchar(&tmp, wch, A_NORMAL, (short) 0, NULL); 53 return wadd_wch(win, &tmp); 54 } 55 56 /* 57 * This wipes out the last character, no matter whether it was a tab, control 58 * or other character, and handles reverse wraparound. 59 */ 60 static wint_t * 61 WipeOut(WINDOW *win, int y, int x, wint_t *first, wint_t *last, int echoed) 62 { 63 if (last > first) { 64 *--last = '\0'; 65 if (echoed) { 66 int y1 = win->_cury; 67 int x1 = win->_curx; 68 int n; 69 70 wmove(win, y, x); 71 for (n = 0; first[n] != 0; ++n) { 72 wadd_wint(win, first + n); 73 } 74 getyx(win, y, x); 75 while (win->_cury < y1 76 || (win->_cury == y1 && win->_curx < x1)) 77 waddch(win, (chtype) ' '); 78 79 wmove(win, y, x); 80 } 81 } 82 return last; 83 } 84 85 NCURSES_EXPORT(int) 86 wgetn_wstr(WINDOW *win, wint_t *str, int maxlen) 87 { 88 SCREEN *sp = _nc_screen_of(win); 89 TTY buf; 90 bool oldnl, oldecho, oldraw, oldcbreak; 91 wint_t erasec; 92 wint_t killc; 93 wint_t *oldstr = str; 94 wint_t *tmpstr = str; 95 wint_t ch; 96 int y, x, code; 97 98 T((T_CALLED("wgetn_wstr(%p,%p, %d)"), (void *) win, (void *) str, maxlen)); 99 100 if (!win) 101 returnCode(ERR); 102 103 _nc_get_tty_mode(&buf); 104 105 oldnl = sp->_nl; 106 oldecho = sp->_echo; 107 oldraw = sp->_raw; 108 oldcbreak = sp->_cbreak; 109 nl(); 110 noecho(); 111 noraw(); 112 cbreak(); 113 114 erasec = (wint_t) erasechar(); 115 killc = (wint_t) killchar(); 116 117 getyx(win, y, x); 118 119 if (is_wintouched(win) || (win->_flags & _HASMOVED)) 120 wrefresh(win); 121 122 while ((code = wget_wch(win, &ch)) != ERR) { 123 /* 124 * Map special characters into key-codes. 125 */ 126 if (ch == '\r') 127 ch = '\n'; 128 if (ch == '\n') { 129 code = KEY_CODE_YES; 130 ch = KEY_ENTER; 131 } 132 if (ch < KEY_MIN) { 133 if (ch == erasec) { 134 ch = KEY_BACKSPACE; 135 code = KEY_CODE_YES; 136 } 137 if (ch == killc) { 138 ch = KEY_EOL; 139 code = KEY_CODE_YES; 140 } 141 } 142 if (code == KEY_CODE_YES) { 143 /* 144 * Some terminals (the Wyse-50 is the most common) generate a \n 145 * from the down-arrow key. With this logic, it's the user's 146 * choice whether to set kcud=\n for wget_wch(); terminating 147 * *getn_wstr() with \n should work either way. 148 */ 149 if (ch == KEY_DOWN || ch == KEY_ENTER) { 150 if (oldecho == TRUE 151 && win->_cury == win->_maxy 152 && win->_scroll) 153 wechochar(win, (chtype) '\n'); 154 break; 155 } 156 if (ch == KEY_LEFT || ch == KEY_BACKSPACE) { 157 if (tmpstr > oldstr) { 158 tmpstr = WipeOut(win, y, x, oldstr, tmpstr, oldecho); 159 } 160 } else if (ch == KEY_EOL) { 161 while (tmpstr > oldstr) { 162 tmpstr = WipeOut(win, y, x, oldstr, tmpstr, oldecho); 163 } 164 } else { 165 beep(); 166 } 167 } else if (maxlen >= 0 && tmpstr - oldstr >= maxlen) { 168 beep(); 169 } else { 170 *tmpstr++ = ch; 171 *tmpstr = 0; 172 if (oldecho == TRUE) { 173 int oldy = win->_cury; 174 175 if (wadd_wint(win, tmpstr - 1) == ERR) { 176 /* 177 * We can't really use the lower-right corner for input, 178 * since it'll mess up bookkeeping for erases. 179 */ 180 win->_flags &= ~_WRAPPED; 181 waddch(win, (chtype) ' '); 182 tmpstr = WipeOut(win, y, x, oldstr, tmpstr, oldecho); 183 continue; 184 } else if (win->_flags & _WRAPPED) { 185 /* 186 * If the last waddch forced a wrap & scroll, adjust our 187 * reference point for erasures. 188 */ 189 if (win->_scroll 190 && oldy == win->_maxy 191 && win->_cury == win->_maxy) { 192 if (--y <= 0) { 193 y = 0; 194 } 195 } 196 win->_flags &= ~_WRAPPED; 197 } 198 wrefresh(win); 199 } 200 } 201 } 202 203 win->_curx = 0; 204 win->_flags &= ~_WRAPPED; 205 if (win->_cury < win->_maxy) 206 win->_cury++; 207 wrefresh(win); 208 209 /* Restore with a single I/O call, to fix minor asymmetry between 210 * raw/noraw, etc. 211 */ 212 sp->_nl = oldnl; 213 sp->_echo = oldecho; 214 sp->_raw = oldraw; 215 sp->_cbreak = oldcbreak; 216 217 (void) _nc_set_tty_mode(&buf); 218 219 *tmpstr = 0; 220 if (code == ERR) { 221 if (tmpstr == oldstr) { 222 *tmpstr++ = WEOF; 223 *tmpstr = 0; 224 } 225 returnCode(ERR); 226 } 227 228 T(("wgetn_wstr returns %s", _nc_viswibuf(oldstr))); 229 230 returnCode(OK); 231 } 232