OSDN Git Service

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