OSDN Git Service

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