OSDN Git Service

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