OSDN Git Service

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