OSDN Git Service

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