OSDN Git Service

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