OSDN Git Service

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