/* * Process an event */ static errr Term_xtra_cap_event(int v) { int i, arg; char buf[2]; /* Wait */ if (v) { /* Wait for one byte */ i = read(0, buf, 1); /* Hack -- Handle "errors" */ if ((i <= 0) && (errno != EINTR)) exit_game_panic(); } /* Do not wait */ else { /* Get the current flags for stdin */ if ((arg = fcntl(0, F_GETFL, 0)) < 1) return (1); /* Tell stdin not to block */ if (fcntl(0, F_SETFL, arg | O_NDELAY) < 0) return (1); /* Read one byte, if possible */ i = read(0, buf, 1); /* Replace the flags for stdin */ if (fcntl(0, F_SETFL, arg)) return (1); } /* No keys ready */ if ((i != 1) || (!buf[0])) return (1); /* Enqueue the keypress */ Term_keypress(buf[0]); /* Success */ return (0); }
/* * Process events, with optional wait */ static errr Term_xtra_gcu_event(int v) { int i, j, k; /* Wait */ if (v) { /* Get a keypress; we use halfdelay(1) so if the user takes more */ /* than 0.1 seconds we get a chance to do updates. */ halfdelay(2); i = getch(); while (i == ERR) { i = getch(); idle_update(); } cbreak(); /* Mega-Hack -- allow graceful "suspend" */ for (k = 0; (k < 10) && (i == ERR); k++) i = getch(); /* Broken input is special */ if (i == ERR) exit_game_panic(); if (i == EOF) exit_game_panic(); } /* Do not wait */ else { /* Do not wait for it */ nodelay(stdscr, TRUE); /* Check for keypresses */ i = getch(); /* Wait for it next time */ nodelay(stdscr, FALSE); /* None ready */ if (i == ERR) return (1); if (i == EOF) return (1); } /* Not sure if this is portable to non-ncurses platforms */ #ifdef USE_NCURSES if (i == KEY_RESIZE) { /* wait until we go one second (10 deci-seconds) before actually * doing the resizing. users often end up triggering multiple * KEY_RESIZE events while changing window size. */ halfdelay(10); do { i = getch(); } while (i == KEY_RESIZE); cbreak(); do_gcu_resize(); if (i == ERR) return (1); } #endif /* uncomment to debug keycode issues */ #if 0 printw("key %d", i); wrefresh(stdscr); #endif /* This might be a bad idea, but... * * Here we try to second-guess ncurses. In some cases, keypad() mode will * fail to translate multi-byte escape sequences into things like number- * pad actions, function keys, etc. So we can hardcode a small list of some * of the most common sequences here, just in case. * * Notice that we turn nodelay() on. This means, that we won't accidentally * interpret sequences as valid unless all the bytes are immediately * available; this seems like an acceptable risk to fix problems associated * with various terminal emulators (I'm looking at you PuTTY). */ if (i == 27) /* ESC */ { nodelay(stdscr, TRUE); j = getch(); switch (j) { case 'O': { k = getch(); switch (k) { /* PuTTY number pad */ case 'q': i = '1'; break; case 'r': i = '2'; break; case 's': i = '3'; break; case 't': i = '4'; break; case 'u': i = '5'; break; case 'v': i = '6'; break; case 'w': i = '7'; break; case 'x': i = '8'; break; case 'y': i = '9'; break; /* no match */ case ERR: break; default: ungetch(k); ungetch(j); } break; } /* no match */ case ERR: break; default: ungetch(j); } nodelay(stdscr, FALSE); } #ifdef KEY_DOWN /* Handle arrow keys */ switch (i) { case KEY_DOWN: i = ARROW_DOWN; break; case KEY_UP: i = ARROW_UP; break; case KEY_LEFT: i = ARROW_LEFT; break; case KEY_RIGHT: i = ARROW_RIGHT; break; default: if (i < KEY_MIN) break; /* Mega-Hack -- Fold, spindle, and mutilate * the keys to fit in 7 bits. */ if (i >= 252) i = KEY_F(63) - (i - 252); if (i >= ARROW_DOWN) i += 4; i = 128 + (i & 127); break; } #endif /* Enqueue the keypress */ Term_keypress(i); /* Success */ return (0); }
/* * Process events, with optional wait */ static errr Term_xtra_gcu_event(int v) { int i, k; /* Wait */ if (v) { /* Paranoia -- Wait for it */ nodelay(stdscr, FALSE); /* Get a keypress */ i = getch(); /* Mega-Hack -- allow graceful "suspend" */ for (k = 0; (k < 10) && (i == ERR); k++) i = getch(); /* Broken input is special */ if (i == ERR) exit_game_panic(); if (i == EOF) exit_game_panic(); } /* Do not wait */ else { /* Do not wait for it */ nodelay(stdscr, TRUE); /* Check for keypresses */ i = getch(); /* Wait for it next time */ nodelay(stdscr, FALSE); /* None ready */ if (i == ERR) return (1); if (i == EOF) return (1); } /* Issue: Currently, we map curses escape sequences via the macro processing system (see pref-gcu.prf). * If you don't already know, this is required for things like arrow keys and the numpad and what not. * The advantage of this approach is that users can (theoretically) edit the pref file themselves in * the event that their terminal is sending a different escape sequence for some reason. All good, right? * Well, except for those places in the code that *disable* macro processing! This includes all user prompts, * the store UI (TODO) and the autopicker. Now, it's rather disconcerting if arrow keys aren't available in * a text editor or if the user can't correct typos with backspace! * * The idea of translating here is from current Vanilla * TODO */ /* Backspace */ if (i == 0x7F) i = '\b'; if (i == 27) /* \e is not ansi c */ { /* char buf[255]; int cb = _getstr(buf, 255); if (cb > 0) { if (strcmp(buf, "[3~") == 0) i = '.'; else if (strcmp(buf, "[2~") == 0) i = '0'; else if (strcmp(buf, "[4~") == 0) i = '1'; else if (strcmp(buf, "[F") == 0) i = '1'; else if (strcmp(buf, "[B") == 0) i = '2'; ... else _ungetstr(buf, cb); } CTK: Actually, I'm not so sure this is going to work. Arrow keys need to be known as such by the game engine not translated to numbers. And looking at what main-win.c and main-x11.c do to get this working is ... uh, a bit overwhelming. So this is on hold for now ... */ } /* Enqueue the keypress */ Term_keypress(i); /* Success */ return (0); }