OSDN Git Service

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