OSDN Git Service

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