Home | History | Annotate | Line # | Download | only in libcurses
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