OSDN Git Service

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