/* * Helper function called only from "inkey()" */ static ui_event inkey_aux(int scan_cutoff) { int w = 0; ui_event ke; /* Wait for a keypress */ if (scan_cutoff == SCAN_OFF) { (void)(Term_inkey(&ke, TRUE, TRUE)); } else { w = 0; /* Wait only as long as macro activation would wait*/ while (Term_inkey(&ke, FALSE, TRUE) != 0) { /* Increase "wait" */ w++; /* Excessive delay */ if (w >= scan_cutoff) { ui_event empty = EVENT_EMPTY; return empty; } /* Delay */ Term_xtra(TERM_XTRA_DELAY, 10); } } return (ke); }
/* * (From the Angband Borg by Ben Harrison & Dr Andrew White) * * This function lets the automaton "steal" control from the user. * * The "z-term.c" file provides a special hook which we use to * bypass the standard "Term_flush()" and "Term_inkey()" functions * and replace them with the function below. * * The only way that the automaton can be stopped once it is started, * unless it dies or encounters an error, is to press any key. * This function checks for user input on a regular basic, and * when any is encountered, it relinquishes control gracefully. * * Note that this function hook automatically removes itself when * it realizes that it should no longer be active. Note that this * may take place after the game has asked for the next keypress, * but the various "keypress" routines should be able to handle this. * * XXX XXX XXX We do not correctly handle the "take" flag */ char automaton_inkey_hack(int flush_first) { int i; char ch; // paranoia if (!p_ptr->automaton) { stop_automaton(); /* Nothing ready */ return (ESCAPE); } // flush key buffer if requested if (flush_first) { // only flush if needed if (automaton_inkey(FALSE) != 0) { // Flush keys ////automaton_flush(); currently not actually doing this as it stops us queuing a 'y' for stepping on traps } } // check for manual user abort (void)Term_inkey(&ch, FALSE, TRUE); // if a key is hit, stop the automaton if (ch > 0) { stop_automaton(); return (ESCAPE); } // check for a previously queued key, without taking it from the queue i = automaton_inkey(FALSE); // if it was empty and we need more keys if (!i) { // handle waiting for commands separately if (waiting_for_command) { // takes its turn by choosing some keys representing commands and queuing them automaton_turn(); // pause for a moment so the user can see what is happening Term_xtra(TERM_XTRA_DELAY, 25 * op_ptr->delay_factor); } else { /* Hack -- Process events (do not wait) */ (void)Term_xtra(TERM_XTRA_EVENT, FALSE); stop_automaton(); return (ESCAPE); } } // check for a previously queued key, taking it from the queue i = automaton_inkey(TRUE); // deal with empty queue if (!i) { // exit return('\0'); } // return the key chosen return (i); }
/* * Get a keypress from the user. * * This function recognizes a few "global parameters". These are variables * which, if set to TRUE before calling this function, will have an effect * on this function, and which are always reset to FALSE by this function * before this function returns. Thus they function just like normal * parameters, except that most calls to this function can ignore them. * * If "inkey_xtra" is TRUE, then all pending keypresses will be flushed. * This is set by flush(), which doesn't actually flush anything itself * but uses that flag to trigger delayed flushing. * * If "inkey_scan" is TRUE, then we will immediately return "zero" if no * keypress is available, instead of waiting for a keypress. * * If "inkey_flag" is TRUE, then we are waiting for a command in the main * map interface, and we shouldn't show a cursor. * * If we are waiting for a keypress, and no keypress is ready, then we will * refresh (once) the window which was active when this function was called. * * Note that "back-quote" is automatically converted into "escape" for * convenience on machines with no "escape" key. * * If "angband_term[0]" is not active, we will make it active during this * function, so that the various "main-xxx.c" files can assume that input * is only requested (via "Term_inkey()") when "angband_term[0]" is active. * * Mega-Hack -- This function is used as the entry point for clearing the * "signal_count" variable, and of the "character_saved" variable. * * Mega-Hack -- Note the use of "inkey_hack" to allow the "Borg" to steal * control of the keyboard from the user. */ ui_event inkey_ex(void) { bool cursor_state; ui_event kk; ui_event ke = EVENT_EMPTY; bool done = FALSE; term *old = Term; /* Delayed flush */ if (inkey_xtra) { Term_flush(); inkey_next = NULL; inkey_xtra = FALSE; } /* Hack -- Use the "inkey_next" pointer */ if (inkey_next && inkey_next->code) { /* Get next character, and advance */ ke.key = *inkey_next++; /* Cancel the various "global parameters" */ inkey_flag = FALSE; inkey_scan = 0; /* Accept result */ return (ke); } /* Forget pointer */ inkey_next = NULL; #ifdef ALLOW_BORG /* Mega-Hack -- Use the special hook */ if (inkey_hack) { ke.key = (*inkey_hack)(inkey_xtra); if (ke.key.type != EVT_NONE) { /* Cancel the various "global parameters" */ inkey_flag = FALSE; inkey_scan = 0; ke.type = EVT_KBRD; /* Accept result */ return (ke); } } #endif /* ALLOW_BORG */ /* Get the cursor state */ (void)Term_get_cursor(&cursor_state); /* Show the cursor if waiting, except sometimes in "command" mode */ if (!inkey_scan && (!inkey_flag || character_icky)) (void)Term_set_cursor(TRUE); /* Hack -- Activate main screen */ Term_activate(term_screen); /* Get a key */ while (ke.type == EVT_NONE) { /* Hack -- Handle "inkey_scan == SCAN_INSTANT */ if (inkey_scan == SCAN_INSTANT && (0 != Term_inkey(&kk, FALSE, FALSE))) break; /* Hack -- Flush output once when no key ready */ if (!done && (0 != Term_inkey(&kk, FALSE, FALSE))) { /* Hack -- activate proper term */ Term_activate(old); /* Flush output */ Term_fresh(); /* Hack -- activate main screen */ Term_activate(term_screen); /* Mega-Hack -- reset saved flag */ character_saved = FALSE; /* Mega-Hack -- reset signal counter */ signal_count = 0; /* Only once */ done = TRUE; } /* Get a key (see above) */ ke = inkey_aux(inkey_scan); /* Handle mouse buttons */ if ((ke.type == EVT_MOUSE) && (OPT(mouse_buttons))) { /* Check to see if we've hit a button */ /* Assuming text buttons here for now - this would have to * change for GUI buttons */ char key = button_get_key(ke.mouse.x, ke.mouse.y); if (key) { /* Rewrite the event */ /* XXXmacro button implementation needs updating */ ke.type = EVT_BUTTON; ke.key.code = key; ke.key.mods = 0; /* Done */ break; } } /* Treat back-quote as escape */ if (ke.key.code == '`') ke.key.code = ESCAPE; } /* Hack -- restore the term */ Term_activate(old); /* Restore the cursor */ Term_set_cursor(cursor_state); /* Cancel the various "global parameters" */ inkey_flag = FALSE; inkey_scan = 0; /* Return the keypress */ return (ke); }
/** * Get a keypress from the user. * * This function recognizes a few "global parameters". These are variables * which, if set to true before calling this function, will have an effect * on this function, and which are always reset to false by this function * before this function returns. Thus they function just like normal * parameters, except that most calls to this function can ignore them. * * If "inkey_xtra" is true, then all pending keypresses will be flushed. * This is set by flush(), which doesn't actually flush anything itself * but uses that flag to trigger delayed flushing. * * If "inkey_scan" is true, then we will immediately return "zero" if no * keypress is available, instead of waiting for a keypress. * * If "inkey_flag" is true, then we are waiting for a command in the main * map interface, and we shouldn't show a cursor. * * If we are waiting for a keypress, and no keypress is ready, then we will * refresh (once) the window which was active when this function was called. * * Note that "back-quote" is automatically converted into "escape" for * convenience on machines with no "escape" key. * * If "angband_term[0]" is not active, we will make it active during this * function, so that the various "main-xxx.c" files can assume that input * is only requested (via "Term_inkey()") when "angband_term[0]" is active. * * Mega-Hack -- This function is used as the entry point for clearing the * "signal_count" variable, and of the "character_saved" variable. * * Mega-Hack -- Note the use of "inkey_hack" to allow the "Borg" to steal * control of the keyboard from the user. */ ui_event inkey_ex(void) { bool cursor_state; ui_event kk; ui_event ke = EVENT_EMPTY; bool done = false; term *old = Term; /* Delayed flush */ if (inkey_xtra) { Term_flush(); inkey_next = NULL; inkey_xtra = false; } /* Hack -- Use the "inkey_next" pointer */ while (inkey_next && inkey_next->code) { /* Get next character, and advance */ ke.key = *inkey_next++; /* Cancel the various "global parameters" */ inkey_flag = false; inkey_scan = 0; /* Peek at the key, and see if we want to skip more prompts */ if (ke.key.code == '(') { keymap_auto_more = true; /* Since we are not returning this char, make sure the * next key below works well */ if (!inkey_next || !inkey_next->code) { ke.type = EVT_NONE; break; } continue; } else if (ke.key.code == ')') { keymap_auto_more = false; /* Since we are not returning this char, make sure the * next key below works well */ if (!inkey_next || !inkey_next->code) { ke.type = EVT_NONE; break; } continue; } /* Accept result */ return (ke); } /* make sure that the flag to skip more prompts is off */ keymap_auto_more = false; /* Forget pointer */ inkey_next = NULL; /* Get the cursor state */ (void)Term_get_cursor(&cursor_state); /* Show the cursor if waiting, except sometimes in "command" mode */ if (!inkey_scan && (!inkey_flag || screen_save_depth || (OPT(show_target) && target_sighted()))) (void)Term_set_cursor(true); /* Hack -- Activate main screen */ Term_activate(term_screen); /* Get a key */ while (ke.type == EVT_NONE) { /* Hack -- Handle "inkey_scan == SCAN_INSTANT */ if (inkey_scan == SCAN_INSTANT && (0 != Term_inkey(&kk, false, false))) break; /* Hack -- Flush output once when no key ready */ if (!done && (0 != Term_inkey(&kk, false, false))) { /* Hack -- activate proper term */ Term_activate(old); /* Flush output */ Term_fresh(); /* Hack -- activate main screen */ Term_activate(term_screen); /* Mega-Hack -- reset saved flag */ character_saved = false; /* Mega-Hack -- reset signal counter */ signal_count = 0; /* Only once */ done = true; } /* Get a key (see above) */ ke = inkey_aux(inkey_scan); if (inkey_scan && ke.type == EVT_NONE) /* The keypress timed out. We need to stop here. */ break; /* Treat back-quote as escape */ if (ke.key.code == '`') ke.key.code = ESCAPE; } /* Hack -- restore the term */ Term_activate(old); /* Restore the cursor */ Term_set_cursor(cursor_state); /* Cancel the various "global parameters" */ inkey_flag = false; inkey_scan = 0; /* Return the keypress */ return (ke); }