OSDN Git Service

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