1 /* $NetBSD: get_wstr.c,v 1.3 2008/04/14 20:33:59 jdc Exp $ */ 2 3 /* 4 * Copyright (c) 2005 The NetBSD Foundation Inc. 5 * All rights reserved. 6 * 7 * This code is derived from code donated to the NetBSD Foundation 8 * by Ruibiao Qiu <ruibiao@arl.wustl.edu,ruibiao@gmail.com>. 9 * 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the NetBSD Foundation nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 24 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #include <sys/cdefs.h> 38 #ifndef lint 39 __RCSID("$NetBSD: get_wstr.c,v 1.3 2008/04/14 20:33:59 jdc Exp $"); 40 #endif /* not lint */ 41 42 #include "curses.h" 43 #include "curses_private.h" 44 45 /* prototypes for private functions */ 46 #ifdef HAVE_WCHAR 47 static int __wgetn_wstr(WINDOW *, wchar_t *, int); 48 #endif /* HAVE_WCHAR */ 49 50 /* 51 * getn_wstr -- 52 * Get a string (of maximum n) characters from stdscr starting at 53 * (cury, curx). 54 */ 55 int 56 getn_wstr(wchar_t *wstr, int n) 57 { 58 #ifndef HAVE_WCHAR 59 return ERR; 60 #else 61 return wgetn_wstr(stdscr, wstr, n); 62 #endif /* HAVE_WCHAR */ 63 } 64 65 /* 66 * get_wstr -- 67 * Get a string from stdscr starting at (cury, curx). 68 */ 69 __warn_references(get_wstr, 70 "warning: this program uses get_wstr(), which is unsafe.") 71 int 72 get_wstr(wchar_t *wstr) 73 { 74 #ifndef HAVE_WCHAR 75 return ERR; 76 #else 77 return wget_wstr(stdscr, wstr); 78 #endif /* HAVE_WCHAR */ 79 } 80 81 /* 82 * mvgetn_wstr -- 83 * Get a string (of maximum n) characters from stdscr starting at (y, x). 84 */ 85 int 86 mvgetn_wstr(int y, int x, wchar_t *wstr, int n) 87 { 88 #ifndef HAVE_WCHAR 89 return ERR; 90 #else 91 return mvwgetn_wstr(stdscr, y, x, wstr, n); 92 #endif /* HAVE_WCHAR */ 93 } 94 95 /* 96 * mvget_wstr -- 97 * Get a string from stdscr starting at (y, x). 98 */ 99 __warn_references(mvget_wstr, 100 "warning: this program uses mvget_wstr(), which is unsafe.") 101 int 102 mvget_wstr(int y, int x, wchar_t *wstr) 103 { 104 #ifndef HAVE_WCHAR 105 return ERR; 106 #else 107 return mvwget_wstr(stdscr, y, x, wstr); 108 #endif /* HAVE_WCHAR */ 109 } 110 111 /* 112 * mvwgetn_wstr -- 113 * Get a string (of maximum n) characters from the given window starting 114 * at (y, x). 115 */ 116 int 117 mvwgetn_wstr(WINDOW *win, int y, int x, wchar_t *wstr, int n) 118 { 119 #ifndef HAVE_WCHAR 120 return ERR; 121 #else 122 if (wmove(win, y, x) == ERR) 123 return ERR; 124 125 return wgetn_wstr(win, wstr, n); 126 #endif /* HAVE_WCHAR */ 127 } 128 129 /* 130 * mvwget_wstr -- 131 * Get a string from the given window starting at (y, x). 132 */ 133 __warn_references(mvget_wstr, 134 "warning: this program uses mvget_wstr(), which is unsafe.") 135 int 136 mvwget_wstr(WINDOW *win, int y, int x, wchar_t *wstr) 137 { 138 #ifndef HAVE_WCHAR 139 return ERR; 140 #else 141 if (wmove(win, y, x) == ERR) 142 return ERR; 143 144 return wget_wstr(win, wstr); 145 #endif /* HAVE_WCHAR */ 146 } 147 148 /* 149 * wget_wstr -- 150 * Get a string starting at (cury, curx). 151 */ 152 __warn_references(wget_wstr, 153 "warning: this program uses wget_wstr(), which is unsafe.") 154 int 155 wget_wstr(WINDOW *win, wchar_t *wstr) 156 { 157 #ifndef HAVE_WCHAR 158 return ERR; 159 #else 160 return __wgetn_wstr(win, wstr, -1); 161 #endif /* HAVE_WCHAR */ 162 } 163 164 /* 165 * wgetn_wstr -- 166 * Get a string starting at (cury, curx). 167 * Note that n < 2 means that we return ERR (SUSv2 specification). 168 */ 169 int 170 wgetn_wstr(WINDOW *win, wchar_t *wstr, int n) 171 { 172 #ifndef HAVE_WCHAR 173 return ERR; 174 #else 175 if (n < 1) 176 return (ERR); 177 if (n == 1) { 178 wstr[0] = L'\0'; 179 return (ERR); 180 } 181 return __wgetn_wstr(win, wstr, n); 182 #endif /* HAVE_WCHAR */ 183 } 184 185 #ifdef HAVE_WCHAR 186 /* 187 * __wgetn_wstr -- 188 * The actual implementation. 189 * Note that we include a trailing L'\0' for safety, so str will contain 190 * at most n - 1 other characters. 191 */ 192 int 193 __wgetn_wstr(WINDOW *win, wchar_t *wstr, int n) 194 { 195 wchar_t *ostr, ec, kc, sc[ 2 ]; 196 int oldx, remain; 197 wint_t wc; 198 cchar_t cc; 199 200 ostr = wstr; 201 if ( erasewchar( &ec ) == ERR ) 202 return ERR; 203 if ( killwchar( &kc ) == ERR ) 204 return ERR; 205 sc[ 0 ] = ( wchar_t )btowc( ' ' ); 206 sc[ 1 ] = L'\0'; 207 setcchar( &cc, sc, win->wattr, 0, NULL ); 208 oldx = win->curx; 209 remain = n - 1; 210 211 while (wget_wch(win, &wc) != ERR 212 && wc != L'\n' && wc != L'\r') { 213 #ifdef DEBUG 214 __CTRACE(__CTRACE_INPUT, 215 "__wgetn_wstr: win %p, char 0x%x, remain %d\n", 216 win, wc, remain); 217 #endif 218 *wstr = wc; 219 touchline(win, win->cury, 1); 220 if (wc == ec || wc == KEY_BACKSPACE || wc == KEY_LEFT) { 221 *wstr = L'\0'; 222 if (wstr != ostr) { 223 if ((wchar_t)wc == ec) { 224 mvwadd_wch(win, win->cury, 225 win->curx, &cc); 226 wmove(win, win->cury, win->curx - 1); 227 } 228 if (wc == KEY_BACKSPACE || wc == KEY_LEFT) { 229 /* getch() displays the key sequence */ 230 mvwadd_wch(win, win->cury, 231 win->curx - 1, &cc); 232 mvwadd_wch(win, win->cury, 233 win->curx - 2, &cc); 234 wmove(win, win->cury, win->curx - 1); 235 } 236 wstr--; 237 if (n != -1) { 238 /* We're counting chars */ 239 remain++; 240 } 241 } else { /* str == ostr */ 242 if (wc == KEY_BACKSPACE || wc == KEY_LEFT) 243 /* getch() displays the other keys */ 244 mvwadd_wch(win, win->cury, 245 win->curx - 1, &cc); 246 wmove(win, win->cury, oldx); 247 } 248 } else if (wc == kc) { 249 *wstr = L'\0'; 250 if (wstr != ostr) { 251 /* getch() displays the kill character */ 252 mvwadd_wch(win, win->cury, win->curx - 1, &cc); 253 /* Clear the characters from screen and str */ 254 while (wstr != ostr) { 255 mvwadd_wch(win, win->cury, 256 win->curx - 1, &cc); 257 wmove(win, win->cury, win->curx - 1); 258 wstr--; 259 if (n != -1) 260 /* We're counting chars */ 261 remain++; 262 } 263 mvwadd_wch(win, win->cury, win->curx - 1, &cc); 264 wmove(win, win->cury, win->curx - 1); 265 } else 266 /* getch() displays the kill character */ 267 mvwadd_wch( win, win->cury, oldx, &cc ); 268 wmove(win, win->cury, oldx); 269 } else if (wc >= KEY_MIN && wc <= KEY_MAX) { 270 /* get_wch() displays these characters */ 271 mvwadd_wch( win, win->cury, win->curx - 1, &cc ); 272 wmove(win, win->cury, win->curx - 1); 273 } else { 274 if (remain) { 275 wstr++; 276 remain--; 277 } else { 278 mvwadd_wch(win, win->cury, win->curx - 1, &cc); 279 wmove(win, win->cury, win->curx - 1); 280 } 281 } 282 } 283 284 if (wc == ERR) { 285 *wstr = L'\0'; 286 return ERR; 287 } 288 *wstr = L'\0'; 289 return OK; 290 } 291 #endif /* HAVE_WCHAR */ 292