OSDN Git Service

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