OSDN Git Service

[Refactor] #37353 Renamed objectkind.c/h to object-kind.c/h
[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 "gameterm.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 "market/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 "object/object-kind.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                         /* Fall through */
3284
3285                 case '\n':
3286                 case '\r':
3287                 case KTRL('s'):
3288                         if (*o_handle) return (back ? -1 : 1);
3289                         string_free(*search_strp);
3290                         *search_strp = string_make(buf);
3291                         *o_handle = NULL;
3292                         return (back ? -1 : 1);
3293
3294                 case KTRL('i'):
3295                         return get_object_for_search(player_ptr, o_handle, search_strp);
3296
3297                 case KTRL('l'):
3298                         if (get_destroyed_object_for_search(player_ptr, o_handle, search_strp))
3299                                 return 1;
3300                         break;
3301
3302                 case '\010':
3303                 {
3304                         int i = 0;
3305                         color = TERM_WHITE;
3306                         if (pos == 0) break;
3307
3308                         while (TRUE)
3309                         {
3310                                 int next_pos = i + 1;
3311 #ifdef JP
3312                                 if (iskanji(buf[i])) next_pos++;
3313 #endif
3314                                 if (next_pos >= pos) break;
3315
3316                                 i = next_pos;
3317                         }
3318
3319                         pos = i;
3320                 }
3321                         /* Fall through */
3322
3323                 case 0x7F:
3324                 case KTRL('d'):
3325                 {
3326                         int dst, src;
3327                         color = TERM_WHITE;
3328                         if (buf[pos] == '\0') break;
3329
3330                         src = pos + 1;
3331 #ifdef JP
3332                         if (iskanji(buf[pos])) src++;
3333 #endif
3334                         dst = pos;
3335                         while ('\0' != (buf[dst++] = buf[src++]));
3336
3337                         break;
3338                 }
3339
3340                 default:
3341                 {
3342                         char tmp[100];
3343                         char c;
3344                         if (skey & SKEY_MASK) break;
3345
3346                         c = (char)skey;
3347                         if (color != TERM_WHITE)
3348                         {
3349                                 if (color == TERM_L_GREEN)
3350                                 {
3351                                         *o_handle = NULL;
3352                                         string_free(*search_strp);
3353                                         *search_strp = NULL;
3354                                 }
3355
3356                                 buf[0] = '\0';
3357                                 color = TERM_WHITE;
3358                         }
3359
3360                         strcpy(tmp, buf + pos);
3361 #ifdef JP
3362                         if (iskanji(c))
3363                         {
3364                                 char next;
3365                                 inkey_base = TRUE;
3366                                 next = inkey();
3367
3368                                 if (pos + 1 < len)
3369                                 {
3370                                         buf[pos++] = c;
3371                                         buf[pos++] = next;
3372                                 }
3373                                 else
3374                                 {
3375                                         bell();
3376                                 }
3377                         }
3378                         else
3379 #endif
3380                         {
3381 #ifdef JP
3382                                 if (pos < len && (isprint(c) || iskana(c)))
3383 #else
3384                                 if (pos < len && isprint(c))
3385 #endif
3386                                 {
3387                                         buf[pos++] = c;
3388                                 }
3389                                 else
3390                                 {
3391                                         bell();
3392                                 }
3393                         }
3394
3395                         buf[pos] = '\0';
3396                         my_strcat(buf, tmp, len + 1);
3397
3398                         break;
3399                 }
3400                 }
3401
3402                 if (*o_handle == NULL || color == TERM_L_GREEN) continue;
3403
3404                 *o_handle = NULL;
3405                 buf[0] = '\0';
3406                 string_free(*search_strp);
3407                 *search_strp = NULL;
3408         }
3409 }
3410
3411
3412 /*
3413  * Search next line matches for o_ptr
3414  */
3415 static void search_for_object(player_type *player_ptr, text_body_type *tb, object_type *o_ptr, bool forward)
3416 {
3417         autopick_type an_entry, *entry = &an_entry;
3418         GAME_TEXT o_name[MAX_NLEN];
3419         int bypassed_cy = -1;
3420         int i = tb->cy;
3421         object_desc(player_ptr, o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
3422         str_tolower(o_name);
3423
3424         while (TRUE)
3425         {
3426                 bool match;
3427                 if (forward)
3428                 {
3429                         if (!tb->lines_list[++i]) break;
3430                 }
3431                 else
3432                 {
3433                         if (--i < 0) break;
3434                 }
3435
3436                 if (!autopick_new_entry(entry, tb->lines_list[i], FALSE)) continue;
3437
3438                 match = is_autopick_aux(player_ptr, o_ptr, entry, o_name);
3439                 autopick_free_entry(entry);
3440                 if (!match)     continue;
3441
3442                 if (tb->states[i] & LSTAT_BYPASS)
3443                 {
3444                         if (bypassed_cy == -1) bypassed_cy = i;
3445                         continue;
3446                 }
3447
3448                 tb->cx = 0;
3449                 tb->cy = i;
3450                 if (bypassed_cy != -1)
3451                 {
3452                         tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
3453                 }
3454
3455                 return;
3456         }
3457
3458         if (bypassed_cy == -1)
3459         {
3460                 tb->dirty_flags |= DIRTY_NOT_FOUND;
3461                 return;
3462         }
3463
3464         tb->cx = 0;
3465         tb->cy = bypassed_cy;
3466         tb->dirty_flags |= DIRTY_INACTIVE;
3467 }
3468
3469
3470 /*
3471  * Search next line matches to the string
3472  */
3473 static void search_for_string(text_body_type *tb, concptr search_str, bool forward)
3474 {
3475         int bypassed_cy = -1;
3476         int bypassed_cx = 0;
3477
3478         int i = tb->cy;
3479         while (TRUE)
3480         {
3481                 concptr pos;
3482                 if (forward)
3483                 {
3484                         if (!tb->lines_list[++i]) break;
3485                 }
3486                 else
3487                 {
3488                         if (--i < 0) break;
3489                 }
3490
3491                 pos = my_strstr(tb->lines_list[i], search_str);
3492                 if (!pos) continue;
3493
3494                 if ((tb->states[i] & LSTAT_BYPASS) &&
3495                         !(tb->states[i] & LSTAT_EXPRESSION))
3496                 {
3497                         if (bypassed_cy == -1)
3498                         {
3499                                 bypassed_cy = i;
3500                                 bypassed_cx = (int)(pos - tb->lines_list[i]);
3501                         }
3502
3503                         continue;
3504                 }
3505
3506                 tb->cx = (int)(pos - tb->lines_list[i]);
3507                 tb->cy = i;
3508
3509                 if (bypassed_cy != -1)
3510                 {
3511                         tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
3512                 }
3513
3514                 return;
3515         }
3516
3517         if (bypassed_cy == -1)
3518         {
3519                 tb->dirty_flags |= DIRTY_NOT_FOUND;
3520                 return;
3521         }
3522
3523         tb->cx = bypassed_cx;
3524         tb->cy = bypassed_cy;
3525         tb->dirty_flags |= DIRTY_INACTIVE;
3526 }
3527
3528
3529 /*
3530  * Find a command by 'key'.
3531  */
3532 static int get_com_id(char key)
3533 {
3534         for (int i = 0; menu_data[i].name; i++)
3535         {
3536                 if (menu_data[i].key == key)
3537                 {
3538                         return menu_data[i].com_id;
3539                 }
3540         }
3541
3542         return 0;
3543 }
3544
3545
3546 /*
3547  * Display the menu, and get a command
3548  */
3549 static int do_command_menu(int level, int start)
3550 {
3551         int max_len = 0;
3552         int col0 = 5 + level * 7;
3553         int row0 = 1 + level * 3;
3554         int menu_id_list[26];
3555         bool redraw = TRUE;
3556         char linestr[MAX_LINELEN];
3557
3558         byte menu_key = 0;
3559         for (int i = start; menu_data[i].level >= level; i++)
3560         {
3561                 int len;
3562
3563                 /* Ignore lower level sub menus */
3564                 if (menu_data[i].level > level) continue;
3565
3566                 len = strlen(menu_data[i].name);
3567                 if (len > max_len) max_len = len;
3568
3569                 menu_id_list[menu_key] = i;
3570                 menu_key++;
3571         }
3572
3573         while (menu_key < 26)
3574         {
3575                 menu_id_list[menu_key] = -1;
3576                 menu_key++;
3577         }
3578
3579         int max_menu_wid = max_len + 3 + 3;
3580
3581         /* Prepare box line */
3582         linestr[0] = '\0';
3583         strcat(linestr, "+");
3584         for (int i = 0; i < max_menu_wid + 2; i++)
3585         {
3586                 strcat(linestr, "-");
3587         }
3588
3589         strcat(linestr, "+");
3590
3591         while (TRUE)
3592         {
3593                 int com_id;
3594                 char key;
3595                 int menu_id;
3596
3597                 if (redraw)
3598                 {
3599                         int row1 = row0 + 1;
3600                         Term_putstr(col0, row0, -1, TERM_WHITE, linestr);
3601
3602                         menu_key = 0;
3603                         for (int i = start; menu_data[i].level >= level; i++)
3604                         {
3605                                 char com_key_str[3];
3606                                 concptr str;
3607                                 if (menu_data[i].level > level) continue;
3608
3609                                 if (menu_data[i].com_id == -1)
3610                                 {
3611                                         strcpy(com_key_str, _("▼", ">"));
3612                                 }
3613                                 else if (menu_data[i].key != -1)
3614                                 {
3615                                         com_key_str[0] = '^';
3616                                         com_key_str[1] = menu_data[i].key + '@';
3617                                         com_key_str[2] = '\0';
3618                                 }
3619                                 else
3620                                 {
3621                                         com_key_str[0] = '\0';
3622                                 }
3623
3624                                 str = format("| %c) %-*s %2s | ", menu_key + 'a', max_len, menu_data[i].name, com_key_str);
3625
3626                                 Term_putstr(col0, row1++, -1, TERM_WHITE, str);
3627
3628                                 menu_key++;
3629                         }
3630
3631                         Term_putstr(col0, row1, -1, TERM_WHITE, linestr);
3632                         redraw = FALSE;
3633                 }
3634
3635                 prt(format(_("(a-%c) コマンド:", "(a-%c) Command:"), menu_key + 'a' - 1), 0, 0);
3636                 key = inkey();
3637
3638                 if (key == ESCAPE) return 0;
3639
3640                 bool is_alphabet = key >= 'a' && key <= 'z';
3641                 if (!is_alphabet)
3642                 {
3643                         com_id = get_com_id(key);
3644                         if (com_id)
3645                         {
3646                                 return com_id;
3647                         }
3648
3649                         continue;
3650                 }
3651
3652                 menu_id = menu_id_list[key - 'a'];
3653
3654                 if (menu_id < 0) continue;
3655
3656                 com_id = menu_data[menu_id].com_id;
3657
3658                 if (com_id == -1)
3659                 {
3660                         com_id = do_command_menu(level + 1, menu_id + 1);
3661
3662                         if (com_id) return com_id;
3663                         else redraw = TRUE;
3664                 }
3665                 else if (com_id)
3666                 {
3667                         return com_id;
3668                 }
3669         }
3670 }
3671
3672
3673 static chain_str_type *new_chain_str(concptr str)
3674 {
3675         chain_str_type *chain;
3676         size_t len = strlen(str);
3677         chain = (chain_str_type *)ralloc(sizeof(chain_str_type) + len * sizeof(char));
3678         strcpy(chain->s, str);
3679         chain->next = NULL;
3680         return chain;
3681 }
3682
3683
3684 static void kill_yank_chain(text_body_type *tb)
3685 {
3686         chain_str_type *chain = tb->yank;
3687         tb->yank = NULL;
3688         tb->yank_eol = TRUE;
3689
3690         while (chain)
3691         {
3692                 chain_str_type *next = chain->next;
3693                 size_t len = strlen(chain->s);
3694
3695                 rnfree(chain, sizeof(chain_str_type) + len * sizeof(char));
3696
3697                 chain = next;
3698         }
3699 }
3700
3701
3702 static void add_str_to_yank(text_body_type *tb, concptr str)
3703 {
3704         tb->yank_eol = FALSE;
3705         if (NULL == tb->yank)
3706         {
3707                 tb->yank = new_chain_str(str);
3708                 return;
3709         }
3710
3711         chain_str_type *chain;
3712         chain = tb->yank;
3713
3714         while (TRUE)
3715         {
3716                 if (!chain->next)
3717                 {
3718                         chain->next = new_chain_str(str);
3719                         return;
3720                 }
3721
3722                 /* Go to next */
3723                 chain = chain->next;
3724         }
3725 }
3726
3727
3728 /*
3729  * Do work for the copy editor-command
3730  */
3731 static void copy_text_to_yank(text_body_type *tb)
3732 {
3733         int len = strlen(tb->lines_list[tb->cy]);
3734         if (tb->cx > len) tb->cx = len;
3735
3736         if (!tb->mark)
3737         {
3738                 tb->cx = 0;
3739                 tb->my = tb->cy;
3740                 tb->mx = len;
3741         }
3742
3743         kill_yank_chain(tb);
3744         if (tb->my != tb->cy)
3745         {
3746                 int by1 = MIN(tb->my, tb->cy);
3747                 int by2 = MAX(tb->my, tb->cy);
3748
3749                 for (int y = by1; y <= by2; y++)
3750                 {
3751                         add_str_to_yank(tb, tb->lines_list[y]);
3752                 }
3753
3754                 add_str_to_yank(tb, "");
3755                 tb->mark = 0;
3756                 tb->dirty_flags |= DIRTY_ALL;
3757                 return;
3758         }
3759
3760         char buf[MAX_LINELEN];
3761         int bx1 = MIN(tb->mx, tb->cx);
3762         int bx2 = MAX(tb->mx, tb->cx);
3763         if (bx2 > len) bx2 = len;
3764
3765         if (bx1 == 0 && bx2 == len)
3766         {
3767                 add_str_to_yank(tb, tb->lines_list[tb->cy]);
3768                 add_str_to_yank(tb, "");
3769         }
3770         else
3771         {
3772                 int end = bx2 - bx1;
3773                 for (int i = 0; i < bx2 - bx1; i++)
3774                 {
3775                         buf[i] = tb->lines_list[tb->cy][bx1 + i];
3776                 }
3777
3778                 buf[end] = '\0';
3779                 add_str_to_yank(tb, buf);
3780         }
3781
3782         tb->mark = 0;
3783         tb->dirty_flags |= DIRTY_ALL;
3784 }
3785
3786
3787 /*
3788  * Draw text
3789  */
3790 static void draw_text_editor(player_type *player_ptr, text_body_type *tb)
3791 {
3792         int i;
3793         int by1 = 0, by2 = 0;
3794
3795         Term_get_size(&tb->wid, &tb->hgt);
3796
3797         /*
3798          * Top line (-1), description line (-3), separator (-1)
3799          *  == -5
3800          */
3801         tb->hgt -= 2 + DESCRIPT_HGT;
3802
3803 #ifdef JP
3804         /* Don't let cursor at second byte of kanji */
3805         for (i = 0; tb->lines_list[tb->cy][i]; i++)
3806                 if (iskanji(tb->lines_list[tb->cy][i]))
3807                 {
3808                         i++;
3809                         if (i == tb->cx)
3810                         {
3811                                 /*
3812                                  * Move to a correct position in the
3813                                  * left or right
3814                                  */
3815                                 if (i & 1) tb->cx--;
3816                                 else tb->cx++;
3817                                 break;
3818                         }
3819                 }
3820 #endif
3821         if (tb->cy < tb->upper || tb->upper + tb->hgt <= tb->cy)
3822                 tb->upper = tb->cy - (tb->hgt) / 2;
3823         if (tb->upper < 0)
3824                 tb->upper = 0;
3825         if ((tb->cx < tb->left + 10 && tb->left > 0) || tb->left + tb->wid - 5 <= tb->cx)
3826                 tb->left = tb->cx - (tb->wid) * 2 / 3;
3827         if (tb->left < 0)
3828                 tb->left = 0;
3829
3830         if (tb->old_wid != tb->wid || tb->old_hgt != tb->hgt)
3831                 tb->dirty_flags |= DIRTY_SCREEN;
3832         else if (tb->old_upper != tb->upper || tb->old_left != tb->left)
3833                 tb->dirty_flags |= DIRTY_ALL;
3834
3835         if (tb->dirty_flags & DIRTY_SCREEN)
3836         {
3837                 tb->dirty_flags |= (DIRTY_ALL | DIRTY_MODE);
3838                 Term_clear();
3839         }
3840
3841         if (tb->dirty_flags & DIRTY_MODE)
3842         {
3843                 char buf[MAX_LINELEN];
3844                 int sepa_length = tb->wid;
3845                 for (i = 0; i < sepa_length; i++)
3846                         buf[i] = '-';
3847                 buf[i] = '\0';
3848                 Term_putstr(0, tb->hgt + 1, sepa_length, TERM_WHITE, buf);
3849         }
3850
3851         if (tb->dirty_flags & DIRTY_EXPRESSION)
3852         {
3853                 byte state = 0;
3854                 for (int y = 0; tb->lines_list[y]; y++)
3855                 {
3856                         char f;
3857                         concptr v;
3858                         concptr s = tb->lines_list[y];
3859                         char *ss, *s_keep;
3860                         int s_len;
3861
3862                         tb->states[y] = state;
3863
3864                         if (*s++ != '?') continue;
3865                         if (*s++ != ':') continue;
3866
3867                         if (streq(s, "$AUTOREGISTER"))
3868                                 state |= LSTAT_AUTOREGISTER;
3869
3870                         s_len = strlen(s);
3871                         ss = (char *)string_make(s);
3872                         s_keep = ss;
3873
3874                         v = process_pref_file_expr(player_ptr, &ss, &f);
3875
3876                         if (streq(v, "0")) state |= LSTAT_BYPASS;
3877                         else state &= ~LSTAT_BYPASS;
3878
3879                         C_KILL(s_keep, s_len + 1, char);
3880
3881                         tb->states[y] = state | LSTAT_EXPRESSION;
3882                 }
3883
3884                 tb->dirty_flags |= DIRTY_ALL;
3885         }
3886
3887         if (tb->mark)
3888         {
3889                 tb->dirty_flags |= DIRTY_ALL;
3890
3891                 by1 = MIN(tb->my, tb->cy);
3892                 by2 = MAX(tb->my, tb->cy);
3893         }
3894
3895         for (i = 0; i < tb->hgt; i++)
3896         {
3897                 int j;
3898                 int leftcol = 0;
3899                 concptr msg;
3900                 byte color;
3901                 int y = tb->upper + i;
3902
3903                 if (!(tb->dirty_flags & DIRTY_ALL) && (tb->dirty_line != y))
3904                         continue;
3905
3906                 msg = tb->lines_list[y];
3907                 if (!msg) break;
3908
3909                 for (j = 0; *msg; msg++, j++)
3910                 {
3911                         if (j == tb->left) break;
3912 #ifdef JP
3913                         if (j > tb->left)
3914                         {
3915                                 leftcol = 1;
3916                                 break;
3917                         }
3918                         if (iskanji(*msg))
3919                         {
3920                                 msg++;
3921                                 j++;
3922                         }
3923 #endif
3924                 }
3925
3926                 Term_erase(0, i + 1, tb->wid);
3927                 if (tb->states[y] & LSTAT_AUTOREGISTER)
3928                 {
3929                         color = TERM_L_RED;
3930                 }
3931                 else
3932                 {
3933                         if (tb->states[y] & LSTAT_BYPASS) color = TERM_SLATE;
3934                         else color = TERM_WHITE;
3935                 }
3936
3937                 if (!tb->mark || (y < by1 || by2 < y))
3938                 {
3939                         Term_putstr(leftcol, i + 1, tb->wid - 1, color, msg);
3940                 }
3941                 else if (by1 != by2)
3942                 {
3943                         Term_putstr(leftcol, i + 1, tb->wid - 1, TERM_YELLOW, msg);
3944                 }
3945                 else
3946                 {
3947                         int x0 = leftcol + tb->left;
3948                         int len = strlen(tb->lines_list[tb->cy]);
3949                         int bx1 = MIN(tb->mx, tb->cx);
3950                         int bx2 = MAX(tb->mx, tb->cx);
3951
3952                         if (bx2 > len) bx2 = len;
3953
3954                         Term_gotoxy(leftcol, i + 1);
3955                         if (x0 < bx1) Term_addstr(bx1 - x0, color, msg);
3956                         if (x0 < bx2) Term_addstr(bx2 - bx1, TERM_YELLOW, msg + (bx1 - x0));
3957                         Term_addstr(-1, color, msg + (bx2 - x0));
3958                 }
3959         }
3960
3961         for (; i < tb->hgt; i++)
3962         {
3963                 Term_erase(0, i + 1, tb->wid);
3964         }
3965
3966         bool is_dirty_diary = (tb->dirty_flags & (DIRTY_ALL | DIRTY_NOT_FOUND | DIRTY_NO_SEARCH)) != 0;
3967         bool is_updated = tb->old_cy != tb->cy || is_dirty_diary || tb->dirty_line == tb->cy;
3968         if (is_updated) return;
3969
3970         autopick_type an_entry, *entry = &an_entry;
3971         concptr str1 = NULL, str2 = NULL;
3972         for (i = 0; i < DESCRIPT_HGT; i++)
3973         {
3974                 Term_erase(0, tb->hgt + 2 + i, tb->wid);
3975         }
3976
3977         if (tb->dirty_flags & DIRTY_NOT_FOUND)
3978         {
3979                 str1 = format(_("パターンが見つかりません: %s", "Pattern not found: %s"), tb->search_str);
3980         }
3981         else if (tb->dirty_flags & DIRTY_SKIP_INACTIVE)
3982         {
3983                 str1 = format(_("無効状態の行をスキップしました。(%sを検索中)",
3984                         "Some inactive lines are skipped. (Searching %s)"), tb->search_str);
3985         }
3986         else if (tb->dirty_flags & DIRTY_INACTIVE)
3987         {
3988                 str1 = format(_("無効状態の行だけが見付かりました。(%sを検索中)",
3989                         "Found only an inactive line. (Searching %s)"), tb->search_str);
3990         }
3991         else if (tb->dirty_flags & DIRTY_NO_SEARCH)
3992         {
3993                 str1 = _("検索するパターンがありません(^S で検索)。", "No pattern to search. (Press ^S to search.)");
3994         }
3995         else if (tb->lines_list[tb->cy][0] == '#')
3996         {
3997                 str1 = _("この行はコメントです。", "This line is a comment.");
3998         }
3999         else if (tb->lines_list[tb->cy][0] && tb->lines_list[tb->cy][1] == ':')
4000         {
4001                 switch (tb->lines_list[tb->cy][0])
4002                 {
4003                 case '?':
4004                         str1 = _("この行は条件分岐式です。", "This line is a Conditional Expression.");
4005                         break;
4006                 case 'A':
4007                         str1 = _("この行はマクロの実行内容を定義します。", "This line defines a Macro action.");
4008                         break;
4009                 case 'P':
4010                         str1 = _("この行はマクロのトリガー・キーを定義します。", "This line defines a Macro trigger key.");
4011                         break;
4012                 case 'C':
4013                         str1 = _("この行はキー配置を定義します。", "This line defines a Keymap.");
4014                         break;
4015                 }
4016
4017                 switch (tb->lines_list[tb->cy][0])
4018                 {
4019                 case '?':
4020                         if (tb->states[tb->cy] & LSTAT_BYPASS)
4021                         {
4022                                 str2 = _("現在の式の値は「偽(=0)」です。", "The expression is 'False'(=0) currently.");
4023                         }
4024                         else
4025                         {
4026                                 str2 = _("現在の式の値は「真(=1)」です。", "The expression is 'True'(=1) currently.");
4027                         }
4028                         break;
4029
4030                 default:
4031                         if (tb->states[tb->cy] & LSTAT_AUTOREGISTER)
4032                         {
4033                                 str2 = _("この行は後で削除されます。", "This line will be delete later.");
4034                         }
4035
4036                         else if (tb->states[tb->cy] & LSTAT_BYPASS)
4037                         {
4038                                 str2 = _("この行は現在は無効な状態です。", "This line is bypassed currently.");
4039                         }
4040                         break;
4041                 }
4042         }
4043         else if (autopick_new_entry(entry, tb->lines_list[tb->cy], FALSE))
4044         {
4045                 char buf[MAX_LINELEN];
4046                 char temp[MAX_LINELEN];
4047                 concptr t;
4048
4049                 describe_autopick(buf, entry);
4050
4051                 if (tb->states[tb->cy] & LSTAT_AUTOREGISTER)
4052                 {
4053                         strcat(buf, _("この行は後で削除されます。", "  This line will be delete later."));
4054                 }
4055
4056                 if (tb->states[tb->cy] & LSTAT_BYPASS)
4057                 {
4058                         strcat(buf, _("この行は現在は無効な状態です。", "  This line is bypassed currently."));
4059                 }
4060
4061                 roff_to_buf(buf, 81, temp, sizeof(temp));
4062                 t = temp;
4063                 for (i = 0; i < 3; i++)
4064                 {
4065                         if (t[0] == 0)
4066                                 break;
4067                         else
4068                         {
4069                                 prt(t, tb->hgt + 1 + 1 + i, 0);
4070                                 t += strlen(t) + 1;
4071                         }
4072                 }
4073                 autopick_free_entry(entry);
4074         }
4075
4076         if (str1) prt(str1, tb->hgt + 1 + 1, 0);
4077         if (str2) prt(str2, tb->hgt + 1 + 2, 0);
4078 }
4079
4080
4081 /*
4082  * Kill segment of a line
4083  */
4084 static void kill_line_segment(text_body_type *tb, int y, int x0, int x1, bool whole)
4085 {
4086         concptr s = tb->lines_list[y];
4087         if (whole && x0 == 0 && s[x1] == '\0' && tb->lines_list[y + 1])
4088         {
4089                 string_free(tb->lines_list[y]);
4090
4091                 int i;
4092                 for (i = y; tb->lines_list[i + 1]; i++)
4093                         tb->lines_list[i] = tb->lines_list[i + 1];
4094                 tb->lines_list[i] = NULL;
4095
4096                 tb->dirty_flags |= DIRTY_EXPRESSION;
4097
4098                 return;
4099         }
4100
4101         if (x0 == x1) return;
4102
4103         char buf[MAX_LINELEN];
4104         char *d = buf;
4105         for (int x = 0; x < x0; x++)
4106                 *(d++) = s[x];
4107
4108         for (int x = x1; s[x]; x++)
4109                 *(d++) = s[x];
4110
4111         *d = '\0';
4112         string_free(tb->lines_list[y]);
4113         tb->lines_list[y] = string_make(buf);
4114         check_expression_line(tb, y);
4115         tb->changed = TRUE;
4116 }
4117
4118
4119 /*
4120  * Get a trigger key and insert ASCII string for the trigger
4121  */
4122 static bool insert_macro_line(text_body_type *tb)
4123 {
4124         int i, n = 0;
4125         flush();
4126         inkey_base = TRUE;
4127         i = inkey();
4128         char buf[1024];
4129         while (i)
4130         {
4131                 buf[n++] = (char)i;
4132                 inkey_base = TRUE;
4133                 inkey_scan = TRUE;
4134                 i = inkey();
4135         }
4136
4137         buf[n] = '\0';
4138         flush();
4139
4140         char tmp[1024];
4141         ascii_to_text(tmp, buf);
4142         if (!tmp[0]) return FALSE;
4143
4144         tb->cx = 0;
4145         insert_return_code(tb);
4146         string_free(tb->lines_list[tb->cy]);
4147         tb->lines_list[tb->cy] = string_make(format("P:%s", tmp));
4148
4149         i = macro_find_exact(buf);
4150         if (i == -1)
4151         {
4152                 tmp[0] = '\0';
4153         }
4154         else
4155         {
4156                 ascii_to_text(tmp, macro__act[i]);
4157         }
4158
4159         insert_return_code(tb);
4160         string_free(tb->lines_list[tb->cy]);
4161         tb->lines_list[tb->cy] = string_make(format("A:%s", tmp));
4162
4163         return TRUE;
4164 }
4165
4166
4167 /*
4168  * Get a command key and insert ASCII string for the key
4169  */
4170 static bool insert_keymap_line(text_body_type *tb)
4171 {
4172         BIT_FLAGS mode;
4173         if (rogue_like_commands)
4174         {
4175                 mode = KEYMAP_MODE_ROGUE;
4176         }
4177         else
4178         {
4179                 mode = KEYMAP_MODE_ORIG;
4180         }
4181
4182         flush();
4183         char buf[2];
4184         buf[0] = inkey();
4185         buf[1] = '\0';
4186
4187         flush();
4188         char tmp[1024];
4189         ascii_to_text(tmp, buf);
4190         if (!tmp[0]) return FALSE;
4191
4192         tb->cx = 0;
4193         insert_return_code(tb);
4194         string_free(tb->lines_list[tb->cy]);
4195         tb->lines_list[tb->cy] = string_make(format("C:%d:%s", mode, tmp));
4196
4197         concptr act = keymap_act[mode][(byte)(buf[0])];
4198         if (act)
4199         {
4200                 ascii_to_text(tmp, act);
4201         }
4202
4203         insert_return_code(tb);
4204         string_free(tb->lines_list[tb->cy]);
4205         tb->lines_list[tb->cy] = string_make(format("A:%s", tmp));
4206
4207         return TRUE;
4208 }
4209
4210
4211 /*
4212  * Execute a single editor command
4213  */
4214 static bool do_editor_command(player_type *player_ptr, text_body_type *tb, int com_id)
4215 {
4216         switch (com_id)
4217         {
4218         case EC_QUIT:
4219                 if (tb->changed)
4220                 {
4221                         if (!get_check(_("全ての変更を破棄してから終了します。よろしいですか? ",
4222                                 "Discard all changes and quit. Are you sure? "))) break;
4223                 }
4224
4225                 return QUIT_WITHOUT_SAVE;
4226
4227         case EC_SAVEQUIT:
4228                 return QUIT_AND_SAVE;
4229
4230         case EC_REVERT:
4231                 if (!get_check(_("全ての変更を破棄して元の状態に戻します。よろしいですか? ",
4232                         "Discard all changes and revert to original file. Are you sure? "))) break;
4233
4234                 free_text_lines(tb->lines_list);
4235                 tb->lines_list = read_pickpref_text_lines(player_ptr, &tb->filename_mode);
4236                 tb->dirty_flags |= DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
4237                 tb->cx = tb->cy = 0;
4238                 tb->mark = 0;
4239
4240                 tb->changed = FALSE;
4241                 break;
4242
4243         case EC_HELP:
4244                 (void)show_file(player_ptr, TRUE, _("jeditor.txt", "editor.txt"), NULL, 0, 0);
4245                 tb->dirty_flags |= DIRTY_SCREEN;
4246
4247                 break;
4248
4249         case EC_RETURN:
4250                 if (tb->mark)
4251                 {
4252                         tb->mark = 0;
4253                         tb->dirty_flags |= DIRTY_ALL;
4254                 }
4255
4256                 insert_return_code(tb);
4257                 tb->cy++;
4258                 tb->cx = 0;
4259
4260                 tb->dirty_flags |= DIRTY_ALL;
4261                 break;
4262
4263         case EC_LEFT:
4264         {
4265                 if (0 < tb->cx)
4266                 {
4267                         int len;
4268 #ifdef JP
4269                         int i;
4270 #endif
4271                         tb->cx--;
4272                         len = strlen(tb->lines_list[tb->cy]);
4273                         if (len < tb->cx) tb->cx = len;
4274 #ifdef JP
4275                         for (i = 0; tb->lines_list[tb->cy][i]; i++)
4276                         {
4277                                 if (iskanji(tb->lines_list[tb->cy][i]))
4278                                 {
4279                                         i++;
4280                                         if (i == tb->cx)
4281                                         {
4282                                                 tb->cx--;
4283                                                 break;
4284                                         }
4285                                 }
4286                         }
4287 #endif
4288                 }
4289                 else if (tb->cy > 0)
4290                 {
4291                         tb->cy--;
4292                         tb->cx = strlen(tb->lines_list[tb->cy]);
4293                 }
4294
4295                 break;
4296         }
4297         case EC_DOWN:
4298                 if (!tb->lines_list[tb->cy + 1])
4299                 {
4300                         if (!add_empty_line(tb)) break;
4301                 }
4302
4303                 tb->cy++;
4304                 break;
4305
4306         case EC_UP:
4307                 if (tb->cy > 0) tb->cy--;
4308                 break;
4309
4310         case EC_RIGHT:
4311         {
4312 #ifdef JP
4313                 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
4314 #endif
4315                 tb->cx++;
4316                 int len = strlen(tb->lines_list[tb->cy]);
4317                 if (len < tb->cx)
4318                 {
4319                         tb->cx = len;
4320                         if (!tb->lines_list[tb->cy + 1])
4321                         {
4322                                 if (!add_empty_line(tb)) break;
4323                         }
4324
4325                         tb->cy++;
4326                         tb->cx = 0;
4327                 }
4328
4329                 break;
4330         }
4331         case EC_BOL:
4332                 tb->cx = 0;
4333                 break;
4334
4335         case EC_EOL:
4336                 tb->cx = strlen(tb->lines_list[tb->cy]);
4337                 break;
4338
4339         case EC_PGUP:
4340                 while (0 < tb->cy && tb->upper <= tb->cy)
4341                         tb->cy--;
4342                 while (0 < tb->upper && tb->cy + 1 < tb->upper + tb->hgt)
4343                         tb->upper--;
4344                 break;
4345
4346         case EC_PGDOWN:
4347                 while (tb->cy < tb->upper + tb->hgt)
4348                 {
4349                         if (!tb->lines_list[tb->cy + 1])
4350                         {
4351                                 if (!add_empty_line(tb)) break;
4352                         }
4353
4354                         tb->cy++;
4355                 }
4356
4357                 tb->upper = tb->cy;
4358                 break;
4359
4360         case EC_TOP:
4361                 tb->cy = 0;
4362                 break;
4363
4364         case EC_BOTTOM:
4365                 while (TRUE)
4366                 {
4367                         if (!tb->lines_list[tb->cy + 1])
4368                         {
4369                                 if (!add_empty_line(tb)) break;
4370                         }
4371
4372                         tb->cy++;
4373                 }
4374
4375                 tb->cx = 0;
4376                 break;
4377
4378         case EC_CUT:
4379         {
4380                 copy_text_to_yank(tb);
4381                 if (tb->my == tb->cy)
4382                 {
4383                         int bx1 = MIN(tb->mx, tb->cx);
4384                         int bx2 = MAX(tb->mx, tb->cx);
4385                         int len = strlen(tb->lines_list[tb->cy]);
4386                         if (bx2 > len) bx2 = len;
4387
4388                         kill_line_segment(tb, tb->cy, bx1, bx2, TRUE);
4389                         tb->cx = bx1;
4390                 }
4391                 else
4392                 {
4393                         int by1 = MIN(tb->my, tb->cy);
4394                         int by2 = MAX(tb->my, tb->cy);
4395
4396                         for (int y = by2; y >= by1; y--)
4397                         {
4398                                 int len = strlen(tb->lines_list[y]);
4399
4400                                 kill_line_segment(tb, y, 0, len, TRUE);
4401                         }
4402
4403                         tb->cy = by1;
4404                         tb->cx = 0;
4405                 }
4406
4407                 tb->mark = 0;
4408                 tb->dirty_flags |= DIRTY_ALL;
4409                 tb->changed = TRUE;
4410                 break;
4411         }
4412         case EC_COPY:
4413                 copy_text_to_yank(tb);
4414
4415                 /*
4416                  * Move cursor position to the end of the selection
4417                  *
4418                  * Pressing ^C ^V correctly duplicates the selection.
4419                  */
4420                 if (tb->my != tb->cy)
4421                 {
4422                         tb->cy = MAX(tb->cy, tb->my);
4423                         if (!tb->lines_list[tb->cy + 1])
4424                         {
4425                                 if (!add_empty_line(tb)) break;
4426                         }
4427
4428                         tb->cy++;
4429                         break;
4430                 }
4431
4432                 tb->cx = MAX(tb->cx, tb->mx);
4433                 if (!tb->lines_list[tb->cy][tb->cx])
4434                 {
4435                         if (!tb->lines_list[tb->cy + 1])
4436                         {
4437                                 if (!add_empty_line(tb)) break;
4438                         }
4439
4440                         tb->cy++;
4441                         tb->cx = 0;
4442                 }
4443
4444                 break;
4445
4446         case EC_PASTE:
4447         {
4448                 chain_str_type *chain = tb->yank;
4449                 int len = strlen(tb->lines_list[tb->cy]);
4450                 if (!chain) break;
4451                 if (tb->cx > len) tb->cx = len;
4452
4453                 if (tb->mark)
4454                 {
4455                         tb->mark = 0;
4456                         tb->dirty_flags |= DIRTY_ALL;
4457                 }
4458
4459                 while (chain)
4460                 {
4461                         concptr yank_str = chain->s;
4462                         char buf[MAX_LINELEN];
4463                         int i;
4464                         char rest[MAX_LINELEN], *rest_ptr = rest;
4465                         for (i = 0; i < tb->cx; i++)
4466                                 buf[i] = tb->lines_list[tb->cy][i];
4467
4468                         strcpy(rest, &(tb->lines_list[tb->cy][i]));
4469                         while (*yank_str && i < MAX_LINELEN - 1)
4470                         {
4471                                 buf[i++] = *yank_str++;
4472                         }
4473
4474                         buf[i] = '\0';
4475                         chain = chain->next;
4476                         if (chain || tb->yank_eol)
4477                         {
4478                                 insert_return_code(tb);
4479                                 string_free(tb->lines_list[tb->cy]);
4480                                 tb->lines_list[tb->cy] = string_make(buf);
4481                                 tb->cx = 0;
4482                                 tb->cy++;
4483
4484                                 continue;
4485                         }
4486
4487                         tb->cx = strlen(buf);
4488                         while (*rest_ptr && i < MAX_LINELEN - 1)
4489                         {
4490                                 buf[i++] = *rest_ptr++;
4491                         }
4492
4493                         buf[i] = '\0';
4494                         string_free(tb->lines_list[tb->cy]);
4495                         tb->lines_list[tb->cy] = string_make(buf);
4496                         break;
4497                 }
4498
4499                 tb->dirty_flags |= DIRTY_ALL;
4500                 tb->dirty_flags |= DIRTY_EXPRESSION;
4501                 tb->changed = TRUE;
4502                 break;
4503         }
4504         case EC_BLOCK:
4505         {
4506                 if (tb->mark)
4507                 {
4508                         tb->mark = 0;
4509                         tb->dirty_flags |= DIRTY_ALL;
4510                         break;
4511                 }
4512
4513                 tb->mark = MARK_MARK;
4514                 if (com_id == tb->old_com_id)
4515                 {
4516                         int tmp = tb->cy;
4517                         tb->cy = tb->my;
4518                         tb->my = tmp;
4519                         tmp = tb->cx;
4520                         tb->cx = tb->mx;
4521                         tb->mx = tmp;
4522                         tb->dirty_flags |= DIRTY_ALL;
4523                         break;
4524                 }
4525
4526                 int len = strlen(tb->lines_list[tb->cy]);
4527
4528                 tb->my = tb->cy;
4529                 tb->mx = tb->cx;
4530                 if (tb->cx > len) tb->mx = len;
4531                 break;
4532         }
4533         case EC_KILL_LINE:
4534         {
4535                 int len = strlen(tb->lines_list[tb->cy]);
4536                 if (tb->cx > len) tb->cx = len;
4537
4538                 if (tb->mark)
4539                 {
4540                         tb->mark = 0;
4541                         tb->dirty_flags |= DIRTY_ALL;
4542                 }
4543
4544                 if (tb->old_com_id != com_id)
4545                 {
4546                         kill_yank_chain(tb);
4547                         tb->yank = NULL;
4548                 }
4549
4550                 if (tb->cx < len)
4551                 {
4552                         add_str_to_yank(tb, &(tb->lines_list[tb->cy][tb->cx]));
4553                         kill_line_segment(tb, tb->cy, tb->cx, len, FALSE);
4554                         tb->dirty_line = tb->cy;
4555                         break;
4556                 }
4557
4558                 if (tb->yank_eol) add_str_to_yank(tb, "");
4559
4560                 tb->yank_eol = TRUE;
4561                 do_editor_command(player_ptr, tb, EC_DELETE_CHAR);
4562                 break;
4563         }
4564         case EC_DELETE_CHAR:
4565         {
4566                 if (tb->mark)
4567                 {
4568                         tb->mark = 0;
4569                         tb->dirty_flags |= DIRTY_ALL;
4570                 }
4571
4572 #ifdef JP
4573                 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
4574 #endif
4575                 tb->cx++;
4576                 int len = strlen(tb->lines_list[tb->cy]);
4577                 if (len >= tb->cx)
4578                 {
4579                         do_editor_command(player_ptr, tb, EC_BACKSPACE);
4580                         break;
4581                 }
4582
4583                 if (tb->lines_list[tb->cy + 1])
4584                 {
4585                         tb->cy++;
4586                         tb->cx = 0;
4587                 }
4588                 else
4589                 {
4590                         tb->cx = len;
4591                         break;
4592                 }
4593
4594                 do_editor_command(player_ptr, tb, EC_BACKSPACE);
4595                 break;
4596         }
4597         case EC_BACKSPACE:
4598         {
4599                 int len, i, j, k;
4600                 char buf[MAX_LINELEN];
4601                 if (tb->mark)
4602                 {
4603                         tb->mark = 0;
4604                         tb->dirty_flags |= DIRTY_ALL;
4605                 }
4606
4607                 len = strlen(tb->lines_list[tb->cy]);
4608                 if (len < tb->cx) tb->cx = len;
4609
4610                 if (tb->cx == 0)
4611                 {
4612                         if (tb->cy == 0) break;
4613                         tb->cx = strlen(tb->lines_list[tb->cy - 1]);
4614                         strcpy(buf, tb->lines_list[tb->cy - 1]);
4615                         strcat(buf, tb->lines_list[tb->cy]);
4616                         string_free(tb->lines_list[tb->cy - 1]);
4617                         string_free(tb->lines_list[tb->cy]);
4618                         tb->lines_list[tb->cy - 1] = string_make(buf);
4619
4620                         for (i = tb->cy; tb->lines_list[i + 1]; i++)
4621                                 tb->lines_list[i] = tb->lines_list[i + 1];
4622
4623                         tb->lines_list[i] = NULL;
4624                         tb->cy--;
4625                         tb->dirty_flags |= DIRTY_ALL;
4626                         tb->dirty_flags |= DIRTY_EXPRESSION;
4627                         tb->changed = TRUE;
4628                         break;
4629                 }
4630
4631                 for (i = j = k = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
4632                 {
4633                         k = j;
4634 #ifdef JP
4635                         if (iskanji(tb->lines_list[tb->cy][i]))
4636                                 buf[j++] = tb->lines_list[tb->cy][i++];
4637 #endif
4638                         buf[j++] = tb->lines_list[tb->cy][i];
4639                 }
4640
4641                 while (j > k)
4642                 {
4643                         tb->cx--;
4644                         j--;
4645                 }
4646
4647                 for (; tb->lines_list[tb->cy][i]; i++)
4648                 {
4649                         buf[j++] = tb->lines_list[tb->cy][i];
4650                 }
4651
4652                 buf[j] = '\0';
4653                 string_free(tb->lines_list[tb->cy]);
4654                 tb->lines_list[tb->cy] = string_make(buf);
4655                 tb->dirty_line = tb->cy;
4656                 check_expression_line(tb, tb->cy);
4657                 tb->changed = TRUE;
4658                 break;
4659         }
4660         case EC_SEARCH_STR:
4661         {
4662                 byte search_dir;
4663                 tb->dirty_flags |= DIRTY_SCREEN;
4664                 search_dir = get_string_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str);
4665
4666                 if (!search_dir) break;
4667
4668                 if (search_dir == 1) do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
4669                 else do_editor_command(player_ptr, tb, EC_SEARCH_BACK);
4670                 break;
4671         }
4672         case EC_SEARCH_FORW:
4673                 if (tb->search_o_ptr)
4674                 {
4675                         search_for_object(player_ptr, tb, tb->search_o_ptr, TRUE);
4676                         break;
4677                 }
4678
4679                 if (tb->search_str && tb->search_str[0])
4680                 {
4681                         search_for_string(tb, tb->search_str, TRUE);
4682                         break;
4683                 }
4684
4685                 tb->dirty_flags |= DIRTY_NO_SEARCH;
4686                 break;
4687
4688         case EC_SEARCH_BACK:
4689                 if (tb->search_o_ptr)
4690                 {
4691                         search_for_object(player_ptr, tb, tb->search_o_ptr, FALSE);
4692                         break;
4693                 }
4694
4695                 if (tb->search_str && tb->search_str[0])
4696                 {
4697                         search_for_string(tb, tb->search_str, FALSE);
4698                         break;
4699                 }
4700
4701                 tb->dirty_flags |= DIRTY_NO_SEARCH;
4702                 break;
4703
4704         case EC_SEARCH_OBJ:
4705                 tb->dirty_flags |= DIRTY_SCREEN;
4706
4707                 if (!get_object_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str)) break;
4708
4709                 do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
4710                 break;
4711
4712         case EC_SEARCH_DESTROYED:
4713                 if (!get_destroyed_object_for_search(player_ptr, &tb->search_o_ptr, &tb->search_str))
4714                 {
4715                         tb->dirty_flags |= DIRTY_NO_SEARCH;
4716                         break;
4717                 }
4718
4719                 do_editor_command(player_ptr, tb, EC_SEARCH_FORW);
4720                 break;
4721
4722         case EC_INSERT_OBJECT:
4723         {
4724                 autopick_type an_entry, *entry = &an_entry;
4725                 if (!entry_from_choosed_object(player_ptr, entry))
4726                 {
4727                         tb->dirty_flags |= DIRTY_SCREEN;
4728                         break;
4729                 }
4730
4731                 tb->cx = 0;
4732                 insert_return_code(tb);
4733                 string_free(tb->lines_list[tb->cy]);
4734                 tb->lines_list[tb->cy] = autopick_line_from_entry_kill(entry);
4735                 tb->dirty_flags |= DIRTY_SCREEN;
4736                 break;
4737         }
4738         case EC_INSERT_DESTROYED:
4739                 if (!tb->last_destroyed) break;
4740
4741                 tb->cx = 0;
4742                 insert_return_code(tb);
4743                 string_free(tb->lines_list[tb->cy]);
4744                 tb->lines_list[tb->cy] = string_make(tb->last_destroyed);
4745                 tb->dirty_flags |= DIRTY_ALL;
4746                 tb->changed = TRUE;
4747                 break;
4748
4749         case EC_INSERT_BLOCK:
4750         {
4751                 char expression[80];
4752                 sprintf(expression, "?:[AND [EQU $RACE %s] [EQU $CLASS %s] [GEQ $LEVEL %02d]]",
4753 #ifdef JP
4754                         rp_ptr->E_title, cp_ptr->E_title,
4755 #else
4756                         rp_ptr->title, cp_ptr->title,
4757 #endif
4758                         player_ptr->lev);
4759                 tb->cx = 0;
4760                 insert_return_code(tb);
4761                 string_free(tb->lines_list[tb->cy]);
4762                 tb->lines_list[tb->cy] = string_make(expression);
4763                 tb->cy++;
4764                 insert_return_code(tb);
4765                 string_free(tb->lines_list[tb->cy]);
4766                 tb->lines_list[tb->cy] = string_make("?:1");
4767                 tb->dirty_flags |= DIRTY_ALL;
4768                 tb->changed = TRUE;
4769                 break;
4770         }
4771
4772         case EC_INSERT_MACRO:
4773                 draw_text_editor(player_ptr, tb);
4774                 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
4775                 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, _("P:<トリガーキー>: ", "P:<Trigger key>: "));
4776                 if (!insert_macro_line(tb)) break;
4777
4778                 tb->cx = 2;
4779                 tb->dirty_flags |= DIRTY_ALL;
4780                 tb->changed = TRUE;
4781                 break;
4782
4783         case EC_INSERT_KEYMAP:
4784                 draw_text_editor(player_ptr, tb);
4785                 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
4786                 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW,
4787                         format(_("C:%d:<コマンドキー>: ", "C:%d:<Keypress>: "), (rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG)));
4788
4789                 if (!insert_keymap_line(tb)) break;
4790
4791                 tb->cx = 2;
4792                 tb->dirty_flags |= DIRTY_ALL;
4793                 tb->changed = TRUE;
4794                 break;
4795
4796         case EC_CL_AUTOPICK: toggle_command_letter(tb, DO_AUTOPICK); break;
4797         case EC_CL_DESTROY: toggle_command_letter(tb, DO_AUTODESTROY); break;
4798         case EC_CL_LEAVE: toggle_command_letter(tb, DONT_AUTOPICK); break;
4799         case EC_CL_QUERY: toggle_command_letter(tb, DO_QUERY_AUTOPICK); break;
4800         case EC_CL_NO_DISP: toggle_command_letter(tb, DO_DISPLAY); break;
4801
4802         case EC_IK_UNAWARE: toggle_keyword(tb, FLG_UNAWARE); break;
4803         case EC_IK_UNIDENTIFIED: toggle_keyword(tb, FLG_UNIDENTIFIED); break;
4804         case EC_IK_IDENTIFIED: toggle_keyword(tb, FLG_IDENTIFIED); break;
4805         case EC_IK_STAR_IDENTIFIED: toggle_keyword(tb, FLG_STAR_IDENTIFIED); break;
4806         case EC_KK_WEAPONS: toggle_keyword(tb, FLG_WEAPONS); break;
4807         case EC_KK_FAVORITE_WEAPONS: toggle_keyword(tb, FLG_FAVORITE_WEAPONS); break;
4808         case EC_KK_ARMORS: toggle_keyword(tb, FLG_ARMORS); break;
4809         case EC_KK_MISSILES: toggle_keyword(tb, FLG_MISSILES); break;
4810         case EC_KK_DEVICES: toggle_keyword(tb, FLG_DEVICES); break;
4811         case EC_KK_LIGHTS: toggle_keyword(tb, FLG_LIGHTS); break;
4812         case EC_KK_JUNKS: toggle_keyword(tb, FLG_JUNKS); break;
4813         case EC_KK_CORPSES: toggle_keyword(tb, FLG_CORPSES); break;
4814         case EC_KK_SPELLBOOKS: toggle_keyword(tb, FLG_SPELLBOOKS); break;
4815         case EC_KK_SHIELDS: toggle_keyword(tb, FLG_SHIELDS); break;
4816         case EC_KK_BOWS: toggle_keyword(tb, FLG_BOWS); break;
4817         case EC_KK_RINGS: toggle_keyword(tb, FLG_RINGS); break;
4818         case EC_KK_AMULETS: toggle_keyword(tb, FLG_AMULETS); break;
4819         case EC_KK_SUITS: toggle_keyword(tb, FLG_SUITS); break;
4820         case EC_KK_CLOAKS: toggle_keyword(tb, FLG_CLOAKS); break;
4821         case EC_KK_HELMS: toggle_keyword(tb, FLG_HELMS); break;
4822         case EC_KK_GLOVES: toggle_keyword(tb, FLG_GLOVES); break;
4823         case EC_KK_BOOTS: toggle_keyword(tb, FLG_BOOTS); break;
4824         case EC_OK_COLLECTING: toggle_keyword(tb, FLG_COLLECTING); break;
4825         case EC_OK_BOOSTED: toggle_keyword(tb, FLG_BOOSTED); break;
4826         case EC_OK_MORE_DICE: toggle_keyword(tb, FLG_MORE_DICE); break;
4827         case EC_OK_MORE_BONUS: toggle_keyword(tb, FLG_MORE_BONUS); break;
4828         case EC_OK_WORTHLESS: toggle_keyword(tb, FLG_WORTHLESS); break;
4829         case EC_OK_ARTIFACT: toggle_keyword(tb, FLG_ARTIFACT); break;
4830         case EC_OK_EGO: toggle_keyword(tb, FLG_EGO); break;
4831         case EC_OK_GOOD: toggle_keyword(tb, FLG_GOOD); break;
4832         case EC_OK_NAMELESS: toggle_keyword(tb, FLG_NAMELESS); break;
4833         case EC_OK_AVERAGE: toggle_keyword(tb, FLG_AVERAGE); break;
4834         case EC_OK_RARE: toggle_keyword(tb, FLG_RARE); break;
4835         case EC_OK_COMMON: toggle_keyword(tb, FLG_COMMON); break;
4836         case EC_OK_WANTED: toggle_keyword(tb, FLG_WANTED); break;
4837         case EC_OK_UNIQUE: toggle_keyword(tb, FLG_UNIQUE); break;
4838         case EC_OK_HUMAN: toggle_keyword(tb, FLG_HUMAN); break;
4839         case EC_OK_UNREADABLE:
4840                 toggle_keyword(tb, FLG_UNREADABLE);
4841                 add_keyword(tb, FLG_SPELLBOOKS);
4842                 break;
4843         case EC_OK_REALM1:
4844                 toggle_keyword(tb, FLG_REALM1);
4845                 add_keyword(tb, FLG_SPELLBOOKS);
4846                 break;
4847         case EC_OK_REALM2:
4848                 toggle_keyword(tb, FLG_REALM2);
4849                 add_keyword(tb, FLG_SPELLBOOKS);
4850                 break;
4851         case EC_OK_FIRST:
4852                 toggle_keyword(tb, FLG_FIRST);
4853                 add_keyword(tb, FLG_SPELLBOOKS);
4854                 break;
4855         case EC_OK_SECOND:
4856                 toggle_keyword(tb, FLG_SECOND);
4857                 add_keyword(tb, FLG_SPELLBOOKS);
4858                 break;
4859         case EC_OK_THIRD:
4860                 toggle_keyword(tb, FLG_THIRD);
4861                 add_keyword(tb, FLG_SPELLBOOKS);
4862                 break;
4863         case EC_OK_FOURTH:
4864                 toggle_keyword(tb, FLG_FOURTH);
4865                 add_keyword(tb, FLG_SPELLBOOKS);
4866                 break;
4867         }
4868
4869         tb->old_com_id = com_id;
4870         return FALSE;
4871 }
4872
4873
4874 /*
4875  * Insert single letter at cursor position.
4876  */
4877 static void insert_single_letter(text_body_type *tb, int key)
4878 {
4879         int i, j, len;
4880         char buf[MAX_LINELEN];
4881
4882         for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
4883         {
4884                 buf[j++] = tb->lines_list[tb->cy][i];
4885         }
4886
4887 #ifdef JP
4888         if (iskanji(key))
4889         {
4890                 int next;
4891
4892                 inkey_base = TRUE;
4893                 next = inkey();
4894                 if (j + 2 < MAX_LINELEN)
4895                 {
4896                         buf[j++] = (char)key;
4897                         buf[j++] = (char)next;
4898                         tb->cx += 2;
4899                 }
4900                 else
4901                         bell();
4902         }
4903         else
4904 #endif
4905         {
4906                 if (j + 1 < MAX_LINELEN)
4907                         buf[j++] = (char)key;
4908                 tb->cx++;
4909         }
4910
4911         for (; tb->lines_list[tb->cy][i] && j + 1 < MAX_LINELEN; i++)
4912                 buf[j++] = tb->lines_list[tb->cy][i];
4913         buf[j] = '\0';
4914
4915         string_free(tb->lines_list[tb->cy]);
4916         tb->lines_list[tb->cy] = string_make(buf);
4917         len = strlen(tb->lines_list[tb->cy]);
4918         if (len < tb->cx) tb->cx = len;
4919
4920         tb->dirty_line = tb->cy;
4921         check_expression_line(tb, tb->cy);
4922         tb->changed = TRUE;
4923 }
4924
4925
4926 /*
4927  * Check special key code and get a movement command id
4928  */
4929 static int analyze_move_key(text_body_type *tb, int skey)
4930 {
4931         int com_id;
4932         if (!(skey & SKEY_MASK)) return 0;
4933
4934         switch (skey & ~SKEY_MOD_MASK)
4935         {
4936         case SKEY_DOWN:   com_id = EC_DOWN;   break;
4937         case SKEY_LEFT:   com_id = EC_LEFT;   break;
4938         case SKEY_RIGHT:  com_id = EC_RIGHT;  break;
4939         case SKEY_UP:     com_id = EC_UP;     break;
4940         case SKEY_PGUP:   com_id = EC_PGUP;   break;
4941         case SKEY_PGDOWN: com_id = EC_PGDOWN; break;
4942         case SKEY_TOP:    com_id = EC_TOP;    break;
4943         case SKEY_BOTTOM: com_id = EC_BOTTOM; break;
4944         default:
4945                 return 0;
4946         }
4947
4948         if (!(skey & SKEY_MOD_SHIFT))
4949         {
4950                 /*
4951                  * Un-shifted cursor keys cancells
4952                  * selection created by shift+cursor.
4953                  */
4954                 if (tb->mark & MARK_BY_SHIFT)
4955                 {
4956                         tb->mark = 0;
4957                         tb->dirty_flags |= DIRTY_ALL;
4958                 }
4959
4960                 return com_id;
4961         }
4962
4963         if (tb->mark) return com_id;
4964
4965         int len = strlen(tb->lines_list[tb->cy]);
4966         tb->mark = MARK_MARK | MARK_BY_SHIFT;
4967         tb->my = tb->cy;
4968         tb->mx = tb->cx;
4969         if (tb->cx > len) tb->mx = len;
4970
4971         if (com_id == EC_UP || com_id == EC_DOWN)
4972         {
4973                 tb->dirty_flags |= DIRTY_ALL;
4974         }
4975         else
4976         {
4977                 tb->dirty_line = tb->cy;
4978         }
4979
4980         return com_id;
4981 }
4982
4983 /*
4984  * In-game editor of Object Auto-picker/Destoryer
4985  * @param player_ptr プレーヤーへの参照ポインタ
4986  */
4987 void do_cmd_edit_autopick(player_type *player_ptr)
4988 {
4989         static int cx_save = 0;
4990         static int cy_save = 0;
4991         text_body_type text_body, *tb = &text_body;
4992         autopick_type an_entry, *entry = &an_entry;
4993         char buf[MAX_LINELEN];
4994         int i;
4995         int key = -1;
4996         static s32b old_autosave_turn = 0L;
4997         byte quit = 0;
4998
4999         tb->changed = FALSE;
5000         tb->cx = cx_save;
5001         tb->cy = cy_save;
5002         tb->upper = tb->left = 0;
5003         tb->mark = 0;
5004         tb->mx = tb->my = 0;
5005         tb->old_cy = tb->old_upper = tb->old_left = -1;
5006         tb->old_wid = tb->old_hgt = -1;
5007         tb->old_com_id = 0;
5008
5009         tb->yank = NULL;
5010         tb->search_o_ptr = NULL;
5011         tb->search_str = NULL;
5012         tb->last_destroyed = NULL;
5013         tb->dirty_flags = DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
5014         tb->dirty_line = -1;
5015         tb->filename_mode = PT_DEFAULT;
5016
5017         if (current_world_ptr->game_turn < old_autosave_turn)
5018         {
5019                 while (old_autosave_turn > current_world_ptr->game_turn) old_autosave_turn -= TURNS_PER_TICK * TOWN_DAWN;
5020         }
5021
5022         if (current_world_ptr->game_turn > old_autosave_turn + 100L)
5023         {
5024                 do_cmd_save_game(player_ptr, TRUE);
5025                 old_autosave_turn = current_world_ptr->game_turn;
5026         }
5027
5028         update_playtime();
5029         init_autopick();
5030         if (autopick_last_destroyed_object.k_idx)
5031         {
5032                 autopick_entry_from_object(player_ptr, entry, &autopick_last_destroyed_object);
5033                 tb->last_destroyed = autopick_line_from_entry_kill(entry);
5034         }
5035
5036         tb->lines_list = read_pickpref_text_lines(player_ptr, &tb->filename_mode);
5037         for (i = 0; i < tb->cy; i++)
5038         {
5039                 if (!tb->lines_list[i])
5040                 {
5041                         tb->cy = tb->cx = 0;
5042                         break;
5043                 }
5044         }
5045
5046         screen_save();
5047         while (!quit)
5048         {
5049                 int com_id = 0;
5050                 draw_text_editor(player_ptr, tb);
5051                 prt(_("(^Q:終了 ^W:セーブして終了, ESC:メニュー, その他:入力)",
5052                         "(^Q:Quit, ^W:Save&Quit, ESC:Menu, Other:Input text)"), 0, 0);
5053                 if (!tb->mark)
5054                 {
5055                         prt(format("(%d,%d)", tb->cx, tb->cy), 0, 60);
5056                 }
5057                 else
5058                 {
5059                         prt(format("(%d,%d)-(%d,%d)", tb->mx, tb->my, tb->cx, tb->cy), 0, 60);
5060                 }
5061
5062                 Term_gotoxy(tb->cx - tb->left, tb->cy - tb->upper + 1);
5063                 tb->dirty_flags = 0;
5064                 tb->dirty_line = -1;
5065                 tb->old_cy = tb->cy;
5066                 tb->old_upper = tb->upper;
5067                 tb->old_left = tb->left;
5068                 tb->old_wid = tb->wid;
5069                 tb->old_hgt = tb->hgt;
5070
5071                 key = inkey_special(TRUE);
5072
5073                 if (key & SKEY_MASK)
5074                 {
5075                         com_id = analyze_move_key(tb, key);
5076                 }
5077                 else if (key == ESCAPE)
5078                 {
5079                         com_id = do_command_menu(0, 0);
5080                         tb->dirty_flags |= DIRTY_SCREEN;
5081                 }
5082                 else if (!iscntrl((unsigned char)key))
5083                 {
5084                         if (tb->mark)
5085                         {
5086                                 tb->mark = 0;
5087                                 tb->dirty_flags |= DIRTY_ALL;
5088                         }
5089
5090                         insert_single_letter(tb, key);
5091                         continue;
5092                 }
5093                 else
5094                 {
5095                         com_id = get_com_id((char)key);
5096                 }
5097
5098                 if (com_id) quit = do_editor_command(player_ptr, tb, com_id);
5099         }
5100
5101         screen_load();
5102         strcpy(buf, pickpref_filename(player_ptr, tb->filename_mode));
5103
5104         if (quit == QUIT_AND_SAVE)
5105                 write_text_lines(buf, tb->lines_list);
5106
5107         free_text_lines(tb->lines_list);
5108         string_free(tb->search_str);
5109         string_free(tb->last_destroyed);
5110         kill_yank_chain(tb);
5111
5112         process_autopick_file(player_ptr, buf);
5113         current_world_ptr->start_time = (u32b)time(NULL);
5114         cx_save = tb->cx;
5115         cy_save = tb->cy;
5116 }