OSDN Git Service

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