OSDN Git Service

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