1*0c3ae37fSLionel Sambuc /* $NetBSD: get_wch.c,v 1.10 2012/06/29 10:40:29 blymn Exp $ */
251ffecc1SBen Gras
351ffecc1SBen Gras /*
451ffecc1SBen Gras * Copyright (c) 2005 The NetBSD Foundation Inc.
551ffecc1SBen Gras * All rights reserved.
651ffecc1SBen Gras *
751ffecc1SBen Gras * This code is derived from code donated to the NetBSD Foundation
851ffecc1SBen Gras * by Ruibiao Qiu <ruibiao@arl.wustl.edu,ruibiao@gmail.com>.
951ffecc1SBen Gras *
1051ffecc1SBen Gras *
1151ffecc1SBen Gras * Redistribution and use in source and binary forms, with or without
1251ffecc1SBen Gras * modification, are permitted provided that the following conditions
1351ffecc1SBen Gras * are met:
1451ffecc1SBen Gras * 1. Redistributions of source code must retain the above copyright
1551ffecc1SBen Gras * notice, this list of conditions and the following disclaimer.
1651ffecc1SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
1751ffecc1SBen Gras * notice, this list of conditions and the following disclaimer in the
1851ffecc1SBen Gras * documentation and/or other materials provided with the distribution.
1951ffecc1SBen Gras * 3. Neither the name of the NetBSD Foundation nor the names of its
2051ffecc1SBen Gras * contributors may be used to endorse or promote products derived
2151ffecc1SBen Gras * from this software without specific prior written permission.
2251ffecc1SBen Gras *
2351ffecc1SBen Gras * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
2451ffecc1SBen Gras * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
2551ffecc1SBen Gras * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2651ffecc1SBen Gras * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2751ffecc1SBen Gras * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2851ffecc1SBen Gras * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2951ffecc1SBen Gras * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3051ffecc1SBen Gras * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3151ffecc1SBen Gras * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3251ffecc1SBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3351ffecc1SBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3451ffecc1SBen Gras * SUCH DAMAGE.
3551ffecc1SBen Gras */
3651ffecc1SBen Gras
3751ffecc1SBen Gras #include <sys/cdefs.h>
3851ffecc1SBen Gras #ifndef lint
39*0c3ae37fSLionel Sambuc __RCSID("$NetBSD: get_wch.c,v 1.10 2012/06/29 10:40:29 blymn Exp $");
4051ffecc1SBen Gras #endif /* not lint */
4151ffecc1SBen Gras
4251ffecc1SBen Gras #include <string.h>
4351ffecc1SBen Gras #include <stdlib.h>
4451ffecc1SBen Gras #include <unistd.h>
4551ffecc1SBen Gras #include <stdio.h>
4651ffecc1SBen Gras #include "curses.h"
4751ffecc1SBen Gras #include "curses_private.h"
4851ffecc1SBen Gras #include "keymap.h"
4951ffecc1SBen Gras
5051ffecc1SBen Gras #ifdef HAVE_WCHAR
5151ffecc1SBen Gras static short wstate; /* state of the wcinkey function */
5251ffecc1SBen Gras #endif /* HAVE_WCHAR */
5351ffecc1SBen Gras extern short state; /* storage declared in getch.c */
5451ffecc1SBen Gras
5551ffecc1SBen Gras /* prototypes for private functions */
5651ffecc1SBen Gras #ifdef HAVE_WCHAR
5751ffecc1SBen Gras static int inkey(wchar_t *wc, int to, int delay);
5851ffecc1SBen Gras #endif /* HAVE_WCHAR */
5951ffecc1SBen Gras
6051ffecc1SBen Gras #ifdef HAVE_WCHAR
6151ffecc1SBen Gras /*
6251ffecc1SBen Gras * __init_get_wch - initialise all the pointers & structures needed to make
6351ffecc1SBen Gras * get_wch work in keypad mode.
6451ffecc1SBen Gras *
6551ffecc1SBen Gras */
6651ffecc1SBen Gras void
__init_get_wch(SCREEN * screen)6751ffecc1SBen Gras __init_get_wch(SCREEN *screen)
6851ffecc1SBen Gras {
6951ffecc1SBen Gras wstate = INKEY_NORM;
70*0c3ae37fSLionel Sambuc memset( &screen->cbuf, 0, sizeof(screen->cbuf));
7151ffecc1SBen Gras screen->cbuf_head = screen->cbuf_tail = screen->cbuf_cur = 0;
7251ffecc1SBen Gras }
7351ffecc1SBen Gras #endif /* HAVE_WCHAR */
7451ffecc1SBen Gras
7551ffecc1SBen Gras
7651ffecc1SBen Gras #ifdef HAVE_WCHAR
7751ffecc1SBen Gras /*
7851ffecc1SBen Gras * inkey - do the work to process keyboard input, check for multi-key
7951ffecc1SBen Gras * sequences and return the appropriate symbol if we get a match.
8051ffecc1SBen Gras *
8151ffecc1SBen Gras */
8251ffecc1SBen Gras static int
inkey(wchar_t * wc,int to,int delay)8351ffecc1SBen Gras inkey(wchar_t *wc, int to, int delay)
8451ffecc1SBen Gras {
8551ffecc1SBen Gras wchar_t k = 0;
8651ffecc1SBen Gras int c, mapping, ret = 0;
8751ffecc1SBen Gras size_t mlen = 0;
8851ffecc1SBen Gras keymap_t *current = _cursesi_screen->base_keymap;
8951ffecc1SBen Gras FILE *infd = _cursesi_screen->infd;
9051ffecc1SBen Gras int *start = &_cursesi_screen->cbuf_head,
9151ffecc1SBen Gras *working = &_cursesi_screen->cbuf_cur,
9251ffecc1SBen Gras *end = &_cursesi_screen->cbuf_tail;
9351ffecc1SBen Gras char *inbuf = &_cursesi_screen->cbuf[ 0 ];
9451ffecc1SBen Gras
9551ffecc1SBen Gras #ifdef DEBUG
9651ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "inkey (%p, %d, %d)\n", wc, to, delay);
9751ffecc1SBen Gras #endif
9851ffecc1SBen Gras for (;;) { /* loop until we get a complete key sequence */
9951ffecc1SBen Gras if (wstate == INKEY_NORM) {
10051ffecc1SBen Gras if (delay && __timeout(delay) == ERR)
10151ffecc1SBen Gras return ERR;
10251ffecc1SBen Gras c = fgetc(infd);
10351ffecc1SBen Gras if (c == WEOF) {
10451ffecc1SBen Gras clearerr(infd);
10551ffecc1SBen Gras return ERR;
10651ffecc1SBen Gras }
10751ffecc1SBen Gras
10851ffecc1SBen Gras if (delay && (__notimeout() == ERR))
10951ffecc1SBen Gras return ERR;
11051ffecc1SBen Gras
11151ffecc1SBen Gras k = (wchar_t) c;
11251ffecc1SBen Gras #ifdef DEBUG
11351ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
11451ffecc1SBen Gras "inkey (wstate normal) got '%s'\n", unctrl(k));
11551ffecc1SBen Gras #endif
11651ffecc1SBen Gras
11751ffecc1SBen Gras inbuf[ *end ] = k;
11851ffecc1SBen Gras *end = ( *end + 1 ) % MAX_CBUF_SIZE;
11951ffecc1SBen Gras *working = *start;
12051ffecc1SBen Gras wstate = INKEY_ASSEMBLING; /* go to assembling state */
12151ffecc1SBen Gras #ifdef DEBUG
12251ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
12351ffecc1SBen Gras "inkey: NORM=>ASSEMBLING: start(%d), "
12451ffecc1SBen Gras "current(%d), end(%d)\n", *start, *working, *end);
12551ffecc1SBen Gras #endif /* DEBUG */
12651ffecc1SBen Gras } else if (wstate == INKEY_BACKOUT) {
12751ffecc1SBen Gras k = inbuf[*working];
12851ffecc1SBen Gras *working = ( *working + 1 ) % MAX_CBUF_SIZE;
12951ffecc1SBen Gras if (*working == *end) { /* see if run out of keys */
13051ffecc1SBen Gras /* if so, switch to assembling */
13151ffecc1SBen Gras wstate = INKEY_ASSEMBLING;
13251ffecc1SBen Gras #ifdef DEBUG
13351ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
13451ffecc1SBen Gras "inkey: BACKOUT=>ASSEMBLING, start(%d), "
13551ffecc1SBen Gras "current(%d), end(%d)\n",
13651ffecc1SBen Gras *start, *working, *end);
13751ffecc1SBen Gras #endif /* DEBUG */
13851ffecc1SBen Gras }
13951ffecc1SBen Gras } else if (wstate == INKEY_ASSEMBLING) {
14051ffecc1SBen Gras /* assembling a key sequence */
14151ffecc1SBen Gras if (delay) {
14251ffecc1SBen Gras if (__timeout(to ? (ESCDELAY / 100) : delay)
14351ffecc1SBen Gras == ERR)
14451ffecc1SBen Gras return ERR;
14551ffecc1SBen Gras } else {
14651ffecc1SBen Gras if (to && (__timeout(ESCDELAY / 100) == ERR))
14751ffecc1SBen Gras return ERR;
14851ffecc1SBen Gras }
14951ffecc1SBen Gras
15051ffecc1SBen Gras c = fgetc(infd);
15151ffecc1SBen Gras if (ferror(infd)) {
15251ffecc1SBen Gras clearerr(infd);
15351ffecc1SBen Gras return ERR;
15451ffecc1SBen Gras }
15551ffecc1SBen Gras
15651ffecc1SBen Gras if ((to || delay) && (__notimeout() == ERR))
15751ffecc1SBen Gras return ERR;
15851ffecc1SBen Gras
15951ffecc1SBen Gras k = (wchar_t) c;
16051ffecc1SBen Gras #ifdef DEBUG
16151ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
16251ffecc1SBen Gras "inkey (wstate assembling) got '%s'\n", unctrl(k));
16351ffecc1SBen Gras #endif /* DEBUG */
16451ffecc1SBen Gras if (feof(infd)) { /* inter-char T/O, start backout */
16551ffecc1SBen Gras clearerr(infd);
16651ffecc1SBen Gras if (*start == *end)
16751ffecc1SBen Gras /* no chars in the buffer, restart */
16851ffecc1SBen Gras continue;
16951ffecc1SBen Gras
17051ffecc1SBen Gras k = inbuf[*start];
17151ffecc1SBen Gras wstate = INKEY_TIMEOUT;
17251ffecc1SBen Gras #ifdef DEBUG
17351ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
17451ffecc1SBen Gras "inkey: ASSEMBLING=>TIMEOUT, start(%d), "
17551ffecc1SBen Gras "current(%d), end(%d)\n",
17651ffecc1SBen Gras *start, *working, *end);
17751ffecc1SBen Gras #endif /* DEBUG */
17851ffecc1SBen Gras } else {
17951ffecc1SBen Gras inbuf[ *end ] = k;
18051ffecc1SBen Gras *working = *end;
18151ffecc1SBen Gras *end = ( *end + 1 ) % MAX_CBUF_SIZE;
18251ffecc1SBen Gras #ifdef DEBUG
18351ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
18451ffecc1SBen Gras "inkey: ASSEMBLING: start(%d), "
18551ffecc1SBen Gras "current(%d), end(%d)",
18651ffecc1SBen Gras *start, *working, *end);
18751ffecc1SBen Gras #endif /* DEBUG */
18851ffecc1SBen Gras }
18951ffecc1SBen Gras } else if (wstate == INKEY_WCASSEMBLING) {
19051ffecc1SBen Gras /* assembling a wide-char sequence */
19151ffecc1SBen Gras if (delay) {
19251ffecc1SBen Gras if (__timeout(to ? (ESCDELAY / 100) : delay)
19351ffecc1SBen Gras == ERR)
19451ffecc1SBen Gras return ERR;
19551ffecc1SBen Gras } else {
19651ffecc1SBen Gras if (to && (__timeout(ESCDELAY / 100) == ERR))
19751ffecc1SBen Gras return ERR;
19851ffecc1SBen Gras }
19951ffecc1SBen Gras
20051ffecc1SBen Gras c = fgetc(infd);
20151ffecc1SBen Gras if (ferror(infd)) {
20251ffecc1SBen Gras clearerr(infd);
20351ffecc1SBen Gras return ERR;
20451ffecc1SBen Gras }
20551ffecc1SBen Gras
20651ffecc1SBen Gras if ((to || delay) && (__notimeout() == ERR))
20751ffecc1SBen Gras return ERR;
20851ffecc1SBen Gras
20951ffecc1SBen Gras k = (wchar_t) c;
21051ffecc1SBen Gras #ifdef DEBUG
21151ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
21251ffecc1SBen Gras "inkey (wstate wcassembling) got '%s'\n",
21351ffecc1SBen Gras unctrl(k));
21451ffecc1SBen Gras #endif
21551ffecc1SBen Gras if (feof(infd)) { /* inter-char T/O, start backout */
21651ffecc1SBen Gras clearerr(infd);
21751ffecc1SBen Gras if (*start == *end)
21851ffecc1SBen Gras /* no chars in the buffer, restart */
21951ffecc1SBen Gras continue;
22051ffecc1SBen Gras
22151ffecc1SBen Gras *wc = inbuf[*start];
22251ffecc1SBen Gras *working = *start
22351ffecc1SBen Gras = ( *start + 1 ) % MAX_CBUF_SIZE;
22451ffecc1SBen Gras if (*start == *end) {
22551ffecc1SBen Gras state = wstate = INKEY_NORM;
22651ffecc1SBen Gras #ifdef DEBUG
22751ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
22851ffecc1SBen Gras "inkey: WCASSEMBLING=>NORM, "
22951ffecc1SBen Gras "start(%d), current(%d), end(%d)",
23051ffecc1SBen Gras *start, *working, *end);
23151ffecc1SBen Gras #endif /* DEBUG */
23251ffecc1SBen Gras } else {
23351ffecc1SBen Gras state = wstate = INKEY_BACKOUT;
23451ffecc1SBen Gras #ifdef DEBUG
23551ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
23651ffecc1SBen Gras "inkey: WCASSEMBLING=>BACKOUT, "
23751ffecc1SBen Gras "start(%d), current(%d), end(%d)",
23851ffecc1SBen Gras *start, *working, *end);
23951ffecc1SBen Gras #endif /* DEBUG */
24051ffecc1SBen Gras }
24151ffecc1SBen Gras return OK;
24251ffecc1SBen Gras } else {
24351ffecc1SBen Gras /* assembling wide characters */
24451ffecc1SBen Gras inbuf[ *end ] = k;
24551ffecc1SBen Gras *working = *end;
24651ffecc1SBen Gras *end = ( *end + 1 ) % MAX_CBUF_SIZE;
24751ffecc1SBen Gras #ifdef DEBUG
24851ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
24951ffecc1SBen Gras "inkey: WCASSEMBLING[head(%d), "
25051ffecc1SBen Gras "urrent(%d), tail(%d)]\n",
25151ffecc1SBen Gras *start, *working, *end);
25251ffecc1SBen Gras #endif /* DEBUG */
25351ffecc1SBen Gras ret = (int) mbrtowc( wc, inbuf + (*working), 1,
25451ffecc1SBen Gras &_cursesi_screen->sp );
25551ffecc1SBen Gras #ifdef DEBUG
25651ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
25751ffecc1SBen Gras "inkey: mbrtowc returns %d, wc(%x)\n",
25851ffecc1SBen Gras ret, *wc );
25951ffecc1SBen Gras #endif /* DEBUG */
26051ffecc1SBen Gras if ( ret == -2 ) {
26151ffecc1SBen Gras *working = (*working + 1)
26251ffecc1SBen Gras % MAX_CBUF_SIZE;
26351ffecc1SBen Gras continue;
26451ffecc1SBen Gras }
26551ffecc1SBen Gras if ( ret == 0 )
26651ffecc1SBen Gras ret = 1;
26751ffecc1SBen Gras if ( ret == -1 ) {
26851ffecc1SBen Gras /* return the 1st character we know */
26951ffecc1SBen Gras *wc = inbuf[ *start ];
27051ffecc1SBen Gras *working = *start = ( *start + 1 ) % MAX_CBUF_SIZE;
27151ffecc1SBen Gras #ifdef DEBUG
27251ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
27351ffecc1SBen Gras "inkey: Invalid wide char(%x) "
27451ffecc1SBen Gras "[head(%d), current(%d), "
27551ffecc1SBen Gras "tail(%d)]\n",
27651ffecc1SBen Gras *wc, *start, *working, *end);
27751ffecc1SBen Gras #endif /* DEBUG */
27851ffecc1SBen Gras } else { /* > 0 */
27951ffecc1SBen Gras /* return the wide character */
28051ffecc1SBen Gras *start = *working
28151ffecc1SBen Gras = (*working + ret)%MAX_CBUF_SIZE;
28251ffecc1SBen Gras #ifdef DEBUG
28351ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
28451ffecc1SBen Gras "inkey: Wide char found(%x) "
28551ffecc1SBen Gras "[head(%d), current(%d), "
28651ffecc1SBen Gras "tail(%d)]\n",
28751ffecc1SBen Gras *wc, *start, *working, *end);
28851ffecc1SBen Gras #endif /* DEBUG */
28951ffecc1SBen Gras }
29051ffecc1SBen Gras
29151ffecc1SBen Gras if (*start == *end) { /* only one char processed */
29251ffecc1SBen Gras state = wstate = INKEY_NORM;
29351ffecc1SBen Gras #ifdef DEBUG
29451ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
29551ffecc1SBen Gras "inkey: WCASSEMBLING=>NORM, "
29651ffecc1SBen Gras "start(%d), current(%d), end(%d)",
29751ffecc1SBen Gras *start, *working, *end);
29851ffecc1SBen Gras #endif /* DEBUG */
29951ffecc1SBen Gras } else {
30051ffecc1SBen Gras /* otherwise we must have more than one char to backout */
30151ffecc1SBen Gras state = wstate = INKEY_BACKOUT;
30251ffecc1SBen Gras #ifdef DEBUG
30351ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
30451ffecc1SBen Gras "inkey: WCASSEMBLING=>BACKOUT, "
30551ffecc1SBen Gras "start(%d), current(%d), end(%d)",
30651ffecc1SBen Gras *start, *working, *end);
30751ffecc1SBen Gras #endif /* DEBUG */
30851ffecc1SBen Gras }
30951ffecc1SBen Gras return OK;
31051ffecc1SBen Gras }
31151ffecc1SBen Gras } else {
31251ffecc1SBen Gras fprintf(stderr, "Inkey wstate screwed - exiting!!!");
31351ffecc1SBen Gras exit(2);
31451ffecc1SBen Gras }
31551ffecc1SBen Gras
31651ffecc1SBen Gras /*
31751ffecc1SBen Gras * Check key has no special meaning and we have not
31851ffecc1SBen Gras * timed out and the key has not been disabled
31951ffecc1SBen Gras */
32051ffecc1SBen Gras mapping = current->mapping[k];
32151ffecc1SBen Gras if (((wstate == INKEY_TIMEOUT) || (mapping < 0))
32251ffecc1SBen Gras || ((current->key[mapping]->type
32351ffecc1SBen Gras == KEYMAP_LEAF)
32451ffecc1SBen Gras && (current->key[mapping]->enable == FALSE))) {
32551ffecc1SBen Gras /* wide-character specific code */
32651ffecc1SBen Gras #ifdef DEBUG
32751ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
32851ffecc1SBen Gras "inkey: Checking for wide char\n");
32951ffecc1SBen Gras #endif /* DEBUG */
33051ffecc1SBen Gras mbrtowc( NULL, NULL, 1, &_cursesi_screen->sp );
33151ffecc1SBen Gras *working = *start;
33251ffecc1SBen Gras mlen = *end > *working ?
33351ffecc1SBen Gras *end - *working : MAX_CBUF_SIZE - *working;
33451ffecc1SBen Gras if ( !mlen )
33551ffecc1SBen Gras return ERR;
33651ffecc1SBen Gras #ifdef DEBUG
33751ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
33851ffecc1SBen Gras "inkey: Check wide char[head(%d), "
33951ffecc1SBen Gras "current(%d), tail(%d), mlen(%ld)]\n",
34051ffecc1SBen Gras *start, *working, *end, (long) mlen);
34151ffecc1SBen Gras #endif /* DEBUG */
34251ffecc1SBen Gras ret = (int) mbrtowc( wc, inbuf + (*working), mlen,
34351ffecc1SBen Gras &_cursesi_screen->sp );
34451ffecc1SBen Gras #ifdef DEBUG
34551ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
34651ffecc1SBen Gras "inkey: mbrtowc returns %d, wc(%x)\n", ret, *wc);
34751ffecc1SBen Gras #endif /* DEBUG */
34851ffecc1SBen Gras if ( ret == -2 && *end < *working ) {
34951ffecc1SBen Gras /* second half of a wide character */
35051ffecc1SBen Gras *working = 0;
35151ffecc1SBen Gras mlen = *end;
35251ffecc1SBen Gras if ( mlen )
35351ffecc1SBen Gras ret = (int) mbrtowc( wc, inbuf, mlen,
35451ffecc1SBen Gras &_cursesi_screen->sp );
35551ffecc1SBen Gras }
35651ffecc1SBen Gras if ( ret == -2 && wstate != INKEY_TIMEOUT ) {
35751ffecc1SBen Gras *working = (*working + (int) mlen)
35851ffecc1SBen Gras % MAX_CBUF_SIZE;
35951ffecc1SBen Gras wstate = INKEY_WCASSEMBLING;
36051ffecc1SBen Gras continue;
36151ffecc1SBen Gras }
36251ffecc1SBen Gras if ( ret == 0 )
36351ffecc1SBen Gras ret = 1;
36451ffecc1SBen Gras if ( ret == -1 ) {
36551ffecc1SBen Gras /* return the first key we know about */
36651ffecc1SBen Gras *wc = inbuf[ *start ];
36751ffecc1SBen Gras *working = *start
36851ffecc1SBen Gras = ( *start + 1 ) % MAX_CBUF_SIZE;
36951ffecc1SBen Gras #ifdef DEBUG
37051ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
37151ffecc1SBen Gras "inkey: Invalid wide char(%x)[head(%d), "
37251ffecc1SBen Gras "current(%d), tail(%d)]\n",
37351ffecc1SBen Gras *wc, *start, *working, *end);
37451ffecc1SBen Gras #endif /* DEBUG */
37551ffecc1SBen Gras } else { /* > 0 */
37651ffecc1SBen Gras /* return the wide character */
37751ffecc1SBen Gras *start = *working
37851ffecc1SBen Gras = ( *working + ret ) % MAX_CBUF_SIZE;
37951ffecc1SBen Gras #ifdef DEBUG
38051ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
38151ffecc1SBen Gras "inkey: Wide char found(%x)[head(%d), "
38251ffecc1SBen Gras "current(%d), tail(%d)]\n",
38351ffecc1SBen Gras *wc, *start, *working, *end);
38451ffecc1SBen Gras #endif /* DEBUG */
38551ffecc1SBen Gras }
38651ffecc1SBen Gras
38751ffecc1SBen Gras if (*start == *end) { /* only one char processed */
38851ffecc1SBen Gras state = wstate = INKEY_NORM;
38951ffecc1SBen Gras #ifdef DEBUG
39051ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
39151ffecc1SBen Gras "inkey: Empty cbuf=>NORM, "
39251ffecc1SBen Gras "start(%d), current(%d), end(%d)\n",
39351ffecc1SBen Gras *start, *working, *end);
39451ffecc1SBen Gras #endif /* DEBUG */
39551ffecc1SBen Gras } else {
39651ffecc1SBen Gras /* otherwise we must have more than one char to backout */
39751ffecc1SBen Gras state = wstate = INKEY_BACKOUT;
39851ffecc1SBen Gras #ifdef DEBUG
39951ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
40051ffecc1SBen Gras "inkey: Non-empty cbuf=>BACKOUT, "
40151ffecc1SBen Gras "start(%d), current(%d), end(%d)\n",
40251ffecc1SBen Gras *start, *working, *end);
40351ffecc1SBen Gras #endif /* DEBUG */
40451ffecc1SBen Gras }
40551ffecc1SBen Gras return OK;
40651ffecc1SBen Gras } else { /* must be part of a multikey sequence */
40751ffecc1SBen Gras /* check for completed key sequence */
40851ffecc1SBen Gras if (current->key[current->mapping[k]]->type
40951ffecc1SBen Gras == KEYMAP_LEAF) {
41051ffecc1SBen Gras /* eat the key sequence in cbuf */
41151ffecc1SBen Gras *start = *working = ( *working + 1 ) % MAX_CBUF_SIZE;
41251ffecc1SBen Gras
41351ffecc1SBen Gras /* check if inbuf empty now */
41451ffecc1SBen Gras #ifdef DEBUG
41551ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
41651ffecc1SBen Gras "inkey: Key found(%s)\n",
41751ffecc1SBen Gras key_name(current->key[mapping]->value.symbol));
41851ffecc1SBen Gras #endif /* DEBUG */
41951ffecc1SBen Gras if (*start == *end) {
42051ffecc1SBen Gras /* if it is go back to normal */
42151ffecc1SBen Gras state = wstate = INKEY_NORM;
42251ffecc1SBen Gras #ifdef DEBUG
42351ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
42451ffecc1SBen Gras "[inkey]=>NORM, start(%d), "
42551ffecc1SBen Gras "current(%d), end(%d)",
42651ffecc1SBen Gras *start, *working, *end);
42751ffecc1SBen Gras #endif /* DEBUG */
42851ffecc1SBen Gras } else {
42951ffecc1SBen Gras /* otherwise go to backout state */
43051ffecc1SBen Gras state = wstate = INKEY_BACKOUT;
43151ffecc1SBen Gras #ifdef DEBUG
43251ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
43351ffecc1SBen Gras "[inkey]=>BACKOUT, start(%d), "
43451ffecc1SBen Gras "current(%d), end(%d)",
43551ffecc1SBen Gras *start, *working, *end );
43651ffecc1SBen Gras #endif /* DEBUG */
43751ffecc1SBen Gras }
43851ffecc1SBen Gras
43951ffecc1SBen Gras /* return the symbol */
44051ffecc1SBen Gras *wc = current->key[mapping]->value.symbol;
44151ffecc1SBen Gras return KEY_CODE_YES;
44251ffecc1SBen Gras } else {
44351ffecc1SBen Gras /* Step to next part of multi-key sequence */
44451ffecc1SBen Gras current = current->key[current->mapping[k]]->value.next;
44551ffecc1SBen Gras }
44651ffecc1SBen Gras }
44751ffecc1SBen Gras }
44851ffecc1SBen Gras }
44951ffecc1SBen Gras #endif /* HAVE_WCHAR */
45051ffecc1SBen Gras
45151ffecc1SBen Gras /*
45251ffecc1SBen Gras * get_wch --
45351ffecc1SBen Gras * Read in a wide character from stdscr.
45451ffecc1SBen Gras */
45551ffecc1SBen Gras int
get_wch(wint_t * ch)45651ffecc1SBen Gras get_wch(wint_t *ch)
45751ffecc1SBen Gras {
45851ffecc1SBen Gras #ifndef HAVE_WCHAR
45951ffecc1SBen Gras return ERR;
46051ffecc1SBen Gras #else
46151ffecc1SBen Gras return wget_wch(stdscr, ch);
46251ffecc1SBen Gras #endif /* HAVE_WCHAR */
46351ffecc1SBen Gras }
46451ffecc1SBen Gras
46551ffecc1SBen Gras /*
46651ffecc1SBen Gras * mvget_wch --
46751ffecc1SBen Gras * Read in a character from stdscr at the given location.
46851ffecc1SBen Gras */
46951ffecc1SBen Gras int
mvget_wch(int y,int x,wint_t * ch)47051ffecc1SBen Gras mvget_wch(int y, int x, wint_t *ch)
47151ffecc1SBen Gras {
47251ffecc1SBen Gras #ifndef HAVE_WCHAR
47351ffecc1SBen Gras return ERR;
47451ffecc1SBen Gras #else
47551ffecc1SBen Gras return mvwget_wch(stdscr, y, x, ch);
47651ffecc1SBen Gras #endif /* HAVE_WCHAR */
47751ffecc1SBen Gras }
47851ffecc1SBen Gras
47951ffecc1SBen Gras /*
48051ffecc1SBen Gras * mvwget_wch --
48151ffecc1SBen Gras * Read in a character from stdscr at the given location in the
48251ffecc1SBen Gras * given window.
48351ffecc1SBen Gras */
48451ffecc1SBen Gras int
mvwget_wch(WINDOW * win,int y,int x,wint_t * ch)48551ffecc1SBen Gras mvwget_wch(WINDOW *win, int y, int x, wint_t *ch)
48651ffecc1SBen Gras {
48751ffecc1SBen Gras #ifndef HAVE_WCHAR
48851ffecc1SBen Gras return ERR;
48951ffecc1SBen Gras #else
49051ffecc1SBen Gras if (wmove(win, y, x) == ERR)
49151ffecc1SBen Gras return ERR;
49251ffecc1SBen Gras
49351ffecc1SBen Gras return wget_wch(win, ch);
49451ffecc1SBen Gras #endif /* HAVE_WCHAR */
49551ffecc1SBen Gras }
49651ffecc1SBen Gras
49751ffecc1SBen Gras /*
49851ffecc1SBen Gras * wget_wch --
49951ffecc1SBen Gras * Read in a wide character from the window.
50051ffecc1SBen Gras */
50151ffecc1SBen Gras int
wget_wch(WINDOW * win,wint_t * ch)50251ffecc1SBen Gras wget_wch(WINDOW *win, wint_t *ch)
50351ffecc1SBen Gras {
50451ffecc1SBen Gras #ifndef HAVE_WCHAR
50551ffecc1SBen Gras return ERR;
50651ffecc1SBen Gras #else
50751ffecc1SBen Gras int ret, weset;
50851ffecc1SBen Gras int c;
50951ffecc1SBen Gras FILE *infd = _cursesi_screen->infd;
51051ffecc1SBen Gras cchar_t wc;
51151ffecc1SBen Gras wchar_t inp, ws[ 2 ];
51251ffecc1SBen Gras
51351ffecc1SBen Gras if (!(win->flags & __SCROLLOK) && (win->flags & __FULLWIN)
51451ffecc1SBen Gras && win->curx == win->maxx - 1
51551ffecc1SBen Gras && win->cury == win->maxy - 1
51651ffecc1SBen Gras && __echoit)
51751ffecc1SBen Gras return (ERR);
51851ffecc1SBen Gras
51951ffecc1SBen Gras if (is_wintouched(win))
52051ffecc1SBen Gras wrefresh(win);
52151ffecc1SBen Gras #ifdef DEBUG
52251ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "wget_wch: __echoit = %d, "
52351ffecc1SBen Gras "__rawmode = %d, __nl = %d, flags = %#.4x\n",
52451ffecc1SBen Gras __echoit, __rawmode, _cursesi_screen->nl, win->flags);
52551ffecc1SBen Gras #endif
52651ffecc1SBen Gras if (_cursesi_screen->resized) {
52751ffecc1SBen Gras _cursesi_screen->resized = 0;
52851ffecc1SBen Gras *ch = KEY_RESIZE;
52951ffecc1SBen Gras return KEY_CODE_YES;
53051ffecc1SBen Gras }
53151ffecc1SBen Gras if (_cursesi_screen->unget_pos) {
53251ffecc1SBen Gras #ifdef DEBUG
53351ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "wget_wch returning char at %d\n",
53451ffecc1SBen Gras _cursesi_screen->unget_pos);
53551ffecc1SBen Gras #endif
53651ffecc1SBen Gras _cursesi_screen->unget_pos--;
53751ffecc1SBen Gras *ch = _cursesi_screen->unget_list[_cursesi_screen->unget_pos];
53851ffecc1SBen Gras if (__echoit) {
53951ffecc1SBen Gras ws[0] = *ch, ws[1] = L'\0';
54051ffecc1SBen Gras setcchar(&wc, ws, win->wattr, 0, NULL);
54151ffecc1SBen Gras wadd_wch(win, &wc);
54251ffecc1SBen Gras }
54351ffecc1SBen Gras return KEY_CODE_YES;
54451ffecc1SBen Gras }
54551ffecc1SBen Gras if (__echoit && !__rawmode) {
54651ffecc1SBen Gras cbreak();
54751ffecc1SBen Gras weset = 1;
54851ffecc1SBen Gras } else
54951ffecc1SBen Gras weset = 0;
55051ffecc1SBen Gras
55151ffecc1SBen Gras __save_termios();
55251ffecc1SBen Gras
55351ffecc1SBen Gras if (win->flags & __KEYPAD) {
55451ffecc1SBen Gras switch (win->delay) {
55551ffecc1SBen Gras case -1:
55651ffecc1SBen Gras ret = inkey(&inp,
55751ffecc1SBen Gras win->flags & __NOTIMEOUT ? 0 : 1, 0);
55851ffecc1SBen Gras break;
55951ffecc1SBen Gras case 0:
56051ffecc1SBen Gras if (__nodelay() == ERR)
56151ffecc1SBen Gras return ERR;
56251ffecc1SBen Gras ret = inkey(&inp, 0, 0);
56351ffecc1SBen Gras break;
56451ffecc1SBen Gras default:
56551ffecc1SBen Gras ret = inkey(&inp,
56651ffecc1SBen Gras win->flags & __NOTIMEOUT ? 0 : 1,
56751ffecc1SBen Gras win->delay);
56851ffecc1SBen Gras break;
56951ffecc1SBen Gras }
57051ffecc1SBen Gras if ( ret == ERR )
57151ffecc1SBen Gras return ERR;
57251ffecc1SBen Gras } else {
57351ffecc1SBen Gras switch (win->delay) {
57451ffecc1SBen Gras case -1:
57551ffecc1SBen Gras break;
57651ffecc1SBen Gras case 0:
57751ffecc1SBen Gras if (__nodelay() == ERR)
57851ffecc1SBen Gras return ERR;
57951ffecc1SBen Gras break;
58051ffecc1SBen Gras default:
58151ffecc1SBen Gras if (__timeout(win->delay) == ERR)
58251ffecc1SBen Gras return ERR;
58351ffecc1SBen Gras break;
58451ffecc1SBen Gras }
58551ffecc1SBen Gras
58651ffecc1SBen Gras c = getwchar();
58751ffecc1SBen Gras if (feof(infd)) {
58851ffecc1SBen Gras clearerr(infd);
58951ffecc1SBen Gras __restore_termios();
59051ffecc1SBen Gras return ERR; /* we have timed out */
59151ffecc1SBen Gras }
59251ffecc1SBen Gras
59351ffecc1SBen Gras if (ferror(infd)) {
59451ffecc1SBen Gras clearerr(infd);
59551ffecc1SBen Gras return ERR;
59651ffecc1SBen Gras } else {
59751ffecc1SBen Gras ret = c;
59851ffecc1SBen Gras inp = c;
59951ffecc1SBen Gras }
60051ffecc1SBen Gras }
60151ffecc1SBen Gras #ifdef DEBUG
60251ffecc1SBen Gras if (inp > 255)
60351ffecc1SBen Gras /* we have a key symbol - treat it differently */
60451ffecc1SBen Gras /* XXXX perhaps __unctrl should be expanded to include
60551ffecc1SBen Gras * XXXX the keysyms in the table....
60651ffecc1SBen Gras */
60751ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "wget_wch assembled keysym 0x%x\n",
60851ffecc1SBen Gras inp);
60951ffecc1SBen Gras else
61051ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "wget_wch got '%s'\n", unctrl(inp));
61151ffecc1SBen Gras #endif
61251ffecc1SBen Gras if (win->delay > -1) {
61351ffecc1SBen Gras if (__delay() == ERR)
61451ffecc1SBen Gras return ERR;
61551ffecc1SBen Gras }
61651ffecc1SBen Gras
61751ffecc1SBen Gras __restore_termios();
61851ffecc1SBen Gras
61951ffecc1SBen Gras if (__echoit) {
62051ffecc1SBen Gras if ( ret == KEY_CODE_YES ) {
62151ffecc1SBen Gras /* handle [DEL], [BS], and [LEFT] */
62251ffecc1SBen Gras if ( win->curx &&
62351ffecc1SBen Gras ( inp == KEY_DC ||
62451ffecc1SBen Gras inp == KEY_BACKSPACE ||
62551ffecc1SBen Gras inp == KEY_LEFT )) {
62651ffecc1SBen Gras wmove( win, win->cury, win->curx - 1 );
62751ffecc1SBen Gras wdelch( win );
62851ffecc1SBen Gras }
62951ffecc1SBen Gras } else {
63051ffecc1SBen Gras ws[ 0 ] = inp, ws[ 1 ] = L'\0';
63151ffecc1SBen Gras setcchar( &wc, ws, win->wattr, 0, NULL );
63251ffecc1SBen Gras wadd_wch( win, &wc );
63351ffecc1SBen Gras }
63451ffecc1SBen Gras }
63551ffecc1SBen Gras
63651ffecc1SBen Gras if (weset)
63751ffecc1SBen Gras nocbreak();
63851ffecc1SBen Gras
63951ffecc1SBen Gras if (_cursesi_screen->nl && inp == 13)
64051ffecc1SBen Gras inp = 10;
64151ffecc1SBen Gras
64251ffecc1SBen Gras *ch = inp;
64351ffecc1SBen Gras
64451ffecc1SBen Gras if ( ret == KEY_CODE_YES )
64551ffecc1SBen Gras return KEY_CODE_YES;
64651ffecc1SBen Gras return ( inp < 0 ? ERR : OK );
64751ffecc1SBen Gras #endif /* HAVE_WCHAR */
64851ffecc1SBen Gras }
64951ffecc1SBen Gras
65051ffecc1SBen Gras /*
65151ffecc1SBen Gras * unget_wch --
65251ffecc1SBen Gras * Put the wide character back into the input queue.
65351ffecc1SBen Gras */
65451ffecc1SBen Gras int
unget_wch(const wchar_t c)65551ffecc1SBen Gras unget_wch(const wchar_t c)
65651ffecc1SBen Gras {
65751ffecc1SBen Gras return __unget((wint_t) c);
65851ffecc1SBen Gras }
659