OSDN Git Service

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