OSDN Git Service

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