OSDN Git Service

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