Home | History | Annotate | Line # | Download | only in libcurses
get_wstr.c revision 1.3
      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 (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.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