OSDN Git Service

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