OSDN Git Service

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