OSDN Git Service

Initial revision
[hengband/hengband.git] / src / util.c
1 /* File: util.c */
2
3 /* Purpose: Angband utilities -BEN- */
4
5
6 #include "angband.h"
7
8
9
10
11 static int num_more = 0;
12
13 #ifndef HAS_MEMSET
14
15 /*
16  * For those systems that don't have "memset()"
17  *
18  * Set the value of each of 'n' bytes starting at 's' to 'c', return 's'
19  * If 'n' is negative, you will erase a whole lot of memory.
20  */
21 char *memset(char *s, int c, huge n)
22 {
23         char *t;
24         for (t = s; len--; ) *t++ = c;
25         return (s);
26 }
27
28 #endif
29
30
31 #if 0
32 #ifndef HAS_STRICMP
33
34 /*
35  * For those systems that don't have "stricmp()"
36  *
37  * Compare the two strings "a" and "b" ala "strcmp()" ignoring case.
38  */
39 int stricmp(cptr a, cptr b)
40 {
41         cptr s1, s2;
42         char z1, z2;
43
44         /* Scan the strings */
45         for (s1 = a, s2 = b; TRUE; s1++, s2++)
46         {
47                 z1 = FORCEUPPER(*s1);
48                 z2 = FORCEUPPER(*s2);
49                 if (z1 < z2) return (-1);
50                 if (z1 > z2) return (1);
51                 if (!z1) return (0);
52         }
53 }
54
55 #endif /* HAS_STRICMP */
56 #endif /* 0 */
57
58 #ifdef SET_UID
59
60 # ifndef HAS_USLEEP
61
62 /*
63  * For those systems that don't have "usleep()" but need it.
64  *
65  * Fake "usleep()" function grabbed from the inl netrek server -cba
66  */
67 int usleep(huge usecs)
68 {
69         struct timeval      Timer;
70
71         int                 nfds = 0;
72
73 #ifdef FD_SET
74         fd_set          *no_fds = NULL;
75 #else
76         int                     *no_fds = NULL;
77 #endif
78
79
80         /* Was: int readfds, writefds, exceptfds; */
81         /* Was: readfds = writefds = exceptfds = 0; */
82
83
84         /* Paranoia -- No excessive sleeping */
85 #ifdef JP
86         if (usecs > 4000000L) core("ÉÔÅö¤Ê usleep() ¸Æ¤Ó½Ð¤·");
87 #else
88         if (usecs > 4000000L) core("Illegal usleep() call");
89 #endif
90
91
92
93         /* Wait for it */
94         Timer.tv_sec = (usecs / 1000000L);
95         Timer.tv_usec = (usecs % 1000000L);
96
97         /* Wait for it */
98         if (select(nfds, no_fds, no_fds, no_fds, &Timer) < 0)
99         {
100                 /* Hack -- ignore interrupts */
101                 if (errno != EINTR) return -1;
102         }
103
104         /* Success */
105         return 0;
106 }
107
108 # endif
109
110
111 /*
112 * Hack -- External functions
113 */
114 extern struct passwd *getpwuid();
115 extern struct passwd *getpwnam();
116
117
118 /*
119  * Find a default user name from the system.
120  */
121 void user_name(char *buf, int id)
122 {
123 #ifdef SET_UID
124         struct passwd *pw;
125
126         /* Look up the user name */
127         if ((pw = getpwuid(id)))
128         {
129                 (void)strcpy(buf, pw->pw_name);
130                 buf[16] = '\0';
131
132 #ifdef CAPITALIZE_USER_NAME
133                 /* Hack -- capitalize the user name */
134                 if (islower(buf[0])) buf[0] = toupper(buf[0]);
135 #endif /* CAPITALIZE_USER_NAME */
136
137                 return;
138         }
139 #endif /* SET_UID */
140
141         /* Oops.  Hack -- default to "PLAYER" */
142         strcpy(buf, "PLAYER");
143 }
144
145 #endif /* SET_UID */
146
147
148
149
150 /*
151  * The concept of the "file" routines below (and elsewhere) is that all
152  * file handling should be done using as few routines as possible, since
153  * every machine is slightly different, but these routines always have the
154  * same semantics.
155  *
156  * In fact, perhaps we should use the "path_parse()" routine below to convert
157  * from "canonical" filenames (optional leading tilde's, internal wildcards,
158  * slash as the path seperator, etc) to "system" filenames (no special symbols,
159  * system-specific path seperator, etc).  This would allow the program itself
160  * to assume that all filenames are "Unix" filenames, and explicitly "extract"
161  * such filenames if needed (by "path_parse()", or perhaps "path_canon()").
162  *
163  * Note that "path_temp" should probably return a "canonical" filename.
164  *
165  * Note that "my_fopen()" and "my_open()" and "my_make()" and "my_kill()"
166  * and "my_move()" and "my_copy()" should all take "canonical" filenames.
167  *
168  * Note that "canonical" filenames use a leading "slash" to indicate an absolute
169  * path, and a leading "tilde" to indicate a special directory, and default to a
170  * relative path, but MSDOS uses a leading "drivename plus colon" to indicate the
171  * use of a "special drive", and then the rest of the path is parsed "normally",
172  * and MACINTOSH uses a leading colon to indicate a relative path, and an embedded
173  * colon to indicate a "drive plus absolute path", and finally defaults to a file
174  * in the current working directory, which may or may not be defined.
175  *
176  * We should probably parse a leading "~~/" as referring to "ANGBAND_DIR". (?)
177  */
178
179
180 #ifdef ACORN
181
182
183 /*
184  * Most of the "file" routines for "ACORN" should be in "main-acn.c"
185  */
186
187
188 #else /* ACORN */
189
190
191 #ifdef SET_UID
192
193 /*
194  * Extract a "parsed" path from an initial filename
195  * Normally, we simply copy the filename into the buffer
196  * But leading tilde symbols must be handled in a special way
197  * Replace "~user/" by the home directory of the user named "user"
198  * Replace "~/" by the home directory of the current user
199  */
200 errr path_parse(char *buf, int max, cptr file)
201 {
202         cptr            u, s;
203         struct passwd   *pw;
204         char            user[128];
205
206
207         /* Assume no result */
208         buf[0] = '\0';
209
210         /* No file? */
211         if (!file) return (-1);
212
213         /* File needs no parsing */
214         if (file[0] != '~')
215         {
216                 strcpy(buf, file);
217                 return (0);
218         }
219
220         /* Point at the user */
221         u = file+1;
222
223         /* Look for non-user portion of the file */
224         s = strstr(u, PATH_SEP);
225
226         /* Hack -- no long user names */
227         if (s && (s >= u + sizeof(user))) return (1);
228
229         /* Extract a user name */
230         if (s)
231         {
232                 int i;
233                 for (i = 0; u < s; ++i) user[i] = *u++;
234                 user[i] = '\0';
235                 u = user;
236         }
237
238         /* Look up the "current" user */
239         if (u[0] == '\0') u = getlogin();
240
241         /* Look up a user (or "current" user) */
242         if (u) pw = getpwnam(u);
243         else pw = getpwuid(getuid());
244
245         /* Nothing found? */
246         if (!pw) return (1);
247
248         /* Make use of the info */
249         (void)strcpy(buf, pw->pw_dir);
250
251         /* Append the rest of the filename, if any */
252         if (s) (void)strcat(buf, s);
253
254         /* Success */
255         return (0);
256 }
257
258
259 #else /* SET_UID */
260
261
262 /*
263  * Extract a "parsed" path from an initial filename
264  *
265  * This requires no special processing on simple machines,
266  * except for verifying the size of the filename.
267  */
268 errr path_parse(char *buf, int max, cptr file)
269 {
270         /* Accept the filename */
271         (void)strnfmt(buf, max, "%s", file);
272
273         /* Success */
274         return (0);
275 }
276
277
278 #endif /* SET_UID */
279
280
281 #ifndef HAVE_MKSTEMP
282
283 /*
284  * Hack -- acquire a "temporary" file name if possible
285  *
286  * This filename is always in "system-specific" form.
287  */
288 static errr path_temp(char *buf, int max)
289 {
290         cptr s;
291
292         /* Temp file */
293         s = tmpnam(NULL);
294
295         /* Oops */
296         if (!s) return (-1);
297
298         /* Format to length */
299         (void)strnfmt(buf, max, "%s", s);
300
301         /* Success */
302         return (0);
303 }
304
305 #endif
306
307 /*
308  * Create a new path by appending a file (or directory) to a path.
309  *
310  * This requires no special processing on simple machines, except
311  * for verifying the size of the filename, but note the ability to
312  * bypass the given "path" with certain special file-names.
313  *
314  * Note that the "file" may actually be a "sub-path", including
315  * a path and a file.
316  *
317  * Note that this function yields a path which must be "parsed"
318  * using the "parse" function above.
319  */
320 errr path_build(char *buf, int max, cptr path, cptr file)
321 {
322         /* Special file */
323         if (file[0] == '~')
324         {
325                 /* Use the file itself */
326                 (void)strnfmt(buf, max, "%s", file);
327         }
328
329         /* Absolute file, on "normal" systems */
330         else if (prefix(file, PATH_SEP) && !streq(PATH_SEP, ""))
331         {
332                 /* Use the file itself */
333                 (void)strnfmt(buf, max, "%s", file);
334         }
335
336         /* No path given */
337         else if (!path[0])
338         {
339                 /* Use the file itself */
340                 (void)strnfmt(buf, max, "%s", file);
341         }
342
343         /* Path and File */
344         else
345         {
346                 /* Build the new path */
347                 (void)strnfmt(buf, max, "%s%s%s", path, PATH_SEP, file);
348         }
349
350         /* Success */
351         return (0);
352 }
353
354
355 /*
356  * Hack -- replacement for "fopen()"
357  */
358 FILE *my_fopen(cptr file, cptr mode)
359 {
360         char buf[1024];
361
362         /* Hack -- Try to parse the path */
363         if (path_parse(buf, 1024, file)) return (NULL);
364
365         /* Attempt to fopen the file anyway */
366         return (fopen(buf, mode));
367 }
368
369
370 /*
371  * Hack -- replacement for "fclose()"
372  */
373 errr my_fclose(FILE *fff)
374 {
375         /* Require a file */
376         if (!fff) return (-1);
377
378         /* Close, check for error */
379         if (fclose(fff) == EOF) return (1);
380
381         /* Success */
382         return (0);
383 }
384
385
386 #endif /* ACORN */
387
388
389 #ifdef HAVE_MKSTEMP
390
391 FILE *my_fopen_temp(char *buf, int max)
392 {
393         int fd;
394
395         /* Prepare the buffer for mkstemp */
396         strncpy(buf, "/tmp/anXXXXXX", max);
397
398         /* Secure creation of a temporary file */
399         fd = mkstemp(buf);
400
401         /* Check the file-descriptor */
402         if (fd < 0) return (NULL);
403
404         /* Return a file stream */
405         return (fdopen(fd, "w"));
406 }
407
408 #else /* HAVE_MKSTEMP */
409
410 FILE *my_fopen_temp(char *buf, int max)
411 {
412         /* Generate a temporary filename */
413         if (path_temp(buf, max)) return (NULL);
414
415         /* Open the file */
416         return (my_fopen(buf, "w"));
417 }
418
419 #endif /* HAVE_MKSTEMP */
420
421
422 /*
423  * Hack -- replacement for "fgets()"
424  *
425  * Read a string, without a newline, to a file
426  *
427  * Process tabs, strip internal non-printables
428  */
429 errr my_fgets(FILE *fff, char *buf, huge n)
430 {
431         huge i = 0;
432
433         char *s;
434
435         char tmp[1024];
436
437         /* Read a line */
438         if (fgets(tmp, 1024, fff))
439         {
440                 /* Convert weirdness */
441                 for (s = tmp; *s; s++)
442                 {
443                         /* Handle newline */
444                         if (*s == '\n')
445                         {
446                                 /* Terminate */
447                                 buf[i] = '\0';
448
449                                 /* Success */
450                                 return (0);
451                         }
452
453                         /* Handle tabs */
454                         else if (*s == '\t')
455                         {
456                                 /* Hack -- require room */
457                                 if (i + 8 >= n) break;
458
459                                 /* Append a space */
460                                 buf[i++] = ' ';
461
462                                 /* Append some more spaces */
463                                 while (!(i % 8)) buf[i++] = ' ';
464                         }
465
466 #ifdef JP
467                         else if (iskanji(*s))
468                         {
469                                 if (!s[1]) break;
470                                 buf[i++] = *s++;
471                                 buf[i++] = *s;
472                         }
473 # ifndef EUC
474         /* È¾³Ñ¤«¤Ê¤ËÂбþ */
475                         else if ((((int)*s & 0xff) > 0xa1) && (((int)*s & 0xff ) < 0xdf))
476                         {
477                                 buf[i++] = *s;
478                                 if (i >= n) break;
479                         }
480 # endif
481 #endif
482                         /* Handle printables */
483                         else if (isprint(*s))
484                         {
485                                 /* Copy */
486                                 buf[i++] = *s;
487
488                                 /* Check length */
489                                 if (i >= n) break;
490                         }
491                 }
492                 /* No newline character, but terminate */
493                 buf[i] = '\0';
494
495                 /* Success */
496                 return (0);
497         }
498
499         /* Nothing */
500         buf[0] = '\0';
501
502         /* Failure */
503         return (1);
504 }
505
506
507 /*
508  * Hack -- replacement for "fputs()"
509  *
510  * Dump a string, plus a newline, to a file
511  *
512  * XXX XXX XXX Process internal weirdness?
513  */
514 errr my_fputs(FILE *fff, cptr buf, huge n)
515 {
516         /* XXX XXX */
517         n = n ? n : 0;
518
519         /* Dump, ignore errors */
520         (void)fprintf(fff, "%s\n", buf);
521
522         /* Success */
523         return (0);
524 }
525
526
527 #ifdef ACORN
528
529
530 /*
531  * Most of the "file" routines for "ACORN" should be in "main-acn.c"
532  *
533  * Many of them can be rewritten now that only "fd_open()" and "fd_make()"
534  * and "my_fopen()" should ever create files.
535  */
536
537
538 #else /* ACORN */
539
540
541 /*
542  * Code Warrior is a little weird about some functions
543  */
544 #ifdef BEN_HACK
545 extern int open(const char *, int, ...);
546 extern int close(int);
547 extern int read(int, void *, unsigned int);
548 extern int write(int, const void *, unsigned int);
549 extern long lseek(int, long, int);
550 #endif /* BEN_HACK */
551
552
553 /*
554  * The Macintosh is a little bit brain-dead sometimes
555  */
556 #ifdef MACINTOSH
557 # define open(N,F,M) \
558 ((M), open((char*)(N),F))
559 # define write(F,B,S) \
560 write(F,(char*)(B),S)
561 #endif /* MACINTOSH */
562
563
564 /*
565  * Several systems have no "O_BINARY" flag
566  */
567 #ifndef O_BINARY
568 # define O_BINARY 0
569 #endif /* O_BINARY */
570
571
572 /*
573  * Hack -- attempt to delete a file
574  */
575 errr fd_kill(cptr file)
576 {
577         char buf[1024];
578
579         /* Hack -- Try to parse the path */
580         if (path_parse(buf, 1024, file)) return (-1);
581
582         /* Remove */
583         (void)remove(buf);
584
585         /* XXX XXX XXX */
586         return (0);
587 }
588
589
590 /*
591  * Hack -- attempt to move a file
592  */
593 errr fd_move(cptr file, cptr what)
594 {
595         char buf[1024];
596         char aux[1024];
597
598         /* Hack -- Try to parse the path */
599         if (path_parse(buf, 1024, file)) return (-1);
600
601         /* Hack -- Try to parse the path */
602         if (path_parse(aux, 1024, what)) return (-1);
603
604         /* Rename */
605         (void)rename(buf, aux);
606
607         /* XXX XXX XXX */
608         return (0);
609 }
610
611
612 /*
613  * Hack -- attempt to copy a file
614  */
615 errr fd_copy(cptr file, cptr what)
616 {
617         char buf[1024];
618         char aux[1024];
619
620         /* Hack -- Try to parse the path */
621         if (path_parse(buf, 1024, file)) return (-1);
622
623         /* Hack -- Try to parse the path */
624         if (path_parse(aux, 1024, what)) return (-1);
625
626         /* Copy XXX XXX XXX */
627         /* (void)rename(buf, aux); */
628
629         /* XXX XXX XXX */
630         return (1);
631 }
632
633
634 /*
635  * Hack -- attempt to open a file descriptor (create file)
636  *
637  * This function should fail if the file already exists
638  *
639  * Note that we assume that the file should be "binary"
640  *
641  * XXX XXX XXX The horrible "BEN_HACK" code is for compiling under
642  * the CodeWarrior compiler, in which case, for some reason, none
643  * of the "O_*" flags are defined, and we must fake the definition
644  * of "O_RDONLY", "O_WRONLY", and "O_RDWR" in "A-win-h", and then
645  * we must simulate the effect of the proper "open()" call below.
646  */
647 int fd_make(cptr file, int mode)
648 {
649         char buf[1024];
650
651         /* Hack -- Try to parse the path */
652         if (path_parse(buf, 1024, file)) return (-1);
653
654 #ifdef BEN_HACK
655
656         /* Check for existance */
657         /* if (fd_close(fd_open(file, O_RDONLY | O_BINARY))) return (1); */
658
659         /* Mega-Hack -- Create the file */
660         (void)my_fclose(my_fopen(file, "wb"));
661
662         /* Re-open the file for writing */
663         return (open(buf, O_WRONLY | O_BINARY, mode));
664
665 #else /* BEN_HACK */
666
667         /* Create the file, fail if exists, write-only, binary */
668         return (open(buf, O_CREAT | O_EXCL | O_WRONLY | O_BINARY, mode));
669
670 #endif /* BEN_HACK */
671
672 }
673
674
675 /*
676  * Hack -- attempt to open a file descriptor (existing file)
677  *
678  * Note that we assume that the file should be "binary"
679  */
680 int fd_open(cptr file, int flags)
681 {
682         char buf[1024];
683
684         /* Hack -- Try to parse the path */
685         if (path_parse(buf, 1024, file)) return (-1);
686
687         /* Attempt to open the file */
688         return (open(buf, flags | O_BINARY, 0));
689 }
690
691
692 /*
693  * Hack -- attempt to lock a file descriptor
694  *
695  * Legal lock types -- F_UNLCK, F_RDLCK, F_WRLCK
696  */
697 errr fd_lock(int fd, int what)
698 {
699         /* XXX XXX */
700         what = what ? what : 0;
701
702         /* Verify the fd */
703         if (fd < 0) return (-1);
704
705 #ifdef SET_UID
706
707 # ifdef USG
708
709 #  if defined(F_ULOCK) && defined(F_LOCK)
710
711         /* Un-Lock */
712         if (what == F_UNLCK)
713         {
714                 /* Unlock it, Ignore errors */
715                 lockf(fd, F_ULOCK, 0);
716         }
717
718         /* Lock */
719         else
720         {
721                 /* Lock the score file */
722                 if (lockf(fd, F_LOCK, 0) != 0) return (1);
723         }
724
725 #  endif
726
727 # else
728
729 #  if defined(LOCK_UN) && defined(LOCK_EX)
730
731         /* Un-Lock */
732         if (what == F_UNLCK)
733         {
734                 /* Unlock it, Ignore errors */
735                 (void)flock(fd, LOCK_UN);
736         }
737
738         /* Lock */
739         else
740         {
741                 /* Lock the score file */
742                 if (flock(fd, LOCK_EX) != 0) return (1);
743         }
744
745 #  endif
746
747 # endif
748
749 #endif
750
751         /* Success */
752         return (0);
753 }
754
755
756 /*
757  * Hack -- attempt to seek on a file descriptor
758  */
759 errr fd_seek(int fd, huge n)
760 {
761         huge p;
762
763         /* Verify fd */
764         if (fd < 0) return (-1);
765
766         /* Seek to the given position */
767         p = lseek(fd, n, SEEK_SET);
768
769         /* Failure */
770         if (p < 0) return (1);
771
772         /* Failure */
773         if (p != n) return (1);
774
775         /* Success */
776         return (0);
777 }
778
779
780 /*
781  * Hack -- attempt to truncate a file descriptor
782  */
783 errr fd_chop(int fd, huge n)
784 {
785         /* XXX XXX */
786         n = n ? n : 0;
787
788         /* Verify the fd */
789         if (fd < 0) return (-1);
790
791 #if defined(SUNOS) || defined(ULTRIX) || defined(NeXT)
792         /* Truncate */
793         ftruncate(fd, n);
794 #endif
795
796         /* Success */
797         return (0);
798 }
799
800
801 /*
802  * Hack -- attempt to read data from a file descriptor
803  */
804 errr fd_read(int fd, char *buf, huge n)
805 {
806         /* Verify the fd */
807         if (fd < 0) return (-1);
808
809 #ifndef SET_UID
810
811         /* Read pieces */
812         while (n >= 16384)
813         {
814                 /* Read a piece */
815                 if (read(fd, buf, 16384) != 16384) return (1);
816
817                 /* Shorten the task */
818                 buf += 16384;
819
820                 /* Shorten the task */
821                 n -= 16384;
822         }
823
824 #endif
825
826         /* Read the final piece */
827         if (read(fd, buf, n) != (int)n) return (1);
828
829         /* Success */
830         return (0);
831 }
832
833
834 /*
835  * Hack -- Attempt to write data to a file descriptor
836  */
837 errr fd_write(int fd, cptr buf, huge n)
838 {
839         /* Verify the fd */
840         if (fd < 0) return (-1);
841
842 #ifndef SET_UID
843
844         /* Write pieces */
845         while (n >= 16384)
846         {
847                 /* Write a piece */
848                 if (write(fd, buf, 16384) != 16384) return (1);
849
850                 /* Shorten the task */
851                 buf += 16384;
852
853                 /* Shorten the task */
854                 n -= 16384;
855         }
856
857 #endif
858
859         /* Write the final piece */
860         if (write(fd, buf, n) != (int)n) return (1);
861
862         /* Success */
863         return (0);
864 }
865
866
867 /*
868  * Hack -- attempt to close a file descriptor
869  */
870 errr fd_close(int fd)
871 {
872         /* Verify the fd */
873         if (fd < 0) return (-1);
874
875         /* Close */
876         (void)close(fd);
877
878         /* XXX XXX XXX */
879         return (0);
880 }
881
882
883 #endif /* ACORN */
884
885
886
887
888 /*
889  * XXX XXX XXX Important note about "colors" XXX XXX XXX
890  *
891  * The "TERM_*" color definitions list the "composition" of each
892  * "Angband color" in terms of "quarters" of each of the three color
893  * components (Red, Green, Blue), for example, TERM_UMBER is defined
894  * as 2/4 Red, 1/4 Green, 0/4 Blue.
895  *
896  * The following info is from "Torbjorn Lindgren" (see "main-xaw.c").
897  *
898  * These values are NOT gamma-corrected.  On most machines (with the
899  * Macintosh being an important exception), you must "gamma-correct"
900  * the given values, that is, "correct for the intrinsic non-linearity
901  * of the phosphor", by converting the given intensity levels based
902  * on the "gamma" of the target screen, which is usually 1.7 (or 1.5).
903  *
904  * The actual formula for conversion is unknown to me at this time,
905  * but you can use the table below for the most common gamma values.
906  *
907  * So, on most machines, simply convert the values based on the "gamma"
908  * of the target screen, which is usually in the range 1.5 to 1.7, and
909  * usually is closest to 1.7.  The converted value for each of the five
910  * different "quarter" values is given below:
911  *
912  *  Given     Gamma 1.0       Gamma 1.5       Gamma 1.7     Hex 1.7
913  *  -----       ----            ----            ----          ---
914  *   0/4        0.00            0.00            0.00          #00
915  *   1/4        0.25            0.27            0.28          #47
916  *   2/4        0.50            0.55            0.56          #8f
917  *   3/4        0.75            0.82            0.84          #d7
918  *   4/4        1.00            1.00            1.00          #ff
919  *
920  * Note that some machines (i.e. most IBM machines) are limited to a
921  * hard-coded set of colors, and so the information above is useless.
922  *
923  * Also, some machines are limited to a pre-determined set of colors,
924  * for example, the IBM can only display 16 colors, and only 14 of
925  * those colors resemble colors used by Angband, and then only when
926  * you ignore the fact that "Slate" and "cyan" are not really matches,
927  * so on the IBM, we use "orange" for both "Umber", and "Light Umber"
928  * in addition to the obvious "Orange", since by combining all of the
929  * "indeterminate" colors into a single color, the rest of the colors
930  * are left with "meaningful" values.
931  */
932
933
934 /*
935  * Move the cursor
936  */
937 void move_cursor(int row, int col)
938 {
939         Term_gotoxy(col, row);
940 }
941
942
943
944 /*
945  * Convert a decimal to a single digit octal number
946  */
947 static char octify(uint i)
948 {
949         return (hexsym[i%8]);
950 }
951
952 /*
953  * Convert a decimal to a single digit hex number
954  */
955 static char hexify(uint i)
956 {
957         return (hexsym[i%16]);
958 }
959
960
961 /*
962  * Convert a octal-digit into a decimal
963  */
964 static int deoct(char c)
965 {
966         if (isdigit(c)) return (D2I(c));
967         return (0);
968 }
969
970 /*
971  * Convert a hexidecimal-digit into a decimal
972  */
973 static int dehex(char c)
974 {
975         if (isdigit(c)) return (D2I(c));
976         if (islower(c)) return (A2I(c) + 10);
977         if (isupper(c)) return (A2I(tolower(c)) + 10);
978         return (0);
979 }
980
981
982 /*
983  * Hack -- convert a printable string into real ascii
984  *
985  * I have no clue if this function correctly handles, for example,
986  * parsing "\xFF" into a (signed) char.  Whoever thought of making
987  * the "sign" of a "char" undefined is a complete moron.  Oh well.
988  */
989 void text_to_ascii(char *buf, cptr str)
990 {
991         char *s = buf;
992
993         /* Analyze the "ascii" string */
994         while (*str)
995         {
996                 /* Backslash codes */
997                 if (*str == '\\')
998                 {
999                         /* Skip the backslash */
1000                         str++;
1001
1002                         /* Hex-mode XXX */
1003                         if (*str == 'x')
1004                         {
1005                                 *s = 16 * dehex(*++str);
1006                                 *s++ += dehex(*++str);
1007                         }
1008
1009                         /* Hack -- simple way to specify "backslash" */
1010                         else if (*str == '\\')
1011                         {
1012                                 *s++ = '\\';
1013                         }
1014
1015                         /* Hack -- simple way to specify "caret" */
1016                         else if (*str == '^')
1017                         {
1018                                 *s++ = '^';
1019                         }
1020
1021                         /* Hack -- simple way to specify "space" */
1022                         else if (*str == 's')
1023                         {
1024                                 *s++ = ' ';
1025                         }
1026
1027                         /* Hack -- simple way to specify Escape */
1028                         else if (*str == 'e')
1029                         {
1030                                 *s++ = ESCAPE;
1031                         }
1032
1033                         /* Backspace */
1034                         else if (*str == 'b')
1035                         {
1036                                 *s++ = '\b';
1037                         }
1038
1039                         /* Newline */
1040                         else if (*str == 'n')
1041                         {
1042                                 *s++ = '\n';
1043                         }
1044
1045                         /* Return */
1046                         else if (*str == 'r')
1047                         {
1048                                 *s++ = '\r';
1049                         }
1050
1051                         /* Tab */
1052                         else if (*str == 't')
1053                         {
1054                                 *s++ = '\t';
1055                         }
1056
1057                         /* Octal-mode */
1058                         else if (*str == '0')
1059                         {
1060                                 *s = 8 * deoct(*++str);
1061                                 *s++ += deoct(*++str);
1062                         }
1063
1064                         /* Octal-mode */
1065                         else if (*str == '1')
1066                         {
1067                                 *s = 64 + 8 * deoct(*++str);
1068                                 *s++ += deoct(*++str);
1069                         }
1070
1071                         /* Octal-mode */
1072                         else if (*str == '2')
1073                         {
1074                                 *s = 64 * 2 + 8 * deoct(*++str);
1075                                 *s++ += deoct(*++str);
1076                         }
1077
1078                         /* Octal-mode */
1079                         else if (*str == '3')
1080                         {
1081                                 *s = 64 * 3 + 8 * deoct(*++str);
1082                                 *s++ += deoct(*++str);
1083                         }
1084
1085                         /* Skip the final char */
1086                         str++;
1087                 }
1088
1089                 /* Normal Control codes */
1090                 else if (*str == '^')
1091                 {
1092                         str++;
1093                         *s++ = (*str++ & 037);
1094                 }
1095
1096                 /* Normal chars */
1097                 else
1098                 {
1099                         *s++ = *str++;
1100                 }
1101         }
1102
1103         /* Terminate */
1104         *s = '\0';
1105 }
1106
1107
1108 /*
1109  * Hack -- convert a string into a printable form
1110  */
1111 void ascii_to_text(char *buf, cptr str)
1112 {
1113         char *s = buf;
1114
1115         /* Analyze the "ascii" string */
1116         while (*str)
1117         {
1118                 byte i = (byte)(*str++);
1119
1120                 if (i == ESCAPE)
1121                 {
1122                         *s++ = '\\';
1123                         *s++ = 'e';
1124                 }
1125                 else if (i == ' ')
1126                 {
1127                         *s++ = '\\';
1128                         *s++ = 's';
1129                 }
1130                 else if (i == '\b')
1131                 {
1132                         *s++ = '\\';
1133                         *s++ = 'b';
1134                 }
1135                 else if (i == '\t')
1136                 {
1137                         *s++ = '\\';
1138                         *s++ = 't';
1139                 }
1140                 else if (i == '\n')
1141                 {
1142                         *s++ = '\\';
1143                         *s++ = 'n';
1144                 }
1145                 else if (i == '\r')
1146                 {
1147                         *s++ = '\\';
1148                         *s++ = 'r';
1149                 }
1150                 else if (i == '^')
1151                 {
1152                         *s++ = '\\';
1153                         *s++ = '^';
1154                 }
1155                 else if (i == '\\')
1156                 {
1157                         *s++ = '\\';
1158                         *s++ = '\\';
1159                 }
1160                 else if (i < 32)
1161                 {
1162                         *s++ = '^';
1163                         *s++ = i + 64;
1164                 }
1165                 else if (i < 127)
1166                 {
1167                         *s++ = i;
1168                 }
1169                 else if (i < 64)
1170                 {
1171                         *s++ = '\\';
1172                         *s++ = '0';
1173                         *s++ = octify(i / 8);
1174                         *s++ = octify(i % 8);
1175                 }
1176                 else
1177                 {
1178                         *s++ = '\\';
1179                         *s++ = 'x';
1180                         *s++ = hexify(i / 16);
1181                         *s++ = hexify(i % 16);
1182                 }
1183         }
1184
1185         /* Terminate */
1186         *s = '\0';
1187 }
1188
1189
1190
1191 /*
1192  * The "macro" package
1193  *
1194  * Functions are provided to manipulate a collection of macros, each
1195  * of which has a trigger pattern string and a resulting action string
1196  * and a small set of flags.
1197  */
1198
1199
1200
1201 /*
1202  * Determine if any macros have ever started with a given character.
1203  */
1204 static bool macro__use[256];
1205
1206
1207 /*
1208  * Find the macro (if any) which exactly matches the given pattern
1209  */
1210 sint macro_find_exact(cptr pat)
1211 {
1212         int i;
1213
1214         /* Nothing possible */
1215         if (!macro__use[(byte)(pat[0])])
1216         {
1217                 return (-1);
1218         }
1219
1220         /* Scan the macros */
1221         for (i = 0; i < macro__num; ++i)
1222         {
1223                 /* Skip macros which do not match the pattern */
1224                 if (!streq(macro__pat[i], pat)) continue;
1225
1226                 /* Found one */
1227                 return (i);
1228         }
1229
1230         /* No matches */
1231         return (-1);
1232 }
1233
1234
1235 /*
1236  * Find the first macro (if any) which contains the given pattern
1237  */
1238 static sint macro_find_check(cptr pat)
1239 {
1240         int i;
1241
1242         /* Nothing possible */
1243         if (!macro__use[(byte)(pat[0])])
1244         {
1245                 return (-1);
1246         }
1247
1248         /* Scan the macros */
1249         for (i = 0; i < macro__num; ++i)
1250         {
1251                 /* Skip macros which do not contain the pattern */
1252                 if (!prefix(macro__pat[i], pat)) continue;
1253
1254                 /* Found one */
1255                 return (i);
1256         }
1257
1258         /* Nothing */
1259         return (-1);
1260 }
1261
1262
1263 /*
1264  * Find the first macro (if any) which contains the given pattern and more
1265  */
1266 static sint macro_find_maybe(cptr pat)
1267 {
1268         int i;
1269
1270         /* Nothing possible */
1271         if (!macro__use[(byte)(pat[0])])
1272         {
1273                 return (-1);
1274         }
1275
1276         /* Scan the macros */
1277         for (i = 0; i < macro__num; ++i)
1278         {
1279                 /* Skip macros which do not contain the pattern */
1280                 if (!prefix(macro__pat[i], pat)) continue;
1281
1282                 /* Skip macros which exactly match the pattern XXX XXX */
1283                 if (streq(macro__pat[i], pat)) continue;
1284
1285                 /* Found one */
1286                 return (i);
1287         }
1288
1289         /* Nothing */
1290         return (-1);
1291 }
1292
1293
1294 /*
1295  * Find the longest macro (if any) which starts with the given pattern
1296  */
1297 static sint macro_find_ready(cptr pat)
1298 {
1299         int i, t, n = -1, s = -1;
1300
1301         /* Nothing possible */
1302         if (!macro__use[(byte)(pat[0])])
1303         {
1304                 return (-1);
1305         }
1306
1307         /* Scan the macros */
1308         for (i = 0; i < macro__num; ++i)
1309         {
1310                 /* Skip macros which are not contained by the pattern */
1311                 if (!prefix(pat, macro__pat[i])) continue;
1312
1313                 /* Obtain the length of this macro */
1314                 t = strlen(macro__pat[i]);
1315
1316                 /* Only track the "longest" pattern */
1317                 if ((n >= 0) && (s > t)) continue;
1318
1319                 /* Track the entry */
1320                 n = i;
1321                 s = t;
1322         }
1323
1324         /* Result */
1325         return (n);
1326 }
1327
1328
1329 /*
1330  * Add a macro definition (or redefinition).
1331  *
1332  * We should use "act == NULL" to "remove" a macro, but this might make it
1333  * impossible to save the "removal" of a macro definition.  XXX XXX XXX
1334  *
1335  * We should consider refusing to allow macros which contain existing macros,
1336  * or which are contained in existing macros, because this would simplify the
1337  * macro analysis code.  XXX XXX XXX
1338  *
1339  * We should consider removing the "command macro" crap, and replacing it
1340  * with some kind of "powerful keymap" ability, but this might make it hard
1341  * to change the "roguelike" option from inside the game.  XXX XXX XXX
1342  */
1343 errr macro_add(cptr pat, cptr act)
1344 {
1345         int n;
1346
1347
1348         /* Paranoia -- require data */
1349         if (!pat || !act) return (-1);
1350
1351
1352         /* Look for any existing macro */
1353         n = macro_find_exact(pat);
1354
1355         /* Replace existing macro */
1356         if (n >= 0)
1357         {
1358                 /* Free the old macro action */
1359                 string_free(macro__act[n]);
1360         }
1361
1362         /* Create a new macro */
1363         else
1364         {
1365                 /* Acquire a new index */
1366                 n = macro__num++;
1367
1368                 /* Save the pattern */
1369                 macro__pat[n] = string_make(pat);
1370         }
1371
1372         /* Save the action */
1373         macro__act[n] = string_make(act);
1374
1375         /* Efficiency */
1376         macro__use[(byte)(pat[0])] = TRUE;
1377
1378         /* Success */
1379         return (0);
1380 }
1381
1382
1383
1384 /*
1385  * Initialize the "macro" package
1386  */
1387 errr macro_init(void)
1388 {
1389         /* Macro patterns */
1390         C_MAKE(macro__pat, MACRO_MAX, cptr);
1391
1392         /* Macro actions */
1393         C_MAKE(macro__act, MACRO_MAX, cptr);
1394
1395         /* Success */
1396         return (0);
1397 }
1398
1399 /*
1400  * Local variable -- we are inside a "macro action"
1401  *
1402  * Do not match any macros until "ascii 30" is found.
1403  */
1404 static bool parse_macro = FALSE;
1405
1406 /*
1407  * Local variable -- we are inside a "macro trigger"
1408  *
1409  * Strip all keypresses until a low ascii value is found.
1410  */
1411 static bool parse_under = FALSE;
1412
1413
1414 /*
1415  * Flush all input chars.  Actually, remember the flush,
1416  * and do a "special flush" before the next "inkey()".
1417  *
1418  * This is not only more efficient, but also necessary to make sure
1419  * that various "inkey()" codes are not "lost" along the way.
1420  */
1421 void flush(void)
1422 {
1423         /* Do it later */
1424         inkey_xtra = TRUE;
1425 }
1426
1427
1428 /*
1429  * Flush the screen, make a noise
1430  */
1431 void bell(void)
1432 {
1433         /* Mega-Hack -- Flush the output */
1434         Term_fresh();
1435
1436         /* Make a bell noise (if allowed) */
1437         if (ring_bell) Term_xtra(TERM_XTRA_NOISE, 0);
1438
1439         /* Flush the input (later!) */
1440         flush();
1441 }
1442
1443
1444 /*
1445  * Hack -- Make a (relevant?) sound
1446  */
1447 void sound(int val)
1448 {
1449         /* No sound */
1450         if (!use_sound) return;
1451
1452         /* Make a sound (if allowed) */
1453         Term_xtra(TERM_XTRA_SOUND, val);
1454 }
1455
1456
1457
1458 /*
1459  * Helper function called only from "inkey()"
1460  *
1461  * This function does almost all of the "macro" processing.
1462  *
1463  * We use the "Term_key_push()" function to handle "failed" macros, as well
1464  * as "extra" keys read in while choosing the proper macro, and also to hold
1465  * the action for the macro, plus a special "ascii 30" character indicating
1466  * that any macro action in progress is complete.  Embedded macros are thus
1467  * illegal, unless a macro action includes an explicit "ascii 30" character,
1468  * which would probably be a massive hack, and might break things.
1469  *
1470  * Only 500 (0+1+2+...+29+30) milliseconds may elapse between each key in
1471  * the macro trigger sequence.  If a key sequence forms the "prefix" of a
1472  * macro trigger, 500 milliseconds must pass before the key sequence is
1473  * known not to be that macro trigger.  XXX XXX XXX
1474  */
1475 static char inkey_aux(void)
1476 {
1477         int k = 0, n, p = 0, w = 0;
1478
1479         char ch;
1480
1481         cptr pat, act;
1482
1483         char buf[1024];
1484
1485         /* Hack : ¥­¡¼ÆþÎÏÂÔ¤Á¤Ç»ß¤Þ¤Ã¤Æ¤¤¤ë¤Î¤Ç¡¢Î®¤ì¤¿¹Ô¤Îµ­²±¤ÏÉÔÍס£*/
1486         num_more = 0;
1487
1488         /* Wait for a keypress */
1489         (void)(Term_inkey(&ch, TRUE, TRUE));
1490
1491
1492         /* End "macro action" */
1493         if (ch == 30) parse_macro = FALSE;
1494
1495         /* Inside "macro action" */
1496         if (ch == 30) return (ch);
1497
1498         /* Inside "macro action" */
1499         if (parse_macro) return (ch);
1500
1501         /* Inside "macro trigger" */
1502         if (parse_under) return (ch);
1503
1504
1505         /* Save the first key, advance */
1506         buf[p++] = ch;
1507         buf[p] = '\0';
1508
1509
1510         /* Check for possible macro */
1511         k = macro_find_check(buf);
1512
1513         /* No macro pending */
1514         if (k < 0) return (ch);
1515
1516
1517         /* Wait for a macro, or a timeout */
1518         while (TRUE)
1519         {
1520                 /* Check for pending macro */
1521                 k = macro_find_maybe(buf);
1522
1523                 /* No macro pending */
1524                 if (k < 0) break;
1525
1526                 /* Check for (and remove) a pending key */
1527                 if (0 == Term_inkey(&ch, FALSE, TRUE))
1528                 {
1529                         /* Append the key */
1530                         buf[p++] = ch;
1531                         buf[p] = '\0';
1532
1533                         /* Restart wait */
1534                         w = 0;
1535                 }
1536
1537                 /* No key ready */
1538                 else
1539                 {
1540                         /* Increase "wait" */
1541                         w += 10;
1542
1543                         /* Excessive delay */
1544                         if (w >= 100) break;
1545
1546                         /* Delay */
1547                         Term_xtra(TERM_XTRA_DELAY, w);
1548                 }
1549         }
1550
1551
1552         /* Check for available macro */
1553         k = macro_find_ready(buf);
1554
1555         /* No macro available */
1556         if (k < 0)
1557         {
1558                 /* Push all the keys back on the queue */
1559                 while (p > 0)
1560                 {
1561                         /* Push the key, notice over-flow */
1562                         if (Term_key_push(buf[--p])) return (0);
1563                 }
1564
1565                 /* Wait for (and remove) a pending key */
1566                 (void)Term_inkey(&ch, TRUE, TRUE);
1567
1568                 /* Return the key */
1569                 return (ch);
1570         }
1571
1572
1573         /* Get the pattern */
1574         pat = macro__pat[k];
1575
1576         /* Get the length of the pattern */
1577         n = strlen(pat);
1578
1579         /* Push the "extra" keys back on the queue */
1580         while (p > n)
1581         {
1582                 /* Push the key, notice over-flow */
1583                 if (Term_key_push(buf[--p])) return (0);
1584         }
1585
1586
1587         /* Begin "macro action" */
1588         parse_macro = TRUE;
1589
1590         /* Push the "end of macro action" key */
1591         if (Term_key_push(30)) return (0);
1592
1593
1594         /* Access the macro action */
1595         act = macro__act[k];
1596
1597         /* Get the length of the action */
1598         n = strlen(act);
1599
1600         /* Push the macro "action" onto the key queue */
1601         while (n > 0)
1602         {
1603                 /* Push the key, notice over-flow */
1604                 if (Term_key_push(act[--n])) return (0);
1605         }
1606
1607
1608         /* Hack -- Force "inkey()" to call us again */
1609         return (0);
1610 }
1611
1612
1613 /*
1614  * Mega-Hack -- special "inkey_next" pointer.  XXX XXX XXX
1615  *
1616  * This special pointer allows a sequence of keys to be "inserted" into
1617  * the stream of keys returned by "inkey()".  This key sequence will not
1618  * trigger any macros, and cannot be bypassed by the Borg.  It is used
1619  * in Angband to handle "keymaps".
1620  */
1621 static cptr inkey_next = NULL;
1622
1623
1624 #ifdef ALLOW_BORG
1625
1626 /*
1627  * Mega-Hack -- special "inkey_hack" hook.  XXX XXX XXX
1628  *
1629  * This special function hook allows the "Borg" (see elsewhere) to take
1630  * control of the "inkey()" function, and substitute in fake keypresses.
1631  */
1632 char (*inkey_hack)(int flush_first) = NULL;
1633
1634 #endif /* ALLOW_BORG */
1635
1636
1637
1638 /*
1639  * Get a keypress from the user.
1640  *
1641  * This function recognizes a few "global parameters".  These are variables
1642  * which, if set to TRUE before calling this function, will have an effect
1643  * on this function, and which are always reset to FALSE by this function
1644  * before this function returns.  Thus they function just like normal
1645  * parameters, except that most calls to this function can ignore them.
1646  *
1647  * If "inkey_xtra" is TRUE, then all pending keypresses will be flushed,
1648  * and any macro processing in progress will be aborted.  This flag is
1649  * set by the "flush()" function, which does not actually flush anything
1650  * itself, but rather, triggers delayed input flushing via "inkey_xtra".
1651  *
1652  * If "inkey_scan" is TRUE, then we will immediately return "zero" if no
1653  * keypress is available, instead of waiting for a keypress.
1654  *
1655  * If "inkey_base" is TRUE, then all macro processing will be bypassed.
1656  * If "inkey_base" and "inkey_scan" are both TRUE, then this function will
1657  * not return immediately, but will wait for a keypress for as long as the
1658  * normal macro matching code would, allowing the direct entry of macro
1659  * triggers.  The "inkey_base" flag is extremely dangerous!
1660  *
1661  * If "inkey_flag" is TRUE, then we will assume that we are waiting for a
1662  * normal command, and we will only show the cursor if "hilite_player" is
1663  * TRUE (or if the player is in a store), instead of always showing the
1664  * cursor.  The various "main-xxx.c" files should avoid saving the game
1665  * in response to a "menu item" request unless "inkey_flag" is TRUE, to
1666  * prevent savefile corruption.
1667  *
1668  * If we are waiting for a keypress, and no keypress is ready, then we will
1669  * refresh (once) the window which was active when this function was called.
1670  *
1671  * Note that "back-quote" is automatically converted into "escape" for
1672  * convenience on machines with no "escape" key.  This is done after the
1673  * macro matching, so the user can still make a macro for "backquote".
1674  *
1675  * Note the special handling of "ascii 30" (ctrl-caret, aka ctrl-shift-six)
1676  * and "ascii 31" (ctrl-underscore, aka ctrl-shift-minus), which are used to
1677  * provide support for simple keyboard "macros".  These keys are so strange
1678  * that their loss as normal keys will probably be noticed by nobody.  The
1679  * "ascii 30" key is used to indicate the "end" of a macro action, which
1680  * allows recursive macros to be avoided.  The "ascii 31" key is used by
1681  * some of the "main-xxx.c" files to introduce macro trigger sequences.
1682  *
1683  * Hack -- we use "ascii 29" (ctrl-right-bracket) as a special "magic" key,
1684  * which can be used to give a variety of "sub-commands" which can be used
1685  * any time.  These sub-commands could include commands to take a picture of
1686  * the current screen, to start/stop recording a macro action, etc.
1687  *
1688  * If "angband_term[0]" is not active, we will make it active during this
1689  * function, so that the various "main-xxx.c" files can assume that input
1690  * is only requested (via "Term_inkey()") when "angband_term[0]" is active.
1691  *
1692  * Mega-Hack -- This function is used as the entry point for clearing the
1693  * "signal_count" variable, and of the "character_saved" variable.
1694  *
1695  * Hack -- Note the use of "inkey_next" to allow "keymaps" to be processed.
1696  *
1697  * Mega-Hack -- Note the use of "inkey_hack" to allow the "Borg" to steal
1698  * control of the keyboard from the user.
1699  */
1700 char inkey(void)
1701 {
1702         int v;
1703         char kk;
1704         char ch = 0;
1705         bool done = FALSE;
1706         term *old = Term;
1707
1708 #ifdef USE_SCRIPT
1709         char result;
1710 #endif /* USE_SCRIPT */
1711
1712         /* Hack -- Use the "inkey_next" pointer */
1713         if (inkey_next && *inkey_next && !inkey_xtra)
1714         {
1715                 /* Get next character, and advance */
1716                 ch = *inkey_next++;
1717
1718                 /* Cancel the various "global parameters" */
1719                 inkey_base = inkey_xtra = inkey_flag = inkey_scan = FALSE;
1720
1721                 /* Accept result */
1722                 return (ch);
1723         }
1724
1725         /* Forget pointer */
1726         inkey_next = NULL;
1727
1728
1729 #ifdef ALLOW_BORG
1730
1731         /* Mega-Hack -- Use the special hook */
1732         if (inkey_hack && ((ch = (*inkey_hack)(inkey_xtra)) != 0))
1733         {
1734                 /* Cancel the various "global parameters" */
1735                 inkey_base = inkey_xtra = inkey_flag = inkey_scan = FALSE;
1736
1737                 /* Accept result */
1738                 return (ch);
1739         }
1740
1741 #endif /* ALLOW_BORG */
1742
1743 #ifdef USE_SCRIPT
1744
1745         if ((result = inkey_borg_callback(inkey_base, inkey_xtra, inkey_flag, inkey_scan)))
1746         {
1747                 /* Cancel the various "global parameters" */
1748                 inkey_base = inkey_xtra = inkey_flag = inkey_scan = FALSE;
1749
1750                 return (result);
1751         }
1752
1753 #endif /* USE_SCRIPT */
1754
1755
1756         /* Hack -- handle delayed "flush()" */
1757         if (inkey_xtra)
1758         {
1759                 /* End "macro action" */
1760                 parse_macro = FALSE;
1761
1762                 /* End "macro trigger" */
1763                 parse_under = FALSE;
1764
1765                 /* Forget old keypresses */
1766                 Term_flush();
1767         }
1768
1769
1770         /* Access cursor state */
1771         (void)Term_get_cursor(&v);
1772
1773         /* Show the cursor if waiting, except sometimes in "command" mode */
1774         if (!inkey_scan && (!inkey_flag || hilite_player || character_icky))
1775         {
1776                 /* Show the cursor */
1777                 (void)Term_set_cursor(1);
1778         }
1779
1780
1781         /* Hack -- Activate main screen */
1782         Term_activate(angband_term[0]);
1783
1784
1785         /* Get a key */
1786         while (!ch)
1787         {
1788                 /* Hack -- Handle "inkey_scan" */
1789                 if (!inkey_base && inkey_scan &&
1790                         (0 != Term_inkey(&kk, FALSE, FALSE)))
1791                 {
1792                         break;
1793                 }
1794
1795
1796                 /* Hack -- Flush output once when no key ready */
1797                 if (!done && (0 != Term_inkey(&kk, FALSE, FALSE)))
1798                 {
1799                         /* Hack -- activate proper term */
1800                         Term_activate(old);
1801
1802                         /* Flush output */
1803                         Term_fresh();
1804
1805                         /* Hack -- activate main screen */
1806                         Term_activate(angband_term[0]);
1807
1808                         /* Mega-Hack -- reset saved flag */
1809                         character_saved = FALSE;
1810
1811                         /* Mega-Hack -- reset signal counter */
1812                         signal_count = 0;
1813
1814                         /* Only once */
1815                         done = TRUE;
1816                 }
1817
1818
1819                 /* Hack -- Handle "inkey_base" */
1820                 if (inkey_base)
1821                 {
1822                         int w = 0;
1823
1824                         /* Wait forever */
1825                         if (!inkey_scan)
1826                         {
1827                                 /* Wait for (and remove) a pending key */
1828                                 if (0 == Term_inkey(&ch, TRUE, TRUE))
1829                                 {
1830                                         /* Done */
1831                                         break;
1832                                 }
1833
1834                                 /* Oops */
1835                                 break;
1836                         }
1837
1838                         /* Wait */
1839                         while (TRUE)
1840                         {
1841                                 /* Check for (and remove) a pending key */
1842                                 if (0 == Term_inkey(&ch, FALSE, TRUE))
1843                                 {
1844                                         /* Done */
1845                                         break;
1846                                 }
1847
1848                                 /* No key ready */
1849                                 else
1850                                 {
1851                                         /* Increase "wait" */
1852                                         w += 10;
1853
1854                                         /* Excessive delay */
1855                                         if (w >= 100) break;
1856
1857                                         /* Delay */
1858                                         Term_xtra(TERM_XTRA_DELAY, w);
1859                                 }
1860                         }
1861
1862                         /* Done */
1863                         break;
1864                 }
1865
1866
1867                 /* Get a key (see above) */
1868                 ch = inkey_aux();
1869
1870
1871                 /* Handle "control-right-bracket" */
1872                 if (ch == 29)
1873                 {
1874                         /* Strip this key */
1875                         ch = 0;
1876
1877                         /* Continue */
1878                         continue;
1879                 }
1880
1881
1882                 /* Treat back-quote as escape */
1883 //              if (ch == '`') ch = ESCAPE;
1884
1885
1886                 /* End "macro trigger" */
1887                 if (parse_under && (ch <= 32))
1888                 {
1889                         /* Strip this key */
1890                         ch = 0;
1891
1892                         /* End "macro trigger" */
1893                         parse_under = FALSE;
1894                 }
1895
1896
1897                 /* Handle "control-caret" */
1898                 if (ch == 30)
1899                 {
1900                         /* Strip this key */
1901                         ch = 0;
1902                 }
1903
1904                 /* Handle "control-underscore" */
1905                 else if (ch == 31)
1906                 {
1907                         /* Strip this key */
1908                         ch = 0;
1909
1910                         /* Begin "macro trigger" */
1911                         parse_under = TRUE;
1912                 }
1913
1914                 /* Inside "macro trigger" */
1915                 else if (parse_under)
1916                 {
1917                         /* Strip this key */
1918                         ch = 0;
1919                 }
1920         }
1921
1922
1923         /* Hack -- restore the term */
1924         Term_activate(old);
1925
1926
1927         /* Restore the cursor */
1928         Term_set_cursor(v);
1929
1930
1931         /* Cancel the various "global parameters" */
1932         inkey_base = inkey_xtra = inkey_flag = inkey_scan = FALSE;
1933
1934 #ifdef USE_SCRIPT
1935
1936         if ((result = inkey_callback(ch))) return result;
1937
1938 #endif /* USE_SCRIPT */
1939
1940         /* Return the keypress */
1941         return (ch);
1942 }
1943
1944
1945
1946
1947 /*
1948  * We use a global array for all inscriptions to reduce the memory
1949  * spent maintaining inscriptions.  Of course, it is still possible
1950  * to run out of inscription memory, especially if too many different
1951  * inscriptions are used, but hopefully this will be rare.
1952  *
1953  * We use dynamic string allocation because otherwise it is necessary
1954  * to pre-guess the amount of quark activity.  We limit the total
1955  * number of quarks, but this is much easier to "expand" as needed.
1956  *
1957  * Any two items with the same inscription will have the same "quark"
1958  * index, which should greatly reduce the need for inscription space.
1959  *
1960  * Note that "quark zero" is NULL and should not be "dereferenced".
1961  */
1962
1963 /*
1964  * Add a new "quark" to the set of quarks.
1965  */
1966 s16b quark_add(cptr str)
1967 {
1968         int i;
1969
1970         /* Look for an existing quark */
1971         for (i = 1; i < quark__num; i++)
1972         {
1973                 /* Check for equality */
1974                 if (streq(quark__str[i], str)) return (i);
1975         }
1976
1977         /* Paranoia -- Require room */
1978         if (quark__num == QUARK_MAX) return (0);
1979
1980         /* New maximal quark */
1981         quark__num = i + 1;
1982
1983         /* Add a new quark */
1984         quark__str[i] = string_make(str);
1985
1986         /* Return the index */
1987         return (i);
1988 }
1989
1990
1991 /*
1992  * This function looks up a quark
1993  */
1994 cptr quark_str(s16b i)
1995 {
1996         cptr q;
1997
1998         /* Verify */
1999         if ((i < 0) || (i >= quark__num)) i = 0;
2000
2001         /* Access the quark */
2002         q = quark__str[i];
2003
2004         /* Return the quark */
2005         return (q);
2006 }
2007
2008
2009
2010
2011 /*
2012  * Second try for the "message" handling routines.
2013  *
2014  * Each call to "message_add(s)" will add a new "most recent" message
2015  * to the "message recall list", using the contents of the string "s".
2016  *
2017  * The messages will be stored in such a way as to maximize "efficiency",
2018  * that is, we attempt to maximize the number of sequential messages that
2019  * can be retrieved, given a limited amount of storage space.
2020  *
2021  * We keep a buffer of chars to hold the "text" of the messages, not
2022  * necessarily in "order", and an array of offsets into that buffer,
2023  * representing the actual messages.  This is made more complicated
2024  * by the fact that both the array of indexes, and the buffer itself,
2025  * are both treated as "circular arrays" for efficiency purposes, but
2026  * the strings may not be "broken" across the ends of the array.
2027  *
2028  * The "message_add()" function is rather "complex", because it must be
2029  * extremely efficient, both in space and time, for use with the Borg.
2030  */
2031
2032
2033
2034 /*
2035  * How many messages are "available"?
2036  */
2037 s16b message_num(void)
2038 {
2039         int last, next, n;
2040
2041         /* Extract the indexes */
2042         last = message__last;
2043         next = message__next;
2044
2045         /* Handle "wrap" */
2046         if (next < last) next += MESSAGE_MAX;
2047
2048         /* Extract the space */
2049         n = (next - last);
2050
2051         /* Return the result */
2052         return (n);
2053 }
2054
2055
2056
2057 /*
2058  * Recall the "text" of a saved message
2059  */
2060 cptr message_str(int age)
2061 {
2062         s16b x;
2063         s16b o;
2064         cptr s;
2065
2066         /* Forgotten messages have no text */
2067         if ((age < 0) || (age >= message_num())) return ("");
2068
2069         /* Acquire the "logical" index */
2070         x = (message__next + MESSAGE_MAX - (age + 1)) % MESSAGE_MAX;
2071
2072         /* Get the "offset" for the message */
2073         o = message__ptr[x];
2074
2075         /* Access the message text */
2076         s = &message__buf[o];
2077
2078         /* Return the message text */
2079         return (s);
2080 }
2081
2082
2083
2084 /*
2085  * Add a new message, with great efficiency
2086  */
2087 void message_add(cptr str)
2088 {
2089         int i, k, x, m, n;
2090
2091         char u[1024];
2092         char splitted1[81];
2093         cptr splitted2;
2094
2095         /*** Step 1 -- Analyze the message ***/
2096
2097         /* Hack -- Ignore "non-messages" */
2098         if (!str) return;
2099
2100         /* Message length */
2101         n = strlen(str);
2102
2103         /* Important Hack -- Ignore "long" messages */
2104         if (n >= MESSAGE_BUF / 4) return;
2105
2106         /* extra step -- split the message if n>80.   (added by Mogami) */
2107         if (n > 80) {
2108 #ifdef JP
2109           cptr t = str;
2110
2111           for (n = 0; n < 80; n++, t++)
2112             if(iskanji(*t)) {
2113               t++;
2114               n++;
2115             }
2116           if (n == 81) n = 79; /* ºÇ¸å¤Îʸ»ú¤¬´Á»úȾʬ */
2117 #else
2118           for (n = 80; n > 60; n--)
2119                   if (str[n] == ' ') break;
2120           if (n == 60)
2121                   n = 80;
2122 #endif
2123           splitted2 = str + n;
2124           strncpy(splitted1, str ,n);
2125           splitted1[n] = '\0';
2126           str = splitted1;
2127         } else {
2128           splitted2 = NULL;
2129         }
2130
2131         /*** Step 2 -- Attempt to optimize ***/
2132
2133         /* Limit number of messages to check */
2134         m = message_num();
2135
2136         k = m / 4;
2137
2138         /* Limit number of messages to check */
2139         if (k > MESSAGE_MAX / 32) k = MESSAGE_MAX / 32;
2140
2141         /* Check previous message */
2142         for (i = message__next; m; m--)
2143         {
2144                 int j = 1;
2145
2146                 char buf[1024];
2147                 char *t;
2148
2149                 cptr old;
2150
2151                 /* Back up and wrap if needed */
2152                 if (i-- == 0) i = MESSAGE_MAX - 1;
2153
2154                 /* Access the old string */
2155                 old = &message__buf[message__ptr[i]];
2156
2157                 /* Skip small messages */
2158                 if (!old) continue;
2159
2160                 strcpy(buf, old);
2161
2162                 /* Find multiple */
2163 #ifdef JP
2164  for (t = buf; *t && (*t != '<' || (*(t+1) != 'x' )); t++) 
2165      if( iskanji(*t))t++;
2166 #else
2167                 for (t = buf; *t && (*t != '<'); t++);
2168 #endif
2169
2170                 if (*t)
2171                 {
2172                         /* Message is too small */
2173                         if (strlen(buf) < 6) break;
2174
2175                         /* Drop the space */
2176                         *(t - 1) = '\0';
2177
2178                         /* Get multiplier */
2179                         j = atoi(t+2);
2180                 }
2181
2182                 /* Limit the multiplier to 1000 */
2183                 if (buf && streq(buf, str) && (j < 1000))
2184                 {
2185                         j++;
2186
2187                         /* Overwrite */
2188                         message__next = i;
2189
2190                         str = u;
2191
2192                         /* Write it out */
2193                         sprintf(u, "%s <x%d>", buf, j);
2194
2195                         /* Message length */
2196                         n = strlen(str);
2197
2198                         if (!now_message) now_message++;
2199                 }
2200                 else
2201                 {
2202                         num_more++;/*ή¤ì¤¿¹Ô¤Î¿ô¤ò¿ô¤¨¤Æ¤ª¤¯*/
2203                         now_message++;
2204                 }
2205
2206                 /* Done */
2207                 break;
2208         }
2209
2210         /* Check the last few messages (if any to count) */
2211         for (i = message__next; k; k--)
2212         {
2213                 u16b q;
2214
2215                 cptr old;
2216
2217                 /* Back up and wrap if needed */
2218                 if (i-- == 0) i = MESSAGE_MAX - 1;
2219
2220                 /* Stop before oldest message */
2221                 if (i == message__last) break;
2222
2223                 /* Extract "distance" from "head" */
2224                 q = (message__head + MESSAGE_BUF - message__ptr[i]) % MESSAGE_BUF;
2225
2226                 /* Do not optimize over large distance */
2227                 if (q > MESSAGE_BUF / 2) continue;
2228
2229                 /* Access the old string */
2230                 old = &message__buf[message__ptr[i]];
2231
2232                 /* Compare */
2233                 if (!streq(old, str)) continue;
2234
2235                 /* Get the next message index, advance */
2236                 x = message__next++;
2237
2238                 /* Handle wrap */
2239                 if (message__next == MESSAGE_MAX) message__next = 0;
2240
2241                 /* Kill last message if needed */
2242                 if (message__next == message__last) message__last++;
2243
2244                 /* Handle wrap */
2245                 if (message__last == MESSAGE_MAX) message__last = 0;
2246
2247                 /* Assign the starting address */
2248                 message__ptr[x] = message__ptr[i];
2249
2250                 /* Success */
2251                 /* return; */
2252                 goto end_of_message_add;
2253
2254         }
2255
2256
2257         /*** Step 3 -- Ensure space before end of buffer ***/
2258
2259         /* Kill messages and Wrap if needed */
2260         if (message__head + n + 1 >= MESSAGE_BUF)
2261         {
2262                 /* Kill all "dead" messages */
2263                 for (i = message__last; TRUE; i++)
2264                 {
2265                         /* Wrap if needed */
2266                         if (i == MESSAGE_MAX) i = 0;
2267
2268                         /* Stop before the new message */
2269                         if (i == message__next) break;
2270
2271                         /* Kill "dead" messages */
2272                         if (message__ptr[i] >= message__head)
2273                         {
2274                                 /* Track oldest message */
2275                                 message__last = i + 1;
2276                         }
2277                 }
2278
2279                 /* Wrap "tail" if needed */
2280                 if (message__tail >= message__head) message__tail = 0;
2281
2282                 /* Start over */
2283                 message__head = 0;
2284         }
2285
2286
2287         /*** Step 4 -- Ensure space before next message ***/
2288
2289         /* Kill messages if needed */
2290         if (message__head + n + 1 > message__tail)
2291         {
2292                 /* Grab new "tail" */
2293                 message__tail = message__head + n + 1;
2294
2295                 /* Advance tail while possible past first "nul" */
2296                 while (message__buf[message__tail-1]) message__tail++;
2297
2298                 /* Kill all "dead" messages */
2299                 for (i = message__last; TRUE; i++)
2300                 {
2301                         /* Wrap if needed */
2302                         if (i == MESSAGE_MAX) i = 0;
2303
2304                         /* Stop before the new message */
2305                         if (i == message__next) break;
2306
2307                         /* Kill "dead" messages */
2308                         if ((message__ptr[i] >= message__head) &&
2309                                 (message__ptr[i] < message__tail))
2310                         {
2311                                 /* Track oldest message */
2312                                 message__last = i + 1;
2313                         }
2314                 }
2315         }
2316
2317
2318         /*** Step 5 -- Grab a new message index ***/
2319
2320         /* Get the next message index, advance */
2321         x = message__next++;
2322
2323         /* Handle wrap */
2324         if (message__next == MESSAGE_MAX) message__next = 0;
2325
2326         /* Kill last message if needed */
2327         if (message__next == message__last) message__last++;
2328
2329         /* Handle wrap */
2330         if (message__last == MESSAGE_MAX) message__last = 0;
2331
2332
2333
2334         /*** Step 6 -- Insert the message text ***/
2335
2336         /* Assign the starting address */
2337         message__ptr[x] = message__head;
2338
2339         /* Append the new part of the message */
2340         for (i = 0; i < n; i++)
2341         {
2342                 /* Copy the message */
2343                 message__buf[message__head + i] = str[i];
2344         }
2345
2346         /* Terminate */
2347         message__buf[message__head + i] = '\0';
2348
2349         /* Advance the "head" pointer */
2350         message__head += n + 1;
2351
2352         /* recursively add splitted message (added by Mogami) */
2353  end_of_message_add:
2354         if (splitted2 != NULL)
2355           message_add(splitted2);
2356 }
2357
2358
2359
2360 /*
2361  * Hack -- flush
2362  */
2363 static void msg_flush(int x)
2364 {
2365         byte a = TERM_L_BLUE;
2366         bool nagasu = FALSE;
2367
2368         if ((auto_more && !now_damaged) || num_more < 0){
2369                 int i;
2370                 for (i = 0; i < 8; i++)
2371                 {
2372                         if (angband_term[i] && (window_flag[i] & PW_MESSAGE)) break;
2373                 }
2374                 if (i < 8)
2375                 {
2376                         if (num_more < angband_term[i]->hgt) nagasu = TRUE;
2377                 }
2378                 else
2379                 {
2380                         nagasu = TRUE;
2381                 }
2382         }
2383         now_damaged = FALSE;
2384
2385         if (!nagasu)
2386         {
2387                 /* Pause for response */
2388 #ifdef JP
2389                 Term_putstr(x, 0, -1, a, "-³¤¯-");
2390 #else
2391                 Term_putstr(x, 0, -1, a, "-more-");
2392 #endif
2393
2394
2395                 /* Get an acceptable keypress */
2396                 while (1)
2397                 {
2398                         int cmd = inkey();
2399                         if (cmd == ESCAPE) {
2400                             num_more = -9999; /*auto_more¤Î¤È¤­¡¢Á´¤Æή¤¹¡£*/
2401                             break;
2402                         } else if (cmd == ' ') {
2403                             num_more = 0; /*£±²èÌ̤À¤±Î®¤¹¡£*/
2404                             break;
2405                         } else if ((cmd == '\n') || (cmd == '\r')) {
2406                             num_more--; /*£±¹Ô¤À¤±Î®¤¹¡£*/
2407                             break;
2408                         }
2409                         if (quick_messages) break;
2410                         bell();
2411                 }
2412         }
2413
2414         /* Clear the line */
2415         Term_erase(0, 0, 255);
2416 }
2417
2418
2419 /*
2420  * Output a message to the top line of the screen.
2421  *
2422  * Break long messages into multiple pieces (40-72 chars).
2423  *
2424  * Allow multiple short messages to "share" the top line.
2425  *
2426  * Prompt the user to make sure he has a chance to read them.
2427  *
2428  * These messages are memorized for later reference (see above).
2429  *
2430  * We could do "Term_fresh()" to provide "flicker" if needed.
2431  *
2432  * The global "msg_flag" variable can be cleared to tell us to
2433  * "erase" any "pending" messages still on the screen.
2434  *
2435  * XXX XXX XXX Note that we must be very careful about using the
2436  * "msg_print()" functions without explicitly calling the special
2437  * "msg_print(NULL)" function, since this may result in the loss
2438  * of information if the screen is cleared, or if anything is
2439  * displayed on the top line.
2440  *
2441  * XXX XXX XXX Note that "msg_print(NULL)" will clear the top line
2442  * even if no messages are pending.  This is probably a hack.
2443  */
2444 void msg_print(cptr msg)
2445 {
2446         static int p = 0;
2447
2448         int n;
2449
2450         char *t;
2451
2452         char buf[1024];
2453
2454         if (world_monster) return;
2455
2456         /* Hack -- Reset */
2457         if (!msg_flag) {
2458                 /* Clear the line */
2459                 Term_erase(0, 0, 255);
2460                 p = 0;
2461         }
2462
2463         /* Message Length */
2464         n = (msg ? strlen(msg) : 0);
2465
2466         /* Hack -- flush when requested or needed */
2467         if (p && (!msg || ((p + n) > 72)))
2468         {
2469                 /* Flush */
2470                 msg_flush(p);
2471
2472                 /* Forget it */
2473                 msg_flag = FALSE;
2474
2475                 /* Reset */
2476                 p = 0;
2477         }
2478
2479
2480         /* No message */
2481         if (!msg) return;
2482
2483         /* Paranoia */
2484         if (n > 1000) return;
2485
2486
2487         /* Memorize the message */
2488         if (character_generated) message_add(msg);
2489
2490
2491         /* Copy it */
2492         strcpy(buf, msg);
2493
2494         /* Analyze the buffer */
2495         t = buf;
2496
2497         /* Split message */
2498         while (n > 72)
2499         {
2500                 char oops;
2501                 int check, split = 72;
2502
2503 #ifdef JP
2504                 bool k_flag = FALSE;
2505                 int wordlen = 0;
2506
2507                 /* Find the "best" split point */
2508                 for (check = 0; check < 72; check++)
2509                 {
2510                         if (k_flag)
2511                         {
2512                                 k_flag = FALSE;
2513                                 continue;
2514                         }
2515
2516                         /* Found a valid split point */
2517                         if (iskanji(t[check]))
2518                         {
2519                                 k_flag = TRUE;
2520                                 split = check;
2521                         }
2522                         else if (t[check] == ' ')
2523                         {
2524                                 split = check;
2525                                 wordlen = 0;
2526                         }
2527                         else
2528                         {
2529                                 wordlen++;
2530                                 if (wordlen > 20)
2531                                         split = check;
2532                         }
2533                 }
2534 #else
2535                 /* Find the "best" split point */
2536                 for (check = 40; check < 72; check++)
2537                 {
2538                         /* Found a valid split point */
2539                         if (t[check] == ' ') split = check;
2540                 }
2541 #endif
2542
2543                 /* Save the split character */
2544                 oops = t[split];
2545
2546                 /* Split the message */
2547                 t[split] = '\0';
2548
2549                 /* Display part of the message */
2550                 Term_putstr(0, 0, split, TERM_WHITE, t);
2551
2552                 /* Flush it */
2553                 msg_flush(split + 1);
2554
2555                 /* Memorize the piece */
2556                 /* if (character_generated) message_add(t); */
2557
2558                 /* Restore the split character */
2559                 t[split] = oops;
2560
2561                 /* Insert a space */
2562                 t[--split] = ' ';
2563
2564                 /* Prepare to recurse on the rest of "buf" */
2565                 t += split; n -= split;
2566         }
2567
2568
2569         /* Display the tail of the message */
2570         Term_putstr(p, 0, n, TERM_WHITE, t);
2571
2572         /* Memorize the tail */
2573         /* if (character_generated) message_add(t); */
2574
2575         /* Window stuff */
2576         p_ptr->window |= (PW_MESSAGE);
2577         window_stuff();
2578
2579         /* Remember the message */
2580         msg_flag = TRUE;
2581
2582         /* Remember the position */
2583 #ifdef JP
2584         p += n;
2585 #else
2586         p += n + 1;
2587 #endif
2588
2589
2590         /* Optional refresh */
2591         if (fresh_message) Term_fresh();
2592 }
2593
2594
2595 /*
2596  * Hack -- prevent "accidents" in "screen_save()" or "screen_load()"
2597  */
2598 static int screen_depth = 0;
2599
2600
2601 /*
2602  * Save the screen, and increase the "icky" depth.
2603  *
2604  * This function must match exactly one call to "screen_load()".
2605  */
2606 void screen_save(void)
2607 {
2608         /* Hack -- Flush messages */
2609         msg_print(NULL);
2610
2611         /* Save the screen (if legal) */
2612         if (screen_depth++ == 0) Term_save();
2613
2614         /* Increase "icky" depth */
2615         character_icky++;
2616 }
2617
2618
2619 /*
2620  * Load the screen, and decrease the "icky" depth.
2621  *
2622  * This function must match exactly one call to "screen_save()".
2623  */
2624 void screen_load(void)
2625 {
2626         /* Hack -- Flush messages */
2627         msg_print(NULL);
2628
2629         /* Load the screen (if legal) */
2630         if (--screen_depth == 0) Term_load();
2631
2632         /* Decrease "icky" depth */
2633         character_icky--;
2634 }
2635
2636
2637 /*
2638  * Display a formatted message, using "vstrnfmt()" and "msg_print()".
2639  */
2640 void msg_format(cptr fmt, ...)
2641 {
2642         va_list vp;
2643
2644         char buf[1024];
2645
2646         /* Begin the Varargs Stuff */
2647         va_start(vp, fmt);
2648
2649         /* Format the args, save the length */
2650         (void)vstrnfmt(buf, 1024, fmt, vp);
2651
2652         /* End the Varargs Stuff */
2653         va_end(vp);
2654
2655         /* Display */
2656         msg_print(buf);
2657 }
2658
2659
2660
2661 /*
2662  * Display a string on the screen using an attribute.
2663  *
2664  * At the given location, using the given attribute, if allowed,
2665  * add the given string.  Do not clear the line.
2666  */
2667 void c_put_str(byte attr, cptr str, int row, int col)
2668 {
2669         /* Position cursor, Dump the attr/text */
2670         Term_putstr(col, row, -1, attr, str);
2671 }
2672
2673 /*
2674  * As above, but in "white"
2675  */
2676 void put_str(cptr str, int row, int col)
2677 {
2678         /* Spawn */
2679         Term_putstr(col, row, -1, TERM_WHITE, str);
2680 }
2681
2682
2683
2684 /*
2685  * Display a string on the screen using an attribute, and clear
2686  * to the end of the line.
2687  */
2688 void c_prt(byte attr, cptr str, int row, int col)
2689 {
2690         /* Clear line, position cursor */
2691         Term_erase(col, row, 255);
2692
2693         /* Dump the attr/text */
2694         Term_addstr(-1, attr, str);
2695 }
2696
2697 /*
2698  * As above, but in "white"
2699  */
2700 void prt(cptr str, int row, int col)
2701 {
2702         /* Spawn */
2703         c_prt(TERM_WHITE, str, row, col);
2704 }
2705
2706
2707
2708
2709 /*
2710  * Print some (colored) text to the screen at the current cursor position,
2711  * automatically "wrapping" existing text (at spaces) when necessary to
2712  * avoid placing any text into the last column, and clearing every line
2713  * before placing any text in that line.  Also, allow "newline" to force
2714  * a "wrap" to the next line.  Advance the cursor as needed so sequential
2715  * calls to this function will work correctly.
2716  *
2717  * Once this function has been called, the cursor should not be moved
2718  * until all the related "c_roff()" calls to the window are complete.
2719  *
2720  * This function will correctly handle any width up to the maximum legal
2721  * value of 256, though it works best for a standard 80 character width.
2722  */
2723 void c_roff(byte a, cptr str)
2724 {
2725         int x, y;
2726
2727         int w, h;
2728
2729         cptr s;
2730
2731         /* Obtain the size */
2732         (void)Term_get_size(&w, &h);
2733
2734         /* Obtain the cursor */
2735         (void)Term_locate(&x, &y);
2736
2737         /* Hack -- No more space */
2738         if( y == h - 1 && x > w - 3) return;
2739
2740         /* Process the string */
2741         for (s = str; *s; s++)
2742         {
2743                 char ch;
2744
2745 #ifdef JP
2746                 int k_flag = iskanji(*s);
2747 #endif
2748                 /* Force wrap */
2749                 if (*s == '\n')
2750                 {
2751                         /* Wrap */
2752                         x = 0;
2753                         y++;
2754
2755                         /* No more space */
2756                         if( y == h ) break;
2757
2758                         /* Clear line, move cursor */
2759                         Term_erase(x, y, 255);
2760                 }
2761
2762                 /* Clean up the char */
2763 #ifdef JP
2764                 ch = ((isprint(*s) || k_flag) ? *s : ' ');
2765 #else
2766                 ch = (isprint(*s) ? *s : ' ');
2767 #endif
2768
2769
2770                 /* Wrap words as needed */
2771 #ifdef JP
2772                 if (( x >= ( (k_flag) ? w - 2 : w - 1 ) ) && (ch != ' '))
2773 #else
2774                 if ((x >= w - 1) && (ch != ' '))
2775 #endif
2776
2777                 {
2778                         int i, n = 0;
2779
2780                         byte av[256];
2781                         char cv[256];
2782
2783                         /* Wrap word */
2784                         if (x < w)
2785 #ifdef JP
2786                         {
2787                         /* ¸½ºß¤¬È¾³Ñʸ»ú¤Î¾ì¹ç */
2788                         if( !k_flag )
2789 #endif
2790                         {
2791                                 /* Scan existing text */
2792                                 for (i = w - 2; i >= 0; i--)
2793                                 {
2794                                         /* Grab existing attr/char */
2795                                         Term_what(i, y, &av[i], &cv[i]);
2796
2797                                         /* Break on space */
2798                                         if (cv[i] == ' ') break;
2799
2800                                         /* Track current word */
2801                                         n = i;
2802 #ifdef JP
2803                                         if (cv[i] == '(') break;
2804 #endif
2805                                 }
2806                         }
2807
2808 #ifdef JP
2809                         else
2810                         {
2811                                 /* ¸½ºß¤¬Á´³Ñʸ»ú¤Î¤È¤­ */
2812                                 /* Ê¸Æ¬¤¬¡Ö¡£¡×¡Ö¡¢¡×Åù¤Ë¤Ê¤ë¤È¤­¤Ï¡¢¤½¤Î£±¤ÄÁ°¤Î¸ì¤Ç²þ¹Ô */
2813                                 if (strncmp(s, "¡£", 2) == 0 || strncmp(s, "¡¢", 2) == 0
2814 #if 0                   /* °ìÈÌŪ¤Ë¤Ï¡Ö¥£¡×¡Ö¡¼¡×¤Ï¶Ø§¤ÎÂоݳ° */
2815                                         || strncmp(s, "¥£", 2) == 0 || strncmp(s, "¡¼", 2) == 0
2816 #endif
2817                                ){
2818                                         Term_what(x  , y, &av[x  ], &cv[x  ]);
2819                                         Term_what(x-1, y, &av[x-1], &cv[x-1]);
2820                                         Term_what(x-2, y, &av[x-2], &cv[x-2]);
2821                                         n = x - 2;
2822                                         cv[ x ] = '\0';
2823                                 }
2824                         }
2825                         }
2826 #endif
2827                         /* Special case */
2828                         if (n == 0) n = w;
2829
2830                         /* Clear line */
2831                         Term_erase(n, y, 255);
2832
2833                         /* Wrap */
2834                         x = 0;
2835                         y++;
2836
2837                         /* No more space */
2838                         if( y == h ) break;
2839
2840                         /* Clear line, move cursor */
2841                         Term_erase(x, y, 255);
2842
2843                         /* Wrap the word (if any) */
2844                         for (i = n; i < w - 1; i++)
2845                         {
2846 #ifdef JP
2847                                 if( cv[i] == '\0' ) break;
2848 #endif
2849                                 /* Dump */
2850                                 Term_addch(av[i], cv[i]);
2851
2852                                 /* Advance (no wrap) */
2853                                 if (++x > w) x = w;
2854                         }
2855                 }
2856
2857                 /* Dump */
2858 #ifdef JP
2859                 Term_addch(a|0x10, ch);
2860 #else
2861                 Term_addch(a, ch);
2862 #endif
2863
2864
2865 #ifdef JP
2866                 if (k_flag)
2867                 {
2868                         s++;
2869                         x++;
2870                         ch = *s;
2871                         Term_addch(a|0x20, ch);
2872                 }
2873 #endif
2874                 /* Advance */
2875                 if (++x > w) x = w;
2876         }
2877 }
2878
2879 /*
2880  * As above, but in "white"
2881  */
2882 void roff(cptr str)
2883 {
2884         /* Spawn */
2885         c_roff(TERM_WHITE, str);
2886 }
2887
2888
2889
2890
2891 /*
2892  * Clear part of the screen
2893  */
2894 void clear_from(int row)
2895 {
2896         int y;
2897
2898         /* Erase requested rows */
2899         for (y = row; y < Term->hgt; y++)
2900         {
2901                 /* Erase part of the screen */
2902                 Term_erase(0, y, 255);
2903         }
2904 }
2905
2906
2907
2908
2909 /*
2910  * Get some input at the cursor location.
2911  * Assume the buffer is initialized to a default string.
2912  * Note that this string is often "empty" (see below).
2913  * The default buffer is displayed in yellow until cleared.
2914  * Pressing RETURN right away accepts the default entry.
2915  * Normal chars clear the default and append the char.
2916  * Backspace clears the default or deletes the final char.
2917  * ESCAPE clears the buffer and the window and returns FALSE.
2918  * RETURN accepts the current buffer contents and returns TRUE.
2919  */
2920 bool askfor_aux(char *buf, int len)
2921 {
2922         int y, x;
2923
2924         int i = 0;
2925
2926         int k = 0;
2927
2928         bool done = FALSE;
2929
2930
2931 #ifdef JP
2932     int k_flag[128];
2933 #endif
2934         /* Locate the cursor */
2935         Term_locate(&x, &y);
2936
2937
2938         /* Paranoia -- check len */
2939         if (len < 1) len = 1;
2940
2941         /* Paranoia -- check column */
2942         if ((x < 0) || (x >= 80)) x = 0;
2943
2944         /* Restrict the length */
2945         if (x + len > 80) len = 80 - x;
2946
2947
2948         /* Paranoia -- Clip the default entry */
2949         buf[len] = '\0';
2950
2951
2952         /* Display the default answer */
2953         Term_erase(x, y, len);
2954         Term_putstr(x, y, -1, TERM_YELLOW, buf);
2955
2956
2957         /* Process input */
2958         while (!done)
2959         {
2960                 /* Place cursor */
2961                 Term_gotoxy(x + k, y);
2962
2963                 /* Get a key */
2964                 i = inkey();
2965
2966                 /* Analyze the key */
2967                 switch (i)
2968                 {
2969                 case ESCAPE:
2970                         k = 0;
2971                         done = TRUE;
2972                         break;
2973
2974                 case '\n':
2975                 case '\r':
2976                         k = strlen(buf);
2977                         done = TRUE;
2978                         break;
2979
2980                 case 0x7F:
2981                 case '\010':
2982 #ifdef JP
2983                                 if (k > 0)
2984                                 {
2985                                         k--;
2986                                         if (k_flag[k] != 0)
2987                                                 k--;
2988                                 }
2989 #else
2990                         if (k > 0) k--;
2991 #endif
2992
2993                         break;
2994
2995                 default:
2996 #ifdef JP
2997        {                        /* ÊÒ»³¤µ¤óºîÀ® */
2998                 int next;
2999
3000                                 if (iskanji (i)) {
3001                                         inkey_base = TRUE;
3002                                         next = inkey ();
3003                                         if (k+1 < len) {
3004                                                 buf[k++] = i;
3005                                                 buf[k] = next;
3006                                                 k_flag[k++] = 1;
3007                                         } else
3008                                                 bell();
3009                                 } else {
3010 #ifdef SJIS
3011                     if(k<len && (isprint(i) || (0xa0<=i && i<=0xdf))){
3012 #else
3013                     if(k<len && isprint(i)){
3014 #endif
3015                                                 buf[k] = i;
3016                                                 k_flag[k++] = 0;
3017                                         } else
3018                                                 bell();
3019                                }
3020                  }
3021 #else
3022                         if ((k < len) && (isprint(i)))
3023                         {
3024                                 buf[k++] = i;
3025                         }
3026                         else
3027                         {
3028                                 bell();
3029                         }
3030 #endif
3031
3032                         break;
3033                 }
3034
3035                 /* Terminate */
3036                 buf[k] = '\0';
3037
3038                 /* Update the entry */
3039                 Term_erase(x, y, len);
3040                 Term_putstr(x, y, -1, TERM_WHITE, buf);
3041         }
3042
3043         /* Aborted */
3044         if (i == ESCAPE) return (FALSE);
3045
3046         /* Success */
3047         return (TRUE);
3048 }
3049
3050
3051 /*
3052  * Get a string from the user
3053  *
3054  * The "prompt" should take the form "Prompt: "
3055  *
3056  * Note that the initial contents of the string is used as
3057  * the default response, so be sure to "clear" it if needed.
3058  *
3059  * We clear the input, and return FALSE, on "ESCAPE".
3060  */
3061 bool get_string(cptr prompt, char *buf, int len)
3062 {
3063         bool res;
3064
3065         /* Paranoia XXX XXX XXX */
3066         msg_print(NULL);
3067
3068         /* Display prompt */
3069         prt(prompt, 0, 0);
3070
3071         /* Ask the user for a string */
3072         res = askfor_aux(buf, len);
3073
3074         /* Clear prompt */
3075         prt("", 0, 0);
3076
3077         /* Result */
3078         return (res);
3079 }
3080
3081
3082 /*
3083  * Verify something with the user
3084  *
3085  * The "prompt" should take the form "Query? "
3086  *
3087  * Note that "[y/n]" is appended to the prompt.
3088  */
3089 bool get_check(cptr prompt)
3090 {
3091         int i;
3092
3093         char buf[80];
3094
3095         if (auto_more)
3096         {
3097                 p_ptr->window |= PW_MESSAGE;
3098                 window_stuff();
3099                 num_more = 0;
3100         }
3101
3102         /* Paranoia XXX XXX XXX */
3103         msg_print(NULL);
3104
3105         /* Hack -- Build a "useful" prompt */
3106         (void)strnfmt(buf, 78, "%.70s[y/n] ", prompt);
3107
3108         /* Prompt for it */
3109         prt(buf, 0, 0);
3110
3111         /* Get an acceptable answer */
3112         while (TRUE)
3113         {
3114                 i = inkey();
3115 //              if (quick_messages) break;
3116                 if (i == ESCAPE) break;
3117                 if (strchr("YyNn", i)) break;
3118                 bell();
3119         }
3120
3121         /* Erase the prompt */
3122         prt("", 0, 0);
3123
3124         /* Normal negation */
3125         if ((i != 'Y') && (i != 'y')) return (FALSE);
3126
3127         /* Success */
3128         return (TRUE);
3129 }
3130
3131
3132 /*
3133  * Prompts for a keypress
3134  *
3135  * The "prompt" should take the form "Command: "
3136  *
3137  * Returns TRUE unless the character is "Escape"
3138  */
3139 bool get_com(cptr prompt, char *command, bool z_escape)
3140 {
3141         /* Paranoia XXX XXX XXX */
3142         msg_print(NULL);
3143
3144         /* Display a prompt */
3145         prt(prompt, 0, 0);
3146
3147         /* Get a key */
3148         *command = inkey();
3149
3150         /* Clear the prompt */
3151         prt("", 0, 0);
3152
3153         /* Handle "cancel" */
3154         if (*command == ESCAPE) return (FALSE);
3155         if (z_escape && ((*command == 'z') || (*command == 'Z'))) return (FALSE);
3156
3157         /* Success */
3158         return (TRUE);
3159 }
3160
3161
3162 /*
3163  * Request a "quantity" from the user
3164  *
3165  * Hack -- allow "command_arg" to specify a quantity
3166  */
3167 s16b get_quantity(cptr prompt, int max)
3168 {
3169         int amt;
3170
3171         char tmp[80];
3172
3173         char buf[80];
3174
3175
3176         /* Use "command_arg" */
3177         if (command_arg)
3178         {
3179                 /* Extract a number */
3180                 amt = command_arg;
3181
3182                 /* Clear "command_arg" */
3183                 command_arg = 0;
3184
3185                 /* Enforce the maximum */
3186                 if (amt > max) amt = max;
3187
3188                 /* Use it */
3189                 return (amt);
3190         }
3191
3192 #ifdef ALLOW_REPEAT /* TNB */
3193
3194         /* Get the item index */
3195         if ((max != 1) && repeat_pull(&amt))
3196         {
3197                 /* Enforce the maximum */
3198                 if (amt > max) amt = max;
3199
3200                 /* Enforce the minimum */
3201                 if (amt < 0) amt = 0;
3202
3203                 /* Use it */
3204                 return (amt);
3205         }
3206
3207 #endif /* ALLOW_REPEAT -- TNB */
3208
3209         /* Build a prompt if needed */
3210         if (!prompt)
3211         {
3212                 /* Build a prompt */
3213 #ifdef JP
3214                         sprintf(tmp, "¤¤¤¯¤Ä¤Ç¤¹¤« (1-%d): ", max);
3215 #else
3216                 sprintf(tmp, "Quantity (1-%d): ", max);
3217 #endif
3218
3219
3220                 /* Use that prompt */
3221                 prompt = tmp;
3222         }
3223
3224
3225         /* Default to one */
3226         amt = 1;
3227
3228         /* Build the default */
3229         sprintf(buf, "%d", amt);
3230
3231         /* Ask for a quantity */
3232         if (!get_string(prompt, buf, 6)) return (0);
3233
3234         /* Extract a number */
3235         amt = atoi(buf);
3236
3237         /* A letter means "all" */
3238         if (isalpha(buf[0])) amt = max;
3239
3240         /* Enforce the maximum */
3241         if (amt > max) amt = max;
3242
3243         /* Enforce the minimum */
3244         if (amt < 0) amt = 0;
3245
3246 #ifdef ALLOW_REPEAT /* TNB */
3247
3248         if (amt) repeat_push(amt);
3249
3250 #endif /* ALLOW_REPEAT -- TNB */
3251
3252         /* Return the result */
3253         return (amt);
3254 }
3255
3256
3257 /*
3258  * Pause for user response XXX XXX XXX
3259  */
3260 void pause_line(int row)
3261 {
3262         int i;
3263         prt("", row, 0);
3264 #ifdef JP
3265         put_str("[ ²¿¤«¥­¡¼¤ò²¡¤·¤Æ²¼¤µ¤¤ ]", row, 26);
3266 #else
3267         put_str("[Press any key to continue]", row, 23);
3268 #endif
3269
3270         i = inkey();
3271         prt("", row, 0);
3272 }
3273
3274
3275 /*
3276  * Hack -- special buffer to hold the action of the current keymap
3277  */
3278 static char request_command_buffer[256];
3279
3280
3281
3282 typedef struct
3283 {
3284         cptr name;
3285         byte cmd;
3286         bool fin;
3287 } menu_naiyou;
3288
3289 #ifdef JP
3290 menu_naiyou menu_info[10][10] =
3291 {
3292         {
3293                 {"ËâË¡/ÆüìǽÎÏ", 1, FALSE},
3294                 {"¹ÔÆ°", 2, FALSE},
3295                 {"Æ»¶ñ(»ÈÍÑ)", 3, FALSE},
3296                 {"Æ»¶ñ(¤½¤Î¾)", 4, FALSE},
3297                 {"ÁõÈ÷", 5, FALSE},
3298                 {"Èâ/È¢", 6, FALSE},
3299                 {"¾ðÊó", 7, FALSE},
3300                 {"ÀßÄê", 8, FALSE},
3301                 {"¤½¤Î¾", 9, FALSE},
3302                 {"", 0, FALSE},
3303         },
3304
3305         {
3306                 {"»È¤¦(m)", 'm', TRUE},
3307                 {"Ä´¤Ù¤ë(b/P)", 'b', TRUE},
3308                 {"³Ð¤¨¤ë(G)", 'G', TRUE},
3309                 {"ÆüìǽÎϤò»È¤¦(U/O)", 'U', TRUE},
3310                 {"", 0, FALSE},
3311                 {"", 0, FALSE},
3312                 {"", 0, FALSE},
3313                 {"", 0, FALSE},
3314                 {"", 0, FALSE},
3315                 {"", 0, FALSE}
3316         },
3317
3318         {
3319                 {"µÙ©¤¹¤ë(R)", 'R', TRUE},
3320                 {"¥È¥é¥Ã¥×²ò½ü(D)", 'D', TRUE},
3321                 {"õ¤¹(s)", 's', TRUE},
3322                 {"¼þ¤ê¤òÄ´¤Ù¤ë(l/x)", 'l', TRUE},
3323                 {"¥¿¡¼¥²¥Ã¥È»ØÄê(*)", '*', TRUE},
3324                 {"·ê¤ò·¡¤ë(T/^t)", 'T', TRUE},
3325                 {"³¬Ãʤò¾å¤ë(<)", '<', TRUE},
3326                 {"³¬Ãʤò²¼¤ê¤ë(>)", '>', TRUE},
3327                 {"¥Ú¥Ã¥È¤ËÌ¿Î᤹¤ë(p)", 'p', TRUE},
3328                 {"õº÷¥â¡¼¥É¤ÎON/OFF(S/#)", 'S', TRUE}
3329         },
3330
3331         {
3332                 {"Æɤà(r)", 'r', TRUE},
3333                 {"°û¤à(q)", 'q', TRUE},
3334                 {"¾ó¤ò»È¤¦(u/Z)", 'u', TRUE},
3335                 {"ËâË¡ËÀ¤ÇÁÀ¤¦(a/z)", 'a', TRUE},
3336                 {"¥í¥Ã¥É¤ò¿¶¤ë(z/a)", 'z', TRUE},
3337                 {"»ÏÆ°¤¹¤ë(A)", 'A', TRUE},
3338                 {"¿©¤Ù¤ë(E)", 'E', TRUE},
3339                 {"Èô¤ÓÆ»¶ñ¤Ç·â¤Ä(f/t)", 'f', TRUE},
3340                 {"Åꤲ¤ë(v)", 'v', TRUE},
3341                 {"", 0, FALSE}
3342         },
3343
3344         {
3345                 {"½¦¤¦(g)", 'g', TRUE},
3346                 {"Íî¤È¤¹(d)", 'd', TRUE},
3347                 {"²õ¤¹(k/^d)", 'k', TRUE},
3348                 {"Ìäò¹ï¤à({)", '{', TRUE},
3349                 {"Ìäò¾Ã¤¹(})", '}', TRUE},
3350                 {"Ä´ºº(I)", 'I', TRUE},
3351                 {"¥¢¥¤¥Æ¥à°ìÍ÷(i)", 'i', TRUE},
3352                 {"", 0, FALSE},
3353                 {"", 0, FALSE},
3354                 {"", 0, FALSE}
3355         },
3356
3357         {
3358                 {"ÁõÈ÷¤¹¤ë(w)", 'w', TRUE},
3359                 {"ÁõÈ÷¤ò³°¤¹(t/T)", 't', TRUE},
3360                 {"dzÎÁ¤òÊäµë(F)", 'F', TRUE},
3361                 {"ÁõÈ÷°ìÍ÷(e)", 'e', TRUE},
3362                 {"", 0, FALSE},
3363                 {"", 0, FALSE},
3364                 {"", 0, FALSE},
3365                 {"", 0, FALSE},
3366                 {"", 0, FALSE},
3367                 {"", 0, FALSE}
3368         },
3369
3370         {
3371                 {"³«¤±¤ë(o)", 'o', TRUE},
3372                 {"ÊĤ¸¤ë(c)", 'c', TRUE},
3373                 {"ÂÎÅö¤¿¤ê¤¹¤ë(B/f)", 'B', TRUE},
3374                 {"¤¯¤µ¤Ó¤òÂǤÄ(j/S)", 'j', TRUE},
3375                 {"", 0, FALSE},
3376                 {"", 0, FALSE},
3377                 {"", 0, FALSE},
3378                 {"", 0, FALSE},
3379                 {"", 0, FALSE},
3380                 {"", 0, FALSE}
3381         },
3382
3383         {
3384                 {"¥À¥ó¥¸¥ç¥ó¤ÎÁ´ÂοÞ(M)", 'M', TRUE},
3385                 {"°ÌÃÖ¤ò³Îǧ(L/W)", 'L', TRUE},
3386                 {"³¬¤ÎÊ·°Ïµ¤(^f)", KTRL('F'), TRUE},
3387                 {"¥¹¥Æ¡¼¥¿¥¹(C)", 'C', TRUE},
3388                 {"ʸ»ú¤ÎÀâÌÀ(/)", '/', TRUE},
3389                 {"¥á¥Ã¥»¡¼¥¸ÍúÎò(^p)", KTRL('P'), TRUE},
3390                 {"¸½ºß¤Î»þ¹ï(^t/')", KTRL('T'), TRUE},
3391                 {"¸½ºß¤ÎÃμ±(~)", '~', TRUE},
3392                 {"¥×¥ì¥¤µ­Ï¿(|)", '|', TRUE},
3393                 {"", 0, FALSE}
3394         },
3395
3396         {
3397                 {"¥ª¥×¥·¥ç¥ó(=)", '=', TRUE},
3398                 {"¥Þ¥¯¥í(@)", '@', TRUE},
3399                 {"²èÌÌɽ¼¨(%)", '%', TRUE},
3400                 {"¥«¥é¡¼(&)", '&', TRUE},
3401                 {"ÀßÄêÊѹ¹¥³¥Þ¥ó¥É(\")", '\"', TRUE},
3402                 {"¼«Æ°½¦¤¤¤ò¥í¡¼¥É($)", '$', TRUE},
3403                 {"¥·¥¹¥Æ¥à(!)", '!', TRUE},
3404                 {"", 0, FALSE},
3405                 {"", 0, FALSE},
3406                 {"", 0, FALSE}
3407         },
3408
3409         {
3410                 {"¥»¡¼¥Ö&ÃæÃÇ(^x)", KTRL('X'), TRUE},
3411                 {"¥»¡¼¥Ö(^s)", KTRL('S'), TRUE},
3412                 {"¥Ø¥ë¥×(?)", '?', TRUE},
3413                 {"ºÆÉÁ²è(^r)", KTRL('R'), TRUE},
3414                 {"¥á¥â(:)", ':', TRUE},
3415                 {"µ­Ç°»£±Æ())", ')', TRUE},
3416                 {"µ­Ç°»£±Æ¤Îɽ¼¨(()", '(', TRUE},
3417                 {"¥Ð¡¼¥¸¥ç¥ó¾ðÊó(V)", 'V', TRUE},
3418                 {"°úÂह¤ë(Q)", 'Q', TRUE},
3419                 {"", 0, FALSE}
3420         },
3421 };
3422 #else
3423 menu_naiyou menu_info[10][10] =
3424 {
3425         {
3426                 {"Magic/Special", 1, FALSE},
3427                 {"Action", 2, FALSE},
3428                 {"Items(use)", 3, FALSE},
3429                 {"Items(other)", 4, FALSE},
3430                 {"Equip", 5, FALSE},
3431                 {"Door/Box", 6, FALSE},
3432                 {"Infomations", 7, FALSE},
3433                 {"Options", 8, FALSE},
3434                 {"Other commands", 9, FALSE},
3435                 {"", 0, FALSE},
3436         },
3437
3438         {
3439                 {"Use(m)", 'm', TRUE},
3440                 {"See tips(b/P)", 'b', TRUE},
3441                 {"Study(G)", 'G', TRUE},
3442                 {"Special abilities(U/O)", 'U', TRUE},
3443                 {"", 0, FALSE},
3444                 {"", 0, FALSE},
3445                 {"", 0, FALSE},
3446                 {"", 0, FALSE},
3447                 {"", 0, FALSE},
3448                 {"", 0, FALSE}
3449         },
3450
3451         {
3452                 {"Rest(R)", 'R', TRUE},
3453                 {"Disarm a trap(D)", 'D', TRUE},
3454                 {"Search(s)", 's', TRUE},
3455                 {"Look(l/x)", 'l', TRUE},
3456                 {"Target(*)", '*', TRUE},
3457                 {"Dig(T/^t)", 'T', TRUE},
3458                 {"Go up stairs(<)", '<', TRUE},
3459                 {"Go down staies(>)", '>', TRUE},
3460                 {"Command pets(p)", 'p', TRUE},
3461                 {"Search mode ON/OFF(S/#)", 'S', TRUE}
3462         },
3463
3464         {
3465                 {"Read a scroll(r)", 'r', TRUE},
3466                 {"Drink a potion(q)", 'q', TRUE},
3467                 {"Use a staff(u/Z)", 'u', TRUE},
3468                 {"Aim a wand(a/z)", 'a', TRUE},
3469                 {"Zap a rod(z/a)", 'z', TRUE},
3470                 {"Activate an equipment(A)", 'A', TRUE},
3471                 {"Eat(E)", 'E', TRUE},
3472                 {"Fire missile weapon(f/t)", 'f', TRUE},
3473                 {"Throw an item(v)", 'v', TRUE},
3474                 {"", 0, FALSE}
3475         },
3476
3477         {
3478                 {"Get items(g)", 'g', TRUE},
3479                 {"Drop an item(d)", 'd', TRUE},
3480                 {"Destroy an item(k/^d)", 'k', TRUE},
3481                 {"Inscribe an item({)", '{', TRUE},
3482                 {"Uninscribe an item(})", '}', TRUE},
3483                 {"Info about an item(I)", 'I', TRUE},
3484                 {"Inventory list(i)", 'i', TRUE},
3485                 {"", 0, FALSE},
3486                 {"", 0, FALSE},
3487                 {"", 0, FALSE}
3488         },
3489
3490         {
3491                 {"Wear(w)", 'w', TRUE},
3492                 {"Take off(t/T)", 't', TRUE},
3493                 {"Refuel(F)", 'F', TRUE},
3494                 {"Equipment list(e)", 'e', TRUE},
3495                 {"", 0, FALSE},
3496                 {"", 0, FALSE},
3497                 {"", 0, FALSE},
3498                 {"", 0, FALSE},
3499                 {"", 0, FALSE},
3500                 {"", 0, FALSE}
3501         },
3502
3503         {
3504                 {"Open(o)", 'o', TRUE},
3505                 {"Close(c)", 'c', TRUE},
3506                 {"Bash a door(B/f)", 'B', TRUE},
3507                 {"Jam a door(j/S)", 'j', TRUE},
3508                 {"", 0, FALSE},
3509                 {"", 0, FALSE},
3510                 {"", 0, FALSE},
3511                 {"", 0, FALSE},
3512                 {"", 0, FALSE},
3513                 {"", 0, FALSE}
3514         },
3515
3516         {
3517                 {"Full map(M)", 'M', TRUE},
3518                 {"Map(L/W)", 'L', TRUE},
3519                 {"Level feeling(^f)", KTRL('F'), TRUE},
3520                 {"Character status(C)", 'C', TRUE},
3521                 {"Identify symbol(/)", '/', TRUE},
3522                 {"Show prev messages(^p)", KTRL('P'), TRUE},
3523                 {"Current time(^t/')", KTRL('T'), TRUE},
3524                 {"Various infomations(~)", '~', TRUE},
3525                 {"Play record menu(|)", '|', TRUE},
3526                 {"", 0, FALSE}
3527         },
3528
3529         {
3530                 {"Set options(=)", '=', TRUE},
3531                 {"Interact with macros(@)", '@', TRUE},
3532                 {"Interact w/ visuals(%)", '%', TRUE},
3533                 {"Interact with colors(&)", '&', TRUE},
3534                 {"Enter a user pref(\")", '\"', TRUE},
3535                 {"Reload auto-pick pref($)", '$', TRUE},
3536                 {"", 0, FALSE},
3537                 {"", 0, FALSE},
3538                 {"", 0, FALSE},
3539                 {"", 0, FALSE}
3540         },
3541
3542         {
3543                 {"Save and quit(^x)", KTRL('X'), TRUE},
3544                 {"Save(^s)", KTRL('S'), TRUE},
3545                 {"Help(obsoleted)(?)", '?', TRUE},
3546                 {"Redraw(^r)", KTRL('R'), TRUE},
3547                 {"Take note(:)", ':', TRUE},
3548                 {"Dump screen dump(()", ')', TRUE},
3549                 {"Load screen dump())", '(', TRUE},
3550                 {"Version info(V)", 'V', TRUE},
3551                 {"Quit(Q)", 'Q', TRUE},
3552                 {"", 0, FALSE}
3553         },
3554 };
3555 #endif
3556
3557 typedef struct
3558 {
3559         cptr name;
3560         byte window;
3561         byte number;
3562         byte jouken;
3563         byte jouken_naiyou;
3564 } special_menu_naiyou;
3565
3566 #define MENU_CLASS 1
3567 #define MENU_WILD 2
3568
3569 #ifdef JP
3570 special_menu_naiyou special_menu_info[] =
3571 {
3572         {"ĶǽÎÏ/ÆüìǽÎÏ", 0, 0, MENU_CLASS, CLASS_MINDCRAFTER},
3573         {"¤â¤Î¤Þ¤Í/ÆüìǽÎÏ", 0, 0, MENU_CLASS, CLASS_IMITATOR},
3574         {"ɬ»¦µ»/ÆüìǽÎÏ", 0, 0, MENU_CLASS, CLASS_SAMURAI},
3575         {"Îýµ¤½Ñ/ËâË¡/ÆüìǽÎÏ", 0, 0, MENU_CLASS, CLASS_FORCETRAINER},
3576         {"¶ÀËâË¡/ÆüìǽÎÏ", 0, 0, MENU_CLASS, CLASS_MIRROR_MASTER},
3577         {"¹­°è¥Þ¥Ã¥×(<)", 2, 6, MENU_WILD, FALSE},
3578         {"Ä̾ï¥Þ¥Ã¥×(>)", 2, 7, MENU_WILD, TRUE},
3579         {"", 0, 0, 0, 0},
3580 };
3581 #else
3582 special_menu_naiyou special_menu_info[] =
3583 {
3584         {"MindCraft/Special", 0, 0, MENU_CLASS, CLASS_MINDCRAFTER},
3585         {"Imitation/Special", 0, 0, MENU_CLASS, CLASS_IMITATOR},
3586         {"Technique/Special", 0, 0, MENU_CLASS, CLASS_SAMURAI},
3587         {"Mind/Magic/Special", 0, 0, MENU_CLASS, CLASS_FORCETRAINER},
3588         {"MirrorMagic/Special", 0, 0, MENU_CLASS, CLASS_MIRROR_MASTER},
3589         {"Enter global map(<)", 2, 6, MENU_WILD, FALSE},
3590         {"Enter local map(>)", 2, 7, MENU_WILD, TRUE},
3591         {"", 0, 0, 0, 0},
3592 };
3593 #endif
3594
3595 /*
3596  * Request a command from the user.
3597  *
3598  * Sets p_ptr->command_cmd, p_ptr->command_dir, p_ptr->command_rep,
3599  * p_ptr->command_arg.  May modify p_ptr->command_new.
3600  *
3601  * Note that "caret" ("^") is treated specially, and is used to
3602  * allow manual input of control characters.  This can be used
3603  * on many machines to request repeated tunneling (Ctrl-H) and
3604  * on the Macintosh to request "Control-Caret".
3605  *
3606  * Note that "backslash" is treated specially, and is used to bypass any
3607  * keymap entry for the following character.  This is useful for macros.
3608  *
3609  * Note that this command is used both in the dungeon and in
3610  * stores, and must be careful to work in both situations.
3611  *
3612  * Note that "p_ptr->command_new" may not work any more.  XXX XXX XXX
3613  */
3614 void request_command(int shopping)
3615 {
3616         int i;
3617
3618         unsigned char cmd;
3619
3620         int mode;
3621
3622         cptr act;
3623
3624 #ifdef JP
3625         int caretcmd = 0;
3626 #endif
3627         /* Roguelike */
3628         if (rogue_like_commands)
3629         {
3630                 mode = KEYMAP_MODE_ROGUE;
3631         }
3632
3633         /* Original */
3634         else
3635         {
3636                 mode = KEYMAP_MODE_ORIG;
3637         }
3638
3639
3640         /* No command yet */
3641         command_cmd = 0;
3642
3643         /* No "argument" yet */
3644         command_arg = 0;
3645
3646         /* No "direction" yet */
3647         command_dir = 0;
3648
3649         use_menu = FALSE;
3650
3651
3652         /* Get command */
3653         while (1)
3654         {
3655                 /* Hack -- auto-commands */
3656                 if (command_new)
3657                 {
3658                         /* Flush messages */
3659                         msg_print(NULL);
3660
3661                         /* Use auto-command */
3662                         cmd = (unsigned char)command_new;
3663
3664                         /* Forget it */
3665                         command_new = 0;
3666                 }
3667
3668                 /* Get a keypress in "command" mode */
3669                 else
3670                 {
3671                         char sub_cmd;
3672
3673                         /* Hack -- no flush needed */
3674                         msg_flag = FALSE;
3675                         num_more = 0;
3676
3677                         /* Activate "command mode" */
3678                         inkey_flag = TRUE;
3679
3680                         /* Get a command */
3681                         sub_cmd = inkey();
3682
3683                         if (!shopping && command_menu && ((sub_cmd == '\r') || (sub_cmd == 'x') || (sub_cmd == 'X'))
3684                             && !keymap_act[mode][(byte)(sub_cmd)])
3685                         {
3686                                 int basey, basex;
3687                                 int num = 0, max_num, old_num = 0;
3688                                 int menu = 0;
3689                                 bool kisuu;
3690
3691                                 if (py - panel_row_min > 10) basey = 2;
3692                                 else basey = 13;
3693                                 basex = 15;
3694
3695                                 /* Clear top line */
3696                                 prt("", 0, 0);
3697
3698                                 screen_save();
3699
3700                                 while(1)
3701                                 {
3702                                         cptr menu_name;
3703                                         if (!menu) old_num = num;
3704                                         put_str("+----------------------------------------------------+", basey, basex);
3705                                         put_str("|                                                    |", basey+1, basex);
3706                                         put_str("|                                                    |", basey+2, basex);
3707                                         put_str("|                                                    |", basey+3, basex);
3708                                         put_str("|                                                    |", basey+4, basex);
3709                                         put_str("|                                                    |", basey+5, basex);
3710                                         put_str("+----------------------------------------------------+", basey+6, basex);
3711
3712                                         for(i = 0; i < 10; i++)
3713                                         {
3714                                                 int hoge;
3715                                                 if (!menu_info[menu][i].cmd) break;
3716                                                 menu_name = menu_info[menu][i].name;
3717                                                 for(hoge = 0; ; hoge++)
3718                                                 {
3719                                                         if (!special_menu_info[hoge].name[0]) break;
3720                                                         if ((menu != special_menu_info[hoge].window) || (i != special_menu_info[hoge].number)) continue;
3721                                                         switch(special_menu_info[hoge].jouken)
3722                                                         {
3723                                                                 case MENU_CLASS:
3724                                                                 if (p_ptr->pclass == special_menu_info[hoge].jouken_naiyou) menu_name = special_menu_info[hoge].name;
3725                                                                 break;
3726                                                                 case MENU_WILD:
3727                                                                 if (!dun_level && !p_ptr->inside_arena && !p_ptr->inside_quest)
3728                                                                 {
3729                                                                         if ((byte)p_ptr->wild_mode == special_menu_info[hoge].jouken_naiyou) menu_name = special_menu_info[hoge].name;
3730                                                                 }
3731                                                                 break;
3732                                                                 default:
3733                                                                 break;
3734                                                         }
3735                                                 }
3736                                                 put_str(menu_name, basey + 1 + i / 2, basex + 4 + (i % 2) * 24);
3737                                         }
3738                                         max_num = i;
3739                                         kisuu = max_num % 2;
3740 #ifdef JP
3741                                         put_str("¡Õ",basey + 1 + num / 2, basex + 2 + (num % 2) * 24);
3742 #else
3743                                         put_str("> ",basey + 1 + num / 2, basex + 2 + (num % 2) * 24);
3744 #endif
3745
3746                                         /* Place the cursor on the player */
3747                                         move_cursor_relative(py, px);
3748
3749                                         /* Get a command */
3750                                         sub_cmd = inkey();
3751                                         if ((sub_cmd == ' ') || (sub_cmd == 'x') || (sub_cmd == 'X') || (sub_cmd == '\r'))
3752                                         {
3753                                                 if (menu_info[menu][num].fin)
3754                                                 {
3755                                                         cmd = menu_info[menu][num].cmd;
3756                                                         use_menu = TRUE;
3757                                                         break;
3758                                                 }
3759                                                 else
3760                                                 {
3761                                                         menu = menu_info[menu][num].cmd;
3762                                                         num = 0;
3763                                                         basey += 2;
3764                                                         basex += 8;
3765                                                 }
3766                                         }
3767                                         else if ((sub_cmd == ESCAPE) || (sub_cmd == 'z') || (sub_cmd == 'Z') || (sub_cmd == '0'))
3768                                         {
3769                                                 if (!menu)
3770                                                 {
3771                                                         cmd = ESCAPE;
3772                                                         break;
3773                                                 }
3774                                                 else
3775                                                 {
3776                                                         menu = 0;
3777                                                         num = old_num;
3778                                                         basey -= 2;
3779                                                         basex -= 8;
3780                                                         screen_load();
3781                                                         screen_save();
3782                                                 }
3783                                         }
3784                                         else if ((sub_cmd == '2') || (sub_cmd == 'j') || (sub_cmd == 'J'))
3785                                         {
3786                                                 if (kisuu)
3787                                                 {
3788                                                         if (num % 2)
3789                                                                 num = (num + 2) % (max_num - 1);
3790                                                         else
3791                                                                 num = (num + 2) % (max_num + 1);
3792                                                 }
3793                                                 else num = (num + 2) % max_num;
3794                                         }
3795                                         else if ((sub_cmd == '8') || (sub_cmd == 'k') || (sub_cmd == 'K'))
3796                                         {
3797                                                 if (kisuu)
3798                                                 {
3799                                                         if (num % 2)
3800                                                                 num = (num + max_num - 3) % (max_num - 1);
3801                                                         else
3802                                                                 num = (num + max_num - 1) % (max_num + 1);
3803                                                 }
3804                                                 else num = (num + max_num - 2) % max_num;
3805                                         }
3806                                         else if ((sub_cmd == '4') || (sub_cmd == '6') || (sub_cmd == 'h') || (sub_cmd == 'H') || (sub_cmd == 'l') || (sub_cmd == 'L'))
3807                                         {
3808                                                 if ((num % 2) || (num == max_num - 1))
3809                                                 {
3810                                                         num--;
3811                                                 }
3812                                                 else if (num < max_num - 1)
3813                                                 {
3814                                                         num++;
3815                                                 }
3816                                         }
3817                                 }
3818
3819                                 screen_load();
3820                                 if (!inkey_next) inkey_next = "";
3821                         }
3822                         else cmd = sub_cmd;
3823                 }
3824
3825                 /* Clear top line */
3826                 prt("", 0, 0);
3827
3828
3829                 /* Command Count */
3830                 if (cmd == '0')
3831                 {
3832                         int old_arg = command_arg;
3833
3834                         /* Reset */
3835                         command_arg = 0;
3836
3837                         /* Begin the input */
3838 #ifdef JP
3839                         prt("²ó¿ô: ", 0, 0);
3840 #else
3841                         prt("Count: ", 0, 0);
3842 #endif
3843
3844
3845                         /* Get a command count */
3846                         while (1)
3847                         {
3848                                 /* Get a new keypress */
3849                                 cmd = inkey();
3850
3851                                 /* Simple editing (delete or backspace) */
3852                                 if ((cmd == 0x7F) || (cmd == KTRL('H')))
3853                                 {
3854                                         /* Delete a digit */
3855                                         command_arg = command_arg / 10;
3856
3857                                         /* Show current count */
3858 #ifdef JP
3859                                         prt(format("²ó¿ô: %d", command_arg), 0, 0);
3860 #else
3861                                         prt(format("Count: %d", command_arg), 0, 0);
3862 #endif
3863
3864                                 }
3865
3866                                 /* Actual numeric data */
3867                                 else if (cmd >= '0' && cmd <= '9')
3868                                 {
3869                                         /* Stop count at 9999 */
3870                                         if (command_arg >= 1000)
3871                                         {
3872                                                 /* Warn */
3873                                                 bell();
3874
3875                                                 /* Limit */
3876                                                 command_arg = 9999;
3877                                         }
3878
3879                                         /* Increase count */
3880                                         else
3881                                         {
3882                                                 /* Incorporate that digit */
3883                                                 command_arg = command_arg * 10 + D2I(cmd);
3884                                         }
3885
3886                                         /* Show current count */
3887 #ifdef JP
3888                                         prt(format("²ó¿ô: %d", command_arg), 0, 0);
3889 #else
3890                                         prt(format("Count: %d", command_arg), 0, 0);
3891 #endif
3892
3893                                 }
3894
3895                                 /* Exit on "unusable" input */
3896                                 else
3897                                 {
3898                                         break;
3899                                 }
3900                         }
3901
3902                         /* Hack -- Handle "zero" */
3903                         if (command_arg == 0)
3904                         {
3905                                 /* Default to 99 */
3906                                 command_arg = 99;
3907
3908                                 /* Show current count */
3909 #ifdef JP
3910                                 prt(format("²ó¿ô: %d", command_arg), 0, 0);
3911 #else
3912                                 prt(format("Count: %d", command_arg), 0, 0);
3913 #endif
3914
3915                         }
3916
3917                         /* Hack -- Handle "old_arg" */
3918                         if (old_arg != 0)
3919                         {
3920                                 /* Restore old_arg */
3921                                 command_arg = old_arg;
3922
3923                                 /* Show current count */
3924 #ifdef JP
3925 prt(format("²ó¿ô: %d", command_arg), 0, 0);
3926 #else
3927                                 prt(format("Count: %d", command_arg), 0, 0);
3928 #endif
3929
3930                         }
3931
3932                         /* Hack -- white-space means "enter command now" */
3933                         if ((cmd == ' ') || (cmd == '\n') || (cmd == '\r'))
3934                         {
3935                                 /* Get a real command */
3936 #ifdef JP
3937                                 if (!get_com("¥³¥Þ¥ó¥É: ", &cmd, FALSE))
3938 #else
3939                                 if (!get_com("Command: ", &cmd, FALSE))
3940 #endif
3941
3942                                 {
3943                                         /* Clear count */
3944                                         command_arg = 0;
3945
3946                                         /* Continue */
3947                                         continue;
3948                                 }
3949                         }
3950                 }
3951
3952
3953                 /* Allow "keymaps" to be bypassed */
3954                 if (cmd == '\\')
3955                 {
3956                         /* Get a real command */
3957 #ifdef JP
3958                         (void)get_com("¥³¥Þ¥ó¥É: ", &cmd, FALSE);
3959 #else
3960                         (void)get_com("Command: ", &cmd, FALSE);
3961 #endif
3962
3963
3964                         /* Hack -- bypass keymaps */
3965                         if (!inkey_next) inkey_next = "";
3966                 }
3967
3968
3969                 /* Allow "control chars" to be entered */
3970                 if (cmd == '^')
3971                 {
3972                         /* Get a new command and controlify it */
3973 #ifdef JP
3974                         if (get_com("CTRL: ", &cmd, FALSE)) cmd = KTRL(cmd);
3975 #else
3976                         if (get_com("Control: ", &cmd, FALSE)) cmd = KTRL(cmd);
3977 #endif
3978
3979                 }
3980
3981
3982                 /* Look up applicable keymap */
3983                 act = keymap_act[mode][(byte)(cmd)];
3984
3985                 /* Apply keymap if not inside a keymap already */
3986                 if (act && !inkey_next)
3987                 {
3988                         /* Install the keymap (limited buffer size) */
3989                         (void)strnfmt(request_command_buffer, 256, "%s", act);
3990
3991                         /* Start using the buffer */
3992                         inkey_next = request_command_buffer;
3993
3994                         /* Continue */
3995                         continue;
3996                 }
3997
3998
3999                 /* Paranoia */
4000                 if (!cmd) continue;
4001
4002
4003                 /* Use command */
4004                 command_cmd = cmd;
4005
4006                 /* Done */
4007                 break;
4008         }
4009
4010         /* Hack -- Auto-repeat certain commands */
4011         if (always_repeat && (command_arg <= 0))
4012         {
4013                 /* Hack -- auto repeat certain commands */
4014                 if (strchr("TBDoc+", command_cmd))
4015                 {
4016                         /* Repeat 99 times */
4017                         command_arg = 99;
4018                 }
4019         }
4020
4021         /* Shopping */
4022         if (shopping == 1)
4023         {
4024                 /* Convert */
4025                 switch (command_cmd)
4026                 {
4027                         /* Command "p" -> "purchase" (get) */
4028                 case 'p': command_cmd = 'g'; break;
4029
4030                         /* Command "m" -> "purchase" (get) */
4031                 case 'm': command_cmd = 'g'; break;
4032
4033                         /* Command "s" -> "sell" (drop) */
4034                 case 's': command_cmd = 'd'; break;
4035                 }
4036         }
4037
4038 #ifdef JP
4039         for (i = 0; i < 256; i++)
4040         {
4041                 cptr s;
4042                 if ((s = keymap_act[mode][i]) != NULL)
4043                 {
4044                         if (*s == command_cmd && *(s+1) == 0)
4045                         {
4046                                 caretcmd = i;
4047                                 break;
4048                         }
4049                 }
4050         }
4051         if (!caretcmd)
4052                 caretcmd = command_cmd;
4053 #endif
4054         /* Hack -- Scan equipment */
4055         for (i = INVEN_RARM; i < INVEN_TOTAL; i++)
4056         {
4057                 cptr s;
4058
4059                 object_type *o_ptr = &inventory[i];
4060
4061                 /* Skip non-objects */
4062                 if (!o_ptr->k_idx) continue;
4063
4064                 /* No inscription */
4065                 if (!o_ptr->inscription) continue;
4066
4067                 /* Obtain the inscription */
4068                 s = quark_str(o_ptr->inscription);
4069
4070                 /* Find a '^' */
4071                 s = strchr(s, '^');
4072
4073                 /* Process preventions */
4074                 while (s)
4075                 {
4076                         /* Check the "restriction" character */
4077 #ifdef JP
4078                         if ((s[1] == caretcmd) || (s[1] == '*'))
4079 #else
4080                         if ((s[1] == command_cmd) || (s[1] == '*'))
4081 #endif
4082
4083                         {
4084                                 /* Hack -- Verify command */
4085 #ifdef JP
4086                                 if (!get_check("ËÜÅö¤Ç¤¹¤«? "))
4087 #else
4088                                 if (!get_check("Are you sure? "))
4089 #endif
4090
4091                                 {
4092                                         /* Hack -- Use space */
4093                                         command_cmd = ' ';
4094                                 }
4095                         }
4096
4097                         /* Find another '^' */
4098                         s = strchr(s + 1, '^');
4099                 }
4100         }
4101
4102
4103         /* Hack -- erase the message line. */
4104         prt("", 0, 0);
4105 }
4106
4107
4108
4109 /*
4110  * Check a char for "vowel-hood"
4111  */
4112 bool is_a_vowel(int ch)
4113 {
4114         switch (ch)
4115         {
4116         case 'a':
4117         case 'e':
4118         case 'i':
4119         case 'o':
4120         case 'u':
4121         case 'A':
4122         case 'E':
4123         case 'I':
4124         case 'O':
4125         case 'U':
4126                 return (TRUE);
4127         }
4128
4129         return (FALSE);
4130 }
4131
4132
4133
4134 #if 0
4135
4136 /*
4137  * Replace the first instance of "target" in "buf" with "insert"
4138  * If "insert" is NULL, just remove the first instance of "target"
4139  * In either case, return TRUE if "target" is found.
4140  *
4141  * XXX Could be made more efficient, especially in the
4142  * case where "insert" is smaller than "target".
4143  */
4144 static bool insert_str(char *buf, cptr target, cptr insert)
4145 {
4146         int   i, len;
4147         int                b_len, t_len, i_len;
4148
4149         /* Attempt to find the target (modify "buf") */
4150         buf = strstr(buf, target);
4151
4152         /* No target found */
4153         if (!buf) return (FALSE);
4154
4155         /* Be sure we have an insertion string */
4156         if (!insert) insert = "";
4157
4158         /* Extract some lengths */
4159         t_len = strlen(target);
4160         i_len = strlen(insert);
4161         b_len = strlen(buf);
4162
4163         /* How much "movement" do we need? */
4164         len = i_len - t_len;
4165
4166         /* We need less space (for insert) */
4167         if (len < 0)
4168         {
4169                 for (i = t_len; i < b_len; ++i) buf[i+len] = buf[i];
4170         }
4171
4172         /* We need more space (for insert) */
4173         else if (len > 0)
4174         {
4175                 for (i = b_len-1; i >= t_len; --i) buf[i+len] = buf[i];
4176         }
4177
4178         /* If movement occured, we need a new terminator */
4179         if (len) buf[b_len+len] = '\0';
4180
4181         /* Now copy the insertion string */
4182         for (i = 0; i < i_len; ++i) buf[i] = insert[i];
4183
4184         /* Successful operation */
4185         return (TRUE);
4186 }
4187
4188
4189 #endif
4190
4191
4192 /*
4193  * GH
4194  * Called from cmd4.c and a few other places. Just extracts
4195  * a direction from the keymap for ch (the last direction,
4196  * in fact) byte or char here? I'm thinking that keymaps should
4197  * generally only apply to single keys, which makes it no more
4198  * than 128, so a char should suffice... but keymap_act is 256...
4199  */
4200 int get_keymap_dir(char ch)
4201 {
4202         cptr act, s;
4203         int d = 0;
4204
4205         if (rogue_like_commands)
4206         {
4207                 act = keymap_act[KEYMAP_MODE_ROGUE][(byte)ch];
4208         }
4209         else
4210         {
4211                 act = keymap_act[KEYMAP_MODE_ORIG][(byte)ch];
4212         }
4213
4214         if (act)
4215         {
4216                 /* Convert to a direction */
4217                 for (s = act; *s; ++s)
4218                 {
4219                         /* Use any digits in keymap */
4220                         if (isdigit(*s)) d = D2I(*s);
4221                 }
4222         }
4223         return d;
4224 }
4225
4226
4227 #ifdef ALLOW_REPEAT /* TNB */
4228
4229 #define REPEAT_MAX              20
4230
4231 /* Number of chars saved */
4232 static int repeat__cnt = 0;
4233
4234 /* Current index */
4235 static int repeat__idx = 0;
4236
4237 /* Saved "stuff" */
4238 static int repeat__key[REPEAT_MAX];
4239
4240
4241 void repeat_push(int what)
4242 {
4243         /* Too many keys */
4244         if (repeat__cnt == REPEAT_MAX) return;
4245
4246         /* Push the "stuff" */
4247         repeat__key[repeat__cnt++] = what;
4248
4249         /* Prevents us from pulling keys */
4250         ++repeat__idx;
4251 }
4252
4253
4254 bool repeat_pull(int *what)
4255 {
4256         /* All out of keys */
4257         if (repeat__idx == repeat__cnt) return (FALSE);
4258
4259         /* Grab the next key, advance */
4260         *what = repeat__key[repeat__idx++];
4261
4262         /* Success */
4263         return (TRUE);
4264 }
4265
4266 void repeat_check(void)
4267 {
4268         int             what;
4269
4270         /* Ignore some commands */
4271         if (command_cmd == ESCAPE) return;
4272         if (command_cmd == ' ') return;
4273         if (command_cmd == '\r') return;
4274         if (command_cmd == '\n') return;
4275
4276         /* Repeat Last Command */
4277         if (command_cmd == 'n')
4278         {
4279                 /* Reset */
4280                 repeat__idx = 0;
4281
4282                 /* Get the command */
4283                 if (repeat_pull(&what))
4284                 {
4285                         /* Save the command */
4286                         command_cmd = what;
4287                 }
4288         }
4289
4290         /* Start saving new command */
4291         else
4292         {
4293                 /* Reset */
4294                 repeat__cnt = 0;
4295                 repeat__idx = 0;
4296
4297                 what = command_cmd;
4298
4299                 /* Save this command */
4300                 repeat_push(what);
4301         }
4302 }
4303
4304 #endif /* ALLOW_REPEAT -- TNB */
4305
4306
4307 #ifdef SORT_R_INFO
4308
4309 /*
4310  * Array size for which InsertionSort
4311  * is used instead of QuickSort
4312  */
4313 #define CUTOFF 4
4314
4315
4316 /*
4317  * Exchange two sort-entries
4318  * (should probably be coded inline
4319  * for speed increase)
4320  */
4321 static void swap(tag_type *a, tag_type *b)
4322 {
4323         tag_type temp;
4324
4325         temp.tag = a->tag;
4326         temp.pointer = a->pointer;
4327
4328         a->tag = b->tag;
4329         a->pointer = b->pointer;
4330
4331         b->tag = temp.tag;
4332         b->pointer = temp.pointer;
4333 }
4334
4335
4336 /*
4337  * Insertion-Sort algorithm
4338  * (used by the Quicksort algorithm)
4339  */
4340 static void InsertionSort(tag_type elements[], int number)
4341 {
4342         int j, P;
4343
4344         tag_type tmp;
4345
4346         for (P = 1; P < number; P++)
4347         {
4348                 tmp = elements[P];
4349                 for (j = P; (j > 0) && (elements[j - 1].tag > tmp.tag); j--)
4350                         elements[j] = elements[j - 1];
4351                 elements[j] = tmp;
4352         }
4353 }
4354
4355
4356 /*
4357  * Helper function for Quicksort
4358  */
4359 static tag_type median3(tag_type elements[], int left, int right)
4360 {
4361         int center = (left + right) / 2;
4362
4363         if (elements[left].tag > elements[center].tag)
4364                 swap(&elements[left], &elements[center]);
4365         if (elements[left].tag > elements[right].tag)
4366                 swap(&elements[left], &elements[right]);
4367         if (elements[center].tag > elements[right].tag)
4368                 swap(&elements[center], &elements[right]);
4369
4370         swap(&elements[center], &elements[right - 1]);
4371         return (elements[right - 1]);
4372 }
4373
4374
4375 /*
4376  * Quicksort algorithm
4377  *
4378  * The "median of three" pivot selection eliminates
4379  * the bad case of already sorted input.
4380  *
4381  * We use InsertionSort for smaller sub-arrays,
4382  * because it is faster in this case.
4383  *
4384  * For details see: "Data Structures and Algorithm
4385  * Analysis in C" by Mark Allen Weiss.
4386  */
4387 static void quicksort(tag_type elements[], int left, int right)
4388 {
4389         int i, j;
4390         tag_type pivot;
4391
4392         if (left + CUTOFF <= right)
4393         {
4394                 pivot = median3(elements, left, right);
4395
4396                 i = left; j = right -1;
4397
4398                 while (TRUE)
4399                 {
4400                         while (elements[++i].tag < pivot.tag);
4401                         while (elements[--j].tag > pivot.tag);
4402
4403                         if (i < j)
4404                                 swap(&elements[i], &elements[j]);
4405                         else
4406                                 break;
4407                 }
4408
4409                 /* Restore pivot */
4410                 swap(&elements[i], &elements[right - 1]);
4411
4412                 quicksort(elements, left, i - 1);
4413                 quicksort(elements, i + 1, right);
4414         }
4415         else
4416         {
4417                 /* Use InsertionSort on small arrays */
4418                 InsertionSort(elements + left, right - left + 1);
4419         }
4420 }
4421
4422
4423 /*
4424  * Frontend for the sorting algorithm
4425  *
4426  * Sorts an array of tagged pointers
4427  * with <number> elements.
4428  */
4429 void tag_sort(tag_type elements[], int number)
4430 {
4431         quicksort(elements, 0, number - 1);
4432 }
4433
4434 #endif /* SORT_R_INFO */
4435
4436 #ifdef SUPPORT_GAMMA
4437
4438 /* Table of gamma values */
4439 byte gamma_table[256];
4440
4441 /* Table of ln(x/256) * 256 for x going from 0 -> 255 */
4442 static s16b gamma_helper[256] =
4443 {
4444 0,-1420,-1242,-1138,-1065,-1007,-961,-921,-887,-857,-830,-806,-783,-762,-744,-726,
4445 -710,-694,-679,-666,-652,-640,-628,-617,-606,-596,-586,-576,-567,-577,-549,-541,
4446 -532,-525,-517,-509,-502,-495,-488,-482,-475,-469,-463,-457,-451,-455,-439,-434,
4447 -429,-423,-418,-413,-408,-403,-398,-394,-389,-385,-380,-376,-371,-367,-363,-359,
4448 -355,-351,-347,-343,-339,-336,-332,-328,-325,-321,-318,-314,-311,-308,-304,-301,
4449 -298,-295,-291,-288,-285,-282,-279,-276,-273,-271,-268,-265,-262,-259,-257,-254,
4450 -251,-248,-246,-243,-241,-238,-236,-233,-231,-228,-226,-223,-221,-219,-216,-214,
4451 -212,-209,-207,-205,-203,-200,-198,-196,-194,-192,-190,-188,-186,-184,-182,-180,
4452 -178,-176,-174,-172,-170,-168,-166,-164,-162,-160,-158,-156,-155,-153,-151,-149,
4453 -147,-146,-144,-142,-140,-139,-137,-135,-134,-132,-130,-128,-127,-125,-124,-122,
4454 -120,-119,-117,-116,-114,-112,-111,-109,-108,-106,-105,-103,-102,-100,-99,-97,
4455 -96,-95,-93,-92,-90,-89,-87,-86,-85,-83,-82,-80,-79,-78,-76,-75,
4456 -74,-72,-71,-70,-68,-67,-66,-65,-63,-62,-61,-59,-58,-57,-56,-54,
4457 -53,-52,-51,-50,-48,-47,-46,-45,-44,-42,-41,-40,-39,-38,-37,-35,
4458 -34,-33,-32,-31,-30,-29,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,
4459 -17,-16,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1
4460 };
4461
4462
4463 /* 
4464  * Build the gamma table so that floating point isn't needed.
4465  * 
4466  * Note gamma goes from 0->256.  The old value of 100 is now 128.
4467  */
4468 void build_gamma_table(int gamma)
4469 {
4470         int i, n;
4471         
4472         /*
4473          * value is the current sum.
4474          * diff is the new term to add to the series.
4475          */
4476         long value, diff;
4477         
4478         /* Hack - convergence is bad in these cases. */
4479         gamma_table[0] = 0;
4480         gamma_table[255] = 255;
4481         
4482         for (i = 1; i < 255; i++)
4483         {
4484                 /* 
4485                  * Initialise the Taylor series
4486                  *
4487                  * value and diff have been scaled by 256
4488                  */
4489                 
4490                 n = 1;
4491                 value = 256 * 256;
4492                 diff = ((long)gamma_helper[i]) * (gamma - 256);
4493                 
4494                 while (diff)
4495                 {
4496                         value += diff;
4497                         n++;
4498                         
4499                         
4500                         /*
4501                          * Use the following identiy to calculate the gamma table.
4502                          * exp(x) = 1 + x + x^2/2 + x^3/(2*3) + x^4/(2*3*4) +...
4503                          *
4504                          * n is the current term number.
4505                          * 
4506                          * The gamma_helper array contains a table of
4507                          * ln(x/256) * 256
4508                          * This is used because a^b = exp(b*ln(a))
4509                          *
4510                          * In this case:
4511                          * a is i / 256
4512                          * b is gamma.
4513                          *
4514                          * Note that everything is scaled by 256 for accuracy,
4515                          * plus another factor of 256 for the final result to
4516                          * be from 0-255.  Thus gamma_helper[] * gamma must be
4517                          * divided by 256*256 each itteration, to get back to
4518                          * the original power series.
4519                          */
4520                         diff = (((diff / 256) * gamma_helper[i]) * (gamma - 256)) / (256 * n);
4521                 }
4522                 
4523                 /* 
4524                  * Store the value in the table so that the
4525                  * floating point pow function isn't needed .
4526                  */
4527                 gamma_table[i] = ((long)(value / 256) * i) / 256;
4528         }
4529 }
4530
4531 #endif /* SUPPORT_GAMMA */
4532
4533 void roff_to_buf(cptr str, int maxlen, char *tbuf)
4534 {
4535         int read_pt = 0;
4536         int write_pt = 0;
4537         int line_len = 0;
4538         int word_punct = 0;
4539         unsigned char ch[3];
4540         ch[2] = '\0';
4541
4542         while (str[read_pt])
4543         {
4544 #ifdef JP
4545                 bool kanji;
4546 #endif
4547                 ch[0] = str[read_pt];
4548                 ch[1] = '\0';
4549 #ifdef JP
4550                 kanji  = iskanji(ch[0]);
4551                 if (kanji)
4552                         ch[1] = str[read_pt+1];
4553                 if (!kanji && !isprint(ch[0]))
4554                         ch[0] = ' ';
4555 #else
4556                 if (!isprint(ch[0]))
4557                         ch[0] = ' ';
4558 #endif
4559
4560                 if (line_len >= maxlen || str[read_pt] == '\n')
4561                 {
4562                         int word_len;
4563
4564                         /* return to better wrapping point. */
4565                         /* Space character at the end of the line need not to be printed. */
4566                         word_len = read_pt - word_punct;
4567                         if (ch[0] != ' ' && word_len < line_len/2)
4568                         {
4569                                 read_pt = word_punct;
4570                                 if (str[word_punct] == ' ')
4571                                         read_pt++;
4572                                 write_pt -= word_len;
4573                         }
4574                         else
4575                                 read_pt++;
4576                         tbuf[write_pt++] = '\0';
4577                         line_len = 0;
4578                         word_punct = read_pt;
4579                         continue;
4580                 }
4581                 if (ch[0] == ' ')
4582                         word_punct = read_pt;
4583 #ifdef JP
4584                 if (kanji &&
4585                     strcmp(ch, "¡£") != 0 && strcmp(ch, "¡¢") != 0 &&
4586                     strcmp(ch, "¥£") != 0 && strcmp(ch, "¡¼") != 0)
4587                         word_punct = read_pt;
4588 #endif
4589                 tbuf[write_pt++] = ch[0];
4590                 line_len++;
4591                 read_pt++;
4592 #ifdef JP
4593                 if (kanji)
4594                 {
4595                         tbuf[write_pt++] = ch[1];
4596                         line_len++;
4597                         read_pt++;
4598                 }
4599 #endif
4600         }
4601         tbuf[write_pt] = '\0';
4602         tbuf[write_pt+1] = '\0';
4603
4604         return;
4605 }