Home | History | Annotate | Line # | Download | only in libcurses
get_wch.c revision 1.1
      1 /*   $NetBSD: get_wch.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_wch.c,v 1.1 2007/01/21 11:38:59 blymn Exp $");
     40 #endif						  /* not lint */
     41 
     42 #include <string.h>
     43 #include <stdlib.h>
     44 #include <unistd.h>
     45 #include <stdio.h>
     46 #include "curses.h"
     47 #include "curses_private.h"
     48 #include "keymap.h"
     49 
     50 static short   wstate;		  /* state of the wcinkey function */
     51 
     52 /* prototypes for private functions */
     53 static int inkey(wchar_t *wc, int to, int delay);
     54 
     55 /*
     56  * __init_get_wch - initialise all the pointers & structures needed to make
     57  * get_wch work in keypad mode.
     58  *
     59  */
     60 void
     61 __init_get_wch(SCREEN *screen)
     62 {
     63 #ifndef HAVE_WCHAR
     64 	return;
     65 #else
     66 	/* narrow character initialization */
     67 	__init_getch( screen );
     68 
     69 	/* wide character specific stuff */
     70 	wstate = INKEY_NORM;
     71 	memset( &screen->cbuf, 0, MAX_CBUF_SIZE * sizeof( int ));
     72 	screen->cbuf_head = screen->cbuf_tail = screen->cbuf_cur = 0;
     73 #endif /* HAVE_WCHAR */
     74 }
     75 
     76 
     77 /*
     78  * inkey - do the work to process keyboard input, check for multi-key
     79  * sequences and return the appropriate symbol if we get a match.
     80  *
     81  */
     82 
     83 int
     84 inkey(wchar_t *wc, int to, int delay)
     85 {
     86 #ifndef HAVE_WCHAR
     87 	return ERR;
     88 #else
     89 	wchar_t		 k = 0;
     90 	int		  c, mapping, ret = 0;
     91 	size_t	  mlen = 0;
     92 	keymap_t	*current = _cursesi_screen->base_keymap;
     93 	FILE		*infd = _cursesi_screen->infd;
     94 	int		 *start = &_cursesi_screen->cbuf_head,
     95 				*working = &_cursesi_screen->cbuf_cur,
     96 				*end = &_cursesi_screen->cbuf_tail;
     97 	char		*inbuf = &_cursesi_screen->cbuf[ 0 ];
     98 
     99 /*  int	ESCDELAY = 300;*/	/* Delay in ms between keys for esc seq's */
    100 	ESCDELAY = 300;
    101 
    102 	for (;;) { /* loop until we get a complete key sequence */
    103 		if (wstate == INKEY_NORM) {
    104 			if (delay && __timeout(delay) == ERR)
    105 				return ERR;
    106 			c = getchar();
    107 			if (_cursesi_screen->resized) {
    108 				if (c != WEOF) /* was -1 */
    109 					unget_wch(c);
    110 				_cursesi_screen->resized = 0;
    111 				clearerr(infd);
    112 				*wc = KEY_RESIZE;
    113 				return KEY_CODE_YES;
    114 			}
    115 			if (c == WEOF) {
    116 				clearerr(infd);
    117 				return ERR;
    118 			}
    119 
    120 			if (delay && (__notimeout() == ERR))
    121 				return ERR;
    122 
    123 			k = (wchar_t) c;
    124 #ifdef DEBUG
    125 			__CTRACE("inkey (wstate normal) got '%s'\n",
    126 				unctrl(k));
    127 #endif
    128 
    129 			inbuf[ *end ] = k;
    130 			*end = ( *end + 1 ) % MAX_CBUF_SIZE;
    131 			*working = *start;
    132 			wstate = INKEY_ASSEMBLING; /* go to assembling state */
    133 #ifdef DEBUG
    134 			__CTRACE("[inkey]NORM=>ASSEMBLING:start(%d),current(%d),end(%d)\n",
    135 				*start, *working, *end );
    136 #endif /* DEBUG */
    137 		} else if (wstate == INKEY_BACKOUT) {
    138 			k = inbuf[*working];
    139 			*working = ( *working + 1 ) % MAX_CBUF_SIZE;
    140 			if (*working == *end) {	/* see if run out of keys */
    141 				/* if so, switch to assembling */
    142 				wstate = INKEY_ASSEMBLING;
    143 #ifdef DEBUG
    144 				__CTRACE("[inkey]BACKOUT=>ASSEMBLING, start(%d),current(%d),end(%d)\n",
    145 						*start, *working, *end);
    146 #endif /* DEBUG */
    147 			}
    148 		} else if (wstate == INKEY_ASSEMBLING) {
    149 			/* assembling a key sequence */
    150 			if (delay) {
    151 				if (__timeout(to ? (ESCDELAY / 100) : delay)
    152 						== ERR)
    153 					return ERR;
    154 			} else {
    155 				if (to && (__timeout(ESCDELAY / 100) == ERR))
    156 					return ERR;
    157 			}
    158 
    159 			c = getchar();
    160 			if (_cursesi_screen->resized) {
    161 				if (c != -1)
    162 					unget_wch(c);
    163 				_cursesi_screen->resized = 0;
    164 				clearerr(infd);
    165 				*wc = KEY_RESIZE;
    166 				return KEY_CODE_YES;
    167 			}
    168 			if (ferror(infd)) {
    169 				clearerr(infd);
    170 				return ERR;
    171 			}
    172 
    173 			if ((to || delay) && (__notimeout() == ERR))
    174 				return ERR;
    175 
    176 			k = (wchar_t) c;
    177 #ifdef DEBUG
    178 			__CTRACE("inkey (wstate assembling) got '%s'\n",
    179 				unctrl(k));
    180 #endif /* DEBUG */
    181 			if (feof(infd)) { /* inter-char T/O, start backout */
    182 				clearerr(infd);
    183 				if (*start == *end)
    184 					/* no chars in the buffer, restart */
    185 					continue;
    186 
    187 				k = inbuf[*start];
    188 				wstate = INKEY_TIMEOUT;
    189 #ifdef DEBUG
    190 				__CTRACE("[inkey]ASSEMBLING=>TIMEOUT,start(%d),current(%d),end(%d)\n",
    191 					*start, *working, *end );
    192 #endif /* DEBUG */
    193 			} else {
    194 				inbuf[ *end ] = k;
    195 				*working = *end;
    196 				*end = ( *end + 1 ) % MAX_CBUF_SIZE;
    197 #ifdef DEBUG
    198 				__CTRACE("[inkey]ASSEMBLING:start(%d),current(%d),end(%d)",
    199 					*start, *working, *end );
    200 #endif /* DEBUG */
    201 			}
    202 		} else if (wstate == INKEY_WCASSEMBLING) {
    203 			/* assembling a wide char sequence */
    204 			if (delay) {
    205 				if (__timeout(to ? (ESCDELAY / 100) : delay)
    206 						== ERR)
    207 					return ERR;
    208 			} else {
    209 				if (to && (__timeout(ESCDELAY / 100) == ERR))
    210 					return ERR;
    211 			}
    212 
    213 			c = getchar();
    214 			if (_cursesi_screen->resized) {
    215 				if (c != -1)
    216 					unget_wch(c);
    217 				_cursesi_screen->resized = 0;
    218 				clearerr(infd);
    219 				*wc = KEY_RESIZE;
    220 				return KEY_CODE_YES;
    221 			}
    222 			if (ferror(infd)) {
    223 				clearerr(infd);
    224 				return ERR;
    225 			}
    226 
    227 			if ((to || delay) && (__notimeout() == ERR))
    228 				return ERR;
    229 
    230 			k = (wchar_t) c;
    231 #ifdef DEBUG
    232 			__CTRACE("inkey (wstate wcassembling) got '%s'\n",
    233 				unctrl(k));
    234 #endif
    235 			if (feof(infd)) { /* inter-char T/O, start backout */
    236 				clearerr(infd);
    237 				if (*start == *end)
    238 					/* no chars in the buffer, restart */
    239 					continue;
    240 
    241 				*wc = inbuf[*start];
    242 				*working = *start
    243 					= ( *start + 1 ) % MAX_CBUF_SIZE;
    244 				if (*start == *end) {
    245 					state = wstate = INKEY_NORM;
    246 #ifdef DEBUG
    247 					__CTRACE("[inkey]WCASSEMBLING=>NORM,start(%d),current(%d),end(%d)",
    248 						*start, *working, *end );
    249 #endif /* DEBUG */
    250 				} else {
    251 					state = wstate = INKEY_BACKOUT;
    252 #ifdef DEBUG
    253 					__CTRACE("[inkey]WCASSEMBLING=>BACKOUT,start(%d),current(%d),end(%d)",
    254 						*start, *working, *end );
    255 #endif /* DEBUG */
    256 				}
    257 				return OK;
    258 			} else {
    259 				/* assembling wide characters */
    260 				inbuf[ *end ] = k;
    261 				*working = *end;
    262 				*end = ( *end + 1 ) % MAX_CBUF_SIZE;
    263 #ifdef DEBUG
    264 				__CTRACE("[inkey]WCASSEMBLING[head(%d),current(%d),tail(%d)]\n",
    265 					*start, *working, *end );
    266 #endif /* DEBUG */
    267 				ret = mbrtowc( wc, inbuf + (*working), 1,
    268 					&_cursesi_screen->sp );
    269 #ifdef DEBUG
    270 				__CTRACE("[inkey]mbrtowc returns %d,wc(%x)\n",
    271 					ret, *wc );
    272 #endif /* DEBUG */
    273 				if ( ret == -2 ) {
    274 					*working = (*working + 1)
    275 						% MAX_CBUF_SIZE;
    276 					continue;
    277 				}
    278 				if ( ret == 0 )
    279 					ret = 1;
    280 				if ( ret == -1 ) {
    281 					/* return the 1st character we know */
    282 					*wc = inbuf[ *start ];
    283 					*working = *start = ( *start + 1 ) % MAX_CBUF_SIZE;
    284 #ifdef DEBUG
    285 					__CTRACE("[inkey]Invalid wide char(%x)[head(%d),current(%d),tail(%d)]\n",
    286 						*wc, *start, *working, *end );
    287 #endif /* DEBUG */
    288 				} else { /* > 0 */
    289 					/* return the wide character */
    290 					*start = *working
    291 					       = (*working + ret)%MAX_CBUF_SIZE;
    292 #ifdef DEBUG
    293 					__CTRACE("[inkey]Wide char found(%x)[head(%d),current(%d),tail(%d)]\n",
    294 						*wc, *start, *working, *end );
    295 #endif /* DEBUG */
    296 				}
    297 
    298 				if (*start == *end) {	/* only one char processed */
    299 					state = wstate = INKEY_NORM;
    300 #ifdef DEBUG
    301 					__CTRACE("[inkey]WCASSEMBLING=>NORM,start(%d),current(%d),end(%d)",
    302 						*start, *working, *end );
    303 #endif /* DEBUG */
    304 				} else {
    305 					/* otherwise we must have more than one char to backout */
    306 					state = wstate = INKEY_BACKOUT;
    307 #ifdef DEBUG
    308 					__CTRACE(
    309 						"[inkey]WCASSEMBLING=>BACKOUT,start(%d),current(%d),end(%d)",
    310 						*start, *working, *end );
    311 #endif /* DEBUG */
    312 				}
    313 				return OK;
    314 			}
    315 		} else {
    316 			fprintf(stderr, "Inkey wstate screwed - exiting!!!");
    317 			exit(2);
    318 		}
    319 
    320 		/*
    321 		 * Check key has no special meaning and we have not
    322 		 * timed out and the key has not been disabled
    323 		 */
    324 		mapping = current->mapping[k];
    325 		if (((wstate == INKEY_TIMEOUT) || (mapping < 0))
    326 				|| ((current->key[mapping]->type
    327 					== KEYMAP_LEAF)
    328 				&& (current->key[mapping]->enable == FALSE))) {
    329 			/* wide character specific code */
    330 #ifdef DEBUG
    331 			__CTRACE("[inkey]Checking for wide char\n" );
    332 #endif /* DEBUG */
    333 			mbrtowc( NULL, NULL, 1, &_cursesi_screen->sp );
    334 			*working = *start;
    335 			mlen = *end > *working ?
    336 				*end - *working : MAX_CBUF_SIZE - *working;
    337 			if ( !mlen )
    338 				return ERR;
    339 #ifdef DEBUG
    340 			__CTRACE("[inkey]Check wide char[head(%d),current(%d),tail(%d),mlen(%d)]\n",
    341 				*start, *working, *end, mlen );
    342 #endif /* DEBUG */
    343 			ret = mbrtowc( wc, inbuf + (*working), mlen,
    344 				&_cursesi_screen->sp );
    345 #ifdef DEBUG
    346 			__CTRACE("[inkey]mbrtowc returns %d, wc(%x)\n",
    347 				ret, *wc );
    348 #endif /* DEBUG */
    349 			if ( ret == -2 && *end < *working ) {
    350 				/* second half of a wide character */
    351 				*working = 0;
    352 				mlen = *end;
    353 				if ( mlen )
    354 					ret = mbrtowc( wc, inbuf, mlen,
    355 						&_cursesi_screen->sp );
    356 			}
    357 			if ( ret == -2 && wstate != INKEY_TIMEOUT ) {
    358 				*working = (*working + mlen) % MAX_CBUF_SIZE;
    359 				wstate = INKEY_WCASSEMBLING;
    360 				continue;
    361 			}
    362 			if ( ret == 0 )
    363 				ret = 1;
    364 			if ( ret == -1 ) {
    365 				/* return the first key we know about */
    366 				*wc = inbuf[ *start ];
    367 				*working = *start
    368 					= ( *start + 1 ) % MAX_CBUF_SIZE;
    369 #ifdef DEBUG
    370 				__CTRACE("[inkey]Invalid wide char(%x)[head(%d),current(%d),tail(%d)]\n",
    371 					*wc, *start, *working, *end );
    372 #endif /* DEBUG */
    373 			} else { /* > 0 */
    374 				/* return the wide character */
    375 				*start = *working
    376 					= ( *working + ret ) % MAX_CBUF_SIZE;
    377 #ifdef DEBUG
    378 				__CTRACE("[inkey]Wide char found(%x)[head(%d),current(%d),tail(%d)]\n",
    379 					*wc, *start, *working, *end );
    380 #endif /* DEBUG */
    381 			}
    382 
    383 			if (*start == *end) {	/* only one char processed */
    384 				state = wstate = INKEY_NORM;
    385 #ifdef DEBUG
    386 				__CTRACE("[inkey]Empty cbuf=>NORM,start(%d),current(%d),end(%d)\n",
    387 					*start, *working, *end );
    388 #endif /* DEBUG */
    389 			} else {
    390 				/* otherwise we must have more than one char to backout */
    391 				state = wstate = INKEY_BACKOUT;
    392 #ifdef DEBUG
    393 				__CTRACE("[inkey]Non-empty cbuf=>BACKOUT,start(%d),current(%d),end(%d)\n",
    394 					*start, *working, *end );
    395 #endif /* DEBUG */
    396 			}
    397 			return OK;
    398 		} else {	/* must be part of a multikey sequence */
    399 					/* check for completed key sequence */
    400 			if (current->key[current->mapping[k]]->type
    401 					== KEYMAP_LEAF) {
    402 				/* eat the key sequence in cbuf */
    403 				*start = *working = ( *working + 1 ) % MAX_CBUF_SIZE;
    404 
    405 				/* check if inbuf empty now */
    406 #ifdef DEBUG
    407 				__CTRACE("[inkey]Key found(%s)\n",
    408 					key_name( current->key[mapping]->value.symbol ));
    409 #endif /* DEBUG */
    410 				if (*start == *end) {
    411 					/* if it is go back to normal */
    412 					state = wstate = INKEY_NORM;
    413 #ifdef DEBUG
    414 					__CTRACE("[inkey]=>NORM,start(%d),current(%d),end(%d)",
    415 						*start, *working, *end );
    416 #endif /* DEBUG */
    417 				} else {
    418 					/* otherwise go to backout state */
    419 					state = wstate = INKEY_BACKOUT;
    420 #ifdef DEBUG
    421 					__CTRACE("[inkey]=>BACKOUT,start(%d),current(%d),end(%d)",
    422 						*start, *working, *end );
    423 #endif /* DEBUG */
    424 				}
    425 
    426 				/* return the symbol */
    427 				*wc = current->key[mapping]->value.symbol;
    428 				return KEY_CODE_YES;
    429 			} else {
    430 				/* Step to next part of multi-key sequence */
    431 				current = current->key[current->mapping[k]]->value.next;
    432 			}
    433 		}
    434 	}
    435 #endif /* HAVE_WCHAR */
    436 }
    437 
    438 /*
    439  * get_wch --
    440  *	Read in a wide character from stdscr.
    441  */
    442 int
    443 get_wch(wint_t *ch)
    444 {
    445 #ifndef HAVE_WCHAR
    446 	return ERR;
    447 #else
    448 	return wget_wch(stdscr, ch);
    449 #endif /* HAVE_WCHAR */
    450 }
    451 
    452 /*
    453  * mvget_wch --
    454  *	  Read in a character from stdscr at the given location.
    455  */
    456 int
    457 mvget_wch(int y, int x, wint_t *ch)
    458 {
    459 #ifndef HAVE_WCHAR
    460 	return ERR;
    461 #else
    462 	return mvwget_wch(stdscr, y, x, ch);
    463 #endif /* HAVE_WCHAR */
    464 }
    465 
    466 /*
    467  * mvwget_wch --
    468  *	  Read in a character from stdscr at the given location in the
    469  *	  given window.
    470  */
    471 int
    472 mvwget_wch(WINDOW *win, int y, int x, wint_t *ch)
    473 {
    474 #ifndef HAVE_WCHAR
    475 	return ERR;
    476 #else
    477 	if (wmove(win, y, x) == ERR)
    478 		return ERR;
    479 
    480 	return wget_wch(win, ch);
    481 #endif /* HAVE_WCHAR */
    482 }
    483 
    484 /*
    485  * wget_wch --
    486  *	Read in a wide character from the window.
    487  */
    488 int
    489 wget_wch(WINDOW *win, wint_t *ch)
    490 {
    491 #ifndef HAVE_WCHAR
    492 	return ERR;
    493 #else
    494 	int ret, weset;
    495 	int c;
    496 	FILE *infd = _cursesi_screen->infd;
    497 	cchar_t wc;
    498 	wchar_t inp, ws[ 2 ];
    499 
    500 	if (!(win->flags & __SCROLLOK) && (win->flags & __FULLWIN)
    501 			&& win->curx == win->maxx - 1
    502 			&& win->cury == win->maxy - 1
    503 			&& __echoit)
    504 		return (ERR);
    505 
    506 	if (is_wintouched(win))
    507 		wrefresh(win);
    508 #ifdef DEBUG
    509 	__CTRACE("wget_wch: __echoit = %d, __rawmode = %d, __nl = %d, flags = %#.4x\n",
    510 		__echoit, __rawmode, _cursesi_screen->nl, win->flags);
    511 #endif
    512 	if (__echoit && !__rawmode) {
    513 		cbreak();
    514 		weset = 1;
    515 	} else
    516 		weset = 0;
    517 
    518 	__save_termios();
    519 
    520 	if (win->flags & __KEYPAD) {
    521 		switch (win->delay) {
    522 			case -1:
    523 				ret = inkey(&inp,
    524 					win->flags & __NOTIMEOUT ? 0 : 1, 0);
    525 				break;
    526 			case 0:
    527 				if (__nodelay() == ERR) {
    528 					__restore_termios();
    529 					return ERR;
    530 				}
    531 				ret = inkey(&inp, 0, 0);
    532 				break;
    533 			default:
    534 				ret = inkey(&inp,
    535 					win->flags & __NOTIMEOUT ? 0 : 1,
    536 					win->delay);
    537 				break;
    538 		}
    539 		if ( ret == ERR )
    540 			return ERR;
    541 	} else {
    542 		switch (win->delay) {
    543 			case -1:
    544 				break;
    545 			case 0:
    546 				if (__nodelay() == ERR) {
    547 					__restore_termios();
    548 					return ERR;
    549 				}
    550 				break;
    551 			default:
    552 				if (__timeout(win->delay) == ERR) {
    553 					__restore_termios();
    554 					return ERR;
    555 				}
    556 				break;
    557 		}
    558 
    559 		c = getwchar();
    560 		if (_cursesi_screen->resized) {
    561 			if (c != -1)
    562 				unget_wch(c);
    563 			_cursesi_screen->resized = 0;
    564 			clearerr(infd);
    565 			__restore_termios();
    566 			*ch = KEY_RESIZE;
    567 			return KEY_CODE_YES;
    568 		}
    569 		if (feof(infd)) {
    570 			clearerr(infd);
    571 			__restore_termios();
    572 			return ERR;	/* we have timed out */
    573 		}
    574 
    575 		if (ferror(infd)) {
    576 			clearerr(infd);
    577 			return ERR;
    578 		} else {
    579             ret = c;
    580 			inp = c;
    581 		}
    582 	}
    583 #ifdef DEBUG
    584 	if (inp > 255)
    585 		/* we have a key symbol - treat it differently */
    586 		/* XXXX perhaps __unctrl should be expanded to include
    587 		 * XXXX the keysyms in the table....
    588 		 */
    589 		__CTRACE("wget_wch assembled keysym 0x%x\n", inp);
    590 	else
    591 		__CTRACE("wget_wch got '%s'\n", unctrl(inp));
    592 #endif
    593 	if (win->delay > -1) {
    594 		if (__delay() == ERR) {
    595 			__restore_termios();
    596 			return ERR;
    597 		}
    598 	}
    599 
    600 	__restore_termios();
    601 
    602 	if (__echoit) {
    603 		if ( ret == KEY_CODE_YES ) {
    604 			/* handle [DEL], [BS], and [LEFT] */
    605 			if ( win->curx &&
    606 					( inp == KEY_DC ||
    607 					  inp == KEY_BACKSPACE ||
    608 					  inp == KEY_LEFT )) {
    609 				wmove( win, win->cury, win->curx - 1 );
    610 				wdelch( win );
    611 			}
    612 		} else {
    613 			ws[ 0 ] = inp, ws[ 1 ] = L'\0';
    614 			setcchar( &wc, ws, win->wattr, 0, NULL );
    615 			wadd_wch( win, &wc );
    616 		}
    617 	}
    618 
    619 	if (weset)
    620 		nocbreak();
    621 
    622 	if (_cursesi_screen->nl && inp == 13)
    623 		inp = 10;
    624 
    625 	*ch = inp;
    626 
    627 	if ( ret == KEY_CODE_YES )
    628 		return KEY_CODE_YES;
    629 	return ( inp < 0 ? ERR : OK );
    630 #endif /* HAVE_WCHAR */
    631 }
    632 
    633 /*
    634  * unget_wch --
    635  *	 Put the wide character back into the input queue.
    636  */
    637 int
    638 unget_wch(const wchar_t c)
    639 {
    640 	return
    641 		( int )((ungetwc((wint_t)c, _cursesi_screen->infd) == WEOF) ?
    642 				ERR : OK);
    643 }
    644