1 #include "io/input-key-acceptor.h"
2 #include "cmd-io/macro-util.h"
3 #include "game-option/map-screen-options.h"
4 #include "game-option/input-options.h"
5 #include "io/signal-handlers.h"
6 #include "term/gameterm.h"
7 #include "util/string-processor.h"
8 #include "world/world.h"
10 bool inkey_base; /* See the "inkey()" function */
11 bool inkey_xtra; /* See the "inkey()" function */
12 bool inkey_scan; /* See the "inkey()" function */
13 bool inkey_flag; /* See the "inkey()" function */
18 * This special pointer allows a sequence of keys to be "inserted" into
19 * the stream of keys returned by "inkey()". This key sequence will not
20 * trigger any macros, and cannot be bypassed by the Borg. It is used
21 * in Angband to handle "keymaps".
23 concptr inkey_next = NULL;
25 /* Save macro trigger string for use in inkey_special() */
26 static char inkey_macro_trigger_string[1024];
29 * Local variable -- we are inside a "macro action"
31 * Do not match any macros until "ascii 30" is found.
33 static bool parse_macro = FALSE;
36 * Local variable -- we are inside a "macro trigger"
38 * Strip all keypresses until a low ascii value is found.
40 static bool parse_under = FALSE;
43 * Cancel macro action on the queue
45 static void forget_macro_action(void)
52 if (term_inkey(&ch, FALSE, TRUE))
64 * Helper function called only from "inkey()"
66 * This function does almost all of the "macro" processing.
68 * We use the "term_key_push()" function to handle "failed" macros, as well
69 * as "extra" keys read in while choosing the proper macro, and also to hold
70 * the action for the macro, plus a special "ascii 30" character indicating
71 * that any macro action in progress is complete. Embedded macros are thus
72 * illegal, unless a macro action includes an explicit "ascii 30" character,
73 * which would probably be a massive hack, and might break things.
75 * Only 500 (0+1+2+...+29+30) milliseconds may elapse between each key in
76 * the macro trigger sequence. If a key sequence forms the "prefix" of a
77 * macro trigger, 500 milliseconds must pass before the key sequence is
78 * known not to be that macro trigger.
80 static char inkey_aux(void)
82 int k = 0, n, p = 0, w = 0;
84 char *buf = inkey_macro_trigger_string;
89 if (term_inkey(&ch, FALSE, TRUE)) {
93 (void)(term_inkey(&ch, TRUE, TRUE));
108 k = macro_find_check(buf);
113 k = macro_find_maybe(buf);
118 if (0 == term_inkey(&ch, FALSE, TRUE)) {
127 term_xtra(TERM_XTRA_DELAY, w);
131 k = macro_find_ready(buf);
134 if (term_key_push(buf[--p]))
138 (void)term_inkey(&ch, TRUE, TRUE);
142 concptr pat = macro__pat[k];
145 if (term_key_push(buf[--p]))
150 if (term_key_push(30))
153 concptr act = macro__act[k];
157 if (term_key_push(act[--n]))
165 * @brief キー入力を受け付けるメインルーチン / Get a keypress from the user.
173 term_type *old = Term;
175 if (inkey_next && *inkey_next && !inkey_xtra) {
177 inkey_base = inkey_xtra = inkey_flag = inkey_scan = FALSE;
189 (void)term_get_cursor(&v);
191 /* Show the cursor if waiting, except sometimes in "command" mode */
192 if (!inkey_scan && (!inkey_flag || hilite_player || current_world_ptr->character_icky)) {
193 (void)term_set_cursor(1);
196 term_activate(angband_term[0]);
199 if (!inkey_base && inkey_scan && (0 != term_inkey(&kk, FALSE, FALSE))) {
203 if (!done && (0 != term_inkey(&kk, FALSE, FALSE))) {
206 term_activate(angband_term[0]);
207 current_world_ptr->character_saved = FALSE;
216 if (0 == term_inkey(&ch, TRUE, TRUE)) {
224 if (0 == term_inkey(&ch, FALSE, TRUE)) {
231 term_xtra(TERM_XTRA_DELAY, w);
244 if (parse_under && (ch <= 32)) {
251 } else if (ch == 31) {
254 } else if (parse_under) {
261 inkey_base = inkey_xtra = inkey_flag = inkey_scan = FALSE;
266 * Get a keypress from the user.
267 * And interpret special keys as internal code.
269 * This function is a Mega-Hack and depend on pref-xxx.prf's.
270 * Currently works on Linux(UNIX), Windows, and Macintosh only.
272 int inkey_special(bool numpad_cursor)
274 static const struct {
277 } modifier_key_list[] = {
278 { "shift-", SKEY_MOD_SHIFT },
279 { "control-", SKEY_MOD_CONTROL },
283 static const struct {
287 } special_key_list[] = {
288 { FALSE, "Down]", SKEY_DOWN },
289 { FALSE, "Left]", SKEY_LEFT },
290 { FALSE, "Right]", SKEY_RIGHT },
291 { FALSE, "Up]", SKEY_UP },
292 { FALSE, "Page_Up]", SKEY_PGUP },
293 { FALSE, "Page_Down]", SKEY_PGDOWN },
294 { FALSE, "Home]", SKEY_TOP },
295 { FALSE, "End]", SKEY_BOTTOM },
296 { TRUE, "KP_Down]", SKEY_DOWN },
297 { TRUE, "KP_Left]", SKEY_LEFT },
298 { TRUE, "KP_Right]", SKEY_RIGHT },
299 { TRUE, "KP_Up]", SKEY_UP },
300 { TRUE, "KP_Page_Up]", SKEY_PGUP },
301 { TRUE, "KP_Page_Down]", SKEY_PGDOWN },
302 { TRUE, "KP_Home]", SKEY_TOP },
303 { TRUE, "KP_End]", SKEY_BOTTOM },
304 { TRUE, "KP_2]", SKEY_DOWN },
305 { TRUE, "KP_4]", SKEY_LEFT },
306 { TRUE, "KP_6]", SKEY_RIGHT },
307 { TRUE, "KP_8]", SKEY_UP },
308 { TRUE, "KP_9]", SKEY_PGUP },
309 { TRUE, "KP_3]", SKEY_PGDOWN },
310 { TRUE, "KP_7]", SKEY_TOP },
311 { TRUE, "KP_1]", SKEY_BOTTOM },
315 static const struct {
318 } gcu_special_key_list[] = {
324 { "4~", SKEY_BOTTOM },
326 { "6~", SKEY_PGDOWN },
339 * Forget macro trigger ----
340 * It's important if we are already expanding macro action
342 inkey_macro_trigger_string[0] = '\0';
345 trig_len = strlen(inkey_macro_trigger_string);
347 return (int)((unsigned char)key);
348 if (trig_len == 1 && parse_macro) {
349 char c = inkey_macro_trigger_string[0];
350 forget_macro_action();
351 return (int)((unsigned char)c);
354 ascii_to_text(buf, inkey_macro_trigger_string);
355 if (prefix(str, "\\[")) {
358 for (i = 0; modifier_key_list[i].keyname; i++) {
359 if (prefix(str, modifier_key_list[i].keyname)) {
360 str += strlen(modifier_key_list[i].keyname);
361 modifier |= modifier_key_list[i].keyflag;
365 if (!modifier_key_list[i].keyname)
369 if (!numpad_as_cursorkey)
370 numpad_cursor = FALSE;
372 for (i = 0; special_key_list[i].keyname; i++) {
373 if ((!special_key_list[i].numpad || numpad_cursor) && streq(str, special_key_list[i].keyname)) {
374 skey = special_key_list[i].keycode;
380 forget_macro_action();
381 return (skey | modifier);
385 if (prefix(str, "\\e[")) {
388 for (i = 0; gcu_special_key_list[i].keyname; i++) {
389 if (streq(str, gcu_special_key_list[i].keyname)) {
390 return gcu_special_key_list[i].keycode;
395 inkey_macro_trigger_string[0] = '\0';
396 return (int)((unsigned char)key);