get_wstr.c revision 1.1 1 /* $NetBSD: get_wstr.c,v 1.1 2007/01/21 11:38:59 blymn 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 (at) arl.wustl.edu,ruibiao (at) 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.1 2007/01/21 11:38:59 blymn Exp $");
40 #endif /* not lint */
41
42 #include "curses.h"
43 #include "curses_private.h"
44
45 /*
46 * getn_wstr --
47 * Get a string (of maximum n) characters from stdscr starting at
48 * (cury, curx).
49 */
50 int
51 getn_wstr(wchar_t *wstr, int n)
52 {
53 #ifndef HAVE_WCHAR
54 return ERR;
55 #else
56 return wgetn_wstr(stdscr, wstr, n);
57 #endif /* HAVE_WCHAR */
58 }
59
60 /*
61 * get_wstr --
62 * Get a string from stdscr starting at (cury, curx).
63 */
64 __warn_references(get_wstr,
65 "warning: this program uses get_wstr(), which is unsafe.")
66 int
67 get_wstr(wchar_t *wstr)
68 {
69 #ifndef HAVE_WCHAR
70 return ERR;
71 #else
72 return wget_wstr(stdscr, wstr);
73 #endif /* HAVE_WCHAR */
74 }
75
76 /*
77 * mvgetn_wstr --
78 * Get a string (of maximum n) characters from stdscr starting at (y, x).
79 */
80 int
81 mvgetn_wstr(int y, int x, wchar_t *wstr, int n)
82 {
83 #ifndef HAVE_WCHAR
84 return ERR;
85 #else
86 return mvwgetn_wstr(stdscr, y, x, wstr, n);
87 #endif /* HAVE_WCHAR */
88 }
89
90 /*
91 * mvget_wstr --
92 * Get a string from stdscr starting at (y, x).
93 */
94 __warn_references(mvget_wstr,
95 "warning: this program uses mvget_wstr(), which is unsafe.")
96 int
97 mvget_wstr(int y, int x, wchar_t *wstr)
98 {
99 #ifndef HAVE_WCHAR
100 return ERR;
101 #else
102 return mvwget_wstr(stdscr, y, x, wstr);
103 #endif /* HAVE_WCHAR */
104 }
105
106 /*
107 * mvwgetn_wstr --
108 * Get a string (of maximum n) characters from the given window starting
109 * at (y, x).
110 */
111 int
112 mvwgetn_wstr(WINDOW *win, int y, int x, wchar_t *wstr, int n)
113 {
114 #ifndef HAVE_WCHAR
115 return ERR;
116 #else
117 if (wmove(win, y, x) == ERR)
118 return ERR;
119
120 return wgetn_wstr(win, wstr, n);
121 #endif /* HAVE_WCHAR */
122 }
123
124 /*
125 * mvwget_wstr --
126 * Get a string from the given window starting at (y, x).
127 */
128 __warn_references(mvget_wstr,
129 "warning: this program uses mvget_wstr(), which is unsafe.")
130 int
131 mvwget_wstr(WINDOW *win, int y, int x, wchar_t *wstr)
132 {
133 #ifndef HAVE_WCHAR
134 return ERR;
135 #else
136 if (wmove(win, y, x) == ERR)
137 return ERR;
138
139 return wget_wstr(win, wstr);
140 #endif /* HAVE_WCHAR */
141 }
142
143 /*
144 * wget_wstr --
145 * Get a string starting at (cury, curx).
146 */
147 __warn_references(wget_wstr,
148 "warning: this program uses wget_wstr(), which is unsafe.")
149 int
150 wget_wstr(WINDOW *win, wchar_t *wstr)
151 {
152 #ifndef HAVE_WCHAR
153 return ERR;
154 #else
155 return __wgetn_wstr(win, wstr, -1);
156 #endif /* HAVE_WCHAR */
157 }
158
159 /*
160 * wgetn_wstr --
161 * Get a string starting at (cury, curx).
162 * Note that n < 2 means that we return ERR (SUSv2 specification).
163 */
164 int
165 wgetn_wstr(WINDOW *win, wchar_t *wstr, int n)
166 {
167 #ifndef HAVE_WCHAR
168 return ERR;
169 #else
170 if (n < 1)
171 return (ERR);
172 if (n == 1) {
173 wstr[0] = L'\0';
174 return (ERR);
175 }
176 return __wgetn_wstr(win, wstr, n);
177 #endif /* HAVE_WCHAR */
178 }
179
180 /*
181 * __wgetn_wstr --
182 * The actual implementation.
183 * Note that we include a trailing L'\0' for safety, so str will contain
184 * at most n - 1 other characters.
185 */
186 int
187 __wgetn_wstr(WINDOW *win, wchar_t *wstr, int n)
188 {
189 #ifndef HAVE_WCHAR
190 return ERR;
191 #else
192 wchar_t *ostr, ec, kc, sc[ 2 ];
193 int oldx, remain, ret;
194 wint_t wc;
195 cchar_t cc;
196
197 ostr = wstr;
198 if ( erasewchar( &ec ) == ERR )
199 return ERR;
200 if ( killwchar( &kc ) == ERR )
201 return ERR;
202 sc[ 0 ] = ( wchar_t )btowc( ' ' );
203 sc[ 1 ] = L'\0';
204 setcchar( &cc, sc, win->wattr, 0, NULL );
205 oldx = win->curx;
206 remain = n - 1;
207
208 while ((ret = wget_wch(win, &wc)) != ERR
209 && wc != L'\n' && wc != L'\r') {
210 #ifdef DEBUG
211 __CTRACE("__wgetn_wstr: win %p, char 0x%x, remain %d\n",
212 win, wc, remain);
213 #endif
214 *wstr = wc;
215 touchline(win, win->cury, 1);
216 if (wc == ec || wc == KEY_BACKSPACE || wc == KEY_LEFT) {
217 *wstr = L'\0';
218 if (wstr != ostr) {
219 if ((wchar_t)wc == ec) {
220 mvwadd_wch(win, win->cury,
221 win->curx, &cc);
222 wmove(win, win->cury, win->curx - 1);
223 }
224 if (wc == KEY_BACKSPACE || wc == KEY_LEFT) {
225 /* getch() displays the key sequence */
226 mvwadd_wch(win, win->cury,
227 win->curx - 1, &cc);
228 mvwadd_wch(win, win->cury,
229 win->curx - 2, &cc);
230 wmove(win, win->cury, win->curx - 1);
231 }
232 wstr--;
233 if (n != -1) {
234 /* We're counting chars */
235 remain++;
236 }
237 } else { /* str == ostr */
238 if (wc == KEY_BACKSPACE || wc == KEY_LEFT)
239 /* getch() displays the other keys */
240 mvwadd_wch(win, win->cury,
241 win->curx - 1, &cc);
242 wmove(win, win->cury, oldx);
243 }
244 } else if (wc == kc) {
245 *wstr = L'\0';
246 if (wstr != ostr) {
247 /* getch() displays the kill character */
248 mvwadd_wch(win, win->cury, win->curx - 1, &cc);
249 /* Clear the characters from screen and str */
250 while (wstr != ostr) {
251 mvwadd_wch(win, win->cury,
252 win->curx - 1, &cc);
253 wmove(win, win->cury, win->curx - 1);
254 wstr--;
255 if (n != -1)
256 /* We're counting chars */
257 remain++;
258 }
259 mvwadd_wch(win, win->cury, win->curx - 1, &cc);
260 wmove(win, win->cury, win->curx - 1);
261 } else
262 /* getch() displays the kill character */
263 mvwadd_wch( win, win->cury, oldx, &cc );
264 wmove(win, win->cury, oldx);
265 } else if (wc >= KEY_MIN && wc <= KEY_MAX) {
266 /* get_wch() displays these characters */
267 mvwadd_wch( win, win->cury, win->curx - 1, &cc );
268 wmove(win, win->cury, win->curx - 1);
269 } else {
270 if (remain) {
271 wstr++;
272 remain--;
273 } else {
274 mvwadd_wch(win, win->cury, win->curx - 1, &cc);
275 wmove(win, win->cury, win->curx - 1);
276 }
277 }
278 }
279
280 if (wc == ERR) {
281 *wstr = L'\0';
282 return ERR;
283 }
284 *wstr = L'\0';
285 return OK;
286 #endif /* HAVE_WCHAR */
287 }
288