OSDN Git Service

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