OSDN Git Service

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