OSDN Git Service

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