OSDN Git Service

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