OSDN Git Service

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