OSDN Git Service

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