Angband 3.0.9b.
[angband.git] / src / util.c
blobe0b2ec0b36eac2024dc17adf350986a946847453
1 /* File: util.c */
3 /*
4 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
6 * This software may be copied and distributed for educational, research,
7 * and not for profit purposes provided that this copyright and statement
8 * are included in all such copies. Other copyrights may also apply.
9 */
11 #include "angband.h"
12 #include "randname.h"
17 * Convert a decimal to a single digit hex number
19 static char hexify(int i)
21 return (hexsym[i % 16]);
27 * Convert a hexidecimal-digit into a decimal
29 static int dehex(char c)
31 if (isdigit((unsigned char)c)) return (D2I(c));
32 if (isalpha((unsigned char)c)) return (A2I(tolower((unsigned char)c)) + 10);
33 return (0);
38 * Transform macro trigger name ('\[alt-D]' etc..)
39 * into macro trigger key code ('^_O_64\r' or etc..)
41 static size_t trigger_text_to_ascii(char *buf, size_t max, cptr *strptr)
43 cptr str = *strptr;
44 bool mod_status[MAX_MACRO_MOD];
46 int i, len = 0;
47 int shiftstatus = 0;
48 cptr key_code;
50 size_t current_len = strlen(buf);
52 /* No definition of trigger names */
53 if (macro_template == NULL) return 0;
55 /* Initialize modifier key status */
56 for (i = 0; macro_modifier_chr[i]; i++)
57 mod_status[i] = FALSE;
59 str++;
61 /* Examine modifier keys */
62 while (1)
64 /* Look for modifier key name */
65 for (i = 0; macro_modifier_chr[i]; i++)
67 len = strlen(macro_modifier_name[i]);
69 if (!my_strnicmp(str, macro_modifier_name[i], len))
70 break;
73 /* None found? */
74 if (!macro_modifier_chr[i]) break;
76 /* Proceed */
77 str += len;
79 /* This modifier key is pressed */
80 mod_status[i] = TRUE;
82 /* Shift key might be going to change keycode */
83 if ('S' == macro_modifier_chr[i])
84 shiftstatus = 1;
87 /* Look for trigger name */
88 for (i = 0; i < max_macrotrigger; i++)
90 len = strlen(macro_trigger_name[i]);
92 /* Found it and it is ending with ']' */
93 if (!my_strnicmp(str, macro_trigger_name[i], len) && (']' == str[len]))
94 break;
97 /* Invalid trigger name? */
98 if (i == max_macrotrigger)
101 * If this invalid trigger name is ending with ']',
102 * skip whole of it to avoid defining strange macro trigger
104 str = strchr(str, ']');
106 if (str)
108 strnfcat(buf, max, &current_len, "\x1F\r");
110 *strptr = str; /* where **strptr == ']' */
113 return current_len;
116 /* Get keycode for this trigger name */
117 key_code = macro_trigger_keycode[shiftstatus][i];
119 /* Proceed */
120 str += len;
122 /* Begin with '^_' */
123 strnfcat(buf, max, &current_len, "\x1F");
125 /* Write key code style trigger using template */
126 for (i = 0; macro_template[i]; i++)
128 char ch = macro_template[i];
129 int j;
131 switch(ch)
133 case '&':
134 /* Modifier key character */
135 for (j = 0; macro_modifier_chr[j]; j++)
137 if (mod_status[j])
138 strnfcat(buf, max, &current_len, "%c", macro_modifier_chr[j]);
140 break;
141 case '#':
142 /* Key code */
143 strnfcat(buf, max, &current_len, "%s", key_code);
144 break;
145 default:
146 /* Fixed string */
147 strnfcat(buf, max, &current_len, "%c", ch);
148 break;
152 /* End with '\r' */
153 strnfcat(buf, max, &current_len, "\r");
155 /* Succeed */
156 *strptr = str; /* where **strptr == ']' */
158 return current_len;
163 * Hack -- convert a printable string into real ascii
165 * This function will not work on non-ascii systems.
167 * To be safe, "buf" should be at least as large as "str".
169 void text_to_ascii(char *buf, size_t len, cptr str)
171 char *s = buf;
173 /* Analyze the "ascii" string */
174 while (*str)
176 /* Check if the buffer is long enough */
177 if (s >= buf + len - 1) break;
179 /* Backslash codes */
180 if (*str == '\\')
182 /* Skip the backslash */
183 str++;
185 /* Paranoia */
186 if (!(*str)) break;
188 /* Macro Trigger */
189 if (*str == '[')
191 /* Terminate before appending the trigger */
192 *s = '\0';
194 s += trigger_text_to_ascii(buf, len, &str);
197 /* Hack -- simple way to specify Escape */
198 else if (*str == 'e')
200 *s++ = ESCAPE;
203 /* Hack -- simple way to specify "space" */
204 else if (*str == 's')
206 *s++ = ' ';
209 /* Backspace */
210 else if (*str == 'b')
212 *s++ = '\b';
215 /* Newline */
216 else if (*str == 'n')
218 *s++ = '\n';
221 /* Return */
222 else if (*str == 'r')
224 *s++ = '\r';
227 /* Tab */
228 else if (*str == 't')
230 *s++ = '\t';
233 /* Bell */
234 else if (*str == 'a')
236 *s++ = '\a';
239 /* Actual "backslash" */
240 else if (*str == '\\')
242 *s++ = '\\';
245 /* Hack -- Actual "caret" */
246 else if (*str == '^')
248 *s++ = '^';
251 /* Hack -- Hex-mode */
252 else if (*str == 'x')
254 if (isxdigit((unsigned char)(*(str + 1))) &&
255 isxdigit((unsigned char)(*(str + 2))))
257 *s = 16 * dehex(*++str);
258 *s++ += dehex(*++str);
260 else
262 /* HACK - Invalid hex number */
263 *s++ = '?';
267 /* Oops */
268 else
270 *s = *str;
273 /* Skip the final char */
274 str++;
277 /* Normal Control codes */
278 else if (*str == '^')
280 str++;
282 if (*str)
284 *s++ = KTRL(*str);
285 str++;
289 /* Normal chars */
290 else
292 *s++ = *str++;
296 /* Terminate */
297 *s = '\0';
302 * Transform macro trigger key code ('^_O_64\r' or etc..)
303 * into macro trigger name ('\[alt-D]' etc..)
305 static size_t trigger_ascii_to_text(char *buf, size_t max, cptr *strptr)
307 cptr str = *strptr;
308 char key_code[100];
309 int i;
310 cptr tmp;
311 size_t current_len = strlen(buf);
314 /* No definition of trigger names */
315 if (macro_template == NULL) return 0;
317 /* Trigger name will be written as '\[name]' */
318 strnfcat(buf, max, &current_len, "\\[");
320 /* Use template to read key-code style trigger */
321 for (i = 0; macro_template[i]; i++)
323 int j;
324 char ch = macro_template[i];
326 switch(ch)
328 case '&':
329 /* Read modifier */
330 while ((tmp = strchr(macro_modifier_chr, *str)))
332 j = (int)(tmp - macro_modifier_chr);
333 strnfcat(buf, max, &current_len, "%s", macro_modifier_name[j]);
334 str++;
336 break;
337 case '#':
338 /* Read key code */
339 for (j = 0; *str && (*str != '\r') && (j < (int)sizeof(key_code) - 1); j++)
340 key_code[j] = *str++;
341 key_code[j] = '\0';
342 break;
343 default:
344 /* Skip fixed strings */
345 if (ch != *str) return 0;
346 str++;
350 /* Key code style triggers always end with '\r' */
351 if (*str++ != '\r') return 0;
353 /* Look for trigger name with given keycode (normal or shifted keycode) */
354 for (i = 0; i < max_macrotrigger; i++)
356 if (!my_stricmp(key_code, macro_trigger_keycode[0][i]) ||
357 !my_stricmp(key_code, macro_trigger_keycode[1][i]))
358 break;
361 /* Not found? */
362 if (i == max_macrotrigger) return 0;
364 /* Write trigger name + "]" */
365 strnfcat(buf, max, &current_len, "%s]", macro_trigger_name[i]);
367 /* Succeed */
368 *strptr = str;
369 return current_len;
374 * Hack -- convert a string into a printable form
376 * This function will not work on non-ascii systems.
378 void ascii_to_text(char *buf, size_t len, cptr str)
380 char *s = buf;
382 /* Analyze the "ascii" string */
383 while (*str)
385 byte i = (byte)(*str++);
387 /* Check if the buffer is long enough */
388 /* HACK - always assume worst case (hex-value + '\0') */
389 if (s >= buf + len - 5) break;
391 if (i == ESCAPE)
393 *s++ = '\\';
394 *s++ = 'e';
396 else if (i == ' ')
398 *s++ = '\\';
399 *s++ = 's';
401 else if (i == '\b')
403 *s++ = '\\';
404 *s++ = 'b';
406 else if (i == '\t')
408 *s++ = '\\';
409 *s++ = 't';
411 else if (i == '\a')
413 *s++ = '\\';
414 *s++ = 'a';
416 else if (i == '\n')
418 *s++ = '\\';
419 *s++ = 'n';
421 else if (i == '\r')
423 *s++ = '\\';
424 *s++ = 'r';
426 else if (i == '\\')
428 *s++ = '\\';
429 *s++ = '\\';
431 else if (i == '^')
433 *s++ = '\\';
434 *s++ = '^';
436 /* Macro Trigger */
437 else if (i == 31)
439 size_t offset;
441 /* Terminate before appending the trigger */
442 *s = '\0';
444 offset = trigger_ascii_to_text(buf, len, &str);
446 if (offset == 0)
448 /* No trigger found */
449 *s++ = '^';
450 *s++ = '_';
452 else
453 s += offset;
455 else if (i < 32)
457 *s++ = '^';
458 *s++ = UN_KTRL(i);
460 else if (i < 127)
462 *s++ = i;
464 else
466 *s++ = '\\';
467 *s++ = 'x';
468 *s++ = hexify((int)i / 16);
469 *s++ = hexify((int)i % 16);
473 /* Terminate */
474 *s = '\0';
480 * The "macro" package
482 * Functions are provided to manipulate a collection of macros, each
483 * of which has a trigger pattern string and a resulting action string
484 * and a small set of flags.
490 * Determine if any macros have ever started with a given character.
492 static bool macro__use[256];
496 * Find the macro (if any) which exactly matches the given pattern
498 int macro_find_exact(cptr pat)
500 int i;
502 /* Nothing possible */
503 if (!macro__use[(byte)(pat[0])])
505 return (-1);
508 /* Scan the macros */
509 for (i = 0; i < macro__num; ++i)
511 /* Skip macros which do not match the pattern */
512 if (!streq(macro__pat[i], pat)) continue;
514 /* Found one */
515 return (i);
518 /* No matches */
519 return (-1);
524 * Find the first macro (if any) which contains the given pattern
526 static int macro_find_check(cptr pat)
528 int i;
530 /* Nothing possible */
531 if (!macro__use[(byte)(pat[0])])
533 return (-1);
536 /* Scan the macros */
537 for (i = 0; i < macro__num; ++i)
539 /* Skip macros which do not contain the pattern */
540 if (!prefix(macro__pat[i], pat)) continue;
542 /* Found one */
543 return (i);
546 /* Nothing */
547 return (-1);
553 * Find the first macro (if any) which contains the given pattern and more
555 static int macro_find_maybe(cptr pat)
557 int i;
559 /* Nothing possible */
560 if (!macro__use[(byte)(pat[0])])
562 return (-1);
565 /* Scan the macros */
566 for (i = 0; i < macro__num; ++i)
568 /* Skip macros which do not contain the pattern */
569 if (!prefix(macro__pat[i], pat)) continue;
571 /* Skip macros which exactly match the pattern XXX XXX */
572 if (streq(macro__pat[i], pat)) continue;
574 /* Found one */
575 return (i);
578 /* Nothing */
579 return (-1);
584 * Find the longest macro (if any) which starts with the given pattern
586 static int macro_find_ready(cptr pat)
588 int i, t, n = -1, s = -1;
590 /* Nothing possible */
591 if (!macro__use[(byte)(pat[0])])
593 return (-1);
596 /* Scan the macros */
597 for (i = 0; i < macro__num; ++i)
599 /* Skip macros which are not contained by the pattern */
600 if (!prefix(pat, macro__pat[i])) continue;
602 /* Obtain the length of this macro */
603 t = strlen(macro__pat[i]);
605 /* Only track the "longest" pattern */
606 if ((n >= 0) && (s > t)) continue;
608 /* Track the entry */
609 n = i;
610 s = t;
613 /* Result */
614 return (n);
619 * Add a macro definition (or redefinition).
621 * We should use "act == NULL" to "remove" a macro, but this might make it
622 * impossible to save the "removal" of a macro definition. XXX XXX XXX
624 * We should consider refusing to allow macros which contain existing macros,
625 * or which are contained in existing macros, because this would simplify the
626 * macro analysis code. XXX XXX XXX
628 * We should consider removing the "command macro" crap, and replacing it
629 * with some kind of "powerful keymap" ability, but this might make it hard
630 * to change the "roguelike" option from inside the game. XXX XXX XXX
632 errr macro_add(cptr pat, cptr act)
634 int n;
637 /* Paranoia -- require data */
638 if (!pat || !act) return (-1);
641 /* Look for any existing macro */
642 n = macro_find_exact(pat);
644 /* Replace existing macro */
645 if (n >= 0)
647 /* Free the old macro action */
648 string_free(macro__act[n]);
651 /* Create a new macro */
652 else
654 /* Get a new index */
655 n = macro__num++;
657 /* Boundary check */
658 if (macro__num >= MACRO_MAX) quit("Too many macros!");
660 /* Save the pattern */
661 macro__pat[n] = string_make(pat);
664 /* Save the action */
665 macro__act[n] = string_make(act);
667 /* Efficiency */
668 macro__use[(byte)(pat[0])] = TRUE;
670 /* Success */
671 return (0);
677 * Initialize the "macro" package
679 errr macro_init(void)
681 /* Macro patterns */
682 C_MAKE(macro__pat, MACRO_MAX, cptr);
684 /* Macro actions */
685 C_MAKE(macro__act, MACRO_MAX, cptr);
687 /* Success */
688 return (0);
693 * Free the macro package
695 errr macro_free(void)
697 int i, j;
699 /* Free the macros */
700 for (i = 0; i < macro__num; ++i)
702 string_free(macro__pat[i]);
703 string_free(macro__act[i]);
706 FREE((void*)macro__pat);
707 FREE((void*)macro__act);
709 /* Free the keymaps */
710 for (i = 0; i < KEYMAP_MODES; ++i)
712 for (j = 0; j < (int)N_ELEMENTS(keymap_act[i]); ++j)
714 string_free(keymap_act[i][j]);
715 keymap_act[i][j] = NULL;
719 /* Success */
720 return (0);
725 * Free the macro trigger package
727 errr macro_trigger_free(void)
729 int i;
730 int num;
732 if (macro_template != NULL)
734 /* Free the template */
735 string_free(macro_template);
736 macro_template = NULL;
738 /* Free the trigger names and keycodes */
739 for (i = 0; i < max_macrotrigger; i++)
741 string_free(macro_trigger_name[i]);
743 string_free(macro_trigger_keycode[0][i]);
744 string_free(macro_trigger_keycode[1][i]);
747 /* No more macro triggers */
748 max_macrotrigger = 0;
750 /* Count modifier-characters */
751 num = strlen(macro_modifier_chr);
753 /* Free modifier names */
754 for (i = 0; i < num; i++)
756 string_free(macro_modifier_name[i]);
759 /* Free modifier chars */
760 string_free(macro_modifier_chr);
761 macro_modifier_chr = NULL;
764 /* Success */
765 return (0);
770 * Flush all pending input.
772 * Actually, remember the flush, using the "inkey_xtra" flag, and in the
773 * next call to "inkey()", perform the actual flushing, for efficiency,
774 * and correctness of the "inkey()" function.
776 void flush(void)
778 /* Do it later */
779 inkey_xtra = TRUE;
784 * Flush all pending input if the flush_failure option is set.
786 void flush_fail(void)
788 if (flush_failure) flush();
793 * Local variable -- we are inside a "macro action"
795 * Do not match any macros until "ascii 30" is found.
797 static bool parse_macro = FALSE;
801 * Local variable -- we are inside a "macro trigger"
803 * Strip all keypresses until a low ascii value is found.
805 static bool parse_under = FALSE;
810 * Helper function called only from "inkey()"
812 * This function does almost all of the "macro" processing.
814 * We use the "Term_key_push()" function to handle "failed" macros, as well
815 * as "extra" keys read in while choosing the proper macro, and also to hold
816 * the action for the macro, plus a special "ascii 30" character indicating
817 * that any macro action in progress is complete. Embedded macros are thus
818 * illegal, unless a macro action includes an explicit "ascii 30" character,
819 * which would probably be a massive hack, and might break things.
821 * Only 500 (0+1+2+...+29+30) milliseconds may elapse between each key in
822 * the macro trigger sequence. If a key sequence forms the "prefix" of a
823 * macro trigger, 500 milliseconds must pass before the key sequence is
824 * known not to be that macro trigger. XXX XXX XXX
826 static event_type inkey_aux(void)
828 int k = 0, n, p = 0, w = 0;
830 event_type ke, ke0;
831 char ch;
833 cptr pat, act;
835 char buf[1024];
837 /* Initialize the no return */
838 ke0.type = EVT_KBRD;
839 ke0.key = 0;
840 ke0.index = 0; /* To fix GCC warnings on X11 */
841 ke0.mousey = 0;
842 ke0.mousex = 0;
844 /* Wait for a keypress */
845 (void)(Term_inkey(&ke, TRUE, TRUE));
846 ch = ke.key;
848 /* End "macro action" */
849 if ((ch == 30) || (ch == '\xff'))
851 parse_macro = FALSE;
852 return (ke);
855 /* Inside "macro action" */
856 if (parse_macro) return (ke);
858 /* Inside "macro trigger" */
859 if (parse_under) return (ke);
862 /* Save the first key, advance */
863 buf[p++] = ch;
864 buf[p] = '\0';
867 /* Check for possible macro */
868 k = macro_find_check(buf);
870 /* No macro pending */
871 if (k < 0) return (ke);
874 /* Wait for a macro, or a timeout */
875 while (TRUE)
877 /* Check for pending macro */
878 k = macro_find_maybe(buf);
880 /* No macro pending */
881 if (k < 0) break;
883 /* Check for (and remove) a pending key */
884 if (0 == Term_inkey(&ke, FALSE, TRUE))
886 /* Append the key */
887 buf[p++] = ke.key;
888 buf[p] = '\0';
890 /* Restart wait */
891 w = 0;
894 /* No key ready */
895 else
897 /* Increase "wait" */
898 w += 10;
900 /* Excessive delay */
901 if (w >= 100) break;
903 /* Delay */
904 Term_xtra(TERM_XTRA_DELAY, w);
909 /* Check for available macro */
910 k = macro_find_ready(buf);
912 /* No macro available */
913 if (k < 0)
915 /* Push all the "keys" back on the queue */
916 /* The most recent event may not be a keypress. */
917 if(p)
919 if(Term_event_push(&ke)) return (ke0);
920 p--;
922 while (p > 0)
924 /* Push the key, notice over-flow */
925 if (Term_key_push(buf[--p])) return (ke0);
928 /* Wait for (and remove) a pending key */
929 (void)Term_inkey(&ke, TRUE, TRUE);
931 /* Return the key */
932 return (ke);
936 /* Get the pattern */
937 pat = macro__pat[k];
939 /* Get the length of the pattern */
940 n = strlen(pat);
942 /* Push the "extra" keys back on the queue */
943 while (p > n)
945 /* Push the key, notice over-flow */
946 if (Term_key_push(buf[--p])) return (ke0);
950 /* Begin "macro action" */
951 parse_macro = TRUE;
953 /* Push the "end of macro action" key */
954 if (Term_key_push(30)) return (ke0);
957 /* Access the macro action */
958 act = macro__act[k];
960 /* Get the length of the action */
961 n = strlen(act);
963 /* Push the macro "action" onto the key queue */
964 while (n > 0)
966 /* Push the key, notice over-flow */
967 if (Term_key_push(act[--n])) return (ke0);
971 /* Hack -- Force "inkey()" to call us again */
972 return (ke0);
978 * Mega-Hack -- special "inkey_next" pointer. XXX XXX XXX
980 * This special pointer allows a sequence of keys to be "inserted" into
981 * the stream of keys returned by "inkey()". This key sequence will not
982 * trigger any macros, and cannot be bypassed by the Borg. It is used
983 * in Angband to handle "keymaps".
985 static cptr inkey_next = NULL;
988 #ifdef ALLOW_BORG
991 * Mega-Hack -- special "inkey_hack" hook. XXX XXX XXX
993 * This special function hook allows the "Borg" (see elsewhere) to take
994 * control of the "inkey()" function, and substitute in fake keypresses.
996 char (*inkey_hack)(int flush_first) = NULL;
998 #endif /* ALLOW_BORG */
1002 * Get a keypress from the user.
1004 * This function recognizes a few "global parameters". These are variables
1005 * which, if set to TRUE before calling this function, will have an effect
1006 * on this function, and which are always reset to FALSE by this function
1007 * before this function returns. Thus they function just like normal
1008 * parameters, except that most calls to this function can ignore them.
1010 * If "inkey_xtra" is TRUE, then all pending keypresses will be flushed,
1011 * and any macro processing in progress will be aborted. This flag is
1012 * set by the "flush()" function, which does not actually flush anything
1013 * itself, but rather, triggers delayed input flushing via "inkey_xtra".
1015 * If "inkey_scan" is TRUE, then we will immediately return "zero" if no
1016 * keypress is available, instead of waiting for a keypress.
1018 * If "inkey_base" is TRUE, then all macro processing will be bypassed.
1019 * If "inkey_base" and "inkey_scan" are both TRUE, then this function will
1020 * not return immediately, but will wait for a keypress for as long as the
1021 * normal macro matching code would, allowing the direct entry of macro
1022 * triggers. The "inkey_base" flag is extremely dangerous!
1024 * If "inkey_flag" is TRUE, then we will assume that we are waiting for a
1025 * normal command, and we will only show the cursor if "hilite_player" is
1026 * TRUE (or if the player is in a store), instead of always showing the
1027 * cursor. The various "main-xxx.c" files should avoid saving the game
1028 * in response to a "menu item" request unless "inkey_flag" is TRUE, to
1029 * prevent savefile corruption.
1031 * If we are waiting for a keypress, and no keypress is ready, then we will
1032 * refresh (once) the window which was active when this function was called.
1034 * Note that "back-quote" is automatically converted into "escape" for
1035 * convenience on machines with no "escape" key. This is done after the
1036 * macro matching, so the user can still make a macro for "backquote".
1038 * Note the special handling of "ascii 30" (ctrl-caret, aka ctrl-shift-six)
1039 * and "ascii 31" (ctrl-underscore, aka ctrl-shift-minus), which are used to
1040 * provide support for simple keyboard "macros". These keys are so strange
1041 * that their loss as normal keys will probably be noticed by nobody. The
1042 * "ascii 30" key is used to indicate the "end" of a macro action, which
1043 * allows recursive macros to be avoided. The "ascii 31" key is used by
1044 * some of the "main-xxx.c" files to introduce macro trigger sequences.
1046 * Hack -- we use "ascii 29" (ctrl-right-bracket) as a special "magic" key,
1047 * which can be used to give a variety of "sub-commands" which can be used
1048 * any time. These sub-commands could include commands to take a picture of
1049 * the current screen, to start/stop recording a macro action, etc.
1051 * If "angband_term[0]" is not active, we will make it active during this
1052 * function, so that the various "main-xxx.c" files can assume that input
1053 * is only requested (via "Term_inkey()") when "angband_term[0]" is active.
1055 * Mega-Hack -- This function is used as the entry point for clearing the
1056 * "signal_count" variable, and of the "character_saved" variable.
1058 * Hack -- Note the use of "inkey_next" to allow "keymaps" to be processed.
1060 * Mega-Hack -- Note the use of "inkey_hack" to allow the "Borg" to steal
1061 * control of the keyboard from the user.
1063 event_type inkey_ex(void)
1065 bool cursor_state;
1066 event_type kk;
1067 event_type ke;
1069 bool done = FALSE;
1071 term *old = Term;
1074 /* Initialise keypress */
1075 ke.key = 0;
1076 ke.type = EVT_KBRD;
1078 /* Hack -- Use the "inkey_next" pointer */
1079 if (inkey_next && *inkey_next && !inkey_xtra)
1081 /* Get next character, and advance */
1082 ke.key = *inkey_next++;
1084 /* Cancel the various "global parameters" */
1085 inkey_base = inkey_xtra = inkey_flag = inkey_scan = FALSE;
1087 /* Accept result */
1088 return (ke);
1091 /* Forget pointer */
1092 inkey_next = NULL;
1095 #ifdef ALLOW_BORG
1097 /* Mega-Hack -- Use the special hook */
1098 if (inkey_hack && ((ch = (*inkey_hack)(inkey_xtra)) != 0))
1100 /* Cancel the various "global parameters" */
1101 inkey_base = inkey_xtra = inkey_flag = inkey_scan = FALSE;
1102 ke.type = EVT_KBRD;
1104 /* Accept result */
1105 return (ke);
1108 #endif /* ALLOW_BORG */
1111 /* Hack -- handle delayed "flush()" */
1112 if (inkey_xtra)
1114 /* End "macro action" */
1115 parse_macro = FALSE;
1116 ke.type = EVT_KBRD;
1118 /* End "macro trigger" */
1119 parse_under = FALSE;
1121 /* Forget old keypresses */
1122 Term_flush();
1126 /* Get the cursor state */
1127 (void)Term_get_cursor(&cursor_state);
1129 /* Show the cursor if waiting, except sometimes in "command" mode */
1130 if (!inkey_scan && (!inkey_flag || hilite_player || character_icky))
1132 /* Show the cursor */
1133 (void)Term_set_cursor(TRUE);
1137 /* Hack -- Activate main screen */
1138 Term_activate(term_screen);
1141 /* Get a key */
1142 while (!ke.key)
1144 /* Hack -- Handle "inkey_scan" */
1145 if (!inkey_base && inkey_scan &&
1146 (0 != Term_inkey(&kk, FALSE, FALSE)))
1148 break;
1152 /* Hack -- Flush output once when no key ready */
1153 if (!done && (0 != Term_inkey(&kk, FALSE, FALSE)))
1156 /* Hack -- activate proper term */
1157 Term_activate(old);
1159 /* Flush output */
1160 Term_fresh();
1162 /* Hack -- activate main screen */
1163 Term_activate(term_screen);
1165 /* Mega-Hack -- reset saved flag */
1166 character_saved = FALSE;
1168 /* Mega-Hack -- reset signal counter */
1169 signal_count = 0;
1171 /* Only once */
1172 done = TRUE;
1176 /* Hack -- Handle "inkey_base" */
1177 if (inkey_base)
1179 int w = 0;
1181 /* Wait forever */
1182 if (!inkey_scan)
1184 /* Wait for (and remove) a pending key */
1185 if (0 == Term_inkey(&ke, TRUE, TRUE))
1187 /* Done */
1188 break;
1191 /* Oops */
1192 break;
1195 /* Wait only as long as macro activation would wait*/
1196 while (TRUE)
1198 /* Check for (and remove) a pending key */
1199 if (0 == Term_inkey(&ke, FALSE, TRUE))
1201 /* Done */
1202 break;
1205 /* No key ready */
1206 else
1208 /* Increase "wait" */
1209 w += 10;
1211 /* Excessive delay */
1212 if (w >= 100) break;
1214 /* Delay */
1215 Term_xtra(TERM_XTRA_DELAY, w);
1220 /* Done */
1221 ke.type = EVT_KBRD;
1222 break;
1226 /* Get a key (see above) */
1227 ke = inkey_aux();
1230 /* Handle "control-right-bracket" */
1231 if (ke.key == 29)
1233 /* Strip this key */
1234 ke.key = 0;
1236 /* Continue */
1237 continue;
1241 /* Treat back-quote as escape */
1242 if (ke.key == '`') ke.key = ESCAPE;
1245 /* End "macro trigger" */
1246 if (parse_under && (ke.key <= 32))
1248 /* Strip this key */
1249 ke.key = 0;
1251 /* End "macro trigger" */
1252 parse_under = FALSE;
1255 /* Handle "control-caret" */
1256 if (ke.key == 30)
1258 /* Strip this key */
1259 ke.key = 0;
1262 /* Handle "control-underscore" */
1263 else if (ke.key == 31)
1265 /* Strip this key */
1266 ke.key = 0;
1268 /* Begin "macro trigger" */
1269 parse_under = TRUE;
1272 /* Inside "macro trigger" */
1273 else if (parse_under)
1275 /* Strip this key */
1276 ke.key = 0;
1281 /* Hack -- restore the term */
1282 Term_activate(old);
1285 /* Restore the cursor */
1286 Term_set_cursor(cursor_state);
1289 /* Cancel the various "global parameters" */
1290 inkey_base = inkey_xtra = inkey_flag = inkey_scan = FALSE;
1293 /* Return the keypress */
1294 return (ke);
1299 * Get a keypress or mouse click from the user.
1301 char anykey(void)
1303 event_type ke = EVENT_EMPTY;
1305 /* Only accept a keypress or mouse click*/
1308 ke = inkey_ex();
1309 } while (!(ke.type & (EVT_MOUSE|EVT_KBRD)));
1311 return ke.key;
1315 * Get a "keypress" from the user.
1317 char inkey(void)
1319 event_type ke;
1321 /* Only accept a keypress */
1324 ke = inkey_ex();
1325 } while (!(ke.type & (EVT_KBRD|EVT_ESCAPE)));
1326 /* Paranoia */
1327 if(ke.type == EVT_ESCAPE) ke.key = ESCAPE;
1329 return ke.key;
1335 * Flush the screen, make a noise
1337 void bell(cptr reason)
1339 /* Mega-Hack -- Flush the output */
1340 Term_fresh();
1342 /* Hack -- memorize the reason if possible */
1343 if (character_generated && reason)
1345 message_add(reason, MSG_BELL);
1347 /* Window stuff */
1348 p_ptr->window |= (PW_MESSAGE);
1350 /* Force window redraw */
1351 window_stuff();
1354 /* Make a bell noise (if allowed) */
1355 if (ring_bell) Term_xtra(TERM_XTRA_NOISE, 0);
1357 /* Flush the input (later!) */
1358 flush();
1364 * Hack -- Make a (relevant?) sound
1366 void sound(int val)
1368 /* No sound */
1369 if (!use_sound) return;
1371 /* Make a noise */
1372 if (sound_hook)
1373 sound_hook(val);
1380 * The "quark" package
1382 * This package is used to reduce the memory usage of object inscriptions.
1384 * We use dynamic string allocation because otherwise it is necessary to
1385 * pre-guess the amount of quark activity. We limit the total number of
1386 * quarks, but this is much easier to "expand" as needed. XXX XXX XXX
1388 * Two objects with the same inscription will have the same "quark" index.
1390 * Some code uses "zero" to indicate the non-existance of a quark.
1392 * Note that "quark zero" is NULL and should never be "dereferenced".
1394 * ToDo: Add reference counting for quarks, so that unused quarks can
1395 * be overwritten.
1397 * ToDo: Automatically resize the array if necessary.
1402 * The number of quarks (first quark is NULL)
1404 static s16b quark__num = 1;
1408 * The array[QUARK_MAX] of pointers to the quarks
1410 static cptr *quark__str;
1414 * Add a new "quark" to the set of quarks.
1416 s16b quark_add(cptr str)
1418 int i;
1420 /* Look for an existing quark */
1421 for (i = 1; i < quark__num; i++)
1423 /* Check for equality */
1424 if (streq(quark__str[i], str)) return (i);
1427 /* Hack -- Require room XXX XXX XXX */
1428 if (quark__num == QUARK_MAX) return (0);
1430 /* New quark */
1431 i = quark__num++;
1433 /* Add a new quark */
1434 quark__str[i] = string_make(str);
1436 /* Return the index */
1437 return (i);
1442 * This function looks up a quark
1444 cptr quark_str(s16b i)
1446 cptr q;
1448 /* Verify */
1449 if ((i < 0) || (i >= quark__num)) i = 0;
1451 /* Get the quark */
1452 q = quark__str[i];
1454 /* Return the quark */
1455 return (q);
1460 * Initialize the "quark" package
1462 errr quarks_init(void)
1464 /* Quark variables */
1465 C_MAKE(quark__str, QUARK_MAX, cptr);
1467 /* Success */
1468 return (0);
1473 * Free the "quark" package
1475 errr quarks_free(void)
1477 int i;
1479 /* Free the "quarks" */
1480 for (i = 1; i < quark__num; i++)
1482 string_free(quark__str[i]);
1485 /* Free the list of "quarks" */
1486 FREE(quark__str);
1488 /* Success */
1489 return (0);
1493 * Looks if "inscrip" is present on the given object.
1495 bool check_for_inscrip(const object_type *o_ptr, const char *inscrip)
1497 if (o_ptr->note)
1499 const char *s = strstr(quark_str(o_ptr->note), inscrip);
1500 if (s) return TRUE;
1503 return FALSE;
1507 * The "message memorization" package.
1509 * Each call to "message_add(s)" will add a new "most recent" message
1510 * to the "message recall list", using the contents of the string "s".
1512 * The number of memorized messages is available as "message_num()".
1514 * Old messages can be retrieved by "message_str(age)", where the "age"
1515 * of the most recently memorized message is zero, and the oldest "age"
1516 * which is available is "message_num() - 1". Messages outside this
1517 * range are returned as the empty string.
1519 * The messages are stored in a special manner that maximizes "efficiency",
1520 * that is, we attempt to maximize the number of semi-sequential messages
1521 * that can be retrieved, given a limited amount of storage space, without
1522 * causing the memorization of new messages or the recall of old messages
1523 * to be too expensive.
1525 * We keep a buffer of chars to hold the "text" of the messages, more or
1526 * less in the order they were memorized, and an array of offsets into that
1527 * buffer, representing the actual messages, but we allow the "text" to be
1528 * "shared" by two messages with "similar" ages, as long as we never cause
1529 * sharing to reach too far back in the the buffer.
1531 * The implementation is complicated by the fact that both the array of
1532 * offsets, and the buffer itself, are both treated as "circular arrays"
1533 * for efficiency purposes, but the strings may not be "broken" across
1534 * the ends of the array.
1536 * When we want to memorize a new message, we attempt to "reuse" the buffer
1537 * space by checking for message duplication within the recent messages.
1539 * Otherwise, if we need more buffer space, we grab a full quarter of the
1540 * total buffer space at a time, to keep the reclamation code efficient.
1542 * The "message_add()" function is rather "complex", because it must be
1543 * extremely efficient, both in space and time, for use with the Borg.
1548 * The next "free" index to use
1550 static u16b message__next;
1553 * The index of the oldest message (none yet)
1555 static u16b message__last;
1558 * The next "free" offset
1560 static u16b message__head;
1563 * The offset to the oldest used char (none yet)
1565 static u16b message__tail;
1568 * The array[MESSAGE_MAX] of offsets, by index
1570 static u16b *message__ptr;
1573 * The array[MESSAGE_BUF] of chars, by offset
1575 static char *message__buf;
1578 * The array[MESSAGE_MAX] of u16b for the types of messages
1580 static u16b *message__type;
1583 * The array[MESSAGE_MAX] of u16b for the count of messages
1585 static u16b *message__count;
1589 * Table of colors associated to message-types
1591 static byte message__color[MSG_MAX];
1595 * Calculate the index of a message
1597 static s16b message_age2idx(int age)
1599 return ((message__next + MESSAGE_MAX - (age + 1)) % MESSAGE_MAX);
1604 * How many messages are "available"?
1606 s16b message_num(void)
1608 /* Determine how many messages are "available" */
1609 return (message_age2idx(message__last - 1));
1615 * Recall the "text" of a saved message
1617 cptr message_str(s16b age)
1619 static char buf[1024];
1620 s16b x;
1621 u16b o;
1622 cptr s;
1624 /* Forgotten messages have no text */
1625 if ((age < 0) || (age >= message_num())) return ("");
1627 /* Get the "logical" index */
1628 x = message_age2idx(age);
1630 /* Get the "offset" for the message */
1631 o = message__ptr[x];
1633 /* Get the message text */
1634 s = &message__buf[o];
1636 /* HACK - Handle repeated messages */
1637 if (message__count[x] > 1)
1639 strnfmt(buf, sizeof(buf), "%s <%dx>", s, message__count[x]);
1640 s = buf;
1643 /* Return the message text */
1644 return (s);
1649 * Recall the "type" of a saved message
1651 u16b message_type(s16b age)
1653 s16b x;
1655 /* Paranoia */
1656 if (!message__type) return (MSG_GENERIC);
1658 /* Forgotten messages are generic */
1659 if ((age < 0) || (age >= message_num())) return (MSG_GENERIC);
1661 /* Get the "logical" index */
1662 x = message_age2idx(age);
1664 /* Return the message type */
1665 return (message__type[x]);
1670 * Recall the "color" of a message type
1672 static byte message_type_color(u16b type)
1674 byte color = message__color[type];
1676 if (color == TERM_DARK) color = TERM_WHITE;
1678 return (color);
1683 * Recall the "color" of a saved message
1685 byte message_color(s16b age)
1687 return message_type_color(message_type(age));
1691 errr message_color_define(u16b type, byte color)
1693 /* Ignore illegal types */
1694 if (type >= MSG_MAX) return (1);
1696 /* Store the color */
1697 message__color[type] = color;
1699 /* Success */
1700 return (0);
1705 * Add a new message, with great efficiency
1707 * We must ignore long messages to prevent internal overflow, since we
1708 * assume that we can always get enough space by advancing "message__tail"
1709 * by one quarter the total buffer space.
1711 * We must not attempt to optimize using a message index or buffer space
1712 * which is "far away" from the most recent entries, or we will lose a lot
1713 * of messages when we "expire" the old message index and/or buffer space.
1715 void message_add(cptr str, u16b type)
1717 int k, i, x, o;
1718 size_t n;
1720 cptr s;
1722 cptr u;
1723 char *v;
1726 /*** Step 1 -- Analyze the message ***/
1728 /* Hack -- Ignore "non-messages" */
1729 if (!str) return;
1731 /* Message length */
1732 n = strlen(str);
1734 /* Hack -- Ignore "long" messages */
1735 if (n >= MESSAGE_BUF / 4) return;
1738 /*** Step 2 -- Attempt to optimize ***/
1740 /* Get the "logical" last index */
1741 x = message_age2idx(0);
1743 /* Get the "offset" for the last message */
1744 o = message__ptr[x];
1746 /* Get the message text */
1747 s = &message__buf[o];
1749 /* Last message repeated? */
1750 if (streq(str, s))
1752 /* Increase the message count */
1753 message__count[x]++;
1755 /* Success */
1756 return;
1759 /*** Step 3 -- Attempt to optimize ***/
1761 /* Limit number of messages to check */
1762 k = message_num() / 4;
1764 /* Limit number of messages to check */
1765 if (k > 32) k = 32;
1767 /* Start just after the most recent message */
1768 i = message__next;
1770 /* Check the last few messages for duplication */
1771 for ( ; k; k--)
1773 u16b q;
1775 cptr old;
1777 /* Back up, wrap if needed */
1778 if (i-- == 0) i = MESSAGE_MAX - 1;
1780 /* Stop before oldest message */
1781 if (i == message__last) break;
1783 /* Index */
1784 o = message__ptr[i];
1786 /* Extract "distance" from "head" */
1787 q = (message__head + MESSAGE_BUF - o) % MESSAGE_BUF;
1789 /* Do not optimize over large distances */
1790 if (q >= MESSAGE_BUF / 4) continue;
1792 /* Get the old string */
1793 old = &message__buf[o];
1795 /* Continue if not equal */
1796 if (!streq(str, old)) continue;
1798 /* Get the next available message index */
1799 x = message__next;
1801 /* Advance 'message__next', wrap if needed */
1802 if (++message__next == MESSAGE_MAX) message__next = 0;
1804 /* Kill last message if needed */
1805 if (message__next == message__last)
1807 /* Advance 'message__last', wrap if needed */
1808 if (++message__last == MESSAGE_MAX) message__last = 0;
1811 /* Assign the starting address */
1812 message__ptr[x] = message__ptr[i];
1814 /* Store the message type */
1815 message__type[x] = type;
1817 /* Store the message count */
1818 message__count[x] = 1;
1820 /* Success */
1821 return;
1824 /*** Step 4 -- Ensure space before end of buffer ***/
1826 /* Kill messages, and wrap, if needed */
1827 if (message__head + (n + 1) >= MESSAGE_BUF)
1829 /* Kill all "dead" messages */
1830 for (i = message__last; TRUE; i++)
1832 /* Wrap if needed */
1833 if (i == MESSAGE_MAX) i = 0;
1835 /* Stop before the new message */
1836 if (i == message__next) break;
1838 /* Get offset */
1839 o = message__ptr[i];
1841 /* Kill "dead" messages */
1842 if (o >= message__head)
1844 /* Track oldest message */
1845 message__last = i + 1;
1849 /* Wrap "tail" if needed */
1850 if (message__tail >= message__head) message__tail = 0;
1852 /* Start over */
1853 message__head = 0;
1857 /*** Step 5 -- Ensure space for actual characters ***/
1859 /* Kill messages, if needed */
1860 if (message__head + (n + 1) > message__tail)
1862 /* Advance to new "tail" location */
1863 message__tail += (MESSAGE_BUF / 4);
1865 /* Kill all "dead" messages */
1866 for (i = message__last; TRUE; i++)
1868 /* Wrap if needed */
1869 if (i == MESSAGE_MAX) i = 0;
1871 /* Stop before the new message */
1872 if (i == message__next) break;
1874 /* Get offset */
1875 o = message__ptr[i];
1877 /* Kill "dead" messages */
1878 if ((o >= message__head) && (o < message__tail))
1880 /* Track oldest message */
1881 message__last = i + 1;
1887 /*** Step 6 -- Grab a new message index ***/
1889 /* Get the next available message index */
1890 x = message__next;
1892 /* Advance 'message__next', wrap if needed */
1893 if (++message__next == MESSAGE_MAX) message__next = 0;
1895 /* Kill last message if needed */
1896 if (message__next == message__last)
1898 /* Advance 'message__last', wrap if needed */
1899 if (++message__last == MESSAGE_MAX) message__last = 0;
1903 /*** Step 7 -- Insert the message text ***/
1905 /* Assign the starting address */
1906 message__ptr[x] = message__head;
1908 /* Inline 'strcpy(message__buf + message__head, str)' */
1909 v = message__buf + message__head;
1910 for (u = str; *u; ) *v++ = *u++;
1911 *v = '\0';
1913 /* Advance the "head" pointer */
1914 message__head += (n + 1);
1916 /* Store the message type */
1917 message__type[x] = type;
1919 /* Store the message count */
1920 message__count[x] = 1;
1925 * Initialize the "message" package
1927 errr messages_init(void)
1929 /* Message variables */
1930 C_MAKE(message__ptr, MESSAGE_MAX, u16b);
1931 C_MAKE(message__buf, MESSAGE_BUF, char);
1932 C_MAKE(message__type, MESSAGE_MAX, u16b);
1933 C_MAKE(message__count, MESSAGE_MAX, u16b);
1935 /* Init the message colors to white */
1936 (void)C_BSET(message__color, TERM_WHITE, MSG_MAX, byte);
1938 /* Hack -- No messages yet */
1939 message__tail = MESSAGE_BUF;
1941 /* Success */
1942 return (0);
1947 * Free the "message" package
1949 void messages_free(void)
1951 /* Free the messages */
1952 FREE(message__ptr);
1953 FREE(message__buf);
1954 FREE(message__type);
1955 FREE(message__count);
1960 * XXX XXX XXX Important note about "colors" XXX XXX XXX
1962 * The "TERM_*" color definitions list the "composition" of each
1963 * "Angband color" in terms of "quarters" of each of the three color
1964 * components (Red, Green, Blue), for example, TERM_UMBER is defined
1965 * as 2/4 Red, 1/4 Green, 0/4 Blue.
1967 * The following info is from "Torbjorn Lindgren" (see "main-xaw.c").
1969 * These values are NOT gamma-corrected. On most machines (with the
1970 * Macintosh being an important exception), you must "gamma-correct"
1971 * the given values, that is, "correct for the intrinsic non-linearity
1972 * of the phosphor", by converting the given intensity levels based
1973 * on the "gamma" of the target screen, which is usually 1.7 (or 1.5).
1975 * The actual formula for conversion is unknown to me at this time,
1976 * but you can use the table below for the most common gamma values.
1978 * So, on most machines, simply convert the values based on the "gamma"
1979 * of the target screen, which is usually in the range 1.5 to 1.7, and
1980 * usually is closest to 1.7. The converted value for each of the five
1981 * different "quarter" values is given below:
1983 * Given Gamma 1.0 Gamma 1.5 Gamma 1.7 Hex 1.7
1984 * ----- ---- ---- ---- ---
1985 * 0/4 0.00 0.00 0.00 #00
1986 * 1/4 0.25 0.27 0.28 #47
1987 * 2/4 0.50 0.55 0.56 #8f
1988 * 3/4 0.75 0.82 0.84 #d7
1989 * 4/4 1.00 1.00 1.00 #ff
1991 * Note that some machines (i.e. most IBM machines) are limited to a
1992 * hard-coded set of colors, and so the information above is useless.
1994 * Also, some machines are limited to a pre-determined set of colors,
1995 * for example, the IBM can only display 16 colors, and only 14 of
1996 * those colors resemble colors used by Angband, and then only when
1997 * you ignore the fact that "Slate" and "cyan" are not really matches,
1998 * so on the IBM, we use "orange" for both "Umber", and "Light Umber"
1999 * in addition to the obvious "Orange", since by combining all of the
2000 * "indeterminate" colors into a single color, the rest of the colors
2001 * are left with "meaningful" values.
2008 * Hack -- flush
2010 static void msg_flush(int x)
2012 byte a = TERM_L_BLUE;
2014 /* Pause for response */
2015 Term_putstr(x, 0, -1, a, "-more-");
2017 if (!auto_more)
2019 /* Get an acceptable keypress */
2020 while (1)
2022 char ch;
2023 ch = inkey();
2024 if (quick_messages) break;
2025 if ((ch == ESCAPE) || (ch == ' ')) break;
2026 if ((ch == '\n') || (ch == '\r')) break;
2027 bell("Illegal response to a 'more' prompt!");
2031 /* Clear the line */
2032 Term_erase(0, 0, 255);
2036 static int message_column = 0;
2040 * Output a message to the top line of the screen.
2042 * Break long messages into multiple pieces (40-72 chars).
2044 * Allow multiple short messages to "share" the top line.
2046 * Prompt the user to make sure he has a chance to read them.
2048 * These messages are memorized for later reference (see above).
2050 * We could do a "Term_fresh()" to provide "flicker" if needed.
2052 * The global "msg_flag" variable can be cleared to tell us to "erase" any
2053 * "pending" messages still on the screen, instead of using "msg_flush()".
2054 * This should only be done when the user is known to have read the message.
2056 * We must be very careful about using the "msg_print()" functions without
2057 * explicitly calling the special "msg_print(NULL)" function, since this may
2058 * result in the loss of information if the screen is cleared, or if anything
2059 * is displayed on the top line.
2061 * Hack -- Note that "msg_print(NULL)" will clear the top line even if no
2062 * messages are pending.
2064 static void msg_print_aux(u16b type, cptr msg)
2066 int n;
2067 char *t;
2068 char buf[1024];
2069 byte color;
2070 int w, h;
2073 /* Obtain the size */
2074 (void)Term_get_size(&w, &h);
2076 /* Hack -- Reset */
2077 if (!msg_flag) message_column = 0;
2079 /* Message Length */
2080 n = (msg ? strlen(msg) : 0);
2082 /* Hack -- flush when requested or needed */
2083 if (message_column && (!msg || ((message_column + n) > (w - 8))))
2085 /* Flush */
2086 msg_flush(message_column);
2088 /* Forget it */
2089 msg_flag = FALSE;
2091 /* Reset */
2092 message_column = 0;
2096 /* No message */
2097 if (!msg) return;
2099 /* Paranoia */
2100 if (n > 1000) return;
2103 /* Memorize the message (if legal) */
2104 if (character_generated && !(p_ptr->is_dead))
2105 message_add(msg, type);
2107 /* Window stuff */
2108 p_ptr->window |= (PW_MESSAGE);
2110 /* Copy it */
2111 my_strcpy(buf, msg, sizeof(buf));
2113 /* Analyze the buffer */
2114 t = buf;
2116 /* Get the color of the message */
2117 color = message_type_color(type);
2119 /* Split message */
2120 while (n > (w - 8))
2122 char oops;
2124 int check, split;
2126 /* Default split */
2127 split = (w - 8);
2129 /* Find the "best" split point */
2130 for (check = (w / 2); check < (w - 8); check++)
2132 /* Found a valid split point */
2133 if (t[check] == ' ') split = check;
2136 /* Save the split character */
2137 oops = t[split];
2139 /* Split the message */
2140 t[split] = '\0';
2142 /* Display part of the message */
2143 Term_putstr(0, 0, split, color, t);
2145 /* Flush it */
2146 msg_flush(split + 1);
2148 /* Restore the split character */
2149 t[split] = oops;
2151 /* Insert a space */
2152 t[--split] = ' ';
2154 /* Prepare to recurse on the rest of "buf" */
2155 t += split; n -= split;
2158 /* Display the tail of the message */
2159 Term_putstr(message_column, 0, n, color, t);
2161 /* Remember the message */
2162 msg_flag = TRUE;
2164 /* Remember the position */
2165 message_column += n + 1;
2170 * Print a message in the default color (white)
2172 void msg_print(cptr msg)
2174 msg_print_aux(MSG_GENERIC, msg);
2179 * Display a formatted message, using "vstrnfmt()" and "msg_print()".
2181 void msg_format(cptr fmt, ...)
2183 va_list vp;
2185 char buf[1024];
2187 /* Begin the Varargs Stuff */
2188 va_start(vp, fmt);
2190 /* Format the args, save the length */
2191 (void)vstrnfmt(buf, sizeof(buf), fmt, vp);
2193 /* End the Varargs Stuff */
2194 va_end(vp);
2196 /* Display */
2197 msg_print_aux(MSG_GENERIC, buf);
2202 * Display a message and play the associated sound.
2204 * The "extra" parameter is currently unused.
2206 void message(u16b message_type, s16b extra, cptr message)
2208 /* Unused parameter */
2209 (void)extra;
2211 sound(message_type);
2213 msg_print_aux(message_type, message);
2219 * Display a formatted message and play the associated sound.
2221 * The "extra" parameter is currently unused.
2223 void message_format(u16b message_type, s16b extra, cptr fmt, ...)
2225 va_list vp;
2227 char buf[1024];
2229 /* Begin the Varargs Stuff */
2230 va_start(vp, fmt);
2232 /* Format the args, save the length */
2233 (void)vstrnfmt(buf, sizeof(buf), fmt, vp);
2235 /* End the Varargs Stuff */
2236 va_end(vp);
2238 /* Display */
2239 message(message_type, extra, buf);
2244 * Print the queued messages.
2246 void message_flush(void)
2248 /* Hack -- Reset */
2249 if (!msg_flag) message_column = 0;
2251 /* Flush when needed */
2252 if (message_column)
2254 /* Print pending messages */
2255 msg_flush(message_column);
2257 /* Forget it */
2258 msg_flag = FALSE;
2260 /* Reset */
2261 message_column = 0;
2268 * Save the screen, and increase the "icky" depth.
2270 * This function must match exactly one call to "screen_load()".
2272 void screen_save(void)
2274 /* Hack -- Flush messages */
2275 message_flush();
2277 /* Save the screen (if legal) */
2278 Term_save();
2280 /* Increase "icky" depth */
2281 character_icky++;
2286 * Load the screen, and decrease the "icky" depth.
2288 * This function must match exactly one call to "screen_save()".
2290 void screen_load(void)
2292 /* Hack -- Flush messages */
2293 message_flush();
2295 /* Load the screen (if legal) */
2296 Term_load();
2298 /* Decrease "icky" depth */
2299 character_icky--;
2304 * Display a string on the screen using an attribute.
2306 * At the given location, using the given attribute, if allowed,
2307 * add the given string. Do not clear the line.
2309 void c_put_str(byte attr, cptr str, int row, int col)
2311 /* Position cursor, Dump the attr/text */
2312 Term_putstr(col, row, -1, attr, str);
2317 * As above, but in "white"
2319 void put_str(cptr str, int row, int col)
2321 /* Spawn */
2322 Term_putstr(col, row, -1, TERM_WHITE, str);
2328 * Display a string on the screen using an attribute, and clear
2329 * to the end of the line.
2331 void c_prt(byte attr, cptr str, int row, int col)
2333 /* Clear line, position cursor */
2334 Term_erase(col, row, 255);
2336 /* Dump the attr/text */
2337 Term_addstr(-1, attr, str);
2342 * As above, but in "white"
2344 void prt(cptr str, int row, int col)
2346 /* Spawn */
2347 c_prt(TERM_WHITE, str, row, col);
2352 * Print some (colored) text to the screen at the current cursor position,
2353 * automatically "wrapping" existing text (at spaces) when necessary to
2354 * avoid placing any text into the last column, and clearing every line
2355 * before placing any text in that line. Also, allow "newline" to force
2356 * a "wrap" to the next line. Advance the cursor as needed so sequential
2357 * calls to this function will work correctly.
2359 * Once this function has been called, the cursor should not be moved
2360 * until all the related "text_out()" calls to the window are complete.
2362 * This function will correctly handle any width up to the maximum legal
2363 * value of 256, though it works best for a standard 80 character width.
2365 void text_out_to_screen(byte a, cptr str)
2367 int x, y;
2369 int wid, h;
2371 int wrap;
2373 cptr s;
2376 /* Obtain the size */
2377 (void)Term_get_size(&wid, &h);
2379 /* Obtain the cursor */
2380 (void)Term_locate(&x, &y);
2382 /* Use special wrapping boundary? */
2383 if ((text_out_wrap > 0) && (text_out_wrap < wid))
2384 wrap = text_out_wrap;
2385 else
2386 wrap = wid;
2388 /* Process the string */
2389 for (s = str; *s; s++)
2391 char ch;
2393 /* Force wrap */
2394 if (*s == '\n')
2396 /* Wrap */
2397 x = text_out_indent;
2398 y++;
2400 /* Clear line, move cursor */
2401 Term_erase(x, y, 255);
2403 continue;
2406 /* Clean up the char */
2407 ch = (isprint((unsigned char)*s) ? *s : ' ');
2409 /* Wrap words as needed */
2410 if ((x >= wrap - 1) && (ch != ' '))
2412 int i, n = 0;
2414 byte av[256];
2415 char cv[256];
2417 /* Wrap word */
2418 if (x < wrap)
2420 /* Scan existing text */
2421 for (i = wrap - 2; i >= 0; i--)
2423 /* Grab existing attr/char */
2424 Term_what(i, y, &av[i], &cv[i]);
2426 /* Break on space */
2427 if (cv[i] == ' ') break;
2429 /* Track current word */
2430 n = i;
2434 /* Special case */
2435 if (n == 0) n = wrap;
2437 /* Clear line */
2438 Term_erase(n, y, 255);
2440 /* Wrap */
2441 x = text_out_indent;
2442 y++;
2444 /* Clear line, move cursor */
2445 Term_erase(x, y, 255);
2447 /* Wrap the word (if any) */
2448 for (i = n; i < wrap - 1; i++)
2450 /* Dump */
2451 Term_addch(av[i], cv[i]);
2453 /* Advance (no wrap) */
2454 if (++x > wrap) x = wrap;
2458 /* Dump */
2459 Term_addch(a, ch);
2461 /* Advance */
2462 if (++x > wrap) x = wrap;
2468 * Write text to the given file and apply line-wrapping.
2470 * Hook function for text_out(). Make sure that text_out_file points
2471 * to an open text-file.
2473 * Long lines will be wrapped at text_out_wrap, or at column 75 if that
2474 * is not set; or at a newline character. Note that punctuation can
2475 * sometimes be placed one column beyond the wrap limit.
2477 * You must be careful to end all file output with a newline character
2478 * to "flush" the stored line position.
2480 void text_out_to_file(byte a, cptr str)
2482 /* Current position on the line */
2483 static int pos = 0;
2485 /* Wrap width */
2486 int wrap = (text_out_wrap ? text_out_wrap : 75);
2488 /* Current location within "str" */
2489 cptr s = str;
2491 /* Unused parameter */
2492 (void)a;
2494 /* Process the string */
2495 while (*s)
2497 char ch;
2498 int n = 0;
2499 int len = wrap - pos;
2500 int l_space = -1;
2502 /* If we are at the start of the line... */
2503 if (pos == 0)
2505 int i;
2507 /* Output the indent */
2508 for (i = 0; i < text_out_indent; i++)
2510 fputc(' ', text_out_file);
2511 pos++;
2515 /* Find length of line up to next newline or end-of-string */
2516 while ((n < len) && !((s[n] == '\n') || (s[n] == '\0')))
2518 /* Mark the most recent space in the string */
2519 if (s[n] == ' ') l_space = n;
2521 /* Increment */
2522 n++;
2525 /* If we have encountered no spaces */
2526 if ((l_space == -1) && (n == len))
2528 /* If we are at the start of a new line */
2529 if (pos == text_out_indent)
2531 len = n;
2533 /* HACK - Output punctuation at the end of the line */
2534 else if ((s[0] == ' ') || (s[0] == ',') || (s[0] == '.'))
2536 len = 1;
2538 else
2540 /* Begin a new line */
2541 fputc('\n', text_out_file);
2543 /* Reset */
2544 pos = 0;
2546 continue;
2549 else
2551 /* Wrap at the newline */
2552 if ((s[n] == '\n') || (s[n] == '\0')) len = n;
2554 /* Wrap at the last space */
2555 else len = l_space;
2558 /* Write that line to file */
2559 for (n = 0; n < len; n++)
2561 /* Ensure the character is printable */
2562 ch = (isprint((unsigned char) s[n]) ? s[n] : ' ');
2564 /* Write out the character */
2565 fputc(ch, text_out_file);
2567 /* Increment */
2568 pos++;
2571 /* Move 's' past the stuff we've written */
2572 s += len;
2574 /* If we are at the end of the string, end */
2575 if (*s == '\0') return;
2577 /* Skip newlines */
2578 if (*s == '\n') s++;
2580 /* Begin a new line */
2581 fputc('\n', text_out_file);
2583 /* Reset */
2584 pos = 0;
2586 /* Skip whitespace */
2587 while (*s == ' ') s++;
2590 /* We are done */
2591 return;
2596 * Output text to the screen or to a file depending on the selected
2597 * text_out hook.
2599 void text_out(cptr str)
2601 text_out_c(TERM_WHITE, str);
2606 * Output text to the screen (in color) or to a file depending on the
2607 * selected hook.
2609 void text_out_c(byte a, cptr str)
2611 text_out_hook(a, str);
2616 * Clear part of the screen
2618 void clear_from(int row)
2620 int y;
2622 /* Erase requested rows */
2623 for (y = row; y < Term->hgt; y++)
2625 /* Erase part of the screen */
2626 Term_erase(0, y, 255);
2631 * The default "keypress handling function" for askfor_aux, this takes the
2632 * given keypress, input buffer, length, etc, and does the appropriate action
2633 * for each keypress, such as moving the cursor left or inserting a character.
2635 * It should return TRUE when editing of the buffer is "complete" (e.g. on
2636 * the press of RETURN).
2638 bool askfor_aux_keypress(char *buf, size_t buflen, size_t *curs, size_t *len, char keypress, bool firsttime)
2640 switch (keypress)
2642 case ESCAPE:
2644 *curs = 0;
2645 return TRUE;
2646 break;
2649 case '\n':
2650 case '\r':
2652 *curs = *len;
2653 return TRUE;
2654 break;
2657 case ARROW_LEFT:
2659 if (firsttime) *curs = 0;
2660 if (*curs > 0) (*curs)--;
2661 break;
2664 case ARROW_RIGHT:
2666 if (firsttime) *curs = *len - 1;
2667 if (*curs < *len) (*curs)++;
2668 break;
2671 case 0x7F:
2672 case '\010':
2674 /* If this is the first time round, backspace means "delete all" */
2675 if (firsttime)
2677 buf[0] = '\0';
2678 *curs = 0;
2679 *len = 0;
2681 break;
2684 /* Refuse to backspace into oblivion */
2685 if (*curs == 0) break;
2687 /* Move the string from k to nul along to the left by 1 */
2688 memmove(&buf[*curs - 1], &buf[*curs], *len - *curs);
2690 /* Decrement */
2691 (*curs)--;
2692 (*len)--;
2694 /* Terminate */
2695 buf[*len] = '\0';
2697 break;
2700 default:
2702 bool atnull = (buf[*curs] == 0);
2705 if (!isprint((unsigned char)keypress))
2707 bell("Illegal edit key!");
2708 break;
2711 /* Clear the buffer if this is the first time round */
2712 if (firsttime)
2714 buf[0] = '\0';
2715 *curs = 0;
2716 *len = 0;
2717 atnull = 1;
2720 if (atnull)
2722 /* Make sure we have enough room for a new character */
2723 if ((*curs + 1) >= buflen) break;
2725 else
2727 /* Make sure we have enough room to add a new character */
2728 if ((*len + 1) >= buflen) break;
2730 /* Move the rest of the buffer along to make room */
2731 memmove(&buf[*curs+1], &buf[*curs], *len - *curs);
2734 /* Insert the character */
2735 buf[(*curs)++] = keypress;
2736 (*len)++;
2738 /* Terminate */
2739 buf[*len] = '\0';
2741 break;
2745 /* By default, we aren't done. */
2746 return FALSE;
2750 * Get some input at the cursor location.
2752 * The buffer is assumed to have been initialized to a default string.
2753 * Note that this string is often "empty" (see below).
2755 * The default buffer is displayed in yellow until cleared, which happens
2756 * on the first keypress, unless that keypress is Return.
2758 * Normal chars clear the default and append the char.
2759 * Backspace clears the default or deletes the final char.
2760 * Return accepts the current buffer contents and returns TRUE.
2761 * Escape clears the buffer and the window and returns FALSE.
2763 * Note that 'len' refers to the size of the buffer. The maximum length
2764 * of the input is 'len-1'.
2766 * 'keypress_h' is a pointer to a function to handle keypresses, altering
2767 * the input buffer, cursor position and suchlike as required. See
2768 * 'askfor_aux_keypress' (the default handler if you supply NULL for
2769 * 'keypress_h') for an example.
2771 bool askfor_aux(char *buf, size_t len, bool keypress_h(char *, size_t, size_t *, size_t *, char, bool))
2774 int y, x;
2776 size_t k = 0; /* Cursor position */
2777 size_t nul = 0; /* Position of the null byte in the string */
2779 char ch = '\0';
2781 bool done = FALSE;
2782 bool firsttime = TRUE;
2784 if (keypress_h == NULL)
2786 keypress_h = askfor_aux_keypress;
2789 /* Locate the cursor */
2790 Term_locate(&x, &y);
2793 /* Paranoia */
2794 if ((x < 0) || (x >= 80)) x = 0;
2797 /* Restrict the length */
2798 if (x + len > 80) len = 80 - x;
2800 /* Truncate the default entry */
2801 buf[len-1] = '\0';
2803 /* Get the position of the null byte */
2804 nul = strlen(buf);
2806 /* Display the default answer */
2807 Term_erase(x, y, (int)len);
2808 Term_putstr(x, y, -1, TERM_YELLOW, buf);
2810 /* Process input */
2811 while (!done)
2813 /* Place cursor */
2814 Term_gotoxy(x + k, y);
2816 /* Get a key */
2817 ch = inkey();
2819 /* Let the keypress handler deal with the keypress */
2820 done = keypress_h(buf, len, &k, &nul, ch, firsttime);
2822 /* Update the entry */
2823 Term_erase(x, y, (int)len);
2824 Term_putstr(x, y, -1, TERM_WHITE, buf);
2826 /* Not the first time round anymore */
2827 firsttime = FALSE;
2830 /* Done */
2831 return (ch != ESCAPE);
2835 * A "keypress" handling function for askfor_aux, that handles the special
2836 * case of '*' for a new random "name" and passes any other "keypress"
2837 * through to the default "editing" handler.
2839 bool get_name_keypress(char *buf, size_t buflen, size_t *curs, size_t *len, char keypress, bool firsttime)
2841 bool result;
2843 switch (keypress)
2845 case '*':
2847 *len = randname_make(RANDNAME_TOLKIEN, 4, 8, buf, buflen);
2848 buf[0] = toupper((unsigned char) buf[0]);
2849 *curs = 0;
2850 result = FALSE;
2851 break;
2855 default:
2857 result = askfor_aux_keypress(buf, buflen, curs, len, keypress, firsttime);
2858 break;
2862 return result;
2867 * Gets a name for the character, reacting to name changes.
2869 * If sf is TRUE, we change the savefile name depending on the character name.
2871 * What a horrible name for a global function. XXX XXX XXX
2873 bool get_name(bool sf)
2875 bool res;
2876 char tmp[32];
2878 /* Paranoia XXX XXX XXX */
2879 message_flush();
2881 /* Display prompt */
2882 prt("Enter a name for your character (* for a random name): ", 0, 0);
2884 /* Save the player name */
2885 my_strcpy(tmp, op_ptr->full_name, sizeof(tmp));
2887 /* Ask the user for a string */
2888 res = askfor_aux(tmp, sizeof(tmp), get_name_keypress);
2890 /* Clear prompt */
2891 prt("", 0, 0);
2893 if (res)
2895 /* Use the name */
2896 my_strcpy(op_ptr->full_name, tmp, sizeof(op_ptr->full_name));
2898 /* Process the player name */
2899 process_player_name(sf);
2902 return res;
2908 * Prompt for a string from the user.
2910 * The "prompt" should take the form "Prompt: ".
2912 * See "askfor_aux" for some notes about "buf" and "len", and about
2913 * the return value of this function.
2915 bool get_string(cptr prompt, char *buf, size_t len)
2917 bool res;
2919 /* Paranoia XXX XXX XXX */
2920 message_flush();
2922 /* Display prompt */
2923 prt(prompt, 0, 0);
2925 /* Ask the user for a string */
2926 res = askfor_aux(buf, len, NULL);
2928 /* Clear prompt */
2929 prt("", 0, 0);
2931 /* Result */
2932 return (res);
2938 * Request a "quantity" from the user
2940 * Allow "p_ptr->command_arg" to specify a quantity
2942 s16b get_quantity(cptr prompt, int max)
2944 int amt = 1;
2947 /* Use "command_arg" */
2948 if (p_ptr->command_arg)
2950 /* Extract a number */
2951 amt = p_ptr->command_arg;
2953 /* Clear "command_arg" */
2954 p_ptr->command_arg = 0;
2957 /* Get the item index */
2958 else if ((max != 1) && repeat_pull(&amt))
2960 /* nothing */
2963 /* Prompt if needed */
2964 else if ((max != 1))
2966 char tmp[80];
2968 char buf[80];
2970 /* Build a prompt if needed */
2971 if (!prompt)
2973 /* Build a prompt */
2974 strnfmt(tmp, sizeof(tmp), "Quantity (0-%d, *=all): ", max);
2976 /* Use that prompt */
2977 prompt = tmp;
2980 /* Build the default */
2981 strnfmt(buf, sizeof(buf), "%d", amt);
2983 /* Ask for a quantity */
2984 if (!get_string(prompt, buf, 7)) return (0);
2986 /* Extract a number */
2987 amt = atoi(buf);
2989 /* A star or letter means "all" */
2990 if ((buf[0] == '*') || isalpha((unsigned char)buf[0])) amt = max;
2993 /* Enforce the maximum */
2994 if (amt > max) amt = max;
2996 /* Enforce the minimum */
2997 if (amt < 0) amt = 0;
2999 if (amt) repeat_push(amt);
3001 /* Return the result */
3002 return (amt);
3006 * Hack - duplication of get_check prompt to give option of setting destroyed
3007 * option to squelch.
3009 * 0 - No
3010 * 1 = Yes
3011 * 2 = third option
3013 * The "prompt" should take the form "Query? "
3015 * Note that "[y/n/{char}]" is appended to the prompt.
3017 int get_check_other(cptr prompt, char other)
3019 char ch;
3020 char buf[80];
3022 int result;
3024 /* Paranoia XXX XXX XXX */
3025 message_flush();
3027 /* Hack -- Build a "useful" prompt */
3028 strnfmt(buf, 78, "%.70s[y/n/%c] ", prompt, other);
3030 /* Prompt for it */
3031 prt(buf, 0, 0);
3033 /* Get an acceptable answer */
3034 while (TRUE)
3036 ch = inkey();
3037 if (quick_messages) break;
3038 if (ch == ESCAPE) break;
3039 if (strchr("YyNn", ch)) break;
3040 if (ch == toupper((unsigned char) other)) break;
3041 if (ch == tolower((unsigned char) other)) break;
3042 bell("Illegal response to question!");
3045 /* Erase the prompt */
3046 prt("", 0, 0);
3049 /* Yes */
3050 if ((ch == 'Y') || (ch == 'y'))
3051 result = 1;
3053 /* Third option */
3054 else if ((ch == toupper((unsigned char) other)) || (ch == tolower((unsigned char) other)))
3055 result = 2;
3057 /* Default to no */
3058 else
3059 result = 0;
3062 /* Success */
3063 return (result);
3068 * Verify something with the user
3070 * The "prompt" should take the form "Query? "
3072 * Note that "[y/n]" is appended to the prompt.
3074 bool get_check(cptr prompt)
3076 char ch;
3078 char buf[80];
3080 /* Paranoia XXX XXX XXX */
3081 message_flush();
3083 /* Hack -- Build a "useful" prompt */
3084 strnfmt(buf, 78, "%.70s[y/n] ", prompt);
3086 /* Prompt for it */
3087 prt(buf, 0, 0);
3089 /* Get an acceptable answer */
3090 while (TRUE)
3092 ch = inkey();
3093 if (quick_messages) break;
3094 if (ch == ESCAPE) break;
3095 if (strchr("YyNn", ch)) break;
3096 bell("Illegal response to a 'yes/no' question!");
3099 /* Erase the prompt */
3100 prt("", 0, 0);
3102 /* Normal negation */
3103 if ((ch != 'Y') && (ch != 'y')) return (FALSE);
3105 /* Success */
3106 return (TRUE);
3111 * Prompts for a keypress
3113 * The "prompt" should take the form "Command: "
3115 * Returns TRUE unless the character is "Escape"
3117 bool get_com(cptr prompt, char *command)
3119 event_type ke;
3120 bool result;
3122 result = get_com_ex(prompt, &ke);
3123 *command = ke.key;
3125 return result;
3128 bool get_com_ex(cptr prompt, event_type *command)
3130 event_type ke;
3132 /* Paranoia XXX XXX XXX */
3133 message_flush();
3135 /* Display a prompt */
3136 prt(prompt, 0, 0);
3138 /* Get a key */
3139 ke = inkey_ex();
3141 /* Clear the prompt */
3142 prt("", 0, 0);
3144 /* Save the command */
3145 *command = ke;
3147 /* Done */
3148 return (ke.key != ESCAPE);
3153 * Pause for user response
3155 * This function is stupid. XXX XXX XXX
3157 void pause_line(int row)
3159 prt("", row, 0);
3160 put_str("[Press any key to continue]", row, 23);
3161 (void)inkey();
3162 prt("", row, 0);
3169 * Hack -- special buffer to hold the action of the current keymap
3171 static char request_command_buffer[256];
3175 * Request a command from the user.
3177 * Sets p_ptr->command_cmd, p_ptr->command_dir, p_ptr->command_rep,
3178 * p_ptr->command_arg. May modify p_ptr->command_new.
3180 * Note that "caret" ("^") is treated specially, and is used to
3181 * allow manual input of control characters. This can be used
3182 * on many machines to request repeated tunneling (Ctrl-H) and
3183 * on the Macintosh to request "Control-Caret".
3185 * Note that "backslash" is treated specially, and is used to bypass any
3186 * keymap entry for the following character. This is useful for macros.
3188 * Note that this command is used both in the dungeon and in
3189 * stores, and must be careful to work in both situations.
3191 * Note that "p_ptr->command_new" may not work any more. XXX XXX XXX
3193 void request_command(void)
3195 int i;
3197 event_type ke = EVENT_EMPTY;
3199 int mode;
3201 cptr act;
3204 /* Roguelike */
3205 if (rogue_like_commands)
3207 mode = KEYMAP_MODE_ROGUE;
3210 /* Original */
3211 else
3213 mode = KEYMAP_MODE_ORIG;
3217 /* No command yet */
3218 p_ptr->command_cmd = 0;
3220 /* No "argument" yet */
3221 p_ptr->command_arg = 0;
3223 /* No "direction" yet */
3224 p_ptr->command_dir = 0;
3227 /* Get command */
3228 while (1)
3230 /* Hack -- auto-commands */
3231 if (p_ptr->command_new)
3233 /* Flush messages */
3234 message_flush();
3236 /* Use auto-command */
3237 ke.key = (char)p_ptr->command_new;
3238 ke.type = EVT_KBRD;
3240 /* Forget it */
3241 p_ptr->command_new = 0;
3244 /* Get a keypress in "command" mode */
3245 else
3247 /* Hack -- no flush needed */
3248 msg_flag = FALSE;
3250 /* Activate "command mode" */
3251 inkey_flag = TRUE;
3253 /* Get a command */
3254 ke = inkey_ex();
3257 /* Clear top line */
3258 prt("", 0, 0);
3261 /* Resize events XXX XXX */
3262 if (ke.type == EVT_RESIZE)
3264 p_ptr->command_cmd_ex = ke;
3265 p_ptr->command_new = ' ';
3269 /* Command Count */
3270 if (ke.key == '0')
3272 int old_arg = p_ptr->command_arg;
3274 /* Reset */
3275 p_ptr->command_arg = 0;
3277 /* Begin the input */
3278 prt("Count: ", 0, 0);
3280 /* Get a command count */
3281 while (1)
3283 /* Get a new keypress */
3284 ke.key = inkey();
3286 /* Simple editing (delete or backspace) */
3287 if ((ke.key == 0x7F) || (ke.key == KTRL('H')))
3289 /* Delete a digit */
3290 p_ptr->command_arg = p_ptr->command_arg / 10;
3292 /* Show current count */
3293 prt(format("Count: %d", p_ptr->command_arg), 0, 0);
3296 /* Actual numeric data */
3297 else if (isdigit((unsigned char)ke.key))
3299 /* Stop count at 9999 */
3300 if (p_ptr->command_arg >= 1000)
3302 /* Warn */
3303 bell("Invalid repeat count!");
3305 /* Limit */
3306 p_ptr->command_arg = 9999;
3309 /* Increase count */
3310 else
3312 /* Incorporate that digit */
3313 p_ptr->command_arg = p_ptr->command_arg * 10 + D2I(ke.key);
3316 /* Show current count */
3317 prt(format("Count: %d", p_ptr->command_arg), 0, 0);
3320 /* Exit on "unusable" input */
3321 else
3323 break;
3327 /* Hack -- Handle "zero" */
3328 if (p_ptr->command_arg == 0)
3330 /* Default to 99 */
3331 p_ptr->command_arg = 99;
3333 /* Show current count */
3334 prt(format("Count: %d", p_ptr->command_arg), 0, 0);
3337 /* Hack -- Handle "old_arg" */
3338 if (old_arg != 0)
3340 /* Restore old_arg */
3341 p_ptr->command_arg = old_arg;
3343 /* Show current count */
3344 prt(format("Count: %d", p_ptr->command_arg), 0, 0);
3347 /* Hack -- white-space means "enter command now" */
3348 if ((ke.key == ' ') || (ke.key == '\n') || (ke.key == '\r'))
3350 /* Get a real command */
3351 if (!get_com("Command: ", &ke.key))
3353 /* Clear count */
3354 p_ptr->command_arg = 0;
3356 /* Continue */
3357 continue;
3363 /* Special case for the arrow keys */
3364 if (isarrow(ke.key))
3366 switch (ke.key)
3368 case ARROW_DOWN: ke.key = '2'; break;
3369 case ARROW_LEFT: ke.key = '4'; break;
3370 case ARROW_RIGHT: ke.key = '6'; break;
3371 case ARROW_UP: ke.key = '8'; break;
3376 /* Allow "keymaps" to be bypassed */
3377 if (ke.key == '\\')
3379 /* Get a real command */
3380 (void)get_com("Command: ", &ke.key);
3382 /* Hack -- bypass keymaps */
3383 if (!inkey_next) inkey_next = "";
3387 /* Allow "control chars" to be entered */
3388 if (ke.key == '^')
3390 /* Get a new command and controlify it */
3391 if (get_com("Control: ", &ke.key)) ke.key = KTRL(ke.key);
3395 /* Look up applicable keymap */
3396 act = keymap_act[mode][(byte)(ke.key)];
3398 /* Apply keymap if not inside a keymap already */
3399 if (act && !inkey_next)
3401 /* Install the keymap */
3402 my_strcpy(request_command_buffer, act,
3403 sizeof(request_command_buffer));
3405 /* Start using the buffer */
3406 inkey_next = request_command_buffer;
3408 /* Continue */
3409 continue;
3413 /* Paranoia */
3414 if (ke.key == '\0') continue;
3417 /* Use command */
3418 p_ptr->command_cmd = ke.key;
3419 p_ptr->command_cmd_ex = ke;
3421 /* Done */
3422 break;
3425 /* Hack -- Auto-repeat certain commands */
3426 if (p_ptr->command_arg <= 0)
3428 /* Hack -- auto repeat certain commands */
3429 if (strchr(AUTO_REPEAT_COMMANDS, p_ptr->command_cmd))
3431 /* Repeat 99 times */
3432 p_ptr->command_arg = 99;
3437 /* Hack -- Scan equipment */
3438 for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
3440 char verify_inscrip[] = "^*";
3442 object_type *o_ptr = &inventory[i];
3444 /* Skip non-objects */
3445 if (!o_ptr->k_idx) continue;
3447 /* Set up string to look for, e.g. "^d" */
3448 verify_inscrip[1] = p_ptr->command_cmd;
3450 if (check_for_inscrip(o_ptr, "^*") || check_for_inscrip(o_ptr, verify_inscrip))
3452 /* Hack -- Verify command */
3453 if (!get_check("Are you sure? "))
3455 /* Hack -- Use "newline" */
3456 p_ptr->command_cmd = '\n';
3462 /* Hack -- erase the message line. */
3463 prt("", 0, 0);
3465 /* Hack again -- apply the modified key command */
3466 p_ptr->command_cmd_ex.key = p_ptr->command_cmd;
3473 * Generates damage for "2d6" style dice rolls
3475 int damroll(int num, int sides)
3477 int i;
3478 int sum = 0;
3481 /* HACK - prevent undefined behaviour */
3482 if (sides <= 0) return (0);
3484 for (i = 0; i < num; i++)
3486 sum += rand_die(sides);
3489 return (sum);
3494 * Same as above, but always maximal
3496 int maxroll(int num, int sides)
3498 return (num * sides);
3505 * Check a char for "vowel-hood"
3507 bool is_a_vowel(int ch)
3509 switch (ch)
3511 case 'a':
3512 case 'e':
3513 case 'i':
3514 case 'o':
3515 case 'u':
3516 case 'A':
3517 case 'E':
3518 case 'I':
3519 case 'O':
3520 case 'U':
3521 return (TRUE);
3524 return (FALSE);
3529 * Convert a "color letter" into an "actual" color
3530 * The colors are: dwsorgbuDWvyRGBU, as shown below
3532 int color_char_to_attr(char c)
3534 switch (c)
3536 case 'd': return (TERM_DARK);
3537 case 'w': return (TERM_WHITE);
3538 case 's': return (TERM_SLATE);
3539 case 'o': return (TERM_ORANGE);
3540 case 'r': return (TERM_RED);
3541 case 'g': return (TERM_GREEN);
3542 case 'b': return (TERM_BLUE);
3543 case 'u': return (TERM_UMBER);
3545 case 'D': return (TERM_L_DARK);
3546 case 'W': return (TERM_L_WHITE);
3547 case 'v': return (TERM_VIOLET);
3548 case 'y': return (TERM_YELLOW);
3549 case 'R': return (TERM_L_RED);
3550 case 'G': return (TERM_L_GREEN);
3551 case 'B': return (TERM_L_BLUE);
3552 case 'U': return (TERM_L_UMBER);
3555 return (-1);
3560 * Converts a string to a terminal color byte.
3562 int color_text_to_attr(cptr name)
3564 if (my_stricmp(name, "dark") == 0) return (TERM_DARK);
3565 if (my_stricmp(name, "white") == 0) return (TERM_WHITE);
3566 if (my_stricmp(name, "slate") == 0) return (TERM_SLATE);
3567 if (my_stricmp(name, "orange") == 0) return (TERM_ORANGE);
3568 if (my_stricmp(name, "red") == 0) return (TERM_RED);
3569 if (my_stricmp(name, "green") == 0) return (TERM_GREEN);
3570 if (my_stricmp(name, "blue") == 0) return (TERM_BLUE);
3571 if (my_stricmp(name, "umber") == 0) return (TERM_UMBER);
3572 if (my_stricmp(name, "violet") == 0) return (TERM_VIOLET);
3573 if (my_stricmp(name, "yellow") == 0) return (TERM_YELLOW);
3574 if (my_stricmp(name, "lightdark") == 0) return (TERM_L_DARK);
3575 if (my_stricmp(name, "lightwhite") == 0) return (TERM_L_WHITE);
3576 if (my_stricmp(name, "lightred") == 0) return (TERM_L_RED);
3577 if (my_stricmp(name, "lightgreen") == 0) return (TERM_L_GREEN);
3578 if (my_stricmp(name, "lightblue") == 0) return (TERM_L_BLUE);
3579 if (my_stricmp(name, "lightumber") == 0) return (TERM_L_UMBER);
3581 /* Oops */
3582 return (-1);
3587 * Extract a textual representation of an attribute
3589 cptr attr_to_text(byte a)
3591 switch (a)
3593 case TERM_DARK: return ("Dark");
3594 case TERM_WHITE: return ("White");
3595 case TERM_SLATE: return ("Slate");
3596 case TERM_ORANGE: return ("Orange");
3597 case TERM_RED: return ("Red");
3598 case TERM_GREEN: return ("Green");
3599 case TERM_BLUE: return ("Blue");
3600 case TERM_UMBER: return ("Umber");
3601 case TERM_L_DARK: return ("L.Dark");
3602 case TERM_L_WHITE: return ("L.Slate");
3603 case TERM_VIOLET: return ("Violet");
3604 case TERM_YELLOW: return ("Yellow");
3605 case TERM_L_RED: return ("L.Red");
3606 case TERM_L_GREEN: return ("L.Green");
3607 case TERM_L_BLUE: return ("L.Blue");
3608 case TERM_L_UMBER: return ("L.Umber");
3611 /* Oops */
3612 return ("Icky");
3617 #if 0
3620 * Replace the first instance of "target" in "buf" with "insert"
3621 * If "insert" is NULL, just remove the first instance of "target"
3622 * In either case, return TRUE if "target" is found.
3624 * Could be made more efficient, especially in the case where "insert"
3625 * is smaller than "target".
3627 static bool insert_str(char *buf, cptr target, cptr insert)
3629 int i, len;
3630 int b_len, t_len, i_len;
3632 /* Attempt to find the target (modify "buf") */
3633 buf = strstr(buf, target);
3635 /* No target found */
3636 if (!buf) return (FALSE);
3638 /* Be sure we have an insertion string */
3639 if (!insert) insert = "";
3641 /* Extract some lengths */
3642 t_len = strlen(target);
3643 i_len = strlen(insert);
3644 b_len = strlen(buf);
3646 /* How much "movement" do we need? */
3647 len = i_len - t_len;
3649 /* We need less space (for insert) */
3650 if (len < 0)
3652 for (i = t_len; i < b_len; ++i) buf[i+len] = buf[i];
3655 /* We need more space (for insert) */
3656 else if (len > 0)
3658 for (i = b_len-1; i >= t_len; --i) buf[i+len] = buf[i];
3661 /* If movement occured, we need a new terminator */
3662 if (len) buf[b_len+len] = '\0';
3664 /* Now copy the insertion string */
3665 for (i = 0; i < i_len; ++i) buf[i] = insert[i];
3667 /* Successful operation */
3668 return (TRUE);
3672 #endif
3675 #define REPEAT_MAX 20
3677 /* Number of chars saved */
3678 static int repeat__cnt = 0;
3680 /* Current index */
3681 static int repeat__idx = 0;
3683 /* Saved "stuff" */
3684 static int repeat__key[REPEAT_MAX];
3688 * Push data.
3690 void repeat_push(int what)
3692 /* Too many keys */
3693 if (repeat__cnt == REPEAT_MAX) return;
3695 /* Push the "stuff" */
3696 repeat__key[repeat__cnt++] = what;
3698 /* Prevents us from pulling keys */
3699 ++repeat__idx;
3704 * Pull data.
3706 bool repeat_pull(int *what)
3708 /* All out of keys */
3709 if (repeat__idx == repeat__cnt) return (FALSE);
3711 /* Grab the next key, advance */
3712 *what = repeat__key[repeat__idx++];
3714 /* Success */
3715 return (TRUE);
3719 void repeat_clear(void)
3721 /* Start over from the failed pull */
3722 if (repeat__idx)
3723 repeat__cnt = --repeat__idx;
3724 /* Paranoia */
3725 else
3726 repeat__cnt = repeat__idx;
3728 return;
3733 * Repeat previous command, or begin memorizing new command.
3735 void repeat_check(void)
3737 int what;
3739 /* Ignore some commands */
3740 if (p_ptr->command_cmd == ESCAPE) return;
3741 if (p_ptr->command_cmd == ' ') return;
3742 if (p_ptr->command_cmd == '\n') return;
3743 if (p_ptr->command_cmd == '\r') return;
3745 /* Repeat Last Command */
3746 if (p_ptr->command_cmd == KTRL('V'))
3748 /* Reset */
3749 repeat__idx = 0;
3751 /* Get the command */
3752 if (repeat_pull(&what))
3754 /* Save the command */
3755 p_ptr->command_cmd = what;
3759 /* Start saving new command */
3760 else
3762 /* Reset */
3763 repeat__cnt = 0;
3764 repeat__idx = 0;
3766 /* Get the current command */
3767 what = p_ptr->command_cmd;
3769 /* Save this command */
3770 repeat_push(what);
3775 #ifdef SUPPORT_GAMMA
3777 /* Table of gamma values */
3778 byte gamma_table[256];
3780 /* Table of ln(x / 256) * 256 for x going from 0 -> 255 */
3781 static const s16b gamma_helper[256] =
3783 0, -1420, -1242, -1138, -1065, -1007, -961, -921, -887, -857, -830,
3784 -806, -783, -762, -744, -726, -710, -694, -679, -666, -652, -640,
3785 -628, -617, -606, -596, -586, -576, -567, -577, -549, -541, -532,
3786 -525, -517, -509, -502, -495, -488, -482, -475, -469, -463, -457,
3787 -451, -455, -439, -434, -429, -423, -418, -413, -408, -403, -398,
3788 -394, -389, -385, -380, -376, -371, -367, -363, -359, -355, -351,
3789 -347, -343, -339, -336, -332, -328, -325, -321, -318, -314, -311,
3790 -308, -304, -301, -298, -295, -291, -288, -285, -282, -279, -276,
3791 -273, -271, -268, -265, -262, -259, -257, -254, -251, -248, -246,
3792 -243, -241, -238, -236, -233, -231, -228, -226, -223, -221, -219,
3793 -216, -214, -212, -209, -207, -205, -203, -200, -198, -196, -194,
3794 -192, -190, -188, -186, -184, -182, -180, -178, -176, -174, -172,
3795 -170, -168, -166, -164, -162, -160, -158, -156, -155, -153, -151,
3796 -149, -147, -146, -144, -142, -140, -139, -137, -135, -134, -132,
3797 -130, -128, -127, -125, -124, -122, -120, -119, -117, -116, -114,
3798 -112, -111, -109, -108, -106, -105, -103, -102, -100, -99, -97, -96,
3799 -95, -93, -92, -90, -89, -87, -86, -85, -83, -82, -80, -79, -78,
3800 -76, -75, -74, -72, -71, -70, -68, -67, -66, -65, -63, -62, -61,
3801 -59, -58, -57, -56, -54, -53, -52, -51, -50, -48, -47, -46, -45,
3802 -44, -42, -41, -40, -39, -38, -37, -35, -34, -33, -32, -31, -30,
3803 -29, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16,
3804 -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1
3809 * Build the gamma table so that floating point isn't needed.
3811 * Note gamma goes from 0->256. The old value of 100 is now 128.
3813 void build_gamma_table(int gamma)
3815 int i, n;
3818 * value is the current sum.
3819 * diff is the new term to add to the series.
3821 long value, diff;
3823 /* Hack - convergence is bad in these cases. */
3824 gamma_table[0] = 0;
3825 gamma_table[255] = 255;
3827 for (i = 1; i < 255; i++)
3830 * Initialise the Taylor series
3832 * value and diff have been scaled by 256
3834 n = 1;
3835 value = 256L * 256L;
3836 diff = ((long)gamma_helper[i]) * (gamma - 256);
3838 while (diff)
3840 value += diff;
3841 n++;
3844 * Use the following identiy to calculate the gamma table.
3845 * exp(x) = 1 + x + x^2/2 + x^3/(2*3) + x^4/(2*3*4) +...
3847 * n is the current term number.
3849 * The gamma_helper array contains a table of
3850 * ln(x/256) * 256
3851 * This is used because a^b = exp(b*ln(a))
3853 * In this case:
3854 * a is i / 256
3855 * b is gamma.
3857 * Note that everything is scaled by 256 for accuracy,
3858 * plus another factor of 256 for the final result to
3859 * be from 0-255. Thus gamma_helper[] * gamma must be
3860 * divided by 256*256 each itteration, to get back to
3861 * the original power series.
3863 diff = (((diff / 256) * gamma_helper[i]) * (gamma - 256)) / (256 * n);
3867 * Store the value in the table so that the
3868 * floating point pow function isn't needed.
3870 gamma_table[i] = ((long)(value / 256) * i) / 256;
3874 #endif /* SUPPORT_GAMMA */