OSDN Git Service

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