OSDN Git Service

広域マップで画面をスクロールすると右端の境界の外までスクロールできてしまうバグ修正。
[hengbandforosx/hengbandosx.git] / src / util.c
index c5cff8f..66b3a53 100644 (file)
 
 static int num_more = 0;
 
-#ifndef HAS_MEMSET
-
-/*
- * For those systems that don't have "memset()"
- *
- * Set the value of each of 'n' bytes starting at 's' to 'c', return 's'
- * If 'n' is negative, you will erase a whole lot of memory.
- */
-char *memset(char *s, int c, huge n)
-{
-       char *t;
-       for (t = s; len--; ) *t++ = c;
-       return (s);
-}
-
-#endif
-
-
 #if 0
 #ifndef HAS_STRICMP
 
@@ -57,7 +39,7 @@ int stricmp(cptr a, cptr b)
 
 #ifdef SET_UID
 
-# ifndef HAS_USLEEP
+# ifndef HAVE_USLEEP
 
 /*
  * For those systems that don't have "usleep()" but need it.
@@ -109,10 +91,12 @@ int usleep(huge usecs)
 
 
 /*
-* Hack -- External functions
-*/
-extern struct passwd *getpwuid();
-extern struct passwd *getpwnam();
+ * Hack -- External functions
+ */
+#ifdef SET_UID
+extern struct passwd *getpwuid(uid_t uid);
+extern struct passwd *getpwnam(const char *name);
+#endif
 
 
 /*
@@ -120,7 +104,6 @@ extern struct passwd *getpwnam();
  */
 void user_name(char *buf, int id)
 {
-#ifdef SET_UID
        struct passwd *pw;
 
        /* Look up the user name */
@@ -140,7 +123,6 @@ void user_name(char *buf, int id)
 
                return;
        }
-#endif /* SET_UID */
 
        /* Oops.  Hack -- default to "PLAYER" */
        strcpy(buf, "PLAYER");
@@ -363,9 +345,23 @@ FILE *my_fopen(cptr file, cptr mode)
 {
        char buf[1024];
 
+#if defined(MACINTOSH) && defined(MAC_MPW)
+       FILE *tempfff;
+#endif
+
        /* Hack -- Try to parse the path */
        if (path_parse(buf, 1024, file)) return (NULL);
 
+#if defined(MACINTOSH) && defined(MAC_MPW)
+       if (strchr(mode, 'w'))
+       {
+               /* setting file type/creator */
+               tempfff = fopen(buf, mode);
+               fsetfileinfo(file, _fcreator, _ftype);
+               fclose(tempfff);
+       }
+#endif
+
        /* Attempt to fopen the file anyway */
        return (fopen(buf, mode));
 }
@@ -685,8 +681,20 @@ int fd_make(cptr file, int mode)
 
 #else /* BEN_HACK */
 
+# if defined(MACINTOSH) && defined(MAC_MPW)
+
+       /* setting file type and creator -- AR */
+       {
+               errr errr_tmp;
+               errr_tmp = open(buf, O_CREAT | O_EXCL | O_WRONLY | O_BINARY, mode);
+               fsetfileinfo(file, _fcreator, _ftype);
+               return(errr_tmp);
+       }
+
+# else
        /* Create the file, fail if exists, write-only, binary */
        return (open(buf, O_CREAT | O_EXCL | O_WRONLY | O_BINARY, mode));
+# endif
 
 #endif /* BEN_HACK */
 
@@ -788,9 +796,6 @@ errr fd_seek(int fd, huge n)
        p = lseek(fd, n, SEEK_SET);
 
        /* Failure */
-       if (p < 0) return (1);
-
-       /* Failure */
        if (p != n) return (1);
 
        /* Success */
@@ -1076,8 +1081,20 @@ static void trigger_text_to_ascii(char **bufptr, cptr *strptr)
                        break;
                }
        }
+
+       /* Invalid trigger name? */
        if (i == max_macrotrigger)
+       {
+               str = strchr(str, ']');
+               if (str)
+               {
+                       *s++ = (char)31;
+                       *s++ = '\r';
+                       *bufptr = s;
+                       *strptr = str; /* where **strptr == ']' */
+               }
                return;
+       }
        key_code = macro_trigger_keycode[shiftstatus][i];
        str += len;
 
@@ -1104,7 +1121,7 @@ static void trigger_text_to_ascii(char **bufptr, cptr *strptr)
                        break;
                }
        }
-       *s++ = (char)13;
+       *s++ = '\r';
 
        *bufptr = s;
        *strptr = str; /* where **strptr == ']' */
@@ -1132,7 +1149,7 @@ void text_to_ascii(char *buf, cptr str)
                        /* Skip the backslash */
                        str++;
 
-                        /* Macro Trigger */
+                       /* Macro Trigger */
                        if (*str == '[')
                        {
                                trigger_text_to_ascii(&s, &str);
@@ -1245,7 +1262,7 @@ void text_to_ascii(char *buf, cptr str)
 }
 
 
-bool trigger_ascii_to_text(char **bufptr, cptr *strptr)
+static bool trigger_ascii_to_text(char **bufptr, cptr *strptr)
 {
        char *s = *bufptr;
        cptr str = *strptr;
@@ -1276,7 +1293,7 @@ bool trigger_ascii_to_text(char **bufptr, cptr *strptr)
                        }
                        break;
                case '#':
-                       for (j = 0; *str && *str != (char)13; j++)
+                       for (j = 0; *str && *str != '\r'; j++)
                                key_code[j] = *str++;
                        key_code[j] = '\0';
                        break;
@@ -1285,7 +1302,7 @@ bool trigger_ascii_to_text(char **bufptr, cptr *strptr)
                        str++;
                }
        }
-       if (*str++ != (char)13) return FALSE;
+       if (*str++ != '\r') return FALSE;
 
        for (i = 0; i < max_macrotrigger; i++)
        {
@@ -1595,21 +1612,6 @@ errr macro_add(cptr pat, cptr act)
 
 
 /*
- * Initialize the "macro" package
- */
-errr macro_init(void)
-{
-       /* Macro patterns */
-       C_MAKE(macro__pat, MACRO_MAX, cptr);
-
-       /* Macro actions */
-       C_MAKE(macro__act, MACRO_MAX, cptr);
-
-       /* Success */
-       return (0);
-}
-
-/*
  * Local variable -- we are inside a "macro action"
  *
  * Do not match any macros until "ascii 30" is found.
@@ -1634,7 +1636,7 @@ static bool parse_under = FALSE;
 void flush(void)
 {
        /* Do it later */
-        inkey_xtra = TRUE;
+       inkey_xtra = TRUE;
 }
 
 
@@ -1698,8 +1700,20 @@ static char inkey_aux(void)
        /* Hack : ¥­¡¼ÆþÎÏÂÔ¤Á¤Ç»ß¤Þ¤Ã¤Æ¤¤¤ë¤Î¤Ç¡¢Î®¤ì¤¿¹Ô¤Îµ­²±¤ÏÉÔÍס£ */
        num_more = 0;
 
-       /* Wait for a keypress */
-       (void)(Term_inkey(&ch, TRUE, TRUE));
+       if (parse_macro)
+       {
+               /* Scan next keypress from macro action */
+               if (Term_inkey(&ch, FALSE, TRUE))
+               {
+                       /* Over-flowed? Cancel macro action */
+                       parse_macro = FALSE;
+               }
+       }
+       else
+       {
+               /* Wait for a keypress */
+               (void) (Term_inkey(&ch, TRUE, TRUE));
+       }
 
 
        /* End "macro action" */
@@ -1714,6 +1728,8 @@ static char inkey_aux(void)
        /* Inside "macro trigger" */
        if (parse_under) return (ch);
 
+       /* Parse special key only */
+       if (inkey_special && ch != 31) return (ch);
 
        /* Save the first key, advance */
        buf[p++] = ch;
@@ -1925,7 +1941,7 @@ char inkey(void)
                ch = *inkey_next++;
 
                /* Cancel the various "global parameters" */
-               inkey_base = inkey_xtra = inkey_flag = inkey_scan = FALSE;
+               inkey_base = inkey_xtra = inkey_flag = inkey_scan = inkey_special = FALSE;
 
                /* Accept result */
                return (ch);
@@ -1941,7 +1957,7 @@ char inkey(void)
        if (inkey_hack && ((ch = (*inkey_hack)(inkey_xtra)) != 0))
        {
                /* Cancel the various "global parameters" */
-               inkey_base = inkey_xtra = inkey_flag = inkey_scan = FALSE;
+               inkey_base = inkey_xtra = inkey_flag = inkey_scan = inkey_special = FALSE;
 
                /* Accept result */
                return (ch);
@@ -2126,7 +2142,7 @@ char inkey(void)
 
 
        /* Cancel the various "global parameters" */
-       inkey_base = inkey_xtra = inkey_flag = inkey_scan = FALSE;
+       inkey_base = inkey_xtra = inkey_flag = inkey_scan = inkey_special = FALSE;
 
        /* Return the keypress */
        return (ch);
@@ -2355,7 +2371,7 @@ void message_add(cptr str)
  for (t = buf; *t && (*t != '<' || (*(t+1) != 'x' )); t++) 
      if( iskanji(*t))t++;
 #else
-                for (t = buf; *t && (*t != '<'); t++);
+               for (t = buf; *t && (*t != '<'); t++);
 #endif
 
                if (*t)
@@ -2573,7 +2589,7 @@ static void msg_flush(int x)
        }
        now_damaged = FALSE;
 
-       if (!alive || !nagasu)
+       if (!p_ptr->playing || !nagasu)
        {
                /* Pause for response */
 #ifdef JP
@@ -2948,6 +2964,8 @@ void c_roff(byte a, cptr str)
 
                        /* Clear line, move cursor */
                        Term_erase(x, y, 255);
+
+                       break;
                }
 
                /* Clean up the char */
@@ -3047,7 +3065,7 @@ void c_roff(byte a, cptr str)
 
                /* Dump */
 #ifdef JP
-                Term_addch((byte)(a|0x10), ch);
+               Term_addch((byte)(a|0x10), ch);
 #else
                Term_addch(a, ch);
 #endif
@@ -3186,28 +3204,28 @@ bool askfor_aux(char *buf, int len)
                default:
 #ifdef JP
        {                       /* ÊÒ»³¤µ¤óºîÀ® */
-                int next;
-
-                                if (iskanji (i)) {
-                                        inkey_base = TRUE;
-                                        next = inkey ();
-                                        if (k+1 < len) {
-                                                buf[k++] = i;
-                                                buf[k] = next;
-                                                k_flag[k++] = 1;
-                                        } else
-                                                bell();
-                                } else {
+               int next;
+
+                               if (iskanji (i)) {
+                                       inkey_base = TRUE;
+                                       next = inkey ();
+                                       if (k+1 < len) {
+                                               buf[k++] = i;
+                                               buf[k] = next;
+                                               k_flag[k++] = 1;
+                                       } else
+                                               bell();
+                               } else {
 #ifdef SJIS
-                    if(k<len && (isprint(i) || (0xa0<=i && i<=0xdf))){
+                   if(k<len && (isprint(i) || (0xa0<=i && i<=0xdf))){
 #else
-                    if(k<len && isprint(i)){
+                   if(k<len && isprint(i)){
 #endif
-                                                buf[k] = i;
-                                                k_flag[k++] = 0;
-                                        } else
-                                                bell();
-                              }
+                                               buf[k] = i;
+                                               k_flag[k++] = 0;
+                                       } else
+                                               bell();
+                              }
                 }
 #else
                        if ((k < len) && (isprint(i)))
@@ -3285,8 +3303,9 @@ bool get_check(cptr prompt)
 /*
  * Verify something with the user strictly
  *
- * mode & 0x01 : force user to answer "YES" or "N"
- * mode & 0x02 : don't allow ESCAPE key
+ * mode & CHECK_OKAY_CANCEL : force user to answer 'O'kay or 'C'ancel
+ * mode & CHECK_NO_ESCAPE   : don't allow ESCAPE key
+ * mode & CHECK_NO_HISTORY  : no message_add
  */
 bool get_check_strict(cptr prompt, int mode)
 {
@@ -3304,68 +3323,60 @@ bool get_check_strict(cptr prompt, int mode)
        msg_print(NULL);
 
        if (!rogue_like_commands)
-               mode &= ~1;
+               mode &= ~CHECK_OKAY_CANCEL;
+
 
        /* Hack -- Build a "useful" prompt */
-       if (mode & 1)
+       if (mode & CHECK_OKAY_CANCEL)
        {
-#ifdef JP
-               mb_strlcpy(buf, prompt, 78-8);
-#else
-               strncpy(buf, prompt, 78-8);
-#endif
-               strcat(buf, "[yes/no]");
+               my_strcpy(buf, prompt, sizeof(buf)-15);
+               strcat(buf, "[(O)k/(C)ancel]");
        }
        else
        {
-#ifdef JP
-               mb_strlcpy(buf, prompt, 78-5);
-#else
-               strncpy(buf, prompt, 78-5);
-#endif
+               my_strcpy(buf, prompt, sizeof(buf)-5);
                strcat(buf, "[y/n]");
        }
 
        /* Prompt for it */
        prt(buf, 0, 0);
 
+       if (!(mode & CHECK_NO_HISTORY) && p_ptr->playing)
+       {
+               /* HACK : Add the line to message buffer */
+               message_add(buf);
+               p_ptr->window |= (PW_MESSAGE);
+               window_stuff();
+       }
+
        /* Get an acceptable answer */
        while (TRUE)
        {
                i = inkey();
-
-               if (i == 'y' || i == 'Y')
+               if (mode & CHECK_OKAY_CANCEL)
                {
-                       if (!(mode & 1))
+                       if ( i == 'o' || i == 'O' )
+                       {
+                               i = 'Y';
                                break;
-                       else
+                       }
+               }
+               else if (i == 'y' || i == 'Y')
+               {
+                               break;
+               }
+               if (!(mode & CHECK_NO_ESCAPE) && (i == ESCAPE)) break;
+               if ( mode & CHECK_OKAY_CANCEL )
+               {
+                       if ( i == 'c' || i == 'C' )
                        {
-#ifdef JP
-                               prt("y (YES¤ÈÆþÎϤ·¤Æ¤¯¤À¤µ¤¤)", 0, strlen(buf));
-#else
-                               prt("y (Please answer YES.)", 0, strlen(buf));
-#endif
-                               i = inkey();
-                               if (i == 'e' || i == 'E')
-                               {
-#ifdef JP
-                                       prt("e (YES¤ÈÆþÎϤ·¤Æ¤¯¤À¤µ¤¤)", 0, strlen(buf)+1);
-#else
-                                       prt("e (Please answer YES.)", 0, strlen(buf)+1);
-#endif
-                                       i = inkey();
-                                       if (i == 's' || i == 'S')
-                                       {
-                                               i = 'y';
-                                               break;
-                                       }
-                                       prt("", 0, strlen(buf)+1);
-                               }
-                               prt("", 0, strlen(buf));
+                               break;
                        }
                }
-               if (!(mode & 2) && (i == ESCAPE)) break;
-               if (strchr("Nn", i)) break;
+               else if (i == 'n' || i == 'N')
+               {
+                               break;
+               }
                bell();
        }
 
@@ -3843,6 +3854,150 @@ special_menu_naiyou special_menu_info[] =
 };
 #endif
 
+static char inkey_from_menu(void)
+{
+       char cmd;
+       int basey, basex;
+       int num = 0, max_num, old_num = 0;
+       int menu = 0;
+       bool kisuu;
+
+       if (py - panel_row_min > 10) basey = 2;
+       else basey = 13;
+       basex = 15;
+
+       /* Clear top line */
+       prt("", 0, 0);
+
+       screen_save();
+
+       while(1)
+       {
+               int i;
+               char sub_cmd;
+               cptr menu_name;
+               if (!menu) old_num = num;
+               put_str("+----------------------------------------------------+", basey, basex);
+               put_str("|                                                    |", basey+1, basex);
+               put_str("|                                                    |", basey+2, basex);
+               put_str("|                                                    |", basey+3, basex);
+               put_str("|                                                    |", basey+4, basex);
+               put_str("|                                                    |", basey+5, basex);
+               put_str("+----------------------------------------------------+", basey+6, basex);
+
+               for(i = 0; i < 10; i++)
+               {
+                       int hoge;
+                       if (!menu_info[menu][i].cmd) break;
+                       menu_name = menu_info[menu][i].name;
+                       for(hoge = 0; ; hoge++)
+                       {
+                               if (!special_menu_info[hoge].name[0]) break;
+                               if ((menu != special_menu_info[hoge].window) || (i != special_menu_info[hoge].number)) continue;
+                               switch(special_menu_info[hoge].jouken)
+                               {
+                               case MENU_CLASS:
+                                       if (p_ptr->pclass == special_menu_info[hoge].jouken_naiyou) menu_name = special_menu_info[hoge].name;
+                                       break;
+                               case MENU_WILD:
+                                       if (!dun_level && !p_ptr->inside_arena && !p_ptr->inside_quest)
+                                       {
+                                               if ((byte)p_ptr->wild_mode == special_menu_info[hoge].jouken_naiyou) menu_name = special_menu_info[hoge].name;
+                                       }
+                                       break;
+                               default:
+                                       break;
+                               }
+                       }
+                       put_str(menu_name, basey + 1 + i / 2, basex + 4 + (i % 2) * 24);
+               }
+               max_num = i;
+               kisuu = max_num % 2;
+#ifdef JP
+               put_str("¡Õ",basey + 1 + num / 2, basex + 2 + (num % 2) * 24);
+#else
+               put_str("> ",basey + 1 + num / 2, basex + 2 + (num % 2) * 24);
+#endif
+
+               /* Place the cursor on the player */
+               move_cursor_relative(py, px);
+
+               /* Get a command */
+               sub_cmd = inkey();
+               if ((sub_cmd == ' ') || (sub_cmd == 'x') || (sub_cmd == 'X') || (sub_cmd == '\r') || (sub_cmd == '\n'))
+               {
+                       if (menu_info[menu][num].fin)
+                       {
+                               cmd = menu_info[menu][num].cmd;
+                               use_menu = TRUE;
+                               break;
+                       }
+                       else
+                       {
+                               menu = menu_info[menu][num].cmd;
+                               num = 0;
+                               basey += 2;
+                               basex += 8;
+                       }
+               }
+               else if ((sub_cmd == ESCAPE) || (sub_cmd == 'z') || (sub_cmd == 'Z') || (sub_cmd == '0'))
+               {
+                       if (!menu)
+                       {
+                               cmd = ESCAPE;
+                               break;
+                       }
+                       else
+                       {
+                               menu = 0;
+                               num = old_num;
+                               basey -= 2;
+                               basex -= 8;
+                               screen_load();
+                               screen_save();
+                       }
+               }
+               else if ((sub_cmd == '2') || (sub_cmd == 'j') || (sub_cmd == 'J'))
+               {
+                       if (kisuu)
+                       {
+                               if (num % 2)
+                                       num = (num + 2) % (max_num - 1);
+                               else
+                                       num = (num + 2) % (max_num + 1);
+                       }
+                       else num = (num + 2) % max_num;
+               }
+               else if ((sub_cmd == '8') || (sub_cmd == 'k') || (sub_cmd == 'K'))
+               {
+                       if (kisuu)
+                       {
+                               if (num % 2)
+                                       num = (num + max_num - 3) % (max_num - 1);
+                               else
+                                       num = (num + max_num - 1) % (max_num + 1);
+                       }
+                       else num = (num + max_num - 2) % max_num;
+               }
+               else if ((sub_cmd == '4') || (sub_cmd == '6') || (sub_cmd == 'h') || (sub_cmd == 'H') || (sub_cmd == 'l') || (sub_cmd == 'L'))
+               {
+                       if ((num % 2) || (num == max_num - 1))
+                       {
+                               num--;
+                       }
+                       else if (num < max_num - 1)
+                       {
+                               num++;
+                       }
+               }
+       }
+
+       screen_load();
+       if (!inkey_next) inkey_next = "";
+
+       return (cmd);
+}
+
 /*
  * Request a command from the user.
  *
@@ -3866,14 +4021,13 @@ void request_command(int shopping)
 {
        int i;
 
-       unsigned char cmd;
-
+       char cmd;
        int mode;
 
        cptr act;
 
 #ifdef JP
-        int caretcmd = 0;
+       int caretcmd = 0;
 #endif
        /* Roguelike */
        if (rogue_like_commands)
@@ -3910,7 +4064,7 @@ void request_command(int shopping)
                        msg_print(NULL);
 
                        /* Use auto-command */
-                       cmd = (unsigned char)command_new;
+                       cmd = command_new;
 
                        /* Forget it */
                        command_new = 0;
@@ -3919,8 +4073,6 @@ void request_command(int shopping)
                /* Get a keypress in "command" mode */
                else
                {
-                       char sub_cmd;
-
                        /* Hack -- no flush needed */
                        msg_flag = FALSE;
                        num_more = 0;
@@ -3929,148 +4081,11 @@ void request_command(int shopping)
                        inkey_flag = TRUE;
 
                        /* Get a command */
-                       sub_cmd = inkey();
-
-                       if (!shopping && command_menu && ((sub_cmd == '\r') || (sub_cmd == 'x') || (sub_cmd == 'X'))
-                           && !keymap_act[mode][(byte)(sub_cmd)])
-                       {
-                               int basey, basex;
-                               int num = 0, max_num, old_num = 0;
-                               int menu = 0;
-                               bool kisuu;
-
-                               if (py - panel_row_min > 10) basey = 2;
-                               else basey = 13;
-                               basex = 15;
-
-                               /* Clear top line */
-                               prt("", 0, 0);
+                       cmd = inkey();
 
-                               screen_save();
-
-                               while(1)
-                               {
-                                       cptr menu_name;
-                                       if (!menu) old_num = num;
-                                       put_str("+----------------------------------------------------+", basey, basex);
-                                       put_str("|                                                    |", basey+1, basex);
-                                       put_str("|                                                    |", basey+2, basex);
-                                       put_str("|                                                    |", basey+3, basex);
-                                       put_str("|                                                    |", basey+4, basex);
-                                       put_str("|                                                    |", basey+5, basex);
-                                       put_str("+----------------------------------------------------+", basey+6, basex);
-
-                                       for(i = 0; i < 10; i++)
-                                       {
-                                               int hoge;
-                                               if (!menu_info[menu][i].cmd) break;
-                                               menu_name = menu_info[menu][i].name;
-                                               for(hoge = 0; ; hoge++)
-                                               {
-                                                       if (!special_menu_info[hoge].name[0]) break;
-                                                       if ((menu != special_menu_info[hoge].window) || (i != special_menu_info[hoge].number)) continue;
-                                                       switch(special_menu_info[hoge].jouken)
-                                                       {
-                                                               case MENU_CLASS:
-                                                               if (p_ptr->pclass == special_menu_info[hoge].jouken_naiyou) menu_name = special_menu_info[hoge].name;
-                                                               break;
-                                                               case MENU_WILD:
-                                                               if (!dun_level && !p_ptr->inside_arena && !p_ptr->inside_quest)
-                                                               {
-                                                                       if ((byte)p_ptr->wild_mode == special_menu_info[hoge].jouken_naiyou) menu_name = special_menu_info[hoge].name;
-                                                               }
-                                                               break;
-                                                               default:
-                                                               break;
-                                                       }
-                                               }
-                                               put_str(menu_name, basey + 1 + i / 2, basex + 4 + (i % 2) * 24);
-                                       }
-                                       max_num = i;
-                                       kisuu = max_num % 2;
-#ifdef JP
-                                       put_str("¡Õ",basey + 1 + num / 2, basex + 2 + (num % 2) * 24);
-#else
-                                       put_str("> ",basey + 1 + num / 2, basex + 2 + (num % 2) * 24);
-#endif
-
-                                       /* Place the cursor on the player */
-                                       move_cursor_relative(py, px);
-
-                                       /* Get a command */
-                                       sub_cmd = inkey();
-                                       if ((sub_cmd == ' ') || (sub_cmd == 'x') || (sub_cmd == 'X') || (sub_cmd == '\r'))
-                                       {
-                                               if (menu_info[menu][num].fin)
-                                               {
-                                                       cmd = menu_info[menu][num].cmd;
-                                                       use_menu = TRUE;
-                                                       break;
-                                               }
-                                               else
-                                               {
-                                                       menu = menu_info[menu][num].cmd;
-                                                       num = 0;
-                                                       basey += 2;
-                                                       basex += 8;
-                                               }
-                                       }
-                                       else if ((sub_cmd == ESCAPE) || (sub_cmd == 'z') || (sub_cmd == 'Z') || (sub_cmd == '0'))
-                                       {
-                                               if (!menu)
-                                               {
-                                                       cmd = ESCAPE;
-                                                       break;
-                                               }
-                                               else
-                                               {
-                                                       menu = 0;
-                                                       num = old_num;
-                                                       basey -= 2;
-                                                       basex -= 8;
-                                                       screen_load();
-                                                       screen_save();
-                                               }
-                                       }
-                                       else if ((sub_cmd == '2') || (sub_cmd == 'j') || (sub_cmd == 'J'))
-                                       {
-                                               if (kisuu)
-                                               {
-                                                       if (num % 2)
-                                                               num = (num + 2) % (max_num - 1);
-                                                       else
-                                                               num = (num + 2) % (max_num + 1);
-                                               }
-                                               else num = (num + 2) % max_num;
-                                       }
-                                       else if ((sub_cmd == '8') || (sub_cmd == 'k') || (sub_cmd == 'K'))
-                                       {
-                                               if (kisuu)
-                                               {
-                                                       if (num % 2)
-                                                               num = (num + max_num - 3) % (max_num - 1);
-                                                       else
-                                                               num = (num + max_num - 1) % (max_num + 1);
-                                               }
-                                               else num = (num + max_num - 2) % max_num;
-                                       }
-                                       else if ((sub_cmd == '4') || (sub_cmd == '6') || (sub_cmd == 'h') || (sub_cmd == 'H') || (sub_cmd == 'l') || (sub_cmd == 'L'))
-                                       {
-                                               if ((num % 2) || (num == max_num - 1))
-                                               {
-                                                       num--;
-                                               }
-                                               else if (num < max_num - 1)
-                                               {
-                                                       num++;
-                                               }
-                                       }
-                               }
-
-                               screen_load();
-                               if (!inkey_next) inkey_next = "";
-                       }
-                       else cmd = sub_cmd;
+                       if (!shopping && command_menu && ((cmd == '\r') || (cmd == '\n') || (cmd == 'x') || (cmd == 'X'))
+                           && !keymap_act[mode][(byte)(cmd)])
+                               cmd = inkey_from_menu();
                }
 
                /* Clear top line */
@@ -4252,7 +4267,7 @@ prt(format("
 
 
                /* Use command */
-               command_cmd = cmd;
+               command_cmd = (byte)cmd;
 
                /* Done */
                break;
@@ -4287,20 +4302,20 @@ prt(format("
        }
 
 #ifdef JP
-        for (i = 0; i < 256; i++)
-        {
-                cptr s;
-                if ((s = keymap_act[mode][i]) != NULL)
-                {
-                        if (*s == command_cmd && *(s+1) == 0)
-                        {
-                                caretcmd = i;
-                                break;
-                        }
-                }
-        }
-        if (!caretcmd)
-                caretcmd = command_cmd;
+       for (i = 0; i < 256; i++)
+       {
+               cptr s;
+               if ((s = keymap_act[mode][i]) != NULL)
+               {
+                       if (*s == command_cmd && *(s+1) == 0)
+                       {
+                               caretcmd = i;
+                               break;
+                       }
+               }
+       }
+       if (!caretcmd)
+               caretcmd = command_cmd;
 #endif
        /* Hack -- Scan equipment */
        for (i = INVEN_RARM; i < INVEN_TOTAL; i++)
@@ -4326,7 +4341,7 @@ prt(format("
                {
                        /* Check the "restriction" character */
 #ifdef JP
-                        if ((s[1] == caretcmd) || (s[1] == '*'))
+                       if ((s[1] == caretcmd) || (s[1] == '*'))
 #else
                        if ((s[1] == command_cmd) || (s[1] == '*'))
 #endif
@@ -4450,28 +4465,50 @@ static bool insert_str(char *buf, cptr target, cptr insert)
  */
 int get_keymap_dir(char ch)
 {
-       cptr act, s;
        int d = 0;
 
-       if (rogue_like_commands)
+       /* Already a direction? */
+       if (isdigit(ch))
        {
-               act = keymap_act[KEYMAP_MODE_ROGUE][(byte)ch];
+               d = D2I(ch);
        }
        else
        {
-               act = keymap_act[KEYMAP_MODE_ORIG][(byte)ch];
-       }
+               int mode;
+               cptr act, s;
 
-       if (act)
-       {
-               /* Convert to a direction */
-               for (s = act; *s; ++s)
+               /* Roguelike */
+               if (rogue_like_commands)
+               {
+                       mode = KEYMAP_MODE_ROGUE;
+               }
+
+               /* Original */
+               else
                {
-                       /* Use any digits in keymap */
-                       if (isdigit(*s)) d = D2I(*s);
+                       mode = KEYMAP_MODE_ORIG;
+               }
+
+               /* Extract the action (if any) */
+               act = keymap_act[mode][(byte)(ch)];
+
+               /* Analyze */
+               if (act)
+               {
+                       /* Convert to a direction */
+                       for (s = act; *s; ++s)
+                       {
+                               /* Use any digits in keymap */
+                               if (isdigit(*s)) d = D2I(*s);
+                       }
                }
        }
-       return d;
+
+       /* Paranoia */
+       if (d == 5) d = 0;
+
+       /* Return direction */
+       return (d);
 }
 
 
@@ -4787,43 +4824,63 @@ void roff_to_buf(cptr str, int maxlen, char *tbuf)
        int write_pt = 0;
        int line_len = 0;
        int word_punct = 0;
-       unsigned char ch[3];
+       char ch[3];
        ch[2] = '\0';
 
        while (str[read_pt])
        {
 #ifdef JP
+               bool kinsoku = FALSE;
                bool kanji;
 #endif
+               int ch_len = 1;
+
+               /* Prepare one character */
                ch[0] = str[read_pt];
                ch[1] = '\0';
 #ifdef JP
                kanji  = iskanji(ch[0]);
+
                if (kanji)
+               {
                        ch[1] = str[read_pt+1];
-               if (!kanji && !isprint(ch[0]))
+                       ch_len = 2;
+
+                       if (strcmp(ch, "¡£") == 0 ||
+                           strcmp(ch, "¡¢") == 0 ||
+                           strcmp(ch, "¥£") == 0 ||
+                           strcmp(ch, "¡¼") == 0)
+                               kinsoku = TRUE;
+               }
+               else if (!isprint(ch[0]))
                        ch[0] = ' ';
 #else
                if (!isprint(ch[0]))
                        ch[0] = ' ';
 #endif
 
-               if (line_len >= maxlen - 1 || str[read_pt] == '\n')
+               if (line_len + ch_len > maxlen - 1 || str[read_pt] == '\n')
                {
                        int word_len;
 
                        /* return to better wrapping point. */
                        /* Space character at the end of the line need not to be printed. */
                        word_len = read_pt - word_punct;
-                       if (ch[0] != ' ' && word_len < line_len/2)
+#ifdef JP
+                       if (kanji && !kinsoku)
+                               /* nothing */ ;
+                       else
+#endif
+                       if (ch[0] == ' ' || word_len >= line_len/2)
+                               read_pt++;
+                       else
                        {
                                read_pt = word_punct;
                                if (str[word_punct] == ' ')
                                        read_pt++;
                                write_pt -= word_len;
                        }
-                       else
-                               read_pt++;
+
                        tbuf[write_pt++] = '\0';
                        line_len = 0;
                        word_punct = read_pt;
@@ -4832,10 +4889,7 @@ void roff_to_buf(cptr str, int maxlen, char *tbuf)
                if (ch[0] == ' ')
                        word_punct = read_pt;
 #ifdef JP
-               if (kanji &&
-                   strcmp((char *)ch, "¡£") != 0 && strcmp((char *)ch, "¡¢") != 0 &&
-                   strcmp((char *)ch, "¥£") != 0 && strcmp((char *)ch, "¡¼") != 0)
-                       word_punct = read_pt;
+               if (!kinsoku) word_punct = read_pt;
 #endif
                tbuf[write_pt++] = ch[0];
                line_len++;
@@ -4855,3 +4909,95 @@ void roff_to_buf(cptr str, int maxlen, char *tbuf)
        return;
 }
 
+
+/*
+ * The my_strcpy() function copies up to 'bufsize'-1 characters from 'src'
+ * to 'buf' and NUL-terminates the result.  The 'buf' and 'src' strings may
+ * not overlap.
+ *
+ * my_strcpy() returns strlen(src).  This makes checking for truncation
+ * easy.  Example: if (my_strcpy(buf, src, sizeof(buf)) >= sizeof(buf)) ...;
+ *
+ * This function should be equivalent to the strlcpy() function in BSD.
+ */
+size_t my_strcpy(char *buf, const char *src, size_t bufsize)
+{
+#ifdef JP
+
+       char *d = buf;
+       const char *s = src;
+       size_t len = 0;
+
+       /* reserve for NUL termination */
+       bufsize--;
+
+       /* Copy as many bytes as will fit */
+       while (len < bufsize)
+       {
+               if (iskanji(*s))
+               {
+                       if (len + 1 >= bufsize || !*(s+1)) break;
+                       *d++ = *s++;
+                       *d++ = *s++;
+                       len += 2;
+               }
+               else
+               {
+                       *d++ = *s++;
+                       len++;
+               }
+       }
+       *d = '\0';
+       while(*s++) len++;
+
+       return len;
+
+#else
+
+       size_t len = strlen(src);
+       size_t ret = len;
+
+       /* Paranoia */
+       if (bufsize == 0) return ret;
+
+       /* Truncate */
+       if (len >= bufsize) len = bufsize - 1;
+
+       /* Copy the string and terminate it */
+       (void)memcpy(buf, src, len);
+       buf[len] = '\0';
+
+       /* Return strlen(src) */
+       return ret;
+
+#endif
+}
+
+
+/*
+ * The my_strcat() tries to append a string to an existing NUL-terminated string.
+ * It never writes more characters into the buffer than indicated by 'bufsize' and
+ * NUL-terminates the buffer.  The 'buf' and 'src' strings may not overlap.
+ *
+ * my_strcat() returns strlen(buf) + strlen(src).  This makes checking for
+ * truncation easy.  Example:
+ * if (my_strcat(buf, src, sizeof(buf)) >= sizeof(buf)) ...;
+ *
+ * This function should be equivalent to the strlcat() function in BSD.
+ */
+size_t my_strcat(char *buf, const char *src, size_t bufsize)
+{
+       size_t dlen = strlen(buf);
+
+       /* Is there room left in the buffer? */
+       if (dlen < bufsize - 1)
+       {
+               /* Append as much as possible  */
+               return (dlen + my_strcpy(buf + dlen, src, bufsize - dlen));
+       }
+       else
+       {
+               /* Return without appending */
+               return (dlen + strlen(src));
+       }
+}