1 1.79 uwe /* $NetBSD: getch.c,v 1.79 2024/05/14 10:22:48 uwe Exp $ */ 2 1.8 mikel 3 1.1 cgd /* 4 1.7 cgd * Copyright (c) 1981, 1993, 1994 5 1.5 cgd * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.42 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd */ 31 1.1 cgd 32 1.8 mikel #include <sys/cdefs.h> 33 1.1 cgd #ifndef lint 34 1.8 mikel #if 0 35 1.7 cgd static char sccsid[] = "@(#)getch.c 8.2 (Berkeley) 5/4/94"; 36 1.8 mikel #else 37 1.79 uwe __RCSID("$NetBSD: getch.c,v 1.79 2024/05/14 10:22:48 uwe Exp $"); 38 1.8 mikel #endif 39 1.10 mrg #endif /* not lint */ 40 1.1 cgd 41 1.66 rin #include <errno.h> 42 1.10 mrg #include <string.h> 43 1.10 mrg #include <stdlib.h> 44 1.10 mrg #include <unistd.h> 45 1.10 mrg #include <stdio.h> 46 1.7 cgd #include "curses.h" 47 1.16 blymn #include "curses_private.h" 48 1.48 blymn #include "keymap.h" 49 1.1 cgd 50 1.71 rin short _cursesi_state; /* state of the inkey function */ 51 1.10 mrg 52 1.13 simonb static const struct tcdata tc[] = { 53 1.55 roy {TICODE_kSAV, KEY_SSAVE}, 54 1.55 roy {TICODE_kSPD, KEY_SSUSPEND}, 55 1.55 roy {TICODE_kUND, KEY_SUNDO}, 56 1.55 roy {TICODE_kHLP, KEY_SHELP}, 57 1.55 roy {TICODE_kHOM, KEY_SHOME}, 58 1.55 roy {TICODE_kIC, KEY_SIC}, 59 1.55 roy {TICODE_kLFT, KEY_SLEFT}, 60 1.55 roy {TICODE_krdo, KEY_REDO}, 61 1.55 roy {TICODE_khlp, KEY_HELP}, 62 1.55 roy {TICODE_kmrk, KEY_MARK}, 63 1.55 roy {TICODE_kmsg, KEY_MESSAGE}, 64 1.55 roy {TICODE_kmov, KEY_MOVE}, 65 1.55 roy {TICODE_knxt, KEY_NEXT}, 66 1.55 roy {TICODE_kopn, KEY_OPEN}, 67 1.55 roy {TICODE_kopt, KEY_OPTIONS}, 68 1.55 roy {TICODE_kprv, KEY_PREVIOUS}, 69 1.55 roy {TICODE_kprt, KEY_PRINT}, 70 1.55 roy {TICODE_kMSG, KEY_SMESSAGE}, 71 1.55 roy {TICODE_kMOV, KEY_SMOVE}, 72 1.55 roy {TICODE_kNXT, KEY_SNEXT}, 73 1.55 roy {TICODE_kOPT, KEY_SOPTIONS}, 74 1.55 roy {TICODE_kPRV, KEY_SPREVIOUS}, 75 1.55 roy {TICODE_kPRT, KEY_SPRINT}, 76 1.55 roy {TICODE_kRDO, KEY_SREDO}, 77 1.55 roy {TICODE_kRPL, KEY_SREPLACE}, 78 1.55 roy {TICODE_kRIT, KEY_SRIGHT}, 79 1.55 roy {TICODE_kRES, KEY_SRSUME}, 80 1.55 roy {TICODE_kCAN, KEY_SCANCEL}, 81 1.55 roy {TICODE_kref, KEY_REFERENCE}, 82 1.55 roy {TICODE_krfr, KEY_REFRESH}, 83 1.55 roy {TICODE_krpl, KEY_REPLACE}, 84 1.55 roy {TICODE_krst, KEY_RESTART}, 85 1.55 roy {TICODE_kres, KEY_RESUME}, 86 1.55 roy {TICODE_ksav, KEY_SAVE}, 87 1.55 roy {TICODE_kspd, KEY_SUSPEND}, 88 1.55 roy {TICODE_kund, KEY_UNDO}, 89 1.55 roy {TICODE_kBEG, KEY_SBEG}, 90 1.55 roy {TICODE_kFND, KEY_SFIND}, 91 1.55 roy {TICODE_kCMD, KEY_SCOMMAND}, 92 1.55 roy {TICODE_kCPY, KEY_SCOPY}, 93 1.55 roy {TICODE_kCRT, KEY_SCREATE}, 94 1.55 roy {TICODE_kDC, KEY_SDC}, 95 1.55 roy {TICODE_kDL, KEY_SDL}, 96 1.55 roy {TICODE_kslt, KEY_SELECT}, 97 1.55 roy {TICODE_kEND, KEY_SEND}, 98 1.55 roy {TICODE_kEOL, KEY_SEOL}, 99 1.55 roy {TICODE_kEXT, KEY_SEXIT}, 100 1.55 roy {TICODE_kfnd, KEY_FIND}, 101 1.55 roy {TICODE_kbeg, KEY_BEG}, 102 1.55 roy {TICODE_kcan, KEY_CANCEL}, 103 1.55 roy {TICODE_kclo, KEY_CLOSE}, 104 1.55 roy {TICODE_kcmd, KEY_COMMAND}, 105 1.55 roy {TICODE_kcpy, KEY_COPY}, 106 1.55 roy {TICODE_kcrt, KEY_CREATE}, 107 1.55 roy {TICODE_kend, KEY_END}, 108 1.55 roy {TICODE_kent, KEY_ENTER}, 109 1.55 roy {TICODE_kext, KEY_EXIT}, 110 1.55 roy {TICODE_kf11, KEY_F(11)}, 111 1.55 roy {TICODE_kf12, KEY_F(12)}, 112 1.55 roy {TICODE_kf13, KEY_F(13)}, 113 1.55 roy {TICODE_kf14, KEY_F(14)}, 114 1.55 roy {TICODE_kf15, KEY_F(15)}, 115 1.55 roy {TICODE_kf16, KEY_F(16)}, 116 1.55 roy {TICODE_kf17, KEY_F(17)}, 117 1.55 roy {TICODE_kf18, KEY_F(18)}, 118 1.55 roy {TICODE_kf19, KEY_F(19)}, 119 1.55 roy {TICODE_kf20, KEY_F(20)}, 120 1.55 roy {TICODE_kf21, KEY_F(21)}, 121 1.55 roy {TICODE_kf22, KEY_F(22)}, 122 1.55 roy {TICODE_kf23, KEY_F(23)}, 123 1.55 roy {TICODE_kf24, KEY_F(24)}, 124 1.55 roy {TICODE_kf25, KEY_F(25)}, 125 1.55 roy {TICODE_kf26, KEY_F(26)}, 126 1.55 roy {TICODE_kf27, KEY_F(27)}, 127 1.55 roy {TICODE_kf28, KEY_F(28)}, 128 1.55 roy {TICODE_kf29, KEY_F(29)}, 129 1.55 roy {TICODE_kf30, KEY_F(30)}, 130 1.55 roy {TICODE_kf31, KEY_F(31)}, 131 1.55 roy {TICODE_kf32, KEY_F(32)}, 132 1.55 roy {TICODE_kf33, KEY_F(33)}, 133 1.55 roy {TICODE_kf34, KEY_F(34)}, 134 1.55 roy {TICODE_kf35, KEY_F(35)}, 135 1.55 roy {TICODE_kf36, KEY_F(36)}, 136 1.55 roy {TICODE_kf37, KEY_F(37)}, 137 1.55 roy {TICODE_kf38, KEY_F(38)}, 138 1.55 roy {TICODE_kf39, KEY_F(39)}, 139 1.55 roy {TICODE_kf40, KEY_F(40)}, 140 1.55 roy {TICODE_kf41, KEY_F(41)}, 141 1.55 roy {TICODE_kf42, KEY_F(42)}, 142 1.55 roy {TICODE_kf43, KEY_F(43)}, 143 1.55 roy {TICODE_kf44, KEY_F(44)}, 144 1.55 roy {TICODE_kf45, KEY_F(45)}, 145 1.55 roy {TICODE_kf46, KEY_F(46)}, 146 1.55 roy {TICODE_kf47, KEY_F(47)}, 147 1.55 roy {TICODE_kf48, KEY_F(48)}, 148 1.55 roy {TICODE_kf49, KEY_F(49)}, 149 1.55 roy {TICODE_kf50, KEY_F(50)}, 150 1.55 roy {TICODE_kf51, KEY_F(51)}, 151 1.55 roy {TICODE_kf52, KEY_F(52)}, 152 1.55 roy {TICODE_kf53, KEY_F(53)}, 153 1.55 roy {TICODE_kf54, KEY_F(54)}, 154 1.55 roy {TICODE_kf55, KEY_F(55)}, 155 1.55 roy {TICODE_kf56, KEY_F(56)}, 156 1.55 roy {TICODE_kf57, KEY_F(57)}, 157 1.55 roy {TICODE_kf58, KEY_F(58)}, 158 1.55 roy {TICODE_kf59, KEY_F(59)}, 159 1.55 roy {TICODE_kf60, KEY_F(60)}, 160 1.55 roy {TICODE_kf61, KEY_F(61)}, 161 1.55 roy {TICODE_kf62, KEY_F(62)}, 162 1.55 roy {TICODE_kf63, KEY_F(63)}, 163 1.55 roy {TICODE_ka1, KEY_A1}, 164 1.55 roy {TICODE_kb2, KEY_B2}, 165 1.55 roy {TICODE_ka3, KEY_A3}, 166 1.55 roy {TICODE_kc1, KEY_C1}, 167 1.55 roy {TICODE_kc3, KEY_C3}, 168 1.55 roy {TICODE_kmous, KEY_MOUSE}, 169 1.55 roy {TICODE_kf0, KEY_F0}, 170 1.55 roy {TICODE_kf1, KEY_F(1)}, 171 1.55 roy {TICODE_kf2, KEY_F(2)}, 172 1.55 roy {TICODE_kf3, KEY_F(3)}, 173 1.55 roy {TICODE_kf4, KEY_F(4)}, 174 1.55 roy {TICODE_kf5, KEY_F(5)}, 175 1.55 roy {TICODE_kf6, KEY_F(6)}, 176 1.55 roy {TICODE_kf7, KEY_F(7)}, 177 1.55 roy {TICODE_kf8, KEY_F(8)}, 178 1.55 roy {TICODE_kf9, KEY_F(9)}, 179 1.55 roy {TICODE_kf10, KEY_F(10)}, 180 1.55 roy {TICODE_kil1, KEY_IL}, 181 1.55 roy {TICODE_ktbc, KEY_CATAB}, 182 1.55 roy {TICODE_kcbt, KEY_BTAB}, 183 1.55 roy {TICODE_kbs, KEY_BACKSPACE}, 184 1.55 roy {TICODE_kclr, KEY_CLEAR}, 185 1.55 roy {TICODE_kdch1, KEY_DC}, 186 1.55 roy {TICODE_kcud1, KEY_DOWN}, 187 1.55 roy {TICODE_kel, KEY_EOL}, 188 1.55 roy {TICODE_kind, KEY_SF}, 189 1.55 roy {TICODE_kll, KEY_LL}, 190 1.55 roy {TICODE_khome, KEY_HOME}, 191 1.55 roy {TICODE_kich1, KEY_IC}, 192 1.55 roy {TICODE_kdl1, KEY_DL}, 193 1.55 roy {TICODE_kcub1, KEY_LEFT}, 194 1.55 roy {TICODE_krmir, KEY_EIC}, 195 1.55 roy {TICODE_knp, KEY_NPAGE}, 196 1.55 roy {TICODE_kpp, KEY_PPAGE}, 197 1.55 roy {TICODE_kri, KEY_SR}, 198 1.55 roy {TICODE_kcuf1, KEY_RIGHT}, 199 1.55 roy {TICODE_ked, KEY_EOS}, 200 1.55 roy {TICODE_khts, KEY_STAB}, 201 1.55 roy {TICODE_kctab, KEY_CTAB}, 202 1.55 roy {TICODE_kcuu1, KEY_UP} 203 1.10 mrg }; 204 1.10 mrg /* Number of TC entries .... */ 205 1.13 simonb static const int num_tcs = (sizeof(tc) / sizeof(struct tcdata)); 206 1.10 mrg 207 1.48 blymn /* Key buffer */ 208 1.48 blymn #define INBUF_SZ 16 /* size of key buffer - must be larger than 209 1.48 blymn * longest multi-key sequence */ 210 1.50 jdc static wchar_t inbuf[INBUF_SZ]; 211 1.50 jdc static int start, end, working; /* pointers for manipulating inbuf data */ 212 1.48 blymn 213 1.10 mrg /* prototypes for private functions */ 214 1.79 uwe static void add_key_sequence(SCREEN *screen, const char *sequence, int key_type); 215 1.48 blymn static key_entry_t *add_new_key(keymap_t *current, char ch, int key_type, 216 1.48 blymn int symbol); 217 1.37 blymn static void delete_key_sequence(keymap_t *current, int key_type); 218 1.60 roy static void do_keyok(keymap_t *current, int key_type, bool set, bool flag, 219 1.60 roy int *retval); 220 1.48 blymn static keymap_t *new_keymap(void); /* create a new keymap */ 221 1.48 blymn static key_entry_t *new_key(void); /* create a new key entry */ 222 1.20 blymn static wchar_t inkey(int to, int delay); 223 1.20 blymn 224 1.20 blymn /* 225 1.35 blymn * Free the storage associated with the given keymap 226 1.35 blymn */ 227 1.35 blymn void 228 1.35 blymn _cursesi_free_keymap(keymap_t *map) 229 1.35 blymn { 230 1.35 blymn int i; 231 1.35 blymn 232 1.35 blymn /* check for, and free, child keymaps */ 233 1.35 blymn for (i = 0; i < MAX_CHAR; i++) { 234 1.35 blymn if (map->mapping[i] >= 0) { 235 1.35 blymn if (map->key[map->mapping[i]]->type == KEYMAP_MULTI) 236 1.35 blymn _cursesi_free_keymap( 237 1.35 blymn map->key[map->mapping[i]]->value.next); 238 1.35 blymn } 239 1.35 blymn } 240 1.35 blymn 241 1.35 blymn /* now free any allocated keymap structs */ 242 1.35 blymn for (i = 0; i < map->count; i += KEYMAP_ALLOC_CHUNK) { 243 1.35 blymn free(map->key[i]); 244 1.35 blymn } 245 1.36 blymn 246 1.35 blymn free(map->key); 247 1.35 blymn free(map); 248 1.35 blymn } 249 1.35 blymn 250 1.48 blymn 251 1.35 blymn /* 252 1.20 blymn * Add a new key entry to the keymap pointed to by current. Entry 253 1.20 blymn * contains the character to add to the keymap, type is the type of 254 1.20 blymn * entry to add (either multikey or leaf) and symbol is the symbolic 255 1.20 blymn * value for a leaf type entry. The function returns a pointer to the 256 1.20 blymn * new keymap entry. 257 1.20 blymn */ 258 1.20 blymn static key_entry_t * 259 1.20 blymn add_new_key(keymap_t *current, char chr, int key_type, int symbol) 260 1.20 blymn { 261 1.20 blymn key_entry_t *the_key; 262 1.37 blymn int i, ki; 263 1.20 blymn 264 1.47 jdc __CTRACE(__CTRACE_MISC, 265 1.47 jdc "Adding character %s of type %d, symbol 0x%x\n", 266 1.47 jdc unctrl(chr), key_type, symbol); 267 1.62 roy if (current->mapping[(unsigned char)chr] < 0) { 268 1.62 roy if (current->mapping[(unsigned char)chr] == MAPPING_UNUSED) { 269 1.37 blymn /* first time for this char */ 270 1.62 roy current->mapping[(unsigned char)chr] = 271 1.37 blymn current->count; /* map new entry */ 272 1.37 blymn ki = current->count; 273 1.48 blymn 274 1.37 blymn /* make sure we have room in the key array first */ 275 1.37 blymn if ((current->count & (KEYMAP_ALLOC_CHUNK - 1)) == 0) 276 1.37 blymn { 277 1.37 blymn if ((current->key = 278 1.37 blymn realloc(current->key, 279 1.37 blymn ki * sizeof(key_entry_t *) 280 1.37 blymn + KEYMAP_ALLOC_CHUNK * sizeof(key_entry_t *))) == NULL) { 281 1.37 blymn fprintf(stderr, 282 1.37 blymn "Could not malloc for key entry\n"); 283 1.37 blymn exit(1); 284 1.37 blymn } 285 1.48 blymn 286 1.37 blymn the_key = new_key(); 287 1.37 blymn for (i = 0; i < KEYMAP_ALLOC_CHUNK; i++) { 288 1.37 blymn current->key[ki + i] = &the_key[i]; 289 1.37 blymn } 290 1.20 blymn } 291 1.37 blymn } else { 292 1.37 blymn /* the mapping was used but freed, reuse it */ 293 1.37 blymn ki = - current->mapping[(unsigned char) chr]; 294 1.37 blymn current->mapping[(unsigned char) chr] = ki; 295 1.37 blymn } 296 1.48 blymn 297 1.37 blymn current->count++; 298 1.48 blymn 299 1.37 blymn /* point at the current key array element to use */ 300 1.37 blymn the_key = current->key[ki]; 301 1.48 blymn 302 1.20 blymn the_key->type = key_type; 303 1.20 blymn 304 1.20 blymn switch (key_type) { 305 1.77 rin case KEYMAP_MULTI: 306 1.77 rin /* need for next key */ 307 1.77 rin __CTRACE(__CTRACE_MISC, "Creating new keymap\n"); 308 1.77 rin the_key->value.next = new_keymap(); 309 1.77 rin the_key->enable = TRUE; 310 1.77 rin break; 311 1.77 rin 312 1.77 rin case KEYMAP_LEAF: 313 1.77 rin /* the associated symbol for the key */ 314 1.77 rin __CTRACE(__CTRACE_MISC, "Adding leaf key\n"); 315 1.77 rin the_key->value.symbol = symbol; 316 1.77 rin the_key->enable = TRUE; 317 1.77 rin break; 318 1.77 rin 319 1.77 rin default: 320 1.77 rin fprintf(stderr, "add_new_key: bad type passed\n"); 321 1.77 rin exit(1); 322 1.20 blymn } 323 1.20 blymn } else { 324 1.77 rin /* the key is already known - just return the address. */ 325 1.47 jdc __CTRACE(__CTRACE_MISC, "Keymap already known\n"); 326 1.62 roy the_key = current->key[current->mapping[(unsigned char)chr]]; 327 1.20 blymn } 328 1.20 blymn 329 1.20 blymn return the_key; 330 1.20 blymn } 331 1.10 mrg 332 1.10 mrg /* 333 1.37 blymn * Delete the given key symbol from the key mappings for the screen. 334 1.37 blymn * 335 1.37 blymn */ 336 1.64 roy static void 337 1.37 blymn delete_key_sequence(keymap_t *current, int key_type) 338 1.37 blymn { 339 1.37 blymn key_entry_t *key; 340 1.37 blymn int i; 341 1.37 blymn 342 1.37 blymn /* 343 1.37 blymn * we need to iterate over all the keys as there may be 344 1.37 blymn * multiple instances of the leaf symbol. 345 1.37 blymn */ 346 1.37 blymn for (i = 0; i < MAX_CHAR; i++) { 347 1.37 blymn if (current->mapping[i] < 0) 348 1.37 blymn continue; /* no mapping for the key, next! */ 349 1.37 blymn 350 1.37 blymn key = current->key[current->mapping[i]]; 351 1.37 blymn 352 1.37 blymn if (key->type == KEYMAP_MULTI) { 353 1.37 blymn /* have not found the leaf, recurse down */ 354 1.37 blymn delete_key_sequence(key->value.next, key_type); 355 1.37 blymn /* if we deleted the last key in the map, free */ 356 1.37 blymn if (key->value.next->count == 0) 357 1.37 blymn _cursesi_free_keymap(key->value.next); 358 1.37 blymn } else if ((key->type == KEYMAP_LEAF) 359 1.37 blymn && (key->value.symbol == key_type)) { 360 1.77 rin __CTRACE(__CTRACE_INPUT, 361 1.77 rin "delete_key_sequence: found keysym %d, deleting\n", 362 1.58 blymn key_type); 363 1.58 blymn key->enable = FALSE; 364 1.37 blymn } 365 1.37 blymn } 366 1.37 blymn } 367 1.48 blymn 368 1.37 blymn /* 369 1.37 blymn * Add the sequence of characters given in sequence as the key mapping 370 1.37 blymn * for the given key symbol. 371 1.37 blymn */ 372 1.64 roy static void 373 1.79 uwe add_key_sequence(SCREEN *screen, const char *sequence, int key_type) 374 1.37 blymn { 375 1.37 blymn key_entry_t *tmp_key; 376 1.37 blymn keymap_t *current; 377 1.37 blymn int length, j, key_ent; 378 1.37 blymn 379 1.48 blymn __CTRACE(__CTRACE_MISC, "add_key_sequence: add key sequence: %s(%s)\n", 380 1.48 blymn sequence, keyname(key_type)); 381 1.37 blymn current = screen->base_keymap; /* always start with 382 1.37 blymn * base keymap. */ 383 1.62 roy length = (int)strlen(sequence); 384 1.37 blymn 385 1.49 blymn /* 386 1.49 blymn * OK - we really should never get a zero length string here, either 387 1.59 roy * the terminfo entry is there and it has a value or we are not called 388 1.59 roy * at all. Unfortunately, if someone assigns a terminfo string to the 389 1.49 blymn * ^@ value we get passed a null string which messes up our length. 390 1.49 blymn * So, if we get a null string then just insert a leaf value in 391 1.49 blymn * the 0th char position of the root keymap. Note that we are 392 1.49 blymn * totally screwed if someone terminates a multichar sequence 393 1.49 blymn * with ^@... oh well. 394 1.49 blymn */ 395 1.49 blymn if (length == 0) 396 1.49 blymn length = 1; 397 1.49 blymn 398 1.37 blymn for (j = 0; j < length - 1; j++) { 399 1.37 blymn /* add the entry to the struct */ 400 1.37 blymn tmp_key = add_new_key(current, sequence[j], KEYMAP_MULTI, 0); 401 1.48 blymn 402 1.37 blymn /* index into the key array - it's 403 1.37 blymn clearer if we stash this */ 404 1.37 blymn key_ent = current->mapping[(unsigned char) sequence[j]]; 405 1.37 blymn 406 1.37 blymn current->key[key_ent] = tmp_key; 407 1.48 blymn 408 1.37 blymn /* next key uses this map... */ 409 1.37 blymn current = current->key[key_ent]->value.next; 410 1.37 blymn } 411 1.37 blymn 412 1.37 blymn /* 413 1.37 blymn * This is the last key in the sequence (it may have been the 414 1.37 blymn * only one but that does not matter) this means it is a leaf 415 1.37 blymn * key and should have a symbol associated with it. 416 1.37 blymn */ 417 1.37 blymn tmp_key = add_new_key(current, sequence[length - 1], KEYMAP_LEAF, 418 1.37 blymn key_type); 419 1.37 blymn current->key[current->mapping[(int)sequence[length - 1]]] = tmp_key; 420 1.37 blymn } 421 1.37 blymn 422 1.37 blymn /* 423 1.10 mrg * Init_getch - initialise all the pointers & structures needed to make 424 1.10 mrg * getch work in keypad mode. 425 1.10 mrg * 426 1.10 mrg */ 427 1.10 mrg void 428 1.35 blymn __init_getch(SCREEN *screen) 429 1.10 mrg { 430 1.27 blymn char entry[1024], *p; 431 1.55 roy const char *s; 432 1.37 blymn int i; 433 1.55 roy size_t limit, l; 434 1.20 blymn #ifdef DEBUG 435 1.37 blymn int k, length; 436 1.20 blymn #endif 437 1.10 mrg 438 1.10 mrg /* init the inkey state variable */ 439 1.71 rin _cursesi_state = INKEY_NORM; 440 1.10 mrg 441 1.10 mrg /* init the base keymap */ 442 1.35 blymn screen->base_keymap = new_keymap(); 443 1.10 mrg 444 1.10 mrg /* key input buffer pointers */ 445 1.10 mrg start = end = working = 0; 446 1.10 mrg 447 1.55 roy /* now do the terminfo snarfing ... */ 448 1.35 blymn 449 1.27 blymn for (i = 0; i < num_tcs; i++) { 450 1.27 blymn p = entry; 451 1.27 blymn limit = 1023; 452 1.55 roy s = screen->term->strs[tc[i].code]; 453 1.55 roy if (s == NULL) 454 1.55 roy continue; 455 1.55 roy l = strlen(s) + 1; 456 1.57 joerg if (limit < l) 457 1.55 roy continue; 458 1.55 roy strlcpy(p, s, limit); 459 1.55 roy p += l; 460 1.55 roy limit -= l; 461 1.20 blymn #ifdef DEBUG 462 1.47 jdc __CTRACE(__CTRACE_INIT, 463 1.59 roy "Processing terminfo entry %d, sequence ", 464 1.55 roy tc[i].code); 465 1.37 blymn length = (int) strlen(entry); 466 1.27 blymn for (k = 0; k <= length -1; k++) 467 1.47 jdc __CTRACE(__CTRACE_INIT, "%s", unctrl(entry[k])); 468 1.47 jdc __CTRACE(__CTRACE_INIT, "\n"); 469 1.27 blymn #endif 470 1.55 roy add_key_sequence(screen, entry, tc[i].symbol); 471 1.10 mrg } 472 1.10 mrg } 473 1.10 mrg 474 1.10 mrg 475 1.10 mrg /* 476 1.10 mrg * new_keymap - allocates & initialises a new keymap structure. This 477 1.10 mrg * function returns a pointer to the new keymap. 478 1.10 mrg * 479 1.10 mrg */ 480 1.13 simonb static keymap_t * 481 1.10 mrg new_keymap(void) 482 1.10 mrg { 483 1.10 mrg int i; 484 1.10 mrg keymap_t *new_map; 485 1.10 mrg 486 1.10 mrg if ((new_map = malloc(sizeof(keymap_t))) == NULL) { 487 1.10 mrg perror("Inkey: Cannot allocate new keymap"); 488 1.10 mrg exit(2); 489 1.10 mrg } 490 1.12 pk 491 1.12 pk /* Initialise the new map */ 492 1.10 mrg new_map->count = 0; 493 1.10 mrg for (i = 0; i < MAX_CHAR; i++) { 494 1.37 blymn new_map->mapping[i] = MAPPING_UNUSED; /* no mapping for char */ 495 1.10 mrg } 496 1.10 mrg 497 1.23 thorpej /* key array will be allocated when first key is added */ 498 1.23 thorpej new_map->key = NULL; 499 1.23 thorpej 500 1.20 blymn return new_map; 501 1.10 mrg } 502 1.10 mrg 503 1.10 mrg /* 504 1.10 mrg * new_key - allocates & initialises a new key entry. This function returns 505 1.10 mrg * a pointer to the newly allocated key entry. 506 1.10 mrg * 507 1.10 mrg */ 508 1.13 simonb static key_entry_t * 509 1.10 mrg new_key(void) 510 1.10 mrg { 511 1.10 mrg key_entry_t *new_one; 512 1.20 blymn int i; 513 1.36 blymn 514 1.62 roy new_one = malloc(KEYMAP_ALLOC_CHUNK * sizeof(key_entry_t)); 515 1.62 roy if (new_one == NULL) { 516 1.20 blymn perror("inkey: Cannot allocate new key entry chunk"); 517 1.10 mrg exit(2); 518 1.10 mrg } 519 1.10 mrg 520 1.20 blymn for (i = 0; i < KEYMAP_ALLOC_CHUNK; i++) { 521 1.20 blymn new_one[i].type = 0; 522 1.20 blymn new_one[i].value.next = NULL; 523 1.20 blymn } 524 1.36 blymn 525 1.20 blymn return new_one; 526 1.10 mrg } 527 1.10 mrg 528 1.10 mrg /* 529 1.10 mrg * inkey - do the work to process keyboard input, check for multi-key 530 1.10 mrg * sequences and return the appropriate symbol if we get a match. 531 1.10 mrg * 532 1.10 mrg */ 533 1.10 mrg 534 1.64 roy static wchar_t 535 1.20 blymn inkey(int to, int delay) 536 1.10 mrg { 537 1.21 jdc wchar_t k; 538 1.37 blymn int c, mapping; 539 1.35 blymn keymap_t *current = _cursesi_screen->base_keymap; 540 1.35 blymn FILE *infd = _cursesi_screen->infd; 541 1.10 mrg 542 1.25 jdc k = 0; /* XXX gcc -Wuninitialized */ 543 1.25 jdc 544 1.47 jdc __CTRACE(__CTRACE_INPUT, "inkey (%d, %d)\n", to, delay); 545 1.10 mrg for (;;) { /* loop until we get a complete key sequence */ 546 1.10 mrg reread: 547 1.71 rin if (_cursesi_state == INKEY_NORM) { 548 1.10 mrg if (delay && __timeout(delay) == ERR) 549 1.10 mrg return ERR; 550 1.68 roy c = __fgetc_resize(infd); 551 1.68 roy if (c == ERR || c == KEY_RESIZE) { 552 1.35 blymn clearerr(infd); 553 1.68 roy return c; 554 1.22 blymn } 555 1.48 blymn 556 1.10 mrg if (delay && (__notimeout() == ERR)) 557 1.10 mrg return ERR; 558 1.22 blymn 559 1.62 roy k = (wchar_t)c; 560 1.47 jdc __CTRACE(__CTRACE_INPUT, 561 1.47 jdc "inkey (state normal) got '%s'\n", unctrl(k)); 562 1.10 mrg 563 1.10 mrg working = start; 564 1.10 mrg inbuf[working] = k; 565 1.10 mrg INC_POINTER(working); 566 1.10 mrg end = working; 567 1.71 rin 568 1.71 rin /* go to the assembling state now */ 569 1.71 rin _cursesi_state = INKEY_ASSEMBLING; 570 1.71 rin 571 1.71 rin } else if (_cursesi_state == INKEY_BACKOUT) { 572 1.12 pk k = inbuf[working]; 573 1.12 pk INC_POINTER(working); 574 1.12 pk if (working == end) { /* see if we have run 575 1.12 pk * out of keys in the 576 1.12 pk * backlog */ 577 1.12 pk 578 1.41 jdc /* if we have then switch to assembling */ 579 1.71 rin _cursesi_state = INKEY_ASSEMBLING; 580 1.12 pk } 581 1.71 rin } else if (_cursesi_state == INKEY_ASSEMBLING) { 582 1.12 pk /* assembling a key sequence */ 583 1.12 pk if (delay) { 584 1.65 roy if (__timeout(to ? (ESCDELAY / 100) : delay) 585 1.41 jdc == ERR) 586 1.41 jdc return ERR; 587 1.12 pk } else { 588 1.65 roy if (to && (__timeout(ESCDELAY / 100) == ERR)) 589 1.10 mrg return ERR; 590 1.12 pk } 591 1.22 blymn 592 1.68 roy c = __fgetc_resize(infd); 593 1.52 jdc if (ferror(infd)) { 594 1.35 blymn clearerr(infd); 595 1.68 roy return c; 596 1.22 blymn } 597 1.48 blymn 598 1.12 pk if ((to || delay) && (__notimeout() == ERR)) 599 1.10 mrg return ERR; 600 1.14 simonb 601 1.47 jdc __CTRACE(__CTRACE_INPUT, 602 1.47 jdc "inkey (state assembling) got '%s'\n", unctrl(k)); 603 1.52 jdc if (feof(infd) || c == -1) { /* inter-char timeout, 604 1.52 jdc * start backing out */ 605 1.35 blymn clearerr(infd); 606 1.12 pk if (start == end) 607 1.12 pk /* no chars in the buffer, restart */ 608 1.12 pk goto reread; 609 1.12 pk 610 1.12 pk k = inbuf[start]; 611 1.71 rin _cursesi_state = INKEY_TIMEOUT; 612 1.10 mrg } else { 613 1.52 jdc k = (wchar_t) c; 614 1.12 pk inbuf[working] = k; 615 1.12 pk INC_POINTER(working); 616 1.12 pk end = working; 617 1.10 mrg } 618 1.12 pk } else { 619 1.12 pk fprintf(stderr, "Inkey state screwed - exiting!!!"); 620 1.12 pk exit(2); 621 1.12 pk } 622 1.10 mrg 623 1.37 blymn /* 624 1.37 blymn * Check key has no special meaning and we have not 625 1.37 blymn * timed out and the key has not been disabled 626 1.37 blymn */ 627 1.37 blymn mapping = current->mapping[k]; 628 1.71 rin if (((_cursesi_state == INKEY_TIMEOUT) || (mapping < 0)) 629 1.37 blymn || ((current->key[mapping]->type == KEYMAP_LEAF) 630 1.37 blymn && (current->key[mapping]->enable == FALSE))) { 631 1.12 pk /* return the first key we know about */ 632 1.12 pk k = inbuf[start]; 633 1.10 mrg 634 1.10 mrg INC_POINTER(start); 635 1.10 mrg working = start; 636 1.10 mrg 637 1.10 mrg if (start == end) { /* only one char processed */ 638 1.71 rin _cursesi_state = INKEY_NORM; 639 1.10 mrg } else {/* otherwise we must have more than one char 640 1.10 mrg * to backout */ 641 1.71 rin _cursesi_state = INKEY_BACKOUT; 642 1.10 mrg } 643 1.10 mrg return k; 644 1.10 mrg } else { /* must be part of a multikey sequence */ 645 1.10 mrg /* check for completed key sequence */ 646 1.10 mrg if (current->key[current->mapping[k]]->type == KEYMAP_LEAF) { 647 1.10 mrg start = working; /* eat the key sequence 648 1.10 mrg * in inbuf */ 649 1.10 mrg 650 1.12 pk /* check if inbuf empty now */ 651 1.12 pk if (start == end) { 652 1.12 pk /* if it is go back to normal */ 653 1.71 rin _cursesi_state = INKEY_NORM; 654 1.12 pk } else { 655 1.12 pk /* otherwise go to backout state */ 656 1.71 rin _cursesi_state = INKEY_BACKOUT; 657 1.10 mrg } 658 1.10 mrg 659 1.10 mrg /* return the symbol */ 660 1.10 mrg return current->key[current->mapping[k]]->value.symbol; 661 1.10 mrg 662 1.12 pk } else { 663 1.12 pk /* 664 1.12 pk * Step on to next part of the multi-key 665 1.12 pk * sequence. 666 1.12 pk */ 667 1.10 mrg current = current->key[current->mapping[k]]->value.next; 668 1.10 mrg } 669 1.10 mrg } 670 1.10 mrg } 671 1.10 mrg } 672 1.10 mrg 673 1.18 blymn #ifndef _CURSES_USE_MACROS 674 1.18 blymn /* 675 1.18 blymn * getch -- 676 1.18 blymn * Read in a character from stdscr. 677 1.18 blymn */ 678 1.18 blymn int 679 1.18 blymn getch(void) 680 1.18 blymn { 681 1.18 blymn return wgetch(stdscr); 682 1.18 blymn } 683 1.18 blymn 684 1.18 blymn /* 685 1.18 blymn * mvgetch -- 686 1.18 blymn * Read in a character from stdscr at the given location. 687 1.18 blymn */ 688 1.18 blymn int 689 1.18 blymn mvgetch(int y, int x) 690 1.18 blymn { 691 1.18 blymn return mvwgetch(stdscr, y, x); 692 1.18 blymn } 693 1.18 blymn 694 1.18 blymn /* 695 1.18 blymn * mvwgetch -- 696 1.18 blymn * Read in a character from stdscr at the given location in the 697 1.18 blymn * given window. 698 1.18 blymn */ 699 1.18 blymn int 700 1.18 blymn mvwgetch(WINDOW *win, int y, int x) 701 1.18 blymn { 702 1.73 blymn if (wmove(win, y, x) == ERR) 703 1.18 blymn return ERR; 704 1.18 blymn 705 1.18 blymn return wgetch(win); 706 1.18 blymn } 707 1.18 blymn 708 1.18 blymn #endif 709 1.18 blymn 710 1.37 blymn /* 711 1.37 blymn * keyok -- 712 1.37 blymn * Set the enable flag for a keysym, if the flag is false then 713 1.37 blymn * getch will not return this keysym even if the matching key sequence 714 1.37 blymn * is seen. 715 1.37 blymn */ 716 1.37 blymn int 717 1.37 blymn keyok(int key_type, bool flag) 718 1.37 blymn { 719 1.37 blymn int result = ERR; 720 1.48 blymn 721 1.64 roy if (_cursesi_screen != NULL) 722 1.64 roy do_keyok(_cursesi_screen->base_keymap, key_type, 723 1.64 roy true, flag, &result); 724 1.37 blymn return result; 725 1.37 blymn } 726 1.37 blymn 727 1.37 blymn /* 728 1.37 blymn * do_keyok -- 729 1.37 blymn * Does the actual work for keyok, we need to recurse through the 730 1.37 blymn * keymaps finding the passed key symbol. 731 1.37 blymn */ 732 1.60 roy static void 733 1.60 roy do_keyok(keymap_t *current, int key_type, bool set, bool flag, int *retval) 734 1.37 blymn { 735 1.37 blymn key_entry_t *key; 736 1.37 blymn int i; 737 1.37 blymn 738 1.37 blymn /* 739 1.37 blymn * we need to iterate over all the keys as there may be 740 1.37 blymn * multiple instances of the leaf symbol. 741 1.37 blymn */ 742 1.37 blymn for (i = 0; i < MAX_CHAR; i++) { 743 1.37 blymn if (current->mapping[i] < 0) 744 1.37 blymn continue; /* no mapping for the key, next! */ 745 1.37 blymn 746 1.37 blymn key = current->key[current->mapping[i]]; 747 1.37 blymn 748 1.37 blymn if (key->type == KEYMAP_MULTI) 749 1.60 roy do_keyok(key->value.next, key_type, set, flag, retval); 750 1.37 blymn else if ((key->type == KEYMAP_LEAF) 751 1.37 blymn && (key->value.symbol == key_type)) { 752 1.60 roy if (set) 753 1.60 roy key->enable = flag; 754 1.37 blymn *retval = OK; /* we found at least one instance, ok */ 755 1.37 blymn } 756 1.37 blymn } 757 1.37 blymn } 758 1.37 blymn 759 1.37 blymn /* 760 1.37 blymn * define_key -- 761 1.37 blymn * Add a custom mapping of a key sequence to key symbol. 762 1.37 blymn * 763 1.37 blymn */ 764 1.37 blymn int 765 1.79 uwe define_key(const char *sequence, int symbol) 766 1.37 blymn { 767 1.37 blymn 768 1.64 roy if (symbol <= 0 || _cursesi_screen == NULL) 769 1.37 blymn return ERR; 770 1.37 blymn 771 1.58 blymn if (sequence == NULL) { 772 1.58 blymn __CTRACE(__CTRACE_INPUT, "define_key: deleting keysym %d\n", 773 1.58 blymn symbol); 774 1.37 blymn delete_key_sequence(_cursesi_screen->base_keymap, symbol); 775 1.58 blymn } else 776 1.37 blymn add_key_sequence(_cursesi_screen, sequence, symbol); 777 1.37 blymn 778 1.37 blymn return OK; 779 1.37 blymn } 780 1.48 blymn 781 1.1 cgd /* 782 1.4 mycroft * wgetch -- 783 1.4 mycroft * Read in a character from the window. 784 1.1 cgd */ 785 1.4 mycroft int 786 1.18 blymn wgetch(WINDOW *win) 787 1.4 mycroft { 788 1.30 itojun int inp, weset; 789 1.30 itojun int c; 790 1.35 blymn FILE *infd = _cursesi_screen->infd; 791 1.1 cgd 792 1.51 jdc __CTRACE(__CTRACE_INPUT, "wgetch: win(%p)\n", win); 793 1.64 roy if (win == NULL) 794 1.64 roy return ERR; 795 1.5 cgd if (!(win->flags & __SCROLLOK) && (win->flags & __FULLWIN) 796 1.10 mrg && win->curx == win->maxx - 1 && win->cury == win->maxy - 1 797 1.10 mrg && __echoit) 798 1.64 roy return ERR; 799 1.25 jdc 800 1.75 uwe if (!(win->flags & __ISPAD)) { 801 1.75 uwe if (is_wintouched(win)) 802 1.75 uwe wrefresh(win); 803 1.78 blymn else if (__echoit && ((_cursesi_screen->curscr->cury != (win->begy + win->cury)) 804 1.78 blymn || (_cursesi_screen->curscr->curx != (win->begx + win->curx)))) { 805 1.77 rin __CTRACE(__CTRACE_INPUT, 806 1.77 rin "wgetch: curscr cury %d cury %d " 807 1.77 rin "curscr curx %d curx %d\n", 808 1.77 rin _cursesi_screen->curscr->cury, 809 1.77 rin win->begy + win->cury, 810 1.77 rin _cursesi_screen->curscr->curx, 811 1.77 rin win->begx + win->curx); 812 1.72 blymn /* 813 1.72 blymn * Just in case the window is not dirty but the 814 1.72 blymn * cursor was moved, check and update the 815 1.72 blymn * cursor location. 816 1.72 blymn */ 817 1.73 blymn mvcur(_cursesi_screen->curscr->cury, 818 1.73 blymn _cursesi_screen->curscr->curx, 819 1.73 blymn win->cury + win->begy, win->curx + win->begx); 820 1.72 blymn _cursesi_screen->curscr->cury = 821 1.73 blymn win->cury + win->begy; 822 1.72 blymn _cursesi_screen->curscr->curx = 823 1.73 blymn win->curx + win->begx; 824 1.72 blymn } 825 1.72 blymn } 826 1.72 blymn 827 1.47 jdc __CTRACE(__CTRACE_INPUT, "wgetch: __echoit = %d, " 828 1.52 jdc "__rawmode = %d, __nl = %d, flags = %#.4x, delay = %d\n", 829 1.52 jdc __echoit, __rawmode, _cursesi_screen->nl, win->flags, win->delay); 830 1.50 jdc if (_cursesi_screen->resized) { 831 1.70 roy resizeterm(LINES, COLS); 832 1.50 jdc _cursesi_screen->resized = 0; 833 1.51 jdc __CTRACE(__CTRACE_INPUT, "wgetch returning KEY_RESIZE\n"); 834 1.50 jdc return KEY_RESIZE; 835 1.50 jdc } 836 1.50 jdc if (_cursesi_screen->unget_pos) { 837 1.50 jdc __CTRACE(__CTRACE_INPUT, "wgetch returning char at %d\n", 838 1.50 jdc _cursesi_screen->unget_pos); 839 1.50 jdc _cursesi_screen->unget_pos--; 840 1.50 jdc c = _cursesi_screen->unget_list[_cursesi_screen->unget_pos]; 841 1.50 jdc if (__echoit) 842 1.50 jdc waddch(win, (chtype) c); 843 1.50 jdc return c; 844 1.50 jdc } 845 1.4 mycroft if (__echoit && !__rawmode) { 846 1.1 cgd cbreak(); 847 1.4 mycroft weset = 1; 848 1.4 mycroft } else 849 1.4 mycroft weset = 0; 850 1.4 mycroft 851 1.10 mrg __save_termios(); 852 1.10 mrg 853 1.10 mrg if (win->flags & __KEYPAD) { 854 1.74 simonb switch (win->delay) { 855 1.10 mrg case -1: 856 1.10 mrg inp = inkey (win->flags & __NOTIMEOUT ? 0 : 1, 0); 857 1.10 mrg break; 858 1.10 mrg case 0: 859 1.53 dsl if (__nodelay() == ERR) 860 1.19 jdc return ERR; 861 1.10 mrg inp = inkey(0, 0); 862 1.10 mrg break; 863 1.10 mrg default: 864 1.10 mrg inp = inkey(win->flags & __NOTIMEOUT ? 0 : 1, win->delay); 865 1.10 mrg break; 866 1.10 mrg } 867 1.10 mrg } else { 868 1.74 simonb switch (win->delay) { 869 1.10 mrg case -1: 870 1.53 dsl if (__delay() == ERR) 871 1.46 christos return ERR; 872 1.10 mrg break; 873 1.10 mrg case 0: 874 1.53 dsl if (__nodelay() == ERR) 875 1.10 mrg return ERR; 876 1.10 mrg break; 877 1.10 mrg default: 878 1.53 dsl if (__timeout(win->delay) == ERR) 879 1.10 mrg return ERR; 880 1.10 mrg break; 881 1.10 mrg } 882 1.12 pk 883 1.68 roy inp = __fgetc_resize(infd); 884 1.68 roy if (inp == ERR || inp == KEY_RESIZE) { 885 1.35 blymn clearerr(infd); 886 1.22 blymn __restore_termios(); 887 1.68 roy return inp; 888 1.10 mrg } 889 1.10 mrg } 890 1.4 mycroft #ifdef DEBUG 891 1.15 simonb if (inp > 255) 892 1.20 blymn /* we have a key symbol - treat it differently */ 893 1.20 blymn /* XXXX perhaps __unctrl should be expanded to include 894 1.20 blymn * XXXX the keysyms in the table.... 895 1.20 blymn */ 896 1.47 jdc __CTRACE(__CTRACE_INPUT, "wgetch assembled keysym 0x%x\n", inp); 897 1.15 simonb else 898 1.47 jdc __CTRACE(__CTRACE_INPUT, "wgetch got '%s'\n", unctrl(inp)); 899 1.4 mycroft #endif 900 1.12 pk if (win->delay > -1) { 901 1.53 dsl if (__delay() == ERR) 902 1.10 mrg return ERR; 903 1.12 pk } 904 1.12 pk 905 1.10 mrg __restore_termios(); 906 1.27 blymn 907 1.56 blymn if ((__echoit) && (inp < KEY_MIN)) 908 1.16 blymn waddch(win, (chtype) inp); 909 1.27 blymn 910 1.1 cgd if (weset) 911 1.1 cgd nocbreak(); 912 1.40 jdc 913 1.40 jdc if (_cursesi_screen->nl && inp == 13) 914 1.40 jdc inp = 10; 915 1.12 pk 916 1.10 mrg return ((inp < 0) || (inp == ERR) ? ERR : inp); 917 1.22 blymn } 918 1.22 blymn 919 1.22 blymn /* 920 1.22 blymn * ungetch -- 921 1.22 blymn * Put the character back into the input queue. 922 1.22 blymn */ 923 1.22 blymn int 924 1.22 blymn ungetch(int c) 925 1.22 blymn { 926 1.62 roy return __unget((wint_t)c); 927 1.50 jdc } 928 1.50 jdc 929 1.50 jdc /* 930 1.50 jdc * __unget -- 931 1.50 jdc * Do the work for ungetch() and unget_wch(); 932 1.50 jdc */ 933 1.50 jdc int 934 1.50 jdc __unget(wint_t c) 935 1.50 jdc { 936 1.50 jdc wchar_t *p; 937 1.50 jdc int len; 938 1.50 jdc 939 1.50 jdc __CTRACE(__CTRACE_INPUT, "__unget(%x)\n", c); 940 1.64 roy if (_cursesi_screen == NULL) 941 1.64 roy return ERR; 942 1.50 jdc if (_cursesi_screen->unget_pos >= _cursesi_screen->unget_len) { 943 1.50 jdc len = _cursesi_screen->unget_len + 32; 944 1.50 jdc if ((p = realloc(_cursesi_screen->unget_list, 945 1.50 jdc sizeof(wchar_t) * len)) == NULL) { 946 1.50 jdc /* Can't realloc(), so just lose the oldest entry */ 947 1.50 jdc memmove(_cursesi_screen->unget_list, 948 1.50 jdc _cursesi_screen->unget_list + sizeof(wchar_t), 949 1.50 jdc _cursesi_screen->unget_len - 1); 950 1.50 jdc _cursesi_screen->unget_list[_cursesi_screen->unget_len 951 1.50 jdc - 1] = c; 952 1.50 jdc _cursesi_screen->unget_pos = 953 1.50 jdc _cursesi_screen->unget_len; 954 1.50 jdc return OK; 955 1.50 jdc } else { 956 1.50 jdc _cursesi_screen->unget_pos = 957 1.50 jdc _cursesi_screen->unget_len; 958 1.50 jdc _cursesi_screen->unget_len = len; 959 1.50 jdc _cursesi_screen->unget_list = p; 960 1.50 jdc } 961 1.50 jdc } 962 1.50 jdc _cursesi_screen->unget_list[_cursesi_screen->unget_pos] = c; 963 1.50 jdc _cursesi_screen->unget_pos++; 964 1.50 jdc return OK; 965 1.1 cgd } 966 1.60 roy 967 1.60 roy int 968 1.60 roy has_key(int key_type) 969 1.60 roy { 970 1.60 roy int result = ERR; 971 1.60 roy 972 1.64 roy if (_cursesi_screen != NULL) 973 1.64 roy do_keyok(_cursesi_screen->base_keymap, key_type, 974 1.64 roy false, false, &result); 975 1.60 roy return result; 976 1.60 roy } 977 1.61 roy 978 1.61 roy /* 979 1.61 roy * set_escdelay -- 980 1.61 roy * Sets the escape delay for the current screen. 981 1.61 roy */ 982 1.61 roy int 983 1.61 roy set_escdelay(int escdelay) 984 1.61 roy { 985 1.61 roy 986 1.64 roy if (_cursesi_screen == NULL) 987 1.64 roy return ERR; 988 1.61 roy _cursesi_screen->ESCDELAY = escdelay; 989 1.61 roy ESCDELAY = escdelay; 990 1.61 roy return OK; 991 1.61 roy } 992 1.68 roy 993 1.68 roy /* 994 1.68 roy * __fgetc_resize -- 995 1.68 roy * Any call to fgetc(3) should use this function instead 996 1.68 roy * and test for the return value of KEY_RESIZE as well as ERR. 997 1.68 roy */ 998 1.68 roy int 999 1.68 roy __fgetc_resize(FILE *infd) 1000 1.68 roy { 1001 1.68 roy int c; 1002 1.68 roy 1003 1.68 roy c = fgetc(infd); 1004 1.68 roy if (c != EOF) 1005 1.68 roy return c; 1006 1.68 roy 1007 1.68 roy if (!ferror(infd) || errno != EINTR || !_cursesi_screen->resized) 1008 1.68 roy return ERR; 1009 1.68 roy __CTRACE(__CTRACE_INPUT, "__fgetc_resize returning KEY_RESIZE\n"); 1010 1.70 roy resizeterm(LINES, COLS); 1011 1.68 roy _cursesi_screen->resized = 0; 1012 1.68 roy return KEY_RESIZE; 1013 1.68 roy } 1014