OSDN Git Service

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