OSDN Git Service

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