OSDN Git Service

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