OSDN Git Service

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