OSDN Git Service

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