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.
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);
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
)
44 bool mod_status
[MAX_MACRO_MOD
];
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
;
61 /* Examine modifier keys */
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
))
74 if (!macro_modifier_chr
[i
]) break;
79 /* This modifier key is pressed */
82 /* Shift key might be going to change keycode */
83 if ('S' == macro_modifier_chr
[i
])
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
]))
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
, ']');
108 strnfcat(buf
, max
, ¤t_len
, "\x1F\r");
110 *strptr
= str
; /* where **strptr == ']' */
116 /* Get keycode for this trigger name */
117 key_code
= macro_trigger_keycode
[shiftstatus
][i
];
122 /* Begin with '^_' */
123 strnfcat(buf
, max
, ¤t_len
, "\x1F");
125 /* Write key code style trigger using template */
126 for (i
= 0; macro_template
[i
]; i
++)
128 char ch
= macro_template
[i
];
134 /* Modifier key character */
135 for (j
= 0; macro_modifier_chr
[j
]; j
++)
138 strnfcat(buf
, max
, ¤t_len
, "%c", macro_modifier_chr
[j
]);
143 strnfcat(buf
, max
, ¤t_len
, "%s", key_code
);
147 strnfcat(buf
, max
, ¤t_len
, "%c", ch
);
153 strnfcat(buf
, max
, ¤t_len
, "\r");
156 *strptr
= str
; /* where **strptr == ']' */
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
)
173 /* Analyze the "ascii" string */
176 /* Check if the buffer is long enough */
177 if (s
>= buf
+ len
- 1) break;
179 /* Backslash codes */
182 /* Skip the backslash */
191 /* Terminate before appending the trigger */
194 s
+= trigger_text_to_ascii(buf
, len
, &str
);
197 /* Hack -- simple way to specify Escape */
198 else if (*str
== 'e')
203 /* Hack -- simple way to specify "space" */
204 else if (*str
== 's')
210 else if (*str
== 'b')
216 else if (*str
== 'n')
222 else if (*str
== 'r')
228 else if (*str
== 't')
234 else if (*str
== 'a')
239 /* Actual "backslash" */
240 else if (*str
== '\\')
245 /* Hack -- Actual "caret" */
246 else if (*str
== '^')
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
);
262 /* HACK - Invalid hex number */
273 /* Skip the final char */
277 /* Normal Control codes */
278 else if (*str
== '^')
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
)
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
, ¤t_len
, "\\[");
320 /* Use template to read key-code style trigger */
321 for (i
= 0; macro_template
[i
]; i
++)
324 char ch
= macro_template
[i
];
330 while ((tmp
= strchr(macro_modifier_chr
, *str
)))
332 j
= (int)(tmp
- macro_modifier_chr
);
333 strnfcat(buf
, max
, ¤t_len
, "%s", macro_modifier_name
[j
]);
339 for (j
= 0; *str
&& (*str
!= '\r') && (j
< (int)sizeof(key_code
) - 1); j
++)
340 key_code
[j
] = *str
++;
344 /* Skip fixed strings */
345 if (ch
!= *str
) return 0;
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
]))
362 if (i
== max_macrotrigger
) return 0;
364 /* Write trigger name + "]" */
365 strnfcat(buf
, max
, ¤t_len
, "%s]", macro_trigger_name
[i
]);
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
)
382 /* Analyze the "ascii" string */
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;
441 /* Terminate before appending the trigger */
444 offset
= trigger_ascii_to_text(buf
, len
, &str
);
448 /* No trigger found */
468 *s
++ = hexify((int)i
/ 16);
469 *s
++ = hexify((int)i
% 16);
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
)
502 /* Nothing possible */
503 if (!macro__use
[(byte
)(pat
[0])])
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;
524 * Find the first macro (if any) which contains the given pattern
526 static int macro_find_check(cptr pat
)
530 /* Nothing possible */
531 if (!macro__use
[(byte
)(pat
[0])])
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;
553 * Find the first macro (if any) which contains the given pattern and more
555 static int macro_find_maybe(cptr pat
)
559 /* Nothing possible */
560 if (!macro__use
[(byte
)(pat
[0])])
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;
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])])
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 */
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
)
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 */
647 /* Free the old macro action */
648 string_free(macro__act
[n
]);
651 /* Create a new macro */
654 /* Get a new index */
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
);
668 macro__use
[(byte
)(pat
[0])] = TRUE
;
677 * Initialize the "macro" package
679 errr
macro_init(void)
682 C_MAKE(macro__pat
, MACRO_MAX
, cptr
);
685 C_MAKE(macro__act
, MACRO_MAX
, cptr
);
693 * Free the macro package
695 errr
macro_free(void)
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
;
725 * Free the macro trigger package
727 errr
macro_trigger_free(void)
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
;
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.
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;
837 /* Initialize the no return */
840 ke0
.index
= 0; /* To fix GCC warnings on X11 */
844 /* Wait for a keypress */
845 (void)(Term_inkey(&ke
, TRUE
, TRUE
));
848 /* End "macro action" */
849 if ((ch
== 30) || (ch
== '\xff'))
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 */
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 */
877 /* Check for pending macro */
878 k
= macro_find_maybe(buf
);
880 /* No macro pending */
883 /* Check for (and remove) a pending key */
884 if (0 == Term_inkey(&ke
, FALSE
, TRUE
))
897 /* Increase "wait" */
900 /* Excessive delay */
904 Term_xtra(TERM_XTRA_DELAY
, w
);
909 /* Check for available macro */
910 k
= macro_find_ready(buf
);
912 /* No macro available */
915 /* Push all the "keys" back on the queue */
916 /* The most recent event may not be a keypress. */
919 if(Term_event_push(&ke
)) return (ke0
);
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
);
936 /* Get the pattern */
939 /* Get the length of the pattern */
942 /* Push the "extra" keys back on the queue */
945 /* Push the key, notice over-flow */
946 if (Term_key_push(buf
[--p
])) return (ke0
);
950 /* Begin "macro action" */
953 /* Push the "end of macro action" key */
954 if (Term_key_push(30)) return (ke0
);
957 /* Access the macro action */
960 /* Get the length of the action */
963 /* Push the macro "action" onto the key queue */
966 /* Push the key, notice over-flow */
967 if (Term_key_push(act
[--n
])) return (ke0
);
971 /* Hack -- Force "inkey()" to call us again */
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
;
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)
1074 /* Initialise keypress */
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
;
1091 /* Forget pointer */
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
;
1108 #endif /* ALLOW_BORG */
1111 /* Hack -- handle delayed "flush()" */
1114 /* End "macro action" */
1115 parse_macro
= FALSE
;
1118 /* End "macro trigger" */
1119 parse_under
= FALSE
;
1121 /* Forget old keypresses */
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
);
1144 /* Hack -- Handle "inkey_scan" */
1145 if (!inkey_base
&& inkey_scan
&&
1146 (0 != Term_inkey(&kk
, FALSE
, FALSE
)))
1152 /* Hack -- Flush output once when no key ready */
1153 if (!done
&& (0 != Term_inkey(&kk
, FALSE
, FALSE
)))
1156 /* Hack -- activate proper term */
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 */
1176 /* Hack -- Handle "inkey_base" */
1184 /* Wait for (and remove) a pending key */
1185 if (0 == Term_inkey(&ke
, TRUE
, TRUE
))
1195 /* Wait only as long as macro activation would wait*/
1198 /* Check for (and remove) a pending key */
1199 if (0 == Term_inkey(&ke
, FALSE
, TRUE
))
1208 /* Increase "wait" */
1211 /* Excessive delay */
1212 if (w
>= 100) break;
1215 Term_xtra(TERM_XTRA_DELAY
, w
);
1226 /* Get a key (see above) */
1230 /* Handle "control-right-bracket" */
1233 /* Strip this key */
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 */
1251 /* End "macro trigger" */
1252 parse_under
= FALSE
;
1255 /* Handle "control-caret" */
1258 /* Strip this key */
1262 /* Handle "control-underscore" */
1263 else if (ke
.key
== 31)
1265 /* Strip this key */
1268 /* Begin "macro trigger" */
1272 /* Inside "macro trigger" */
1273 else if (parse_under
)
1275 /* Strip this key */
1281 /* Hack -- restore the term */
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 */
1299 * Get a keypress or mouse click from the user.
1303 event_type ke
= EVENT_EMPTY
;
1305 /* Only accept a keypress or mouse click*/
1309 } while (!(ke
.type
& (EVT_MOUSE
|EVT_KBRD
)));
1315 * Get a "keypress" from the user.
1321 /* Only accept a keypress */
1325 } while (!(ke
.type
& (EVT_KBRD
|EVT_ESCAPE
)));
1327 if(ke
.type
== EVT_ESCAPE
) ke
.key
= ESCAPE
;
1335 * Flush the screen, make a noise
1337 void bell(cptr reason
)
1339 /* Mega-Hack -- Flush the output */
1342 /* Hack -- memorize the reason if possible */
1343 if (character_generated
&& reason
)
1345 message_add(reason
, MSG_BELL
);
1348 p_ptr
->window
|= (PW_MESSAGE
);
1350 /* Force window redraw */
1354 /* Make a bell noise (if allowed) */
1355 if (ring_bell
) Term_xtra(TERM_XTRA_NOISE
, 0);
1357 /* Flush the input (later!) */
1364 * Hack -- Make a (relevant?) sound
1369 if (!use_sound
) return;
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
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
)
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);
1433 /* Add a new quark */
1434 quark__str
[i
] = string_make(str
);
1436 /* Return the index */
1442 * This function looks up a quark
1444 cptr
quark_str(s16b i
)
1449 if ((i
< 0) || (i
>= quark__num
)) i
= 0;
1454 /* Return the quark */
1460 * Initialize the "quark" package
1462 errr
quarks_init(void)
1464 /* Quark variables */
1465 C_MAKE(quark__str
, QUARK_MAX
, cptr
);
1473 * Free the "quark" package
1475 errr
quarks_free(void)
1479 /* Free the "quarks" */
1480 for (i
= 1; i
< quark__num
; i
++)
1482 string_free(quark__str
[i
]);
1485 /* Free the list of "quarks" */
1493 * Looks if "inscrip" is present on the given object.
1495 bool check_for_inscrip(const object_type
*o_ptr
, const char *inscrip
)
1499 const char *s
= strstr(quark_str(o_ptr
->note
), inscrip
);
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];
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
]);
1643 /* Return the message text */
1649 * Recall the "type" of a saved message
1651 u16b
message_type(s16b age
)
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
;
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
;
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
)
1726 /*** Step 1 -- Analyze the message ***/
1728 /* Hack -- Ignore "non-messages" */
1731 /* Message length */
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? */
1752 /* Increase the message count */
1753 message__count
[x
]++;
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 */
1767 /* Start just after the most recent message */
1770 /* Check the last few messages for duplication */
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;
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 */
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;
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;
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;
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;
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 */
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
++;
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
;
1947 * Free the "message" package
1949 void messages_free(void)
1951 /* Free the messages */
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.
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-");
2019 /* Get an acceptable keypress */
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
)
2073 /* Obtain the size */
2074 (void)Term_get_size(&w
, &h
);
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))))
2086 msg_flush(message_column
);
2100 if (n
> 1000) return;
2103 /* Memorize the message (if legal) */
2104 if (character_generated
&& !(p_ptr
->is_dead
))
2105 message_add(msg
, type
);
2108 p_ptr
->window
|= (PW_MESSAGE
);
2111 my_strcpy(buf
, msg
, sizeof(buf
));
2113 /* Analyze the buffer */
2116 /* Get the color of the message */
2117 color
= message_type_color(type
);
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 */
2139 /* Split the message */
2142 /* Display part of the message */
2143 Term_putstr(0, 0, split
, color
, t
);
2146 msg_flush(split
+ 1);
2148 /* Restore the split character */
2151 /* Insert a space */
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 */
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
, ...)
2187 /* Begin the Varargs Stuff */
2190 /* Format the args, save the length */
2191 (void)vstrnfmt(buf
, sizeof(buf
), fmt
, vp
);
2193 /* End the Varargs Stuff */
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 */
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
, ...)
2229 /* Begin the Varargs Stuff */
2232 /* Format the args, save the length */
2233 (void)vstrnfmt(buf
, sizeof(buf
), fmt
, vp
);
2235 /* End the Varargs Stuff */
2239 message(message_type
, extra
, buf
);
2244 * Print the queued messages.
2246 void message_flush(void)
2249 if (!msg_flag
) message_column
= 0;
2251 /* Flush when needed */
2254 /* Print pending messages */
2255 msg_flush(message_column
);
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 */
2277 /* Save the screen (if legal) */
2280 /* Increase "icky" depth */
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 */
2295 /* Load the screen (if legal) */
2298 /* Decrease "icky" depth */
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
)
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
)
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
)
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
;
2388 /* Process the string */
2389 for (s
= str
; *s
; s
++)
2397 x
= text_out_indent
;
2400 /* Clear line, move cursor */
2401 Term_erase(x
, y
, 255);
2406 /* Clean up the char */
2407 ch
= (isprint((unsigned char)*s
) ? *s
: ' ');
2409 /* Wrap words as needed */
2410 if ((x
>= wrap
- 1) && (ch
!= ' '))
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 */
2435 if (n
== 0) n
= wrap
;
2438 Term_erase(n
, y
, 255);
2441 x
= text_out_indent
;
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
++)
2451 Term_addch(av
[i
], cv
[i
]);
2453 /* Advance (no wrap) */
2454 if (++x
> wrap
) x
= wrap
;
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 */
2486 int wrap
= (text_out_wrap
? text_out_wrap
: 75);
2488 /* Current location within "str" */
2491 /* Unused parameter */
2494 /* Process the string */
2499 int len
= wrap
- pos
;
2502 /* If we are at the start of the line... */
2507 /* Output the indent */
2508 for (i
= 0; i
< text_out_indent
; i
++)
2510 fputc(' ', text_out_file
);
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
;
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
)
2533 /* HACK - Output punctuation at the end of the line */
2534 else if ((s
[0] == ' ') || (s
[0] == ',') || (s
[0] == '.'))
2540 /* Begin a new line */
2541 fputc('\n', text_out_file
);
2551 /* Wrap at the newline */
2552 if ((s
[n
] == '\n') || (s
[n
] == '\0')) len
= n
;
2554 /* Wrap at the last 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
);
2571 /* Move 's' past the stuff we've written */
2574 /* If we are at the end of the string, end */
2575 if (*s
== '\0') return;
2578 if (*s
== '\n') s
++;
2580 /* Begin a new line */
2581 fputc('\n', text_out_file
);
2586 /* Skip whitespace */
2587 while (*s
== ' ') s
++;
2596 * Output text to the screen or to a file depending on the selected
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
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
)
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
)
2659 if (firsttime
) *curs
= 0;
2660 if (*curs
> 0) (*curs
)--;
2666 if (firsttime
) *curs
= *len
- 1;
2667 if (*curs
< *len
) (*curs
)++;
2674 /* If this is the first time round, backspace means "delete all" */
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
);
2702 bool atnull
= (buf
[*curs
] == 0);
2705 if (!isprint((unsigned char)keypress
))
2707 bell("Illegal edit key!");
2711 /* Clear the buffer if this is the first time round */
2722 /* Make sure we have enough room for a new character */
2723 if ((*curs
+ 1) >= buflen
) break;
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
;
2745 /* By default, we aren't done. */
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))
2776 size_t k
= 0; /* Cursor position */
2777 size_t nul
= 0; /* Position of the null byte in the string */
2782 bool firsttime
= TRUE
;
2784 if (keypress_h
== NULL
)
2786 keypress_h
= askfor_aux_keypress
;
2789 /* Locate the cursor */
2790 Term_locate(&x
, &y
);
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 */
2803 /* Get the position of the null byte */
2806 /* Display the default answer */
2807 Term_erase(x
, y
, (int)len
);
2808 Term_putstr(x
, y
, -1, TERM_YELLOW
, buf
);
2814 Term_gotoxy(x
+ k
, y
);
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 */
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
)
2847 *len
= randname_make(RANDNAME_TOLKIEN
, 4, 8, buf
, buflen
);
2848 buf
[0] = toupper((unsigned char) buf
[0]);
2857 result
= askfor_aux_keypress(buf
, buflen
, curs
, len
, keypress
, firsttime
);
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
)
2878 /* Paranoia XXX XXX XXX */
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
);
2896 my_strcpy(op_ptr
->full_name
, tmp
, sizeof(op_ptr
->full_name
));
2898 /* Process the player name */
2899 process_player_name(sf
);
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
)
2919 /* Paranoia XXX XXX XXX */
2922 /* Display prompt */
2925 /* Ask the user for a string */
2926 res
= askfor_aux(buf
, len
, NULL
);
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
)
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
))
2963 /* Prompt if needed */
2964 else if ((max
!= 1))
2970 /* Build a prompt if needed */
2973 /* Build a prompt */
2974 strnfmt(tmp
, sizeof(tmp
), "Quantity (0-%d, *=all): ", max
);
2976 /* Use that prompt */
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 */
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 */
3006 * Hack - duplication of get_check prompt to give option of setting destroyed
3007 * option to squelch.
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
)
3024 /* Paranoia XXX XXX XXX */
3027 /* Hack -- Build a "useful" prompt */
3028 strnfmt(buf
, 78, "%.70s[y/n/%c] ", prompt
, other
);
3033 /* Get an acceptable answer */
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 */
3050 if ((ch
== 'Y') || (ch
== 'y'))
3054 else if ((ch
== toupper((unsigned char) other
)) || (ch
== tolower((unsigned char) other
)))
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
)
3080 /* Paranoia XXX XXX XXX */
3083 /* Hack -- Build a "useful" prompt */
3084 strnfmt(buf
, 78, "%.70s[y/n] ", prompt
);
3089 /* Get an acceptable answer */
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 */
3102 /* Normal negation */
3103 if ((ch
!= 'Y') && (ch
!= 'y')) return (FALSE
);
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
)
3122 result
= get_com_ex(prompt
, &ke
);
3128 bool get_com_ex(cptr prompt
, event_type
*command
)
3132 /* Paranoia XXX XXX XXX */
3135 /* Display a prompt */
3141 /* Clear the prompt */
3144 /* Save the command */
3148 return (ke
.key
!= ESCAPE
);
3153 * Pause for user response
3155 * This function is stupid. XXX XXX XXX
3157 void pause_line(int row
)
3160 put_str("[Press any key to continue]", row
, 23);
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)
3197 event_type ke
= EVENT_EMPTY
;
3205 if (rogue_like_commands
)
3207 mode
= KEYMAP_MODE_ROGUE
;
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;
3230 /* Hack -- auto-commands */
3231 if (p_ptr
->command_new
)
3233 /* Flush messages */
3236 /* Use auto-command */
3237 ke
.key
= (char)p_ptr
->command_new
;
3241 p_ptr
->command_new
= 0;
3244 /* Get a keypress in "command" mode */
3247 /* Hack -- no flush needed */
3250 /* Activate "command mode" */
3257 /* Clear top line */
3261 /* Resize events XXX XXX */
3262 if (ke
.type
== EVT_RESIZE
)
3264 p_ptr
->command_cmd_ex
= ke
;
3265 p_ptr
->command_new
= ' ';
3272 int old_arg
= p_ptr
->command_arg
;
3275 p_ptr
->command_arg
= 0;
3277 /* Begin the input */
3278 prt("Count: ", 0, 0);
3280 /* Get a command count */
3283 /* Get a new keypress */
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)
3303 bell("Invalid repeat count!");
3306 p_ptr
->command_arg
= 9999;
3309 /* Increase count */
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 */
3327 /* Hack -- Handle "zero" */
3328 if (p_ptr
->command_arg
== 0)
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" */
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
))
3354 p_ptr
->command_arg
= 0;
3363 /* Special case for the arrow keys */
3364 if (isarrow(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 */
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 */
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
;
3414 if (ke
.key
== '\0') continue;
3418 p_ptr
->command_cmd
= ke
.key
;
3419 p_ptr
->command_cmd_ex
= ke
;
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. */
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
)
3481 /* HACK - prevent undefined behaviour */
3482 if (sides
<= 0) return (0);
3484 for (i
= 0; i
< num
; i
++)
3486 sum
+= rand_die(sides
);
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
)
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
)
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
);
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
);
3587 * Extract a textual representation of an attribute
3589 cptr
attr_to_text(byte 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");
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
)
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) */
3652 for (i
= t_len
; i
< b_len
; ++i
) buf
[i
+len
] = buf
[i
];
3655 /* We need more space (for insert) */
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 */
3675 #define REPEAT_MAX 20
3677 /* Number of chars saved */
3678 static int repeat__cnt
= 0;
3681 static int repeat__idx
= 0;
3684 static int repeat__key
[REPEAT_MAX
];
3690 void repeat_push(int what
)
3693 if (repeat__cnt
== REPEAT_MAX
) return;
3695 /* Push the "stuff" */
3696 repeat__key
[repeat__cnt
++] = what
;
3698 /* Prevents us from pulling keys */
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
++];
3719 void repeat_clear(void)
3721 /* Start over from the failed pull */
3723 repeat__cnt
= --repeat__idx
;
3726 repeat__cnt
= repeat__idx
;
3733 * Repeat previous command, or begin memorizing new command.
3735 void repeat_check(void)
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'))
3751 /* Get the command */
3752 if (repeat_pull(&what
))
3754 /* Save the command */
3755 p_ptr
->command_cmd
= what
;
3759 /* Start saving new command */
3766 /* Get the current command */
3767 what
= p_ptr
->command_cmd
;
3769 /* Save this command */
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
)
3818 * value is the current sum.
3819 * diff is the new term to add to the series.
3823 /* Hack - convergence is bad in these cases. */
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
3835 value
= 256L * 256L;
3836 diff
= ((long)gamma_helper
[i
]) * (gamma
- 256);
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
3851 * This is used because a^b = exp(b*ln(a))
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 */