OSDN Git Service

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