13941Svenki/* $NetBSD: getch.c,v 1.79 2024/05/14 10:22:48 uwe Exp $ */ 23941Svenki 33941Svenki/* 43941Svenki * Copyright (c) 1981, 1993, 1994 53941Svenki * The Regents of the University of California. All rights reserved. 63941Svenki * 73941Svenki * Redistribution and use in source and binary forms, with or without 83941Svenki * modification, are permitted provided that the following conditions 93941Svenki * are met: 103941Svenki * 1. Redistributions of source code must retain the above copyright 113941Svenki * notice, this list of conditions and the following disclaimer. 123941Svenki * 2. Redistributions in binary form must reproduce the above copyright 133941Svenki * notice, this list of conditions and the following disclaimer in the 143941Svenki * documentation and/or other materials provided with the distribution. 153941Svenki * 3. Neither the name of the University nor the names of its contributors 163941Svenki * may be used to endorse or promote products derived from this software 173941Svenki * without specific prior written permission. 183941Svenki * 193941Svenki * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 203941Svenki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 213941Svenki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 223941Svenki * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2311471SMichael.Bergknoff@Sun.COM * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 243941Svenki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 253941Svenki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 263941Svenki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 273941Svenki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 283941Svenki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 293941Svenki * SUCH DAMAGE. 303941Svenki */ 313941Svenki 323941Svenki#include <sys/cdefs.h> 333941Svenki#ifndef lint 343941Svenki#if 0 353941Svenkistatic char sccsid[] = "@(#)getch.c 8.2 (Berkeley) 5/4/94"; 363941Svenki#else 373941Svenki__RCSID("$NetBSD: getch.c,v 1.79 2024/05/14 10:22:48 uwe Exp $"); 383941Svenki#endif 393941Svenki#endif /* not lint */ 403941Svenki 413941Svenki#include <errno.h> 423941Svenki#include <string.h> 437746SKelly.Moyer@Sun.COM#include <stdlib.h> 4411471SMichael.Bergknoff@Sun.COM#include <unistd.h> 453941Svenki#include <stdio.h> 463941Svenki#include "curses.h" 473941Svenki#include "curses_private.h" 483941Svenki#include "keymap.h" 493941Svenki 503941Svenkishort _cursesi_state; /* state of the inkey function */ 513941Svenki 523941Svenkistatic const struct tcdata tc[] = { 533941Svenki {TICODE_kSAV, KEY_SSAVE}, 543941Svenki {TICODE_kSPD, KEY_SSUSPEND}, 553941Svenki {TICODE_kUND, KEY_SUNDO}, 563941Svenki {TICODE_kHLP, KEY_SHELP}, 573941Svenki {TICODE_kHOM, KEY_SHOME}, 583941Svenki {TICODE_kIC, KEY_SIC}, 593941Svenki {TICODE_kLFT, KEY_SLEFT}, 603941Svenki {TICODE_krdo, KEY_REDO}, 613941Svenki {TICODE_khlp, KEY_HELP}, 623941Svenki {TICODE_kmrk, KEY_MARK}, 633941Svenki {TICODE_kmsg, KEY_MESSAGE}, 643941Svenki {TICODE_kmov, KEY_MOVE}, 653941Svenki {TICODE_knxt, KEY_NEXT}, 663941Svenki {TICODE_kopn, KEY_OPEN}, 673941Svenki {TICODE_kopt, KEY_OPTIONS}, 683941Svenki {TICODE_kprv, KEY_PREVIOUS}, 693941Svenki {TICODE_kprt, KEY_PRINT}, 703941Svenki {TICODE_kMSG, KEY_SMESSAGE}, 713941Svenki {TICODE_kMOV, KEY_SMOVE}, 723941Svenki {TICODE_kNXT, KEY_SNEXT}, 733941Svenki {TICODE_kOPT, KEY_SOPTIONS}, 743941Svenki {TICODE_kPRV, KEY_SPREVIOUS}, 753941Svenki {TICODE_kPRT, KEY_SPRINT}, 763941Svenki {TICODE_kRDO, KEY_SREDO}, 773941Svenki {TICODE_kRPL, KEY_SREPLACE}, 783941Svenki {TICODE_kRIT, KEY_SRIGHT}, 793941Svenki {TICODE_kRES, KEY_SRSUME}, 803941Svenki {TICODE_kCAN, KEY_SCANCEL}, 813941Svenki {TICODE_kref, KEY_REFERENCE}, 823941Svenki {TICODE_krfr, KEY_REFRESH}, 833941Svenki {TICODE_krpl, KEY_REPLACE}, 843941Svenki {TICODE_krst, KEY_RESTART}, 853941Svenki {TICODE_kres, KEY_RESUME}, 863941Svenki {TICODE_ksav, KEY_SAVE}, 873941Svenki {TICODE_kspd, KEY_SUSPEND}, 883941Svenki {TICODE_kund, KEY_UNDO}, 893941Svenki {TICODE_kBEG, KEY_SBEG}, 905723Sfw157321 {TICODE_kFND, KEY_SFIND}, 913941Svenki {TICODE_kCMD, KEY_SCOMMAND}, 923941Svenki {TICODE_kCPY, KEY_SCOPY}, 933941Svenki {TICODE_kCRT, KEY_SCREATE}, 943941Svenki {TICODE_kDC, KEY_SDC}, 953941Svenki {TICODE_kDL, KEY_SDL}, 963941Svenki {TICODE_kslt, KEY_SELECT}, 973941Svenki {TICODE_kEND, KEY_SEND}, 983941Svenki {TICODE_kEOL, KEY_SEOL}, 993941Svenki {TICODE_kEXT, KEY_SEXIT}, 1005029Sfw157321 {TICODE_kfnd, KEY_FIND}, 1015029Sfw157321 {TICODE_kbeg, KEY_BEG}, 1023941Svenki {TICODE_kcan, KEY_CANCEL}, 1033941Svenki {TICODE_kclo, KEY_CLOSE}, 1047746SKelly.Moyer@Sun.COM {TICODE_kcmd, KEY_COMMAND}, 1057746SKelly.Moyer@Sun.COM {TICODE_kcpy, KEY_COPY}, 1067746SKelly.Moyer@Sun.COM {TICODE_kcrt, KEY_CREATE}, 1077746SKelly.Moyer@Sun.COM {TICODE_kend, KEY_END}, 1087746SKelly.Moyer@Sun.COM {TICODE_kent, KEY_ENTER}, 1097746SKelly.Moyer@Sun.COM {TICODE_kext, KEY_EXIT}, 1107746SKelly.Moyer@Sun.COM {TICODE_kf11, KEY_F(11)}, 1117746SKelly.Moyer@Sun.COM {TICODE_kf12, KEY_F(12)}, 1127746SKelly.Moyer@Sun.COM {TICODE_kf13, KEY_F(13)}, 1137746SKelly.Moyer@Sun.COM {TICODE_kf14, KEY_F(14)}, 1147746SKelly.Moyer@Sun.COM {TICODE_kf15, KEY_F(15)}, 1157746SKelly.Moyer@Sun.COM {TICODE_kf16, KEY_F(16)}, 1167746SKelly.Moyer@Sun.COM {TICODE_kf17, KEY_F(17)}, 1177746SKelly.Moyer@Sun.COM {TICODE_kf18, KEY_F(18)}, 1187746SKelly.Moyer@Sun.COM {TICODE_kf19, KEY_F(19)}, 1197746SKelly.Moyer@Sun.COM {TICODE_kf20, KEY_F(20)}, 1207746SKelly.Moyer@Sun.COM {TICODE_kf21, KEY_F(21)}, 1217746SKelly.Moyer@Sun.COM {TICODE_kf22, KEY_F(22)}, 1227746SKelly.Moyer@Sun.COM {TICODE_kf23, KEY_F(23)}, 1237746SKelly.Moyer@Sun.COM {TICODE_kf24, KEY_F(24)}, 1247746SKelly.Moyer@Sun.COM {TICODE_kf25, KEY_F(25)}, 1257746SKelly.Moyer@Sun.COM {TICODE_kf26, KEY_F(26)}, 1267746SKelly.Moyer@Sun.COM {TICODE_kf27, KEY_F(27)}, 1277746SKelly.Moyer@Sun.COM {TICODE_kf28, KEY_F(28)}, 1283941Svenki {TICODE_kf29, KEY_F(29)}, 1293941Svenki {TICODE_kf30, KEY_F(30)}, 1303941Svenki {TICODE_kf31, KEY_F(31)}, 1313941Svenki {TICODE_kf32, KEY_F(32)}, 1323941Svenki {TICODE_kf33, KEY_F(33)}, 1333941Svenki {TICODE_kf34, KEY_F(34)}, 1343941Svenki {TICODE_kf35, KEY_F(35)}, 1353941Svenki {TICODE_kf36, KEY_F(36)}, 1363941Svenki {TICODE_kf37, KEY_F(37)}, 1373941Svenki {TICODE_kf38, KEY_F(38)}, 1383941Svenki {TICODE_kf39, KEY_F(39)}, 1393941Svenki {TICODE_kf40, KEY_F(40)}, 1403941Svenki {TICODE_kf41, KEY_F(41)}, 1413941Svenki {TICODE_kf42, KEY_F(42)}, 1423941Svenki {TICODE_kf43, KEY_F(43)}, 1433941Svenki {TICODE_kf44, KEY_F(44)}, 1443941Svenki {TICODE_kf45, KEY_F(45)}, 1453941Svenki {TICODE_kf46, KEY_F(46)}, 1463941Svenki {TICODE_kf47, KEY_F(47)}, 1473941Svenki {TICODE_kf48, KEY_F(48)}, 1483941Svenki {TICODE_kf49, KEY_F(49)}, 1493941Svenki {TICODE_kf50, KEY_F(50)}, 1503941Svenki {TICODE_kf51, KEY_F(51)}, 1513941Svenki {TICODE_kf52, KEY_F(52)}, 1523941Svenki {TICODE_kf53, KEY_F(53)}, 1533941Svenki {TICODE_kf54, KEY_F(54)}, 1543941Svenki {TICODE_kf55, KEY_F(55)}, 1553941Svenki {TICODE_kf56, KEY_F(56)}, 1563941Svenki {TICODE_kf57, KEY_F(57)}, 1573941Svenki {TICODE_kf58, KEY_F(58)}, 1583941Svenki {TICODE_kf59, KEY_F(59)}, 1595723Sfw157321 {TICODE_kf60, KEY_F(60)}, 1605723Sfw157321 {TICODE_kf61, KEY_F(61)}, 1615723Sfw157321 {TICODE_kf62, KEY_F(62)}, 1625723Sfw157321 {TICODE_kf63, KEY_F(63)}, 1635723Sfw157321 {TICODE_ka1, KEY_A1}, 1645723Sfw157321 {TICODE_kb2, KEY_B2}, 1655723Sfw157321 {TICODE_ka3, KEY_A3}, 1665723Sfw157321 {TICODE_kc1, KEY_C1}, 1675723Sfw157321 {TICODE_kc3, KEY_C3}, 1685723Sfw157321 {TICODE_kmous, KEY_MOUSE}, 1698411SKelly.Moyer@Sun.COM {TICODE_kf0, KEY_F0}, 1705723Sfw157321 {TICODE_kf1, KEY_F(1)}, 1715723Sfw157321 {TICODE_kf2, KEY_F(2)}, 1723941Svenki {TICODE_kf3, KEY_F(3)}, 1733941Svenki {TICODE_kf4, KEY_F(4)}, 1743941Svenki {TICODE_kf5, KEY_F(5)}, 1753941Svenki {TICODE_kf6, KEY_F(6)}, 1763941Svenki {TICODE_kf7, KEY_F(7)}, 1773941Svenki {TICODE_kf8, KEY_F(8)}, 1783941Svenki {TICODE_kf9, KEY_F(9)}, 1793941Svenki {TICODE_kf10, KEY_F(10)}, 1803941Svenki {TICODE_kil1, KEY_IL}, 1813941Svenki {TICODE_ktbc, KEY_CATAB}, 1823941Svenki {TICODE_kcbt, KEY_BTAB}, 1833941Svenki {TICODE_kbs, KEY_BACKSPACE}, 1843941Svenki {TICODE_kclr, KEY_CLEAR}, 1853941Svenki {TICODE_kdch1, KEY_DC}, 1863941Svenki {TICODE_kcud1, KEY_DOWN}, 1873941Svenki {TICODE_kel, KEY_EOL}, 1883941Svenki {TICODE_kind, KEY_SF}, 1893941Svenki {TICODE_kll, KEY_LL}, 1905723Sfw157321 {TICODE_khome, KEY_HOME}, 1915723Sfw157321 {TICODE_kich1, KEY_IC}, 1925723Sfw157321 {TICODE_kdl1, KEY_DL}, 1935723Sfw157321 {TICODE_kcub1, KEY_LEFT}, 1945723Sfw157321 {TICODE_krmir, KEY_EIC}, 1955723Sfw157321 {TICODE_knp, KEY_NPAGE}, 1965723Sfw157321 {TICODE_kpp, KEY_PPAGE}, 1975723Sfw157321 {TICODE_kri, KEY_SR}, 1985723Sfw157321 {TICODE_kcuf1, KEY_RIGHT}, 1995723Sfw157321 {TICODE_ked, KEY_EOS}, 2005723Sfw157321 {TICODE_khts, KEY_STAB}, 2015723Sfw157321 {TICODE_kctab, KEY_CTAB}, 2025723Sfw157321 {TICODE_kcuu1, KEY_UP} 2035723Sfw157321}; 2045723Sfw157321/* Number of TC entries .... */ 2053941Svenkistatic const int num_tcs = (sizeof(tc) / sizeof(struct tcdata)); 2063941Svenki 2073941Svenki/* Key buffer */ 2083941Svenki#define INBUF_SZ 16 /* size of key buffer - must be larger than 2093941Svenki * longest multi-key sequence */ 2103941Svenkistatic wchar_t inbuf[INBUF_SZ]; 2113941Svenkistatic int start, end, working; /* pointers for manipulating inbuf data */ 2123941Svenki 2133941Svenki/* prototypes for private functions */ 2143941Svenkistatic void add_key_sequence(SCREEN *screen, const char *sequence, int key_type); 2153941Svenkistatic key_entry_t *add_new_key(keymap_t *current, char ch, int key_type, 2163941Svenki int symbol); 2173941Svenkistatic void delete_key_sequence(keymap_t *current, int key_type); 2183941Svenkistatic void do_keyok(keymap_t *current, int key_type, bool set, bool flag, 2193941Svenki int *retval); 2203941Svenkistatic keymap_t *new_keymap(void); /* create a new keymap */ 2213941Svenkistatic key_entry_t *new_key(void); /* create a new key entry */ 2223941Svenkistatic wchar_t inkey(int to, int delay); 2233941Svenki 2243941Svenki/* 2253941Svenki * Free the storage associated with the given keymap 2263941Svenki */ 2273941Svenkivoid 2283941Svenki_cursesi_free_keymap(keymap_t *map) 2293941Svenki{ 2303941Svenki int i; 2313941Svenki 2323941Svenki /* check for, and free, child keymaps */ 2333941Svenki for (i = 0; i < MAX_CHAR; i++) { 2343941Svenki if (map->mapping[i] >= 0) { 2353941Svenki if (map->key[map->mapping[i]]->type == KEYMAP_MULTI) 2363941Svenki _cursesi_free_keymap( 2373941Svenki map->key[map->mapping[i]]->value.next); 2383941Svenki } 2393941Svenki } 2403941Svenki 2413941Svenki /* now free any allocated keymap structs */ 2423941Svenki for (i = 0; i < map->count; i += KEYMAP_ALLOC_CHUNK) { 2433941Svenki free(map->key[i]); 2443941Svenki } 2453941Svenki 2463941Svenki free(map->key); 2473941Svenki free(map); 2483941Svenki} 2493941Svenki 2503941Svenki 2513941Svenki/* 2523941Svenki * Add a new key entry to the keymap pointed to by current. Entry 2533941Svenki * contains the character to add to the keymap, type is the type of 2543941Svenki * entry to add (either multikey or leaf) and symbol is the symbolic 2555723Sfw157321 * value for a leaf type entry. The function returns a pointer to the 2563941Svenki * new keymap entry. 2573941Svenki */ 2583941Svenkistatic key_entry_t * 2593941Svenkiadd_new_key(keymap_t *current, char chr, int key_type, int symbol) 2603941Svenki{ 2613941Svenki key_entry_t *the_key; 2623941Svenki int i, ki; 2633941Svenki 2643941Svenki __CTRACE(__CTRACE_MISC, 2653941Svenki "Adding character %s of type %d, symbol 0x%x\n", 2663941Svenki unctrl(chr), key_type, symbol); 2673941Svenki if (current->mapping[(unsigned char)chr] < 0) { 2683941Svenki if (current->mapping[(unsigned char)chr] == MAPPING_UNUSED) { 2693941Svenki /* first time for this char */ 2703941Svenki current->mapping[(unsigned char)chr] = 2717746SKelly.Moyer@Sun.COM current->count; /* map new entry */ 2727746SKelly.Moyer@Sun.COM ki = current->count; 2737746SKelly.Moyer@Sun.COM 2743941Svenki /* make sure we have room in the key array first */ 2753941Svenki if ((current->count & (KEYMAP_ALLOC_CHUNK - 1)) == 0) 2763941Svenki { 2773941Svenki if ((current->key = 2783941Svenki realloc(current->key, 2793941Svenki ki * sizeof(key_entry_t *) 2803941Svenki + KEYMAP_ALLOC_CHUNK * sizeof(key_entry_t *))) == NULL) { 2813941Svenki fprintf(stderr, 2823941Svenki "Could not malloc for key entry\n"); 2833941Svenki exit(1); 2843941Svenki } 2853941Svenki 2863941Svenki the_key = new_key(); 2873941Svenki for (i = 0; i < KEYMAP_ALLOC_CHUNK; i++) { 2883941Svenki current->key[ki + i] = &the_key[i]; 2893941Svenki } 2903941Svenki } 2913941Svenki } else { 2923941Svenki /* the mapping was used but freed, reuse it */ 2933941Svenki ki = - current->mapping[(unsigned char) chr]; 2943941Svenki current->mapping[(unsigned char) chr] = ki; 2953941Svenki } 2963941Svenki 2973941Svenki current->count++; 2983941Svenki 2993941Svenki /* point at the current key array element to use */ 3003941Svenki the_key = current->key[ki]; 3013941Svenki 3023941Svenki the_key->type = key_type; 3033941Svenki 3043941Svenki switch (key_type) { 3053941Svenki case KEYMAP_MULTI: 3063941Svenki /* need for next key */ 3073941Svenki __CTRACE(__CTRACE_MISC, "Creating new keymap\n"); 3083941Svenki the_key->value.next = new_keymap(); 3093941Svenki the_key->enable = TRUE; 3103941Svenki break; 3113941Svenki 3123941Svenki case KEYMAP_LEAF: 3133941Svenki /* the associated symbol for the key */ 3143941Svenki __CTRACE(__CTRACE_MISC, "Adding leaf key\n"); 3153941Svenki the_key->value.symbol = symbol; 3167382SMichael.Bergknoff@Sun.COM the_key->enable = TRUE; 3173941Svenki break; 3183941Svenki 3193941Svenki default: 3203941Svenki fprintf(stderr, "add_new_key: bad type passed\n"); 3213941Svenki exit(1); 3223941Svenki } 3233941Svenki } else { 3243941Svenki /* the key is already known - just return the address. */ 3253941Svenki __CTRACE(__CTRACE_MISC, "Keymap already known\n"); 3263941Svenki the_key = current->key[current->mapping[(unsigned char)chr]]; 3275029Sfw157321 } 3285029Sfw157321 3293941Svenki return the_key; 3303941Svenki} 3313941Svenki 3323941Svenki/* 3333941Svenki * Delete the given key symbol from the key mappings for the screen. 3343941Svenki * 3353941Svenki */ 3365029Sfw157321static void 3373941Svenkidelete_key_sequence(keymap_t *current, int key_type) 3383941Svenki{ 3395029Sfw157321 key_entry_t *key; 3405029Sfw157321 int i; 3415029Sfw157321 3425029Sfw157321 /* 3435029Sfw157321 * we need to iterate over all the keys as there may be 3447746SKelly.Moyer@Sun.COM * multiple instances of the leaf symbol. 3457746SKelly.Moyer@Sun.COM */ 3467746SKelly.Moyer@Sun.COM for (i = 0; i < MAX_CHAR; i++) { 3477746SKelly.Moyer@Sun.COM if (current->mapping[i] < 0) 3487746SKelly.Moyer@Sun.COM continue; /* no mapping for the key, next! */ 3497746SKelly.Moyer@Sun.COM 3507746SKelly.Moyer@Sun.COM key = current->key[current->mapping[i]]; 3517746SKelly.Moyer@Sun.COM 3527746SKelly.Moyer@Sun.COM if (key->type == KEYMAP_MULTI) { 3537746SKelly.Moyer@Sun.COM /* have not found the leaf, recurse down */ 3547746SKelly.Moyer@Sun.COM delete_key_sequence(key->value.next, key_type); 3557746SKelly.Moyer@Sun.COM /* if we deleted the last key in the map, free */ 3567746SKelly.Moyer@Sun.COM if (key->value.next->count == 0) 3577746SKelly.Moyer@Sun.COM _cursesi_free_keymap(key->value.next); 3587746SKelly.Moyer@Sun.COM } else if ((key->type == KEYMAP_LEAF) 3597746SKelly.Moyer@Sun.COM && (key->value.symbol == key_type)) { 3607746SKelly.Moyer@Sun.COM __CTRACE(__CTRACE_INPUT, 3617746SKelly.Moyer@Sun.COM "delete_key_sequence: found keysym %d, deleting\n", 3627746SKelly.Moyer@Sun.COM key_type); 3637746SKelly.Moyer@Sun.COM key->enable = FALSE; 3643941Svenki } 3653941Svenki } 3663941Svenki} 3673941Svenki 3683941Svenki/* 3693941Svenki * Add the sequence of characters given in sequence as the key mapping 3705029Sfw157321 * for the given key symbol. 3715029Sfw157321 */ 3725029Sfw157321static void 3733941Svenkiadd_key_sequence(SCREEN *screen, const char *sequence, int key_type) 3745029Sfw157321{ 3755029Sfw157321 key_entry_t *tmp_key; 3765029Sfw157321 keymap_t *current; 3775029Sfw157321 int length, j, key_ent; 3785029Sfw157321 3795029Sfw157321 __CTRACE(__CTRACE_MISC, "add_key_sequence: add key sequence: %s(%s)\n", 3805029Sfw157321 sequence, keyname(key_type)); 3815029Sfw157321 current = screen->base_keymap; /* always start with 3825029Sfw157321 * base keymap. */ 3835029Sfw157321 length = (int)strlen(sequence); 3845029Sfw157321 3855029Sfw157321 /* 3865029Sfw157321 * OK - we really should never get a zero length string here, either 3875029Sfw157321 * the terminfo entry is there and it has a value or we are not called 3885029Sfw157321 * at all. Unfortunately, if someone assigns a terminfo string to the 3895029Sfw157321 * ^@ value we get passed a null string which messes up our length. 3907746SKelly.Moyer@Sun.COM * So, if we get a null string then just insert a leaf value in 3917746SKelly.Moyer@Sun.COM * the 0th char position of the root keymap. Note that we are 3927746SKelly.Moyer@Sun.COM * totally screwed if someone terminates a multichar sequence 3935029Sfw157321 * with ^@... oh well. 3945029Sfw157321 */ 3955029Sfw157321 if (length == 0) 3965029Sfw157321 length = 1; 3975436Sfw157321 3985029Sfw157321 for (j = 0; j < length - 1; j++) { 3995029Sfw157321 /* add the entry to the struct */ 40011471SMichael.Bergknoff@Sun.COM tmp_key = add_new_key(current, sequence[j], KEYMAP_MULTI, 0); 40111471SMichael.Bergknoff@Sun.COM 40211471SMichael.Bergknoff@Sun.COM /* index into the key array - it's 4035029Sfw157321 clearer if we stash this */ 4045029Sfw157321 key_ent = current->mapping[(unsigned char) sequence[j]]; 4055029Sfw157321 4065029Sfw157321 current->key[key_ent] = tmp_key; 4075029Sfw157321 4085029Sfw157321 /* next key uses this map... */ 4095029Sfw157321 current = current->key[key_ent]->value.next; 4105029Sfw157321 } 4115029Sfw157321 4125029Sfw157321 /* 4133941Svenki * This is the last key in the sequence (it may have been the 4143941Svenki * only one but that does not matter) this means it is a leaf 4153941Svenki * key and should have a symbol associated with it. 4163941Svenki */ 4173941Svenki tmp_key = add_new_key(current, sequence[length - 1], KEYMAP_LEAF, 4183941Svenki key_type); 41911471SMichael.Bergknoff@Sun.COM current->key[current->mapping[(int)sequence[length - 1]]] = tmp_key; 42011471SMichael.Bergknoff@Sun.COM} 42111471SMichael.Bergknoff@Sun.COM 42211471SMichael.Bergknoff@Sun.COM/* 42311471SMichael.Bergknoff@Sun.COM * Init_getch - initialise all the pointers & structures needed to make 42411471SMichael.Bergknoff@Sun.COM * getch work in keypad mode. 42511471SMichael.Bergknoff@Sun.COM * 42611471SMichael.Bergknoff@Sun.COM */ 42711471SMichael.Bergknoff@Sun.COMvoid 42811471SMichael.Bergknoff@Sun.COM__init_getch(SCREEN *screen) 42911471SMichael.Bergknoff@Sun.COM{ 43011471SMichael.Bergknoff@Sun.COM char entry[1024], *p; 43111471SMichael.Bergknoff@Sun.COM const char *s; 43211471SMichael.Bergknoff@Sun.COM int i; 4333941Svenki size_t limit, l; 4343941Svenki#ifdef DEBUG 4353941Svenki int k, length; 4363941Svenki#endif 4373941Svenki 4383941Svenki /* init the inkey state variable */ 4393941Svenki _cursesi_state = INKEY_NORM; 44011471SMichael.Bergknoff@Sun.COM 44111471SMichael.Bergknoff@Sun.COM /* init the base keymap */ 44211471SMichael.Bergknoff@Sun.COM screen->base_keymap = new_keymap(); 44311471SMichael.Bergknoff@Sun.COM 44411471SMichael.Bergknoff@Sun.COM /* key input buffer pointers */ 44511471SMichael.Bergknoff@Sun.COM start = end = working = 0; 44611471SMichael.Bergknoff@Sun.COM 44711471SMichael.Bergknoff@Sun.COM /* now do the terminfo snarfing ... */ 44811471SMichael.Bergknoff@Sun.COM 44911471SMichael.Bergknoff@Sun.COM for (i = 0; i < num_tcs; i++) { 45011471SMichael.Bergknoff@Sun.COM p = entry; 45111471SMichael.Bergknoff@Sun.COM limit = 1023; 45211471SMichael.Bergknoff@Sun.COM s = screen->term->strs[tc[i].code]; 4533941Svenki if (s == NULL) 4543941Svenki continue; 4553941Svenki l = strlen(s) + 1; 4563941Svenki if (limit < l) 4573941Svenki continue; 4583941Svenki strlcpy(p, s, limit); 4593941Svenki p += l; 4603941Svenki limit -= l; 4613941Svenki#ifdef DEBUG 4623941Svenki __CTRACE(__CTRACE_INIT, 4633941Svenki "Processing terminfo entry %d, sequence ", 4643941Svenki tc[i].code); 4653941Svenki length = (int) strlen(entry); 4663941Svenki for (k = 0; k <= length -1; k++) 4673941Svenki __CTRACE(__CTRACE_INIT, "%s", unctrl(entry[k])); 4683941Svenki __CTRACE(__CTRACE_INIT, "\n"); 4695723Sfw157321#endif 4705723Sfw157321 add_key_sequence(screen, entry, tc[i].symbol); 4713941Svenki } 4723941Svenki} 4735723Sfw157321 4745723Sfw157321 4755723Sfw157321/* 4763941Svenki * new_keymap - allocates & initialises a new keymap structure. This 4773941Svenki * function returns a pointer to the new keymap. 4783941Svenki * 4793941Svenki */ 4803941Svenkistatic keymap_t * 4813941Svenkinew_keymap(void) 4823941Svenki{ 4833941Svenki int i; 4843941Svenki keymap_t *new_map; 4853941Svenki 4865029Sfw157321 if ((new_map = malloc(sizeof(keymap_t))) == NULL) { 4875029Sfw157321 perror("Inkey: Cannot allocate new keymap"); 4885029Sfw157321 exit(2); 4895029Sfw157321 } 4905029Sfw157321 4915029Sfw157321 /* Initialise the new map */ 4923941Svenki new_map->count = 0; 4933941Svenki for (i = 0; i < MAX_CHAR; i++) { 4943941Svenki new_map->mapping[i] = MAPPING_UNUSED; /* no mapping for char */ 4953941Svenki } 4963941Svenki 4975029Sfw157321 /* key array will be allocated when first key is added */ 4983941Svenki new_map->key = NULL; 4993941Svenki 5003941Svenki return new_map; 5013941Svenki} 5023941Svenki 5033941Svenki/* 5043941Svenki * new_key - allocates & initialises a new key entry. This function returns 5053941Svenki * a pointer to the newly allocated key entry. 5063941Svenki * 5073941Svenki */ 5083941Svenkistatic key_entry_t * 5095029Sfw157321new_key(void) 5103941Svenki{ 5117746SKelly.Moyer@Sun.COM key_entry_t *new_one; 5123941Svenki int i; 5135029Sfw157321 5143941Svenki new_one = malloc(KEYMAP_ALLOC_CHUNK * sizeof(key_entry_t)); 5153941Svenki if (new_one == NULL) { 5163941Svenki perror("inkey: Cannot allocate new key entry chunk"); 5173941Svenki exit(2); 5183941Svenki } 5193941Svenki 5203941Svenki for (i = 0; i < KEYMAP_ALLOC_CHUNK; i++) { 5213941Svenki new_one[i].type = 0; 5223941Svenki new_one[i].value.next = NULL; 5233941Svenki } 5243941Svenki 5255029Sfw157321 return new_one; 5263941Svenki} 5273941Svenki 5287746SKelly.Moyer@Sun.COM/* 5293941Svenki * inkey - do the work to process keyboard input, check for multi-key 5305029Sfw157321 * sequences and return the appropriate symbol if we get a match. 5313941Svenki * 5323941Svenki */ 5333941Svenki 5343941Svenkistatic wchar_t 5353941Svenkiinkey(int to, int delay) 5363941Svenki{ 5373941Svenki wchar_t k; 5383941Svenki int c, mapping; 5393941Svenki keymap_t *current = _cursesi_screen->base_keymap; 5403941Svenki FILE *infd = _cursesi_screen->infd; 5413941Svenki 5423941Svenki k = 0; /* XXX gcc -Wuninitialized */ 5433941Svenki 5443941Svenki __CTRACE(__CTRACE_INPUT, "inkey (%d, %d)\n", to, delay); 5453941Svenki for (;;) { /* loop until we get a complete key sequence */ 5463941Svenkireread: 5473941Svenki if (_cursesi_state == INKEY_NORM) { 5483941Svenki if (delay && __timeout(delay) == ERR) 5493941Svenki return ERR; 5503941Svenki c = __fgetc_resize(infd); 5513941Svenki if (c == ERR || c == KEY_RESIZE) { 5523941Svenki clearerr(infd); 5533941Svenki return c; 5543941Svenki } 5553941Svenki 5563941Svenki if (delay && (__notimeout() == ERR)) 5573941Svenki return ERR; 5583941Svenki 5593941Svenki k = (wchar_t)c; 5603941Svenki __CTRACE(__CTRACE_INPUT, 5613941Svenki "inkey (state normal) got '%s'\n", unctrl(k)); 5623941Svenki 5633941Svenki working = start; 5643941Svenki inbuf[working] = k; 5653941Svenki INC_POINTER(working); 5663941Svenki end = working; 5676751Sfw157321 5683941Svenki /* go to the assembling state now */ 5693941Svenki _cursesi_state = INKEY_ASSEMBLING; 5705723Sfw157321 5715723Sfw157321 } else if (_cursesi_state == INKEY_BACKOUT) { 5725723Sfw157321 k = inbuf[working]; 5733941Svenki INC_POINTER(working); 5743941Svenki if (working == end) { /* see if we have run 5753941Svenki * out of keys in the 5763941Svenki * backlog */ 5773941Svenki 5783941Svenki /* if we have then switch to assembling */ 5793941Svenki _cursesi_state = INKEY_ASSEMBLING; 5803941Svenki } 5813941Svenki } else if (_cursesi_state == INKEY_ASSEMBLING) { 5823941Svenki /* assembling a key sequence */ 5833941Svenki if (delay) { 5843941Svenki if (__timeout(to ? (ESCDELAY / 100) : delay) 5853941Svenki == ERR) 5863941Svenki return ERR; 5873941Svenki } else { 5883941Svenki if (to && (__timeout(ESCDELAY / 100) == ERR)) 5893941Svenki return ERR; 5905995Sfw157321 } 5913941Svenki 5925995Sfw157321 c = __fgetc_resize(infd); 5935995Sfw157321 if (ferror(infd)) { 5943941Svenki clearerr(infd); 5953941Svenki return c; 5963941Svenki } 5973941Svenki 5983941Svenki if ((to || delay) && (__notimeout() == ERR)) 5993941Svenki return ERR; 6003941Svenki 6013941Svenki __CTRACE(__CTRACE_INPUT, 6023941Svenki "inkey (state assembling) got '%s'\n", unctrl(k)); 6035995Sfw157321 if (feof(infd) || c == -1) { /* inter-char timeout, 6045995Sfw157321 * start backing out */ 6055995Sfw157321 clearerr(infd); 6065995Sfw157321 if (start == end) 6075995Sfw157321 /* no chars in the buffer, restart */ 6085995Sfw157321 goto reread; 6095995Sfw157321 6105995Sfw157321 k = inbuf[start]; 6115995Sfw157321 _cursesi_state = INKEY_TIMEOUT; 6125995Sfw157321 } else { 6135995Sfw157321 k = (wchar_t) c; 6145995Sfw157321 inbuf[working] = k; 6155995Sfw157321 INC_POINTER(working); 6165995Sfw157321 end = working; 6175995Sfw157321 } 6185995Sfw157321 } else { 6195995Sfw157321 fprintf(stderr, "Inkey state screwed - exiting!!!"); 6205995Sfw157321 exit(2); 6215995Sfw157321 } 6223941Svenki 6233941Svenki /* 6243941Svenki * Check key has no special meaning and we have not 6253941Svenki * timed out and the key has not been disabled 6263941Svenki */ 6273941Svenki mapping = current->mapping[k]; 6283941Svenki if (((_cursesi_state == INKEY_TIMEOUT) || (mapping < 0)) 6293941Svenki || ((current->key[mapping]->type == KEYMAP_LEAF) 6303941Svenki && (current->key[mapping]->enable == FALSE))) { 6313941Svenki /* return the first key we know about */ 6323941Svenki k = inbuf[start]; 6333941Svenki 6343941Svenki INC_POINTER(start); 6353941Svenki working = start; 6363941Svenki 6375723Sfw157321 if (start == end) { /* only one char processed */ 6385723Sfw157321 _cursesi_state = INKEY_NORM; 6395723Sfw157321 } else {/* otherwise we must have more than one char 6403941Svenki * to backout */ 6413941Svenki _cursesi_state = INKEY_BACKOUT; 6423941Svenki } 6433941Svenki return k; 6443941Svenki } else { /* must be part of a multikey sequence */ 6453941Svenki /* check for completed key sequence */ 6463941Svenki if (current->key[current->mapping[k]]->type == KEYMAP_LEAF) { 6473941Svenki start = working; /* eat the key sequence 6483941Svenki * in inbuf */ 6493941Svenki 6503941Svenki /* check if inbuf empty now */ 6513941Svenki if (start == end) { 6523941Svenki /* if it is go back to normal */ 6533941Svenki _cursesi_state = INKEY_NORM; 6543941Svenki } else { 6553941Svenki /* otherwise go to backout state */ 6563941Svenki _cursesi_state = INKEY_BACKOUT; 6573941Svenki } 6583941Svenki 6593941Svenki /* return the symbol */ 6603941Svenki return current->key[current->mapping[k]]->value.symbol; 6613941Svenki 6623941Svenki } else { 6633941Svenki /* 6643941Svenki * Step on to next part of the multi-key 6653941Svenki * sequence. 6663941Svenki */ 6673941Svenki current = current->key[current->mapping[k]]->value.next; 6683941Svenki } 6693941Svenki } 6703941Svenki } 6713941Svenki} 6723941Svenki 6733941Svenki#ifndef _CURSES_USE_MACROS 6743941Svenki/* 6753941Svenki * getch -- 6763941Svenki * Read in a character from stdscr. 6773941Svenki */ 6783941Svenkiint 6793941Svenkigetch(void) 6803941Svenki{ 6813941Svenki return wgetch(stdscr); 6823941Svenki} 6833941Svenki 6843941Svenki/* 6853941Svenki * mvgetch -- 68610406SMichael.Bergknoff@Sun.COM * Read in a character from stdscr at the given location. 6873941Svenki */ 6883941Svenkiint 6893941Svenkimvgetch(int y, int x) 6903941Svenki{ 6913941Svenki return mvwgetch(stdscr, y, x); 6923941Svenki} 6933941Svenki 6943941Svenki/* 6953941Svenki * mvwgetch -- 6963941Svenki * Read in a character from stdscr at the given location in the 6973941Svenki * given window. 6983941Svenki */ 6993941Svenkiint 7003941Svenkimvwgetch(WINDOW *win, int y, int x) 7013941Svenki{ 7023941Svenki if (wmove(win, y, x) == ERR) 7033941Svenki return ERR; 7043941Svenki 7053941Svenki return wgetch(win); 7063941Svenki} 7073941Svenki 7083941Svenki#endif 7093941Svenki 7103941Svenki/* 7113941Svenki * keyok -- 7123941Svenki * Set the enable flag for a keysym, if the flag is false then 7133941Svenki * getch will not return this keysym even if the matching key sequence 7143941Svenki * is seen. 7153941Svenki */ 7163941Svenkiint 7173941Svenkikeyok(int key_type, bool flag) 7183941Svenki{ 7193941Svenki int result = ERR; 7203941Svenki 7213941Svenki if (_cursesi_screen != NULL) 7223941Svenki do_keyok(_cursesi_screen->base_keymap, key_type, 7233941Svenki true, flag, &result); 7243941Svenki return result; 7253941Svenki} 7263941Svenki 7273941Svenki/* 7283941Svenki * do_keyok -- 7293941Svenki * Does the actual work for keyok, we need to recurse through the 7303941Svenki * keymaps finding the passed key symbol. 7313941Svenki */ 7323941Svenkistatic void 7333941Svenkido_keyok(keymap_t *current, int key_type, bool set, bool flag, int *retval) 7343941Svenki{ 7353941Svenki key_entry_t *key; 7363941Svenki int i; 7373941Svenki 7383941Svenki /* 7393941Svenki * we need to iterate over all the keys as there may be 7403941Svenki * multiple instances of the leaf symbol. 7413941Svenki */ 7423941Svenki for (i = 0; i < MAX_CHAR; i++) { 7433941Svenki if (current->mapping[i] < 0) 7443941Svenki continue; /* no mapping for the key, next! */ 7453941Svenki 7463941Svenki key = current->key[current->mapping[i]]; 7475723Sfw157321 7485723Sfw157321 if (key->type == KEYMAP_MULTI) 7495723Sfw157321 do_keyok(key->value.next, key_type, set, flag, retval); 7503941Svenki else if ((key->type == KEYMAP_LEAF) 7513941Svenki && (key->value.symbol == key_type)) { 7523941Svenki if (set) 7533941Svenki key->enable = flag; 7543941Svenki *retval = OK; /* we found at least one instance, ok */ 7553941Svenki } 7563941Svenki } 7573941Svenki} 7583941Svenki 7593941Svenki/* 7605723Sfw157321 * define_key -- 7615723Sfw157321 * Add a custom mapping of a key sequence to key symbol. 7625723Sfw157321 * 7633941Svenki */ 7643941Svenkiint 7653941Svenkidefine_key(const char *sequence, int symbol) 7663941Svenki{ 7673941Svenki 7683941Svenki if (symbol <= 0 || _cursesi_screen == NULL) 7693941Svenki return ERR; 7703941Svenki 7713941Svenki if (sequence == NULL) { 7723941Svenki __CTRACE(__CTRACE_INPUT, "define_key: deleting keysym %d\n", 7735723Sfw157321 symbol); 7745723Sfw157321 delete_key_sequence(_cursesi_screen->base_keymap, symbol); 7755723Sfw157321 } else 7763941Svenki add_key_sequence(_cursesi_screen, sequence, symbol); 7773941Svenki 7783941Svenki return OK; 7793941Svenki} 7803941Svenki 7814802Sfw157321/* 7823941Svenki * wgetch -- 7834802Sfw157321 * Read in a character from the window. 7843941Svenki */ 7853941Svenkiint 7863941Svenkiwgetch(WINDOW *win) 7873941Svenki{ 7883941Svenki int inp, weset; 7893941Svenki int c; 7903941Svenki FILE *infd = _cursesi_screen->infd; 7913941Svenki 7923941Svenki __CTRACE(__CTRACE_INPUT, "wgetch: win(%p)\n", win); 7933941Svenki if (win == NULL) 7943941Svenki return ERR; 7953941Svenki if (!(win->flags & __SCROLLOK) && (win->flags & __FULLWIN) 7963941Svenki && win->curx == win->maxx - 1 && win->cury == win->maxy - 1 7973941Svenki && __echoit) 7983941Svenki return ERR; 7993941Svenki 8003941Svenki if (!(win->flags & __ISPAD)) { 8013941Svenki if (is_wintouched(win)) 8023941Svenki wrefresh(win); 8033941Svenki else if (__echoit && ((_cursesi_screen->curscr->cury != (win->begy + win->cury)) 8043941Svenki || (_cursesi_screen->curscr->curx != (win->begx + win->curx)))) { 8053941Svenki __CTRACE(__CTRACE_INPUT, 8063941Svenki "wgetch: curscr cury %d cury %d " 8073941Svenki "curscr curx %d curx %d\n", 8083941Svenki _cursesi_screen->curscr->cury, 8093941Svenki win->begy + win->cury, 8103941Svenki _cursesi_screen->curscr->curx, 8113941Svenki win->begx + win->curx); 8123941Svenki /* 8133941Svenki * Just in case the window is not dirty but the 8143941Svenki * cursor was moved, check and update the 8153941Svenki * cursor location. 8163941Svenki */ 8173941Svenki mvcur(_cursesi_screen->curscr->cury, 8183941Svenki _cursesi_screen->curscr->curx, 8193941Svenki win->cury + win->begy, win->curx + win->begx); 8203941Svenki _cursesi_screen->curscr->cury = 8213941Svenki win->cury + win->begy; 8223941Svenki _cursesi_screen->curscr->curx = 8233941Svenki win->curx + win->begx; 8243941Svenki } 8253941Svenki } 8263941Svenki 8273941Svenki __CTRACE(__CTRACE_INPUT, "wgetch: __echoit = %d, " 8283941Svenki "__rawmode = %d, __nl = %d, flags = %#.4x, delay = %d\n", 8293941Svenki __echoit, __rawmode, _cursesi_screen->nl, win->flags, win->delay); 8303941Svenki if (_cursesi_screen->resized) { 8313941Svenki resizeterm(LINES, COLS); 8323941Svenki _cursesi_screen->resized = 0; 8335723Sfw157321 __CTRACE(__CTRACE_INPUT, "wgetch returning KEY_RESIZE\n"); 8345723Sfw157321 return KEY_RESIZE; 8355723Sfw157321 } 8363941Svenki if (_cursesi_screen->unget_pos) { 8373941Svenki __CTRACE(__CTRACE_INPUT, "wgetch returning char at %d\n", 8383941Svenki _cursesi_screen->unget_pos); 8393941Svenki _cursesi_screen->unget_pos--; 8403941Svenki c = _cursesi_screen->unget_list[_cursesi_screen->unget_pos]; 8413941Svenki if (__echoit) 8423941Svenki waddch(win, (chtype) c); 8433941Svenki return c; 8443941Svenki } 8453941Svenki if (__echoit && !__rawmode) { 8463941Svenki cbreak(); 8473941Svenki weset = 1; 8483941Svenki } else 8493941Svenki weset = 0; 8503941Svenki 8513941Svenki __save_termios(); 8523941Svenki 8533941Svenki if (win->flags & __KEYPAD) { 8543941Svenki switch (win->delay) { 8553941Svenki case -1: 8563941Svenki inp = inkey (win->flags & __NOTIMEOUT ? 0 : 1, 0); 8573941Svenki break; 8583941Svenki case 0: 8593941Svenki if (__nodelay() == ERR) 8603941Svenki return ERR; 8613941Svenki inp = inkey(0, 0); 8623941Svenki break; 8633941Svenki default: 8643941Svenki inp = inkey(win->flags & __NOTIMEOUT ? 0 : 1, win->delay); 8655723Sfw157321 break; 8665723Sfw157321 } 8675723Sfw157321 } else { 8683941Svenki switch (win->delay) { 8693941Svenki case -1: 8703941Svenki if (__delay() == ERR) 8713941Svenki return ERR; 8723941Svenki break; 8733941Svenki case 0: 8743941Svenki if (__nodelay() == ERR) 8753941Svenki return ERR; 8765723Sfw157321 break; 8775723Sfw157321 default: 8785723Sfw157321 if (__timeout(win->delay) == ERR) 8793941Svenki return ERR; 8803941Svenki break; 8813941Svenki } 8823941Svenki 8833941Svenki inp = __fgetc_resize(infd); 8843941Svenki if (inp == ERR || inp == KEY_RESIZE) { 8853941Svenki clearerr(infd); 8863941Svenki __restore_termios(); 8873941Svenki return inp; 8883941Svenki } 8893941Svenki } 8903941Svenki#ifdef DEBUG 8913941Svenki if (inp > 255) 8923941Svenki /* we have a key symbol - treat it differently */ 8933941Svenki /* XXXX perhaps __unctrl should be expanded to include 8943941Svenki * XXXX the keysyms in the table.... 8953941Svenki */ 8963941Svenki __CTRACE(__CTRACE_INPUT, "wgetch assembled keysym 0x%x\n", inp); 8973941Svenki else 8983941Svenki __CTRACE(__CTRACE_INPUT, "wgetch got '%s'\n", unctrl(inp)); 8993941Svenki#endif 9003941Svenki if (win->delay > -1) { 9013941Svenki if (__delay() == ERR) 9023941Svenki return ERR; 9033941Svenki } 9043941Svenki 9053941Svenki __restore_termios(); 9063941Svenki 9073941Svenki if ((__echoit) && (inp < KEY_MIN)) 9083941Svenki waddch(win, (chtype) inp); 9093941Svenki 9103941Svenki if (weset) 9113941Svenki nocbreak(); 9123941Svenki 9133941Svenki if (_cursesi_screen->nl && inp == 13) 9143941Svenki inp = 10; 9153941Svenki 9163941Svenki return ((inp < 0) || (inp == ERR) ? ERR : inp); 9173941Svenki} 9183941Svenki 9193941Svenki/* 9203941Svenki * ungetch -- 9213941Svenki * Put the character back into the input queue. 9223941Svenki */ 9233941Svenkiint 9243941Svenkiungetch(int c) 9253941Svenki{ 9263941Svenki return __unget((wint_t)c); 9273941Svenki} 9283941Svenki 9293941Svenki/* 9303941Svenki * __unget -- 9313941Svenki * Do the work for ungetch() and unget_wch(); 9323941Svenki */ 9333941Svenkiint 9343941Svenki__unget(wint_t c) 9353941Svenki{ 9363941Svenki wchar_t *p; 9373941Svenki int len; 9383941Svenki 9393941Svenki __CTRACE(__CTRACE_INPUT, "__unget(%x)\n", c); 9403941Svenki if (_cursesi_screen == NULL) 9413941Svenki return ERR; 9423941Svenki if (_cursesi_screen->unget_pos >= _cursesi_screen->unget_len) { 9433941Svenki len = _cursesi_screen->unget_len + 32; 9443941Svenki if ((p = realloc(_cursesi_screen->unget_list, 9453941Svenki sizeof(wchar_t) * len)) == NULL) { 9463941Svenki /* Can't realloc(), so just lose the oldest entry */ 9473941Svenki memmove(_cursesi_screen->unget_list, 9483941Svenki _cursesi_screen->unget_list + sizeof(wchar_t), 9493941Svenki _cursesi_screen->unget_len - 1); 9503941Svenki _cursesi_screen->unget_list[_cursesi_screen->unget_len 9513941Svenki - 1] = c; 9523941Svenki _cursesi_screen->unget_pos = 9533941Svenki _cursesi_screen->unget_len; 9543941Svenki return OK; 9553941Svenki } else { 9563941Svenki _cursesi_screen->unget_pos = 9573941Svenki _cursesi_screen->unget_len; 9583941Svenki _cursesi_screen->unget_len = len; 9593941Svenki _cursesi_screen->unget_list = p; 9603941Svenki } 9613941Svenki } 9623941Svenki _cursesi_screen->unget_list[_cursesi_screen->unget_pos] = c; 9633941Svenki _cursesi_screen->unget_pos++; 9643941Svenki return OK; 9653941Svenki} 9663941Svenki 9673941Svenkiint 9683941Svenkihas_key(int key_type) 9693941Svenki{ 9703941Svenki int result = ERR; 9713941Svenki 9723941Svenki if (_cursesi_screen != NULL) 9733941Svenki do_keyok(_cursesi_screen->base_keymap, key_type, 9743941Svenki false, false, &result); 9753941Svenki return result; 9763941Svenki} 9773941Svenki 9783941Svenki/* 9793941Svenki * set_escdelay -- 9803941Svenki * Sets the escape delay for the current screen. 9813941Svenki */ 9823941Svenkiint 9833941Svenkiset_escdelay(int escdelay) 9843941Svenki{ 9853941Svenki 9863941Svenki if (_cursesi_screen == NULL) 9873941Svenki return ERR; 9883941Svenki _cursesi_screen->ESCDELAY = escdelay; 9893941Svenki ESCDELAY = escdelay; 9903941Svenki return OK; 9913941Svenki} 9923941Svenki 9933941Svenki/* 9943941Svenki * __fgetc_resize -- 9953941Svenki * Any call to fgetc(3) should use this function instead 9963941Svenki * and test for the return value of KEY_RESIZE as well as ERR. 9973941Svenki */ 9983941Svenkiint 9993941Svenki__fgetc_resize(FILE *infd) 10003941Svenki{ 10013941Svenki int c; 10023941Svenki 10033941Svenki c = fgetc(infd); 10043941Svenki if (c != EOF) 10053941Svenki return c; 10063941Svenki 10073941Svenki if (!ferror(infd) || errno != EINTR || !_cursesi_screen->resized) 10083941Svenki return ERR; 10093941Svenki __CTRACE(__CTRACE_INPUT, "__fgetc_resize returning KEY_RESIZE\n"); 10103941Svenki resizeterm(LINES, COLS); 10113941Svenki _cursesi_screen->resized = 0; 10123941Svenki return KEY_RESIZE; 10133941Svenki} 10143941Svenki