OSDN Git Service

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