OSDN Git Service

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