1 1.28 blymn /* $NetBSD: get_wch.c,v 1.28 2024/12/23 02:58:03 blymn Exp $ */ 2 1.1 blymn 3 1.1 blymn /* 4 1.1 blymn * Copyright (c) 2005 The NetBSD Foundation Inc. 5 1.1 blymn * All rights reserved. 6 1.1 blymn * 7 1.1 blymn * This code is derived from code donated to the NetBSD Foundation 8 1.1 blymn * by Ruibiao Qiu <ruibiao (at) arl.wustl.edu,ruibiao (at) gmail.com>. 9 1.1 blymn * 10 1.1 blymn * 11 1.1 blymn * Redistribution and use in source and binary forms, with or without 12 1.1 blymn * modification, are permitted provided that the following conditions 13 1.1 blymn * are met: 14 1.1 blymn * 1. Redistributions of source code must retain the above copyright 15 1.1 blymn * notice, this list of conditions and the following disclaimer. 16 1.1 blymn * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 blymn * notice, this list of conditions and the following disclaimer in the 18 1.1 blymn * documentation and/or other materials provided with the distribution. 19 1.1 blymn * 3. Neither the name of the NetBSD Foundation nor the names of its 20 1.1 blymn * contributors may be used to endorse or promote products derived 21 1.1 blymn * from this software without specific prior written permission. 22 1.1 blymn * 23 1.1 blymn * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 24 1.1 blymn * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 25 1.1 blymn * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 26 1.1 blymn * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 1.1 blymn * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 1.1 blymn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 1.1 blymn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 1.1 blymn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 1.1 blymn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 1.1 blymn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 1.1 blymn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 1.1 blymn * SUCH DAMAGE. 35 1.1 blymn */ 36 1.1 blymn 37 1.1 blymn #include <sys/cdefs.h> 38 1.1 blymn #ifndef lint 39 1.28 blymn __RCSID("$NetBSD: get_wch.c,v 1.28 2024/12/23 02:58:03 blymn Exp $"); 40 1.1 blymn #endif /* not lint */ 41 1.1 blymn 42 1.15 rin #include <errno.h> 43 1.1 blymn #include <string.h> 44 1.1 blymn #include <stdlib.h> 45 1.1 blymn #include <unistd.h> 46 1.1 blymn #include <stdio.h> 47 1.1 blymn #include "curses.h" 48 1.1 blymn #include "curses_private.h" 49 1.1 blymn #include "keymap.h" 50 1.1 blymn 51 1.21 rin static short wstate; /* state of the wcinkey function */ 52 1.21 rin extern short _cursesi_state; /* storage declared in getch.c */ 53 1.1 blymn 54 1.1 blymn /* prototypes for private functions */ 55 1.1 blymn static int inkey(wchar_t *wc, int to, int delay); 56 1.17 roy static wint_t __fgetwc_resize(FILE *infd, bool *resized); 57 1.1 blymn 58 1.1 blymn /* 59 1.1 blymn * __init_get_wch - initialise all the pointers & structures needed to make 60 1.1 blymn * get_wch work in keypad mode. 61 1.1 blymn * 62 1.1 blymn */ 63 1.1 blymn void 64 1.1 blymn __init_get_wch(SCREEN *screen) 65 1.1 blymn { 66 1.1 blymn wstate = INKEY_NORM; 67 1.12 roy memset(&screen->cbuf, 0, sizeof(screen->cbuf)); 68 1.1 blymn screen->cbuf_head = screen->cbuf_tail = screen->cbuf_cur = 0; 69 1.6 jdc } 70 1.1 blymn 71 1.1 blymn 72 1.1 blymn /* 73 1.1 blymn * inkey - do the work to process keyboard input, check for multi-key 74 1.1 blymn * sequences and return the appropriate symbol if we get a match. 75 1.1 blymn * 76 1.1 blymn */ 77 1.6 jdc static int 78 1.1 blymn inkey(wchar_t *wc, int to, int delay) 79 1.1 blymn { 80 1.1 blymn wchar_t k = 0; 81 1.12 roy int c, mapping, ret = 0; 82 1.1 blymn size_t mlen = 0; 83 1.1 blymn keymap_t *current = _cursesi_screen->base_keymap; 84 1.1 blymn FILE *infd = _cursesi_screen->infd; 85 1.1 blymn int *start = &_cursesi_screen->cbuf_head, 86 1.1 blymn *working = &_cursesi_screen->cbuf_cur, 87 1.1 blymn *end = &_cursesi_screen->cbuf_tail; 88 1.1 blymn char *inbuf = &_cursesi_screen->cbuf[ 0 ]; 89 1.1 blymn 90 1.5 jdc __CTRACE(__CTRACE_INPUT, "inkey (%p, %d, %d)\n", wc, to, delay); 91 1.1 blymn for (;;) { /* loop until we get a complete key sequence */ 92 1.1 blymn if (wstate == INKEY_NORM) { 93 1.1 blymn if (delay && __timeout(delay) == ERR) 94 1.1 blymn return ERR; 95 1.17 roy c = __fgetc_resize(infd); 96 1.17 roy if (c == ERR || c == KEY_RESIZE) { 97 1.1 blymn clearerr(infd); 98 1.17 roy return c; 99 1.1 blymn } 100 1.1 blymn 101 1.1 blymn if (delay && (__notimeout() == ERR)) 102 1.1 blymn return ERR; 103 1.1 blymn 104 1.12 roy k = (wchar_t)c; 105 1.2 blymn __CTRACE(__CTRACE_INPUT, 106 1.2 blymn "inkey (wstate normal) got '%s'\n", unctrl(k)); 107 1.1 blymn 108 1.12 roy inbuf[*end] = k; 109 1.12 roy *end = (*end + 1) % MAX_CBUF_SIZE; 110 1.1 blymn *working = *start; 111 1.1 blymn wstate = INKEY_ASSEMBLING; /* go to assembling state */ 112 1.2 blymn __CTRACE(__CTRACE_INPUT, 113 1.2 blymn "inkey: NORM=>ASSEMBLING: start(%d), " 114 1.2 blymn "current(%d), end(%d)\n", *start, *working, *end); 115 1.1 blymn } else if (wstate == INKEY_BACKOUT) { 116 1.1 blymn k = inbuf[*working]; 117 1.12 roy *working = (*working + 1) % MAX_CBUF_SIZE; 118 1.1 blymn if (*working == *end) { /* see if run out of keys */ 119 1.1 blymn /* if so, switch to assembling */ 120 1.1 blymn wstate = INKEY_ASSEMBLING; 121 1.2 blymn __CTRACE(__CTRACE_INPUT, 122 1.2 blymn "inkey: BACKOUT=>ASSEMBLING, start(%d), " 123 1.2 blymn "current(%d), end(%d)\n", 124 1.2 blymn *start, *working, *end); 125 1.1 blymn } 126 1.1 blymn } else if (wstate == INKEY_ASSEMBLING) { 127 1.1 blymn /* assembling a key sequence */ 128 1.1 blymn if (delay) { 129 1.14 roy if (__timeout(to ? (ESCDELAY / 100) : delay) 130 1.1 blymn == ERR) 131 1.1 blymn return ERR; 132 1.1 blymn } else { 133 1.14 roy if (to && (__timeout(ESCDELAY / 100) == ERR)) 134 1.1 blymn return ERR; 135 1.1 blymn } 136 1.1 blymn 137 1.17 roy c = __fgetc_resize(infd); 138 1.27 christos if (c == ERR || ferror(infd)) { 139 1.1 blymn clearerr(infd); 140 1.17 roy return c; 141 1.1 blymn } 142 1.1 blymn 143 1.1 blymn if ((to || delay) && (__notimeout() == ERR)) 144 1.1 blymn return ERR; 145 1.1 blymn 146 1.12 roy k = (wchar_t)c; 147 1.2 blymn __CTRACE(__CTRACE_INPUT, 148 1.2 blymn "inkey (wstate assembling) got '%s'\n", unctrl(k)); 149 1.1 blymn if (feof(infd)) { /* inter-char T/O, start backout */ 150 1.1 blymn clearerr(infd); 151 1.1 blymn if (*start == *end) 152 1.1 blymn /* no chars in the buffer, restart */ 153 1.1 blymn continue; 154 1.1 blymn 155 1.1 blymn k = inbuf[*start]; 156 1.1 blymn wstate = INKEY_TIMEOUT; 157 1.2 blymn __CTRACE(__CTRACE_INPUT, 158 1.2 blymn "inkey: ASSEMBLING=>TIMEOUT, start(%d), " 159 1.2 blymn "current(%d), end(%d)\n", 160 1.2 blymn *start, *working, *end); 161 1.1 blymn } else { 162 1.12 roy inbuf[*end] = k; 163 1.1 blymn *working = *end; 164 1.12 roy *end = (*end + 1) % MAX_CBUF_SIZE; 165 1.2 blymn __CTRACE(__CTRACE_INPUT, 166 1.2 blymn "inkey: ASSEMBLING: start(%d), " 167 1.2 blymn "current(%d), end(%d)", 168 1.2 blymn *start, *working, *end); 169 1.1 blymn } 170 1.1 blymn } else if (wstate == INKEY_WCASSEMBLING) { 171 1.9 wiz /* assembling a wide-char sequence */ 172 1.1 blymn if (delay) { 173 1.14 roy if (__timeout(to ? (ESCDELAY / 100) : delay) 174 1.1 blymn == ERR) 175 1.1 blymn return ERR; 176 1.1 blymn } else { 177 1.14 roy if (to && (__timeout(ESCDELAY / 100) == ERR)) 178 1.1 blymn return ERR; 179 1.1 blymn } 180 1.1 blymn 181 1.17 roy c = __fgetc_resize(infd); 182 1.27 christos if (c == ERR || ferror(infd)) { 183 1.1 blymn clearerr(infd); 184 1.17 roy return c; 185 1.1 blymn } 186 1.1 blymn 187 1.1 blymn if ((to || delay) && (__notimeout() == ERR)) 188 1.1 blymn return ERR; 189 1.1 blymn 190 1.12 roy k = (wchar_t)c; 191 1.2 blymn __CTRACE(__CTRACE_INPUT, 192 1.2 blymn "inkey (wstate wcassembling) got '%s'\n", 193 1.26 rin unctrl(k)); 194 1.1 blymn if (feof(infd)) { /* inter-char T/O, start backout */ 195 1.1 blymn clearerr(infd); 196 1.1 blymn if (*start == *end) 197 1.1 blymn /* no chars in the buffer, restart */ 198 1.1 blymn continue; 199 1.1 blymn 200 1.1 blymn *wc = inbuf[*start]; 201 1.12 roy *working = *start = (*start +1) % MAX_CBUF_SIZE; 202 1.1 blymn if (*start == *end) { 203 1.21 rin _cursesi_state = wstate = INKEY_NORM; 204 1.2 blymn __CTRACE(__CTRACE_INPUT, 205 1.2 blymn "inkey: WCASSEMBLING=>NORM, " 206 1.2 blymn "start(%d), current(%d), end(%d)", 207 1.2 blymn *start, *working, *end); 208 1.1 blymn } else { 209 1.21 rin _cursesi_state = wstate = INKEY_BACKOUT; 210 1.2 blymn __CTRACE(__CTRACE_INPUT, 211 1.2 blymn "inkey: WCASSEMBLING=>BACKOUT, " 212 1.2 blymn "start(%d), current(%d), end(%d)", 213 1.2 blymn *start, *working, *end); 214 1.1 blymn } 215 1.1 blymn return OK; 216 1.1 blymn } else { 217 1.1 blymn /* assembling wide characters */ 218 1.12 roy inbuf[*end] = k; 219 1.1 blymn *working = *end; 220 1.12 roy *end = (*end + 1) % MAX_CBUF_SIZE; 221 1.2 blymn __CTRACE(__CTRACE_INPUT, 222 1.2 blymn "inkey: WCASSEMBLING[head(%d), " 223 1.2 blymn "urrent(%d), tail(%d)]\n", 224 1.2 blymn *start, *working, *end); 225 1.12 roy ret = (int)mbrtowc(wc, inbuf + (*working), 1, 226 1.12 roy &_cursesi_screen->sp); 227 1.2 blymn __CTRACE(__CTRACE_INPUT, 228 1.2 blymn "inkey: mbrtowc returns %d, wc(%x)\n", 229 1.12 roy ret, *wc); 230 1.12 roy if (ret == -2) { 231 1.12 roy *working = (*working+1) % MAX_CBUF_SIZE; 232 1.1 blymn continue; 233 1.1 blymn } 234 1.1 blymn if ( ret == 0 ) 235 1.1 blymn ret = 1; 236 1.1 blymn if ( ret == -1 ) { 237 1.1 blymn /* return the 1st character we know */ 238 1.12 roy *wc = inbuf[*start]; 239 1.26 rin *working = *start = 240 1.26 rin (*start + 1) % MAX_CBUF_SIZE; 241 1.2 blymn __CTRACE(__CTRACE_INPUT, 242 1.2 blymn "inkey: Invalid wide char(%x) " 243 1.2 blymn "[head(%d), current(%d), " 244 1.2 blymn "tail(%d)]\n", 245 1.2 blymn *wc, *start, *working, *end); 246 1.1 blymn } else { /* > 0 */ 247 1.1 blymn /* return the wide character */ 248 1.26 rin *start = *working = 249 1.26 rin (*working + ret) % MAX_CBUF_SIZE; 250 1.2 blymn __CTRACE(__CTRACE_INPUT, 251 1.2 blymn "inkey: Wide char found(%x) " 252 1.2 blymn "[head(%d), current(%d), " 253 1.2 blymn "tail(%d)]\n", 254 1.2 blymn *wc, *start, *working, *end); 255 1.1 blymn } 256 1.1 blymn 257 1.12 roy if (*start == *end) { 258 1.12 roy /* only one char processed */ 259 1.21 rin _cursesi_state = wstate = INKEY_NORM; 260 1.2 blymn __CTRACE(__CTRACE_INPUT, 261 1.2 blymn "inkey: WCASSEMBLING=>NORM, " 262 1.2 blymn "start(%d), current(%d), end(%d)", 263 1.2 blymn *start, *working, *end); 264 1.1 blymn } else { 265 1.12 roy /* otherwise we must have more than 266 1.12 roy * one char to backout */ 267 1.21 rin _cursesi_state = wstate = INKEY_BACKOUT; 268 1.2 blymn __CTRACE(__CTRACE_INPUT, 269 1.2 blymn "inkey: WCASSEMBLING=>BACKOUT, " 270 1.2 blymn "start(%d), current(%d), end(%d)", 271 1.2 blymn *start, *working, *end); 272 1.1 blymn } 273 1.1 blymn return OK; 274 1.1 blymn } 275 1.1 blymn } else { 276 1.1 blymn fprintf(stderr, "Inkey wstate screwed - exiting!!!"); 277 1.1 blymn exit(2); 278 1.1 blymn } 279 1.1 blymn 280 1.1 blymn /* 281 1.1 blymn * Check key has no special meaning and we have not 282 1.1 blymn * timed out and the key has not been disabled 283 1.1 blymn */ 284 1.1 blymn mapping = current->mapping[k]; 285 1.1 blymn if (((wstate == INKEY_TIMEOUT) || (mapping < 0)) 286 1.1 blymn || ((current->key[mapping]->type 287 1.1 blymn == KEYMAP_LEAF) 288 1.12 roy && (current->key[mapping]->enable == FALSE))) 289 1.12 roy { 290 1.9 wiz /* wide-character specific code */ 291 1.2 blymn __CTRACE(__CTRACE_INPUT, 292 1.2 blymn "inkey: Checking for wide char\n"); 293 1.26 rin mbrtowc(NULL, NULL, 1, &_cursesi_screen->sp); 294 1.1 blymn *working = *start; 295 1.1 blymn mlen = *end > *working ? 296 1.1 blymn *end - *working : MAX_CBUF_SIZE - *working; 297 1.12 roy if (!mlen) 298 1.1 blymn return ERR; 299 1.2 blymn __CTRACE(__CTRACE_INPUT, 300 1.2 blymn "inkey: Check wide char[head(%d), " 301 1.26 rin "current(%d), tail(%d), mlen(%zu)]\n", 302 1.26 rin *start, *working, *end, mlen); 303 1.12 roy ret = (int)mbrtowc(wc, inbuf + (*working), mlen, 304 1.12 roy &_cursesi_screen->sp); 305 1.2 blymn __CTRACE(__CTRACE_INPUT, 306 1.2 blymn "inkey: mbrtowc returns %d, wc(%x)\n", ret, *wc); 307 1.12 roy if (ret == -2 && *end < *working) { 308 1.1 blymn /* second half of a wide character */ 309 1.1 blymn *working = 0; 310 1.1 blymn mlen = *end; 311 1.12 roy if (mlen) 312 1.12 roy ret = (int)mbrtowc(wc, inbuf, mlen, 313 1.12 roy &_cursesi_screen->sp); 314 1.1 blymn } 315 1.12 roy if (ret == -2 && wstate != INKEY_TIMEOUT) { 316 1.26 rin *working = 317 1.26 rin (*working + (int) mlen) % MAX_CBUF_SIZE; 318 1.1 blymn wstate = INKEY_WCASSEMBLING; 319 1.1 blymn continue; 320 1.1 blymn } 321 1.12 roy if (ret == 0) 322 1.1 blymn ret = 1; 323 1.12 roy if (ret == -1) { 324 1.1 blymn /* return the first key we know about */ 325 1.12 roy *wc = inbuf[*start]; 326 1.26 rin *working = *start = 327 1.26 rin (*start + 1) % MAX_CBUF_SIZE; 328 1.2 blymn __CTRACE(__CTRACE_INPUT, 329 1.2 blymn "inkey: Invalid wide char(%x)[head(%d), " 330 1.2 blymn "current(%d), tail(%d)]\n", 331 1.2 blymn *wc, *start, *working, *end); 332 1.1 blymn } else { /* > 0 */ 333 1.1 blymn /* return the wide character */ 334 1.26 rin *start = *working = 335 1.26 rin (*working + ret) % MAX_CBUF_SIZE; 336 1.2 blymn __CTRACE(__CTRACE_INPUT, 337 1.2 blymn "inkey: Wide char found(%x)[head(%d), " 338 1.2 blymn "current(%d), tail(%d)]\n", 339 1.2 blymn *wc, *start, *working, *end); 340 1.1 blymn } 341 1.1 blymn 342 1.1 blymn if (*start == *end) { /* only one char processed */ 343 1.21 rin _cursesi_state = wstate = INKEY_NORM; 344 1.2 blymn __CTRACE(__CTRACE_INPUT, 345 1.2 blymn "inkey: Empty cbuf=>NORM, " 346 1.2 blymn "start(%d), current(%d), end(%d)\n", 347 1.2 blymn *start, *working, *end); 348 1.1 blymn } else { 349 1.12 roy /* otherwise we must have more than one 350 1.12 roy * char to backout */ 351 1.21 rin _cursesi_state = wstate = INKEY_BACKOUT; 352 1.2 blymn __CTRACE(__CTRACE_INPUT, 353 1.2 blymn "inkey: Non-empty cbuf=>BACKOUT, " 354 1.2 blymn "start(%d), current(%d), end(%d)\n", 355 1.2 blymn *start, *working, *end); 356 1.1 blymn } 357 1.1 blymn return OK; 358 1.1 blymn } else { /* must be part of a multikey sequence */ 359 1.1 blymn /* check for completed key sequence */ 360 1.1 blymn if (current->key[current->mapping[k]]->type 361 1.1 blymn == KEYMAP_LEAF) { 362 1.1 blymn /* eat the key sequence in cbuf */ 363 1.26 rin *start = *working = 364 1.26 rin (*working + 1) % MAX_CBUF_SIZE; 365 1.1 blymn 366 1.1 blymn /* check if inbuf empty now */ 367 1.2 blymn __CTRACE(__CTRACE_INPUT, 368 1.2 blymn "inkey: Key found(%s)\n", 369 1.2 blymn key_name(current->key[mapping]->value.symbol)); 370 1.1 blymn if (*start == *end) { 371 1.1 blymn /* if it is go back to normal */ 372 1.21 rin _cursesi_state = wstate = INKEY_NORM; 373 1.2 blymn __CTRACE(__CTRACE_INPUT, 374 1.2 blymn "[inkey]=>NORM, start(%d), " 375 1.2 blymn "current(%d), end(%d)", 376 1.2 blymn *start, *working, *end); 377 1.1 blymn } else { 378 1.1 blymn /* otherwise go to backout state */ 379 1.21 rin _cursesi_state = wstate = INKEY_BACKOUT; 380 1.2 blymn __CTRACE(__CTRACE_INPUT, 381 1.2 blymn "[inkey]=>BACKOUT, start(%d), " 382 1.2 blymn "current(%d), end(%d)", 383 1.26 rin *start, *working, *end); 384 1.1 blymn } 385 1.1 blymn 386 1.1 blymn /* return the symbol */ 387 1.1 blymn *wc = current->key[mapping]->value.symbol; 388 1.1 blymn return KEY_CODE_YES; 389 1.1 blymn } else { 390 1.1 blymn /* Step to next part of multi-key sequence */ 391 1.1 blymn current = current->key[current->mapping[k]]->value.next; 392 1.1 blymn } 393 1.1 blymn } 394 1.1 blymn } 395 1.6 jdc } 396 1.1 blymn 397 1.1 blymn /* 398 1.1 blymn * get_wch -- 399 1.1 blymn * Read in a wide character from stdscr. 400 1.1 blymn */ 401 1.1 blymn int 402 1.1 blymn get_wch(wint_t *ch) 403 1.1 blymn { 404 1.1 blymn return wget_wch(stdscr, ch); 405 1.1 blymn } 406 1.1 blymn 407 1.1 blymn /* 408 1.1 blymn * mvget_wch -- 409 1.1 blymn * Read in a character from stdscr at the given location. 410 1.1 blymn */ 411 1.1 blymn int 412 1.1 blymn mvget_wch(int y, int x, wint_t *ch) 413 1.1 blymn { 414 1.1 blymn return mvwget_wch(stdscr, y, x, ch); 415 1.1 blymn } 416 1.1 blymn 417 1.1 blymn /* 418 1.1 blymn * mvwget_wch -- 419 1.1 blymn * Read in a character from stdscr at the given location in the 420 1.1 blymn * given window. 421 1.1 blymn */ 422 1.1 blymn int 423 1.1 blymn mvwget_wch(WINDOW *win, int y, int x, wint_t *ch) 424 1.1 blymn { 425 1.23 blymn if (wmove(win, y, x) == ERR) 426 1.1 blymn return ERR; 427 1.1 blymn 428 1.1 blymn return wget_wch(win, ch); 429 1.1 blymn } 430 1.1 blymn 431 1.1 blymn /* 432 1.1 blymn * wget_wch -- 433 1.1 blymn * Read in a wide character from the window. 434 1.1 blymn */ 435 1.1 blymn int 436 1.1 blymn wget_wch(WINDOW *win, wint_t *ch) 437 1.1 blymn { 438 1.1 blymn int ret, weset; 439 1.1 blymn int c; 440 1.1 blymn FILE *infd = _cursesi_screen->infd; 441 1.1 blymn cchar_t wc; 442 1.12 roy wchar_t inp, ws[2]; 443 1.1 blymn 444 1.28 blymn if (__predict_false(win == NULL)) 445 1.28 blymn return ERR; 446 1.28 blymn 447 1.12 roy if (!(win->flags & __SCROLLOK) 448 1.12 roy && (win->flags & __FULLWIN) 449 1.12 roy && win->curx == win->maxx - 1 450 1.12 roy && win->cury == win->maxy - 1 451 1.12 roy && __echoit) 452 1.12 roy return ERR; 453 1.1 blymn 454 1.24 uwe if (!(win->flags & __ISPAD) && is_wintouched(win)) 455 1.1 blymn wrefresh(win); 456 1.2 blymn __CTRACE(__CTRACE_INPUT, "wget_wch: __echoit = %d, " 457 1.2 blymn "__rawmode = %d, __nl = %d, flags = %#.4x\n", 458 1.2 blymn __echoit, __rawmode, _cursesi_screen->nl, win->flags); 459 1.5 jdc if (_cursesi_screen->resized) { 460 1.19 roy resizeterm(LINES, COLS); 461 1.5 jdc _cursesi_screen->resized = 0; 462 1.5 jdc *ch = KEY_RESIZE; 463 1.5 jdc return KEY_CODE_YES; 464 1.5 jdc } 465 1.5 jdc if (_cursesi_screen->unget_pos) { 466 1.5 jdc __CTRACE(__CTRACE_INPUT, "wget_wch returning char at %d\n", 467 1.5 jdc _cursesi_screen->unget_pos); 468 1.5 jdc _cursesi_screen->unget_pos--; 469 1.5 jdc *ch = _cursesi_screen->unget_list[_cursesi_screen->unget_pos]; 470 1.5 jdc if (__echoit) { 471 1.5 jdc ws[0] = *ch, ws[1] = L'\0'; 472 1.5 jdc setcchar(&wc, ws, win->wattr, 0, NULL); 473 1.5 jdc wadd_wch(win, &wc); 474 1.5 jdc } 475 1.5 jdc return KEY_CODE_YES; 476 1.5 jdc } 477 1.1 blymn if (__echoit && !__rawmode) { 478 1.1 blymn cbreak(); 479 1.1 blymn weset = 1; 480 1.1 blymn } else 481 1.1 blymn weset = 0; 482 1.1 blymn 483 1.1 blymn __save_termios(); 484 1.1 blymn 485 1.1 blymn if (win->flags & __KEYPAD) { 486 1.1 blymn switch (win->delay) { 487 1.1 blymn case -1: 488 1.1 blymn ret = inkey(&inp, 489 1.1 blymn win->flags & __NOTIMEOUT ? 0 : 1, 0); 490 1.1 blymn break; 491 1.1 blymn case 0: 492 1.7 dsl if (__nodelay() == ERR) 493 1.1 blymn return ERR; 494 1.1 blymn ret = inkey(&inp, 0, 0); 495 1.1 blymn break; 496 1.1 blymn default: 497 1.1 blymn ret = inkey(&inp, 498 1.1 blymn win->flags & __NOTIMEOUT ? 0 : 1, 499 1.1 blymn win->delay); 500 1.1 blymn break; 501 1.1 blymn } 502 1.1 blymn if ( ret == ERR ) 503 1.1 blymn return ERR; 504 1.1 blymn } else { 505 1.17 roy bool resized; 506 1.17 roy 507 1.1 blymn switch (win->delay) { 508 1.1 blymn case -1: 509 1.1 blymn break; 510 1.1 blymn case 0: 511 1.7 dsl if (__nodelay() == ERR) 512 1.1 blymn return ERR; 513 1.1 blymn break; 514 1.1 blymn default: 515 1.7 dsl if (__timeout(win->delay) == ERR) 516 1.1 blymn return ERR; 517 1.1 blymn break; 518 1.1 blymn } 519 1.1 blymn 520 1.17 roy c = __fgetwc_resize(infd, &resized); 521 1.17 roy if (c == WEOF) { 522 1.1 blymn clearerr(infd); 523 1.1 blymn __restore_termios(); 524 1.17 roy if (resized) { 525 1.15 rin *ch = KEY_RESIZE; 526 1.15 rin return KEY_CODE_YES; 527 1.15 rin } else 528 1.15 rin return ERR; 529 1.1 blymn } else { 530 1.5 jdc ret = c; 531 1.1 blymn inp = c; 532 1.1 blymn } 533 1.1 blymn } 534 1.1 blymn #ifdef DEBUG 535 1.1 blymn if (inp > 255) 536 1.1 blymn /* we have a key symbol - treat it differently */ 537 1.1 blymn /* XXXX perhaps __unctrl should be expanded to include 538 1.1 blymn * XXXX the keysyms in the table.... 539 1.1 blymn */ 540 1.2 blymn __CTRACE(__CTRACE_INPUT, "wget_wch assembled keysym 0x%x\n", 541 1.2 blymn inp); 542 1.1 blymn else 543 1.2 blymn __CTRACE(__CTRACE_INPUT, "wget_wch got '%s'\n", unctrl(inp)); 544 1.1 blymn #endif 545 1.1 blymn if (win->delay > -1) { 546 1.7 dsl if (__delay() == ERR) 547 1.1 blymn return ERR; 548 1.1 blymn } 549 1.1 blymn 550 1.1 blymn __restore_termios(); 551 1.1 blymn 552 1.1 blymn if (__echoit) { 553 1.1 blymn if ( ret == KEY_CODE_YES ) { 554 1.1 blymn /* handle [DEL], [BS], and [LEFT] */ 555 1.1 blymn if ( win->curx && 556 1.1 blymn ( inp == KEY_DC || 557 1.1 blymn inp == KEY_BACKSPACE || 558 1.1 blymn inp == KEY_LEFT )) { 559 1.23 blymn wmove( win, win->cury, win->curx - 1); 560 1.1 blymn wdelch( win ); 561 1.1 blymn } 562 1.1 blymn } else { 563 1.1 blymn ws[ 0 ] = inp, ws[ 1 ] = L'\0'; 564 1.1 blymn setcchar( &wc, ws, win->wattr, 0, NULL ); 565 1.1 blymn wadd_wch( win, &wc ); 566 1.1 blymn } 567 1.1 blymn } 568 1.1 blymn 569 1.1 blymn if (weset) 570 1.1 blymn nocbreak(); 571 1.1 blymn 572 1.1 blymn if (_cursesi_screen->nl && inp == 13) 573 1.1 blymn inp = 10; 574 1.1 blymn 575 1.1 blymn *ch = inp; 576 1.1 blymn 577 1.1 blymn if ( ret == KEY_CODE_YES ) 578 1.1 blymn return KEY_CODE_YES; 579 1.12 roy return inp < 0 ? ERR : OK; 580 1.1 blymn } 581 1.1 blymn 582 1.1 blymn /* 583 1.1 blymn * unget_wch -- 584 1.1 blymn * Put the wide character back into the input queue. 585 1.1 blymn */ 586 1.1 blymn int 587 1.1 blymn unget_wch(const wchar_t c) 588 1.1 blymn { 589 1.12 roy return __unget((wint_t)c); 590 1.1 blymn } 591 1.17 roy 592 1.17 roy /* 593 1.17 roy * __fgetwc_resize -- 594 1.17 roy * Any call to fgetwc(3) should use this function instead. 595 1.17 roy */ 596 1.17 roy static wint_t 597 1.17 roy __fgetwc_resize(FILE *infd, bool *resized) 598 1.17 roy { 599 1.17 roy wint_t c; 600 1.17 roy 601 1.17 roy c = fgetwc(infd); 602 1.17 roy if (c != WEOF) 603 1.17 roy return c; 604 1.17 roy 605 1.17 roy if (!ferror(infd) || errno != EINTR || !_cursesi_screen->resized) 606 1.17 roy return ERR; 607 1.17 roy __CTRACE(__CTRACE_INPUT, "__fgetwc_resize returning KEY_RESIZE\n"); 608 1.19 roy resizeterm(LINES, COLS); 609 1.17 roy _cursesi_screen->resized = 0; 610 1.17 roy *resized = true; 611 1.17 roy return c; 612 1.17 roy } 613