OSDN Git Service

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