OSDN Git Service

[Refacotr] #39964 Separated autopick-menu-data-table.c/h from autopick.c
[hengband/hengband.git] / src / autopick / autopick.c
1 /*!
2  * @file autopick.c
3  * @brief 自動拾い機能の実装 / Object Auto-picker/Destroyer
4  * @date 2014/01/02
5  * @author
6  * Copyright (c) 2002  Mogami\n
7  *\n
8  * This software may be copied and distributed for educational, research, and\n
9  * not for profit purposes provided that this copyright and statement are\n
10  * included in all such copies.\n
11  * 2014 Deskull rearranged comment for Doxygen.\n
12  */
13
14 #include "angband.h"
15 #include "util.h"
16 #include "autopick/autopick-commands-table.h"
17 #include "autopick/autopick-dirty-flags.h"
18 #include "autopick/autopick-editor-table.h"
19 #include "autopick/autopick-flags-table.h"
20 #include "autopick/autopick-key-flag-process.h"
21 #include "autopick/autopick-menu-data-table.h"
22 #include "autopick/autopick-keys-table.h"
23 #include "autopick/autopick-util.h"
24 #include "gameterm.h"
25 #include "autopick/autopick.h"
26 #include "core.h"
27 #include "core/show-file.h"
28 #include "cmd/cmd-save.h"
29 #include "io/read-pref-file.h"
30
31 #include "mind.h"
32
33 #include "market/store.h"
34 #include "player-status.h"
35 #include "player-move.h"
36 #include "player-class.h"
37 #include "player-race.h"
38 #include "player-inventory.h"
39 #include "view/display-player.h"
40 #include "object/object-kind.h"
41 #include "object-ego.h"
42 #include "object-flavor.h"
43 #include "object-hook.h"
44
45 #include "files.h"
46 #include "floor.h"
47 #include "world.h"
48 #include "monster.h"
49 #include "monsterrace.h"
50 #include "view-mainwindow.h" // 暫定。後で消す
51
52 #ifdef JP
53 static char kanji_colon[] = ":";
54 #endif
55
56 /*
57  * 自動拾い/破壊設定のリストに関する変数 / List for auto-picker/destroyer entries
58  */
59 int max_autopick = 0; /*!< 現在登録している自動拾い/破壊設定の数 */
60 int max_max_autopick = 0; /*!< 自動拾い/破壊設定の限界数 */
61 autopick_type *autopick_list = NULL; /*!< 自動拾い/破壊設定構造体のポインタ配列 */
62
63 /*
64  * Automatically destroy an item if it is to be destroyed
65  *
66  * When always_pickup is 'yes', we disable auto-destroyer function of
67  * auto-picker/destroyer, and do only easy-auto-destroyer.
68  */
69 static object_type autopick_last_destroyed_object;
70
71 /*
72  * A function to create new entry
73  */
74 static bool autopick_new_entry(autopick_type *entry, concptr str, bool allow_default)
75 {
76         if (str[0] && str[1] == ':') switch (str[0])
77         {
78         case '?': case '%':
79         case 'A': case 'P': case 'C':
80                 return FALSE;
81         }
82
83         entry->flag[0] = entry->flag[1] = 0L;
84         entry->dice = 0;
85         entry->bonus = 0;
86
87         byte act = DO_AUTOPICK | DO_DISPLAY;
88         while (TRUE)
89         {
90                 if ((act & DO_AUTOPICK) && *str == '!')
91                 {
92                         act &= ~DO_AUTOPICK;
93                         act |= DO_AUTODESTROY;
94                         str++;
95                         continue;
96                 }
97
98                 if ((act & DO_AUTOPICK) && *str == '~')
99                 {
100                         act &= ~DO_AUTOPICK;
101                         act |= DONT_AUTOPICK;
102                         str++;
103                         continue;
104                 }
105
106                 if ((act & DO_AUTOPICK) && *str == ';')
107                 {
108                         act &= ~DO_AUTOPICK;
109                         act |= DO_QUERY_AUTOPICK;
110                         str++;
111                         continue;
112                 }
113
114                 if ((act & DO_DISPLAY) && *str == '(')
115                 {
116                         act &= ~DO_DISPLAY;
117                         str++;
118                         continue;
119                 }
120
121                 break;
122         }
123
124         concptr insc = NULL;
125         char buf[MAX_LINELEN];
126         int i;
127         for (i = 0; *str; i++)
128         {
129                 char c = *str++;
130 #ifdef JP
131                 if (iskanji(c))
132                 {
133                         buf[i++] = c;
134                         buf[i] = *str++;
135                         continue;
136                 }
137 #endif
138                 if (c == '#')
139                 {
140                         buf[i] = '\0';
141                         insc = str;
142                         break;
143                 }
144
145                 if (isupper(c)) c = (char)tolower(c);
146
147                 buf[i] = c;
148         }
149
150         buf[i] = '\0';
151         if (!allow_default && *buf == 0) return FALSE;
152         if (*buf == 0 && insc) return FALSE;
153
154         concptr prev_ptr, ptr;
155         ptr = prev_ptr = buf;
156         concptr old_ptr = NULL;
157         while (old_ptr != ptr)
158         {
159                 old_ptr = ptr;
160                 if (MATCH_KEY(KEY_ALL)) ADD_FLG(FLG_ALL);
161                 if (MATCH_KEY(KEY_COLLECTING)) ADD_FLG(FLG_COLLECTING);
162                 if (MATCH_KEY(KEY_UNAWARE)) ADD_FLG(FLG_UNAWARE);
163                 if (MATCH_KEY(KEY_UNIDENTIFIED)) ADD_FLG(FLG_UNIDENTIFIED);
164                 if (MATCH_KEY(KEY_IDENTIFIED)) ADD_FLG(FLG_IDENTIFIED);
165                 if (MATCH_KEY(KEY_STAR_IDENTIFIED)) ADD_FLG(FLG_STAR_IDENTIFIED);
166                 if (MATCH_KEY(KEY_BOOSTED)) ADD_FLG(FLG_BOOSTED);
167
168                 /*** Weapons whose dd*ds is more than nn ***/
169                 if (MATCH_KEY2(KEY_MORE_THAN))
170                 {
171                         int k = 0;
172                         entry->dice = 0;
173
174                         while (' ' == *ptr) ptr++;
175
176                         while ('0' <= *ptr && *ptr <= '9')
177                         {
178                                 entry->dice = 10 * entry->dice + (*ptr - '0');
179                                 ptr++;
180                                 k++;
181                         }
182
183                         if (k > 0 && k <= 2)
184                         {
185                                 (void)MATCH_KEY(KEY_DICE);
186                                 ADD_FLG(FLG_MORE_DICE);
187                         }
188                         else
189                                 ptr = prev_ptr;
190                 }
191
192                 /*** Items whose magical bonus is more than n ***/
193                 if (MATCH_KEY2(KEY_MORE_BONUS))
194                 {
195                         int k = 0;
196                         entry->bonus = 0;
197
198                         while (' ' == *ptr) ptr++;
199
200                         while ('0' <= *ptr && *ptr <= '9')
201                         {
202                                 entry->bonus = 10 * entry->bonus + (*ptr - '0');
203                                 ptr++;
204                                 k++;
205                         }
206
207                         if (k > 0 && k <= 2)
208                         {
209 #ifdef JP
210                                 (void)MATCH_KEY(KEY_MORE_BONUS2);
211 #else
212                                 if (' ' == *ptr) ptr++;
213 #endif
214                                 ADD_FLG(FLG_MORE_BONUS);
215                         }
216                         else
217                                 ptr = prev_ptr;
218                 }
219
220                 if (MATCH_KEY(KEY_WORTHLESS)) ADD_FLG(FLG_WORTHLESS);
221                 if (MATCH_KEY(KEY_EGO)) ADD_FLG(FLG_EGO);
222                 if (MATCH_KEY(KEY_GOOD)) ADD_FLG(FLG_GOOD);
223                 if (MATCH_KEY(KEY_NAMELESS)) ADD_FLG(FLG_NAMELESS);
224                 if (MATCH_KEY(KEY_AVERAGE)) ADD_FLG(FLG_AVERAGE);
225                 if (MATCH_KEY(KEY_RARE)) ADD_FLG(FLG_RARE);
226                 if (MATCH_KEY(KEY_COMMON)) ADD_FLG(FLG_COMMON);
227                 if (MATCH_KEY(KEY_WANTED)) ADD_FLG(FLG_WANTED);
228                 if (MATCH_KEY(KEY_UNIQUE)) ADD_FLG(FLG_UNIQUE);
229                 if (MATCH_KEY(KEY_HUMAN)) ADD_FLG(FLG_HUMAN);
230                 if (MATCH_KEY(KEY_UNREADABLE)) ADD_FLG(FLG_UNREADABLE);
231                 if (MATCH_KEY(KEY_REALM1)) ADD_FLG(FLG_REALM1);
232                 if (MATCH_KEY(KEY_REALM2)) ADD_FLG(FLG_REALM2);
233                 if (MATCH_KEY(KEY_FIRST)) ADD_FLG(FLG_FIRST);
234                 if (MATCH_KEY(KEY_SECOND)) ADD_FLG(FLG_SECOND);
235                 if (MATCH_KEY(KEY_THIRD)) ADD_FLG(FLG_THIRD);
236                 if (MATCH_KEY(KEY_FOURTH)) ADD_FLG(FLG_FOURTH);
237         }
238
239         int prev_flg = -1;
240         if (MATCH_KEY2(KEY_ARTIFACT)) ADD_FLG_NOUN(FLG_ARTIFACT);
241
242         if (MATCH_KEY2(KEY_ITEMS)) ADD_FLG_NOUN(FLG_ITEMS);
243         else if (MATCH_KEY2(KEY_WEAPONS)) ADD_FLG_NOUN(FLG_WEAPONS);
244         else if (MATCH_KEY2(KEY_FAVORITE_WEAPONS)) ADD_FLG_NOUN(FLG_FAVORITE_WEAPONS);
245         else if (MATCH_KEY2(KEY_ARMORS)) ADD_FLG_NOUN(FLG_ARMORS);
246         else if (MATCH_KEY2(KEY_MISSILES)) ADD_FLG_NOUN(FLG_MISSILES);
247         else if (MATCH_KEY2(KEY_DEVICES)) ADD_FLG_NOUN(FLG_DEVICES);
248         else if (MATCH_KEY2(KEY_LIGHTS)) ADD_FLG_NOUN(FLG_LIGHTS);
249         else if (MATCH_KEY2(KEY_JUNKS)) ADD_FLG_NOUN(FLG_JUNKS);
250         else if (MATCH_KEY2(KEY_CORPSES)) ADD_FLG_NOUN(FLG_CORPSES);
251         else if (MATCH_KEY2(KEY_SPELLBOOKS)) ADD_FLG_NOUN(FLG_SPELLBOOKS);
252         else if (MATCH_KEY2(KEY_HAFTED)) ADD_FLG_NOUN(FLG_HAFTED);
253         else if (MATCH_KEY2(KEY_SHIELDS)) ADD_FLG_NOUN(FLG_SHIELDS);
254         else if (MATCH_KEY2(KEY_BOWS)) ADD_FLG_NOUN(FLG_BOWS);
255         else if (MATCH_KEY2(KEY_RINGS)) ADD_FLG_NOUN(FLG_RINGS);
256         else if (MATCH_KEY2(KEY_AMULETS)) ADD_FLG_NOUN(FLG_AMULETS);
257         else if (MATCH_KEY2(KEY_SUITS)) ADD_FLG_NOUN(FLG_SUITS);
258         else if (MATCH_KEY2(KEY_CLOAKS)) ADD_FLG_NOUN(FLG_CLOAKS);
259         else if (MATCH_KEY2(KEY_HELMS)) ADD_FLG_NOUN(FLG_HELMS);
260         else if (MATCH_KEY2(KEY_GLOVES)) ADD_FLG_NOUN(FLG_GLOVES);
261         else if (MATCH_KEY2(KEY_BOOTS)) ADD_FLG_NOUN(FLG_BOOTS);
262
263         if (*ptr == ':')
264                 ptr++;
265 #ifdef JP
266         else if (ptr[0] == kanji_colon[0] && ptr[1] == kanji_colon[1])
267                 ptr += 2;
268 #endif
269         else if (*ptr == '\0')
270         {
271                 if (prev_flg == -1)
272                         ADD_FLG_NOUN(FLG_ITEMS);
273         }
274         else
275         {
276                 if (prev_flg != -1)
277                 {
278                         entry->flag[prev_flg / 32] &= ~(1L << (prev_flg % 32));
279                         ptr = prev_ptr;
280                 }
281         }
282
283         entry->name = string_make(ptr);
284         entry->action = act;
285         entry->insc = string_make(insc);
286
287         return TRUE;
288 }
289
290
291 /*
292  * Get auto-picker entry from o_ptr.
293  */
294 static void autopick_entry_from_object(player_type *player_ptr, autopick_type *entry, object_type *o_ptr)
295 {
296         /* Assume that object name is to be added */
297         bool name = TRUE;
298
299 #ifdef JP
300         /* エゴ銘が邪魔かもしれないので、デフォルトで「^」は付けない */
301         bool bol_mark = FALSE;
302 #else
303         /* We can always use the ^ mark in English */
304         bool bol_mark = TRUE;
305 #endif
306
307         GAME_TEXT name_str[MAX_NLEN];
308
309         name_str[0] = '\0';
310         entry->insc = string_make(quark_str(o_ptr->inscription));
311         entry->action = DO_AUTOPICK | DO_DISPLAY;
312         entry->flag[0] = entry->flag[1] = 0L;
313         entry->dice = 0;
314
315         if (!object_is_aware(o_ptr))
316         {
317                 ADD_FLG(FLG_UNAWARE);
318                 bol_mark = TRUE;
319         }
320         else if (!object_is_known(o_ptr))
321         {
322                 if (!(o_ptr->ident & IDENT_SENSE))
323                 {
324                         ADD_FLG(FLG_UNIDENTIFIED);
325                         bol_mark = TRUE;
326                 }
327                 else
328                 {
329                         switch (o_ptr->feeling)
330                         {
331                         case FEEL_AVERAGE:
332                         case FEEL_GOOD:
333                                 ADD_FLG(FLG_NAMELESS);
334                                 bol_mark = TRUE;
335                                 break;
336
337                         case FEEL_BROKEN:
338                         case FEEL_CURSED:
339                                 ADD_FLG(FLG_NAMELESS);
340                                 ADD_FLG(FLG_WORTHLESS);
341                                 bol_mark = TRUE;
342                                 break;
343
344                         case FEEL_TERRIBLE:
345                         case FEEL_WORTHLESS:
346                                 ADD_FLG(FLG_WORTHLESS);
347                                 break;
348
349                         case FEEL_EXCELLENT:
350                                 ADD_FLG(FLG_EGO);
351                                 break;
352
353                         case FEEL_UNCURSED:
354                                 break;
355
356                         default:
357                                 break;
358                         }
359                 }
360         }
361         else
362         {
363                 if (object_is_ego(o_ptr))
364                 {
365                         if (object_is_weapon_armour_ammo(o_ptr))
366                         {
367                                 /*
368                                  * Base name of ego weapons and armors
369                                  * are almost meaningless.
370                                  * Register the ego type only.
371                                  */
372                                 ego_item_type *e_ptr = &e_info[o_ptr->name2];
373 #ifdef JP
374                                 /* エゴ銘には「^」マークが使える */
375                                 sprintf(name_str, "^%s", e_name + e_ptr->name);
376 #else
377                                 /* We ommit the basename and cannot use the ^ mark */
378                                 strcpy(name_str, e_name + e_ptr->name);
379 #endif
380                                 name = FALSE;
381                                 if (!object_is_rare(o_ptr)) ADD_FLG(FLG_COMMON);
382                         }
383
384                         ADD_FLG(FLG_EGO);
385                 }
386                 else if (object_is_artifact(o_ptr))
387                         ADD_FLG(FLG_ARTIFACT);
388                 else
389                 {
390                         if (object_is_equipment(o_ptr))
391                                 ADD_FLG(FLG_NAMELESS);
392
393                         bol_mark = TRUE;
394                 }
395
396         }
397
398         if (object_is_melee_weapon(o_ptr))
399         {
400                 object_kind *k_ptr = &k_info[o_ptr->k_idx];
401
402                 if ((o_ptr->dd != k_ptr->dd) || (o_ptr->ds != k_ptr->ds))
403                         ADD_FLG(FLG_BOOSTED);
404         }
405
406         if (object_is_bounty(o_ptr))
407         {
408                 REM_FLG(FLG_WORTHLESS);
409                 ADD_FLG(FLG_WANTED);
410         }
411
412         if ((o_ptr->tval == TV_CORPSE || o_ptr->tval == TV_STATUE)
413                 && (r_info[o_ptr->pval].flags1 & RF1_UNIQUE))
414         {
415                 ADD_FLG(FLG_UNIQUE);
416         }
417
418         if (o_ptr->tval == TV_CORPSE && my_strchr("pht", r_info[o_ptr->pval].d_char))
419         {
420                 ADD_FLG(FLG_HUMAN);
421         }
422
423         if (o_ptr->tval >= TV_LIFE_BOOK &&
424                 !check_book_realm(player_ptr, o_ptr->tval, o_ptr->sval))
425         {
426                 ADD_FLG(FLG_UNREADABLE);
427                 if (o_ptr->tval != TV_ARCANE_BOOK) name = FALSE;
428         }
429
430         if (REALM1_BOOK == o_ptr->tval &&
431                 player_ptr->pclass != CLASS_SORCERER &&
432                 player_ptr->pclass != CLASS_RED_MAGE)
433         {
434                 ADD_FLG(FLG_REALM1);
435                 name = FALSE;
436         }
437
438         if (REALM2_BOOK == o_ptr->tval &&
439                 player_ptr->pclass != CLASS_SORCERER &&
440                 player_ptr->pclass != CLASS_RED_MAGE)
441         {
442                 ADD_FLG(FLG_REALM2);
443                 name = FALSE;
444         }
445
446         if (o_ptr->tval >= TV_LIFE_BOOK && 0 == o_ptr->sval)
447                 ADD_FLG(FLG_FIRST);
448         if (o_ptr->tval >= TV_LIFE_BOOK && 1 == o_ptr->sval)
449                 ADD_FLG(FLG_SECOND);
450         if (o_ptr->tval >= TV_LIFE_BOOK && 2 == o_ptr->sval)
451                 ADD_FLG(FLG_THIRD);
452         if (o_ptr->tval >= TV_LIFE_BOOK && 3 == o_ptr->sval)
453                 ADD_FLG(FLG_FOURTH);
454
455         if (object_is_ammo(o_ptr))
456                 ADD_FLG(FLG_MISSILES);
457         else if (o_ptr->tval == TV_SCROLL || o_ptr->tval == TV_STAFF
458                 || o_ptr->tval == TV_WAND || o_ptr->tval == TV_ROD)
459                 ADD_FLG(FLG_DEVICES);
460         else if (o_ptr->tval == TV_LITE)
461                 ADD_FLG(FLG_LIGHTS);
462         else if (o_ptr->tval == TV_SKELETON || o_ptr->tval == TV_BOTTLE
463                 || o_ptr->tval == TV_JUNK || o_ptr->tval == TV_STATUE)
464                 ADD_FLG(FLG_JUNKS);
465         else if (o_ptr->tval == TV_CORPSE)
466                 ADD_FLG(FLG_CORPSES);
467         else if (o_ptr->tval >= TV_LIFE_BOOK)
468                 ADD_FLG(FLG_SPELLBOOKS);
469         else if (o_ptr->tval == TV_POLEARM || o_ptr->tval == TV_SWORD
470                 || o_ptr->tval == TV_DIGGING || o_ptr->tval == TV_HAFTED)
471                 ADD_FLG(FLG_WEAPONS);
472         else if (o_ptr->tval == TV_SHIELD)
473                 ADD_FLG(FLG_SHIELDS);
474         else if (o_ptr->tval == TV_BOW)
475                 ADD_FLG(FLG_BOWS);
476         else if (o_ptr->tval == TV_RING)
477                 ADD_FLG(FLG_RINGS);
478         else if (o_ptr->tval == TV_AMULET)
479                 ADD_FLG(FLG_AMULETS);
480         else if (o_ptr->tval == TV_DRAG_ARMOR || o_ptr->tval == TV_HARD_ARMOR ||
481                 o_ptr->tval == TV_SOFT_ARMOR)
482                 ADD_FLG(FLG_SUITS);
483         else if (o_ptr->tval == TV_CLOAK)
484                 ADD_FLG(FLG_CLOAKS);
485         else if (o_ptr->tval == TV_HELM)
486                 ADD_FLG(FLG_HELMS);
487         else if (o_ptr->tval == TV_GLOVES)
488                 ADD_FLG(FLG_GLOVES);
489         else if (o_ptr->tval == TV_BOOTS)
490                 ADD_FLG(FLG_BOOTS);
491
492         if (!name)
493         {
494                 str_tolower(name_str);
495                 entry->name = string_make(name_str);
496                 return;
497         }
498
499         GAME_TEXT o_name[MAX_NLEN];
500         object_desc(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL | OD_NAME_ONLY));
501
502         /*
503          * If necessary, add a '^' which indicates the
504          * beginning of line.
505          */
506         sprintf(name_str, "%s%s", bol_mark ? "^" : "", o_name);
507         str_tolower(name_str);
508         entry->name = string_make(name_str);
509 }
510
511
512 /*
513  * A function to delete entry
514  */
515 static void autopick_free_entry(autopick_type *entry)
516 {
517         string_free(entry->name);
518         string_free(entry->insc);
519         entry->name = NULL;
520         entry->insc = NULL;
521 }
522
523
524 /*
525  * Initialize the autopick
526  */
527 static void init_autopick(void)
528 {
529         static const char easy_autopick_inscription[] = "(:=g";
530         autopick_type entry;
531         int i;
532
533         if (!autopick_list)
534         {
535                 max_max_autopick = MAX_AUTOPICK_DEFAULT;
536                 C_MAKE(autopick_list, max_max_autopick, autopick_type);
537                 max_autopick = 0;
538         }
539
540         for (i = 0; i < max_autopick; i++)
541                 autopick_free_entry(&autopick_list[i]);
542
543         max_autopick = 0;
544         autopick_new_entry(&entry, easy_autopick_inscription, TRUE);
545         autopick_list[max_autopick++] = entry;
546 }
547
548
549 /*
550  *  Get file name for autopick preference
551  */
552 static concptr pickpref_filename(player_type *player_ptr, int filename_mode)
553 {
554         static const char namebase[] = _("picktype", "pickpref");
555
556         switch (filename_mode)
557         {
558         case PT_DEFAULT:
559                 return format("%s.prf", namebase);
560
561         case PT_WITH_PNAME:
562                 return format("%s-%s.prf", namebase, player_ptr->base_name);
563
564         default:
565                 return NULL;
566         }
567 }
568
569
570 /*
571  * Load an autopick preference file
572  */
573 void autopick_load_pref(player_type *player_ptr, bool disp_mes)
574 {
575         GAME_TEXT buf[80];
576         init_autopick();
577         my_strcpy(buf, pickpref_filename(player_ptr, PT_WITH_PNAME), sizeof(buf));
578         errr err = process_autopick_file(player_ptr, buf);
579         if (err == 0 && disp_mes)
580         {
581                 msg_format(_("%sを読み込みました。", "Loaded '%s'."), buf);
582         }
583
584         if (err < 0)
585         {
586                 my_strcpy(buf, pickpref_filename(player_ptr, PT_DEFAULT), sizeof(buf));
587                 err = process_autopick_file(player_ptr, buf);
588                 if (err == 0 && disp_mes)
589                 {
590                         msg_format(_("%sを読み込みました。", "Loaded '%s'."), buf);
591                 }
592         }
593
594         if (err && disp_mes)
595         {
596                 msg_print(_("自動拾い設定ファイルの読み込みに失敗しました。", "Failed to reload autopick preference."));
597         }
598 }
599
600
601 /*
602  * Add one line to autopick_list[]
603  */
604 static void add_autopick_list(autopick_type *entry)
605 {
606         if (max_autopick >= max_max_autopick)
607         {
608                 int old_max_max_autopick = max_max_autopick;
609                 autopick_type *old_autopick_list = autopick_list;
610                 max_max_autopick += MAX_AUTOPICK_DEFAULT;
611                 C_MAKE(autopick_list, max_max_autopick, autopick_type);
612                 (void)C_COPY(autopick_list, old_autopick_list, old_max_max_autopick, autopick_type);
613                 C_KILL(old_autopick_list, old_max_max_autopick, autopick_type);
614         }
615
616         autopick_list[max_autopick] = *entry;
617         max_autopick++;
618 }
619
620
621 /*
622  *  Process line for auto picker/destroyer.
623  */
624 void process_autopick_file_command(char *buf)
625 {
626         autopick_type an_entry, *entry = &an_entry;
627         int i;
628         for (i = 0; buf[i]; i++)
629         {
630 #ifdef JP
631                 if (iskanji(buf[i]))
632                 {
633                         i++;
634                         continue;
635                 }
636 #endif
637                 if (iswspace(buf[i]) && buf[i] != ' ')
638                         break;
639         }
640
641         buf[i] = 0;
642         if (!autopick_new_entry(entry, buf, FALSE)) return;
643
644         for (i = 0; i < max_autopick; i++)
645         {
646                 if (!strcmp(entry->name, autopick_list[i].name)
647                         && entry->flag[0] == autopick_list[i].flag[0]
648                         && entry->flag[1] == autopick_list[i].flag[1]
649                         && entry->dice == autopick_list[i].dice
650                         && entry->bonus == autopick_list[i].bonus)
651                 {
652                         autopick_free_entry(entry);
653                         return;
654                 }
655         }
656
657         add_autopick_list(entry);
658         return;
659 }
660
661
662 /*
663  * Reconstruct preference line from entry
664  */
665 concptr autopick_line_from_entry(autopick_type *entry)
666 {
667         char buf[MAX_LINELEN];
668         *buf = '\0';
669         if (!(entry->action & DO_DISPLAY)) strcat(buf, "(");
670         if (entry->action & DO_QUERY_AUTOPICK) strcat(buf, ";");
671         if (entry->action & DO_AUTODESTROY) strcat(buf, "!");
672         if (entry->action & DONT_AUTOPICK) strcat(buf, "~");
673
674         char *ptr;
675         ptr = buf;
676         if (IS_FLG(FLG_ALL)) ADD_KEY(KEY_ALL);
677         if (IS_FLG(FLG_COLLECTING)) ADD_KEY(KEY_COLLECTING);
678         if (IS_FLG(FLG_UNAWARE)) ADD_KEY(KEY_UNAWARE);
679         if (IS_FLG(FLG_UNIDENTIFIED)) ADD_KEY(KEY_UNIDENTIFIED);
680         if (IS_FLG(FLG_IDENTIFIED)) ADD_KEY(KEY_IDENTIFIED);
681         if (IS_FLG(FLG_STAR_IDENTIFIED)) ADD_KEY(KEY_STAR_IDENTIFIED);
682         if (IS_FLG(FLG_BOOSTED)) ADD_KEY(KEY_BOOSTED);
683
684         if (IS_FLG(FLG_MORE_DICE))
685         {
686                 ADD_KEY(KEY_MORE_THAN);
687                 strcat(ptr, format("%d", entry->dice));
688                 ADD_KEY(KEY_DICE);
689         }
690
691         if (IS_FLG(FLG_MORE_BONUS))
692         {
693                 ADD_KEY(KEY_MORE_BONUS);
694                 strcat(ptr, format("%d", entry->bonus));
695                 ADD_KEY(KEY_MORE_BONUS2);
696         }
697
698         if (IS_FLG(FLG_UNREADABLE)) ADD_KEY(KEY_UNREADABLE);
699         if (IS_FLG(FLG_REALM1)) ADD_KEY(KEY_REALM1);
700         if (IS_FLG(FLG_REALM2)) ADD_KEY(KEY_REALM2);
701         if (IS_FLG(FLG_FIRST)) ADD_KEY(KEY_FIRST);
702         if (IS_FLG(FLG_SECOND)) ADD_KEY(KEY_SECOND);
703         if (IS_FLG(FLG_THIRD)) ADD_KEY(KEY_THIRD);
704         if (IS_FLG(FLG_FOURTH)) ADD_KEY(KEY_FOURTH);
705         if (IS_FLG(FLG_WANTED)) ADD_KEY(KEY_WANTED);
706         if (IS_FLG(FLG_UNIQUE)) ADD_KEY(KEY_UNIQUE);
707         if (IS_FLG(FLG_HUMAN)) ADD_KEY(KEY_HUMAN);
708         if (IS_FLG(FLG_WORTHLESS)) ADD_KEY(KEY_WORTHLESS);
709         if (IS_FLG(FLG_GOOD)) ADD_KEY(KEY_GOOD);
710         if (IS_FLG(FLG_NAMELESS)) ADD_KEY(KEY_NAMELESS);
711         if (IS_FLG(FLG_AVERAGE)) ADD_KEY(KEY_AVERAGE);
712         if (IS_FLG(FLG_RARE)) ADD_KEY(KEY_RARE);
713         if (IS_FLG(FLG_COMMON)) ADD_KEY(KEY_COMMON);
714         if (IS_FLG(FLG_EGO)) ADD_KEY(KEY_EGO);
715
716         if (IS_FLG(FLG_ARTIFACT)) ADD_KEY(KEY_ARTIFACT);
717
718         bool sepa_flag = TRUE;
719         if (IS_FLG(FLG_ITEMS)) ADD_KEY2(KEY_ITEMS);
720         else if (IS_FLG(FLG_WEAPONS)) ADD_KEY2(KEY_WEAPONS);
721         else if (IS_FLG(FLG_FAVORITE_WEAPONS)) ADD_KEY2(KEY_FAVORITE_WEAPONS);
722         else if (IS_FLG(FLG_ARMORS)) ADD_KEY2(KEY_ARMORS);
723         else if (IS_FLG(FLG_MISSILES)) ADD_KEY2(KEY_MISSILES);
724         else if (IS_FLG(FLG_DEVICES)) ADD_KEY2(KEY_DEVICES);
725         else if (IS_FLG(FLG_LIGHTS)) ADD_KEY2(KEY_LIGHTS);
726         else if (IS_FLG(FLG_JUNKS)) ADD_KEY2(KEY_JUNKS);
727         else if (IS_FLG(FLG_CORPSES)) ADD_KEY2(KEY_CORPSES);
728         else if (IS_FLG(FLG_SPELLBOOKS)) ADD_KEY2(KEY_SPELLBOOKS);
729         else if (IS_FLG(FLG_HAFTED)) ADD_KEY2(KEY_HAFTED);
730         else if (IS_FLG(FLG_SHIELDS)) ADD_KEY2(KEY_SHIELDS);
731         else if (IS_FLG(FLG_BOWS)) ADD_KEY2(KEY_BOWS);
732         else if (IS_FLG(FLG_RINGS)) ADD_KEY2(KEY_RINGS);
733         else if (IS_FLG(FLG_AMULETS)) ADD_KEY2(KEY_AMULETS);
734         else if (IS_FLG(FLG_SUITS)) ADD_KEY2(KEY_SUITS);
735         else if (IS_FLG(FLG_CLOAKS)) ADD_KEY2(KEY_CLOAKS);
736         else if (IS_FLG(FLG_HELMS)) ADD_KEY2(KEY_HELMS);
737         else if (IS_FLG(FLG_GLOVES)) ADD_KEY2(KEY_GLOVES);
738         else if (IS_FLG(FLG_BOOTS)) ADD_KEY2(KEY_BOOTS);
739         else if (!IS_FLG(FLG_ARTIFACT))
740                 sepa_flag = FALSE;
741
742         if (entry->name && entry->name[0])
743         {
744                 if (sepa_flag) strcat(buf, ":");
745
746                 int i = strlen(buf);
747                 int j = 0;
748                 while (entry->name[j] && i < MAX_LINELEN - 2 - 1)
749                 {
750 #ifdef JP
751                         if (iskanji(entry->name[j]))
752                                 buf[i++] = entry->name[j++];
753 #endif
754                         buf[i++] = entry->name[j++];
755                 }
756                 buf[i] = '\0';
757         }
758
759         if (!entry->insc) return string_make(buf);
760
761         int i, j = 0;
762         strcat(buf, "#");
763         i = strlen(buf);
764
765         while (entry->insc[j] && i < MAX_LINELEN - 2)
766         {
767 #ifdef JP
768                 if (iskanji(entry->insc[j]))
769                         buf[i++] = entry->insc[j++];
770 #endif
771                 buf[i++] = entry->insc[j++];
772         }
773
774         buf[i] = '\0';
775         return string_make(buf);
776 }
777
778
779 /*
780  * Reconstruct preference line from entry and kill entry
781  */
782 static concptr autopick_line_from_entry_kill(autopick_type *entry)
783 {
784         concptr ptr = autopick_line_from_entry(entry);
785         autopick_free_entry(entry);
786         return ptr;
787 }
788
789
790 /*
791  * A function for Auto-picker/destroyer
792  * Examine whether the object matches to the entry
793  */
794 static bool is_autopick_aux(player_type *player_ptr, object_type *o_ptr, autopick_type *entry, concptr o_name)
795 {
796         concptr ptr = entry->name;
797         if (IS_FLG(FLG_UNAWARE) && object_is_aware(o_ptr))
798                 return FALSE;
799
800         if (IS_FLG(FLG_UNIDENTIFIED)
801                 && (object_is_known(o_ptr) || (o_ptr->ident & IDENT_SENSE)))
802                 return FALSE;
803
804         if (IS_FLG(FLG_IDENTIFIED) && !object_is_known(o_ptr))
805                 return FALSE;
806
807         if (IS_FLG(FLG_STAR_IDENTIFIED) &&
808                 (!object_is_known(o_ptr) || !OBJECT_IS_FULL_KNOWN(o_ptr)))
809                 return FALSE;
810
811         if (IS_FLG(FLG_BOOSTED))
812         {
813                 object_kind *k_ptr = &k_info[o_ptr->k_idx];
814                 if (!object_is_melee_weapon(o_ptr))
815                         return FALSE;
816
817                 if ((o_ptr->dd == k_ptr->dd) && (o_ptr->ds == k_ptr->ds))
818                         return FALSE;
819
820                 if (!object_is_known(o_ptr) && object_is_quest_target(o_ptr))
821                 {
822                         return FALSE;
823                 }
824         }
825
826         if (IS_FLG(FLG_MORE_DICE))
827         {
828                 if (o_ptr->dd * o_ptr->ds < entry->dice)
829                         return FALSE;
830         }
831
832         if (IS_FLG(FLG_MORE_BONUS))
833         {
834                 if (!object_is_known(o_ptr)) return FALSE;
835
836                 if (o_ptr->pval)
837                 {
838                         if (o_ptr->pval < entry->bonus) return FALSE;
839                 }
840                 else
841                 {
842                         if (o_ptr->to_h < entry->bonus &&
843                                 o_ptr->to_d < entry->bonus &&
844                                 o_ptr->to_a < entry->bonus &&
845                                 o_ptr->pval < entry->bonus)
846                                 return FALSE;
847                 }
848         }
849
850         if (IS_FLG(FLG_WORTHLESS) && object_value(o_ptr) > 0)
851                 return FALSE;
852
853         if (IS_FLG(FLG_ARTIFACT))
854         {
855                 if (!object_is_known(o_ptr) || !object_is_artifact(o_ptr))
856                         return FALSE;
857         }
858
859         if (IS_FLG(FLG_EGO))
860         {
861                 if (!object_is_ego(o_ptr)) return FALSE;
862                 if (!object_is_known(o_ptr) &&
863                         !((o_ptr->ident & IDENT_SENSE) && o_ptr->feeling == FEEL_EXCELLENT))
864                         return FALSE;
865         }
866
867         if (IS_FLG(FLG_GOOD))
868         {
869                 if (!object_is_equipment(o_ptr)) return FALSE;
870                 if (object_is_known(o_ptr))
871                 {
872                         if (!object_is_nameless(o_ptr))
873                                 return FALSE;
874
875                         if (o_ptr->to_a <= 0 && (o_ptr->to_h + o_ptr->to_d) <= 0)
876                                 return FALSE;
877                 }
878                 else if (o_ptr->ident & IDENT_SENSE)
879                 {
880                         switch (o_ptr->feeling)
881                         {
882                         case FEEL_GOOD:
883                                 break;
884
885                         default:
886                                 return FALSE;
887                         }
888                 }
889                 else
890                 {
891                         return FALSE;
892                 }
893         }
894
895         if (IS_FLG(FLG_NAMELESS))
896         {
897                 if (!object_is_equipment(o_ptr)) return FALSE;
898                 if (object_is_known(o_ptr))
899                 {
900                         if (!object_is_nameless(o_ptr))
901                                 return FALSE;
902                 }
903                 else if (o_ptr->ident & IDENT_SENSE)
904                 {
905                         switch (o_ptr->feeling)
906                         {
907                         case FEEL_AVERAGE:
908                         case FEEL_GOOD:
909                         case FEEL_BROKEN:
910                         case FEEL_CURSED:
911                                 break;
912
913                         default:
914                                 return FALSE;
915                         }
916                 }
917                 else
918                 {
919                         return FALSE;
920                 }
921         }
922
923         if (IS_FLG(FLG_AVERAGE))
924         {
925                 if (!object_is_equipment(o_ptr)) return FALSE;
926                 if (object_is_known(o_ptr))
927                 {
928                         if (!object_is_nameless(o_ptr))
929                                 return FALSE;
930
931                         if (object_is_cursed(o_ptr) || object_is_broken(o_ptr))
932                                 return FALSE;
933
934                         if (o_ptr->to_a > 0 || (o_ptr->to_h + o_ptr->to_d) > 0)
935                                 return FALSE;
936                 }
937                 else if (o_ptr->ident & IDENT_SENSE)
938                 {
939                         switch (o_ptr->feeling)
940                         {
941                         case FEEL_AVERAGE:
942                                 break;
943
944                         default:
945                                 return FALSE;
946                         }
947                 }
948                 else
949                 {
950                         return FALSE;
951                 }
952         }
953
954         if (IS_FLG(FLG_RARE) && !object_is_rare(o_ptr))
955                 return FALSE;
956
957         if (IS_FLG(FLG_COMMON) && object_is_rare(o_ptr))
958                 return FALSE;
959
960         if (IS_FLG(FLG_WANTED) && !object_is_bounty(o_ptr))
961                 return FALSE;
962
963         if (IS_FLG(FLG_UNIQUE) &&
964                 ((o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_STATUE) ||
965                         !(r_info[o_ptr->pval].flags1 & RF1_UNIQUE)))
966                 return FALSE;
967
968         if (IS_FLG(FLG_HUMAN) &&
969                 (o_ptr->tval != TV_CORPSE ||
970                         !my_strchr("pht", r_info[o_ptr->pval].d_char)))
971                 return FALSE;
972
973         if (IS_FLG(FLG_UNREADABLE) &&
974                 (o_ptr->tval < TV_LIFE_BOOK ||
975                         check_book_realm(player_ptr, o_ptr->tval, o_ptr->sval)))
976                 return FALSE;
977
978         if (IS_FLG(FLG_REALM1) &&
979                 (REALM1_BOOK != o_ptr->tval ||
980                         player_ptr->pclass == CLASS_SORCERER ||
981                         player_ptr->pclass == CLASS_RED_MAGE))
982                 return FALSE;
983
984         if (IS_FLG(FLG_REALM2) &&
985                 (REALM2_BOOK != o_ptr->tval ||
986                         player_ptr->pclass == CLASS_SORCERER ||
987                         player_ptr->pclass == CLASS_RED_MAGE))
988                 return FALSE;
989
990         if (IS_FLG(FLG_FIRST) &&
991                 (o_ptr->tval < TV_LIFE_BOOK || 0 != o_ptr->sval))
992                 return FALSE;
993
994         if (IS_FLG(FLG_SECOND) &&
995                 (o_ptr->tval < TV_LIFE_BOOK || 1 != o_ptr->sval))
996                 return FALSE;
997
998         if (IS_FLG(FLG_THIRD) &&
999                 (o_ptr->tval < TV_LIFE_BOOK || 2 != o_ptr->sval))
1000                 return FALSE;
1001
1002         if (IS_FLG(FLG_FOURTH) &&
1003                 (o_ptr->tval < TV_LIFE_BOOK || 3 != o_ptr->sval))
1004                 return FALSE;
1005
1006         if (IS_FLG(FLG_WEAPONS))
1007         {
1008                 if (!object_is_weapon(o_ptr))
1009                         return FALSE;
1010         }
1011         else if (IS_FLG(FLG_FAVORITE_WEAPONS))
1012         {
1013                 if (!object_is_favorite(o_ptr))
1014                         return FALSE;
1015         }
1016         else if (IS_FLG(FLG_ARMORS))
1017         {
1018                 if (!object_is_armour(o_ptr))
1019                         return FALSE;
1020         }
1021         else if (IS_FLG(FLG_MISSILES))
1022         {
1023                 if (!object_is_ammo(o_ptr)) return FALSE;
1024         }
1025         else if (IS_FLG(FLG_DEVICES))
1026         {
1027                 switch (o_ptr->tval)
1028                 {
1029                 case TV_SCROLL: case TV_STAFF: case TV_WAND: case TV_ROD:
1030                         break;
1031                 default: return FALSE;
1032                 }
1033         }
1034         else if (IS_FLG(FLG_LIGHTS))
1035         {
1036                 if (!(o_ptr->tval == TV_LITE))
1037                         return FALSE;
1038         }
1039         else if (IS_FLG(FLG_JUNKS))
1040         {
1041                 switch (o_ptr->tval)
1042                 {
1043                 case TV_SKELETON: case TV_BOTTLE:
1044                 case TV_JUNK: case TV_STATUE:
1045                         break;
1046                 default: return FALSE;
1047                 }
1048         }
1049         else if (IS_FLG(FLG_CORPSES))
1050         {
1051                 if (o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_SKELETON)
1052                         return FALSE;
1053         }
1054         else if (IS_FLG(FLG_SPELLBOOKS))
1055         {
1056                 if (!(o_ptr->tval >= TV_LIFE_BOOK))
1057                         return FALSE;
1058         }
1059         else if (IS_FLG(FLG_HAFTED))
1060         {
1061                 if (!(o_ptr->tval == TV_HAFTED))
1062                         return FALSE;
1063         }
1064         else if (IS_FLG(FLG_SHIELDS))
1065         {
1066                 if (!(o_ptr->tval == TV_SHIELD))
1067                         return FALSE;
1068         }
1069         else if (IS_FLG(FLG_BOWS))
1070         {
1071                 if (!(o_ptr->tval == TV_BOW))
1072                         return FALSE;
1073         }
1074         else if (IS_FLG(FLG_RINGS))
1075         {
1076                 if (!(o_ptr->tval == TV_RING))
1077                         return FALSE;
1078         }
1079         else if (IS_FLG(FLG_AMULETS))
1080         {
1081                 if (!(o_ptr->tval == TV_AMULET))
1082                         return FALSE;
1083         }
1084         else if (IS_FLG(FLG_SUITS))
1085         {
1086                 if (!(o_ptr->tval == TV_DRAG_ARMOR ||
1087                         o_ptr->tval == TV_HARD_ARMOR ||
1088                         o_ptr->tval == TV_SOFT_ARMOR))
1089                         return FALSE;
1090         }
1091         else if (IS_FLG(FLG_CLOAKS))
1092         {
1093                 if (!(o_ptr->tval == TV_CLOAK))
1094                         return FALSE;
1095         }
1096         else if (IS_FLG(FLG_HELMS))
1097         {
1098                 if (!(o_ptr->tval == TV_CROWN || o_ptr->tval == TV_HELM))
1099                         return FALSE;
1100         }
1101         else if (IS_FLG(FLG_GLOVES))
1102         {
1103                 if (!(o_ptr->tval == TV_GLOVES))
1104                         return FALSE;
1105         }
1106         else if (IS_FLG(FLG_BOOTS))
1107         {
1108                 if (!(o_ptr->tval == TV_BOOTS))
1109                         return FALSE;
1110         }
1111
1112         if (*ptr == '^')
1113         {
1114                 ptr++;
1115                 if (strncmp(o_name, ptr, strlen(ptr))) return FALSE;
1116         }
1117         else
1118         {
1119                 if (!my_strstr(o_name, ptr)) return FALSE;
1120         }
1121
1122         if (!IS_FLG(FLG_COLLECTING)) return TRUE;
1123
1124         for (int j = 0; j < INVEN_PACK; j++)
1125         {
1126                 /*
1127                  * 'Collecting' means the item must be absorbed
1128                  * into an inventory slot.
1129                  * But an item can not be absorbed into itself!
1130                  */
1131                 if ((&player_ptr->inventory_list[j] != o_ptr) &&
1132                         object_similar(&player_ptr->inventory_list[j], o_ptr))
1133                         return TRUE;
1134         }
1135
1136         return FALSE;
1137 }
1138
1139
1140 /*
1141  * A function for Auto-picker/destroyer
1142  * Examine whether the object matches to the list of keywords or not.
1143  */
1144 int is_autopick(player_type *player_ptr, object_type *o_ptr)
1145 {
1146         GAME_TEXT o_name[MAX_NLEN];
1147         if (o_ptr->tval == TV_GOLD) return -1;
1148
1149         object_desc(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
1150         str_tolower(o_name);
1151         for (int i = 0; i < max_autopick; i++)
1152         {
1153                 autopick_type *entry = &autopick_list[i];
1154                 if (is_autopick_aux(player_ptr, o_ptr, entry, o_name))
1155                         return i;
1156         }
1157
1158         return -1;
1159 }
1160
1161
1162 /*
1163  *  Auto inscription
1164  */
1165 static void auto_inscribe_item(player_type *player_ptr, object_type *o_ptr, int idx)
1166 {
1167         if (idx < 0 || !autopick_list[idx].insc) return;
1168
1169         if (!o_ptr->inscription)
1170                 o_ptr->inscription = quark_add(autopick_list[idx].insc);
1171
1172         player_ptr->window |= (PW_EQUIP | PW_INVEN);
1173         player_ptr->update |= (PU_BONUS);
1174 }
1175
1176
1177 /*
1178  * Automatically destroy items in this grid.
1179  */
1180 static bool is_opt_confirm_destroy(player_type *player_ptr, object_type *o_ptr)
1181 {
1182         if (!destroy_items) return FALSE;
1183
1184         if (leave_worth)
1185                 if (object_value(o_ptr) > 0) return FALSE;
1186
1187         if (leave_equip)
1188                 if (object_is_weapon_armour_ammo(o_ptr)) return FALSE;
1189
1190         if (leave_chest)
1191                 if ((o_ptr->tval == TV_CHEST) && o_ptr->pval) return FALSE;
1192
1193         if (leave_wanted)
1194         {
1195                 if (object_is_bounty(o_ptr)) return FALSE;
1196         }
1197
1198         if (leave_corpse)
1199                 if (o_ptr->tval == TV_CORPSE) return FALSE;
1200
1201         if (leave_junk)
1202                 if ((o_ptr->tval == TV_SKELETON) || (o_ptr->tval == TV_BOTTLE) || (o_ptr->tval == TV_JUNK) || (o_ptr->tval == TV_STATUE)) return FALSE;
1203
1204         if (leave_special)
1205         {
1206                 if (player_ptr->prace == RACE_DEMON)
1207                 {
1208                         if (o_ptr->tval == TV_CORPSE &&
1209                                 o_ptr->sval == SV_CORPSE &&
1210                                 my_strchr("pht", r_info[o_ptr->pval].d_char))
1211                                 return FALSE;
1212                 }
1213
1214                 if (player_ptr->pclass == CLASS_ARCHER)
1215                 {
1216                         if (o_ptr->tval == TV_SKELETON ||
1217                                 (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_SKELETON))
1218                                 return FALSE;
1219                 }
1220                 else if (player_ptr->pclass == CLASS_NINJA)
1221                 {
1222                         if (o_ptr->tval == TV_LITE &&
1223                                 o_ptr->name2 == EGO_LITE_DARKNESS && object_is_known(o_ptr))
1224                                 return FALSE;
1225                 }
1226                 else if (player_ptr->pclass == CLASS_BEASTMASTER ||
1227                         player_ptr->pclass == CLASS_CAVALRY)
1228                 {
1229                         if (o_ptr->tval == TV_WAND &&
1230                                 o_ptr->sval == SV_WAND_HEAL_MONSTER && object_is_aware(o_ptr))
1231                                 return FALSE;
1232                 }
1233         }
1234
1235         if (o_ptr->tval == TV_GOLD) return FALSE;
1236
1237         return TRUE;
1238 }
1239
1240
1241 static void auto_destroy_item(player_type *player_ptr, object_type *o_ptr, int autopick_idx)
1242 {
1243         bool destroy = FALSE;
1244         if (is_opt_confirm_destroy(player_ptr, o_ptr)) destroy = TRUE;
1245
1246         if (autopick_idx >= 0 &&
1247                 !(autopick_list[autopick_idx].action & DO_AUTODESTROY))
1248                 destroy = FALSE;
1249
1250         if (!always_pickup)
1251         {
1252                 if (autopick_idx >= 0 &&
1253                         (autopick_list[autopick_idx].action & DO_AUTODESTROY))
1254                         destroy = TRUE;
1255         }
1256
1257         if (!destroy) return;
1258
1259         disturb(player_ptr, FALSE, FALSE);
1260         if (!can_player_destroy_object(o_ptr))
1261         {
1262                 GAME_TEXT o_name[MAX_NLEN];
1263                 object_desc(player_ptr, o_name, o_ptr, 0);
1264                 msg_format(_("%sは破壊不能だ。", "You cannot auto-destroy %s."), o_name);
1265                 return;
1266         }
1267
1268         (void)COPY(&autopick_last_destroyed_object, o_ptr, object_type);
1269         o_ptr->marked |= OM_AUTODESTROY;
1270         player_ptr->update |= PU_AUTODESTROY;
1271 }
1272
1273
1274 /*
1275  *  Auto-destroy marked item
1276  */
1277 static void autopick_delayed_alter_aux(player_type *player_ptr, INVENTORY_IDX item)
1278 {
1279         object_type *o_ptr;
1280         o_ptr = REF_ITEM(player_ptr, player_ptr->current_floor_ptr, item);
1281
1282         if (o_ptr->k_idx == 0 || !(o_ptr->marked & OM_AUTODESTROY)) return;
1283
1284         GAME_TEXT o_name[MAX_NLEN];
1285         object_desc(player_ptr, o_name, o_ptr, 0);
1286         if (item >= 0)
1287         {
1288                 inven_item_increase(player_ptr, item, -(o_ptr->number));
1289                 inven_item_optimize(player_ptr, item);
1290         }
1291         else
1292         {
1293                 delete_object_idx(player_ptr, 0 - item);
1294         }
1295
1296         msg_format(_("%sを自動破壊します。", "Auto-destroying %s."), o_name);
1297 }
1298
1299
1300 /*
1301  *  Auto-destroy marked items in inventry and on floor
1302  */
1303 void autopick_delayed_alter(player_type *owner_ptr)
1304 {
1305         INVENTORY_IDX item;
1306
1307         /*
1308          * Scan inventry in reverse order to prevent
1309          * skipping after inven_item_optimize()
1310          */
1311         for (item = INVEN_TOTAL - 1; item >= 0; item--)
1312                 autopick_delayed_alter_aux(owner_ptr, item);
1313
1314         floor_type *floor_ptr = owner_ptr->current_floor_ptr;
1315         item = floor_ptr->grid_array[owner_ptr->y][owner_ptr->x].o_idx;
1316         while (item)
1317         {
1318                 OBJECT_IDX next = floor_ptr->o_list[item].next_o_idx;
1319                 autopick_delayed_alter_aux(owner_ptr, -item);
1320                 item = next;
1321         }
1322 }
1323
1324
1325 /*
1326  * Auto-inscription and/or destroy
1327  *
1328  * Auto-destroyer works only on inventory or on floor stack only when
1329  * requested.
1330  */
1331 void autopick_alter_item(player_type *player_ptr, INVENTORY_IDX item, bool destroy)
1332 {
1333         object_type *o_ptr;
1334         o_ptr = REF_ITEM(player_ptr, player_ptr->current_floor_ptr, item);
1335         int idx = is_autopick(player_ptr, o_ptr);
1336         auto_inscribe_item(player_ptr, o_ptr, idx);
1337         if (destroy && item <= INVEN_PACK)
1338                 auto_destroy_item(player_ptr, o_ptr, idx);
1339 }
1340
1341
1342 /*
1343  * Automatically pickup/destroy items in this grid.
1344  */
1345 void autopick_pickup_items(player_type* player_ptr, grid_type *g_ptr)
1346 {
1347         OBJECT_IDX this_o_idx, next_o_idx = 0;
1348         for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1349         {
1350                 object_type *o_ptr = &player_ptr->current_floor_ptr->o_list[this_o_idx];
1351                 next_o_idx = o_ptr->next_o_idx;
1352                 int idx = is_autopick(player_ptr, o_ptr);
1353                 auto_inscribe_item(player_ptr, o_ptr, idx);
1354                 bool is_auto_pickup = idx >= 0;
1355                 is_auto_pickup &= (autopick_list[idx].action & (DO_AUTOPICK | DO_QUERY_AUTOPICK)) != 0;
1356                 if (!is_auto_pickup)
1357                 {
1358                         auto_destroy_item(player_ptr, o_ptr, idx);
1359                         continue;
1360                 }
1361
1362                 disturb(player_ptr, FALSE, FALSE);
1363                 if (!inven_carry_okay(o_ptr))
1364                 {
1365                         GAME_TEXT o_name[MAX_NLEN];
1366                         object_desc(player_ptr, o_name, o_ptr, 0);
1367                         msg_format(_("ザックには%sを入れる隙間がない。", "You have no room for %s."), o_name);
1368                         o_ptr->marked |= OM_NOMSG;
1369                         continue;
1370                 }
1371
1372                 if (!(autopick_list[idx].action & DO_QUERY_AUTOPICK))
1373                 {
1374                         py_pickup_aux(player_ptr, this_o_idx);
1375                         continue;
1376                 }
1377
1378                 char out_val[MAX_NLEN + 20];
1379                 GAME_TEXT o_name[MAX_NLEN];
1380                 if (o_ptr->marked & OM_NO_QUERY)
1381                 {
1382                         continue;
1383                 }
1384
1385                 object_desc(player_ptr, o_name, o_ptr, 0);
1386                 sprintf(out_val, _("%sを拾いますか? ", "Pick up %s? "), o_name);
1387                 if (!get_check(out_val))
1388                 {
1389                         o_ptr->marked |= OM_NOMSG | OM_NO_QUERY;
1390                         continue;
1391                 }
1392
1393                 py_pickup_aux(player_ptr, this_o_idx);
1394         }
1395 }
1396
1397
1398 static const char autoregister_header[] = "?:$AUTOREGISTER";
1399
1400 /*
1401  *  Clear auto registered lines in the picktype.prf .
1402  */
1403 static bool clear_auto_register(player_type *player_ptr)
1404 {
1405         char tmp_file[1024];
1406         char pref_file[1024];
1407         char buf[1024];
1408         FILE *pref_fff;
1409         FILE *tmp_fff;
1410         int num = 0;
1411         bool autoregister = FALSE;
1412         bool okay = TRUE;
1413
1414         path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_WITH_PNAME));
1415         pref_fff = my_fopen(pref_file, "r");
1416
1417         if (!pref_fff)
1418         {
1419                 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_DEFAULT));
1420                 pref_fff = my_fopen(pref_file, "r");
1421         }
1422
1423         if (!pref_fff)
1424         {
1425                 return TRUE;
1426         }
1427
1428         tmp_fff = my_fopen_temp(tmp_file, sizeof(tmp_file));
1429         if (!tmp_fff)
1430         {
1431                 fclose(pref_fff);
1432                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file);
1433                 msg_print(NULL);
1434                 return FALSE;
1435         }
1436
1437         while (TRUE)
1438         {
1439                 if (my_fgets(pref_fff, buf, sizeof(buf))) break;
1440
1441                 if (autoregister)
1442                 {
1443                         if (buf[0] != '#' && buf[0] != '?') num++;
1444                         continue;
1445                 }
1446
1447                 if (streq(buf, autoregister_header))
1448                 {
1449                         autoregister = TRUE;
1450                 }
1451                 else
1452                 {
1453                         fprintf(tmp_fff, "%s\n", buf);
1454                 }
1455         }
1456
1457         my_fclose(pref_fff);
1458         my_fclose(tmp_fff);
1459
1460         if (num)
1461         {
1462                 msg_format(_("以前のキャラクター用の自動設定(%d行)が残っています。",
1463                         "Auto registered lines (%d lines) for previous character are remaining."), num);
1464                 strcpy(buf, _("古い設定行は削除します。よろしいですか?", "These lines will be deleted.  Are you sure? "));
1465
1466                 if (!get_check(buf))
1467                 {
1468                         okay = FALSE;
1469                         autoregister = FALSE;
1470
1471                         msg_print(_("エディタのカット&ペースト等を使って必要な行を避難してください。",
1472                                 "Use cut & paste of auto picker editor (_) to keep old prefs."));
1473                 }
1474         }
1475
1476         if (autoregister)
1477         {
1478                 tmp_fff = my_fopen(tmp_file, "r");
1479                 pref_fff = my_fopen(pref_file, "w");
1480
1481                 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
1482                         fprintf(pref_fff, "%s\n", buf);
1483
1484                 my_fclose(pref_fff);
1485                 my_fclose(tmp_fff);
1486         }
1487
1488         fd_kill(tmp_file);
1489         return okay;
1490 }
1491
1492
1493 /*
1494  *  Automatically register an auto-destroy preference line
1495  */
1496 bool autopick_autoregister(player_type *player_ptr, object_type *o_ptr)
1497 {
1498         char buf[1024];
1499         char pref_file[1024];
1500         FILE *pref_fff;
1501         autopick_type an_entry, *entry = &an_entry;
1502         int match_autopick = is_autopick(player_ptr, o_ptr);
1503         if (match_autopick != -1)
1504         {
1505                 concptr what;
1506                 byte act = autopick_list[match_autopick].action;
1507                 if (act & DO_AUTOPICK) what = _("自動で拾う", "auto-pickup");
1508                 else if (act & DO_AUTODESTROY) what = _("自動破壊する", "auto-destroy");
1509                 else if (act & DONT_AUTOPICK) what = _("放置する", "leave on floor");
1510                 else what = _("確認して拾う", "query auto-pickup");
1511
1512                 msg_format(_("そのアイテムは既に%sように設定されています。", "The object is already registered to %s."), what);
1513                 return FALSE;
1514         }
1515
1516         if ((object_is_known(o_ptr) && object_is_artifact(o_ptr)) ||
1517                 ((o_ptr->ident & IDENT_SENSE) &&
1518                 (o_ptr->feeling == FEEL_TERRIBLE || o_ptr->feeling == FEEL_SPECIAL)))
1519         {
1520                 GAME_TEXT o_name[MAX_NLEN];
1521                 object_desc(player_ptr, o_name, o_ptr, 0);
1522                 msg_format(_("%sは破壊不能だ。", "You cannot auto-destroy %s."), o_name);
1523                 return FALSE;
1524         }
1525
1526         if (!player_ptr->autopick_autoregister)
1527         {
1528                 if (!clear_auto_register(player_ptr)) return FALSE;
1529         }
1530
1531         path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_WITH_PNAME));
1532         pref_fff = my_fopen(pref_file, "r");
1533
1534         if (!pref_fff)
1535         {
1536                 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(player_ptr, PT_DEFAULT));
1537                 pref_fff = my_fopen(pref_file, "r");
1538         }
1539
1540         if (pref_fff)
1541         {
1542                 while (TRUE)
1543                 {
1544                         if (my_fgets(pref_fff, buf, sizeof(buf)))
1545                         {
1546                                 player_ptr->autopick_autoregister = FALSE;
1547                                 break;
1548                         }
1549
1550                         if (streq(buf, autoregister_header))
1551                         {
1552                                 player_ptr->autopick_autoregister = TRUE;
1553                                 break;
1554                         }
1555                 }
1556
1557                 fclose(pref_fff);
1558         }
1559         else
1560         {
1561                 /*
1562                  * File could not be opened for reading.  Assume header not
1563                  * present.
1564                  */
1565                 player_ptr->autopick_autoregister = FALSE;
1566         }
1567
1568         pref_fff = my_fopen(pref_file, "a");
1569         if (!pref_fff)
1570         {
1571                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), pref_file);
1572                 msg_print(NULL);
1573                 return FALSE;
1574         }
1575
1576         if (!player_ptr->autopick_autoregister)
1577         {
1578                 fprintf(pref_fff, "%s\n", autoregister_header);
1579
1580                 fprintf(pref_fff, "%s\n", _("# *警告!!* 以降の行は自動登録されたものです。",
1581                         "# *Warning!* The lines below will be deleted later."));
1582                 fprintf(pref_fff, "%s\n", _("# 後で自動的に削除されますので、必要な行は上の方へ移動しておいてください。",
1583                         "# Keep it by cut & paste if you need these lines for future characters."));
1584                 player_ptr->autopick_autoregister = TRUE;
1585         }
1586
1587         autopick_entry_from_object(player_ptr, entry, o_ptr);
1588         entry->action = DO_AUTODESTROY;
1589         add_autopick_list(entry);
1590
1591         concptr tmp = autopick_line_from_entry(entry);
1592         fprintf(pref_fff, "%s\n", tmp);
1593         string_free(tmp);
1594         fclose(pref_fff);
1595         return TRUE;
1596 }
1597
1598
1599 /*
1600  * Describe which kind of object is Auto-picked/destroyed
1601  */
1602 static void describe_autopick(char *buff, autopick_type *entry)
1603 {
1604         concptr str = entry->name;
1605         byte act = entry->action;
1606         concptr insc = entry->insc;
1607         int i;
1608
1609         bool top = FALSE;
1610
1611 #ifdef JP
1612         concptr before_str[100], body_str;
1613         int before_n = 0;
1614
1615         body_str = "アイテム";
1616         if (IS_FLG(FLG_COLLECTING))
1617                 before_str[before_n++] = "収集中で既に持っているスロットにまとめられる";
1618
1619         if (IS_FLG(FLG_UNAWARE))
1620                 before_str[before_n++] = "未鑑定でその効果も判明していない";
1621
1622         if (IS_FLG(FLG_UNIDENTIFIED))
1623                 before_str[before_n++] = "未鑑定の";
1624
1625         if (IS_FLG(FLG_IDENTIFIED))
1626                 before_str[before_n++] = "鑑定済みの";
1627
1628         if (IS_FLG(FLG_STAR_IDENTIFIED))
1629                 before_str[before_n++] = "完全に鑑定済みの";
1630
1631         if (IS_FLG(FLG_BOOSTED))
1632         {
1633                 before_str[before_n++] = "ダメージダイスが通常より大きい";
1634                 body_str = "武器";
1635         }
1636
1637         if (IS_FLG(FLG_MORE_DICE))
1638         {
1639                 static char more_than_desc_str[] = "___";
1640                 before_str[before_n++] = "ダメージダイスの最大値が";
1641                 body_str = "武器";
1642
1643                 sprintf(more_than_desc_str, "%d", entry->dice);
1644                 before_str[before_n++] = more_than_desc_str;
1645                 before_str[before_n++] = "以上の";
1646         }
1647
1648         if (IS_FLG(FLG_MORE_BONUS))
1649         {
1650                 static char more_bonus_desc_str[] = "___";
1651                 before_str[before_n++] = "修正値が(+";
1652
1653                 sprintf(more_bonus_desc_str, "%d", entry->bonus);
1654                 before_str[before_n++] = more_bonus_desc_str;
1655                 before_str[before_n++] = ")以上の";
1656         }
1657
1658         if (IS_FLG(FLG_WORTHLESS))
1659                 before_str[before_n++] = "店で無価値と判定される";
1660
1661         if (IS_FLG(FLG_ARTIFACT))
1662         {
1663                 before_str[before_n++] = "アーティファクトの";
1664                 body_str = "装備";
1665         }
1666
1667         if (IS_FLG(FLG_EGO))
1668         {
1669                 before_str[before_n++] = "エゴアイテムの";
1670                 body_str = "装備";
1671         }
1672
1673         if (IS_FLG(FLG_GOOD))
1674         {
1675                 before_str[before_n++] = "上質の";
1676                 body_str = "装備";
1677         }
1678
1679         if (IS_FLG(FLG_NAMELESS))
1680         {
1681                 before_str[before_n++] = "エゴでもアーティファクトでもない";
1682                 body_str = "装備";
1683         }
1684
1685         if (IS_FLG(FLG_AVERAGE))
1686         {
1687                 before_str[before_n++] = "並の";
1688                 body_str = "装備";
1689         }
1690
1691         if (IS_FLG(FLG_RARE))
1692         {
1693                 before_str[before_n++] = "ドラゴン装備やカオス・ブレード等を含む珍しい";
1694                 body_str = "装備";
1695         }
1696
1697         if (IS_FLG(FLG_COMMON))
1698         {
1699                 before_str[before_n++] = "ありふれた(ドラゴン装備やカオス・ブレード等の珍しい物ではない)";
1700                 body_str = "装備";
1701         }
1702
1703         if (IS_FLG(FLG_WANTED))
1704         {
1705                 before_str[before_n++] = "ハンター事務所で賞金首とされている";
1706                 body_str = "死体や骨";
1707         }
1708
1709         if (IS_FLG(FLG_HUMAN))
1710         {
1711                 before_str[before_n++] = "悪魔魔法で使うための人間やヒューマノイドの";
1712                 body_str = "死体や骨";
1713         }
1714
1715         if (IS_FLG(FLG_UNIQUE))
1716         {
1717                 before_str[before_n++] = "ユニークモンスターの";
1718                 body_str = "死体や骨";
1719         }
1720
1721         if (IS_FLG(FLG_UNREADABLE))
1722         {
1723                 before_str[before_n++] = "あなたが読めない領域の";
1724                 body_str = "魔法書";
1725         }
1726
1727         if (IS_FLG(FLG_REALM1))
1728         {
1729                 before_str[before_n++] = "第一領域の";
1730                 body_str = "魔法書";
1731         }
1732
1733         if (IS_FLG(FLG_REALM2))
1734         {
1735                 before_str[before_n++] = "第二領域の";
1736                 body_str = "魔法書";
1737         }
1738
1739         if (IS_FLG(FLG_FIRST))
1740         {
1741                 before_str[before_n++] = "全4冊の内の1冊目の";
1742                 body_str = "魔法書";
1743         }
1744
1745         if (IS_FLG(FLG_SECOND))
1746         {
1747                 before_str[before_n++] = "全4冊の内の2冊目の";
1748                 body_str = "魔法書";
1749         }
1750
1751         if (IS_FLG(FLG_THIRD))
1752         {
1753                 before_str[before_n++] = "全4冊の内の3冊目の";
1754                 body_str = "魔法書";
1755         }
1756
1757         if (IS_FLG(FLG_FOURTH))
1758         {
1759                 before_str[before_n++] = "全4冊の内の4冊目の";
1760                 body_str = "魔法書";
1761         }
1762
1763         if (IS_FLG(FLG_ITEMS))
1764                 ; /* Nothing to do */
1765         else if (IS_FLG(FLG_WEAPONS))
1766                 body_str = "武器";
1767         else if (IS_FLG(FLG_FAVORITE_WEAPONS))
1768                 body_str = "得意武器";
1769         else if (IS_FLG(FLG_ARMORS))
1770                 body_str = "防具";
1771         else if (IS_FLG(FLG_MISSILES))
1772                 body_str = "弾や矢やクロスボウの矢";
1773         else if (IS_FLG(FLG_DEVICES))
1774                 body_str = "巻物や魔法棒や杖やロッド";
1775         else if (IS_FLG(FLG_LIGHTS))
1776                 body_str = "光源用のアイテム";
1777         else if (IS_FLG(FLG_JUNKS))
1778                 body_str = "折れた棒等のガラクタ";
1779         else if (IS_FLG(FLG_CORPSES))
1780                 body_str = "死体や骨";
1781         else if (IS_FLG(FLG_SPELLBOOKS))
1782                 body_str = "魔法書";
1783         else if (IS_FLG(FLG_HAFTED))
1784                 body_str = "鈍器";
1785         else if (IS_FLG(FLG_SHIELDS))
1786                 body_str = "盾";
1787         else if (IS_FLG(FLG_BOWS))
1788                 body_str = "スリングや弓やクロスボウ";
1789         else if (IS_FLG(FLG_RINGS))
1790                 body_str = "指輪";
1791         else if (IS_FLG(FLG_AMULETS))
1792                 body_str = "アミュレット";
1793         else if (IS_FLG(FLG_SUITS))
1794                 body_str = "鎧";
1795         else if (IS_FLG(FLG_CLOAKS))
1796                 body_str = "クローク";
1797         else if (IS_FLG(FLG_HELMS))
1798                 body_str = "ヘルメットや冠";
1799         else if (IS_FLG(FLG_GLOVES))
1800                 body_str = "籠手";
1801         else if (IS_FLG(FLG_BOOTS))
1802                 body_str = "ブーツ";
1803
1804         *buff = '\0';
1805         if (!before_n)
1806                 strcat(buff, "全ての");
1807         else for (i = 0; i < before_n && before_str[i]; i++)
1808                 strcat(buff, before_str[i]);
1809
1810         strcat(buff, body_str);
1811
1812         if (*str)
1813         {
1814                 if (*str == '^')
1815                 {
1816                         str++;
1817                         top = TRUE;
1818                 }
1819
1820                 strcat(buff, "で、名前が「");
1821                 strncat(buff, str, 80);
1822                 if (top)
1823                         strcat(buff, "」で始まるもの");
1824                 else
1825                         strcat(buff, "」を含むもの");
1826         }
1827
1828         if (insc)
1829         {
1830                 strncat(buff, format("に「%s」", insc), 80);
1831
1832                 if (my_strstr(insc, "%%all"))
1833                         strcat(buff, "(%%allは全能力を表す英字の記号で置換)");
1834                 else if (my_strstr(insc, "%all"))
1835                         strcat(buff, "(%allは全能力を表す記号で置換)");
1836                 else if (my_strstr(insc, "%%"))
1837                         strcat(buff, "(%%は追加能力を表す英字の記号で置換)");
1838                 else if (my_strstr(insc, "%"))
1839                         strcat(buff, "(%は追加能力を表す記号で置換)");
1840
1841                 strcat(buff, "と刻んで");
1842         }
1843         else
1844                 strcat(buff, "を");
1845
1846         if (act & DONT_AUTOPICK)
1847                 strcat(buff, "放置する。");
1848         else if (act & DO_AUTODESTROY)
1849                 strcat(buff, "破壊する。");
1850         else if (act & DO_QUERY_AUTOPICK)
1851                 strcat(buff, "確認の後に拾う。");
1852         else
1853                 strcat(buff, "拾う。");
1854
1855         if (act & DO_DISPLAY)
1856         {
1857                 if (act & DONT_AUTOPICK)
1858                         strcat(buff, "全体マップ('M')で'N'を押したときに表示する。");
1859                 else if (act & DO_AUTODESTROY)
1860                         strcat(buff, "全体マップ('M')で'K'を押したときに表示する。");
1861                 else
1862                         strcat(buff, "全体マップ('M')で'M'を押したときに表示する。");
1863         }
1864         else
1865                 strcat(buff, "全体マップには表示しない。");
1866
1867 #else /* JP */
1868
1869         concptr before_str[20], after_str[20], which_str[20], whose_str[20], body_str;
1870         int before_n = 0, after_n = 0, which_n = 0, whose_n = 0;
1871         body_str = "items";
1872         if (IS_FLG(FLG_COLLECTING))
1873                 which_str[which_n++] = "can be absorbed into an existing inventory list slot";
1874
1875         if (IS_FLG(FLG_UNAWARE))
1876         {
1877                 before_str[before_n++] = "unidentified";
1878                 whose_str[whose_n++] = "basic abilities are not known";
1879         }
1880
1881         if (IS_FLG(FLG_UNIDENTIFIED))
1882                 before_str[before_n++] = "unidentified";
1883
1884         if (IS_FLG(FLG_IDENTIFIED))
1885                 before_str[before_n++] = "identified";
1886
1887         if (IS_FLG(FLG_STAR_IDENTIFIED))
1888                 before_str[before_n++] = "fully identified";
1889
1890         if (IS_FLG(FLG_RARE))
1891         {
1892                 before_str[before_n++] = "very rare";
1893                 body_str = "equipments";
1894                 after_str[after_n++] = "such as Dragon armor, Blades of Chaos, etc.";
1895         }
1896
1897         if (IS_FLG(FLG_COMMON))
1898         {
1899                 before_str[before_n++] = "relatively common";
1900                 body_str = "equipments";
1901                 after_str[after_n++] = "compared to very rare Dragon armor, Blades of Chaos, etc.";
1902         }
1903
1904         if (IS_FLG(FLG_WORTHLESS))
1905         {
1906                 before_str[before_n++] = "worthless";
1907                 which_str[which_n++] = "can not be sold at stores";
1908         }
1909
1910         if (IS_FLG(FLG_ARTIFACT))
1911         {
1912                 before_str[before_n++] = "artifact";
1913         }
1914
1915         if (IS_FLG(FLG_EGO))
1916         {
1917                 before_str[before_n++] = "ego";
1918         }
1919
1920         if (IS_FLG(FLG_GOOD))
1921         {
1922                 body_str = "equipment";
1923                 which_str[which_n++] = "have good quality";
1924         }
1925
1926         if (IS_FLG(FLG_NAMELESS))
1927         {
1928                 body_str = "equipment";
1929                 which_str[which_n++] = "is neither ego-item nor artifact";
1930         }
1931
1932         if (IS_FLG(FLG_AVERAGE))
1933         {
1934                 body_str = "equipment";
1935                 which_str[which_n++] = "have average quality";
1936         }
1937
1938         if (IS_FLG(FLG_BOOSTED))
1939         {
1940                 body_str = "weapons";
1941                 whose_str[whose_n++] = "damage dice is bigger than normal";
1942         }
1943
1944         if (IS_FLG(FLG_MORE_DICE))
1945         {
1946                 static char more_than_desc_str[] =
1947                         "maximum damage from dice is bigger than __";
1948                 body_str = "weapons";
1949
1950                 sprintf(more_than_desc_str + sizeof(more_than_desc_str) - 3,
1951                         "%d", entry->dice);
1952                 whose_str[whose_n++] = more_than_desc_str;
1953         }
1954
1955         if (IS_FLG(FLG_MORE_BONUS))
1956         {
1957                 static char more_bonus_desc_str[] =
1958                         "magical bonus is bigger than (+__)";
1959
1960                 sprintf(more_bonus_desc_str + sizeof(more_bonus_desc_str) - 4,
1961                         "%d)", entry->bonus);
1962                 whose_str[whose_n++] = more_bonus_desc_str;
1963         }
1964
1965         if (IS_FLG(FLG_WANTED))
1966         {
1967                 body_str = "corpse or skeletons";
1968                 which_str[which_n++] = "is wanted at the Hunter's Office";
1969         }
1970
1971         if (IS_FLG(FLG_HUMAN))
1972         {
1973                 before_str[before_n++] = "humanoid";
1974                 body_str = "corpse or skeletons";
1975                 which_str[which_n++] = "can be used for Daemon magic";
1976         }
1977
1978         if (IS_FLG(FLG_UNIQUE))
1979         {
1980                 before_str[before_n++] = "unique monster's";
1981                 body_str = "corpse or skeletons";
1982         }
1983
1984         if (IS_FLG(FLG_UNREADABLE))
1985         {
1986                 body_str = "spellbooks";
1987                 after_str[after_n++] = "of different realms from yours";
1988         }
1989
1990         if (IS_FLG(FLG_REALM1))
1991         {
1992                 body_str = "spellbooks";
1993                 after_str[after_n++] = "of your first realm";
1994         }
1995
1996         if (IS_FLG(FLG_REALM2))
1997         {
1998                 body_str = "spellbooks";
1999                 after_str[after_n++] = "of your second realm";
2000         }
2001
2002         if (IS_FLG(FLG_FIRST))
2003         {
2004                 before_str[before_n++] = "first one of four";
2005                 body_str = "spellbooks";
2006         }
2007
2008         if (IS_FLG(FLG_SECOND))
2009         {
2010                 before_str[before_n++] = "second one of four";
2011                 body_str = "spellbooks";
2012         }
2013
2014         if (IS_FLG(FLG_THIRD))
2015         {
2016                 before_str[before_n++] = "third one of four";
2017                 body_str = "spellbooks";
2018         }
2019
2020         if (IS_FLG(FLG_FOURTH))
2021         {
2022                 before_str[before_n++] = "fourth one of four";
2023                 body_str = "spellbooks";
2024         }
2025
2026         if (IS_FLG(FLG_ITEMS))
2027                 ; /* Nothing to do */
2028         else if (IS_FLG(FLG_WEAPONS))
2029                 body_str = "weapons";
2030         else if (IS_FLG(FLG_FAVORITE_WEAPONS))
2031                 body_str = "favorite weapons";
2032         else if (IS_FLG(FLG_ARMORS))
2033                 body_str = "armors";
2034         else if (IS_FLG(FLG_MISSILES))
2035                 body_str = "shots, arrows or crossbow bolts";
2036         else if (IS_FLG(FLG_DEVICES))
2037                 body_str = "scrolls, wands, staffs or rods";
2038         else if (IS_FLG(FLG_LIGHTS))
2039                 body_str = "light sources";
2040         else if (IS_FLG(FLG_JUNKS))
2041                 body_str = "junk such as broken sticks";
2042         else if (IS_FLG(FLG_CORPSES))
2043                 body_str = "corpses or skeletons";
2044         else if (IS_FLG(FLG_SPELLBOOKS))
2045                 body_str = "spellbooks";
2046         else if (IS_FLG(FLG_HAFTED))
2047                 body_str = "hafted weapons";
2048         else if (IS_FLG(FLG_SHIELDS))
2049                 body_str = "shields";
2050         else if (IS_FLG(FLG_BOWS))
2051                 body_str = "slings, bows or crossbows";
2052         else if (IS_FLG(FLG_RINGS))
2053                 body_str = "rings";
2054         else if (IS_FLG(FLG_AMULETS))
2055                 body_str = "amulets";
2056         else if (IS_FLG(FLG_SUITS))
2057                 body_str = "body armors";
2058         else if (IS_FLG(FLG_CLOAKS))
2059                 body_str = "cloaks";
2060         else if (IS_FLG(FLG_HELMS))
2061                 body_str = "helms or crowns";
2062         else if (IS_FLG(FLG_GLOVES))
2063                 body_str = "gloves";
2064         else if (IS_FLG(FLG_BOOTS))
2065                 body_str = "boots";
2066
2067         if (*str)
2068         {
2069                 if (*str == '^')
2070                 {
2071                         str++;
2072                         top = TRUE;
2073                         whose_str[whose_n++] = "name begins with \"";
2074                 }
2075                 else
2076                         which_str[which_n++] = "have \"";
2077         }
2078
2079
2080         if (act & DONT_AUTOPICK)
2081                 strcpy(buff, "Leave on floor ");
2082         else if (act & DO_AUTODESTROY)
2083                 strcpy(buff, "Destroy ");
2084         else if (act & DO_QUERY_AUTOPICK)
2085                 strcpy(buff, "Ask to pick up ");
2086         else
2087                 strcpy(buff, "Pickup ");
2088
2089         if (insc)
2090         {
2091                 strncat(buff, format("and inscribe \"%s\"", insc), 80);
2092
2093                 if (my_strstr(insc, "%all"))
2094                         strcat(buff, ", replacing %all with code string representing all abilities,");
2095                 else if (my_strstr(insc, "%"))
2096                         strcat(buff, ", replacing % with code string representing extra random abilities,");
2097
2098                 strcat(buff, " on ");
2099         }
2100
2101         if (!before_n)
2102                 strcat(buff, "all ");
2103         else for (i = 0; i < before_n && before_str[i]; i++)
2104         {
2105                 strcat(buff, before_str[i]);
2106                 strcat(buff, " ");
2107         }
2108
2109         strcat(buff, body_str);
2110
2111         for (i = 0; i < after_n && after_str[i]; i++)
2112         {
2113                 strcat(buff, " ");
2114                 strcat(buff, after_str[i]);
2115         }
2116
2117         for (i = 0; i < whose_n && whose_str[i]; i++)
2118         {
2119                 if (i == 0)
2120                         strcat(buff, " whose ");
2121                 else
2122                         strcat(buff, ", and ");
2123
2124                 strcat(buff, whose_str[i]);
2125         }
2126
2127         if (*str && top)
2128         {
2129                 strcat(buff, str);
2130                 strcat(buff, "\"");
2131         }
2132
2133         if (whose_n && which_n)
2134                 strcat(buff, ", and ");
2135
2136         for (i = 0; i < which_n && which_str[i]; i++)
2137         {
2138                 if (i == 0)
2139                         strcat(buff, " which ");
2140                 else
2141                         strcat(buff, ", and ");
2142
2143                 strcat(buff, which_str[i]);
2144         }
2145
2146         if (*str && !top)
2147         {
2148                 strncat(buff, str, 80);
2149                 strcat(buff, "\" as part of its name");
2150         }
2151         strcat(buff, ".");
2152
2153         if (act & DO_DISPLAY)
2154         {
2155                 if (act & DONT_AUTOPICK)
2156                         strcat(buff, "  Display these items when you press the N key in the full 'M'ap.");
2157                 else if (act & DO_AUTODESTROY)
2158                         strcat(buff, "  Display these items when you press the K key in the full 'M'ap.");
2159                 else
2160                         strcat(buff, "  Display these items when you press the M key in the full 'M'ap.");
2161         }
2162         else
2163                 strcat(buff, " Not displayed in the full map.");
2164 #endif /* JP */
2165 }
2166
2167
2168 /*
2169  * Read whole lines of a file to memory
2170  */
2171 static concptr *read_text_lines(concptr filename)
2172 {
2173         concptr *lines_list = NULL;
2174         FILE *fff;
2175
2176         int lines = 0;
2177         char buf[1024];
2178
2179         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2180         fff = my_fopen(buf, "r");
2181         if (!fff) return NULL;
2182
2183         C_MAKE(lines_list, MAX_LINES, concptr);
2184         while (my_fgets(fff, buf, sizeof(buf)) == 0)
2185         {
2186                 lines_list[lines++] = string_make(buf);
2187                 if (lines >= MAX_LINES - 1) break;
2188         }
2189
2190         if (lines == 0)
2191                 lines_list[0] = string_make("");
2192
2193         my_fclose(fff);
2194         return lines_list;
2195 }
2196
2197
2198 /*
2199  * Copy the default autopick file to the user directory
2200  */
2201 static void prepare_default_pickpref(player_type *player_ptr)
2202 {
2203         const concptr messages[] = {
2204                 _("あなたは「自動拾いエディタ」を初めて起動しました。", "You have activated the Auto-Picker Editor for the first time."),
2205                 _("自動拾いのユーザー設定ファイルがまだ書かれていないので、", "Since user pref file for autopick is not yet created,"),
2206                 _("基本的な自動拾い設定ファイルをlib/pref/picktype.prfからコピーします。", "the default setting is loaded from lib/pref/pickpref.prf ."),
2207                 NULL
2208         };
2209
2210         concptr filename = pickpref_filename(player_ptr, PT_DEFAULT);
2211         for (int i = 0; messages[i]; i++)
2212         {
2213                 msg_print(messages[i]);
2214         }
2215
2216         msg_print(NULL);
2217         char buf[1024];
2218         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2219         FILE *user_fp;
2220         user_fp = my_fopen(buf, "w");
2221         if (!user_fp) return;
2222
2223         fprintf(user_fp, "#***\n");
2224         for (int i = 0; messages[i]; i++)
2225         {
2226                 fprintf(user_fp, "#***  %s\n", messages[i]);
2227         }
2228
2229         fprintf(user_fp, "#***\n\n\n");
2230         path_build(buf, sizeof(buf), ANGBAND_DIR_PREF, filename);
2231         FILE *pref_fp;
2232         pref_fp = my_fopen(buf, "r");
2233
2234         if (!pref_fp)
2235         {
2236                 my_fclose(user_fp);
2237                 return;
2238         }
2239
2240         while (!my_fgets(pref_fp, buf, sizeof(buf)))
2241         {
2242                 fprintf(user_fp, "%s\n", buf);
2243         }
2244
2245         my_fclose(user_fp);
2246         my_fclose(pref_fp);
2247 }
2248
2249 /*
2250  * Read an autopick prefence file to memory
2251  * Prepare default if no user file is found
2252  */
2253 static concptr *read_pickpref_text_lines(player_type *player_ptr, int *filename_mode_p)
2254 {
2255         /* Try a filename with player name */
2256         *filename_mode_p = PT_WITH_PNAME;
2257         char buf[1024];
2258         strcpy(buf, pickpref_filename(player_ptr, *filename_mode_p));
2259         concptr *lines_list;
2260         lines_list = read_text_lines(buf);
2261
2262         if (!lines_list)
2263         {
2264                 *filename_mode_p = PT_DEFAULT;
2265                 strcpy(buf, pickpref_filename(player_ptr, *filename_mode_p));
2266                 lines_list = read_text_lines(buf);
2267         }
2268
2269         if (!lines_list)
2270         {
2271                 prepare_default_pickpref(player_ptr);
2272                 lines_list = read_text_lines(buf);
2273         }
2274
2275         if (!lines_list)
2276         {
2277                 C_MAKE(lines_list, MAX_LINES, concptr);
2278                 lines_list[0] = string_make("");
2279         }
2280
2281         return lines_list;
2282 }
2283
2284
2285 /*
2286  * Write whole lines of memory to a file.
2287  */
2288 static bool write_text_lines(concptr filename, concptr *lines_list)
2289 {
2290         char buf[1024];
2291         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2292         FILE *fff;
2293         fff = my_fopen(buf, "w");
2294         if (!fff) return FALSE;
2295
2296         for (int lines = 0; lines_list[lines]; lines++)
2297         {
2298                 my_fputs(fff, lines_list[lines], 1024);
2299         }
2300
2301         my_fclose(fff);
2302         return TRUE;
2303 }
2304
2305
2306 /*
2307  * Free memory of lines_list.
2308  */
2309 static void free_text_lines(concptr *lines_list)
2310 {
2311         for (int lines = 0; lines_list[lines]; lines++)
2312         {
2313                 string_free(lines_list[lines]);
2314         }
2315
2316         /* free list of pointers */
2317         C_KILL(lines_list, MAX_LINES, concptr);
2318 }
2319
2320
2321 /*
2322  * Delete or insert string
2323  */
2324 static void toggle_keyword(text_body_type *tb, BIT_FLAGS flg)
2325 {
2326         int by1, by2;
2327         bool add = TRUE;
2328         bool fixed = FALSE;
2329         if (tb->mark)
2330         {
2331                 by1 = MIN(tb->my, tb->cy);
2332                 by2 = MAX(tb->my, tb->cy);
2333         }
2334         else /* if (!tb->mark) */
2335         {
2336                 by1 = by2 = tb->cy;
2337         }
2338
2339         for (int y = by1; y <= by2; y++)
2340         {
2341                 autopick_type an_entry, *entry = &an_entry;
2342                 if (!autopick_new_entry(entry, tb->lines_list[y], !fixed)) continue;
2343
2344                 string_free(tb->lines_list[y]);
2345                 if (!fixed)
2346                 {
2347                         if (!IS_FLG(flg)) add = TRUE;
2348                         else add = FALSE;
2349
2350                         fixed = TRUE;
2351                 }
2352
2353                 if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
2354                 {
2355                         int i;
2356                         for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
2357                                 REM_FLG(i);
2358                 }
2359                 else if (FLG_UNAWARE <= flg && flg <= FLG_STAR_IDENTIFIED)
2360                 {
2361                         int i;
2362                         for (i = FLG_UNAWARE; i <= FLG_STAR_IDENTIFIED; i++)
2363                                 REM_FLG(i);
2364                 }
2365                 else if (FLG_ARTIFACT <= flg && flg <= FLG_AVERAGE)
2366                 {
2367                         int i;
2368                         for (i = FLG_ARTIFACT; i <= FLG_AVERAGE; i++)
2369                                 REM_FLG(i);
2370                 }
2371                 else if (FLG_RARE <= flg && flg <= FLG_COMMON)
2372                 {
2373                         int i;
2374                         for (i = FLG_RARE; i <= FLG_COMMON; i++)
2375                                 REM_FLG(i);
2376                 }
2377
2378                 if (add) ADD_FLG(flg);
2379                 else REM_FLG(flg);
2380
2381                 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
2382                 tb->dirty_flags |= DIRTY_ALL;
2383                 tb->changed = TRUE;
2384         }
2385 }
2386
2387
2388 /*
2389  * Change command letter
2390  */
2391 static void toggle_command_letter(text_body_type *tb, byte flg)
2392 {
2393         autopick_type an_entry, *entry = &an_entry;
2394         int by1, by2, y;
2395         bool add = TRUE;
2396         bool fixed = FALSE;
2397         if (tb->mark)
2398         {
2399                 by1 = MIN(tb->my, tb->cy);
2400                 by2 = MAX(tb->my, tb->cy);
2401         }
2402         else /* if (!tb->mark) */
2403         {
2404                 by1 = by2 = tb->cy;
2405         }
2406
2407         for (y = by1; y <= by2; y++)
2408         {
2409                 int wid = 0;
2410
2411                 if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue;
2412
2413                 string_free(tb->lines_list[y]);
2414
2415                 if (!fixed)
2416                 {
2417                         if (!(entry->action & flg)) add = TRUE;
2418                         else add = FALSE;
2419
2420                         fixed = TRUE;
2421                 }
2422
2423                 if (entry->action & DONT_AUTOPICK) wid--;
2424                 else if (entry->action & DO_AUTODESTROY) wid--;
2425                 else if (entry->action & DO_QUERY_AUTOPICK) wid--;
2426                 if (!(entry->action & DO_DISPLAY)) wid--;
2427
2428                 if (flg != DO_DISPLAY)
2429                 {
2430                         entry->action &= ~(DO_AUTOPICK | DONT_AUTOPICK | DO_AUTODESTROY | DO_QUERY_AUTOPICK);
2431                         if (add) entry->action |= flg;
2432                         else entry->action |= DO_AUTOPICK;
2433                 }
2434                 else
2435                 {
2436                         entry->action &= ~(DO_DISPLAY);
2437                         if (add) entry->action |= flg;
2438                 }
2439
2440                 if (tb->cy == y)
2441                 {
2442                         if (entry->action & DONT_AUTOPICK) wid++;
2443                         else if (entry->action & DO_AUTODESTROY) wid++;
2444                         else if (entry->action & DO_QUERY_AUTOPICK) wid++;
2445                         if (!(entry->action & DO_DISPLAY)) wid++;
2446
2447                         if (wid > 0) tb->cx++;
2448                         if (wid < 0 && tb->cx > 0) tb->cx--;
2449                 }
2450
2451                 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
2452                 tb->dirty_flags |= DIRTY_ALL;
2453                 tb->changed = TRUE;
2454         }
2455 }
2456
2457
2458 /*
2459  * Delete or insert string
2460  */
2461 static void add_keyword(text_body_type *tb, BIT_FLAGS flg)
2462 {
2463         int by1, by2;
2464         if (tb->mark)
2465         {
2466                 by1 = MIN(tb->my, tb->cy);
2467                 by2 = MAX(tb->my, tb->cy);
2468         }
2469         else
2470         {
2471                 by1 = by2 = tb->cy;
2472         }
2473
2474         for (int y = by1; y <= by2; y++)
2475         {
2476                 autopick_type an_entry, *entry = &an_entry;
2477                 if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue;
2478
2479                 if (IS_FLG(flg))
2480                 {
2481                         autopick_free_entry(entry);
2482                         continue;
2483                 }
2484
2485                 string_free(tb->lines_list[y]);
2486                 if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
2487                 {
2488                         int i;
2489                         for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
2490                                 REM_FLG(i);
2491                 }
2492
2493                 ADD_FLG(flg);
2494                 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
2495                 tb->dirty_flags |= DIRTY_ALL;
2496                 tb->changed = TRUE;
2497         }
2498 }
2499
2500
2501 /*
2502  * Check if this line is expression or not.
2503  * And update it if it is.
2504  */
2505 static void check_expression_line(text_body_type *tb, int y)
2506 {
2507         concptr s = tb->lines_list[y];
2508
2509         if ((s[0] == '?' && s[1] == ':') ||
2510                 (tb->states[y] & LSTAT_BYPASS))
2511         {
2512                 tb->dirty_flags |= DIRTY_EXPRESSION;
2513         }
2514 }
2515
2516
2517 /*
2518  * Add an empty line at the last of the file
2519  */
2520 static bool add_empty_line(text_body_type *tb)
2521 {
2522         int num_lines;
2523         for (num_lines = 0; tb->lines_list[num_lines]; num_lines++);
2524
2525         if (num_lines >= MAX_LINES - 2) return FALSE;
2526         if (!tb->lines_list[num_lines - 1][0]) return FALSE;
2527
2528         tb->lines_list[num_lines] = string_make("");
2529         tb->dirty_flags |= DIRTY_EXPRESSION;
2530         tb->changed = TRUE;
2531         return TRUE;
2532 }
2533
2534
2535 /*
2536  * Insert return code and split the line
2537  */
2538 static bool insert_return_code(text_body_type *tb)
2539 {
2540         char buf[MAX_LINELEN];
2541         int i, j, num_lines;
2542
2543         for (num_lines = 0; tb->lines_list[num_lines]; num_lines++);
2544
2545         if (num_lines >= MAX_LINES - 2) return FALSE;
2546         num_lines--;
2547
2548         for (; tb->cy < num_lines; num_lines--)
2549         {
2550                 tb->lines_list[num_lines + 1] = tb->lines_list[num_lines];
2551                 tb->states[num_lines + 1] = tb->states[num_lines];
2552         }
2553
2554         for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
2555         {
2556 #ifdef JP
2557                 if (iskanji(tb->lines_list[tb->cy][i]))
2558                         buf[j++] = tb->lines_list[tb->cy][i++];
2559 #endif
2560                 buf[j++] = tb->lines_list[tb->cy][i];
2561         }
2562
2563         buf[j] = '\0';
2564         tb->lines_list[tb->cy + 1] = string_make(&tb->lines_list[tb->cy][i]);
2565         string_free(tb->lines_list[tb->cy]);
2566         tb->lines_list[tb->cy] = string_make(buf);
2567         tb->dirty_flags |= DIRTY_EXPRESSION;
2568         tb->changed = TRUE;
2569         return TRUE;
2570 }
2571
2572
2573 /*
2574  * Choose an item and get auto-picker entry from it.
2575  */
2576 static bool entry_from_choosed_object(player_type *player_ptr, autopick_type *entry)
2577 {
2578         concptr q = _("どのアイテムを登録しますか? ", "Enter which item? ");
2579         concptr s = _("アイテムを持っていない。", "You have nothing to enter.");
2580         object_type *o_ptr;
2581         o_ptr = choose_object(player_ptr, NULL, q, s, USE_INVEN | USE_FLOOR | USE_EQUIP, 0);
2582         if (!o_ptr) return FALSE;
2583
2584         autopick_entry_from_object(player_ptr, entry, o_ptr);
2585         return TRUE;
2586 }
2587
2588
2589 /*
2590  * Choose an item for search
2591  */
2592 static bool get_object_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp)
2593 {
2594         concptr q = _("どのアイテムを検索しますか? ", "Enter which item? ");
2595         concptr s = _("アイテムを持っていない。", "You have nothing to enter.");
2596         object_type *o_ptr;
2597         o_ptr = choose_object(player_ptr, NULL, q, s, USE_INVEN | USE_FLOOR | USE_EQUIP, 0);
2598         if (!o_ptr) return FALSE;
2599
2600         *o_handle = o_ptr;
2601         string_free(*search_strp);
2602         char buf[MAX_NLEN + 20];
2603         object_desc(player_ptr, buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
2604         *search_strp = string_make(format("<%s>", buf));
2605         return TRUE;
2606 }
2607
2608
2609 /*
2610  * Prepare for search by destroyed object
2611  */
2612 static bool get_destroyed_object_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp)
2613 {
2614         if (!autopick_last_destroyed_object.k_idx) return FALSE;
2615
2616         *o_handle = &autopick_last_destroyed_object;
2617         string_free(*search_strp);
2618         char buf[MAX_NLEN + 20];
2619         object_desc(player_ptr, buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
2620         *search_strp = string_make(format("<%s>", buf));
2621         return TRUE;
2622 }
2623
2624
2625 /*
2626  * Choose an item or string for search
2627  */
2628 static byte get_string_for_search(player_type *player_ptr, object_type **o_handle, concptr *search_strp)
2629 {
2630         /*
2631          * Text color
2632          * TERM_YELLOW : Overwrite mode
2633          * TERM_WHITE : Insert mode
2634          */
2635         byte color = TERM_YELLOW;
2636         char buf[MAX_NLEN + 20];
2637         const int len = 80;
2638         char prompt[] = _("検索(^I:持ち物 ^L:破壊された物): ", "Search key(^I:inven ^L:destroyed): ");
2639         int col = sizeof(prompt) - 1;
2640         if (*search_strp) strcpy(buf, *search_strp);
2641         else buf[0] = '\0';
2642
2643         if (*o_handle) color = TERM_L_GREEN;
2644
2645         prt(prompt, 0, 0);
2646         int pos = 0;
2647         while (TRUE)
2648         {
2649                 bool back = FALSE;
2650                 int skey;
2651
2652                 Term_erase(col, 0, 255);
2653                 Term_putstr(col, 0, -1, color, buf);
2654                 Term_gotoxy(col + pos, 0);
2655
2656                 skey = inkey_special(TRUE);
2657                 switch (skey)
2658                 {
2659                 case SKEY_LEFT:
2660                 case KTRL('b'):
2661                 {
2662                         int i = 0;
2663                         color = TERM_WHITE;
2664                         if (pos == 0) break;
2665
2666                         while (TRUE)
2667                         {
2668                                 int next_pos = i + 1;
2669
2670 #ifdef JP
2671                                 if (iskanji(buf[i])) next_pos++;
2672 #endif
2673                                 if (next_pos >= pos) break;
2674
2675                                 i = next_pos;
2676                         }
2677
2678                         pos = i;
2679                         break;
2680                 }
2681
2682                 case SKEY_RIGHT:
2683                 case KTRL('f'):
2684                         color = TERM_WHITE;
2685                         if ('\0' == buf[pos]) break;
2686
2687 #ifdef JP
2688                         if (iskanji(buf[pos])) pos += 2;
2689                         else pos++;
2690 #else
2691                         pos++;
2692 #endif
2693                         break;
2694
2695                 case ESCAPE:
2696                         return 0;
2697
2698                 case KTRL('r'):
2699                         back = TRUE;
2700                         /* Fall through */
2701
2702                 case '\n':
2703                 case '\r':
2704                 case KTRL('s'):
2705                         if (*o_handle) return (back ? -1 : 1);
2706                         string_free(*search_strp);
2707                         *search_strp = string_make(buf);
2708                         *o_handle = NULL;
2709                         return (back ? -1 : 1);
2710
2711                 case KTRL('i'):
2712                         return get_object_for_search(player_ptr, o_handle, search_strp);
2713
2714                 case KTRL('l'):
2715                         if (get_destroyed_object_for_search(player_ptr, o_handle, search_strp))
2716                                 return 1;
2717                         break;
2718
2719                 case '\010':
2720                 {
2721                         int i = 0;
2722                         color = TERM_WHITE;
2723                         if (pos == 0) break;
2724
2725                         while (TRUE)
2726                         {
2727                                 int next_pos = i + 1;
2728 #ifdef JP
2729                                 if (iskanji(buf[i])) next_pos++;
2730 #endif
2731                                 if (next_pos >= pos) break;
2732
2733                                 i = next_pos;
2734                         }
2735
2736                         pos = i;
2737                 }
2738                         /* Fall through */
2739
2740                 case 0x7F:
2741                 case KTRL('d'):
2742                 {
2743                         int dst, src;
2744                         color = TERM_WHITE;
2745                         if (buf[pos] == '\0') break;
2746
2747                         src = pos + 1;
2748 #ifdef JP
2749                         if (iskanji(buf[pos])) src++;
2750 #endif
2751                         dst = pos;
2752                         while ('\0' != (buf[dst++] = buf[src++]));
2753
2754                         break;
2755                 }
2756
2757                 default:
2758                 {
2759                         char tmp[100];
2760                         char c;
2761                         if (skey & SKEY_MASK) break;
2762
2763                         c = (char)skey;
2764                         if (color != TERM_WHITE)
2765                         {
2766                                 if (color == TERM_L_GREEN)
2767                                 {
2768                                         *o_handle = NULL;
2769                                         string_free(*search_strp);
2770                                         *search_strp = NULL;
2771                                 }
2772
2773                                 buf[0] = '\0';
2774                                 color = TERM_WHITE;
2775                         }
2776
2777                         strcpy(tmp, buf + pos);
2778 #ifdef JP
2779                         if (iskanji(c))
2780                         {
2781                                 char next;
2782                                 inkey_base = TRUE;
2783                                 next = inkey();
2784
2785                                 if (pos + 1 < len)
2786                                 {
2787                                         buf[pos++] = c;
2788                                         buf[pos++] = next;
2789                                 }
2790                                 else
2791                                 {
2792                                         bell();
2793                                 }
2794                         }
2795                         else
2796 #endif
2797                         {
2798 #ifdef JP
2799                                 if (pos < len && (isprint(c) || iskana(c)))
2800 #else
2801                                 if (pos < len && isprint(c))
2802 #endif
2803                                 {
2804                                         buf[pos++] = c;
2805                                 }
2806                                 else
2807                                 {
2808                                         bell();
2809                                 }
2810                         }
2811
2812                         buf[pos] = '\0';
2813                         my_strcat(buf, tmp, len + 1);
2814
2815                         break;
2816                 }
2817                 }
2818
2819                 if (*o_handle == NULL || color == TERM_L_GREEN) continue;
2820
2821                 *o_handle = NULL;
2822                 buf[0] = '\0';
2823                 string_free(*search_strp);
2824                 *search_strp = NULL;
2825         }
2826 }
2827
2828
2829 /*
2830  * Search next line matches for o_ptr
2831  */
2832 static void search_for_object(player_type *player_ptr, text_body_type *tb, object_type *o_ptr, bool forward)
2833 {
2834         autopick_type an_entry, *entry = &an_entry;
2835         GAME_TEXT o_name[MAX_NLEN];
2836         int bypassed_cy = -1;
2837         int i = tb->cy;
2838         object_desc(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
2839         str_tolower(o_name);
2840
2841         while (TRUE)
2842         {
2843                 bool match;
2844                 if (forward)
2845                 {
2846                         if (!tb->lines_list[++i]) break;
2847                 }
2848                 else
2849                 {
2850                         if (--i < 0) break;
2851                 }
2852
2853                 if (!autopick_new_entry(entry, tb->lines_list[i], FALSE)) continue;
2854
2855                 match = is_autopick_aux(player_ptr, o_ptr, entry, o_name);
2856                 autopick_free_entry(entry);
2857                 if (!match)     continue;
2858
2859                 if (tb->states[i] & LSTAT_BYPASS)
2860                 {
2861                         if (bypassed_cy == -1) bypassed_cy = i;
2862                         continue;
2863                 }
2864
2865                 tb->cx = 0;
2866                 tb->cy = i;
2867                 if (bypassed_cy != -1)
2868                 {
2869                         tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
2870                 }
2871
2872                 return;
2873         }
2874
2875         if (bypassed_cy == -1)
2876         {
2877                 tb->dirty_flags |= DIRTY_NOT_FOUND;
2878                 return;
2879         }
2880
2881         tb->cx = 0;
2882         tb->cy = bypassed_cy;
2883         tb->dirty_flags |= DIRTY_INACTIVE;
2884 }
2885
2886
2887 /*
2888  * Search next line matches to the string
2889  */
2890 static void search_for_string(text_body_type *tb, concptr search_str, bool forward)
2891 {
2892         int bypassed_cy = -1;
2893         int bypassed_cx = 0;
2894
2895         int i = tb->cy;
2896         while (TRUE)
2897         {
2898                 concptr pos;
2899                 if (forward)
2900                 {
2901                         if (!tb->lines_list[++i]) break;
2902                 }
2903                 else
2904                 {
2905                         if (--i < 0) break;
2906                 }
2907
2908                 pos = my_strstr(tb->lines_list[i], search_str);
2909                 if (!pos) continue;
2910
2911                 if ((tb->states[i] & LSTAT_BYPASS) &&
2912                         !(tb->states[i] & LSTAT_EXPRESSION))
2913                 {
2914                         if (bypassed_cy == -1)
2915                         {
2916                                 bypassed_cy = i;
2917                                 bypassed_cx = (int)(pos - tb->lines_list[i]);
2918                         }
2919
2920                         continue;
2921                 }
2922
2923                 tb->cx = (int)(pos - tb->lines_list[i]);
2924                 tb->cy = i;
2925
2926                 if (bypassed_cy != -1)
2927                 {
2928                         tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
2929                 }
2930
2931                 return;
2932         }
2933
2934         if (bypassed_cy == -1)
2935         {
2936                 tb->dirty_flags |= DIRTY_NOT_FOUND;
2937                 return;
2938         }
2939
2940         tb->cx = bypassed_cx;
2941         tb->cy = bypassed_cy;
2942         tb->dirty_flags |= DIRTY_INACTIVE;
2943 }
2944
2945
2946 /*
2947  * Find a command by 'key'.
2948  */
2949 static int get_com_id(char key)
2950 {
2951         for (int i = 0; menu_data[i].name; i++)
2952         {
2953                 if (menu_data[i].key == key)
2954                 {
2955                         return menu_data[i].com_id;
2956                 }
2957         }
2958
2959         return 0;
2960 }
2961
2962
2963 /*
2964  * Display the menu, and get a command
2965  */
2966 static int do_command_menu(int level, int start)
2967 {
2968         int max_len = 0;
2969         int col0 = 5 + level * 7;
2970         int row0 = 1 + level * 3;
2971         int menu_id_list[26];
2972         bool redraw = TRUE;
2973         char linestr[MAX_LINELEN];
2974
2975         byte menu_key = 0;
2976         for (int i = start; menu_data[i].level >= level; i++)
2977         {
2978                 int len;
2979
2980                 /* Ignore lower level sub menus */
2981                 if (menu_data[i].level > level) continue;
2982
2983                 len = strlen(menu_data[i].name);
2984                 if (len > max_len) max_len = len;
2985
2986                 menu_id_list[menu_key] = i;
2987                 menu_key++;
2988         }
2989
2990         while (menu_key < 26)
2991         {
2992                 menu_id_list[menu_key] = -1;
2993                 menu_key++;
2994         }
2995
2996         int max_menu_wid = max_len + 3 + 3;
2997
2998         /* Prepare box line */
2999         linestr[0] = '\0';
3000         strcat(linestr, "+");
3001         for (int i = 0; i < max_menu_wid + 2; i++)
3002         {
3003                 strcat(linestr, "-");
3004         }
3005
3006         strcat(linestr, "+");
3007
3008         while (TRUE)
3009         {
3010                 int com_id;
3011                 char key;
3012                 int menu_id;
3013
3014                 if (redraw)
3015                 {
3016                         int row1 = row0 + 1;
3017                         Term_putstr(col0, row0, -1, TERM_WHITE, linestr);
3018
3019                         menu_key = 0;
3020                         for (int i = start; menu_data[i].level >= level; i++)
3021                         {
3022                                 char com_key_str[3];
3023                                 concptr str;
3024                                 if (menu_data[i].level > level) continue;
3025
3026                                 if (menu_data[i].com_id == -1)
3027                                 {
3028                                         strcpy(com_key_str, _("▼", ">"));
3029                                 }
3030                                 else if (menu_data[i].key != -1)
3031                                 {
3032                                         com_key_str[0] = '^';
3033                                         com_key_str[1] = menu_data[i].key + '@';
3034                                         com_key_str[2] = '\0';
3035                                 }
3036                                 else
3037                                 {
3038                                         com_key_str[0] = '\0';
3039                                 }
3040
3041                                 str = format("| %c) %-*s %2s | ", menu_key + 'a', max_len, menu_data[i].name, com_key_str);
3042
3043                                 Term_putstr(col0, row1++, -1, TERM_WHITE, str);
3044
3045                                 menu_key++;
3046                         }
3047
3048                         Term_putstr(col0, row1, -1, TERM_WHITE, linestr);
3049                         redraw = FALSE;
3050                 }
3051
3052                 prt(format(_("(a-%c) コマンド:", "(a-%c) Command:"), menu_key + 'a' - 1), 0, 0);
3053                 key = inkey();
3054
3055                 if (key == ESCAPE) return 0;
3056
3057                 bool is_alphabet = key >= 'a' && key <= 'z';
3058                 if (!is_alphabet)
3059                 {
3060                         com_id = get_com_id(key);
3061                         if (com_id)
3062                         {
3063                                 return com_id;
3064                         }
3065
3066                         continue;
3067                 }
3068
3069                 menu_id = menu_id_list[key - 'a'];
3070
3071                 if (menu_id < 0) continue;
3072
3073                 com_id = menu_data[menu_id].com_id;
3074
3075                 if (com_id == -1)
3076                 {
3077                         com_id = do_command_menu(level + 1, menu_id + 1);
3078
3079                         if (com_id) return com_id;
3080                         else redraw = TRUE;
3081                 }
3082                 else if (com_id)
3083                 {
3084                         return com_id;
3085                 }
3086         }
3087 }
3088
3089
3090 static chain_str_type *new_chain_str(concptr str)
3091 {
3092         chain_str_type *chain;
3093         size_t len = strlen(str);
3094         chain = (chain_str_type *)ralloc(sizeof(chain_str_type) + len * sizeof(char));
3095         strcpy(chain->s, str);
3096         chain->next = NULL;
3097         return chain;
3098 }
3099
3100
3101 static void kill_yank_chain(text_body_type *tb)
3102 {
3103         chain_str_type *chain = tb->yank;
3104         tb->yank = NULL;
3105         tb->yank_eol = TRUE;
3106
3107         while (chain)
3108         {
3109                 chain_str_type *next = chain->next;
3110                 size_t len = strlen(chain->s);
3111
3112                 rnfree(chain, sizeof(chain_str_type) + len * sizeof(char));
3113
3114                 chain = next;
3115         }
3116 }
3117
3118
3119 static void add_str_to_yank(text_body_type *tb, concptr str)
3120 {
3121         tb->yank_eol = FALSE;
3122         if (NULL == tb->yank)
3123         {
3124                 tb->yank = new_chain_str(str);
3125                 return;
3126         }
3127
3128         chain_str_type *chain;
3129         chain = tb->yank;
3130
3131         while (TRUE)
3132         {
3133                 if (!chain->next)
3134                 {
3135                         chain->next = new_chain_str(str);
3136                         return;
3137                 }
3138
3139                 /* Go to next */
3140                 chain = chain->next;
3141         }
3142 }
3143
3144
3145 /*
3146  * Do work for the copy editor-command
3147  */
3148 static void copy_text_to_yank(text_body_type *tb)
3149 {
3150         int len = strlen(tb->lines_list[tb->cy]);
3151         if (tb->cx > len) tb->cx = len;
3152
3153         if (!tb->mark)
3154         {
3155                 tb->cx = 0;
3156                 tb->my = tb->cy;
3157                 tb->mx = len;
3158         }
3159
3160         kill_yank_chain(tb);
3161         if (tb->my != tb->cy)
3162         {
3163                 int by1 = MIN(tb->my, tb->cy);
3164                 int by2 = MAX(tb->my, tb->cy);
3165
3166                 for (int y = by1; y <= by2; y++)
3167                 {
3168                         add_str_to_yank(tb, tb->lines_list[y]);
3169                 }
3170
3171                 add_str_to_yank(tb, "");
3172                 tb->mark = 0;
3173                 tb->dirty_flags |= DIRTY_ALL;
3174                 return;
3175         }
3176
3177         char buf[MAX_LINELEN];
3178         int bx1 = MIN(tb->mx, tb->cx);
3179         int bx2 = MAX(tb->mx, tb->cx);
3180         if (bx2 > len) bx2 = len;
3181
3182         if (bx1 == 0 && bx2 == len)
3183         {
3184                 add_str_to_yank(tb, tb->lines_list[tb->cy]);
3185                 add_str_to_yank(tb, "");
3186         }
3187         else
3188         {
3189                 int end = bx2 - bx1;
3190                 for (int i = 0; i < bx2 - bx1; i++)
3191                 {
3192                         buf[i] = tb->lines_list[tb->cy][bx1 + i];
3193                 }
3194
3195                 buf[end] = '\0';
3196                 add_str_to_yank(tb, buf);
3197         }
3198
3199         tb->mark = 0;
3200         tb->dirty_flags |= DIRTY_ALL;
3201 }
3202
3203
3204 /*
3205  * Draw text
3206  */
3207 static void draw_text_editor(player_type *player_ptr, text_body_type *tb)
3208 {
3209         int i;
3210         int by1 = 0, by2 = 0;
3211
3212         Term_get_size(&tb->wid, &tb->hgt);
3213
3214         /*
3215          * Top line (-1), description line (-3), separator (-1)
3216          *  == -5
3217          */
3218         tb->hgt -= 2 + DESCRIPT_HGT;
3219
3220 #ifdef JP
3221         /* Don't let cursor at second byte of kanji */
3222         for (i = 0; tb->lines_list[tb->cy][i]; i++)
3223                 if (iskanji(tb->lines_list[tb->cy][i]))
3224                 {
3225                         i++;
3226                         if (i == tb->cx)
3227                         {
3228                                 /*
3229                                  * Move to a correct position in the
3230                                  * left or right
3231                                  */
3232                                 if (i & 1) tb->cx--;
3233                                 else tb->cx++;
3234                                 break;
3235                         }
3236                 }
3237 #endif
3238         if (tb->cy < tb->upper || tb->upper + tb->hgt <= tb->cy)
3239                 tb->upper = tb->cy - (tb->hgt) / 2;
3240         if (tb->upper < 0)
3241                 tb->upper = 0;
3242         if ((tb->cx < tb->left + 10 && tb->left > 0) || tb->left + tb->wid - 5 <= tb->cx)
3243                 tb->left = tb->cx - (tb->wid) * 2 / 3;
3244         if (tb->left < 0)
3245                 tb->left = 0;
3246
3247         if (tb->old_wid != tb->wid || tb->old_hgt != tb->hgt)
3248                 tb->dirty_flags |= DIRTY_SCREEN;
3249         else if (tb->old_upper != tb->upper || tb->old_left != tb->left)
3250                 tb->dirty_flags |= DIRTY_ALL;
3251
3252         if (tb->dirty_flags & DIRTY_SCREEN)
3253         {
3254                 tb->dirty_flags |= (DIRTY_ALL | DIRTY_MODE);
3255                 Term_clear();
3256         }
3257
3258         if (tb->dirty_flags & DIRTY_MODE)
3259         {
3260                 char buf[MAX_LINELEN];
3261                 int sepa_length = tb->wid;
3262                 for (i = 0; i < sepa_length; i++)
3263                         buf[i] = '-';
3264                 buf[i] = '\0';
3265                 Term_putstr(0, tb->hgt + 1, sepa_length, TERM_WHITE, buf);
3266         }
3267
3268         if (tb->dirty_flags & DIRTY_EXPRESSION)
3269         {
3270                 byte state = 0;
3271                 for (int y = 0; tb->lines_list[y]; y++)
3272                 {
3273                         char f;
3274                         concptr v;
3275                         concptr s = tb->lines_list[y];
3276                         char *ss, *s_keep;
3277                         int s_len;
3278
3279                         tb->states[y] = state;
3280
3281                         if (*s++ != '?') continue;
3282                         if (*s++ != ':') continue;
3283
3284                         if (streq(s, "$AUTOREGISTER"))
3285                                 state |= LSTAT_AUTOREGISTER;
3286
3287                         s_len = strlen(s);
3288                         ss = (char *)string_make(s);
3289                         s_keep = ss;
3290
3291                         v = process_pref_file_expr(player_ptr, &ss, &f);
3292
3293                         if (streq(v, "0")) state |= LSTAT_BYPASS;
3294                         else state &= ~LSTAT_BYPASS;
3295
3296                         C_KILL(s_keep, s_len + 1, char);
3297
3298                         tb->states[y] = state | LSTAT_EXPRESSION;
3299                 }
3300
3301                 tb->dirty_flags |= DIRTY_ALL;
3302         }
3303
3304         if (tb->mark)
3305         {
3306                 tb->dirty_flags |= DIRTY_ALL;
3307
3308                 by1 = MIN(tb->my, tb->cy);
3309                 by2 = MAX(tb->my, tb->cy);
3310         }
3311
3312         for (i = 0; i < tb->hgt; i++)
3313         {
3314                 int j;
3315                 int leftcol = 0;
3316                 concptr msg;
3317                 byte color;
3318                 int y = tb->upper + i;
3319
3320                 if (!(tb->dirty_flags & DIRTY_ALL) && (tb->dirty_line != y))
3321                         continue;
3322
3323                 msg = tb->lines_list[y];
3324                 if (!msg) break;
3325
3326                 for (j = 0; *msg; msg++, j++)
3327                 {
3328                         if (j == tb->left) break;
3329 #ifdef JP
3330                         if (j > tb->left)
3331                         {
3332                                 leftcol = 1;
3333                                 break;
3334                         }
3335                         if (iskanji(*msg))
3336                         {
3337                                 msg++;
3338                                 j++;
3339                         }
3340 #endif
3341                 }
3342
3343                 Term_erase(0, i + 1, tb->wid);
3344                 if (tb->states[y] & LSTAT_AUTOREGISTER)
3345                 {
3346                         color = TERM_L_RED;
3347                 }
3348                 else
3349                 {
3350                         if (tb->states[y] & LSTAT_BYPASS) color = TERM_SLATE;
3351                         else color = TERM_WHITE;
3352                 }
3353
3354                 if (!tb->mark || (y < by1 || by2 < y))
3355                 {
3356                         Term_putstr(leftcol, i + 1, tb->wid - 1, color, msg);
3357                 }
3358                 else if (by1 != by2)
3359                 {
3360                         Term_putstr(leftcol, i + 1, tb->wid - 1, TERM_YELLOW, msg);
3361                 }
3362                 else
3363                 {
3364                         int x0 = leftcol + tb->left;
3365                         int len = strlen(tb->lines_list[tb->cy]);
3366                         int bx1 = MIN(tb->mx, tb->cx);
3367                         int bx2 = MAX(tb->mx, tb->cx);
3368
3369                         if (bx2 > len) bx2 = len;
3370
3371                         Term_gotoxy(leftcol, i + 1);
3372                         if (x0 < bx1) Term_addstr(bx1 - x0, color, msg);
3373                         if (x0 < bx2) Term_addstr(bx2 - bx1, TERM_YELLOW, msg + (bx1 - x0));
3374                         Term_addstr(-1, color, msg + (bx2 - x0));
3375                 }
3376         }
3377
3378         for (; i < tb->hgt; i++)
3379         {
3380                 Term_erase(0, i + 1, tb->wid);
3381         }
3382
3383         bool is_dirty_diary = (tb->dirty_flags & (DIRTY_ALL | DIRTY_NOT_FOUND | DIRTY_NO_SEARCH)) != 0;
3384         bool is_updated = tb->old_cy != tb->cy || is_dirty_diary || tb->dirty_line == tb->cy;
3385         if (is_updated) return;
3386
3387         autopick_type an_entry, *entry = &an_entry;
3388         concptr str1 = NULL, str2 = NULL;
3389         for (i = 0; i < DESCRIPT_HGT; i++)
3390         {
3391                 Term_erase(0, tb->hgt + 2 + i, tb->wid);
3392         }
3393
3394         if (tb->dirty_flags & DIRTY_NOT_FOUND)
3395         {
3396                 str1 = format(_("パターンが見つかりません: %s", "Pattern not found: %s"), tb->search_str);
3397         }
3398         else if (tb->dirty_flags & DIRTY_SKIP_INACTIVE)
3399         {
3400                 str1 = format(_("無効状態の行をスキップしました。(%sを検索中)",
3401                         "Some inactive lines are skipped. (Searching %s)"), tb->search_str);
3402         }
3403         else if (tb->dirty_flags & DIRTY_INACTIVE)
3404         {
3405                 str1 = format(_("無効状態の行だけが見付かりました。(%sを検索中)",
3406                         "Found only an inactive line. (Searching %s)"), tb->search_str);
3407         }
3408         else if (tb->dirty_flags & DIRTY_NO_SEARCH)
3409         {
3410                 str1 = _("検索するパターンがありません(^S で検索)。", "No pattern to search. (Press ^S to search.)");
3411         }
3412         else if (tb->lines_list[tb->cy][0] == '#')
3413         {
3414                 str1 = _("この行はコメントです。", "This line is a comment.");
3415         }
3416         else if (tb->lines_list[tb->cy][0] && tb->lines_list[tb->cy][1] == ':')
3417         {
3418                 switch (tb->lines_list[tb->cy][0])
3419                 {
3420                 case '?':
3421                         str1 = _("この行は条件分岐式です。", "This line is a Conditional Expression.");
3422                         break;
3423                 case 'A':
3424                         str1 = _("この行はマクロの実行内容を定義します。", "This line defines a Macro action.");
3425                         break;
3426                 case 'P':
3427                         str1 = _("この行はマクロのトリガー・キーを定義します。", "This line defines a Macro trigger key.");
3428                         break;
3429                 case 'C':
3430                         str1 = _("この行はキー配置を定義します。", "This line defines a Keymap.");
3431                         break;
3432                 }
3433
3434                 switch (tb->lines_list[tb->cy][0])
3435                 {
3436                 case '?':
3437                         if (tb->states[tb->cy] & LSTAT_BYPASS)
3438                         {
3439                                 str2 = _("現在の式の値は「偽(=0)」です。", "The expression is 'False'(=0) currently.");
3440                         }
3441                         else
3442                         {
3443                                 str2 = _("現在の式の値は「真(=1)」です。", "The expression is 'True'(=1) currently.");
3444                         }
3445                         break;
3446
3447                 default:
3448                         if (tb->states[tb->cy] & LSTAT_AUTOREGISTER)
3449                         {
3450                                 str2 = _("この行は後で削除されます。", "This line will be delete later.");
3451                         }
3452
3453                         else if (tb->states[tb->cy] & LSTAT_BYPASS)
3454                         {
3455                                 str2 = _("この行は現在は無効な状態です。", "This line is bypassed currently.");
3456                         }
3457                         break;
3458                 }
3459         }
3460         else if (autopick_new_entry(entry, tb->lines_list[tb->cy], FALSE))
3461         {
3462                 char buf[MAX_LINELEN];
3463                 char temp[MAX_LINELEN];
3464                 concptr t;
3465
3466                 describe_autopick(buf, entry);
3467
3468                 if (tb->states[tb->cy] & LSTAT_AUTOREGISTER)
3469                 {
3470                         strcat(buf, _("この行は後で削除されます。", "  This line will be delete later."));
3471                 }
3472
3473                 if (tb->states[tb->cy] & LSTAT_BYPASS)
3474                 {
3475                         strcat(buf, _("この行は現在は無効な状態です。", "  This line is bypassed currently."));
3476                 }
3477
3478                 roff_to_buf(buf, 81, temp, sizeof(temp));
3479                 t = temp;
3480                 for (i = 0; i < 3; i++)
3481                 {
3482                         if (t[0] == 0)
3483                                 break;
3484                         else
3485                         {
3486                                 prt(t, tb->hgt + 1 + 1 + i, 0);
3487                                 t += strlen(t) + 1;
3488                         }
3489                 }
3490                 autopick_free_entry(entry);
3491         }
3492
3493         if (str1) prt(str1, tb->hgt + 1 + 1, 0);
3494         if (str2) prt(str2, tb->hgt + 1 + 2, 0);
3495 }
3496
3497
3498 /*
3499  * Kill segment of a line
3500  */
3501 static void kill_line_segment(text_body_type *tb, int y, int x0, int x1, bool whole)
3502 {
3503         concptr s = tb->lines_list[y];
3504         if (whole && x0 == 0 && s[x1] == '\0' && tb->lines_list[y + 1])
3505         {
3506                 string_free(tb->lines_list[y]);
3507
3508                 int i;
3509                 for (i = y; tb->lines_list[i + 1]; i++)
3510                         tb->lines_list[i] = tb->lines_list[i + 1];
3511                 tb->lines_list[i] = NULL;
3512
3513                 tb->dirty_flags |= DIRTY_EXPRESSION;
3514
3515                 return;
3516         }
3517
3518         if (x0 == x1) return;
3519
3520         char buf[MAX_LINELEN];
3521         char *d = buf;
3522         for (int x = 0; x < x0; x++)
3523                 *(d++) = s[x];
3524
3525         for (int x = x1; s[x]; x++)
3526                 *(d++) = s[x];
3527
3528         *d = '\0';
3529         string_free(tb->lines_list[y]);
3530         tb->lines_list[y] = string_make(buf);
3531         check_expression_line(tb, y);
3532         tb->changed = TRUE;
3533 }
3534
3535
3536 /*
3537  * Get a trigger key and insert ASCII string for the trigger
3538  */
3539 static bool insert_macro_line(text_body_type *tb)
3540 {
3541         int i, n = 0;
3542         flush();
3543         inkey_base = TRUE;
3544         i = inkey();
3545         char buf[1024];
3546         while (i)
3547         {
3548                 buf[n++] = (char)i;
3549                 inkey_base = TRUE;
3550                 inkey_scan = TRUE;
3551                 i = inkey();
3552         }
3553
3554         buf[n] = '\0';
3555         flush();
3556
3557         char tmp[1024];
3558         ascii_to_text(tmp, buf);
3559         if (!tmp[0]) return FALSE;
3560
3561         tb->cx = 0;
3562         insert_return_code(tb);
3563         string_free(tb->lines_list[tb->cy]);
3564         tb->lines_list[tb->cy] = string_make(format("P:%s", tmp));
3565
3566         i = macro_find_exact(buf);
3567         if (i == -1)
3568         {
3569                 tmp[0] = '\0';
3570         }
3571         else
3572         {
3573                 ascii_to_text(tmp, macro__act[i]);
3574         }
3575
3576         insert_return_code(tb);
3577         string_free(tb->lines_list[tb->cy]);
3578         tb->lines_list[tb->cy] = string_make(format("A:%s", tmp));
3579
3580         return TRUE;
3581 }
3582
3583
3584 /*
3585  * Get a command key and insert ASCII string for the key
3586  */
3587 static bool insert_keymap_line(text_body_type *tb)
3588 {
3589         BIT_FLAGS mode;
3590         if (rogue_like_commands)
3591         {
3592                 mode = KEYMAP_MODE_ROGUE;
3593         }
3594         else
3595         {
3596                 mode = KEYMAP_MODE_ORIG;
3597         }
3598
3599         flush();
3600         char buf[2];
3601         buf[0] = inkey();
3602         buf[1] = '\0';
3603
3604         flush();
3605         char tmp[1024];
3606         ascii_to_text(tmp, buf);
3607         if (!tmp[0]) return FALSE;
3608
3609         tb->cx = 0;
3610         insert_return_code(tb);
3611         string_free(tb->lines_list[tb->cy]);
3612         tb->lines_list[tb->cy] = string_make(format("C:%d:%s", mode, tmp));
3613
3614         concptr act = keymap_act[mode][(byte)(buf[0])];
3615         if (act)
3616         {
3617                 ascii_to_text(tmp, act);
3618         }
3619
3620         insert_return_code(tb);
3621         string_free(tb->lines_list[tb->cy]);
3622         tb->lines_list[tb->cy] = string_make(format("A:%s", tmp));
3623
3624         return TRUE;
3625 }
3626
3627
3628 /*
3629  * Execute a single editor command
3630  */
3631 static bool do_editor_command(player_type *player_ptr, text_body_type *tb, int com_id)
3632 {
3633         switch (com_id)
3634         {
3635         case EC_QUIT:
3636                 if (tb->changed)
3637                 {
3638                         if (!get_check(_("全ての変更を破棄してから終了します。よろしいですか? ",
3639                                 "Discard all changes and quit. Are you sure? "))) break;
3640                 }
3641
3642                 return QUIT_WITHOUT_SAVE;
3643
3644         case EC_SAVEQUIT:
3645                 return QUIT_AND_SAVE;
3646
3647         case EC_REVERT:
3648                 if (!get_check(_("全ての変更を破棄して元の状態に戻します。よろしいですか? ",
3649                         "Discard all changes and revert to original file. Are you sure? "))) break;
3650
3651                 free_text_lines(tb->lines_list);
3652                 tb->lines_list = read_pickpref_text_lines(player_ptr, &tb->filename_mode);
3653                 tb->dirty_flags |= DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
3654                 tb->cx = tb->cy = 0;
3655                 tb->mark = 0;
3656
3657                 tb->changed = FALSE;
3658                 break;
3659
3660         case EC_HELP:
3661                 (void)show_file(player_ptr, TRUE, _("jeditor.txt", "editor.txt"), NULL, 0, 0);
3662                 tb->dirty_flags |= DIRTY_SCREEN;
3663
3664                 break;
3665
3666         case EC_RETURN:
3667                 if (tb->mark)
3668                 {
3669                         tb->mark = 0;
3670                         tb->dirty_flags |= DIRTY_ALL;
3671                 }
3672
3673                 insert_return_code(tb);
3674                 tb->cy++;
3675                 tb->cx = 0;
3676
3677                 tb->dirty_flags |= DIRTY_ALL;
3678                 break;
3679
3680         case EC_LEFT:
3681         {
3682                 if (0 < tb->cx)
3683                 {
3684                         int len;
3685 #ifdef JP
3686                         int i;
3687 #endif
3688                         tb->cx--;
3689                         len = strlen(tb->lines_list[tb->cy]);
3690                         if (len < tb->cx) tb->cx = len;
3691 #ifdef JP
3692                         for (i = 0; tb->lines_list[tb->cy][i]; i++)
3693                         {
3694                                 if (iskanji(tb->lines_list[tb->cy][i]))
3695                                 {
3696                                         i++;
3697                                         if (i == tb->cx)
3698                                         {
3699                                                 tb->cx--;
3700                                                 break;
3701                                         }
3702                                 }
3703                         }
3704 #endif
3705                 }
3706                 else if (tb->cy > 0)
3707                 {
3708                         tb->cy--;
3709                         tb->cx = strlen(tb->lines_list[tb->cy]);
3710                 }
3711
3712                 break;
3713         }
3714         case EC_DOWN:
3715                 if (!tb->lines_list[tb->cy + 1])
3716                 {
3717                         if (!add_empty_line(tb)) break;
3718                 }
3719
3720                 tb->cy++;
3721                 break;
3722
3723         case EC_UP:
3724                 if (tb->cy > 0) tb->cy--;
3725                 break;
3726
3727         case EC_RIGHT:
3728         {
3729 #ifdef JP
3730                 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
3731 #endif
3732                 tb->cx++;
3733                 int len = strlen(tb->lines_list[tb->cy]);
3734                 if (len < tb->cx)
3735                 {
3736                         tb->cx = len;
3737                         if (!tb->lines_list[tb->cy + 1])
3738                         {
3739                                 if (!add_empty_line(tb)) break;
3740                         }
3741
3742                         tb->cy++;
3743                         tb->cx = 0;
3744                 }
3745
3746                 break;
3747         }
3748         case EC_BOL:
3749                 tb->cx = 0;
3750                 break;
3751
3752         case EC_EOL:
3753                 tb->cx = strlen(tb->lines_list[tb->cy]);
3754                 break;
3755
3756         case EC_PGUP:
3757                 while (0 < tb->cy && tb->upper <= tb->cy)
3758                         tb->cy--;
3759                 while (0 < tb->upper && tb->cy + 1 < tb->upper + tb->hgt)
3760                         tb->upper--;
3761                 break;
3762
3763         case EC_PGDOWN:
3764                 while (tb->cy < tb->upper + tb->hgt)
3765                 {
3766                         if (!tb->lines_list[tb->cy + 1])
3767                         {
3768                                 if (!add_empty_line(tb)) break;
3769                         }
3770
3771                         tb->cy++;
3772                 }
3773
3774                 tb->upper = tb->cy;
3775                 break;
3776
3777         case EC_TOP:
3778                 tb->cy = 0;
3779                 break;
3780
3781         case EC_BOTTOM:
3782                 while (TRUE)
3783                 {
3784                         if (!tb->lines_list[tb->cy + 1])
3785                         {
3786                                 if (!add_empty_line(tb)) break;
3787                         }
3788
3789                         tb->cy++;
3790                 }
3791
3792                 tb->cx = 0;
3793                 break;
3794
3795         case EC_CUT:
3796         {
3797                 copy_text_to_yank(tb);
3798                 if (tb->my == tb->cy)
3799                 {
3800                         int bx1 = MIN(tb->mx, tb->cx);
3801                         int bx2 = MAX(tb->mx, tb->cx);
3802                         int len = strlen(tb->lines_list[tb->cy]);
3803                         if (bx2 > len) bx2 = len;
3804
3805                         kill_line_segment(tb, tb->cy, bx1, bx2, TRUE);
3806                         tb->cx = bx1;
3807                 }
3808                 else
3809                 {
3810                         int by1 = MIN(tb->my, tb->cy);
3811                         int by2 = MAX(tb->my, tb->cy);
3812
3813                         for (int y = by2; y >= by1; y--)
3814                         {
3815                                 int len = strlen(tb->lines_list[y]);
3816
3817                                 kill_line_segment(tb, y, 0, len, TRUE);
3818                         }
3819
3820                         tb->cy = by1;
3821                         tb->cx = 0;
3822                 }
3823
3824                 tb->mark = 0;
3825                 tb->dirty_flags |= DIRTY_ALL;
3826                 tb->changed = TRUE;
3827                 break;
3828         }
3829         case EC_COPY:
3830                 copy_text_to_yank(tb);
3831
3832                 /*
3833                  * Move cursor position to the end of the selection
3834                  *
3835                  * Pressing ^C ^V correctly duplicates the selection.
3836                  */
3837                 if (tb->my != tb->cy)
3838                 {
3839                         tb->cy = MAX(tb->cy, tb->my);
3840                         if (!tb->lines_list[tb->cy + 1])
3841                         {
3842                                 if (!add_empty_line(tb)) break;
3843                         }
3844
3845                         tb->cy++;
3846                         break;
3847                 }
3848
3849                 tb->cx = MAX(tb->cx, tb->mx);
3850                 if (!tb->lines_list[tb->cy][tb->cx])
3851                 {
3852                         if (!tb->lines_list[tb->cy + 1])
3853                         {
3854                                 if (!add_empty_line(tb)) break;
3855                         }
3856
3857                         tb->cy++;
3858                         tb->cx = 0;
3859                 }
3860
3861                 break;
3862
3863         case EC_PASTE:
3864         {
3865                 chain_str_type *chain = tb->yank;
3866                 int len = strlen(tb->lines_list[tb->cy]);
3867                 if (!chain) break;
3868                 if (tb->cx > len) tb->cx = len;
3869
3870                 if (tb->mark)
3871                 {
3872                         tb->mark = 0;
3873                         tb->dirty_flags |= DIRTY_ALL;
3874                 }
3875
3876                 while (chain)
3877                 {
3878                         concptr yank_str = chain->s;
3879                         char buf[MAX_LINELEN];
3880                         int i;
3881                         char rest[MAX_LINELEN], *rest_ptr = rest;
3882                         for (i = 0; i < tb->cx; i++)
3883                                 buf[i] = tb->lines_list[tb->cy][i];
3884
3885                         strcpy(rest, &(tb->lines_list[tb->cy][i]));
3886                         while (*yank_str && i < MAX_LINELEN - 1)
3887                         {
3888                                 buf[i++] = *yank_str++;
3889                         }
3890
3891                         buf[i] = '\0';
3892                         chain = chain->next;
3893                         if (chain || tb->yank_eol)
3894                         {
3895                                 insert_return_code(tb);
3896                                 string_free(tb->lines_list[tb->cy]);
3897                                 tb->lines_list[tb->cy] = string_make(buf);
3898                                 tb->cx = 0;
3899                                 tb->cy++;
3900
3901                                 continue;
3902                         }
3903
3904                         tb->cx = strlen(buf);
3905                         while (*rest_ptr && i < MAX_LINELEN - 1)
3906                         {
3907                                 buf[i++] = *rest_ptr++;
3908                         }
3909
3910                         buf[i] = '\0';
3911                         string_free(tb->lines_list[tb->cy]);
3912                         tb->lines_list[tb->cy] = string_make(buf);
3913                         break;
3914                 }
3915
3916                 tb->dirty_flags |= DIRTY_ALL;
3917                 tb->dirty_flags |= DIRTY_EXPRESSION;
3918                 tb->changed = TRUE;
3919                 break;
3920         }
3921         case EC_BLOCK:
3922         {
3923                 if (tb->mark)
3924                 {
3925                         tb->mark = 0;
3926                         tb->dirty_flags |= DIRTY_ALL;
3927                         break;
3928                 }
3929
3930                 tb->mark = MARK_MARK;
3931                 if (com_id == tb->old_com_id)
3932                 {
3933                         int tmp = tb->cy;
3934                         tb->cy = tb->my;
3935                         tb->my = tmp;
3936                         tmp = tb->cx;
3937                         tb->cx = tb->mx;
3938                         tb->mx = tmp;
3939                         tb->dirty_flags |= DIRTY_ALL;
3940                         break;
3941                 }
3942
3943                 int len = strlen(tb->lines_list[tb->cy]);
3944
3945                 tb->my = tb->cy;
3946                 tb->mx = tb->cx;
3947                 if (tb->cx > len) tb->mx = len;
3948                 break;
3949         }
3950         case EC_KILL_LINE:
3951         {
3952                 int len = strlen(tb->lines_list[tb->cy]);
3953                 if (tb->cx > len) tb->cx = len;
3954
3955                 if (tb->mark)
3956                 {
3957                         tb->mark = 0;
3958                         tb->dirty_flags |= DIRTY_ALL;
3959                 }
3960
3961                 if (tb->old_com_id != com_id)
3962                 {
3963                         kill_yank_chain(tb);
3964                         tb->yank = NULL;
3965                 }
3966
3967                 if (tb->cx < len)
3968                 {
3969                         add_str_to_yank(tb, &(tb->lines_list[tb->cy][tb->cx]));
3970                         kill_line_segment(tb, tb->cy, tb->cx, len, FALSE);
3971                         tb->dirty_line = tb->cy;
3972                         break;
3973                 }
3974
3975                 if (tb->yank_eol) add_str_to_yank(tb, "");
3976
3977                 tb->yank_eol = TRUE;
3978                 do_editor_command(player_ptr, tb, EC_DELETE_CHAR);
3979                 break;
3980         }
3981         case EC_DELETE_CHAR:
3982         {
3983                 if (tb->mark)
3984                 {
3985                         tb->mark = 0;
3986                         tb->dirty_flags |= DIRTY_ALL;
3987                 }
3988
3989 #ifdef JP
3990                 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
3991 #endif
3992                 tb->cx++;
3993                 int len = strlen(tb->lines_list[tb->cy]);
3994                 if (len >= tb->cx)
3995                 {
3996                         do_editor_command(player_ptr, tb, EC_BACKSPACE);
3997                         break;
3998                 }
3999
4000                 if (tb->lines_list[tb->cy + 1])
4001                 {
4002                         tb->cy++;
4003                         tb->cx = 0;
4004                 }
4005                 else
4006                 {
4007                         tb->cx = len;
4008                         break;
4009                 }
4010
4011                 do_editor_command(player_ptr, tb, EC_BACKSPACE);
4012                 break;
4013         }
4014         case EC_BACKSPACE:
4015         {
4016                 int len, i, j, k;
4017                 char buf[MAX_LINELEN];
4018                 if (tb->mark)
4019                 {
4020                         tb->mark = 0;
4021                         tb->dirty_flags |= DIRTY_ALL;
4022                 }
4023
4024                 len = strlen(tb->lines_list[tb->cy]);
4025                 if (len < tb->cx) tb->cx = len;
4026
4027                 if (tb->cx == 0)
4028                 {
4029                         if (tb->cy == 0) break;
4030                         tb->cx = strlen(tb->lines_list[tb->cy - 1]);
4031                         strcpy(buf, tb->lines_list[tb->cy - 1]);
4032                         strcat(buf, tb->lines_list[tb->cy]);
4033                         string_free(tb->lines_list[tb->cy - 1]);
4034                         string_free(tb->lines_list[tb->cy]);
4035                         tb->lines_list[tb->cy - 1] = string_make(buf);
4036
4037                         for (i = tb->cy; tb->lines_list[i + 1]; i++)
4038                                 tb->lines_list[i] = tb->lines_list[i + 1];
4039
4040                         tb->lines_list[i] = NULL;
4041                         tb->cy--;
4042                         tb->dirty_flags |= DIRTY_ALL;
4043                         tb->dirty_flags |= DIRTY_EXPRESSION;
4044                         tb->changed = TRUE;
4045                         break;
4046                 }
4047
4048                 for (i = j = k = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
4049                 {
4050                         k = j;
4051 #ifdef JP
4052                         if (iskanji(tb->lines_list[tb->cy][i]))
4053                                 buf[j++] = tb->lines_list[tb->cy][i++];
4054 #endif
4055                         buf[j++] = tb->lines_list[tb->cy][i];
4056                 }
4057
4058                 while (j > k)
4059                 {
4060                         tb->cx--;
4061                         j--;
4062                 }
4063
4064                 for (; tb->lines_list[tb->cy][i]; i++)
4065                 {
4066                         buf[j++] = tb->lines_list[tb->cy][i];
4067                 }
4068
4069                 buf[j] = '\0';
4070                 string_free(tb->lines_list[tb->cy]);
4071                 tb->lines_list[tb->cy] = string_make(buf);
4072                 tb->dirty_line = tb->cy;
4073                 check_expression_line(tb, tb->cy);
4074                 tb->changed = TRUE;
4075                 break;
4076         }
4077         case EC_SEARCH_STR:
4078         {
4079                 byte search_dir;
4080                 tb->dirty_flags |= DIRTY_SCREEN;
4081                 search_dir = get_string_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str);
4082
4083                 if (!search_dir) break;
4084
4085                 if (search_dir == 1) do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
4086                 else do_editor_command(player_ptr, tb, EC_SEARCH_BACK);
4087                 break;
4088         }
4089         case EC_SEARCH_FORW:
4090                 if (tb->search_o_ptr)
4091                 {
4092                         search_for_object(player_ptr, tb, tb->search_o_ptr, TRUE);
4093                         break;
4094                 }
4095
4096                 if (tb->search_str && tb->search_str[0])
4097                 {
4098                         search_for_string(tb, tb->search_str, TRUE);
4099                         break;
4100                 }
4101
4102                 tb->dirty_flags |= DIRTY_NO_SEARCH;
4103                 break;
4104
4105         case EC_SEARCH_BACK:
4106                 if (tb->search_o_ptr)
4107                 {
4108                         search_for_object(player_ptr, tb, tb->search_o_ptr, FALSE);
4109                         break;
4110                 }
4111
4112                 if (tb->search_str && tb->search_str[0])
4113                 {
4114                         search_for_string(tb, tb->search_str, FALSE);
4115                         break;
4116                 }
4117
4118                 tb->dirty_flags |= DIRTY_NO_SEARCH;
4119                 break;
4120
4121         case EC_SEARCH_OBJ:
4122                 tb->dirty_flags |= DIRTY_SCREEN;
4123
4124                 if (!get_object_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str)) break;
4125
4126                 do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
4127                 break;
4128
4129         case EC_SEARCH_DESTROYED:
4130                 if (!get_destroyed_object_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str))
4131                 {
4132                         tb->dirty_flags |= DIRTY_NO_SEARCH;
4133                         break;
4134                 }
4135
4136                 do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
4137                 break;
4138
4139         case EC_INSERT_OBJECT:
4140         {
4141                 autopick_type an_entry, *entry = &an_entry;
4142                 if (!entry_from_choosed_object(player_ptr, entry))
4143                 {
4144                         tb->dirty_flags |= DIRTY_SCREEN;
4145                         break;
4146                 }
4147
4148                 tb->cx = 0;
4149                 insert_return_code(tb);
4150                 string_free(tb->lines_list[tb->cy]);
4151                 tb->lines_list[tb->cy] = autopick_line_from_entry_kill(entry);
4152                 tb->dirty_flags |= DIRTY_SCREEN;
4153                 break;
4154         }
4155         case EC_INSERT_DESTROYED:
4156                 if (!tb->last_destroyed) break;
4157
4158                 tb->cx = 0;
4159                 insert_return_code(tb);
4160                 string_free(tb->lines_list[tb->cy]);
4161                 tb->lines_list[tb->cy] = string_make(tb->last_destroyed);
4162                 tb->dirty_flags |= DIRTY_ALL;
4163                 tb->changed = TRUE;
4164                 break;
4165
4166         case EC_INSERT_BLOCK:
4167         {
4168                 char expression[80];
4169                 sprintf(expression, "?:[AND [EQU $RACE %s] [EQU $CLASS %s] [GEQ $LEVEL %02d]]",
4170 #ifdef JP
4171                         rp_ptr->E_title, cp_ptr->E_title,
4172 #else
4173                         rp_ptr->title, cp_ptr->title,
4174 #endif
4175                         player_ptr->lev);
4176                 tb->cx = 0;
4177                 insert_return_code(tb);
4178                 string_free(tb->lines_list[tb->cy]);
4179                 tb->lines_list[tb->cy] = string_make(expression);
4180                 tb->cy++;
4181                 insert_return_code(tb);
4182                 string_free(tb->lines_list[tb->cy]);
4183                 tb->lines_list[tb->cy] = string_make("?:1");
4184                 tb->dirty_flags |= DIRTY_ALL;
4185                 tb->changed = TRUE;
4186                 break;
4187         }
4188
4189         case EC_INSERT_MACRO:
4190                 draw_text_editor(player_ptr, tb);
4191                 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
4192                 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, _("P:<トリガーキー>: ", "P:<Trigger key>: "));
4193                 if (!insert_macro_line(tb)) break;
4194
4195                 tb->cx = 2;
4196                 tb->dirty_flags |= DIRTY_ALL;
4197                 tb->changed = TRUE;
4198                 break;
4199
4200         case EC_INSERT_KEYMAP:
4201                 draw_text_editor(player_ptr, tb);
4202                 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
4203                 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW,
4204                         format(_("C:%d:<コマンドキー>: ", "C:%d:<Keypress>: "), (rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG)));
4205
4206                 if (!insert_keymap_line(tb)) break;
4207
4208                 tb->cx = 2;
4209                 tb->dirty_flags |= DIRTY_ALL;
4210                 tb->changed = TRUE;
4211                 break;
4212
4213         case EC_CL_AUTOPICK: toggle_command_letter(tb, DO_AUTOPICK); break;
4214         case EC_CL_DESTROY: toggle_command_letter(tb, DO_AUTODESTROY); break;
4215         case EC_CL_LEAVE: toggle_command_letter(tb, DONT_AUTOPICK); break;
4216         case EC_CL_QUERY: toggle_command_letter(tb, DO_QUERY_AUTOPICK); break;
4217         case EC_CL_NO_DISP: toggle_command_letter(tb, DO_DISPLAY); break;
4218
4219         case EC_IK_UNAWARE: toggle_keyword(tb, FLG_UNAWARE); break;
4220         case EC_IK_UNIDENTIFIED: toggle_keyword(tb, FLG_UNIDENTIFIED); break;
4221         case EC_IK_IDENTIFIED: toggle_keyword(tb, FLG_IDENTIFIED); break;
4222         case EC_IK_STAR_IDENTIFIED: toggle_keyword(tb, FLG_STAR_IDENTIFIED); break;
4223         case EC_KK_WEAPONS: toggle_keyword(tb, FLG_WEAPONS); break;
4224         case EC_KK_FAVORITE_WEAPONS: toggle_keyword(tb, FLG_FAVORITE_WEAPONS); break;
4225         case EC_KK_ARMORS: toggle_keyword(tb, FLG_ARMORS); break;
4226         case EC_KK_MISSILES: toggle_keyword(tb, FLG_MISSILES); break;
4227         case EC_KK_DEVICES: toggle_keyword(tb, FLG_DEVICES); break;
4228         case EC_KK_LIGHTS: toggle_keyword(tb, FLG_LIGHTS); break;
4229         case EC_KK_JUNKS: toggle_keyword(tb, FLG_JUNKS); break;
4230         case EC_KK_CORPSES: toggle_keyword(tb, FLG_CORPSES); break;
4231         case EC_KK_SPELLBOOKS: toggle_keyword(tb, FLG_SPELLBOOKS); break;
4232         case EC_KK_SHIELDS: toggle_keyword(tb, FLG_SHIELDS); break;
4233         case EC_KK_BOWS: toggle_keyword(tb, FLG_BOWS); break;
4234         case EC_KK_RINGS: toggle_keyword(tb, FLG_RINGS); break;
4235         case EC_KK_AMULETS: toggle_keyword(tb, FLG_AMULETS); break;
4236         case EC_KK_SUITS: toggle_keyword(tb, FLG_SUITS); break;
4237         case EC_KK_CLOAKS: toggle_keyword(tb, FLG_CLOAKS); break;
4238         case EC_KK_HELMS: toggle_keyword(tb, FLG_HELMS); break;
4239         case EC_KK_GLOVES: toggle_keyword(tb, FLG_GLOVES); break;
4240         case EC_KK_BOOTS: toggle_keyword(tb, FLG_BOOTS); break;
4241         case EC_OK_COLLECTING: toggle_keyword(tb, FLG_COLLECTING); break;
4242         case EC_OK_BOOSTED: toggle_keyword(tb, FLG_BOOSTED); break;
4243         case EC_OK_MORE_DICE: toggle_keyword(tb, FLG_MORE_DICE); break;
4244         case EC_OK_MORE_BONUS: toggle_keyword(tb, FLG_MORE_BONUS); break;
4245         case EC_OK_WORTHLESS: toggle_keyword(tb, FLG_WORTHLESS); break;
4246         case EC_OK_ARTIFACT: toggle_keyword(tb, FLG_ARTIFACT); break;
4247         case EC_OK_EGO: toggle_keyword(tb, FLG_EGO); break;
4248         case EC_OK_GOOD: toggle_keyword(tb, FLG_GOOD); break;
4249         case EC_OK_NAMELESS: toggle_keyword(tb, FLG_NAMELESS); break;
4250         case EC_OK_AVERAGE: toggle_keyword(tb, FLG_AVERAGE); break;
4251         case EC_OK_RARE: toggle_keyword(tb, FLG_RARE); break;
4252         case EC_OK_COMMON: toggle_keyword(tb, FLG_COMMON); break;
4253         case EC_OK_WANTED: toggle_keyword(tb, FLG_WANTED); break;
4254         case EC_OK_UNIQUE: toggle_keyword(tb, FLG_UNIQUE); break;
4255         case EC_OK_HUMAN: toggle_keyword(tb, FLG_HUMAN); break;
4256         case EC_OK_UNREADABLE:
4257                 toggle_keyword(tb, FLG_UNREADABLE);
4258                 add_keyword(tb, FLG_SPELLBOOKS);
4259                 break;
4260         case EC_OK_REALM1:
4261                 toggle_keyword(tb, FLG_REALM1);
4262                 add_keyword(tb, FLG_SPELLBOOKS);
4263                 break;
4264         case EC_OK_REALM2:
4265                 toggle_keyword(tb, FLG_REALM2);
4266                 add_keyword(tb, FLG_SPELLBOOKS);
4267                 break;
4268         case EC_OK_FIRST:
4269                 toggle_keyword(tb, FLG_FIRST);
4270                 add_keyword(tb, FLG_SPELLBOOKS);
4271                 break;
4272         case EC_OK_SECOND:
4273                 toggle_keyword(tb, FLG_SECOND);
4274                 add_keyword(tb, FLG_SPELLBOOKS);
4275                 break;
4276         case EC_OK_THIRD:
4277                 toggle_keyword(tb, FLG_THIRD);
4278                 add_keyword(tb, FLG_SPELLBOOKS);
4279                 break;
4280         case EC_OK_FOURTH:
4281                 toggle_keyword(tb, FLG_FOURTH);
4282                 add_keyword(tb, FLG_SPELLBOOKS);
4283                 break;
4284         }
4285
4286         tb->old_com_id = com_id;
4287         return FALSE;
4288 }
4289
4290
4291 /*
4292  * Insert single letter at cursor position.
4293  */
4294 static void insert_single_letter(text_body_type *tb, int key)
4295 {
4296         int i, j, len;
4297         char buf[MAX_LINELEN];
4298
4299         for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
4300         {
4301                 buf[j++] = tb->lines_list[tb->cy][i];
4302         }
4303
4304 #ifdef JP
4305         if (iskanji(key))
4306         {
4307                 int next;
4308
4309                 inkey_base = TRUE;
4310                 next = inkey();
4311                 if (j + 2 < MAX_LINELEN)
4312                 {
4313                         buf[j++] = (char)key;
4314                         buf[j++] = (char)next;
4315                         tb->cx += 2;
4316                 }
4317                 else
4318                         bell();
4319         }
4320         else
4321 #endif
4322         {
4323                 if (j + 1 < MAX_LINELEN)
4324                         buf[j++] = (char)key;
4325                 tb->cx++;
4326         }
4327
4328         for (; tb->lines_list[tb->cy][i] && j + 1 < MAX_LINELEN; i++)
4329                 buf[j++] = tb->lines_list[tb->cy][i];
4330         buf[j] = '\0';
4331
4332         string_free(tb->lines_list[tb->cy]);
4333         tb->lines_list[tb->cy] = string_make(buf);
4334         len = strlen(tb->lines_list[tb->cy]);
4335         if (len < tb->cx) tb->cx = len;
4336
4337         tb->dirty_line = tb->cy;
4338         check_expression_line(tb, tb->cy);
4339         tb->changed = TRUE;
4340 }
4341
4342
4343 /*
4344  * Check special key code and get a movement command id
4345  */
4346 static int analyze_move_key(text_body_type *tb, int skey)
4347 {
4348         int com_id;
4349         if (!(skey & SKEY_MASK)) return 0;
4350
4351         switch (skey & ~SKEY_MOD_MASK)
4352         {
4353         case SKEY_DOWN:   com_id = EC_DOWN;   break;
4354         case SKEY_LEFT:   com_id = EC_LEFT;   break;
4355         case SKEY_RIGHT:  com_id = EC_RIGHT;  break;
4356         case SKEY_UP:     com_id = EC_UP;     break;
4357         case SKEY_PGUP:   com_id = EC_PGUP;   break;
4358         case SKEY_PGDOWN: com_id = EC_PGDOWN; break;
4359         case SKEY_TOP:    com_id = EC_TOP;    break;
4360         case SKEY_BOTTOM: com_id = EC_BOTTOM; break;
4361         default:
4362                 return 0;
4363         }
4364
4365         if (!(skey & SKEY_MOD_SHIFT))
4366         {
4367                 /*
4368                  * Un-shifted cursor keys cancells
4369                  * selection created by shift+cursor.
4370                  */
4371                 if (tb->mark & MARK_BY_SHIFT)
4372                 {
4373                         tb->mark = 0;
4374                         tb->dirty_flags |= DIRTY_ALL;
4375                 }
4376
4377                 return com_id;
4378         }
4379
4380         if (tb->mark) return com_id;
4381
4382         int len = strlen(tb->lines_list[tb->cy]);
4383         tb->mark = MARK_MARK | MARK_BY_SHIFT;
4384         tb->my = tb->cy;
4385         tb->mx = tb->cx;
4386         if (tb->cx > len) tb->mx = len;
4387
4388         if (com_id == EC_UP || com_id == EC_DOWN)
4389         {
4390                 tb->dirty_flags |= DIRTY_ALL;
4391         }
4392         else
4393         {
4394                 tb->dirty_line = tb->cy;
4395         }
4396
4397         return com_id;
4398 }
4399
4400 /*
4401  * In-game editor of Object Auto-picker/Destoryer
4402  * @param player_ptr プレーヤーへの参照ポインタ
4403  */
4404 void do_cmd_edit_autopick(player_type *player_ptr)
4405 {
4406         static int cx_save = 0;
4407         static int cy_save = 0;
4408         text_body_type text_body, *tb = &text_body;
4409         autopick_type an_entry, *entry = &an_entry;
4410         char buf[MAX_LINELEN];
4411         int i;
4412         int key = -1;
4413         static s32b old_autosave_turn = 0L;
4414         byte quit = 0;
4415
4416         tb->changed = FALSE;
4417         tb->cx = cx_save;
4418         tb->cy = cy_save;
4419         tb->upper = tb->left = 0;
4420         tb->mark = 0;
4421         tb->mx = tb->my = 0;
4422         tb->old_cy = tb->old_upper = tb->old_left = -1;
4423         tb->old_wid = tb->old_hgt = -1;
4424         tb->old_com_id = 0;
4425
4426         tb->yank = NULL;
4427         tb->search_o_ptr = NULL;
4428         tb->search_str = NULL;
4429         tb->last_destroyed = NULL;
4430         tb->dirty_flags = DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
4431         tb->dirty_line = -1;
4432         tb->filename_mode = PT_DEFAULT;
4433
4434         if (current_world_ptr->game_turn < old_autosave_turn)
4435         {
4436                 while (old_autosave_turn > current_world_ptr->game_turn) old_autosave_turn -= TURNS_PER_TICK * TOWN_DAWN;
4437         }
4438
4439         if (current_world_ptr->game_turn > old_autosave_turn + 100L)
4440         {
4441                 do_cmd_save_game(player_ptr, TRUE);
4442                 old_autosave_turn = current_world_ptr->game_turn;
4443         }
4444
4445         update_playtime();
4446         init_autopick();
4447         if (autopick_last_destroyed_object.k_idx)
4448         {
4449                 autopick_entry_from_object(player_ptr, entry, &autopick_last_destroyed_object);
4450                 tb->last_destroyed = autopick_line_from_entry_kill(entry);
4451         }
4452
4453         tb->lines_list = read_pickpref_text_lines(player_ptr, &tb->filename_mode);
4454         for (i = 0; i < tb->cy; i++)
4455         {
4456                 if (!tb->lines_list[i])
4457                 {
4458                         tb->cy = tb->cx = 0;
4459                         break;
4460                 }
4461         }
4462
4463         screen_save();
4464         while (!quit)
4465         {
4466                 int com_id = 0;
4467                 draw_text_editor(player_ptr, tb);
4468                 prt(_("(^Q:終了 ^W:セーブして終了, ESC:メニュー, その他:入力)",
4469                         "(^Q:Quit, ^W:Save&Quit, ESC:Menu, Other:Input text)"), 0, 0);
4470                 if (!tb->mark)
4471                 {
4472                         prt(format("(%d,%d)", tb->cx, tb->cy), 0, 60);
4473                 }
4474                 else
4475                 {
4476                         prt(format("(%d,%d)-(%d,%d)", tb->mx, tb->my, tb->cx, tb->cy), 0, 60);
4477                 }
4478
4479                 Term_gotoxy(tb->cx - tb->left, tb->cy - tb->upper + 1);
4480                 tb->dirty_flags = 0;
4481                 tb->dirty_line = -1;
4482                 tb->old_cy = tb->cy;
4483                 tb->old_upper = tb->upper;
4484                 tb->old_left = tb->left;
4485                 tb->old_wid = tb->wid;
4486                 tb->old_hgt = tb->hgt;
4487
4488                 key = inkey_special(TRUE);
4489
4490                 if (key & SKEY_MASK)
4491                 {
4492                         com_id = analyze_move_key(tb, key);
4493                 }
4494                 else if (key == ESCAPE)
4495                 {
4496                         com_id = do_command_menu(0, 0);
4497                         tb->dirty_flags |= DIRTY_SCREEN;
4498                 }
4499                 else if (!iscntrl((unsigned char)key))
4500                 {
4501                         if (tb->mark)
4502                         {
4503                                 tb->mark = 0;
4504                                 tb->dirty_flags |= DIRTY_ALL;
4505                         }
4506
4507                         insert_single_letter(tb, key);
4508                         continue;
4509                 }
4510                 else
4511                 {
4512                         com_id = get_com_id((char)key);
4513                 }
4514
4515                 if (com_id) quit = do_editor_command(player_ptr, tb, com_id);
4516         }
4517
4518         screen_load();
4519         strcpy(buf, pickpref_filename(player_ptr, tb->filename_mode));
4520
4521         if (quit == QUIT_AND_SAVE)
4522                 write_text_lines(buf, tb->lines_list);
4523
4524         free_text_lines(tb->lines_list);
4525         string_free(tb->search_str);
4526         string_free(tb->last_destroyed);
4527         kill_yank_chain(tb);
4528
4529         process_autopick_file(player_ptr, buf);
4530         current_world_ptr->start_time = (u32b)time(NULL);
4531         cx_save = tb->cx;
4532         cy_save = tb->cy;
4533 }