OSDN Git Service

修正2つ。最下行をカットするとクラッシュ。行末より右にカーソルが(表示上で)位置する時にテキスト選択を始めると表示がバグる。
[hengband/hengband.git] / src / autopick.c
1 /* File: autopick.c */
2
3 /* Purpose: Object Auto-picker/Destroyer */
4
5 /*
6  * Copyright (c) 2002  Mogami
7  *
8  * This software may be copied and distributed for educational, research, and
9  * not for profit purposes provided that this copyright and statement are
10  * included in all such copies.
11  */
12
13 #include "angband.h"
14
15
16 #define MAX_LINELEN 1024
17
18 /*
19  * Macros for Keywords
20  */
21 #define FLG_ALL             0
22 #define FLG_COLLECTING      1
23 #define FLG_UNAWARE         2 
24 #define FLG_UNIDENTIFIED    3 
25 #define FLG_IDENTIFIED      4 
26 #define FLG_STAR_IDENTIFIED 5 
27 #define FLG_BOOSTED         6 
28 #define FLG_MORE_THAN       7 
29 #define FLG_DICE            8 
30 #define FLG_MORE_BONUS      9 
31 #define FLG_MORE_BONUS2     10
32 #define FLG_WORTHLESS       11
33 #define FLG_ARTIFACT        12
34 #define FLG_EGO             13
35 #define FLG_NAMELESS        14
36 #define FLG_WANTED          15
37 #define FLG_UNIQUE          16
38 #define FLG_HUMAN           17
39 #define FLG_UNREADABLE      18
40 #define FLG_REALM1          19
41 #define FLG_REALM2          20
42 #define FLG_FIRST           21
43 #define FLG_SECOND          22
44 #define FLG_THIRD           23
45 #define FLG_FOURTH          24
46
47 #define FLG_ITEMS           30
48 #define FLG_WEAPONS         31
49 #define FLG_ARMORS          32
50 #define FLG_MISSILES        33
51 #define FLG_DEVICES         34
52 #define FLG_LIGHTS          35
53 #define FLG_JUNKS           36
54 #define FLG_SPELLBOOKS      37
55 #define FLG_HAFTED          38
56 #define FLG_SHIELDS         39
57 #define FLG_BOWS            40
58 #define FLG_RINGS           41
59 #define FLG_AMULETS         42
60 #define FLG_SUITS           43
61 #define FLG_CLOAKS          44
62 #define FLG_HELMS           45
63 #define FLG_GLOVES          46
64 #define FLG_BOOTS           47
65 #define FLG_FAVORITE        48
66
67 #define FLG_NOUN_BEGIN      FLG_ITEMS
68 #define FLG_NOUN_END        FLG_FAVORITE
69
70 #ifdef JP
71
72 #define KEY_ALL "¤¹¤Ù¤Æ¤Î"
73
74 #ifdef MAC_MPW
75 /*
76  * MEGA HACK -- MPW¤Î¥Ð¥°½ü¤±¡£
77  * pre-processÃæ¤Ë¡Ö¼ý¡×¤Î»ú¤Î2¥Ð¥¤¥ÈÌܤ¬¾¡¼ê¤Ë¾Ã¤¨¤Æ¤·¤Þ¤¦¡£
78  */
79 #define KEY_COLLECTING "\x8e\xfb½¸Ãæ¤Î"
80 #else
81 #define KEY_COLLECTING "¼ý½¸Ãæ¤Î"
82 #endif
83
84 #define KEY_UNIDENTIFIED "̤´ÕÄê¤Î"
85 #define KEY_IDENTIFIED "´ÕÄêºÑ¤ß¤Î"
86 #define KEY_STAR_IDENTIFIED "*´ÕÄê*ºÑ¤ß¤Î"
87 #define KEY_BOOSTED "¥À¥¤¥¹Ìܤΰ㤦"
88 #define KEY_MORE_THAN  "¥À¥¤¥¹ÌÜ"
89 #define KEY_DICE  "°Ê¾å¤Î"
90 #define KEY_MORE_BONUS  "½¤ÀµÃÍ"
91 #define KEY_MORE_BONUS2  "°Ê¾å¤Î"
92 #define KEY_WORTHLESS "̵²ÁÃͤÎ"
93 #define KEY_ARTIFACT "¥¢¡¼¥Æ¥£¥Õ¥¡¥¯¥È"
94 #define KEY_EGO "¥¨¥´"
95 #define KEY_NAMELESS "̵ÌäÎ"
96 #define KEY_UNAWARE "̤ȽÌÀ¤Î"
97 #define KEY_WANTED "¾Þ¶â¼ó¤Î"
98 #define KEY_UNIQUE "¥æ¥Ë¡¼¥¯¡¦¥â¥ó¥¹¥¿¡¼¤Î"
99 #define KEY_HUMAN "¿Í´Ö¤Î"
100 #define KEY_UNREADABLE "Æɤá¤Ê¤¤"
101 #define KEY_REALM1 "Âè°ìÎΰè¤Î"
102 #define KEY_REALM2 "ÂèÆóÎΰè¤Î"
103 #define KEY_FIRST "1ºýÌܤÎ"
104 #define KEY_SECOND "2ºýÌܤÎ"
105 #define KEY_THIRD "3ºýÌܤÎ"
106 #define KEY_FOURTH "4ºýÌܤÎ"
107 #define KEY_ITEMS "¥¢¥¤¥Æ¥à"
108 #define KEY_WEAPONS "Éð´ï"
109 #define KEY_ARMORS "Ëɶñ"
110 #define KEY_MISSILES "Ìð"
111 #define KEY_DEVICES "ËâË¡¥¢¥¤¥Æ¥à"
112 #define KEY_LIGHTS "¸÷¸»"
113 #define KEY_JUNKS "¤¬¤é¤¯¤¿"
114 #define KEY_SPELLBOOKS "ËâË¡½ñ"
115 #define KEY_HAFTED "Æß´ï"
116 #define KEY_SHIELDS "½â"
117 #define KEY_BOWS "µÝ"
118 #define KEY_RINGS "»ØÎØ"
119 #define KEY_AMULETS "¥¢¥ß¥å¥ì¥Ã¥È"
120 #define KEY_SUITS "³»"
121 #define KEY_CLOAKS "¥¯¥í¡¼¥¯"
122 #define KEY_HELMS "³õ"
123 #define KEY_GLOVES "äƼê"
124 #define KEY_BOOTS "·¤"
125 #define KEY_FAVORITE "ÆÀ°ÕÉð´ï"
126
127 #else 
128
129 #define KEY_ALL "all"
130 #define KEY_COLLECTING "collecting"
131 #define KEY_UNIDENTIFIED "unidentified"
132 #define KEY_IDENTIFIED "identified"
133 #define KEY_STAR_IDENTIFIED "*identified*"
134 #define KEY_BOOSTED "dice boosted"
135 #define KEY_MORE_THAN  "more than"
136 #define KEY_DICE  " dice"
137 #define KEY_MORE_BONUS  "more bonus than"
138 #define KEY_MORE_BONUS2  ""
139 #define KEY_WORTHLESS "worthless"
140 #define KEY_ARTIFACT "artifact"
141 #define KEY_EGO "ego"
142 #define KEY_NAMELESS "nameless"
143 #define KEY_UNAWARE "unaware"
144 #define KEY_WANTED "wanted"
145 #define KEY_UNIQUE "unique monster's"
146 #define KEY_HUMAN "human"
147 #define KEY_UNREADABLE "unreadable"
148 #define KEY_REALM1 "first realm's"
149 #define KEY_REALM2 "second realm's"
150 #define KEY_FIRST "first"
151 #define KEY_SECOND "second"
152 #define KEY_THIRD "third"
153 #define KEY_FOURTH "fourth"
154 #define KEY_ITEMS "items"
155 #define KEY_WEAPONS "weapons"
156 #define KEY_ARMORS "armors"
157 #define KEY_MISSILES "missiles"
158 #define KEY_DEVICES "magical devices"
159 #define KEY_LIGHTS "lights"
160 #define KEY_JUNKS "junks"
161 #define KEY_SPELLBOOKS "spellbooks"
162 #define KEY_HAFTED "hafted weapons"
163 #define KEY_SHIELDS "shields"
164 #define KEY_BOWS "bows"
165 #define KEY_RINGS "rings"
166 #define KEY_AMULETS "amulets"
167 #define KEY_SUITS "suits"
168 #define KEY_CLOAKS "cloaks"
169 #define KEY_HELMS "helms"
170 #define KEY_GLOVES "gloves"
171 #define KEY_BOOTS "boots"
172 #define KEY_FAVORITE "favorite weapons"
173
174 #endif /* JP */
175
176 #define MATCH_KEY(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\
177      ? (ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE)
178 #define MATCH_KEY2(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\
179      ? (prev_ptr = ptr, ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE)
180
181 #ifdef JP
182 #define ADD_KEY(KEY) strcat(ptr, KEY)
183 #else
184 #define ADD_KEY(KEY) (strcat(ptr, KEY), strcat(ptr, " "))
185 #endif
186 #define ADD_KEY2(KEY) strcat(ptr, KEY)
187
188 #define ADD_FLG(FLG) (entry->flag[FLG / 32] |= (1L << (FLG % 32)))
189 #define REM_FLG(FLG) (entry->flag[FLG / 32] &= ~(1L << (FLG % 32)))
190 #define ADD_FLG_NOUN(FLG) (ADD_FLG(FLG), prev_flg = FLG)
191 #define IS_FLG(FLG) (entry->flag[FLG / 32] & (1L << (FLG % 32)))
192
193 #ifdef JP
194         static char kanji_colon[] = "¡§";
195 #endif
196
197
198 /*
199  * A function to create new entry
200  */
201 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 #define MARK_MARK     0x01
1394 #define MARK_BY_SHIFT 0x02
1395
1396 /* 
1397  * Struct for yank buffer
1398  */
1399 typedef struct chain_str {
1400         struct chain_str *next;
1401         char s[1];
1402 } chain_str_type;
1403
1404
1405 /*
1406  * Data struct for text editor
1407  */
1408 typedef struct {
1409         int wid, hgt;
1410         int cx, cy;
1411         int upper, left;
1412         int old_wid, old_hgt;
1413         int old_cy;
1414         int old_upper, old_left;
1415         int mx, my;
1416         byte mark;
1417
1418         object_type *search_o_ptr;
1419         cptr search_str;
1420         cptr last_destroyed;
1421
1422         chain_str_type *yank;
1423         bool yank_eol;
1424
1425         cptr *lines_list;
1426
1427         byte dirty_flags;
1428         int dirty_line;
1429         int filename_mode;
1430         int old_com_id;
1431 } text_body_type;
1432
1433
1434 /*
1435  * Dirty flag for text editor
1436  */
1437 #define DIRTY_ALL 0x01
1438 #define DIRTY_MODE 0x04
1439 #define DIRTY_SCREEN 0x08
1440 #define DIRTY_NOT_FOUND 0x10
1441 #define DIRTY_NO_SEARCH 0x20
1442
1443
1444 /*
1445  * Describe which kind of object is Auto-picked/destroyed
1446  */
1447 static void describe_autopick(char *buff, autopick_type *entry)
1448 {
1449         cptr str = entry->name;
1450         byte act = entry->action;
1451         cptr insc = entry->insc;
1452         int i;
1453
1454         bool top = FALSE;
1455
1456 #ifdef JP
1457         cptr before_str[100], body_str;
1458         int before_n = 0;
1459
1460         body_str = "¥¢¥¤¥Æ¥à";
1461
1462         /*** Collecting items ***/
1463         /*** Which can be absorbed into a slot as a bundle ***/
1464         if (IS_FLG(FLG_COLLECTING))
1465                 before_str[before_n++] = "¼ý½¸Ãæ¤Ç´û¤Ë»ý¤Ã¤Æ¤¤¤ë¥¹¥í¥Ã¥È¤Ë¤Þ¤È¤á¤é¤ì¤ë";
1466         
1467         /*** Unidentified ***/
1468         if (IS_FLG(FLG_UNIDENTIFIED))
1469                 before_str[before_n++] = "̤´ÕÄê¤Î";
1470
1471         /*** Identified ***/
1472         if (IS_FLG(FLG_IDENTIFIED))
1473                 before_str[before_n++] = "´ÕÄêºÑ¤ß¤Î";
1474
1475         /*** *Identified* ***/
1476         if (IS_FLG(FLG_STAR_IDENTIFIED))
1477                 before_str[before_n++] = "´°Á´¤Ë´ÕÄêºÑ¤ß¤Î";
1478
1479         /*** Dice boosted (weapon of slaying) ***/
1480         if (IS_FLG(FLG_BOOSTED))
1481         {
1482                 before_str[before_n++] = "¥À¥á¡¼¥¸¥À¥¤¥¹¤¬Ä̾ï¤è¤êÂ礭¤¤";
1483                 body_str = "Éð´ï";
1484         }
1485
1486         /*** Weapons whose dd*ds is more than nn ***/
1487         if (IS_FLG(FLG_MORE_THAN))
1488         {
1489                 static char more_than_desc_str[] = "___";
1490                 before_str[before_n++] = "¥À¥á¡¼¥¸¥À¥¤¥¹¤ÎºÇÂçÃͤ¬";
1491                 body_str = "Éð´ï";
1492                         
1493                 sprintf(more_than_desc_str,"%d", entry->dice);
1494                 before_str[before_n++] = more_than_desc_str;
1495                 before_str[before_n++] = "°Ê¾å¤Î";
1496         }
1497
1498         /*** Items whose magical bonus is more than nn ***/
1499         if (IS_FLG(FLG_MORE_BONUS))
1500         {
1501                 static char more_bonus_desc_str[] = "___";
1502                 before_str[before_n++] = "½¤ÀµÃͤ¬(+";
1503                         
1504                 sprintf(more_bonus_desc_str,"%d", entry->bonus);
1505                 before_str[before_n++] = more_bonus_desc_str;
1506                 before_str[before_n++] = ")°Ê¾å¤Î";
1507         }
1508
1509         /*** Worthless items ***/
1510         if (IS_FLG(FLG_WORTHLESS))
1511                 before_str[before_n++] = "Ź¤Ç̵²ÁÃͤÈȽÄꤵ¤ì¤ë";
1512
1513         /*** Artifact ***/
1514         if (IS_FLG(FLG_ARTIFACT))
1515         {
1516                 before_str[before_n++] = "¥¢¡¼¥Æ¥£¥Õ¥¡¥¯¥È¤Î";
1517                 body_str = "ÁõÈ÷";
1518         }
1519
1520         /*** Ego ***/
1521         if (IS_FLG(FLG_EGO))
1522         {
1523                 before_str[before_n++] = "¥¨¥´¥¢¥¤¥Æ¥à¤Î";
1524                 body_str = "ÁõÈ÷";
1525         }
1526
1527         /*** Nameless ***/
1528         if (IS_FLG(FLG_NAMELESS))
1529         {
1530                 before_str[before_n++] = "¥¨¥´¤Ç¤â¥¢¡¼¥Æ¥£¥Õ¥¡¥¯¥È¤Ç¤â¤Ê¤¤";
1531                 body_str = "ÁõÈ÷";
1532         }
1533
1534         /*** Unaware items ***/
1535         if (IS_FLG(FLG_UNAWARE))
1536                 before_str[before_n++] = "̤´ÕÄê¤Ç¤½¤Î¸ú²Ì¤âȽÌÀ¤·¤Æ¤¤¤Ê¤¤";
1537
1538         /*** Wanted monster's corpse/skeletons ***/
1539         if (IS_FLG(FLG_WANTED))
1540         {
1541                 before_str[before_n++] = "¥Ï¥ó¥¿¡¼»ö̳½ê¤Ç¾Þ¶â¼ó¤È¤µ¤ì¤Æ¤¤¤ë";
1542                 body_str = "»àÂΤä¹ü";
1543         }
1544
1545         /*** Human corpse/skeletons (for Daemon magic) ***/
1546         if (IS_FLG(FLG_HUMAN))
1547         {
1548                 before_str[before_n++] = "°­ËâËâË¡¤Ç»È¤¦¤¿¤á¤Î¿Í´Ö¤ä¥Ò¥å¡¼¥Þ¥Î¥¤¥É¤Î";
1549                 body_str = "»àÂΤä¹ü";
1550         }
1551
1552         /*** Unique monster's corpse/skeletons/statues ***/
1553         if (IS_FLG(FLG_UNIQUE))
1554         {
1555                 before_str[before_n++] = "¥æ¥Ë¡¼¥¯¥â¥ó¥¹¥¿¡¼¤Î";
1556                 body_str = "»àÂΤä¹ü";
1557         }
1558
1559         /*** Unreadable spellbooks ***/
1560         if (IS_FLG(FLG_UNREADABLE))
1561         {
1562                 before_str[before_n++] = "¤¢¤Ê¤¿¤¬Æɤá¤Ê¤¤Îΰè¤Î";
1563                 body_str = "ËâË¡½ñ";
1564         }
1565
1566         /*** First realm spellbooks ***/
1567         if (IS_FLG(FLG_REALM1))
1568         {
1569                 before_str[before_n++] = "Âè°ìÎΰè¤Î";
1570                 body_str = "ËâË¡½ñ";
1571         }
1572
1573         /*** Second realm spellbooks ***/
1574         if (IS_FLG(FLG_REALM2))
1575         {
1576                 before_str[before_n++] = "ÂèÆóÎΰè¤Î";
1577                 body_str = "ËâË¡½ñ";
1578         }
1579
1580         /*** First rank spellbooks ***/
1581         if (IS_FLG(FLG_FIRST))
1582         {
1583                 before_str[before_n++] = "Á´4ºý¤ÎÆâ¤Î1ºýÌܤÎ";
1584                 body_str = "ËâË¡½ñ";
1585         }
1586
1587         /*** Second rank spellbooks ***/
1588         if (IS_FLG(FLG_SECOND))
1589         {
1590                 before_str[before_n++] = "Á´4ºý¤ÎÆâ¤Î2ºýÌܤÎ";
1591                 body_str = "ËâË¡½ñ";
1592         }
1593
1594         /*** Third rank spellbooks ***/
1595         if (IS_FLG(FLG_THIRD))
1596         {
1597                 before_str[before_n++] = "Á´4ºý¤ÎÆâ¤Î3ºýÌܤÎ";
1598                 body_str = "ËâË¡½ñ";
1599         }
1600
1601         /*** Fourth rank spellbooks ***/
1602         if (IS_FLG(FLG_FOURTH))
1603         {
1604                 before_str[before_n++] = "Á´4ºý¤ÎÆâ¤Î4ºýÌܤÎ";
1605                 body_str = "ËâË¡½ñ";
1606         }
1607
1608         /*** Items ***/
1609         if (IS_FLG(FLG_ITEMS))
1610                 ; /* Nothing to do */
1611         else if (IS_FLG(FLG_WEAPONS))
1612                 body_str = "Éð´ï";
1613         else if (IS_FLG(FLG_ARMORS))
1614                 body_str = "Ëɶñ";
1615         else if (IS_FLG(FLG_MISSILES))
1616                 body_str = "ÃƤäÌð¤ä¥¯¥í¥¹¥Ü¥¦¤ÎÌð";
1617         else if (IS_FLG(FLG_DEVICES))
1618                 body_str = "´¬Êª¤äËâË¡ËÀ¤ä¾ó¤ä¥í¥Ã¥É";
1619         else if (IS_FLG(FLG_LIGHTS))
1620                 body_str = "¸÷¸»ÍѤΥ¢¥¤¥Æ¥à";
1621         else if (IS_FLG(FLG_JUNKS))
1622                 body_str = "Àޤ줿ËÀÅù¤Î¥¬¥é¥¯¥¿";
1623         else if (IS_FLG(FLG_SPELLBOOKS))
1624                 body_str = "ËâË¡½ñ";
1625         else if (IS_FLG(FLG_HAFTED))
1626                 body_str = "Æß´ï";
1627         else if (IS_FLG(FLG_SHIELDS))
1628                 body_str = "½â";
1629         else if (IS_FLG(FLG_BOWS))
1630                 body_str = "¥¹¥ê¥ó¥°¤äµÝ¤ä¥¯¥í¥¹¥Ü¥¦";
1631         else if (IS_FLG(FLG_RINGS))
1632                 body_str = "»ØÎØ";
1633         else if (IS_FLG(FLG_AMULETS))
1634                 body_str = "¥¢¥ß¥å¥ì¥Ã¥È";
1635         else if (IS_FLG(FLG_SUITS))
1636                 body_str = "³»";
1637         else if (IS_FLG(FLG_CLOAKS))
1638                 body_str = "¥¯¥í¡¼¥¯";
1639         else if (IS_FLG(FLG_HELMS))
1640                 body_str = "¥Ø¥ë¥á¥Ã¥È¤ä´§";
1641         else if (IS_FLG(FLG_GLOVES))
1642                 body_str = "äƼê";
1643         else if (IS_FLG(FLG_BOOTS))
1644                 body_str = "¥Ö¡¼¥Ä";
1645         else if (IS_FLG(FLG_FAVORITE))
1646                 body_str = "ÆÀ°ÕÉð´ï";
1647
1648         *buff = '\0';
1649         if (!before_n) 
1650                 strcat(buff, "Á´¤Æ¤Î");
1651         else for (i = 0; i < before_n && before_str[i]; i++)
1652                 strcat(buff, before_str[i]);
1653
1654         strcat(buff, body_str);
1655
1656         if (*str)
1657         {
1658                 if (*str == '^')
1659                 {
1660                         str++;
1661                         top = TRUE;
1662                 }
1663
1664                 strcat(buff, "¤Ç¡¢Ì¾Á°¤¬¡Ö");
1665                 strncat(buff, str, 80);
1666                 if (top)
1667                         strcat(buff, "¡×¤Ç»Ï¤Þ¤ë¤â¤Î");
1668                 else
1669                         strcat(buff, "¡×¤ò´Þ¤à¤â¤Î");
1670         }
1671
1672         if (insc)
1673         {
1674                 strncat(buff, format("¤Ë¡Ö%s¡×", insc), 80);
1675
1676                 if (strstr(insc, "%%all"))
1677                         strcat(buff, "(%%all¤ÏÁ´Ç½ÎϤòɽ¤¹±Ñ»ú¤Îµ­¹æ¤ÇÃÖ´¹)");
1678                 else if (strstr(insc, "%all"))
1679                         strcat(buff, "(%all¤ÏÁ´Ç½ÎϤòɽ¤¹µ­¹æ¤ÇÃÖ´¹)");
1680                 else if (strstr(insc, "%%"))
1681                         strcat(buff, "(%%¤ÏÄɲÃǽÎϤòɽ¤¹±Ñ»ú¤Îµ­¹æ¤ÇÃÖ´¹)");
1682                 else if (strstr(insc, "%"))
1683                         strcat(buff, "(%¤ÏÄɲÃǽÎϤòɽ¤¹µ­¹æ¤ÇÃÖ´¹)");
1684
1685                 strcat(buff, "¤È¹ï¤ó¤Ç");
1686         }
1687         else
1688                 strcat(buff, "¤ò");
1689
1690         if (act & DONT_AUTOPICK)
1691                 strcat(buff, "ÊüÃÖ¤¹¤ë¡£");
1692         else if (act & DO_AUTODESTROY)
1693                 strcat(buff, "Ç˲õ¤¹¤ë¡£");
1694         else if (act & DO_QUERY_AUTOPICK)
1695                 strcat(buff, "³Îǧ¤Î¸å¤Ë½¦¤¦¡£");
1696         else
1697                 strcat(buff, "½¦¤¦¡£");
1698
1699         if (act & DO_DISPLAY)
1700         {
1701                 if (act & DONT_AUTOPICK)
1702                         strcat(buff, "Á´ÂΥޥå×('M')¤Ç'N'¤ò²¡¤·¤¿¤È¤­¤Ëɽ¼¨¤¹¤ë¡£");
1703                 else if (act & DO_AUTODESTROY)
1704                         strcat(buff, "Á´ÂΥޥå×('M')¤Ç'K'¤ò²¡¤·¤¿¤È¤­¤Ëɽ¼¨¤¹¤ë¡£");
1705                 else
1706                         strcat(buff, "Á´ÂΥޥå×('M')¤Ç'M'¤ò²¡¤·¤¿¤È¤­¤Ëɽ¼¨¤¹¤ë¡£");
1707         }
1708         else
1709                 strcat(buff, "Á´ÂΥޥåפˤÏɽ¼¨¤·¤Ê¤¤");
1710
1711 #else /* JP */
1712
1713         cptr before_str[20], after_str[20], which_str[20], whose_str[20], body_str;
1714         int before_n = 0, after_n = 0, which_n = 0, whose_n = 0;
1715
1716         body_str = "items";
1717
1718         /*** Collecting items ***/
1719         /*** Which can be absorbed into a slot as a bundle ***/
1720         if (IS_FLG(FLG_COLLECTING))
1721                 which_str[which_n++] = "can be absorbed into an existing inventory slot";
1722         
1723         /*** Unidentified ***/
1724         if (IS_FLG(FLG_UNIDENTIFIED))
1725                 before_str[before_n++] = "unidentified";
1726
1727         /*** Identified ***/
1728         if (IS_FLG(FLG_IDENTIFIED))
1729                 before_str[before_n++] = "identified";
1730
1731         /*** *Identified* ***/
1732         if (IS_FLG(FLG_STAR_IDENTIFIED))
1733                 before_str[before_n++] = "fully identified";
1734
1735         /*** Worthless items ***/
1736         if (IS_FLG(FLG_WORTHLESS))
1737         {
1738                 before_str[before_n++] = "worthless";
1739                 which_str[which_n++] = "can not be sold at stores";
1740         }
1741
1742         /*** Artifacto ***/
1743         if (IS_FLG(FLG_ARTIFACT))
1744         {
1745                 before_str[before_n++] = "artifact";
1746         }
1747
1748         /*** Ego ***/
1749         if (IS_FLG(FLG_EGO))
1750         {
1751                 before_str[before_n++] = "ego";
1752         }
1753
1754         /*** Nameless ***/
1755         if (IS_FLG(FLG_NAMELESS))
1756         {
1757                 body_str = "equipment";
1758                 which_str[which_n++] = "is neither ego-item nor artifact";
1759         }
1760
1761         /*** Unaware items ***/
1762         if (IS_FLG(FLG_UNAWARE))
1763         {
1764                 before_str[before_n++] = "unidentified";
1765                 whose_str[whose_n++] = "basic abilities are not known";
1766         }
1767
1768         /*** Dice boosted (weapon of slaying) ***/
1769         if (IS_FLG(FLG_BOOSTED))
1770         {
1771                 body_str = "weapons";
1772                 whose_str[whose_n++] = "damage dice is bigger than normal";
1773         }
1774
1775         /*** Weapons whose dd*ds is more than nn ***/
1776         if (IS_FLG(FLG_MORE_THAN))
1777         {
1778                 static char more_than_desc_str[] =
1779                         "maximum damage from dice is bigger than __";
1780                 body_str = "weapons";
1781                         
1782                 sprintf(more_than_desc_str + sizeof(more_than_desc_str) - 3,
1783                         "%d", entry->dice);
1784                 whose_str[whose_n++] = more_than_desc_str;
1785         }
1786
1787         /*** Items whose magical bonus is more than nn ***/
1788         if (IS_FLG(FLG_MORE_BONUS))
1789         {
1790                 static char more_bonus_desc_str[] =
1791                         "magical bonus is bigger than (+__)";
1792                         
1793                 sprintf(more_bonus_desc_str + sizeof(more_bonus_desc_str) - 4,
1794                         "%d)", entry->bonus);
1795                 whose_str[whose_n++] = more_bonus_desc_str;
1796         }
1797
1798         /*** Wanted monster's corpse/skeletons ***/
1799         if (IS_FLG(FLG_WANTED))
1800         {
1801                 body_str = "corpse or skeletons";
1802                 which_str[which_n++] = "is wanted at the Hunter's Office";
1803         }
1804
1805         /*** Human corpse/skeletons (for Daemon magic) ***/
1806         if (IS_FLG(FLG_HUMAN))
1807         {
1808                 before_str[before_n++] = "humanoid";
1809                 body_str = "corpse or skeletons";
1810                 which_str[which_n++] = "can be used for Daemon magic";
1811         }
1812
1813         /*** Unique monster's corpse/skeletons/statues ***/
1814         if (IS_FLG(FLG_UNIQUE))
1815         {
1816                 before_str[before_n++] = "unique monster's";
1817                 body_str = "corpse or skeletons";
1818         }
1819
1820         /*** Unreadable spellbooks ***/
1821         if (IS_FLG(FLG_UNREADABLE))
1822         {
1823                 body_str = "spellbooks";
1824                 after_str[after_n++] = "of different realms from yours";
1825         }
1826
1827         /*** First realm spellbooks ***/
1828         if (IS_FLG(FLG_REALM1))
1829         {
1830                 body_str = "spellbooks";
1831                 after_str[after_n++] = "of your first realm";
1832         }
1833
1834         /*** Second realm spellbooks ***/
1835         if (IS_FLG(FLG_REALM2))
1836         {
1837                 body_str = "spellbooks";
1838                 after_str[after_n++] = "of your second realm";
1839         }
1840
1841         /*** First rank spellbooks ***/
1842         if (IS_FLG(FLG_FIRST))
1843         {
1844                 before_str[before_n++] = "first one of four";
1845                 body_str = "spellbooks";
1846         }
1847
1848         /*** Second rank spellbooks ***/
1849         if (IS_FLG(FLG_SECOND))
1850         {
1851                 before_str[before_n++] = "second one of four";
1852                 body_str = "spellbooks";
1853         }
1854
1855         /*** Third rank spellbooks ***/
1856         if (IS_FLG(FLG_THIRD))
1857         {
1858                 before_str[before_n++] = "third one of four";
1859                 body_str = "spellbooks";
1860         }
1861
1862         /*** Fourth rank spellbooks ***/
1863         if (IS_FLG(FLG_FOURTH))
1864         {
1865                 before_str[before_n++] = "fourth one of four";
1866                 body_str = "spellbooks";
1867         }
1868
1869         /*** Items ***/
1870         if (IS_FLG(FLG_ITEMS))
1871                 ; /* Nothing to do */
1872         else if (IS_FLG(FLG_WEAPONS))
1873                 body_str = "weapons";
1874         else if (IS_FLG(FLG_ARMORS))
1875                 body_str = "armors";
1876         else if (IS_FLG(FLG_MISSILES))
1877                 body_str = "shots, arrows or crossbow bolts";
1878         else if (IS_FLG(FLG_DEVICES))
1879                 body_str = "scrolls, wands, staves or rods";
1880         else if (IS_FLG(FLG_LIGHTS))
1881                 body_str = "light sources";
1882         else if (IS_FLG(FLG_JUNKS))
1883                 body_str = "junk such as broken sticks";
1884         else if (IS_FLG(FLG_SPELLBOOKS))
1885                 body_str = "spellbooks";
1886         else if (IS_FLG(FLG_HAFTED))
1887                 body_str = "hafted weapons";
1888         else if (IS_FLG(FLG_SHIELDS))
1889                 body_str = "shields";
1890         else if (IS_FLG(FLG_BOWS))
1891                 body_str = "slings, bows or crossbows";
1892         else if (IS_FLG(FLG_RINGS))
1893                 body_str = "rings";
1894         else if (IS_FLG(FLG_AMULETS))
1895                 body_str = "amulets";
1896         else if (IS_FLG(FLG_SUITS))
1897                 body_str = "body armors";
1898         else if (IS_FLG(FLG_CLOAKS))
1899                 body_str = "cloaks";
1900         else if (IS_FLG(FLG_HELMS))
1901                 body_str = "helms or crowns";
1902         else if (IS_FLG(FLG_GLOVES))
1903                 body_str = "gloves";
1904         else if (IS_FLG(FLG_BOOTS))
1905                 body_str = "boots";
1906         else if (IS_FLG(FLG_FAVORITE))
1907                 body_str = "favorite weapons";
1908
1909         /* Prepare a string for item name */
1910         if (*str)
1911         {
1912                 if (*str == '^')
1913                 {
1914                         str++;
1915                         top = TRUE;
1916                         whose_str[whose_n++] = "name is beginning with \"";
1917                 }
1918                 else
1919                         which_str[which_n++] = "have \"";
1920         }
1921
1922
1923         /* Describe action flag */
1924         if (act & DONT_AUTOPICK)
1925                 strcpy(buff, "Leave on floor ");
1926         else if (act & DO_AUTODESTROY)
1927                 strcpy(buff, "Destroy ");
1928         else if (act & DO_QUERY_AUTOPICK)
1929                 strcpy(buff, "Ask to pick up ");
1930         else
1931                 strcpy(buff, "Pickup ");
1932
1933         /* Auto-insctiption */
1934         if (insc)
1935         {
1936                 strncat(buff, format("and inscribe \"%s\"", insc), 80);
1937
1938                 if (strstr(insc, "%all"))
1939                         strcat(buff, ", replacing %all with code string representing all abilities,");
1940                 else if (strstr(insc, "%"))
1941                         strcat(buff, ", replacing % with code string representing extra random abilities,");
1942
1943                 strcat(buff, " on ");
1944         }
1945
1946         /* Adjective */
1947         if (!before_n) 
1948                 strcat(buff, "all ");
1949         else for (i = 0; i < before_n && before_str[i]; i++)
1950         {
1951                 strcat(buff, before_str[i]);
1952                 strcat(buff, " ");
1953         }
1954
1955         /* Item class */
1956         strcat(buff, body_str);
1957
1958         /* of ... */
1959         for (i = 0; i < after_n && after_str[i]; i++)
1960         {
1961                 strcat(buff, " ");
1962                 strcat(buff, after_str[i]);
1963         }
1964
1965         /* which ... */
1966         for (i = 0; i < whose_n && whose_str[i]; i++)
1967         {
1968                 if (i == 0)
1969                         strcat(buff, " whose ");
1970                 else
1971                         strcat(buff, ", and ");
1972
1973                 strcat(buff, whose_str[i]);
1974         }
1975
1976         /* Item name ; whose name is beginning with "str" */
1977         if (*str && top)
1978         {
1979                 strcat(buff, str);
1980                 strcat(buff, "\"");
1981         }
1982
1983         /* whose ..., and which .... */
1984         if (whose_n && which_n)
1985                 strcat(buff, ", and ");
1986
1987         /* which ... */
1988         for (i = 0; i < which_n && which_str[i]; i++)
1989         {
1990                 if (i == 0)
1991                         strcat(buff, " which ");
1992                 else
1993                         strcat(buff, ", and ");
1994
1995                 strcat(buff, which_str[i]);
1996         }
1997
1998         /* Item name ; which have "str" as part of its name */
1999         if (*str && !top)
2000         {
2001                 strncat(buff, str, 80);
2002                 strcat(buff, "\" as part of its name");
2003         }
2004         strcat(buff, ".");
2005
2006         /* Describe whether it will be displayed on the full map or not */
2007         if (act & DO_DISPLAY)
2008         {
2009                 if (act & DONT_AUTOPICK)
2010                         strcat(buff, "  Display these items when you press the N key in the full 'M'ap.");
2011                 else if (act & DO_AUTODESTROY)
2012                         strcat(buff, "  Display these items when you press the K key in the full 'M'ap.");
2013                 else
2014                         strcat(buff, "  Display these items when you press the M key in the full 'M'ap.");
2015         }
2016         else
2017                 strcat(buff, " Not displayed in the full map.");
2018 #endif /* JP */
2019
2020 }
2021
2022
2023 #define MAX_LINES 3000
2024
2025 /*
2026  * Read whole lines of a file to memory
2027  */
2028 static cptr *read_text_lines(cptr filename, bool user)
2029 {
2030         cptr *lines_list = NULL;
2031         FILE *fff;
2032
2033         int lines = 0;
2034         char buf[1024];
2035
2036         if (user)
2037         {
2038                 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2039         }
2040         else
2041         {
2042                 path_build(buf, sizeof(buf), ANGBAND_DIR_PREF, filename);
2043         }
2044         
2045         /* Open the file */
2046         fff = my_fopen(buf, "r");
2047
2048         if (fff)
2049         {
2050                 /* Allocate list of pointers */
2051                 C_MAKE(lines_list, MAX_LINES, cptr);
2052
2053                 /* Parse it */
2054                 while (0 == my_fgets(fff, buf, sizeof(buf)))
2055                 {
2056                         lines_list[lines++] = string_make(buf);
2057                         if (lines >= MAX_LINES - 1) break;
2058                 }
2059                 if (lines == 0)
2060                         lines_list[0] = string_make("");
2061
2062                 my_fclose(fff);
2063         }
2064
2065         if (!fff) return NULL;
2066         return lines_list;
2067 }
2068
2069
2070 #define PT_DEFAULT 0
2071 #define PT_WITH_PNAME 1
2072
2073 static cptr *read_pickpref_text_lines(int *filename_mode_p)
2074 {
2075         char buf[1024];
2076         cptr *lines_list;
2077
2078 #ifdef JP
2079         sprintf(buf, "picktype-%s.prf", player_name);
2080 #else
2081         sprintf(buf, "pickpref-%s.prf", player_name);
2082 #endif
2083         lines_list = read_text_lines(buf, TRUE);
2084
2085         if (!lines_list)
2086         {
2087 #ifdef JP
2088                 lines_list = read_text_lines("picktype.prf", TRUE);
2089 #else
2090                 lines_list = read_text_lines("pickpref.prf", TRUE);
2091 #endif
2092                 *filename_mode_p = PT_DEFAULT;
2093         }
2094
2095         if (!lines_list)
2096         {
2097 #ifdef JP
2098                 lines_list = read_text_lines("picktype.prf", FALSE);
2099 #else
2100                 lines_list = read_text_lines("pickpref.prf", FALSE);
2101 #endif
2102                 *filename_mode_p = PT_WITH_PNAME;
2103         }
2104
2105         if (!lines_list)
2106         {
2107                 /* Allocate list of pointers */
2108                 C_MAKE(lines_list, MAX_LINES, cptr);
2109                 lines_list[0] = string_make("");
2110                 *filename_mode_p = PT_WITH_PNAME;
2111         }
2112         return lines_list;
2113 }
2114
2115
2116 /*
2117  * Write whole lines of memory to a file.
2118  */
2119 static bool write_text_lines(cptr filename, cptr *lines_list)
2120 {
2121         FILE *fff;
2122
2123         int lines = 0;
2124         char buf[1024];
2125
2126         /* Build the filename */
2127         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2128         
2129         /* Open the file */
2130         fff = my_fopen(buf, "w");
2131         if (fff)
2132         {
2133                 for (lines = 0; lines_list[lines]; lines++)
2134                         my_fputs(fff, lines_list[lines], 1024);
2135
2136                 my_fclose(fff);
2137         }
2138
2139         if (!fff) return FALSE;
2140         return TRUE;
2141 }
2142
2143
2144 /*
2145  * Free memory of lines_list.
2146  */
2147 static void free_text_lines(cptr *lines_list)
2148 {
2149         int lines;
2150
2151         for (lines = 0; lines_list[lines]; lines++)
2152                 string_free(lines_list[lines]);
2153
2154         /* free list of pointers */
2155         C_FREE((char **)lines_list, MAX_LINES, char *);
2156 }
2157
2158
2159 /*
2160  * Delete or insert string
2161  */
2162 static void toggle_keyword(text_body_type *tb, int flg)
2163 {
2164         int by1, by2, bx1, bx2, y;
2165         bool add = TRUE;
2166         bool fixed = FALSE;
2167
2168         /* Select this line */
2169         if (!tb->mark) tb->my = tb->cy;
2170
2171         if (tb->my < tb->cy)
2172         {
2173                 by1 = tb->my;
2174                 by2 = tb->cy;
2175                 bx1 = tb->mx;
2176                 bx2 = tb->cx;
2177         }
2178         else
2179         {
2180                 by2 = tb->my;
2181                 by1 = tb->cy;
2182                 bx2 = tb->mx;
2183                 bx1 = tb->cx;
2184         }
2185
2186         /* String on these lines are not really selected */  
2187         if (tb->lines_list[by1][bx1] == '\0' && by1 < tb->cy) by1++;
2188         if (bx2 == 0 && tb->cy < by2) by2--;
2189
2190
2191         /* Set/Reset flag of each line */
2192         for (y = by1; y <= by2; y++)
2193         {
2194                 autopick_type an_entry, *entry = &an_entry;
2195
2196                 if (!autopick_new_entry(entry, tb->lines_list[y]))
2197                         return;
2198
2199                 string_free(tb->lines_list[y]);
2200
2201                 if (!fixed)
2202                 {
2203                         /* Add? or Remove? */
2204                         if (!IS_FLG(flg)) add = TRUE;
2205                         else add = FALSE;
2206
2207                         /* No more change */
2208                         fixed = TRUE;
2209                 }
2210
2211                 /* You can use only one noun flag */
2212                 if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
2213                 {
2214                         int i;
2215                         for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
2216                                 REM_FLG(i);
2217                 }
2218                 
2219                 /* You can use only one identify state flag */
2220                 else if (FLG_UNAWARE <= flg && flg <= FLG_STAR_IDENTIFIED)
2221                 {
2222                         int i;
2223                         for (i = FLG_UNAWARE; i <= FLG_STAR_IDENTIFIED; i++)
2224                                 REM_FLG(i);
2225                 }
2226                 
2227                 /* You can use only one flag in artifact/ego/nameless */
2228                 else if (FLG_ARTIFACT <= flg && flg <= FLG_NAMELESS)
2229                 {
2230                         int i;
2231                         for (i = FLG_ARTIFACT; i <= FLG_NAMELESS; i++)
2232                                 REM_FLG(i);
2233                 }
2234                 
2235                 if (add) ADD_FLG(flg);
2236                 else REM_FLG(flg);
2237                 
2238                 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
2239                 
2240                 /* Now dirty */
2241                 tb->dirty_flags |= DIRTY_ALL;
2242         }
2243 }
2244
2245
2246 /*
2247  * Change command letter
2248  */
2249 static void toggle_command_letter(text_body_type *tb, byte flg)
2250 {
2251         autopick_type an_entry, *entry = &an_entry;
2252         int by1, by2, bx1, bx2, y;
2253         bool add = TRUE;
2254         bool fixed = FALSE;
2255
2256         /* Select this line */
2257         if (!tb->mark) tb->my = tb->cy;
2258
2259         if (tb->my < tb->cy)
2260         {
2261                 by1 = tb->my;
2262                 by2 = tb->cy;
2263                 bx1 = tb->mx;
2264                 bx2 = tb->cx;
2265         }
2266         else
2267         {
2268                 by2 = tb->my;
2269                 by1 = tb->cy;
2270                 bx2 = tb->mx;
2271                 bx1 = tb->cx;
2272         }
2273
2274         /* String on these lines are not really selected */  
2275         if (tb->lines_list[by1][bx1] == '\0' && by1 < tb->cy) by1++;
2276         if (bx2 == 0 && tb->cy < by2) by2--;
2277
2278
2279         /* Set/Reset flag of each line */
2280         for (y = by1; y <= by2; y++)
2281         {
2282                 int wid = 0;
2283
2284                 if (!autopick_new_entry(entry, tb->lines_list[y])) continue;
2285
2286                 string_free(tb->lines_list[y]);
2287
2288                 if (!fixed)
2289                 {
2290                         /* Add? or Remove? */
2291                         if (!(entry->action & flg)) add = TRUE;
2292                         else add = FALSE;
2293
2294                         /* No more change */
2295                         fixed = TRUE;
2296                 }
2297
2298                 /* Count number of letter (by negative number) */
2299                 if (entry->action & DONT_AUTOPICK) wid--;
2300                 else if (entry->action & DO_AUTODESTROY) wid--;
2301                 else if (entry->action & DO_QUERY_AUTOPICK) wid--;
2302                 if (!(entry->action & DO_DISPLAY)) wid--;
2303
2304                 /* Set/Reset the flag */
2305                 if (flg != DO_DISPLAY)
2306                 {
2307                         entry->action &= ~(DO_AUTOPICK | DONT_AUTOPICK | DO_AUTODESTROY | DO_QUERY_AUTOPICK);
2308                         if (add) entry->action |= flg;
2309                         else entry->action |= DO_AUTOPICK;
2310                 }
2311                 else
2312                 {
2313                         entry->action &= ~(DO_DISPLAY);
2314                         if (add) entry->action |= flg;
2315                 }
2316
2317                 /* Correct cursor location */
2318                 if (tb->cy == y)
2319                 {
2320                         if (entry->action & DONT_AUTOPICK) wid++;
2321                         else if (entry->action & DO_AUTODESTROY) wid++;
2322                         else if (entry->action & DO_QUERY_AUTOPICK) wid++;
2323                         if (!(entry->action & DO_DISPLAY)) wid++;
2324
2325                         if (wid > 0) tb->cx++;
2326                         if (wid < 0 && tb->cx > 0) tb->cx--;
2327                 }
2328                         
2329                 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
2330                         
2331                 /* Now dirty */
2332                 tb->dirty_flags |= DIRTY_ALL;
2333         }
2334 }
2335
2336 /*
2337  * Delete or insert string
2338  */
2339 static void add_keyword(text_body_type *tb, int flg)
2340 {
2341         autopick_type an_entry, *entry = &an_entry;
2342
2343         if (!autopick_new_entry(entry, tb->lines_list[tb->cy]))
2344                 return;
2345
2346         /* There is the flag already */
2347         if (IS_FLG(flg))
2348         {
2349                 /* Free memory for the entry */
2350                 autopick_free_entry(entry);
2351
2352                 return;
2353         }
2354
2355         string_free(tb->lines_list[tb->cy]);
2356
2357         /* Remove all noun flag */
2358         if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
2359         {
2360                 int i;
2361                 for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
2362                         REM_FLG(i);
2363         }
2364
2365         ADD_FLG(flg);
2366
2367         tb->lines_list[tb->cy] = autopick_line_from_entry_kill(entry);
2368
2369         /* Now dirty */
2370         tb->dirty_line = tb->cy;
2371 }
2372
2373
2374 /*
2375  * Insert return code and split the line
2376  */
2377 static bool insert_return_code(cptr *lines_list, int cx, int cy)
2378 {
2379         char buf[MAX_LINELEN];
2380         int i, j, k;
2381
2382         for (k = 0; lines_list[k]; k++)
2383                 /* count number of lines */ ;
2384
2385         if (k >= MAX_LINES - 2) return FALSE;
2386         k--;
2387
2388         /* Move down lines */
2389         for (; cy < k; k--)
2390                 lines_list[k+1] = lines_list[k];
2391
2392         /* Split current line */
2393         for (i = j = 0; lines_list[cy][i] && i < cx; i++)
2394         {
2395 #ifdef JP
2396                 if (iskanji(lines_list[cy][i]))
2397                         buf[j++] = lines_list[cy][i++];
2398 #endif
2399                 buf[j++] = lines_list[cy][i];
2400         }
2401         buf[j] = '\0';
2402         lines_list[cy+1] = string_make(&lines_list[cy][i]);
2403         string_free(lines_list[cy]);
2404         lines_list[cy] = string_make(buf);
2405         return TRUE;
2406 }
2407
2408
2409 /*
2410  * Get auto-picker entry from o_ptr.
2411  */
2412 void autopick_entry_from_object(autopick_type *entry, object_type *o_ptr)
2413 {
2414         char o_name[MAX_NLEN];
2415         object_desc(o_name, o_ptr, FALSE, 0);
2416
2417         entry->name = string_make(o_name);
2418         entry->insc = string_make(quark_str(o_ptr->inscription));
2419         entry->action = DO_AUTOPICK | DO_DISPLAY;
2420         entry->flag[0] = entry->flag[1] = 0L;
2421         entry->dice = 0;
2422
2423         if (!object_aware_p(o_ptr))
2424                 ADD_FLG(FLG_UNAWARE);
2425         if (object_value(o_ptr) <= 0)
2426                 ADD_FLG(FLG_WORTHLESS);
2427
2428         if (object_known_p(o_ptr))
2429         {
2430                 if (o_ptr->name2)
2431                         ADD_FLG(FLG_EGO);
2432                 else if (o_ptr->name1 || o_ptr->art_name)
2433                         ADD_FLG(FLG_ARTIFACT);
2434         }
2435
2436         switch(o_ptr->tval)
2437         {
2438                 object_kind *k_ptr; 
2439         case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_DIGGING:
2440                 k_ptr = &k_info[o_ptr->k_idx];
2441                 if ((o_ptr->dd != k_ptr->dd) || (o_ptr->ds != k_ptr->ds))
2442                         ADD_FLG(FLG_BOOSTED);
2443         }
2444
2445         if (o_ptr->tval == TV_CORPSE && object_is_shoukinkubi(o_ptr))
2446         {
2447                 REM_FLG(FLG_WORTHLESS);
2448                 ADD_FLG(FLG_WANTED);
2449         }
2450
2451         if ((o_ptr->tval == TV_CORPSE || o_ptr->tval == TV_STATUE)
2452             && (r_info[o_ptr->pval].flags1 & RF1_UNIQUE))
2453         {
2454                 REM_FLG(FLG_WORTHLESS);
2455                 ADD_FLG(FLG_UNIQUE);
2456         }
2457
2458         if (o_ptr->tval == TV_CORPSE && strchr("pht", r_info[o_ptr->pval].d_char))
2459         {
2460                 REM_FLG(FLG_WORTHLESS);
2461                 ADD_FLG(FLG_HUMAN);
2462         }
2463
2464         if (o_ptr->tval >= TV_LIFE_BOOK &&
2465             !check_book_realm(o_ptr->tval, o_ptr->sval))
2466                 ADD_FLG(FLG_UNREADABLE);
2467
2468         if (REALM1_BOOK == o_ptr->tval &&
2469             p_ptr->pclass != CLASS_SORCERER &&
2470             p_ptr->pclass != CLASS_RED_MAGE)
2471                 ADD_FLG(FLG_REALM1);
2472
2473         if (REALM2_BOOK == o_ptr->tval &&
2474             p_ptr->pclass != CLASS_SORCERER &&
2475             p_ptr->pclass != CLASS_RED_MAGE)
2476                 ADD_FLG(FLG_REALM2);
2477
2478         if (o_ptr->tval >= TV_LIFE_BOOK && 0 == o_ptr->sval)
2479                 ADD_FLG(FLG_FIRST);
2480         if (o_ptr->tval >= TV_LIFE_BOOK && 1 == o_ptr->sval)
2481                 ADD_FLG(FLG_SECOND);
2482         if (o_ptr->tval >= TV_LIFE_BOOK && 2 == o_ptr->sval)
2483                 ADD_FLG(FLG_THIRD);
2484         if (o_ptr->tval >= TV_LIFE_BOOK && 3 == o_ptr->sval)
2485                 ADD_FLG(FLG_FOURTH);
2486
2487         if (o_ptr->tval == TV_SHOT || o_ptr->tval == TV_BOLT
2488                  || o_ptr->tval == TV_ARROW)
2489                 ADD_FLG(FLG_MISSILES);
2490         else if (o_ptr->tval == TV_SCROLL || o_ptr->tval == TV_STAFF
2491                  || o_ptr->tval == TV_WAND || o_ptr->tval == TV_ROD)
2492                 ADD_FLG(FLG_DEVICES);
2493         else if (o_ptr->tval == TV_LITE)
2494                 ADD_FLG(FLG_LIGHTS);
2495         else if (o_ptr->tval == TV_SKELETON || o_ptr->tval == TV_BOTTLE
2496                  || o_ptr->tval == TV_JUNK || o_ptr->tval == TV_STATUE)
2497                 ADD_FLG(FLG_JUNKS);
2498         else if (o_ptr->tval >= TV_LIFE_BOOK)
2499                 ADD_FLG(FLG_SPELLBOOKS);
2500         else if (is_favorite(o_ptr, FALSE))
2501                 ADD_FLG(FLG_FAVORITE);
2502         else if (o_ptr->tval == TV_POLEARM || o_ptr->tval == TV_SWORD
2503                  || o_ptr->tval == TV_DIGGING || o_ptr->tval == TV_HAFTED)
2504                 ADD_FLG(FLG_WEAPONS);
2505         else if (o_ptr->tval == TV_SHIELD)
2506                 ADD_FLG(FLG_SHIELDS);
2507         else if (o_ptr->tval == TV_BOW)
2508                 ADD_FLG(FLG_BOWS);
2509         else if (o_ptr->tval == TV_RING)
2510                 ADD_FLG(FLG_RINGS);
2511         else if (o_ptr->tval == TV_AMULET)
2512                 ADD_FLG(FLG_AMULETS);
2513         else if (o_ptr->tval == TV_DRAG_ARMOR || o_ptr->tval == TV_HARD_ARMOR ||
2514                  o_ptr->tval == TV_SOFT_ARMOR)
2515                 ADD_FLG(FLG_SUITS);
2516         else if (o_ptr->tval == TV_CLOAK)
2517                 ADD_FLG(FLG_CLOAKS);
2518         else if (o_ptr->tval == TV_HELM)
2519                 ADD_FLG(FLG_HELMS);
2520         else if (o_ptr->tval == TV_GLOVES)
2521                 ADD_FLG(FLG_GLOVES);
2522         else if (o_ptr->tval == TV_BOOTS)
2523                 ADD_FLG(FLG_BOOTS);
2524
2525         return;
2526 }
2527
2528
2529 /*
2530  * Choose an item and get auto-picker entry from it.
2531  */
2532 static object_type *choose_object(cptr q, cptr s)
2533 {
2534         int item;
2535
2536         if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EQUIP))) return NULL;
2537
2538         /* Get the item (in the pack) */
2539         if (item >= 0) return &inventory[item];
2540
2541         /* Get the item (on the floor) */
2542         else return &o_list[0 - item];
2543 }
2544
2545
2546 /*
2547  * Choose an item and get auto-picker entry from it.
2548  */
2549 static bool entry_from_choosed_object(autopick_type *entry)
2550 {
2551         object_type *o_ptr;
2552         cptr q, s;
2553
2554         /* Get an item */
2555 #ifdef JP
2556         q = "¤É¤Î¥¢¥¤¥Æ¥à¤òÅÐÏ¿¤·¤Þ¤¹¤«? ";
2557         s = "¥¢¥¤¥Æ¥à¤ò»ý¤Ã¤Æ¤¤¤Ê¤¤¡£";
2558 #else
2559         q = "Enter which item? ";
2560         s = "You have nothing to enter.";
2561 #endif
2562         o_ptr = choose_object(q, s);
2563         if (!o_ptr) return FALSE;
2564
2565         autopick_entry_from_object(entry, o_ptr);
2566         return TRUE;
2567 }
2568
2569
2570 /*
2571  * Choose an item for search
2572  */
2573 static byte get_object_for_search(object_type **o_handle, cptr *search_strp)
2574 {
2575         char buf[MAX_NLEN+20];
2576         object_type *o_ptr;
2577         cptr q, s;
2578
2579         /* Get an item */
2580 #ifdef JP
2581         q = "¤É¤Î¥¢¥¤¥Æ¥à¤ò¸¡º÷¤·¤Þ¤¹¤«? ";
2582         s = "¥¢¥¤¥Æ¥à¤ò»ý¤Ã¤Æ¤¤¤Ê¤¤¡£";
2583 #else
2584         q = "Enter which item? ";
2585         s = "You have nothing to enter.";
2586 #endif
2587         o_ptr = choose_object(q, s);
2588         if (!o_ptr) return 0;
2589
2590         *o_handle = o_ptr;
2591
2592         string_free(*search_strp);
2593         object_desc(buf, *o_handle, FALSE, 3);
2594         *search_strp = string_make(format("<%s>", buf));
2595         return 1;
2596 }
2597
2598
2599 /*
2600  * Prepare for search by destroyed object
2601  */
2602 static byte get_destroyed_object_for_search(object_type **o_handle, cptr *search_strp)
2603 {
2604         char buf[MAX_NLEN+20];
2605
2606         if (!autopick_last_destroyed_object.k_idx) return 0;
2607
2608         *o_handle = &autopick_last_destroyed_object;
2609
2610         string_free(*search_strp);
2611         object_desc(buf, *o_handle, FALSE, 3);
2612         *search_strp = string_make(format("<%s>", buf));
2613         return 1;
2614 }
2615
2616
2617 /*
2618  * Choose an item or string for search
2619  */
2620 static byte get_string_for_search(object_type **o_handle, cptr *search_strp)
2621 {
2622         int pos = 0;
2623         char buf[MAX_NLEN+20];
2624
2625 #ifdef JP
2626         int k_flag[MAX_NLEN+20];
2627         char prompt[] = "¸¡º÷(^I:»ý¤Áʪ ^L:Ç˲õ¤µ¤ì¤¿Êª): ";
2628 #else
2629         char prompt[] = "Search key(^I:inven ^L:destroyed): ";
2630 #endif
2631         int col = sizeof(prompt) - 1;
2632
2633         if (*search_strp) strcpy(buf, *search_strp);
2634         else buf[0] = '\0';
2635
2636         /* Display prompt */
2637         prt(prompt, 0, 0);
2638
2639         /* Display the default answer */
2640         Term_erase(col, 0, 255);
2641         Term_putstr(col, 0, -1, TERM_YELLOW, buf);
2642
2643         /* Process input */
2644         while (1)
2645         {
2646                 bool back = FALSE;
2647                 int i;
2648
2649                 /* Place cursor */
2650                 Term_gotoxy(col + pos, 0);
2651
2652                 /* Get a key */
2653                 i = inkey();
2654
2655                 /* HACK -- ignore macro defined on ASCII keys */
2656                 if (strlen(inkey_macro_trigger_string) == 1)
2657                         i = inkey_macro_trigger_string[0];
2658
2659
2660                 /* Analyze the key */
2661                 switch (i)
2662                 {
2663                 case ESCAPE:
2664                         return 0;
2665
2666                 case KTRL('r'):
2667                         back = TRUE;
2668                         /* Fall through */
2669
2670                 case '\n':
2671                 case '\r':
2672                 case KTRL('s'):
2673                         if (!pos && *o_handle) return (back ? -1 : 1);
2674                         string_free(*search_strp);
2675                         *search_strp = string_make(buf);
2676                         *o_handle = NULL;
2677                         return (back ? -1 : 1);
2678
2679                 case KTRL('i'):
2680                         /* Get an item */
2681                         return get_object_for_search(o_handle, search_strp);
2682
2683                 case KTRL('l'):
2684                         /* Prepare string for destroyed object if there is one. */
2685                         if (get_destroyed_object_for_search(o_handle, search_strp))
2686                                 return 1;
2687                         break;
2688
2689                 case 0x7F:
2690                 case '\010':
2691 #ifdef JP
2692                         if (pos > 0)
2693                         {
2694                                 pos--;
2695                                 if (k_flag[pos]) pos--;
2696                         }
2697 #else
2698                         if (pos > 0) pos--;
2699 #endif
2700                         break;
2701
2702                 default:
2703 #ifdef JP
2704                         if (iskanji(i))
2705                         {
2706                                 int next;
2707
2708                                 inkey_base = TRUE;
2709                                 next = inkey ();
2710                                 if (pos + 1 < MAX_NLEN)
2711                                 {
2712                                         buf[pos++] = i;
2713                                         buf[pos] = next;
2714                                         k_flag[pos++] = 1;
2715                                 }
2716                                 else bell();
2717                         }
2718                         else if (pos < MAX_NLEN && isprint(i))
2719                         {
2720                                 buf[pos] = i;
2721                                 k_flag[pos++] = 0;
2722                         }
2723                         else bell();
2724 #else
2725                         if (pos < MAX_NLEN && isprint(i)) buf[pos++] = i;
2726                         else bell();
2727 #endif
2728                         break;
2729                 }
2730
2731                 /* Terminate */
2732                 buf[pos] = '\0';
2733
2734                 /* Update the entry */
2735                 Term_erase(col, 0, 255);
2736                 Term_putstr(col, 0, -1, TERM_WHITE, buf);
2737         }
2738
2739         /* Never reached */
2740 }
2741
2742
2743 /*
2744  * Search next line matches for o_ptr
2745  */
2746 static bool search_for_object(cptr *lines_list, object_type *o_ptr, int *cxp, int *cyp, bool forward)
2747 {
2748         int i;
2749         autopick_type an_entry, *entry = &an_entry;
2750         char o_name[MAX_NLEN];
2751
2752         object_desc(o_name, o_ptr, FALSE, 3);
2753
2754         /* Force to be lower case string */
2755         for (i = 0; o_name[i]; i++)
2756         {
2757 #ifdef JP
2758                 if (iskanji(o_name[i]))
2759                         i++;
2760                 else
2761 #endif
2762                 if (isupper(o_name[i]))
2763                         o_name[i] = tolower(o_name[i]);
2764         }
2765         
2766         i = *cyp;
2767
2768         while (1)
2769         {
2770                 if (forward)
2771                 {
2772                         if (!lines_list[++i]) break;
2773                 }
2774                 else
2775                 {
2776                         if (--i < 0) break;
2777                 }
2778
2779                 if (!autopick_new_entry(entry, lines_list[i])) continue;
2780
2781                 if (is_autopick_aux(o_ptr, entry, o_name))
2782                 {
2783                         *cxp = 0;
2784                         *cyp = i;
2785                         return TRUE;
2786                 }
2787         }
2788
2789         return FALSE;
2790 }
2791
2792
2793 /*
2794  * Search next line matches to the string
2795  */
2796 static bool search_for_string(cptr *lines_list, cptr search_str, int *cxp, int *cyp, bool forward)
2797 {
2798         int i = *cyp;
2799
2800         while (1)
2801         {
2802                 cptr pos;
2803
2804                 if (forward)
2805                 {
2806                         if (!lines_list[++i]) break;
2807                 }
2808                 else
2809                 {
2810                         if (--i < 0) break;
2811                 }
2812 #ifdef JP
2813                 pos = strstr_j(lines_list[i], search_str);
2814 #else
2815                 pos = strstr(lines_list[i], search_str);
2816 #endif
2817                 if (pos)
2818                 {
2819                         *cxp = (int)(pos - lines_list[i]);
2820                         *cyp = i;
2821                         return TRUE;
2822                 }
2823         }
2824
2825         return FALSE;
2826 }
2827
2828
2829
2830
2831 /*
2832  * Editor command id's
2833  */
2834 #define EC_QUIT                1 
2835 #define EC_REVERT              2 
2836 #define EC_HELP                3 
2837 #define EC_RETURN              4        
2838 #define EC_LEFT                5 
2839 #define EC_DOWN                6 
2840 #define EC_UP                  7 
2841 #define EC_RIGHT               8 
2842 #define EC_BOL                 9 
2843 #define EC_EOL                 10
2844 #define EC_PGUP                11
2845 #define EC_PGDOWN              12
2846 #define EC_TOP                 13
2847 #define EC_BOTTOM              14
2848 #define EC_CUT                 15
2849 #define EC_COPY                16
2850 #define EC_PASTE               17
2851 #define EC_BLOCK               18
2852 #define EC_KILL_LINE           19
2853 #define EC_DELETE_CHAR         20
2854 #define EC_BACKSPACE           21
2855 #define EC_SEARCH_STR          22
2856 #define EC_SEARCH_FORW         23
2857 #define EC_SEARCH_BACK         24
2858 #define EC_SEARCH_OBJ          25
2859 #define EC_SEARCH_DESTROYED    26
2860 #define EC_INSERT_OBJECT       27
2861 #define EC_INSERT_DESTROYED    28
2862 #define EC_INSERT_BLOCK        29
2863 #define EC_INSERT_MACRO        30
2864 #define EC_INSERT_KEYMAP       31
2865 #define EC_CL_AUTOPICK         32
2866 #define EC_CL_DESTROY          33
2867 #define EC_CL_LEAVE            34
2868 #define EC_CL_QUERY            35
2869 #define EC_CL_NO_DISP          36
2870 #define EC_OK_COLLECTING       37
2871 #define EC_IK_UNAWARE          38
2872 #define EC_IK_UNIDENTIFIED     39
2873 #define EC_IK_IDENTIFIED       40
2874 #define EC_IK_STAR_IDENTIFIED  41
2875 #define EC_OK_BOOSTED          42
2876 #define EC_OK_MORE_THAN        43
2877 #define EC_OK_MORE_BONUS       44
2878 #define EC_OK_WORTHLESS        45
2879 #define EC_OK_ARTIFACT         46
2880 #define EC_OK_EGO              47
2881 #define EC_OK_NAMELESS         48
2882 #define EC_OK_WANTED           49
2883 #define EC_OK_UNIQUE           50
2884 #define EC_OK_HUMAN            51
2885 #define EC_OK_UNREADABLE       52
2886 #define EC_OK_REALM1           53
2887 #define EC_OK_REALM2           54
2888 #define EC_OK_FIRST            55
2889 #define EC_OK_SECOND           56
2890 #define EC_OK_THIRD            57
2891 #define EC_OK_FOURTH           58
2892 #define EC_KK_WEAPONS          59
2893 #define EC_KK_FAVORITE         60
2894 #define EC_KK_ARMORS           61
2895 #define EC_KK_MISSILES         62
2896 #define EC_KK_DEVICES          63
2897 #define EC_KK_LIGHTS           64
2898 #define EC_KK_JUNKS            65
2899 #define EC_KK_SPELLBOOKS       66
2900 #define EC_KK_SHIELDS          67
2901 #define EC_KK_BOWS             68
2902 #define EC_KK_RINGS            69
2903 #define EC_KK_AMULETS          70
2904 #define EC_KK_SUITS            71
2905 #define EC_KK_CLOAKS           72
2906 #define EC_KK_HELMS            73
2907 #define EC_KK_GLOVES           74
2908 #define EC_KK_BOOTS            75
2909
2910
2911 /* Manu names */
2912 #ifdef JP
2913
2914 #define MN_QUIT "¥»¡¼¥Ö¤·¤Æ½ªÎ»" 
2915 #define MN_REVERT "Á´¤Æ¤ÎÊѹ¹¤òÇË´þ" 
2916 #define MN_HELP "¥Ø¥ë¥×" 
2917
2918 #define MN_MOVE "¥«¡¼¥½¥ë°ÜÆ°" 
2919 #define MN_LEFT "º¸" 
2920 #define MN_DOWN "²¼" 
2921 #define MN_UP "¾å" 
2922 #define MN_RIGHT "±¦" 
2923 #define MN_BOL "¹Ô¤ÎÀèƬ" 
2924 #define MN_EOL "¹Ô¤Î½ªÃ¼" 
2925 #define MN_PGUP "¾å¤Î¥Ú¡¼¥¸" 
2926 #define MN_PGDOWN "²¼¤Î¥Ú¡¼¥¸" 
2927 #define MN_TOP "1¹ÔÌܤذÜÆ°" 
2928 #define MN_BOTTOM "ºÇ²¼¹Ô¤Ø°ÜÆ°" 
2929
2930 #define MN_EDIT "ÊÔ½¸" 
2931 #define MN_CUT "¥«¥Ã¥È" 
2932 #define MN_COPY "¥³¥Ô¡¼" 
2933 #define MN_PASTE "¥Ú¡¼¥¹¥È" 
2934 #define MN_BLOCK "ÁªÂòÈϰϤλØÄê" 
2935 #define MN_KILL_LINE "¹Ô¤Î»Ä¤ê¤òºï½ü" 
2936 #define MN_DELETE_CHAR "1ʸ»úºï½ü" 
2937 #define MN_BACKSPACE "¥Ð¥Ã¥¯¥¹¥Ú¡¼¥¹" 
2938 #define MN_RETURN "²þ¹Ô" 
2939 #define MN_RETURN "²þ¹Ô" 
2940
2941 #define MN_SEARCH "¸¡º÷" 
2942 #define MN_SEARCH_STR "ʸ»úÎó¤Ç¸¡º÷" 
2943 #define MN_SEARCH_FORW "Á°Êý¤ØºÆ¸¡º÷" 
2944 #define MN_SEARCH_BACK "¸åÊý¤ØºÆ¸¡º÷" 
2945 #define MN_SEARCH_OBJ "¥¢¥¤¥Æ¥à¤òÁªÂò¤·¤Æ¸¡º÷" 
2946 #define MN_SEARCH_DESTROYED "¼«Æ°Ç˲õ¤µ¤ì¤¿¥¢¥¤¥Æ¥à¤Ç¸¡º÷" 
2947
2948 #define MN_INSERT "¿§¡¹ÁÞÆþ" 
2949 #define MN_INSERT_OBJECT "ÁªÂò¤·¤¿¥¢¥¤¥Æ¥à¤Î̾Á°¤òÁÞÆþ" 
2950 #define MN_INSERT_DESTROYED "¼«Æ°Ç˲õ¤µ¤ì¤¿¥¢¥¤¥Æ¥à¤Î̾Á°¤òÁÞÆþ" 
2951 #define MN_INSERT_BLOCK "¾ò·ïʬ´ô¥Ö¥í¥Ã¥¯¤ÎÎã¤òÁÞÆþ" 
2952 #define MN_INSERT_MACRO "¥Þ¥¯¥íÄêµÁ¤òÁÞÆþ" 
2953 #define MN_INSERT_KEYMAP "¥­¡¼¥Þ¥Ã¥×ÄêµÁ¤òÁÞÆþ" 
2954
2955 #define MN_COMMAND_LETTER "½¦¤¤/Ç˲õ/ÊüÃÖ¤ÎÁªÂò" 
2956 #define MN_CL_AUTOPICK "¡Ö ¡× (¼«Æ°½¦¤¤)" 
2957 #define MN_CL_DESTROY "¡Ö!¡× (¼«Æ°Ç˲õ)" 
2958 #define MN_CL_LEAVE "¡Ö~¡× (ÊüÃÖ)" 
2959 #define MN_CL_QUERY "¡Ö;¡× (³Îǧ¤·¤Æ½¦¤¦)" 
2960 #define MN_CL_NO_DISP "¡Ö(¡× (¥Þ¥Ã¥×¥³¥Þ¥ó¥É¤Çɽ¼¨¤·¤Ê¤¤)" 
2961
2962 #define MN_ADJECTIVE_GEN "·ÁÍÆ»ì(°ìÈÌ)¤ÎÁªÂò" 
2963
2964 #define MN_ADJECTIVE_SPECIAL "·ÁÍÆ»ì(Æüì)¤ÎÁªÂò" 
2965 #define MN_BOOSTED "¥À¥¤¥¹Ìܤΰ㤦 (Éð´ï)" 
2966 #define MN_MORE_THAN "¥À¥¤¥¹ÌÜ # °Ê¾å¤Î (Éð´ï)" 
2967 #define MN_MORE_BONUS "½¤ÀµÃÍ # °Ê¾å¤Î (»ØÎØÅù)" 
2968 #define MN_ARTIFACT "¥¢¡¼¥Æ¥£¥Õ¥¡¥¯¥È (ÁõÈ÷)" 
2969 #define MN_EGO "¥¨¥´ (ÁõÈ÷)" 
2970 #define MN_NAMELESS "̵ÌäΠ(ÁõÈ÷)" 
2971 #define MN_WANTED "¾Þ¶â¼ó¤Î (»àÂÎ)" 
2972 #define MN_UNIQUE "¥æ¥Ë¡¼¥¯¡¦¥â¥ó¥¹¥¿¡¼¤Î (»àÂÎ)" 
2973 #define MN_HUMAN "¿Í´Ö¤Î (»àÂÎ)" 
2974 #define MN_UNREADABLE "Æɤá¤Ê¤¤ (ËâË¡½ñ)" 
2975 #define MN_REALM1 "Âè°ìÎΰè¤Î (ËâË¡½ñ)" 
2976 #define MN_REALM2 "ÂèÆóÎΰè¤Î (ËâË¡½ñ)" 
2977 #define MN_FIRST "1ºýÌܤΠ(ËâË¡½ñ)" 
2978 #define MN_SECOND "2ºýÌܤΠ(ËâË¡½ñ)" 
2979 #define MN_THIRD "3ºýÌܤΠ(ËâË¡½ñ)" 
2980 #define MN_FOURTH "4ºýÌܤΠ(ËâË¡½ñ)" 
2981
2982 #define MN_NOUN "̾»ì¤ÎÁªÂò" 
2983
2984 #else
2985
2986 #define MN_QUIT "Save & Quit" 
2987 #define MN_REVERT "Revert all changes" 
2988 #define MN_HELP "Help" 
2989
2990 #define MN_MOVE "Move cursor" 
2991 #define MN_LEFT "Left" 
2992 #define MN_DOWN "Down" 
2993 #define MN_UP "Up" 
2994 #define MN_RIGHT "Right" 
2995 #define MN_BOL "Beggining of line" 
2996 #define MN_EOL "End of line" 
2997 #define MN_PGUP "Page up" 
2998 #define MN_PGDOWN "Page down" 
2999 #define MN_TOP "Top" 
3000 #define MN_BOTTOM "Bottom" 
3001
3002 #define MN_EDIT "Edit" 
3003 #define MN_CUT "Cut" 
3004 #define MN_COPY "Copy" 
3005 #define MN_PASTE "Paste" 
3006 #define MN_BLOCK "Select block" 
3007 #define MN_KILL_LINE "Kill rest of line" 
3008 #define MN_DELETE_CHAR "Delete character" 
3009 #define MN_BACKSPACE "Backspace" 
3010 #define MN_RETURN "Return" 
3011 #define MN_RETURN "Return" 
3012
3013 #define MN_SEARCH "Search" 
3014 #define MN_SEARCH_STR "Search by string" 
3015 #define MN_SEARCH_FORW "Search forward" 
3016 #define MN_SEARCH_BACK "Search backward" 
3017 #define MN_SEARCH_OBJ "Search by inventory object" 
3018 #define MN_SEARCH_DESTROYED "Search by destroyed object" 
3019
3020 #define MN_INSERT "Insert..." 
3021 #define MN_INSERT_OBJECT "Insert name of choosen object" 
3022 #define MN_INSERT_DESTROYED "Insert name of destroyed object" 
3023 #define MN_INSERT_BLOCK "Insert conditional block" 
3024 #define MN_INSERT_MACRO "Insert a macro definition" 
3025 #define MN_INSERT_KEYMAP "Insert a keymap definition" 
3026
3027 #define MN_COMMAND_LETTER "Command letter" 
3028 #define MN_CL_AUTOPICK "' ' (Auto pick)" 
3029 #define MN_CL_DESTROY "'!' (Auto destroy)" 
3030 #define MN_CL_LEAVE "'~' (Leave it on the floor)" 
3031 #define MN_CL_QUERY "';' (Query to pick up)" 
3032 #define MN_CL_NO_DISP "'(' (No display on the large map)" 
3033
3034 #define MN_ADJECTIVE_GEN "Adjective (general)" 
3035
3036 #define MN_ADJECTIVE_SPECIAL "Adjective (special)" 
3037 #define MN_BOOSTED "dice boosted (weapons)" 
3038 #define MN_MORE_THAN "more than # dice (weapons)" 
3039 #define MN_MORE_BONUS "more bonus than # (rings etc.)" 
3040 #define MN_ARTIFACT "artifact (equipments)" 
3041 #define MN_EGO "ego (equipments)" 
3042 #define MN_NAMELESS "nameless (equipments)" 
3043 #define MN_WANTED "wanted (corpse)" 
3044 #define MN_UNIQUE "unique (corpse)" 
3045 #define MN_HUMAN "human (corpse)" 
3046 #define MN_UNREADABLE "unreadable (spellbooks)" 
3047 #define MN_REALM1 "realm1 (spellbooks)" 
3048 #define MN_REALM2 "realm2 (spellbooks)" 
3049 #define MN_FIRST "first (spellbooks)" 
3050 #define MN_SECOND "second (spellbooks)" 
3051 #define MN_THIRD "third (spellbooks)" 
3052 #define MN_FOURTH "fourth (spellbooks)" 
3053
3054 #define MN_NOUN "Keywords (noun)" 
3055
3056 #endif
3057
3058
3059 typedef struct {
3060         cptr name;
3061         int level;
3062         int key;
3063         int com_id;
3064 } command_menu_type;
3065
3066
3067 command_menu_type menu_data[] =
3068 {
3069         {MN_QUIT, 0, KTRL('q'), EC_QUIT}, 
3070         {MN_REVERT, 0, KTRL('z'), EC_REVERT},
3071         {MN_HELP, 0, -1, EC_HELP},
3072
3073         {MN_MOVE, 0, -1, -1},
3074         {MN_LEFT, 1, KTRL('b'), EC_LEFT},
3075         {MN_DOWN, 1, KTRL('n'), EC_DOWN},
3076         {MN_UP, 1, KTRL('p'), EC_UP},
3077         {MN_RIGHT, 1, KTRL('f'), EC_RIGHT},
3078         {MN_BOL, 1, KTRL('a'), EC_BOL},
3079         {MN_EOL, 1, KTRL('e'), EC_EOL},
3080         {MN_PGUP, 1, KTRL('o'), EC_PGUP},
3081         {MN_PGDOWN, 1, KTRL('l'), EC_PGDOWN},
3082         {MN_TOP, 1, KTRL('y'), EC_TOP},
3083         {MN_BOTTOM, 1, KTRL('u'), EC_BOTTOM},
3084
3085         {MN_EDIT, 0, -1, -1},
3086         {MN_CUT, 1, KTRL('x'), EC_CUT},
3087         {MN_COPY, 1, KTRL('c'), EC_COPY},
3088         {MN_PASTE, 1, KTRL('v'), EC_PASTE},
3089         {MN_BLOCK, 1, KTRL('g'), EC_BLOCK},
3090         {MN_KILL_LINE, 1, KTRL('k'), EC_KILL_LINE},
3091         {MN_DELETE_CHAR, 1, KTRL('d'), EC_DELETE_CHAR},
3092         {MN_BACKSPACE, 1, KTRL('h'), EC_BACKSPACE},
3093         {MN_RETURN, 1, KTRL('j'), EC_RETURN},
3094         {MN_RETURN, 1, KTRL('m'), EC_RETURN},
3095
3096         {MN_SEARCH, 0, -1, -1},
3097         {MN_SEARCH_STR, 1, KTRL('s'), EC_SEARCH_STR},
3098         {MN_SEARCH_FORW, 1, -1, EC_SEARCH_FORW},
3099         {MN_SEARCH_BACK, 1, KTRL('r'), EC_SEARCH_BACK},
3100         {MN_SEARCH_OBJ, 1, -1, EC_SEARCH_OBJ},
3101         {MN_SEARCH_DESTROYED, 1, -1, EC_SEARCH_DESTROYED},
3102
3103         {MN_INSERT, 0, -1, -1},
3104         {MN_INSERT_OBJECT, 1, KTRL('i'), EC_INSERT_OBJECT},
3105         {MN_INSERT_DESTROYED, 1, -1, EC_INSERT_DESTROYED},
3106         {MN_INSERT_BLOCK, 1, -1, EC_INSERT_BLOCK},
3107         {MN_INSERT_MACRO, 1, -1, EC_INSERT_MACRO},
3108         {MN_INSERT_KEYMAP, 1, -1, EC_INSERT_KEYMAP},
3109
3110         {MN_COMMAND_LETTER, 0, -1, -1},
3111         {MN_CL_AUTOPICK, 1, -1, EC_CL_AUTOPICK},
3112         {MN_CL_DESTROY, 1, -1, EC_CL_DESTROY},
3113         {MN_CL_LEAVE, 1, -1, EC_CL_LEAVE},
3114         {MN_CL_QUERY, 1, -1, EC_CL_QUERY},
3115         {MN_CL_NO_DISP, 1, -1, EC_CL_NO_DISP},
3116
3117         {MN_ADJECTIVE_GEN, 0, -1, -1},
3118         {KEY_UNAWARE, 1, -1, EC_IK_UNAWARE},
3119         {KEY_UNIDENTIFIED, 1, -1, EC_IK_UNIDENTIFIED},
3120         {KEY_IDENTIFIED, 1, -1, EC_IK_IDENTIFIED},
3121         {KEY_STAR_IDENTIFIED, 1, -1, EC_IK_STAR_IDENTIFIED},
3122         {KEY_COLLECTING, 1, -1, EC_OK_COLLECTING},
3123         {KEY_WORTHLESS, 1, -1, EC_OK_WORTHLESS},
3124
3125         {MN_ADJECTIVE_SPECIAL, 0, -1, -1},
3126         {MN_BOOSTED, 1, -1, EC_OK_BOOSTED},
3127         {MN_MORE_THAN, 1, -1, EC_OK_MORE_THAN},
3128         {MN_MORE_BONUS, 1, -1, EC_OK_MORE_BONUS},
3129         {MN_ARTIFACT, 1, -1, EC_OK_ARTIFACT},
3130         {MN_EGO, 1, -1, EC_OK_EGO},
3131         {MN_NAMELESS, 1, -1, EC_OK_NAMELESS},
3132         {MN_WANTED, 1, -1, EC_OK_WANTED},
3133         {MN_UNIQUE, 1, -1, EC_OK_UNIQUE},
3134         {MN_HUMAN, 1, -1, EC_OK_HUMAN},
3135         {MN_UNREADABLE, 1, -1, EC_OK_UNREADABLE},
3136         {MN_REALM1, 1, -1, EC_OK_REALM1},
3137         {MN_REALM2, 1, -1, EC_OK_REALM2},
3138         {MN_FIRST, 1, -1, EC_OK_FIRST},
3139         {MN_SECOND, 1, -1, EC_OK_SECOND},
3140         {MN_THIRD, 1, -1, EC_OK_THIRD},
3141         {MN_FOURTH, 1, -1, EC_OK_FOURTH},
3142
3143         {MN_NOUN, 0, -1, -1},
3144         {KEY_WEAPONS, 1, -1, EC_KK_WEAPONS},
3145         {KEY_FAVORITE, 1, -1, EC_KK_FAVORITE},
3146         {KEY_ARMORS, 1, -1, EC_KK_ARMORS},
3147         {KEY_MISSILES, 1, -1, EC_KK_MISSILES},
3148         {KEY_DEVICES, 1, -1, EC_KK_DEVICES},
3149         {KEY_LIGHTS, 1, -1, EC_KK_LIGHTS},
3150         {KEY_JUNKS, 1, -1, EC_KK_JUNKS},
3151         {KEY_SPELLBOOKS, 1, -1, EC_KK_SPELLBOOKS},
3152         {KEY_SHIELDS, 1, -1, EC_KK_SHIELDS},
3153         {KEY_BOWS, 1, -1, EC_KK_BOWS},
3154         {KEY_RINGS, 1, -1, EC_KK_RINGS},
3155         {KEY_AMULETS, 1, -1, EC_KK_AMULETS},
3156         {KEY_SUITS, 1, -1, EC_KK_SUITS},
3157         {KEY_CLOAKS, 1, -1, EC_KK_CLOAKS},
3158         {KEY_HELMS, 1, -1, EC_KK_HELMS},
3159         {KEY_GLOVES, 1, -1, EC_KK_GLOVES},
3160         {KEY_BOOTS, 1, -1, EC_KK_BOOTS},
3161
3162         {NULL, -1, -1, 0}
3163 };
3164
3165
3166 /*
3167  * Find a command by 'key'.
3168  */
3169 static int get_com_id(char key)
3170 {
3171         int i;
3172
3173         for (i = 0; menu_data[i].name; i++)
3174         {
3175                 if (menu_data[i].key == key)
3176                 {
3177                         return menu_data[i].com_id;
3178                 }
3179         }
3180
3181         return 0;
3182 }
3183
3184
3185 /*
3186  * Display the menu, and get a command 
3187  */
3188 static int do_command_menu(int level, int start)
3189 {
3190         int i;
3191         int max_len = 0;
3192         int max_menu_wid;
3193         int col0 = 5 + level*7;
3194         int row0 = 1 + level*3;
3195         byte menu_key = 0;
3196         int menu_id_list[26];
3197         bool redraw = TRUE;
3198         char linestr[MAX_LINELEN];
3199
3200         /* Get max length */
3201         menu_key = 0;
3202         for (i = start; menu_data[i].level >= level; i++)
3203         {
3204                 int len;
3205
3206                 /* Ignore lower level sub menus */
3207                 if (menu_data[i].level > level) continue;
3208
3209                 len = strlen(menu_data[i].name);
3210                 if (len > max_len) max_len = len;
3211
3212                 menu_id_list[menu_key] = i;
3213                 menu_key++;
3214         }
3215
3216         while (menu_key < 26)
3217         {
3218                 menu_id_list[menu_key] = -1;
3219                 menu_key++;
3220         }
3221
3222         /* Extra space for displaying menu key and command key */
3223         max_menu_wid = max_len + 3 + 3;
3224
3225         /* Prepare box line */
3226         linestr[0] = '\0';
3227         strcat(linestr, "+");
3228         for (i = 0; i < max_menu_wid + 2; i++)
3229         {
3230                 strcat(linestr, "-");
3231         }
3232         strcat(linestr, "+");
3233
3234         while (1)
3235         {
3236                 int com_id;
3237                 char key;
3238                 int menu_id;
3239
3240                 if (redraw)
3241                 {
3242                         int row1 = row0 + 1;
3243
3244                         /* Draw top line */
3245                         Term_putstr(col0, row0, -1, TERM_WHITE, linestr);
3246
3247                         /* Draw menu items */
3248                         menu_key = 0;
3249                         for (i = start; menu_data[i].level >= level; i++)
3250                         {
3251                                 char com_key_str[3];
3252                                 cptr str;
3253
3254                                 /* Ignore lower level sub menus */
3255                                 if (menu_data[i].level > level) continue;
3256
3257                                 if (menu_data[i].com_id == -1)
3258                                 {
3259 #ifdef JP
3260                                         strcpy(com_key_str, "¢§");
3261 #else
3262                                         strcpy(com_key_str, ">");
3263 #endif
3264                                 }
3265                                 else if (menu_data[i].key != -1)
3266                                 {
3267                                         com_key_str[0] = '^';
3268                                         com_key_str[1] = menu_data[i].key + '@';
3269                                         com_key_str[2] = '\0';
3270                                 }
3271                                 else
3272                                 {
3273                                         com_key_str[0] = '\0';
3274                                 }
3275
3276                                 str = format("| %c) %-*s %2s | ", menu_key + 'a', max_len, menu_data[i].name, com_key_str);
3277
3278                                 Term_putstr(col0, row1++, -1, TERM_WHITE, str);
3279
3280                                 menu_key++;
3281                         }
3282
3283                         /* Draw bottom line */
3284                         Term_putstr(col0, row1, -1, TERM_WHITE, linestr);
3285
3286                         /* The menu was shown */
3287                         redraw = FALSE;
3288                 }
3289 #ifdef JP
3290                 prt(format("(a-%c) ¥³¥Þ¥ó¥É:", menu_key + 'a' - 1), 0, 0);
3291 #else
3292                 prt(format("(a-%c) Command:", menu_key + 'a' - 1), 0, 0);
3293 #endif
3294                 key = inkey();
3295
3296                 if (key == ESCAPE) return 0;
3297
3298                 if ('a' <= key && key <= 'z')
3299                 {
3300                         menu_id = menu_id_list[key - 'a'];
3301
3302                         if (menu_id >= 0)
3303                         {
3304                                 com_id = menu_data[menu_id].com_id;
3305
3306                                 if (com_id == -1)
3307                                 {
3308                                         com_id = do_command_menu(level + 1, menu_id + 1);
3309
3310                                         if (com_id) return com_id;
3311                                         else redraw = TRUE;
3312                                 }
3313                                 else if (com_id)
3314                                 {
3315                                         return com_id;
3316                                 }
3317                         }
3318                 }
3319
3320                 else
3321                 {
3322                         com_id = get_com_id(key);
3323                         if (com_id) return com_id;
3324                         else continue;
3325                 }
3326         }
3327 }
3328
3329
3330 static chain_str_type *new_chain_str(cptr str)
3331 {
3332         chain_str_type *chain;
3333
3334         size_t len = strlen(str);
3335
3336         chain = (chain_str_type *)ralloc(sizeof(chain_str_type) + len * sizeof(char));
3337
3338         strcpy(chain->s, str);
3339         chain->next = NULL;
3340
3341         return chain;
3342 }
3343
3344
3345 static void kill_yank_chain(text_body_type *tb)
3346 {
3347         chain_str_type *chain = tb->yank;
3348         tb->yank = NULL;
3349
3350         while (chain)
3351         {
3352                 chain_str_type *next = chain->next;
3353                 size_t len = strlen(chain->s);
3354
3355                 rnfree(chain, sizeof(chain_str_type) + len * sizeof(char));
3356
3357                 chain = next;
3358         }
3359 }
3360
3361
3362 static void add_str_to_yank(text_body_type *tb, cptr str)
3363 {
3364         chain_str_type *chain;
3365
3366         tb->yank_eol = FALSE;
3367
3368         if (NULL == tb->yank)
3369         {
3370                 tb->yank = new_chain_str(str);
3371                 return;
3372         }
3373
3374         chain = tb->yank;
3375
3376         while (1)
3377         {
3378                 if (!chain->next)
3379                 {
3380                         chain->next = new_chain_str(str);
3381                         return;
3382                 }
3383
3384                 /* Go to next */
3385                 chain = chain->next;
3386         }
3387 }
3388
3389
3390 #define DESCRIPT_HGT 3
3391
3392 /*
3393  * Draw text
3394  */
3395 static void draw_text_editor(text_body_type *tb)
3396 {
3397         int i;
3398         int by1 = -1, bx1 = -1, by2 = -1, bx2 = -1;
3399
3400         /* Get size */
3401         Term_get_size(&tb->wid, &tb->hgt);
3402
3403         /*
3404          * Top line (-1), description line (-3), separator (-1)
3405          *  == -5
3406          */
3407         tb->hgt -= 2 + DESCRIPT_HGT;
3408
3409 #ifdef JP
3410         /* Don't let cursor at second byte of kanji */
3411         for (i = 0; tb->lines_list[tb->cy][i]; i++)
3412                 if (iskanji(tb->lines_list[tb->cy][i]))
3413                 {
3414                         i++;
3415                         if (i == tb->cx)
3416                         {
3417                                 tb->cx--;
3418                                 break;
3419                         }
3420                 }
3421 #endif
3422
3423         /* Scroll if necessary */
3424         if (tb->cy < tb->upper || tb->upper + tb->hgt <= tb->cy)
3425                 tb->upper = tb->cy - (tb->hgt)/2;
3426         if (tb->upper < 0)
3427                 tb->upper = 0;
3428         if ((tb->cx < tb->left + 10 && tb->left > 0) || tb->left + tb->wid - 5 <= tb->cx)
3429                 tb->left = tb->cx - (tb->wid)*2/3;
3430         if (tb->left < 0)
3431                 tb->left = 0;
3432
3433         /* Redraw whole window after resize */
3434         if (tb->old_wid != tb->wid || tb->old_hgt != tb->hgt)
3435                 tb->dirty_flags |= DIRTY_SCREEN;
3436
3437         /* Redraw all text after scroll */
3438         else if (tb->old_upper != tb->upper || tb->old_left != tb->left)
3439                 tb->dirty_flags |= DIRTY_ALL;
3440
3441
3442         if (tb->dirty_flags & DIRTY_SCREEN)
3443         {
3444                 tb->dirty_flags |= (DIRTY_ALL | DIRTY_MODE);
3445
3446                 /* Clear screen */
3447                 Term_clear();
3448         }
3449
3450         /* Redraw mode line */
3451         if (tb->dirty_flags & DIRTY_MODE)
3452         {
3453                 char buf[MAX_LINELEN];
3454
3455                 int sepa_length = tb->wid;
3456
3457                 /* Separator */
3458                 for (i = 0; i < sepa_length; i++)
3459                         buf[i] = '-';
3460                 buf[i] = '\0';
3461
3462                 Term_putstr(0, tb->hgt + 1, sepa_length, TERM_WHITE, buf);
3463         }
3464
3465         if (tb->mark)
3466         {
3467                 int tmp_cx = tb->cx;
3468                 int len = strlen(tb->lines_list[tb->cy]);
3469
3470                 /* Correct cursor location */
3471                 if (tb->cx > len) tmp_cx = len;
3472
3473                 tb->dirty_flags |= DIRTY_ALL;
3474
3475                 if (tb->my < tb->cy ||
3476                     (tb->my == tb->cy && tb->mx < tmp_cx))
3477                 {
3478                         by1 = tb->my;
3479                         bx1 = tb->mx;
3480                         by2 = tb->cy;
3481                         bx2 = tmp_cx;
3482                 }
3483                 else
3484                 {
3485                         by2 = tb->my;
3486                         bx2 = tb->mx;
3487                         by1 = tb->cy;
3488                         bx1 = tmp_cx;
3489                 }
3490         }
3491
3492         /* Dump up to tb->hgt lines of messages */
3493         for (i = 0; i < tb->hgt; i++)
3494         {
3495                 int j;
3496                 int leftcol = 0;
3497                 cptr msg;
3498                 int y = tb->upper+i;
3499
3500                 /* clean or dirty? */
3501                 if (!(tb->dirty_flags & DIRTY_ALL) && (tb->dirty_line != y))
3502                         continue;
3503
3504                 msg = tb->lines_list[y];
3505                 if (!msg) break;
3506
3507                 /* Apply horizontal scroll */
3508                 for (j = 0; *msg; msg++, j++)
3509                 {
3510                         if (j == tb->left) break;
3511 #ifdef JP
3512                         if (j > tb->left)
3513                         {
3514                                 leftcol = 1;
3515                                 break;
3516                         }
3517                         if (iskanji(*msg))
3518                         {
3519                                 msg++;
3520                                 j++;
3521                         }
3522 #endif
3523                 }
3524
3525                 /* Erase line */
3526                 Term_erase(0, i + 1, tb->wid);
3527
3528                 if (!tb->mark)
3529                 {
3530                         /* Dump the messages, bottom to top */
3531                         Term_putstr(leftcol, i + 1, tb->wid - 1, TERM_WHITE, msg);
3532                 }
3533
3534                 else
3535                 {
3536                         int x0 = leftcol + tb->left;
3537
3538                         int sx0 = 0;
3539                         int sx1 = 0;
3540
3541                         if (by1 <= y && y < by2) sx1 = strlen(msg);
3542                         if (y == by1) sx0 = bx1;
3543                         if (y == by2) sx1 = bx2;
3544
3545                         Term_gotoxy(leftcol, i + 1);
3546                         if (x0 < sx0) Term_addstr(sx0 - x0, TERM_WHITE, msg);
3547                         if (x0 < sx1) Term_addstr(sx1 - sx0, TERM_YELLOW, msg + (sx0 - x0));
3548                         Term_addstr(-1, TERM_WHITE, msg + (sx1 - x0));
3549                 }
3550         }
3551
3552         for (; i < tb->hgt; i++)
3553         {
3554                 /* Erase line */
3555                 Term_erase(0, i + 1, tb->wid);
3556         }
3557
3558         /* Display information when updated */
3559         if (tb->old_cy != tb->cy || (tb->dirty_flags & (DIRTY_ALL | DIRTY_NOT_FOUND | DIRTY_NO_SEARCH)) || tb->dirty_line == tb->cy)
3560         {
3561                 autopick_type an_entry, *entry = &an_entry;
3562
3563                 /* Clear information line */
3564                 for (i = 0; i < DESCRIPT_HGT; i++)
3565                 {
3566                         /* Erase line */
3567                         Term_erase(0, tb->hgt + 2 + i, tb->wid);
3568                 }
3569
3570                 /* Display information */
3571                 if (tb->dirty_flags & DIRTY_NOT_FOUND)
3572                 {
3573 #ifdef JP
3574                         prt(format("¥Ñ¥¿¡¼¥ó¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó: %s", tb->search_str), tb->hgt + 1 + 1, 0);
3575 #else
3576                         prt(format("Pattern not found: %s", tb->search_str), tb->hgt + 1 + 1, 0);
3577 #endif
3578                 }
3579                 else if (tb->dirty_flags & DIRTY_NO_SEARCH)
3580                 {
3581 #ifdef JP
3582                         prt("¸¡º÷Ãæ¤Î¥Ñ¥¿¡¼¥ó¤¬¤¢¤ê¤Þ¤»¤ó('/'¤Ç¸¡º÷)¡£", tb->hgt + 1 + 1, 0);
3583 #else
3584                         prt("No pattern to search. (Press '/' to search.)", tb->hgt +1 + 1, 0);
3585 #endif
3586                 }
3587                 else if (tb->lines_list[tb->cy][0] == '#')
3588                 {
3589 #ifdef JP
3590                         prt("¤³¤Î¹Ô¤Ï¥³¥á¥ó¥È¤Ç¤¹¡£", tb->hgt +1 + 1, 0);
3591 #else
3592                         prt("This line is a comment.", tb->hgt +1 + 1, 0);
3593 #endif
3594                 }
3595                 else if (tb->lines_list[tb->cy][1] == ':')
3596                 {
3597                         switch(tb->lines_list[tb->cy][0])
3598                         {
3599                         case '?':
3600 #ifdef JP
3601                                 prt("¤³¤Î¹Ô¤Ï¾ò·ïʬ´ô¼°¤Ç¤¹¡£", tb->hgt +1 + 1, 0);
3602 #else
3603                                 prt("This line is a Conditional Expression.", tb->hgt +1 + 1, 0);
3604 #endif
3605                                 break;
3606                         case 'A':
3607 #ifdef JP
3608                                 prt("¤³¤Î¹Ô¤Ï¥Þ¥¯¥í¤Î¼Â¹ÔÆâÍƤòÄêµÁ¤·¤Þ¤¹¡£", tb->hgt +1 + 1, 0);
3609 #else
3610                                 prt("This line defines a Macro action.", tb->hgt +1 + 1, 0);
3611 #endif
3612                                 break;
3613                         case 'P':
3614 #ifdef JP
3615                                 prt("¤³¤Î¹Ô¤Ï¥Þ¥¯¥í¤Î¥È¥ê¥¬¡¼¡¦¥­¡¼¤òÄêµÁ¤·¤Þ¤¹¡£", tb->hgt +1 + 1, 0);
3616 #else
3617                                 prt("This line defines a Macro trigger key.", tb->hgt +1 + 1, 0);
3618 #endif
3619                                 break;
3620                         case 'C':
3621 #ifdef JP
3622                                 prt("¤³¤Î¹Ô¤Ï¥­¡¼ÇÛÃÖ¤òÄêµÁ¤·¤Þ¤¹¡£", tb->hgt +1 + 1, 0);
3623 #else
3624                                 prt("This line defines a Keymap.", tb->hgt +1 + 1, 0);
3625 #endif
3626                                 break;
3627                         }
3628                 }
3629
3630                 /* Get description of an autopicker preference line */
3631                 else if (autopick_new_entry(entry, tb->lines_list[tb->cy]))
3632                 {
3633                         char buf[MAX_LINELEN];
3634                         char temp[MAX_LINELEN];
3635                         cptr t;
3636
3637                         describe_autopick(buf, entry);
3638
3639                         roff_to_buf(buf, 81, temp, sizeof(temp));
3640                         t = temp;
3641                         for (i = 0; i < 3; i++)
3642                         {
3643                                 if(t[0] == 0)
3644                                         break; 
3645                                 else
3646                                 {
3647                                         prt(t, tb->hgt +1 + 1 + i, 0);
3648                                         t += strlen(t) + 1;
3649                                 }
3650                         }
3651                         autopick_free_entry(entry);
3652                 }
3653         }
3654 }
3655
3656
3657 /*
3658  * Kill segment of a line
3659  */
3660 static void kill_line_segment(text_body_type *tb, int y, int x0, int x1)
3661 {
3662         char buf[MAX_LINELEN];
3663         cptr s = tb->lines_list[y];
3664         char *d = buf;
3665         int x;
3666
3667         /* No segment? */
3668         if (x0 == x1) return;
3669
3670         /* Kill whole line? */
3671         if (x0 == 0 && s[x1] == '\0' && tb->lines_list[y+1])
3672         {
3673                 int i;
3674
3675                 string_free(tb->lines_list[y]);
3676
3677                 /* Shift lines up */
3678                 for (i = y; tb->lines_list[i+1]; i++)
3679                         tb->lines_list[i] = tb->lines_list[i+1];
3680                 tb->lines_list[i] = NULL;
3681
3682                 return;
3683         }
3684
3685         /* Before the segment */
3686         for (x = 0; x < x0; x++)
3687                 *(d++) = s[x];
3688
3689         /* After the segment */
3690         for (x = x1; s[x]; x++)
3691                 *(d++) = s[x];
3692
3693         *d = '\0';
3694
3695         /* Replace */
3696         string_free(tb->lines_list[y]);
3697         tb->lines_list[y] = string_make(buf);
3698 }
3699
3700
3701 /*
3702  * Kill text in the block selection
3703  */
3704 static bool kill_text_in_selection(text_body_type *tb)
3705 {
3706         int by1, bx1, by2, bx2;
3707         int y;
3708
3709         int len = strlen(tb->lines_list[tb->cy]);
3710
3711         /* Correct cursor location */
3712         if (tb->cx > len) tb->cx = len;
3713
3714         if (tb->my < tb->cy ||
3715             (tb->my == tb->cy && tb->mx < tb->cx))
3716         {
3717                 by1 = tb->my;
3718                 bx1 = tb->mx;
3719                 by2 = tb->cy;
3720                 bx2 = tb->cx;
3721         }
3722         else
3723         {
3724                 by2 = tb->my;
3725                 bx2 = tb->mx;
3726                 by1 = tb->cy;
3727                 bx1 = tb->cx;
3728         }
3729
3730         /* Kill lines in reverse order */
3731         for (y = by2; y >= by1; y--)
3732         {
3733                 int x0 = 0;
3734                 int x1 = strlen(tb->lines_list[y]);
3735
3736                 if (y == by1) x0 = bx1;
3737                 if (y == by2) x1 = bx2;
3738
3739                 kill_line_segment(tb, y, x0, x1);
3740         }
3741
3742         /* Correct cursor position */
3743         tb->cy = by1;
3744         tb->cx = bx1;
3745
3746         /* Disable selection */
3747         tb->mark = 0;
3748
3749         /* Now dirty */
3750         tb->dirty_flags |= DIRTY_ALL;
3751
3752         return TRUE;
3753 }
3754
3755
3756 /*
3757  * Get a trigger key and insert ASCII string for the trigger
3758  */
3759 static bool insert_macro_line(cptr *lines_list, int cy)
3760 {
3761         char tmp[1024];
3762         char buf[1024];
3763         int i, n = 0;
3764
3765         /* Flush */
3766         flush();
3767
3768         /* Do not process macros */
3769         inkey_base = TRUE;
3770
3771         /* First key */
3772         i = inkey();
3773
3774         /* Read the pattern */
3775         while (i)
3776         {
3777                 /* Save the key */
3778                 buf[n++] = i;
3779
3780                 /* Do not process macros */
3781                 inkey_base = TRUE;
3782
3783                 /* Do not wait for keys */
3784                 inkey_scan = TRUE;
3785
3786                 /* Attempt to read a key */
3787                 i = inkey();
3788         }
3789
3790         /* Terminate */
3791         buf[n] = '\0';
3792
3793         /* Flush */
3794         flush();
3795
3796         /* Convert the trigger */
3797         ascii_to_text(tmp, buf);
3798
3799         /* Null */
3800         if(!tmp[0]) return FALSE;
3801
3802         /* Insert preference string */
3803         insert_return_code(lines_list, 0, cy);
3804         string_free(lines_list[cy]);
3805         lines_list[cy] = string_make(format("P:%s", tmp));
3806
3807         /* Acquire action */
3808         i = macro_find_exact(buf);
3809
3810         if (i == -1)
3811         {
3812                 /* Nothing defined */
3813                 tmp[0] = '\0';
3814         }
3815         else
3816         {
3817                 /* Analyze the current action */
3818                 ascii_to_text(tmp, macro__act[i]);
3819         }
3820
3821         /* Insert blank action preference line */
3822         insert_return_code(lines_list, 0, cy);
3823         string_free(lines_list[cy]);
3824         lines_list[cy] = string_make(format("A:%s", tmp));
3825
3826         return TRUE;
3827 }
3828
3829
3830 /*
3831  * Get a command key and insert ASCII string for the key
3832  */
3833 static bool insert_keymap_line(cptr *lines_list, int cy)
3834 {
3835         char tmp[1024];
3836         char buf[2];
3837         int mode;
3838         cptr act;
3839
3840         /* Roguelike */
3841         if (rogue_like_commands)
3842         {
3843                 mode = KEYMAP_MODE_ROGUE;
3844         }
3845
3846         /* Original */
3847         else
3848         {
3849                 mode = KEYMAP_MODE_ORIG;
3850         }
3851
3852         /* Flush */
3853         flush();
3854
3855         /* Get a key */
3856         buf[0] = inkey();
3857         buf[1] = '\0';
3858
3859         /* Flush */
3860         flush();
3861
3862         /* Convert the trigger */
3863         ascii_to_text(tmp, buf);
3864
3865         /* Null */
3866         if(!tmp[0]) return FALSE;
3867
3868         /* Insert preference string */
3869         insert_return_code(lines_list, 0, cy);
3870         string_free(lines_list[cy]);
3871         lines_list[cy] = string_make(format("C:%d:%s", mode, tmp));
3872
3873         /* Look up the keymap */
3874         act = keymap_act[mode][(byte)(buf[0])];
3875
3876         /* Insert blank action preference line */
3877         insert_return_code(lines_list, 0, cy);
3878         string_free(lines_list[cy]);
3879         lines_list[cy] = string_make(format("A:%s", act));
3880
3881         return TRUE;
3882 }
3883
3884
3885 /*
3886  * Execute a single editor command
3887  */
3888 static bool do_editor_command(text_body_type *tb, int com_id)
3889 {
3890         switch(com_id)
3891         {
3892         case EC_QUIT:
3893                 return TRUE;
3894
3895         case EC_REVERT:
3896                 /* Revert to original */
3897 #ifdef JP
3898                 if (!get_check("Á´¤Æ¤ÎÊѹ¹¤òÇË´þ¤·¤Æ¸µ¤Î¾õÂÖ¤ËÌᤷ¤Þ¤¹¡£¤è¤í¤·¤¤¤Ç¤¹¤«¡© ")) break;
3899 #else
3900                 if (!get_check("Discard all changes and revert to original file. Are you sure? ")) break;
3901 #endif
3902
3903                 free_text_lines(tb->lines_list);
3904                 tb->lines_list = read_pickpref_text_lines(&tb->filename_mode);
3905                 tb->dirty_flags |= DIRTY_ALL | DIRTY_MODE;
3906                 tb->cx = tb->cy = 0;
3907                 tb->mark = 0;
3908                 break;
3909
3910         case EC_HELP:
3911                 /* Peruse the main help file */
3912 #ifdef JP
3913                 (void)show_file(TRUE, "jeditor.txt", NULL, 0, 0);
3914 #else
3915                 (void)show_file(TRUE, "editor.txt", NULL, 0, 0);
3916 #endif
3917                 /* Redraw all */
3918                 tb->dirty_flags |= DIRTY_SCREEN;
3919
3920                 break;
3921
3922         case EC_RETURN:
3923                 /* Split a line or insert end of line */
3924
3925                 /*
3926                  * If there is a selection, kill it, and replace it
3927                  * with return code.
3928                  */
3929                 if (tb->mark) kill_text_in_selection(tb);
3930
3931                 insert_return_code(tb->lines_list, tb->cx, tb->cy);
3932                 tb->cy++;
3933                 tb->cx = 0;
3934
3935                 /* Now dirty */
3936                 tb->dirty_flags |= DIRTY_ALL;
3937                 break;
3938
3939         case EC_LEFT:
3940                 /* Back */
3941                 if (0 < tb->cx)
3942                 {
3943                         int len;
3944
3945                         tb->cx--;
3946                         len = strlen(tb->lines_list[tb->cy]);
3947                         if (len < tb->cx) tb->cx = len;
3948                 }
3949                 else if (tb->cy > 0)
3950                 {
3951                         tb->cy--;
3952                         tb->cx = strlen(tb->lines_list[tb->cy]);
3953                 }
3954                 break;
3955
3956         case EC_DOWN:
3957                 /* Next line */
3958                 if (tb->lines_list[tb->cy + 1]) tb->cy++;
3959                 break;
3960
3961         case EC_UP:
3962                 /* Previous line */
3963                 if (tb->cy > 0) tb->cy--;
3964                 break;
3965
3966         case EC_RIGHT:
3967         {
3968                 /* Forward */
3969
3970                 int len;
3971 #ifdef JP
3972                 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
3973 #endif
3974                 tb->cx++;
3975                 len = strlen(tb->lines_list[tb->cy]);
3976                 if (len < tb->cx)
3977                 {
3978                         if (tb->lines_list[tb->cy + 1])
3979                         {
3980                                 tb->cy++;
3981                                 tb->cx = 0;
3982                         }
3983                         else
3984                                 tb->cx = len;
3985                 }
3986                 break;
3987         }
3988
3989         case EC_BOL:
3990                 /* Beginning of line */
3991                 tb->cx = 0;
3992                 break;
3993
3994         case EC_EOL:
3995                 /* End of line */
3996                 tb->cx = strlen(tb->lines_list[tb->cy]);
3997                 break;
3998
3999         case EC_PGUP:
4000                 while (0 < tb->cy && tb->upper <= tb->cy)
4001                         tb->cy--;
4002                 while (0 < tb->upper && tb->cy + 1 < tb->upper + tb->hgt)
4003                         tb->upper--;
4004                 break;
4005
4006         case EC_PGDOWN:
4007                 /* Page down */
4008                 while (tb->cy < tb->upper + tb->hgt && tb->lines_list[tb->cy + 1])
4009                         tb->cy++;
4010                 tb->upper = tb->cy;
4011                 break;
4012
4013         case EC_TOP:
4014                 tb->cy = 0;
4015                 break;
4016
4017         case EC_BOTTOM:
4018                 while (tb->lines_list[tb->cy + 1])
4019                         tb->cy++;
4020                 break;
4021
4022         case EC_CUT:
4023         {       
4024                 /* Copy the text first */
4025                 do_editor_command(tb, EC_COPY);
4026
4027                 /* Kill all */
4028                 kill_text_in_selection(tb);
4029
4030                 break;
4031         }
4032
4033         case EC_COPY:
4034         {       
4035                 int by1, bx1, by2, bx2;
4036                 int y;
4037                 int len = strlen(tb->lines_list[tb->cy]);
4038
4039                 /* Correct cursor location */
4040                 if (tb->cx > len) tb->cx = len;
4041
4042                 /* Use single line? */
4043                 if (!tb->mark)
4044                 {
4045                         tb->my = tb->cy;
4046                         tb->mx = 0;
4047                         if (tb->lines_list[tb->cy + 1])
4048                         {
4049                                 /* Select a single line */
4050                                 tb->cx = 0;
4051                                 tb->cy++;
4052                         }
4053                         else
4054                         {
4055                                 /* Select bottom line */
4056                                 tb->cx = len;
4057                         }
4058                 }
4059
4060                 if (tb->my < tb->cy ||
4061                     (tb->my == tb->cy && tb->mx < tb->cx))
4062                 {
4063                         by1 = tb->my;
4064                         bx1 = tb->mx;
4065                         by2 = tb->cy;
4066                         bx2 = tb->cx;
4067                 }
4068                 else
4069                 {
4070                         by2 = tb->my;
4071                         bx2 = tb->mx;
4072                         by1 = tb->cy;
4073                         bx1 = tb->cx;
4074                 }
4075
4076                 /* Kill old yank buffer */
4077                 kill_yank_chain(tb);
4078
4079                 /* Copy string to yank buffer */
4080                 for (y = by1; y <= by2; y++)
4081                 {
4082                         int i;
4083                         char buf[MAX_LINELEN];
4084
4085                         int x0 = 0;
4086                         int x1 = strlen(tb->lines_list[y]);
4087
4088                         if (y == by1) x0 = bx1;
4089                         if (y == by2) x1 = bx2;
4090
4091                         for (i = 0; i < x1 - x0; i++)
4092                         {
4093                                 buf[i] = tb->lines_list[y][x0 + i];
4094                         }
4095                         buf[i] = '\0';
4096
4097                         add_str_to_yank(tb, buf);
4098                 }
4099
4100                 /* Disable selection */
4101                 tb->mark = 0;
4102
4103                 /* Now dirty */
4104                 tb->dirty_flags |= DIRTY_ALL;
4105                 break;
4106         }
4107
4108         case EC_PASTE:
4109         {
4110                 /* Paste killed text */
4111
4112                 chain_str_type *chain = tb->yank;
4113                 int len = strlen(tb->lines_list[tb->cy]);
4114
4115                 /* Nothing to do? */
4116                 if (!chain) break;
4117
4118                 /* Correct cursor location */
4119                 if (tb->cx > len) tb->cx = len;
4120
4121                 /*
4122                  * If there is a selection, kill text, and
4123                  * replace it with the yank text.
4124                  */
4125                 if (tb->mark) kill_text_in_selection(tb);
4126
4127                 /* Paste text */
4128                 while (chain)
4129                 {
4130                         cptr yank_str = chain->s;
4131
4132                         char buf[MAX_LINELEN];
4133                         int i;
4134                         char rest[MAX_LINELEN], *rest_ptr = rest;
4135
4136                         /* Save preceding string */
4137                         for(i = 0; i < tb->cx; i++)
4138                                 buf[i] = tb->lines_list[tb->cy][i];
4139
4140                         strcpy(rest, &(tb->lines_list[tb->cy][i]));
4141
4142                         /* Paste yank buffer */
4143                         while (*yank_str && i < MAX_LINELEN-1)
4144                         {
4145                                 buf[i++] = *yank_str++;
4146                         }
4147
4148                         /* Terminate */
4149                         buf[i] = '\0';
4150
4151                         chain = chain->next;
4152
4153                         if (chain || tb->yank_eol)
4154                         {
4155                                 /* There is an end of line between chain nodes */
4156
4157                                 insert_return_code(tb->lines_list, tb->cx, tb->cy);
4158
4159                                 /* Replace this line with new one */
4160                                 string_free(tb->lines_list[tb->cy]);
4161                                 tb->lines_list[tb->cy] = string_make(buf);
4162
4163                                 /* Move to next line */
4164                                 tb->cx = 0;
4165                                 tb->cy++;
4166
4167                                 continue;
4168                         }
4169
4170                         /* Final line doesn't have end of line */
4171
4172                         tb->cx = strlen(buf);
4173
4174                         /* Rest of original line */
4175                         while (*rest_ptr && i < MAX_LINELEN-1)
4176                         {
4177                                 buf[i++] = *rest_ptr++;
4178                         }
4179
4180                         /* Terminate */
4181                         buf[i] = '\0';
4182
4183                         /* Replace this line with new one */
4184                         string_free(tb->lines_list[tb->cy]);
4185                         tb->lines_list[tb->cy] = string_make(buf);
4186
4187                         /* Finish */
4188                         break;
4189                 }
4190
4191                 /* Now dirty */
4192                 tb->dirty_flags |= DIRTY_ALL;
4193                 break;
4194         }
4195
4196         case EC_BLOCK:
4197                 if (tb->mark)
4198                 {
4199                         /* Disable the selection */
4200                         tb->mark = 0;
4201
4202                         /* Redraw text */
4203                         tb->dirty_flags |= DIRTY_ALL;
4204                 }
4205                 else
4206                 {
4207                         tb->mark = MARK_MARK;
4208
4209                         /* Repeating this command swaps cursor position */
4210                         if (com_id == tb->old_com_id)
4211                         {
4212                                 int tmp;
4213
4214                                 tmp = tb->cy;
4215                                 tb->cy = tb->my;
4216                                 tb->my = tmp;
4217                                 tmp = tb->cx;
4218                                 tb->cx = tb->mx;
4219                                 tb->mx = tmp;
4220
4221                                 /* Redraw text */
4222                                 tb->dirty_flags |= DIRTY_ALL;
4223                         }
4224                         else
4225                         {
4226                                 int len = strlen(tb->lines_list[tb->cy]);
4227
4228                                 /* Mark the point 1 */
4229                                 tb->my = tb->cy;
4230                                 tb->mx = tb->cx;
4231
4232                                 /* Correct cursor location */
4233                                 if (tb->cx > len) tb->mx = len;
4234                         }
4235                 }
4236                 break;
4237
4238         case EC_KILL_LINE:
4239         {
4240                 /* Kill rest of line */
4241
4242                 int i;
4243                 char buf[MAX_LINELEN];
4244                 cptr line;
4245
4246                 /* If there is a selection, kill it */
4247                 if (tb->mark)
4248                 {
4249                         if (kill_text_in_selection(tb)) break;
4250                 }
4251
4252                 /* Correct cursor location */
4253                 if ((uint)tb->cx > strlen(tb->lines_list[tb->cy]))
4254                         tb->cx = (int)strlen(tb->lines_list[tb->cy]);
4255
4256                 /* Save preceding string */
4257                 for (i = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
4258                 {
4259 #ifdef JP
4260                         if (iskanji(tb->lines_list[tb->cy][i]))
4261                         {
4262                                 buf[i] = tb->lines_list[tb->cy][i];
4263                                 i++;
4264                         }
4265 #endif
4266                         buf[i] = tb->lines_list[tb->cy][i];
4267                 }
4268                 buf[i] = '\0';
4269                 line = string_make(buf);
4270
4271                 /* Append only if this command is repeated. */
4272                 if (tb->old_com_id != com_id)
4273                 {
4274                         kill_yank_chain(tb);
4275                         tb->yank = NULL;
4276                 }
4277
4278                 /* Really deleted some text */
4279                 if (strlen(tb->lines_list[tb->cy] + i))
4280                 {
4281                         /* Add deleted string to yank buffer */
4282                         add_str_to_yank(tb, tb->lines_list[tb->cy] + i);
4283
4284                         /* Replace current line with 'preceding string' */
4285                         string_free(tb->lines_list[tb->cy]);
4286                         tb->lines_list[tb->cy] = line;
4287
4288                         /* Now dirty */
4289                         tb->dirty_line = tb->cy;
4290
4291                         /* Leave end of line character */
4292                         break;
4293                 }
4294
4295                 /* Delete the end of line character only */
4296                 if (tb->yank_eol) add_str_to_yank(tb, "");
4297                 else tb->yank_eol = TRUE;
4298
4299                 do_editor_command(tb, EC_DELETE_CHAR);
4300                 break;
4301         }
4302
4303         case EC_DELETE_CHAR:
4304                 /* DELETE == go forward + BACK SPACE */
4305
4306                 /* If there is a selection, kill it */
4307                 if (tb->mark)
4308                 {
4309                         if (kill_text_in_selection(tb)) break;
4310                 }
4311
4312 #ifdef JP
4313                 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
4314 #endif
4315                 tb->cx++;
4316
4317                 do_editor_command(tb, EC_BACKSPACE);
4318                 break;
4319
4320         case EC_BACKSPACE:
4321         {
4322                 /* BACK SPACE */
4323
4324                 int len, i, j, k;
4325                 char buf[MAX_LINELEN];
4326
4327                 /* If there is a selection, kill it */
4328                 if (tb->mark)
4329                 {
4330                         if (kill_text_in_selection(tb)) break;
4331                 }
4332
4333                 len = strlen(tb->lines_list[tb->cy]);
4334                 if (len < tb->cx)
4335                 {
4336                         if (tb->lines_list[tb->cy + 1])
4337                         {
4338                                 tb->cy++;
4339                                 tb->cx = 0;
4340                         }
4341                         else
4342                         {
4343                                 tb->cx = len;
4344                                 break;
4345                         }
4346                 }
4347
4348                 if (tb->cx == 0)
4349                 {
4350                         /* delete a return code and union two lines */
4351                         if (tb->cy == 0) break;
4352                         tb->cx = strlen(tb->lines_list[tb->cy-1]);
4353                         strcpy(buf, tb->lines_list[tb->cy-1]);
4354                         strcat(buf, tb->lines_list[tb->cy]);
4355                         string_free(tb->lines_list[tb->cy-1]);
4356                         string_free(tb->lines_list[tb->cy]);
4357                         tb->lines_list[tb->cy-1] = string_make(buf);
4358                         for (i = tb->cy; tb->lines_list[i+1]; i++)
4359                                 tb->lines_list[i] = tb->lines_list[i+1];
4360                         tb->lines_list[i] = NULL;
4361                         tb->cy--;
4362
4363                         /* Now dirty */
4364                         tb->dirty_flags |= DIRTY_ALL;
4365                         break;
4366                 }
4367
4368                 for (i = j = k = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
4369                 {
4370                         k = j;
4371 #ifdef JP
4372                         if (iskanji(tb->lines_list[tb->cy][i]))
4373                                 buf[j++] = tb->lines_list[tb->cy][i++];
4374 #endif
4375                         buf[j++] = tb->lines_list[tb->cy][i];
4376                 }
4377                 while (j > k)
4378                 {
4379                         tb->cx--;
4380                         j--;
4381                 }
4382                 for (; tb->lines_list[tb->cy][i]; i++)
4383                         buf[j++] = tb->lines_list[tb->cy][i];
4384                 buf[j] = '\0';
4385                 string_free(tb->lines_list[tb->cy]);
4386                 tb->lines_list[tb->cy] = string_make(buf);
4387
4388                 /* Now dirty */
4389                 tb->dirty_line = tb->cy;
4390                 break;
4391         }
4392
4393         case EC_SEARCH_STR:
4394         {
4395                 byte search_dir;
4396
4397                 /* Become dirty because of item/equip menu */
4398                 tb->dirty_flags |= DIRTY_SCREEN;
4399
4400                 search_dir = get_string_for_search(&tb->search_o_ptr, &tb->search_str);
4401
4402                 if (!search_dir) break;
4403
4404                 if (search_dir == 1) do_editor_command(tb, EC_SEARCH_FORW);
4405                 else do_editor_command(tb, EC_SEARCH_BACK);
4406                 break;
4407         }
4408
4409         case EC_SEARCH_FORW:
4410                 if (tb->search_o_ptr)
4411                 {
4412                         if (!search_for_object(tb->lines_list, tb->search_o_ptr, &tb->cx, &tb->cy, TRUE)) tb->dirty_flags |= DIRTY_NOT_FOUND;
4413                 }
4414                 else if (tb->search_str)
4415                 {
4416                         if (!search_for_string(tb->lines_list, tb->search_str, &tb->cx, &tb->cy, TRUE)) tb->dirty_flags |= DIRTY_NOT_FOUND;
4417                 }
4418                 else
4419                 {
4420                         tb->dirty_flags |= DIRTY_NO_SEARCH;
4421                 }
4422                 break;
4423
4424         case EC_SEARCH_BACK:
4425                 if (tb->search_o_ptr)
4426                 {
4427                         if (!search_for_object(tb->lines_list, tb->search_o_ptr, &tb->cx, &tb->cy, FALSE)) tb->dirty_flags |= DIRTY_NOT_FOUND;
4428                 }
4429                 else if (tb->search_str)
4430                 {
4431                         if (!search_for_string(tb->lines_list, tb->search_str, &tb->cx, &tb->cy, FALSE)) tb->dirty_flags |= DIRTY_NOT_FOUND;
4432                 }
4433                 else
4434                 {
4435                         tb->dirty_flags |= DIRTY_NO_SEARCH;
4436                 }
4437                 break;
4438
4439         case EC_SEARCH_OBJ:
4440                 /* Become dirty because of item/equip menu */
4441                 tb->dirty_flags |= DIRTY_SCREEN;
4442
4443                 if (!get_object_for_search(&tb->search_o_ptr, &tb->search_str)) break;
4444
4445                 do_editor_command(tb, EC_SEARCH_FORW);
4446                 break;
4447
4448         case EC_SEARCH_DESTROYED:
4449                 if (!get_destroyed_object_for_search(&tb->search_o_ptr, &tb->search_str)) break;
4450
4451                 do_editor_command(tb, EC_SEARCH_FORW);
4452                 break;
4453
4454         case EC_INSERT_OBJECT:
4455         {
4456                 /* Insert choosen item name */
4457
4458                 autopick_type an_entry, *entry = &an_entry;
4459
4460                 if (!entry_from_choosed_object(entry))
4461                 {
4462                         /* Now dirty because of item/equip menu */
4463                         tb->dirty_flags |= DIRTY_SCREEN;
4464                         break;
4465                 }
4466
4467                 insert_return_code(tb->lines_list, 0, tb->cy);
4468                 string_free(tb->lines_list[tb->cy]);
4469                 tb->lines_list[tb->cy] = autopick_line_from_entry_kill(entry);
4470                 tb->cx = 0;
4471
4472                 /* Now dirty because of item/equip menu */
4473                 tb->dirty_flags |= DIRTY_SCREEN;
4474
4475                 break;
4476         }
4477
4478         case EC_INSERT_DESTROYED:
4479                 /* Insert a name of last destroyed item */
4480                 if (tb->last_destroyed)
4481                 {
4482                         insert_return_code(tb->lines_list, 0, tb->cy);
4483                         string_free(tb->lines_list[tb->cy]);
4484                         tb->lines_list[tb->cy] = string_make(tb->last_destroyed);
4485                         tb->cx = 0;
4486
4487                         /* Now dirty */
4488                         tb->dirty_flags |= DIRTY_ALL;
4489                 }
4490                 break;
4491
4492         case EC_INSERT_BLOCK:
4493         {
4494                 /* Insert a conditinal expression line */
4495                 char classrace[80];
4496
4497                 /* Conditional Expression for Class and Race */
4498                 sprintf(classrace, "?:[AND [EQU $RACE %s] [EQU $CLASS %s]]", 
4499 #ifdef JP
4500                         rp_ptr->E_title, cp_ptr->E_title
4501 #else
4502                         rp_ptr->title, cp_ptr->title
4503 #endif
4504                         );
4505
4506                 insert_return_code(tb->lines_list, 0, tb->cy);
4507                 string_free(tb->lines_list[tb->cy]);
4508                 tb->lines_list[tb->cy] = string_make(classrace);
4509                 tb->cy++;
4510                 insert_return_code(tb->lines_list, 0, tb->cy);
4511                 string_free(tb->lines_list[tb->cy]);
4512                 tb->lines_list[tb->cy] = string_make("?:1");
4513                 tb->cx = 0;
4514
4515                 /* Now dirty */
4516                 tb->dirty_flags |= DIRTY_ALL;
4517                 break;
4518         }
4519
4520         case EC_INSERT_MACRO:
4521                 /* Draw_everythig (delete menu) */
4522                 draw_text_editor(tb);
4523
4524                 /* Erase line */
4525                 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
4526
4527                 /* Prompt */
4528 #ifdef JP
4529                 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, "P:<¥È¥ê¥¬¡¼¥­¡¼>: ");
4530 #else
4531                 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, "P:<Trigger key>: ");
4532 #endif
4533                 if (insert_macro_line(tb->lines_list, tb->cy))
4534                 {
4535                         /* Prepare to input action */
4536                         tb->cx = 2;
4537
4538                         /* Now dirty */
4539                         tb->dirty_flags |= DIRTY_ALL;
4540                         tb->dirty_flags |= DIRTY_MODE;
4541                 }
4542
4543                 break;
4544
4545         case EC_INSERT_KEYMAP:
4546                 /* Draw_everythig (delete menu) */
4547                 draw_text_editor(tb);
4548
4549                 /* Erase line */
4550                 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
4551
4552                 /* Prompt */
4553 #ifdef JP
4554                 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)));
4555 #else
4556                 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)));
4557 #endif
4558
4559                 if (insert_keymap_line(tb->lines_list, tb->cy))
4560                 {
4561                         /* Prepare to input action */
4562                         tb->cx = 2;
4563
4564                         /* Now dirty */
4565                         tb->dirty_flags |= DIRTY_ALL;
4566                         tb->dirty_flags |= DIRTY_MODE;
4567                 }                               
4568                 break;
4569
4570         case EC_CL_AUTOPICK: toggle_command_letter(tb, DO_AUTOPICK); break;
4571         case EC_CL_DESTROY: toggle_command_letter(tb, DO_AUTODESTROY); break;
4572         case EC_CL_LEAVE: toggle_command_letter(tb, DONT_AUTOPICK); break;
4573         case EC_CL_QUERY: toggle_command_letter(tb, DO_QUERY_AUTOPICK); break;
4574         case EC_CL_NO_DISP: toggle_command_letter(tb, DO_DISPLAY); break;
4575
4576         case EC_IK_UNAWARE: toggle_keyword(tb, FLG_UNAWARE); break;
4577         case EC_IK_UNIDENTIFIED: toggle_keyword(tb, FLG_UNIDENTIFIED); break;
4578         case EC_IK_IDENTIFIED: toggle_keyword(tb, FLG_IDENTIFIED); break;
4579         case EC_IK_STAR_IDENTIFIED: toggle_keyword(tb, FLG_STAR_IDENTIFIED); break;
4580         case EC_KK_WEAPONS: toggle_keyword(tb, FLG_WEAPONS); break;
4581         case EC_KK_FAVORITE: toggle_keyword(tb, FLG_FAVORITE); break;
4582         case EC_KK_ARMORS: toggle_keyword(tb, FLG_ARMORS); break;
4583         case EC_KK_MISSILES: toggle_keyword(tb, FLG_MISSILES); break;
4584         case EC_KK_DEVICES: toggle_keyword(tb, FLG_DEVICES); break;
4585         case EC_KK_LIGHTS: toggle_keyword(tb, FLG_LIGHTS); break;
4586         case EC_KK_JUNKS: toggle_keyword(tb, FLG_JUNKS); break;
4587         case EC_KK_SPELLBOOKS: toggle_keyword(tb, FLG_SPELLBOOKS); break;
4588         case EC_KK_SHIELDS: toggle_keyword(tb, FLG_SHIELDS); break;
4589         case EC_KK_BOWS: toggle_keyword(tb, FLG_BOWS); break;
4590         case EC_KK_RINGS: toggle_keyword(tb, FLG_RINGS); break;
4591         case EC_KK_AMULETS: toggle_keyword(tb, FLG_AMULETS); break;
4592         case EC_KK_SUITS: toggle_keyword(tb, FLG_SUITS); break;
4593         case EC_KK_CLOAKS: toggle_keyword(tb, FLG_CLOAKS); break;
4594         case EC_KK_HELMS: toggle_keyword(tb, FLG_HELMS); break;
4595         case EC_KK_GLOVES: toggle_keyword(tb, FLG_GLOVES); break;
4596         case EC_KK_BOOTS: toggle_keyword(tb, FLG_BOOTS); break;
4597         case EC_OK_COLLECTING: toggle_keyword(tb, FLG_COLLECTING); break;
4598         case EC_OK_BOOSTED: toggle_keyword(tb, FLG_BOOSTED); break;
4599         case EC_OK_MORE_THAN: toggle_keyword(tb, FLG_MORE_THAN); break;
4600         case EC_OK_MORE_BONUS: toggle_keyword(tb, FLG_MORE_BONUS); break;
4601         case EC_OK_WORTHLESS: toggle_keyword(tb, FLG_WORTHLESS); break;
4602         case EC_OK_ARTIFACT: toggle_keyword(tb, FLG_ARTIFACT); break;
4603         case EC_OK_EGO: toggle_keyword(tb, FLG_EGO); break;
4604         case EC_OK_NAMELESS: toggle_keyword(tb, FLG_NAMELESS); break;
4605         case EC_OK_WANTED: toggle_keyword(tb, FLG_WANTED); break;
4606         case EC_OK_UNIQUE: toggle_keyword(tb, FLG_UNIQUE); break;
4607         case EC_OK_HUMAN: toggle_keyword(tb, FLG_HUMAN); break;
4608         case EC_OK_UNREADABLE:
4609                 toggle_keyword(tb, FLG_UNREADABLE);
4610                 add_keyword(tb, FLG_SPELLBOOKS);
4611                 break;
4612         case EC_OK_REALM1:
4613                 toggle_keyword(tb, FLG_REALM1);
4614                 add_keyword(tb, FLG_SPELLBOOKS);
4615                 break;
4616         case EC_OK_REALM2:
4617                 toggle_keyword(tb, FLG_REALM2);
4618                 add_keyword(tb, FLG_SPELLBOOKS);
4619                 break;
4620         case EC_OK_FIRST:
4621                 toggle_keyword(tb, FLG_FIRST);
4622                 add_keyword(tb, FLG_SPELLBOOKS);
4623                 break;
4624         case EC_OK_SECOND:
4625                 toggle_keyword(tb, FLG_SECOND);
4626                 add_keyword(tb, FLG_SPELLBOOKS);
4627                 break;
4628         case EC_OK_THIRD:
4629                 toggle_keyword(tb, FLG_THIRD);
4630                 add_keyword(tb, FLG_SPELLBOOKS);
4631                 break;
4632         case EC_OK_FOURTH:
4633                 toggle_keyword(tb, FLG_FOURTH);
4634                 add_keyword(tb, FLG_SPELLBOOKS);
4635                 break;
4636         }
4637
4638         /* Save old command */
4639         tb->old_com_id = com_id;
4640
4641         return FALSE;
4642 }
4643
4644
4645 /*
4646  * Insert single letter at cursor position.
4647  */
4648 static void insert_single_letter(text_body_type *tb, int key)
4649 {
4650         int i, j, len;
4651         char buf[MAX_LINELEN];
4652
4653         /* Save preceding string */
4654         for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
4655                 buf[j++] = tb->lines_list[tb->cy][i];
4656
4657         /* Add a character */
4658 #ifdef JP
4659         if (iskanji(key))
4660         {
4661                 int next;
4662
4663                 inkey_base = TRUE;
4664                 next = inkey();
4665                 if (j+2 < MAX_LINELEN)
4666                 {
4667                         buf[j++] = key;
4668                         buf[j++] = next;
4669                         tb->cx += 2;
4670                 }
4671                 else
4672                         bell();
4673         }
4674         else
4675 #endif
4676         {
4677                 if (j+1 < MAX_LINELEN)
4678                         buf[j++] = key;
4679                 tb->cx++;
4680         }
4681
4682         /* Add following */
4683         for (; tb->lines_list[tb->cy][i] && j + 1 < MAX_LINELEN; i++)
4684                 buf[j++] = tb->lines_list[tb->cy][i];
4685         buf[j] = '\0';
4686
4687         /* Replace current line with new line */
4688         string_free(tb->lines_list[tb->cy]);
4689         tb->lines_list[tb->cy] = string_make(buf);
4690
4691         /* Move to correct collumn */
4692         len = strlen(tb->lines_list[tb->cy]);
4693         if (len < tb->cx) tb->cx = len;
4694
4695         /* Now dirty */
4696         tb->dirty_line = tb->cy;
4697 }
4698
4699 /*
4700  * In-game editor of Object Auto-picker/Destoryer
4701  */
4702 void do_cmd_edit_autopick(void)
4703 {
4704         text_body_type text_body, *tb = &text_body;
4705
4706         autopick_type an_entry, *entry = &an_entry;
4707         char buf[MAX_LINELEN];
4708
4709         int i;
4710         int key = -1;
4711
4712         static s32b old_autosave_turn = 0L;
4713         bool quit = FALSE;
4714
4715         tb->cx = tb->cy = tb->upper = tb->left = 0;
4716         tb->mark = 0;
4717         tb->mx = tb->my = 0;
4718         tb->old_cy = tb->old_upper = tb->old_left = -1;
4719         tb->old_wid = tb->old_hgt = -1;
4720         tb->old_com_id = 0;
4721
4722         tb->yank = NULL;
4723         tb->search_o_ptr = NULL;
4724         tb->search_str = NULL;
4725         tb->last_destroyed = NULL;
4726         tb->dirty_flags = DIRTY_ALL | DIRTY_MODE;
4727         tb->dirty_line = -1;
4728         tb->filename_mode = PT_WITH_PNAME;
4729
4730         /* Autosave */
4731         if (turn > old_autosave_turn + 100L)
4732         {
4733                 do_cmd_save_game(TRUE);
4734                 old_autosave_turn = turn;
4735         }
4736
4737         /* HACK -- Reset start_time to stop counting playtime while edit */
4738         update_playtime();
4739
4740         /* Free old entries */
4741         init_autopicker();
4742
4743         /* Command Description of the 'Last Destroyed Item' */
4744         if (autopick_last_destroyed_object.k_idx)
4745         {
4746                 autopick_entry_from_object(entry, &autopick_last_destroyed_object);
4747                 tb->last_destroyed = autopick_line_from_entry_kill(entry);
4748         }
4749
4750         /* Read or initialize whole text */
4751         tb->lines_list = read_pickpref_text_lines(&tb->filename_mode);
4752
4753         /* Reset cursor position if needed */
4754         for (i = 0; i < tb->cy; i++)
4755         {
4756                 if (!tb->lines_list[i])
4757                 {
4758                         tb->cy = tb->cx = 0;
4759                         break;
4760                 }
4761         }
4762
4763         /* Save the screen */
4764         screen_save();
4765
4766         /* Process requests until done */
4767         while (!quit)
4768         {
4769                 int com_id = 0;
4770                 size_t trig_len;
4771
4772                 /* Draw_everythig */
4773                 draw_text_editor(tb);
4774
4775                 /* Display header line */
4776 #ifdef JP
4777                 prt("(^Q:½ªÎ», ESC:¥á¥Ë¥å¡¼, ¤½¤Î¾:ÆþÎÏ)", 0, 0);
4778 #else   
4779                 prt("(^Q:quit, ESC:menu, Other:input text)", 0, 0);
4780 #endif
4781                 if (!tb->mark)
4782                 {
4783                         /* Display current position */
4784                         prt (format("(%d,%d)", tb->cx, tb->cy), 0, 60);
4785                 }
4786                 else
4787                 {
4788                         /* Display current position and mark position */
4789                         prt (format("(%d,%d)-(%d,%d)", tb->mx, tb->my, tb->cx, tb->cy), 0, 60);
4790                 }
4791
4792                 /* Place cursor */
4793                 Term_gotoxy(tb->cx - tb->left, tb->cy - tb->upper + 1);
4794
4795                 /* Now clean */
4796                 tb->dirty_flags = 0;
4797                 tb->dirty_line = -1;
4798
4799                 /* Save old key and location */
4800                 tb->old_cy = tb->cy;
4801                 tb->old_upper = tb->upper;
4802                 tb->old_left = tb->left;
4803                 tb->old_wid = tb->wid;
4804                 tb->old_hgt = tb->hgt;
4805
4806                 /* Get a command */
4807                 key = inkey();
4808
4809                 /* Count length of macro trigger which induced this key */
4810                 trig_len = strlen(inkey_macro_trigger_string);
4811
4812                 /* HACK -- ignore macro defined on ASCII keys */
4813                 if (trig_len == 1)
4814                 {
4815                         /* Get original key */
4816                         key = inkey_macro_trigger_string[0];
4817                 }
4818
4819                 /* Delete key */
4820                 if (key == 0x7F) key = KTRL('d');
4821
4822
4823                 /* Cursor key macroes to direction command */
4824                 if (trig_len > 1)
4825                 {
4826                         switch (key)
4827                         {
4828                         case '2':
4829                                 com_id = EC_DOWN;
4830                                 break;
4831                         case '4':
4832                                 com_id = EC_LEFT;
4833                                 break;
4834                         case '6':
4835                                 com_id = EC_RIGHT;
4836                                 break;
4837                         case '8':
4838                                 com_id = EC_UP;
4839                                 break;
4840                         }
4841
4842                         if (com_id)
4843                         {
4844                                 /*
4845                                  * Un-shifted cursor keys cancells
4846                                  * selection created by shift+cursor.
4847                                  */
4848                                 if (tb->mark & MARK_BY_SHIFT)
4849                                 {
4850                                         tb->mark = 0;
4851
4852                                         /* Now dirty */
4853                                         tb->dirty_flags |= DIRTY_ALL;
4854                                 }
4855                         }
4856
4857                         /* Mega Hack!!! Start selection with shift + cursor keys */
4858                         else
4859                         {
4860                                 char buf[1024];
4861
4862                                 /* Get ascii form */
4863                                 ascii_to_text(buf, inkey_macro_trigger_string);
4864
4865                                 if (strstr(buf, "shift-Down"))
4866                                         com_id = EC_DOWN;
4867                                 else if (strstr(buf, "shift-Left"))
4868                                         com_id = EC_LEFT;
4869                                 else if (strstr(buf, "shift-Right"))
4870                                         com_id = EC_RIGHT;
4871                                 else if (strstr(buf, "shift-Up"))
4872                                         com_id = EC_UP;
4873
4874                                 if (com_id)
4875                                 {
4876                                         /* Kill further macro expansion */
4877                                         flush();
4878
4879                                         /* Start selection */
4880                                         if (!tb->mark)
4881                                         {
4882                                                 int len = strlen(tb->lines_list[tb->cy]);
4883
4884                                                 tb->mark = MARK_MARK | MARK_BY_SHIFT;
4885                                                 tb->my = tb->cy;
4886                                                 tb->mx = tb->cx;
4887
4888                                                 /* Correct cursor location */
4889                                                 if (tb->cx > len) tb->mx = len;
4890                                                 
4891                                                 /* Need to redraw text */
4892                                                 if (com_id == EC_UP || com_id == EC_DOWN)
4893                                                 {
4894                                                         /* Redraw all text */
4895                                                         tb->dirty_flags |= DIRTY_ALL;
4896                                                 }
4897                                                 else
4898                                                 {
4899                                                         tb->dirty_line = tb->cy;
4900                                                 }
4901                                         }
4902                                 }
4903                         }
4904                 }
4905
4906                 if (com_id)
4907                 {
4908                         /* Already done */
4909                 }
4910
4911                 /* Open the menu */
4912                 else if (key == ESCAPE)
4913                 {
4914                         com_id = do_command_menu(0, 0);
4915
4916                         /* Redraw all text later */
4917                         tb->dirty_flags |= DIRTY_SCREEN;
4918                 }
4919
4920                 /* Insert a character */
4921                 else if (!iscntrl(key & 0xff))
4922                 {
4923                         /*
4924                          * If there is a selection, kill text, and
4925                          * replace it with a single letter.
4926                          */
4927                         if (tb->mark) kill_text_in_selection(tb);
4928
4929                         insert_single_letter(tb, key);
4930
4931                         /* Next loop */
4932                         continue;
4933                 }
4934
4935                 /* Other commands */
4936                 else
4937                 {
4938                         com_id = get_com_id(key);
4939                 }
4940
4941                 if (com_id) quit = do_editor_command(tb, com_id);
4942         } /* while (1) */
4943
4944         /* Restore the screen */
4945         screen_load();
4946
4947         switch (tb->filename_mode)
4948         {
4949         case PT_DEFAULT:
4950 #ifdef JP
4951                 strcpy(buf, "picktype.prf");
4952 #else
4953                 strcpy(buf, "pickpref.prf");
4954 #endif
4955                 break;
4956
4957         case PT_WITH_PNAME:
4958 #ifdef JP
4959                 sprintf(buf, "picktype-%s.prf", player_name);
4960 #else
4961                 sprintf(buf, "pickpref-%s.prf", player_name);
4962 #endif
4963                 break;
4964         }
4965
4966         write_text_lines(buf, tb->lines_list);
4967         free_text_lines(tb->lines_list);
4968
4969         string_free(tb->last_destroyed);
4970
4971         /* Destroy string chain */
4972         kill_yank_chain(tb);
4973
4974         /* Reload autopick pref */
4975         process_pickpref_file(buf);
4976
4977         /* HACK -- reset start_time so that playtime is not increase while edit */
4978         start_time = time(NULL);
4979 }