OSDN Git Service

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