OSDN Git Service

自動拾いエディタの使用中にはプレイ時間のカウントが進まないようにした。
[hengband/hengband.git] / src / autopick.c
1 /* File: autopick.c */
2
3 /* Purpose: Object Auto-picker/Destroyer */
4
5 /*
6  * Copyright (c) 2002  Mogami
7  *
8  * This software may be copied and distributed for educational, research, and
9  * not for profit purposes provided that this copyright and statement are
10  * included in all such copies.
11  */
12
13 #include "angband.h"
14
15 #define MAX_LINELEN 1024
16
17 static object_type autopick_last_destroyed_object;
18
19 /*
20  * Macros for Keywords
21  */
22 #define FLG_ALL             0
23 #define FLG_COLLECTING      1
24 #define FLG_UNIDENTIFIED    2
25 #define FLG_IDENTIFIED      3
26 #define FLG_STAR_IDENTIFIED 4
27 #define FLG_BOOSTED         5
28 #define FLG_MORE_THAN       6
29 #define FLG_DICE            7
30 #define FLG_MORE_BONUS      8
31 #define FLG_MORE_BONUS2     9
32 #define FLG_WORTHLESS       10
33 #define FLG_ARTIFACT        11
34 #define FLG_EGO             12
35 #define FLG_NAMELESS        13
36 #define FLG_UNAWARE         14
37 #define FLG_WANTED          15
38 #define FLG_UNIQUE          16
39 #define FLG_HUMAN           17
40 #define FLG_UNREADABLE      18
41 #define FLG_REALM1          19
42 #define FLG_REALM2          20
43 #define FLG_FIRST           21
44 #define FLG_SECOND          22
45 #define FLG_THIRD           23
46 #define FLG_FOURTH          24
47
48 #define FLG_ITEMS           30
49 #define FLG_WEAPONS         31
50 #define FLG_ARMORS          32
51 #define FLG_MISSILES        33
52 #define FLG_DEVICES         34
53 #define FLG_LIGHTS          35
54 #define FLG_JUNKS           36
55 #define FLG_SPELLBOOKS      37
56 #define FLG_HAFTED          38
57 #define FLG_SHIELDS         39
58 #define FLG_BOWS            40
59 #define FLG_RINGS           41
60 #define FLG_AMULETS         42
61 #define FLG_SUITS           43
62 #define FLG_CLOAKS          44
63 #define FLG_HELMS           45
64 #define FLG_GLOVES          46
65 #define FLG_BOOTS           47
66
67 #ifdef JP
68
69 #define KEY_ALL "¤¹¤Ù¤Æ¤Î"
70 #define KEY_COLLECTING "¼ý½¸Ãæ¤Î"
71 #define KEY_UNIDENTIFIED "̤´ÕÄê¤Î"
72 #define KEY_IDENTIFIED "´ÕÄêºÑ¤ß¤Î"
73 #define KEY_STAR_IDENTIFIED "*´ÕÄê*ºÑ¤ß¤Î"
74 #define KEY_BOOSTED "¥À¥¤¥¹Ìܤΰ㤦"
75 #define KEY_MORE_THAN  "¥À¥¤¥¹ÌÜ"
76 #define KEY_DICE  "°Ê¾å¤Î"
77 #define KEY_MORE_BONUS  "½¤ÀµÃͤ¬"
78 #define KEY_MORE_BONUS2  "°Ê¾å¤Î"
79 #define KEY_WORTHLESS "̵²ÁÃͤÎ"
80 #define KEY_ARTIFACT "¥¢¡¼¥Æ¥£¥Õ¥¡¥¯¥È"
81 #define KEY_EGO "¥¨¥´"
82 #define KEY_NAMELESS "̵ÌäÎ"
83 #define KEY_UNAWARE "̤ȽÌÀ¤Î"
84 #define KEY_WANTED "¾Þ¶â¼ó¤Î"
85 #define KEY_UNIQUE "¥æ¥Ë¡¼¥¯¡¦¥â¥ó¥¹¥¿¡¼¤Î"
86 #define KEY_HUMAN "¿Í´Ö¤Î"
87 #define KEY_UNREADABLE "Æɤá¤Ê¤¤"
88 #define KEY_REALM1 "Âè°ìÎΰè¤Î"
89 #define KEY_REALM2 "ÂèÆóÎΰè¤Î"
90 #define KEY_FIRST "1ºýÌܤÎ"
91 #define KEY_SECOND "2ºýÌܤÎ"
92 #define KEY_THIRD "3ºýÌܤÎ"
93 #define KEY_FOURTH "4ºýÌܤÎ"
94 #define KEY_ITEMS "¥¢¥¤¥Æ¥à"
95 #define KEY_WEAPONS "Éð´ï"
96 #define KEY_ARMORS "Ëɶñ"
97 #define KEY_MISSILES "Ìð"
98 #define KEY_DEVICES "ËâË¡¥¢¥¤¥Æ¥à"
99 #define KEY_LIGHTS "¸÷¸»"
100 #define KEY_JUNKS "¤¬¤é¤¯¤¿"
101 #define KEY_SPELLBOOKS "ËâË¡½ñ"
102 #define KEY_HAFTED "Æß´ï"
103 #define KEY_SHIELDS "½â"
104 #define KEY_BOWS "µÝ"
105 #define KEY_RINGS "»ØÎØ"
106 #define KEY_AMULETS "¥¢¥ß¥å¥ì¥Ã¥È"
107 #define KEY_SUITS "³»"
108 #define KEY_CLOAKS "¥¯¥í¡¼¥¯"
109 #define KEY_HELMS "³õ"
110 #define KEY_GLOVES "äƼê"
111 #define KEY_BOOTS "·¤"
112
113 #else 
114
115 #define KEY_ALL "all"
116 #define KEY_COLLECTING "collecting"
117 #define KEY_UNIDENTIFIED "unidentified"
118 #define KEY_IDENTIFIED "identified"
119 #define KEY_STAR_IDENTIFIED "*identified*"
120 #define KEY_BOOSTED "dice boosted"
121 #define KEY_MORE_THAN  "more than"
122 #define KEY_DICE  " dice"
123 #define KEY_MORE_BONUS  "more bonus than"
124 #define KEY_MORE_BONUS2  ""
125 #define KEY_WORTHLESS "worthless"
126 #define KEY_ARTIFACT "artifact"
127 #define KEY_EGO "ego"
128 #define KEY_NAMELESS "nameless"
129 #define KEY_UNAWARE "unaware"
130 #define KEY_WANTED "wanted"
131 #define KEY_UNIQUE "unique monster's"
132 #define KEY_HUMAN "human"
133 #define KEY_UNREADABLE "unreadable"
134 #define KEY_REALM1 "first realm's"
135 #define KEY_REALM2 "second realm's"
136 #define KEY_FIRST "first"
137 #define KEY_SECOND "second"
138 #define KEY_THIRD "third"
139 #define KEY_FOURTH "fourth"
140 #define KEY_ITEMS "items"
141 #define KEY_WEAPONS "weapons"
142 #define KEY_ARMORS "armors"
143 #define KEY_MISSILES "missiles"
144 #define KEY_DEVICES "magical devices"
145 #define KEY_LIGHTS "lights"
146 #define KEY_JUNKS "junks"
147 #define KEY_SPELLBOOKS "spellbooks"
148 #define KEY_HAFTED "hafted weapons"
149 #define KEY_SHIELDS "shields"
150 #define KEY_BOWS "bows"
151 #define KEY_RINGS "rings"
152 #define KEY_AMULETS "amulets"
153 #define KEY_SUITS "suits"
154 #define KEY_CLOAKS "cloaks"
155 #define KEY_HELMS "helms"
156 #define KEY_GLOVES "gloves"
157 #define KEY_BOOTS "boots"
158
159 #endif /* JP */
160
161 #define MATCH_KEY(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\
162      ? (ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE)
163 #define MATCH_KEY2(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\
164      ? (prev_ptr = ptr, ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE)
165
166 #ifdef JP
167 #define ADD_KEY(KEY) strcat(ptr, KEY)
168 #else
169 #define ADD_KEY(KEY) (strcat(ptr, KEY), strcat(ptr, " "))
170 #endif
171 #define ADD_KEY2(KEY) strcat(ptr, KEY)
172
173 #define ADD_FLG(FLG) (entry->flag[FLG / 32] |= (1L << (FLG % 32)))
174 #define REM_FLG(FLG) (entry->flag[FLG / 32] &= ~(1L << (FLG % 32)))
175 #define ADD_FLG_NOUN(FLG) (ADD_FLG(FLG), prev_flg = FLG)
176 #define IS_FLG(FLG) (entry->flag[FLG / 32] & (1L << (FLG % 32)))
177
178 #ifdef JP
179         static char kanji_colon[] = "¡§";
180 #endif
181
182
183 /*
184  * Reconstruct preference line from entry
185  */
186 cptr autopick_line_from_entry(autopick_type *entry)
187 {
188         char buf[MAX_LINELEN];
189         char *ptr;
190         bool sepa_flag = TRUE;
191
192         *buf = '\0';
193         if (!(entry->action & DO_DISPLAY)) strcat(buf, "(");
194         if (entry->action & DO_AUTODESTROY) strcat(buf, "!");
195         if (entry->action & DONT_AUTOPICK) strcat(buf, "~");
196
197         ptr = buf;
198
199         if (IS_FLG(FLG_ALL)) ADD_KEY(KEY_ALL);
200         if (IS_FLG(FLG_COLLECTING)) ADD_KEY(KEY_COLLECTING);
201         if (IS_FLG(FLG_UNIDENTIFIED)) ADD_KEY(KEY_UNIDENTIFIED);
202         if (IS_FLG(FLG_IDENTIFIED)) ADD_KEY(KEY_IDENTIFIED);
203         if (IS_FLG(FLG_STAR_IDENTIFIED)) ADD_KEY(KEY_STAR_IDENTIFIED);
204         if (IS_FLG(FLG_UNAWARE)) ADD_KEY(KEY_UNAWARE);
205         if (IS_FLG(FLG_BOOSTED)) ADD_KEY(KEY_BOOSTED);
206
207         if (IS_FLG(FLG_MORE_THAN))
208         {
209                 ADD_KEY(KEY_MORE_THAN);
210                 strcat(ptr, format("%d", entry->dice));
211                 ADD_KEY(KEY_DICE);
212         }
213
214         if (IS_FLG(FLG_MORE_BONUS))
215         {
216                 ADD_KEY(KEY_MORE_BONUS);
217                 strcat(ptr, format("%d", entry->bonus));
218                 ADD_KEY(KEY_MORE_BONUS2);
219         }
220
221         if (IS_FLG(FLG_UNREADABLE)) ADD_KEY(KEY_UNREADABLE);
222         if (IS_FLG(FLG_REALM1)) ADD_KEY(KEY_REALM1);
223         if (IS_FLG(FLG_REALM2)) ADD_KEY(KEY_REALM2);
224         if (IS_FLG(FLG_FIRST)) ADD_KEY(KEY_FIRST);
225         if (IS_FLG(FLG_SECOND)) ADD_KEY(KEY_SECOND);
226         if (IS_FLG(FLG_THIRD)) ADD_KEY(KEY_THIRD);
227         if (IS_FLG(FLG_FOURTH)) ADD_KEY(KEY_FOURTH);
228         if (IS_FLG(FLG_WANTED)) ADD_KEY(KEY_WANTED);
229         if (IS_FLG(FLG_UNIQUE)) ADD_KEY(KEY_UNIQUE);
230         if (IS_FLG(FLG_HUMAN)) ADD_KEY(KEY_HUMAN);
231         if (IS_FLG(FLG_WORTHLESS)) ADD_KEY(KEY_WORTHLESS);
232         if (IS_FLG(FLG_NAMELESS)) ADD_KEY(KEY_NAMELESS);
233         if (IS_FLG(FLG_EGO)) ADD_KEY(KEY_EGO);
234
235         if (IS_FLG(FLG_ARTIFACT)) ADD_KEY(KEY_ARTIFACT);
236
237         if (IS_FLG(FLG_ITEMS)) ADD_KEY2(KEY_ITEMS);
238         else if (IS_FLG(FLG_WEAPONS)) ADD_KEY2(KEY_WEAPONS);
239         else if (IS_FLG(FLG_ARMORS)) ADD_KEY2(KEY_ARMORS);
240         else if (IS_FLG(FLG_MISSILES)) ADD_KEY2(KEY_MISSILES);
241         else if (IS_FLG(FLG_DEVICES)) ADD_KEY2(KEY_DEVICES);
242         else if (IS_FLG(FLG_LIGHTS)) ADD_KEY2(KEY_LIGHTS);
243         else if (IS_FLG(FLG_JUNKS)) ADD_KEY2(KEY_JUNKS);
244         else if (IS_FLG(FLG_SPELLBOOKS)) ADD_KEY2(KEY_SPELLBOOKS);
245         else if (IS_FLG(FLG_HAFTED)) ADD_KEY2(KEY_HAFTED);
246         else if (IS_FLG(FLG_SHIELDS)) ADD_KEY2(KEY_SHIELDS);
247         else if (IS_FLG(FLG_BOWS)) ADD_KEY2(KEY_BOWS);
248         else if (IS_FLG(FLG_RINGS)) ADD_KEY2(KEY_RINGS);
249         else if (IS_FLG(FLG_AMULETS)) ADD_KEY2(KEY_AMULETS);
250         else if (IS_FLG(FLG_SUITS)) ADD_KEY2(KEY_SUITS);
251         else if (IS_FLG(FLG_CLOAKS)) ADD_KEY2(KEY_CLOAKS);
252         else if (IS_FLG(FLG_HELMS)) ADD_KEY2(KEY_HELMS);
253         else if (IS_FLG(FLG_GLOVES)) ADD_KEY2(KEY_GLOVES);
254         else if (IS_FLG(FLG_BOOTS)) ADD_KEY2(KEY_BOOTS);
255
256         /* You don't need sepalator after adjective */
257         /* 'artifact' is not true adjective */
258         else if (!IS_FLG(FLG_ARTIFACT))
259                 sepa_flag = FALSE;
260
261         if (entry->name && entry->name[0])
262         {
263                 int i, j = 0;
264
265                 if (sepa_flag) strcat(buf, ":");
266
267                 i = strlen(buf);
268                 while (entry->name[j] && i < MAX_LINELEN - 2 - 1)
269                 {
270 #ifdef JP
271                         if (iskanji(entry->name[j]))
272                                 buf[i++] = entry->name[j++];
273 #endif
274                         buf[i++] = entry->name[j++];
275                 }
276                 buf[i] = '\0';
277         }
278
279         if (entry->insc)
280         {
281                 int i, j = 0;
282                 strcat(buf, "#");
283                 i = strlen(buf);
284
285                 while (entry->insc[j] && i < MAX_LINELEN - 2)
286                 {
287 #ifdef JP
288                         if (iskanji(entry->insc[j]))
289                                 buf[i++] = entry->insc[j++];
290 #endif
291                         buf[i++] = entry->insc[j++];
292                 }
293                 buf[i] = '\0';
294         }
295
296         return string_make(buf);
297 }
298
299
300 /*
301  * Reconstruct preference line from entry and kill entry
302  */
303 static cptr autopick_line_from_entry_kill(autopick_type *entry)
304 {
305         cptr ptr = autopick_line_from_entry(entry);
306
307         /* Free memory for original entry */
308         autopick_free_entry(entry);
309
310         return ptr;
311 }
312
313
314 /*
315  * A function to create new entry
316  */
317 bool autopick_new_entry(autopick_type *entry, cptr str)
318 {
319         cptr insc;
320         int i;
321         byte act = 0;
322         char buf[MAX_LINELEN];
323         cptr prev_ptr, ptr, old_ptr;
324         int prev_flg;
325
326         if (str[1] == ':') switch (str[0])
327         {
328         case '?': case '%':
329         case 'A': case 'P': case 'C':
330                 return FALSE;
331         }
332
333         entry->flag[0] = entry->flag[1] = 0L;
334         entry->dice = 0;
335
336         act = DO_AUTOPICK | DO_DISPLAY;
337         while (1)
338         {
339                 if ((act & DO_AUTOPICK) && *str == '!')
340                 {
341                         act &= ~DO_AUTOPICK;
342                         act |= DO_AUTODESTROY;
343                         str++;
344                 }
345                 else if ((act & DO_AUTOPICK) && *str == '~')
346                 {
347                         act &= ~DO_AUTOPICK;
348                         act |= DONT_AUTOPICK;
349                         str++;
350                 }
351                 else if ((act & DO_DISPLAY) && *str == '(')
352                 {
353                         act &= ~DO_DISPLAY;
354                         str++;
355                 }
356                 else
357                         break;
358         }
359
360         /* don't mind upper or lower case */
361         insc = NULL;
362         for (i = 0; *str; i++)
363         {
364                 char c = *str++;
365 #ifdef JP
366                 if (iskanji(c))
367                 {
368                         buf[i++] = c;
369                         buf[i] = *str++;
370                         continue;
371                 }
372 #endif
373                 /* Auto-inscription? */
374                 if (c == '#')
375                 {
376                         buf[i] = '\0';
377                         insc = str;
378                         break;
379                 }
380
381                 if (isupper(c)) c = tolower(c);
382
383                 buf[i] = c;
384         }
385         buf[i] = '\0';
386         
387         /* Skip empty line */
388         if (*buf == 0) return FALSE;
389
390         ptr = prev_ptr = buf;
391         old_ptr = NULL;
392
393         while (old_ptr != ptr)
394         {
395                 /* Save current location */
396                 old_ptr = ptr;
397
398                 if (MATCH_KEY(KEY_ALL)) ADD_FLG(FLG_ALL);
399                 if (MATCH_KEY(KEY_COLLECTING)) ADD_FLG(FLG_COLLECTING);
400                 if (MATCH_KEY(KEY_UNIDENTIFIED)) ADD_FLG(FLG_UNIDENTIFIED);
401                 if (MATCH_KEY(KEY_IDENTIFIED)) ADD_FLG(FLG_IDENTIFIED);
402                 if (MATCH_KEY(KEY_STAR_IDENTIFIED)) ADD_FLG(FLG_STAR_IDENTIFIED);
403                 if (MATCH_KEY(KEY_BOOSTED)) ADD_FLG(FLG_BOOSTED);
404
405                 /*** Weapons whose dd*ds is more than nn ***/
406                 if (MATCH_KEY2(KEY_MORE_THAN))
407                 {
408                         int k = 0;
409                         entry->dice = 0;
410
411                         /* Drop leading spaces */
412                         while (' ' == *ptr) ptr++;
413
414                         /* Read number */
415                         while (isdigit(*ptr))
416                         {
417                                 entry->dice = 10 * entry->dice + (*ptr - '0');
418                                 ptr++;
419                                 k++;
420                         }
421
422                         if (k > 0 && k <= 2)
423                         {
424                                 (void)MATCH_KEY(KEY_DICE);
425                                 ADD_FLG(FLG_MORE_THAN);
426                         }
427                         else
428                                 ptr = prev_ptr;
429                 }
430
431                 /*** Items whose magical bonus is more than n ***/
432                 if (MATCH_KEY2(KEY_MORE_BONUS))
433                 {
434                         int k = 0;
435                         entry->bonus = 0;
436
437                         /* Drop leading spaces */
438                         while (' ' == *ptr) ptr++;
439
440                         /* Read number */
441                         while (isdigit(*ptr))
442                         {
443                                 entry->bonus = 10 * entry->bonus + (*ptr - '0');
444                                 ptr++;
445                                 k++;
446                         }
447
448                         if (k > 0 && k <= 2)
449                         {
450                                 (void)MATCH_KEY(KEY_MORE_BONUS2);
451                                 ADD_FLG(FLG_MORE_BONUS);
452                         }
453                         else
454                                 ptr = prev_ptr;
455                 }
456
457                 if (MATCH_KEY(KEY_WORTHLESS)) ADD_FLG(FLG_WORTHLESS);
458                 if (MATCH_KEY(KEY_EGO)) ADD_FLG(FLG_EGO);
459                 if (MATCH_KEY(KEY_NAMELESS)) ADD_FLG(FLG_NAMELESS);
460                 if (MATCH_KEY(KEY_UNAWARE)) ADD_FLG(FLG_UNAWARE);
461                 if (MATCH_KEY(KEY_WANTED)) ADD_FLG(FLG_WANTED);
462                 if (MATCH_KEY(KEY_UNIQUE)) ADD_FLG(FLG_UNIQUE);
463                 if (MATCH_KEY(KEY_HUMAN)) ADD_FLG(FLG_HUMAN);
464                 if (MATCH_KEY(KEY_UNREADABLE)) ADD_FLG(FLG_UNREADABLE);
465                 if (MATCH_KEY(KEY_REALM1)) ADD_FLG(FLG_REALM1);
466                 if (MATCH_KEY(KEY_REALM2)) ADD_FLG(FLG_REALM2);
467                 if (MATCH_KEY(KEY_FIRST)) ADD_FLG(FLG_FIRST);
468                 if (MATCH_KEY(KEY_SECOND)) ADD_FLG(FLG_SECOND);
469                 if (MATCH_KEY(KEY_THIRD)) ADD_FLG(FLG_THIRD);
470                 if (MATCH_KEY(KEY_FOURTH)) ADD_FLG(FLG_FOURTH);
471         }
472
473         /* Not yet found any noun */
474         prev_flg = -1;
475
476         if (MATCH_KEY2(KEY_ARTIFACT)) ADD_FLG_NOUN(FLG_ARTIFACT);
477
478         if (MATCH_KEY2(KEY_ITEMS)) ADD_FLG_NOUN(FLG_ITEMS);
479         else if (MATCH_KEY2(KEY_WEAPONS)) ADD_FLG_NOUN(FLG_WEAPONS);
480         else if (MATCH_KEY2(KEY_ARMORS)) ADD_FLG_NOUN(FLG_ARMORS);
481         else if (MATCH_KEY2(KEY_MISSILES)) ADD_FLG_NOUN(FLG_MISSILES);
482         else if (MATCH_KEY2(KEY_DEVICES)) ADD_FLG_NOUN(FLG_DEVICES);
483         else if (MATCH_KEY2(KEY_LIGHTS)) ADD_FLG_NOUN(FLG_LIGHTS);
484         else if (MATCH_KEY2(KEY_JUNKS)) ADD_FLG_NOUN(FLG_JUNKS);
485         else if (MATCH_KEY2(KEY_SPELLBOOKS)) ADD_FLG_NOUN(FLG_SPELLBOOKS);
486         else if (MATCH_KEY2(KEY_HAFTED)) ADD_FLG_NOUN(FLG_HAFTED);
487         else if (MATCH_KEY2(KEY_SHIELDS)) ADD_FLG_NOUN(FLG_SHIELDS);
488         else if (MATCH_KEY2(KEY_BOWS)) ADD_FLG_NOUN(FLG_BOWS);
489         else if (MATCH_KEY2(KEY_RINGS)) ADD_FLG_NOUN(FLG_RINGS);
490         else if (MATCH_KEY2(KEY_AMULETS)) ADD_FLG_NOUN(FLG_AMULETS);
491         else if (MATCH_KEY2(KEY_SUITS)) ADD_FLG_NOUN(FLG_SUITS);
492         else if (MATCH_KEY2(KEY_CLOAKS)) ADD_FLG_NOUN(FLG_CLOAKS);
493         else if (MATCH_KEY2(KEY_HELMS)) ADD_FLG_NOUN(FLG_HELMS);
494         else if (MATCH_KEY2(KEY_GLOVES)) ADD_FLG_NOUN(FLG_GLOVES);
495         else if (MATCH_KEY2(KEY_BOOTS)) ADD_FLG_NOUN(FLG_BOOTS);
496
497         /* Last 'keyword' must be at the correct location */
498         if (*ptr == ':')
499                 ptr++;
500 #ifdef JP
501         else if (ptr[0] == kanji_colon[0] && ptr[1] == kanji_colon[1])
502                 ptr += 2;
503 #endif
504         else if (*ptr == '\0')
505                 ; /* nothing to do */
506         else
507         {
508                 /* Noun type? */
509                 if (prev_flg != -1)
510                 {
511                         /* A noun type keyword didn't end correctly */
512                         entry->flag[prev_flg/32] &= ~(1L<< (prev_flg%32));
513                         ptr = prev_ptr;
514                 }
515         }
516
517         /* Save this auto-picker entry line */
518         entry->name = string_make(ptr);
519         entry->action = act;
520         entry->insc = string_make(insc);
521
522         return TRUE;
523 }
524
525 /*
526  * A function to delete entry
527  */
528 void autopick_free_entry(autopick_type *entry)
529 {
530         string_free(entry->name);
531         string_free(entry->insc);
532 }
533
534
535 /*
536  * A function for Auto-picker/destroyer
537  * Examine whether the object matches to the entry
538  */
539 static bool is_autopick_aux(object_type *o_ptr, autopick_type *entry, cptr o_name)
540 {
541         int j;
542         cptr ptr = entry->name;
543
544         /*** Unidentified ***/
545         if (IS_FLG(FLG_UNIDENTIFIED)
546             && (object_known_p(o_ptr) || (o_ptr->ident & IDENT_SENSE)))
547                 return FALSE;
548
549         /*** Identified ***/
550         if (IS_FLG(FLG_IDENTIFIED) && !object_known_p(o_ptr))
551                 return FALSE;
552
553         /*** *Identified* ***/
554         if (IS_FLG(FLG_STAR_IDENTIFIED) &&
555             (!object_known_p(o_ptr) || !(o_ptr->ident & IDENT_MENTAL)))
556                 return FALSE;
557
558         /*** Dice boosted (weapon of slaying) ***/
559         if (IS_FLG(FLG_BOOSTED))
560         {
561                 object_kind *k_ptr = &k_info[o_ptr->k_idx];
562                         
563                 switch( o_ptr->tval )
564                 {
565                 case TV_HAFTED:
566                 case TV_POLEARM:
567                 case TV_SWORD:
568                 case TV_DIGGING:
569                         if ((o_ptr->dd != k_ptr->dd) || (o_ptr->ds != k_ptr->ds))
570                                 break;
571                         else
572                                 return FALSE;
573                 default:
574                         return FALSE;
575                 }
576         }
577
578         /*** Weapons whic dd*ds is more than nn ***/
579         if (IS_FLG(FLG_MORE_THAN))
580         {
581                 if (o_ptr->dd * o_ptr->ds < entry->dice)
582                         return FALSE;
583         }
584                                 
585         /*** Weapons whic dd*ds is more than nn ***/
586         if (IS_FLG(FLG_MORE_BONUS))
587         {
588                 if (!object_known_p(o_ptr)) return FALSE;
589
590                 if (k_info[o_ptr->k_idx].pval ||
591                     (o_ptr->name2 && e_info[o_ptr->name2].max_pval))
592                 {
593                         if (o_ptr->pval < entry->bonus) return FALSE;
594                 }
595                 else
596                 {
597                         if (o_ptr->to_h < entry->bonus &&
598                             o_ptr->to_d < entry->bonus &&
599                             o_ptr->to_a < entry->bonus &&
600                             o_ptr->pval < entry->bonus)
601                                 return FALSE;
602                 }
603         }
604                                 
605         /*** Worthless items ***/
606         if (IS_FLG(FLG_WORTHLESS) && object_value(o_ptr) > 0)
607                 return FALSE;
608
609         /*** Artifact object ***/
610         if (IS_FLG(FLG_ARTIFACT))
611         {
612                 if (!object_known_p(o_ptr) || (!o_ptr->name1 && !o_ptr->art_name))
613                         return FALSE;
614         }
615
616         /*** Ego object ***/
617         if (IS_FLG(FLG_EGO))
618         {
619                 if (!object_known_p(o_ptr) || !o_ptr->name2)
620                         return FALSE;
621         }
622
623         /*** Nameless ***/
624         if (IS_FLG(FLG_NAMELESS))
625         {
626                 switch (o_ptr->tval)
627                 {
628                 case TV_WHISTLE:
629                 case TV_SHOT: case TV_ARROW: case TV_BOLT: case TV_BOW:
630                 case TV_DIGGING: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: 
631                 case TV_BOOTS: case TV_GLOVES: case TV_HELM: case TV_CROWN:
632                 case TV_SHIELD: case TV_CLOAK:
633                 case TV_SOFT_ARMOR: case TV_HARD_ARMOR: case TV_DRAG_ARMOR:
634                 case TV_LITE: case TV_AMULET: case TV_RING: case TV_CARD:
635                         if ((!object_known_p(o_ptr) || o_ptr->inscription
636                              || o_ptr->name1 || o_ptr->name2 || o_ptr->art_name))
637                                 return FALSE;
638                         break;
639                 default:
640                         /* don't match */
641                         return FALSE;
642                 }
643         }
644
645         /*** Unaware items ***/
646         if (IS_FLG(FLG_UNAWARE) && object_aware_p(o_ptr))
647                 return FALSE;
648
649         /*** Wanted monster's corpse/skeletons ***/
650         if (IS_FLG(FLG_WANTED) &&
651             (o_ptr->tval != TV_CORPSE || !object_is_shoukinkubi(o_ptr)))
652                 return FALSE;
653
654         /*** Unique monster's corpse/skeletons/statues ***/
655         if (IS_FLG(FLG_UNIQUE) &&
656             ((o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_STATUE) ||
657              !(r_info[o_ptr->pval].flags1 & RF1_UNIQUE)))
658                 return FALSE;
659
660         /*** Human corpse/skeletons (for Daemon magic) ***/
661         if (IS_FLG(FLG_HUMAN) &&
662             (o_ptr->tval != TV_CORPSE ||
663              !strchr("pht", r_info[o_ptr->pval].d_char)))
664                 return FALSE;
665
666         /*** Unreadable spellbooks ***/
667         if (IS_FLG(FLG_UNREADABLE) &&
668             (o_ptr->tval < TV_LIFE_BOOK ||
669              check_book_realm(o_ptr->tval, o_ptr->sval)))
670                 return FALSE;
671
672         /*** First realm spellbooks ***/
673         if (IS_FLG(FLG_REALM1) && 
674             (REALM1_BOOK != o_ptr->tval ||
675              p_ptr->pclass == CLASS_SORCERER ||
676              p_ptr->pclass == CLASS_RED_MAGE))
677                 return FALSE;
678
679         /*** Second realm spellbooks ***/
680         if (IS_FLG(FLG_REALM2) &&
681             (REALM2_BOOK != o_ptr->tval ||
682              p_ptr->pclass == CLASS_SORCERER ||
683              p_ptr->pclass == CLASS_RED_MAGE))
684                 return FALSE;
685
686         /*** First rank spellbooks ***/
687         if (IS_FLG(FLG_FIRST) &&
688             (o_ptr->tval < TV_LIFE_BOOK || 0 != o_ptr->sval))
689                 return FALSE;
690
691         /*** Second rank spellbooks ***/
692         if (IS_FLG(FLG_SECOND) &&
693             (o_ptr->tval < TV_LIFE_BOOK || 1 != o_ptr->sval))
694                 return FALSE;
695
696         /*** Third rank spellbooks ***/
697         if (IS_FLG(FLG_THIRD) && 
698             (o_ptr->tval < TV_LIFE_BOOK || 2 != o_ptr->sval))
699                 return FALSE;
700
701         /*** Fourth rank spellbooks ***/
702         if (IS_FLG(FLG_FOURTH) &&
703             (o_ptr->tval < TV_LIFE_BOOK || 3 != o_ptr->sval))
704                 return FALSE;
705
706         /*** Items ***/
707         if (IS_FLG(FLG_WEAPONS))
708         {
709                 switch(o_ptr->tval)
710                 {
711                 case TV_BOW: case TV_HAFTED: case TV_POLEARM:
712                 case TV_SWORD: case TV_DIGGING:
713                         break;
714                 default: return FALSE;
715                 }
716         }
717         else if (IS_FLG(FLG_ARMORS))
718         {
719                 switch(o_ptr->tval)
720                 {
721                 case TV_BOOTS: case TV_GLOVES: case TV_CLOAK: case TV_CROWN:
722                 case TV_HELM: case TV_SHIELD: case TV_SOFT_ARMOR:
723                 case TV_HARD_ARMOR: case TV_DRAG_ARMOR:
724                         break;
725                 default: return FALSE;
726                 }
727         }
728         else if (IS_FLG(FLG_MISSILES))
729         {
730                 switch(o_ptr->tval)
731                 {
732                 case TV_SHOT: case TV_BOLT: case TV_ARROW:
733                         break;
734                 default: return FALSE;
735                 }
736         }
737         else if (IS_FLG(FLG_DEVICES))
738         {
739                 switch(o_ptr->tval)
740                 {
741                 case TV_SCROLL: case TV_STAFF: case TV_WAND: case TV_ROD:
742                         break;
743                 default: return FALSE;
744                 }
745         }
746         else if (IS_FLG(FLG_LIGHTS))
747         {
748                 if (!(o_ptr->tval == TV_LITE))
749                         return FALSE;
750         }
751         else if (IS_FLG(FLG_JUNKS))
752         {
753                 switch(o_ptr->tval)
754                 {
755                 case TV_SKELETON: case TV_BOTTLE:
756                 case TV_JUNK: case TV_STATUE:
757                         break;
758                 default: return FALSE;
759                 }
760         }
761         else if (IS_FLG(FLG_SPELLBOOKS))
762         {
763                 if (!(o_ptr->tval >= TV_LIFE_BOOK))
764                         return FALSE;
765         }
766         else if (IS_FLG(FLG_HAFTED))
767         {
768                 if (!(o_ptr->tval == TV_HAFTED))
769                         return FALSE;
770         }
771         else if (IS_FLG(FLG_SHIELDS))
772         {
773                 if (!(o_ptr->tval == TV_SHIELD))
774                         return FALSE;
775         }
776         else if (IS_FLG(FLG_BOWS))
777         {
778                 if (!(o_ptr->tval == TV_BOW))
779                         return FALSE;
780         }
781         else if (IS_FLG(FLG_RINGS))
782         {
783                 if (!(o_ptr->tval == TV_RING))
784                         return FALSE;
785         }
786         else if (IS_FLG(FLG_AMULETS))
787         {
788                 if (!(o_ptr->tval == TV_AMULET))
789                         return FALSE;
790         }
791         else if (IS_FLG(FLG_SUITS))
792         {
793                 if (!(o_ptr->tval == TV_DRAG_ARMOR ||
794                       o_ptr->tval == TV_HARD_ARMOR ||
795                       o_ptr->tval == TV_SOFT_ARMOR))
796                         return FALSE;
797         }
798         else if (IS_FLG(FLG_CLOAKS))
799         {
800                 if (!(o_ptr->tval == TV_CLOAK))
801                         return FALSE;
802         }
803         else if (IS_FLG(FLG_HELMS))
804         {
805                 if (!(o_ptr->tval == TV_CROWN || o_ptr->tval == TV_HELM))
806                         return FALSE;
807         }
808         else if (IS_FLG(FLG_GLOVES))
809         {
810                 if (!(o_ptr->tval == TV_GLOVES))
811                         return FALSE;
812         }
813         else if (IS_FLG(FLG_BOOTS))
814         {
815                 if (!(o_ptr->tval == TV_BOOTS))
816                         return FALSE;
817         }
818
819         /* Keyword don't match */
820         if (*ptr == '^')
821         {
822                 ptr++;
823                 if (strncmp(o_name, ptr, strlen(ptr))) return FALSE;
824         }
825         else
826         {
827 #ifdef JP
828                 if (!strstr_j(o_name, ptr)) return FALSE;
829 #else
830                 if (!strstr(o_name, ptr)) return FALSE;
831 #endif
832         }
833
834         /* TRUE when it need not to be 'collecting' */
835         if (!IS_FLG(FLG_COLLECTING)) return TRUE;
836
837         /* Check if there is a same item */
838         for (j = 0; j < INVEN_PACK; j++)
839         {
840                 /*
841                  * 'Collecting' means the item must be absorbed 
842                  * into an inventory slot.
843                  * But an item can not be absorbed into itself!
844                  */
845                 if ((&inventory[j] != o_ptr) &&
846                     object_similar(&inventory[j], o_ptr))
847                         return TRUE;
848         }
849
850         /* Not collecting */
851         return FALSE;
852 }
853
854
855 /*
856  * A function for Auto-picker/destroyer
857  * Examine whether the object matches to the list of keywords or not.
858  */
859 int is_autopick(object_type *o_ptr)
860 {
861         int i;
862         char o_name[MAX_NLEN];
863
864         if (o_ptr->tval == TV_GOLD) return -1;
865         
866         object_desc(o_name, o_ptr, FALSE, 3);
867
868         /* Force to be lower case string */
869         for (i = 0; o_name[i]; i++)
870         {
871 #ifdef JP
872                 if (iskanji(o_name[i]))
873                         i++;
874                 else
875 #endif
876                 if (isupper(o_name[i]))
877                         o_name[i] = tolower(o_name[i]);
878         }
879         
880         for (i=0; i < max_autopick; i++)
881         {
882                 autopick_type *entry = &autopick_list[i];
883
884                 if (is_autopick_aux(o_ptr, entry, o_name)) return i;
885         }
886
887         /* No matching entry */
888         return -1;
889 }
890
891
892 /*
893  * Automatically destroy items in this grid.
894  */
895 static bool is_opt_confirm_destroy(object_type *o_ptr)
896 {
897         if (!destroy_items) return FALSE;
898
899         /* Known to be worthless? */
900         if (leave_worth)
901                 if (object_value(o_ptr) > 0) return FALSE;
902         
903         if (leave_equip)
904                 if ((o_ptr->tval >= TV_SHOT) && (o_ptr->tval <= TV_DRAG_ARMOR)) return FALSE;
905         
906         if (leave_chest)
907                 if ((o_ptr->tval == TV_CHEST) && o_ptr->pval) return FALSE;
908         
909         if (leave_wanted)
910         {
911                 if (o_ptr->tval == TV_CORPSE
912                     && object_is_shoukinkubi(o_ptr)) return FALSE;
913         }
914         
915         if (leave_corpse)
916                 if (o_ptr->tval == TV_CORPSE) return FALSE;
917         
918         if (leave_junk)
919                 if ((o_ptr->tval == TV_SKELETON) || (o_ptr->tval == TV_BOTTLE) || (o_ptr->tval == TV_JUNK) || (o_ptr->tval == TV_STATUE)) return FALSE;
920         
921         if (o_ptr->tval == TV_GOLD) return FALSE;
922         
923         return TRUE;
924 }
925
926
927 /*
928  *  Auto inscription
929  */
930 void auto_inscribe_item(int item, int idx)
931 {
932         object_type *o_ptr;
933
934         /* Get the item (in the pack) */
935         if (item >= 0) o_ptr = &inventory[item];
936
937         /* Get the item (on the floor) */
938         else o_ptr = &o_list[0 - item];
939
940         /* Auto-inscription or Re-inscribe for resistances {%} */
941         if ((idx < 0 || !autopick_list[idx].insc) && !o_ptr->inscription)
942                 return;
943
944         if (o_ptr->inscription)
945                 o_ptr->inscription = inscribe_flags(o_ptr, quark_str(o_ptr->inscription));
946         else
947                 o_ptr->inscription = inscribe_flags(o_ptr, autopick_list[idx].insc);
948
949         if (item > INVEN_PACK)
950         {
951                 /* Redraw inscription */
952                 p_ptr->window |= (PW_EQUIP);
953
954                 /* {.} and {$} effect p_ptr->warning and TRC_TELEPORT_SELF */
955                 p_ptr->update |= (PU_BONUS);
956         }
957         else if (item >= 0)
958         {
959                 /* Redraw inscription */
960                 p_ptr->window |= (PW_INVEN);
961         }
962 }
963
964
965 /*
966  * Automatically destroy an item if it is to be destroyed
967  */
968 bool auto_destroy_item(int item, int autopick_idx, bool wait_optimize)
969 {
970         bool destroy = FALSE;
971         char o_name[MAX_NLEN];
972         object_type *o_ptr;
973
974         /* Don't destroy equipped items */
975         if (item > INVEN_PACK) return FALSE;
976
977         /* Get the item (in the pack) */
978         if (item >= 0) o_ptr = &inventory[item];
979
980         /* Get the item (on the floor) */
981         else o_ptr = &o_list[0 - item];
982
983         /* Easy-Auto-Destroyer */
984         if (is_opt_confirm_destroy(o_ptr)) destroy = TRUE;
985
986         /* Protected by auto-picker */
987         if (autopick_idx >= 0 &&
988             !(autopick_list[autopick_idx].action & DO_AUTODESTROY))
989                 destroy = FALSE;
990
991         if (!always_pickup)
992         {
993                 /* Auto-picker/destroyer */
994                 if (autopick_idx >= 0 &&
995                     (autopick_list[autopick_idx].action & DO_AUTODESTROY))
996                         destroy = TRUE;
997         }
998
999         /* Not to be destroyed */
1000         if (!destroy) return FALSE;
1001
1002         /* Now decided to destroy */
1003
1004         disturb(0,0);
1005
1006         /* Describe the object (with {terrible/special}) */
1007         object_desc(o_name, o_ptr, TRUE, 3);
1008
1009         /* Artifact? */
1010         if (!can_player_destroy_object(o_ptr))
1011         {
1012                 /* Message */
1013 #ifdef JP
1014                 msg_format("%s¤ÏÇ˲õÉÔǽ¤À¡£", o_name);
1015 #else
1016                 msg_format("You cannot auto-destroy %s.", o_name);
1017 #endif
1018
1019                 /* Done */
1020                 return TRUE;
1021         }
1022
1023         /* Record name of destroyed item */
1024         COPY(&autopick_last_destroyed_object, o_ptr, object_type);
1025
1026         /* Eliminate the item (from the pack) */
1027         if (item >= 0)
1028         {
1029                 inven_item_increase(item, -(o_ptr->number));
1030
1031                 /*
1032                  * always optimize equipment.
1033                  * optimize inventry only when wait_optimize is FALSE.
1034                  */
1035                 if (!wait_optimize || item > INVEN_PACK)
1036                         inven_item_optimize(item);
1037         }
1038
1039         /* Eliminate the item (from the floor) */
1040         else
1041         {
1042                 delete_object_idx(0 - item);
1043         }
1044
1045         /* Print a message */
1046 #ifdef JP
1047         msg_format("%s¤ò¼«Æ°Ç˲õ¤·¤Þ¤¹¡£", o_name);
1048 #else
1049         msg_format("Auto-destroying %s.", o_name);
1050 #endif
1051                         
1052         return TRUE;
1053 }
1054
1055
1056 /*
1057  * Optimize all inventry items after consumption of staves or scrolls.
1058  */
1059 void optimize_inventry_auto_destroy(void)
1060 {
1061         int i;
1062
1063         for (i = 0; i <= INVEN_PACK; i++)
1064                 inven_item_optimize(i);
1065 }
1066
1067
1068 /*
1069  * Automatically pickup/destroy items in this grid.
1070  */
1071 void auto_pickup_items(cave_type *c_ptr)
1072 {
1073         s16b this_o_idx, next_o_idx = 0;
1074         
1075         /* Scan the pile of objects */
1076         for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1077         {
1078                 int idx;
1079         
1080                 /* Acquire object */
1081                 object_type *o_ptr = &o_list[this_o_idx];
1082                 
1083                 /* Acquire next object */
1084                 next_o_idx = o_ptr->next_o_idx;
1085
1086                 idx = is_autopick(o_ptr);
1087
1088                 /* Item index for floor -1,-2,-3,...  */
1089                 auto_inscribe_item((-this_o_idx), idx);
1090
1091                 if (idx >= 0 && (autopick_list[idx].action & DO_AUTOPICK))
1092                 {
1093                         disturb(0,0);
1094
1095                         if (!inven_carry_okay(o_ptr))
1096                         {
1097                                 char o_name[MAX_NLEN];
1098
1099                                 /* Describe the object */
1100                                 object_desc(o_name, o_ptr, TRUE, 3);
1101
1102                                 /* Message */
1103 #ifdef JP
1104                                 msg_format("¥¶¥Ã¥¯¤Ë¤Ï%s¤òÆþ¤ì¤ë·ä´Ö¤¬¤Ê¤¤¡£", o_name);
1105 #else
1106                                 msg_format("You have no room for %s.", o_name);
1107 #endif
1108                                 continue;
1109                         }
1110                         py_pickup_aux(this_o_idx);
1111
1112                         continue;
1113                 }
1114                 
1115                 /*
1116                  * Do auto-destroy;
1117                  * When always_pickup is 'yes', we disable
1118                  * auto-destroyer from autopick function, and do only
1119                  * easy-auto-destroyer.
1120                  */
1121                 else
1122                 {
1123                         if (auto_destroy_item((-this_o_idx), idx, FALSE))
1124                                 continue;
1125                 }
1126         }
1127 }
1128
1129
1130 /*
1131  * Describe which kind of object is Auto-picked/destroyed
1132  */
1133 static void describe_autopick(char *buff, autopick_type *entry)
1134 {
1135         cptr str = entry->name;
1136         byte act = entry->action;
1137         cptr insc = entry->insc;
1138         int i;
1139
1140         bool top = FALSE;
1141
1142 #ifdef JP
1143         cptr before_str[100], body_str;
1144         int before_n = 0;
1145
1146         body_str = "¥¢¥¤¥Æ¥à";
1147
1148         /*** Collecting items ***/
1149         /*** Which can be absorbed into a slot as a bundle ***/
1150         if (IS_FLG(FLG_COLLECTING))
1151                 before_str[before_n++] = "¼ý½¸Ãæ¤Ç´û¤Ë»ý¤Ã¤Æ¤¤¤ë¥¹¥í¥Ã¥È¤Ë¤Þ¤È¤á¤é¤ì¤ë";
1152         
1153         /*** Unidentified ***/
1154         if (IS_FLG(FLG_UNIDENTIFIED))
1155                 before_str[before_n++] = "̤´ÕÄê¤Î";
1156
1157         /*** Identified ***/
1158         if (IS_FLG(FLG_IDENTIFIED))
1159                 before_str[before_n++] = "´ÕÄêºÑ¤ß¤Î";
1160
1161         /*** *Identified* ***/
1162         if (IS_FLG(FLG_STAR_IDENTIFIED))
1163                 before_str[before_n++] = "´°Á´¤Ë´ÕÄêºÑ¤ß¤Î";
1164
1165         /*** Dice boosted (weapon of slaying) ***/
1166         if (IS_FLG(FLG_BOOSTED))
1167         {
1168                 before_str[before_n++] = "¥À¥á¡¼¥¸¥À¥¤¥¹¤¬Ä̾ï¤è¤êÂ礭¤¤";
1169                 body_str = "Éð´ï";
1170         }
1171
1172         /*** Weapons whose dd*ds is more than nn ***/
1173         if (IS_FLG(FLG_MORE_THAN))
1174         {
1175                 static char more_than_desc_str[] = "___";
1176                 before_str[before_n++] = "¥À¥á¡¼¥¸¥À¥¤¥¹¤ÎºÇÂçÃͤ¬";
1177                 body_str = "Éð´ï";
1178                         
1179                 sprintf(more_than_desc_str,"%d", entry->dice);
1180                 before_str[before_n++] = more_than_desc_str;
1181                 before_str[before_n++] = "°Ê¾å¤Î";
1182         }
1183
1184         /*** Items whose magical bonus is more than nn ***/
1185         if (IS_FLG(FLG_MORE_BONUS))
1186         {
1187                 static char more_bonus_desc_str[] = "___";
1188                 before_str[before_n++] = "½¤ÀµÃͤ¬(+";
1189                         
1190                 sprintf(more_bonus_desc_str,"%d", entry->bonus);
1191                 before_str[before_n++] = more_bonus_desc_str;
1192                 before_str[before_n++] = ")°Ê¾å¤Î";
1193         }
1194
1195         /*** Worthless items ***/
1196         if (IS_FLG(FLG_WORTHLESS))
1197                 before_str[before_n++] = "Ź¤Ç̵²ÁÃͤÈȽÄꤵ¤ì¤ë";
1198
1199         /*** Artifact ***/
1200         if (IS_FLG(FLG_ARTIFACT))
1201         {
1202                 before_str[before_n++] = "¥¢¡¼¥Æ¥£¥Õ¥¡¥¯¥È¤Î";
1203                 body_str = "ÁõÈ÷";
1204         }
1205
1206         /*** Ego ***/
1207         if (IS_FLG(FLG_EGO))
1208         {
1209                 before_str[before_n++] = "¥¨¥´¥¢¥¤¥Æ¥à¤Î";
1210                 body_str = "ÁõÈ÷";
1211         }
1212
1213         /*** Nameless ***/
1214         if (IS_FLG(FLG_NAMELESS))
1215         {
1216                 before_str[before_n++] = "¥¨¥´¤Ç¤â¥¢¡¼¥Æ¥£¥Õ¥¡¥¯¥È¤Ç¤â¤Ê¤¤";
1217                 body_str = "ÁõÈ÷";
1218         }
1219
1220         /*** Unaware items ***/
1221         if (IS_FLG(FLG_UNAWARE))
1222                 before_str[before_n++] = "̤´ÕÄê¤Ç¤½¤Î¸ú²Ì¤âȽÌÀ¤·¤Æ¤¤¤Ê¤¤";
1223
1224         /*** Wanted monster's corpse/skeletons ***/
1225         if (IS_FLG(FLG_WANTED))
1226         {
1227                 before_str[before_n++] = "¥Ï¥ó¥¿¡¼»ö̳½ê¤Ç¾Þ¶â¼ó¤È¤µ¤ì¤Æ¤¤¤ë";
1228                 body_str = "»àÂΤä¹ü";
1229         }
1230
1231         /*** Human corpse/skeletons (for Daemon magic) ***/
1232         if (IS_FLG(FLG_HUMAN))
1233         {
1234                 before_str[before_n++] = "°­ËâËâË¡¤Ç»È¤¦¤¿¤á¤Î¿Í´Ö¤ä¥Ò¥å¡¼¥Þ¥Î¥¤¥É¤Î";
1235                 body_str = "»àÂΤä¹ü";
1236         }
1237
1238         /*** Unique monster's corpse/skeletons/statues ***/
1239         if (IS_FLG(FLG_UNIQUE))
1240         {
1241                 before_str[before_n++] = "¥æ¥Ë¡¼¥¯¥â¥ó¥¹¥¿¡¼¤Î";
1242                 body_str = "»àÂΤä¹ü";
1243         }
1244
1245         /*** Unreadable spellbooks ***/
1246         if (IS_FLG(FLG_UNREADABLE))
1247         {
1248                 before_str[before_n++] = "¤¢¤Ê¤¿¤¬Æɤá¤Ê¤¤Îΰè¤Î";
1249                 body_str = "ËâË¡½ñ";
1250         }
1251
1252         /*** First realm spellbooks ***/
1253         if (IS_FLG(FLG_REALM1))
1254         {
1255                 before_str[before_n++] = "Âè°ìÎΰè¤Î";
1256                 body_str = "ËâË¡½ñ";
1257         }
1258
1259         /*** Second realm spellbooks ***/
1260         if (IS_FLG(FLG_REALM2))
1261         {
1262                 before_str[before_n++] = "ÂèÆóÎΰè¤Î";
1263                 body_str = "ËâË¡½ñ";
1264         }
1265
1266         /*** First rank spellbooks ***/
1267         if (IS_FLG(FLG_FIRST))
1268         {
1269                 before_str[before_n++] = "Á´4ºý¤ÎÆâ¤Î1ºýÌܤÎ";
1270                 body_str = "ËâË¡½ñ";
1271         }
1272
1273         /*** Second rank spellbooks ***/
1274         if (IS_FLG(FLG_SECOND))
1275         {
1276                 before_str[before_n++] = "Á´4ºý¤ÎÆâ¤Î2ºýÌܤÎ";
1277                 body_str = "ËâË¡½ñ";
1278         }
1279
1280         /*** Third rank spellbooks ***/
1281         if (IS_FLG(FLG_THIRD))
1282         {
1283                 before_str[before_n++] = "Á´4ºý¤ÎÆâ¤Î3ºýÌܤÎ";
1284                 body_str = "ËâË¡½ñ";
1285         }
1286
1287         /*** Fourth rank spellbooks ***/
1288         if (IS_FLG(FLG_FOURTH))
1289         {
1290                 before_str[before_n++] = "Á´4ºý¤ÎÆâ¤Î4ºýÌܤÎ";
1291                 body_str = "ËâË¡½ñ";
1292         }
1293
1294         /*** Items ***/
1295         if (IS_FLG(FLG_ITEMS))
1296                 ; /* Nothing to do */
1297         else if (IS_FLG(FLG_WEAPONS))
1298                 body_str = "Éð´ï";
1299         else if (IS_FLG(FLG_ARMORS))
1300                 body_str = "Ëɶñ";
1301         else if (IS_FLG(FLG_MISSILES))
1302                 body_str = "ÃƤäÌð¤ä¥¯¥í¥¹¥Ü¥¦¤ÎÌð";
1303         else if (IS_FLG(FLG_DEVICES))
1304                 body_str = "´¬Êª¤äËâË¡ËÀ¤ä¾ó¤ä¥í¥Ã¥É";
1305         else if (IS_FLG(FLG_LIGHTS))
1306                 body_str = "¸÷¸»ÍѤΥ¢¥¤¥Æ¥à";
1307         else if (IS_FLG(FLG_JUNKS))
1308                 body_str = "Àޤ줿ËÀÅù¤Î¥¬¥é¥¯¥¿";
1309         else if (IS_FLG(FLG_SPELLBOOKS))
1310                 body_str = "ËâË¡½ñ";
1311         else if (IS_FLG(FLG_HAFTED))
1312                 body_str = "Æß´ï";
1313         else if (IS_FLG(FLG_SHIELDS))
1314                 body_str = "½â";
1315         else if (IS_FLG(FLG_BOWS))
1316                 body_str = "¥¹¥ê¥ó¥°¤äµÝ¤ä¥¯¥í¥¹¥Ü¥¦";
1317         else if (IS_FLG(FLG_RINGS))
1318                 body_str = "»ØÎØ";
1319         else if (IS_FLG(FLG_AMULETS))
1320                 body_str = "¥¢¥ß¥å¥ì¥Ã¥È";
1321         else if (IS_FLG(FLG_SUITS))
1322                 body_str = "³»";
1323         else if (IS_FLG(FLG_CLOAKS))
1324                 body_str = "¥¯¥í¡¼¥¯";
1325         else if (IS_FLG(FLG_HELMS))
1326                 body_str = "¥Ø¥ë¥á¥Ã¥È¤ä´§";
1327         else if (IS_FLG(FLG_GLOVES))
1328                 body_str = "äƼê";
1329         else if (IS_FLG(FLG_BOOTS))
1330                 body_str = "¥Ö¡¼¥Ä";
1331
1332         *buff = '\0';
1333         if (!before_n) 
1334                 strcat(buff, "Á´¤Æ¤Î");
1335         else for (i = 0; i < before_n && before_str[i]; i++)
1336                 strcat(buff, before_str[i]);
1337
1338         strcat(buff, body_str);
1339
1340         if (*str)
1341         {
1342                 if (*str == '^')
1343                 {
1344                         str++;
1345                         top = TRUE;
1346                 }
1347
1348                 strcat(buff, "¤Ç¡¢Ì¾Á°¤¬¡Ö");
1349                 strncat(buff, str, 80);
1350                 if (top)
1351                         strcat(buff, "¡×¤Ç»Ï¤Þ¤ë¤â¤Î");
1352                 else
1353                         strcat(buff, "¡×¤ò´Þ¤à¤â¤Î");
1354         }
1355
1356         if (insc)
1357         {
1358                 strncat(buff, format("¤Ë¡Ö%s¡×", insc), 80);
1359
1360                 if (strstr(insc, "%%all"))
1361                         strcat(buff, "(%%all¤ÏÁ´Ç½ÎϤòɽ¤¹±Ñ»ú¤Îµ­¹æ¤ÇÃÖ´¹)");
1362                 else if (strstr(insc, "%all"))
1363                         strcat(buff, "(%all¤ÏÁ´Ç½ÎϤòɽ¤¹µ­¹æ¤ÇÃÖ´¹)");
1364                 else if (strstr(insc, "%%"))
1365                         strcat(buff, "(%%¤ÏÄɲÃǽÎϤòɽ¤¹±Ñ»ú¤Îµ­¹æ¤ÇÃÖ´¹)");
1366                 else if (strstr(insc, "%"))
1367                         strcat(buff, "(%¤ÏÄɲÃǽÎϤòɽ¤¹µ­¹æ¤ÇÃÖ´¹)");
1368
1369                 strcat(buff, "¤È¹ï¤ó¤Ç");
1370         }
1371         else
1372                 strcat(buff, "¤ò");
1373
1374         if (act & DONT_AUTOPICK)
1375                 strcat(buff, "ÊüÃÖ¤¹¤ë¡£");
1376         else if (act & DO_AUTODESTROY)
1377                 strcat(buff, "Ç˲õ¤¹¤ë¡£");
1378         else
1379                 strcat(buff, "½¦¤¦¡£");
1380
1381         if (act & DO_DISPLAY)
1382         {
1383                 if (act & DONT_AUTOPICK)
1384                         strcat(buff, "Á´ÂΥޥå×('M')¤Ç'N'¤ò²¡¤·¤¿¤È¤­¤Ëɽ¼¨¤¹¤ë¡£");
1385                 else if (act & DO_AUTODESTROY)
1386                         strcat(buff, "Á´ÂΥޥå×('M')¤Ç'K'¤ò²¡¤·¤¿¤È¤­¤Ëɽ¼¨¤¹¤ë¡£");
1387                 else
1388                         strcat(buff, "Á´ÂΥޥå×('M')¤Ç'M'¤ò²¡¤·¤¿¤È¤­¤Ëɽ¼¨¤¹¤ë¡£");
1389         }
1390         else
1391                 strcat(buff, "Á´ÂΥޥåפˤÏɽ¼¨¤·¤Ê¤¤");
1392
1393 #else /* JP */
1394
1395         cptr before_str[20], after_str[20], which_str[20], whose_str[20], body_str;
1396         int before_n = 0, after_n = 0, which_n = 0, whose_n = 0;
1397
1398         body_str = "items";
1399
1400         /*** Collecting items ***/
1401         /*** Which can be absorbed into a slot as a bundle ***/
1402         if (IS_FLG(FLG_COLLECTING))
1403                 which_str[which_n++] = "can be absorbed into an existing inventory slot";
1404         
1405         /*** Unidentified ***/
1406         if (IS_FLG(FLG_UNIDENTIFIED))
1407                 before_str[before_n++] = "unidentified";
1408
1409         /*** Identified ***/
1410         if (IS_FLG(FLG_IDENTIFIED))
1411                 before_str[before_n++] = "identified";
1412
1413         /*** *Identified* ***/
1414         if (IS_FLG(FLG_STAR_IDENTIFIED))
1415                 before_str[before_n++] = "fully identified";
1416
1417         /*** Worthless items ***/
1418         if (IS_FLG(FLG_WORTHLESS))
1419         {
1420                 before_str[before_n++] = "worthless";
1421                 which_str[which_n++] = "can not be sold at stores";
1422         }
1423
1424         /*** Artifacto ***/
1425         if (IS_FLG(FLG_ARTIFACT))
1426         {
1427                 before_str[before_n++] = "artifact";
1428         }
1429
1430         /*** Ego ***/
1431         if (IS_FLG(FLG_EGO))
1432         {
1433                 before_str[before_n++] = "ego";
1434         }
1435
1436         /*** Nameless ***/
1437         if (IS_FLG(FLG_NAMELESS))
1438         {
1439                 body_str = "equipment";
1440                 which_str[which_n++] = "is neither ego-item nor artifact";
1441         }
1442
1443         /*** Unaware items ***/
1444         if (IS_FLG(FLG_UNAWARE))
1445         {
1446                 before_str[before_n++] = "unidentified";
1447                 whose_str[whose_n++] = "basic abilities are not known";
1448         }
1449
1450         /*** Dice boosted (weapon of slaying) ***/
1451         if (IS_FLG(FLG_BOOSTED))
1452         {
1453                 body_str = "weapons";
1454                 whose_str[whose_n++] = "damage dice is bigger than normal";
1455         }
1456
1457         /*** Weapons whose dd*ds is more than nn ***/
1458         if (IS_FLG(FLG_MORE_THAN))
1459         {
1460                 static char more_than_desc_str[] =
1461                         "maximum damage from dice is bigger than __";
1462                 body_str = "weapons";
1463                         
1464                 sprintf(more_than_desc_str + sizeof(more_than_desc_str) - 3,
1465                         "%d", entry->dice);
1466                 whose_str[whose_n++] = more_than_desc_str;
1467         }
1468
1469         /*** Items whose magical bonus is more than nn ***/
1470         if (IS_FLG(FLG_MORE_BONUS))
1471         {
1472                 static char more_bonus_desc_str[] =
1473                         "magical bonus is bigger than (+__)";
1474                         
1475                 sprintf(more_bonus_desc_str + sizeof(more_bonus_desc_str) - 4,
1476                         "%d)", entry->bonus);
1477                 whose_str[whose_n++] = more_bonus_desc_str;
1478         }
1479
1480         /*** Wanted monster's corpse/skeletons ***/
1481         if (IS_FLG(FLG_WANTED))
1482         {
1483                 body_str = "corpse or skeletons";
1484                 which_str[which_n++] = "is wanted at the Hunter's Office";
1485         }
1486
1487         /*** Human corpse/skeletons (for Daemon magic) ***/
1488         if (IS_FLG(FLG_HUMAN))
1489         {
1490                 before_str[before_n++] = "humanoid";
1491                 body_str = "corpse or skeletons";
1492                 which_str[which_n++] = "can be used for Daemon magic";
1493         }
1494
1495         /*** Unique monster's corpse/skeletons/statues ***/
1496         if (IS_FLG(FLG_UNIQUE))
1497         {
1498                 before_str[before_n++] = "unique monster's";
1499                 body_str = "corpse or skeletons";
1500         }
1501
1502         /*** Unreadable spellbooks ***/
1503         if (IS_FLG(FLG_UNREADABLE))
1504         {
1505                 body_str = "spellbooks";
1506                 after_str[after_n++] = "of different realms from yours";
1507         }
1508
1509         /*** First realm spellbooks ***/
1510         if (IS_FLG(FLG_REALM1))
1511         {
1512                 body_str = "spellbooks";
1513                 after_str[after_n++] = "of your first realm";
1514         }
1515
1516         /*** Second realm spellbooks ***/
1517         if (IS_FLG(FLG_REALM2))
1518         {
1519                 body_str = "spellbooks";
1520                 after_str[after_n++] = "of your second realm";
1521         }
1522
1523         /*** First rank spellbooks ***/
1524         if (IS_FLG(FLG_FIRST))
1525         {
1526                 before_str[before_n++] = "first one of four";
1527                 body_str = "spellbooks";
1528         }
1529
1530         /*** Second rank spellbooks ***/
1531         if (IS_FLG(FLG_SECOND))
1532         {
1533                 before_str[before_n++] = "second one of four";
1534                 body_str = "spellbooks";
1535         }
1536
1537         /*** Third rank spellbooks ***/
1538         if (IS_FLG(FLG_THIRD))
1539         {
1540                 before_str[before_n++] = "third one of four";
1541                 body_str = "spellbooks";
1542         }
1543
1544         /*** Fourth rank spellbooks ***/
1545         if (IS_FLG(FLG_FOURTH))
1546         {
1547                 before_str[before_n++] = "fourth one of four";
1548                 body_str = "spellbooks";
1549         }
1550
1551         /*** Items ***/
1552         if (IS_FLG(FLG_ITEMS))
1553                 ; /* Nothing to do */
1554         else if (IS_FLG(FLG_WEAPONS))
1555                 body_str = "weapons";
1556         else if (IS_FLG(FLG_ARMORS))
1557                 body_str = "armors";
1558         else if (IS_FLG(FLG_MISSILES))
1559                 body_str = "shots, arrows or crossbow bolts";
1560         else if (IS_FLG(FLG_DEVICES))
1561                 body_str = "scrolls, wands, staves or rods";
1562         else if (IS_FLG(FLG_LIGHTS))
1563                 body_str = "light sources";
1564         else if (IS_FLG(FLG_JUNKS))
1565                 body_str = "junk such as broken sticks";
1566         else if (IS_FLG(FLG_SPELLBOOKS))
1567                 body_str = "spellbooks";
1568         else if (IS_FLG(FLG_HAFTED))
1569                 body_str = "hafted weapons";
1570         else if (IS_FLG(FLG_SHIELDS))
1571                 body_str = "shields";
1572         else if (IS_FLG(FLG_BOWS))
1573                 body_str = "slings, bows or crossbows";
1574         else if (IS_FLG(FLG_RINGS))
1575                 body_str = "rings";
1576         else if (IS_FLG(FLG_AMULETS))
1577                 body_str = "amulets";
1578         else if (IS_FLG(FLG_SUITS))
1579                 body_str = "body armors";
1580         else if (IS_FLG(FLG_CLOAKS))
1581                 body_str = "cloaks";
1582         else if (IS_FLG(FLG_HELMS))
1583                 body_str = "helms or crowns";
1584         else if (IS_FLG(FLG_GLOVES))
1585                 body_str = "gloves";
1586         else if (IS_FLG(FLG_BOOTS))
1587                 body_str = "boots";
1588
1589         /* Prepare a string for item name */
1590         if (*str)
1591         {
1592                 if (*str == '^')
1593                 {
1594                         str++;
1595                         top = TRUE;
1596                         whose_str[whose_n++] = "name is beginning with \"";
1597                 }
1598                 else
1599                         which_str[which_n++] = "have \"";
1600         }
1601
1602
1603         /* Describe action flag */
1604         if (act & DONT_AUTOPICK)
1605                 strcpy(buff, "Leave on floor ");
1606         else if (act & DO_AUTODESTROY)
1607                 strcpy(buff, "Destroy ");
1608         else
1609                 strcpy(buff, "Pickup ");
1610
1611         /* Auto-insctiption */
1612         if (insc)
1613         {
1614                 strncat(buff, format("and inscribe \"%s\"", insc), 80);
1615
1616                 if (strstr(insc, "%all"))
1617                         strcat(buff, ", replacing %all with code string representing all abilities,");
1618                 else if (strstr(insc, "%"))
1619                         strcat(buff, ", replacing % with code string representing extra random abilities,");
1620
1621                 strcat(buff, " on ");
1622         }
1623
1624         /* Adjective */
1625         if (!before_n) 
1626                 strcat(buff, "all ");
1627         else for (i = 0; i < before_n && before_str[i]; i++)
1628         {
1629                 strcat(buff, before_str[i]);
1630                 strcat(buff, " ");
1631         }
1632
1633         /* Item class */
1634         strcat(buff, body_str);
1635
1636         /* of ... */
1637         for (i = 0; i < after_n && after_str[i]; i++)
1638         {
1639                 strcat(buff, " ");
1640                 strcat(buff, after_str[i]);
1641         }
1642
1643         /* which ... */
1644         for (i = 0; i < whose_n && whose_str[i]; i++)
1645         {
1646                 if (i == 0)
1647                         strcat(buff, " whose ");
1648                 else
1649                         strcat(buff, ", and ");
1650
1651                 strcat(buff, whose_str[i]);
1652         }
1653
1654         /* Item name ; whose name is beginning with "str" */
1655         if (*str && top)
1656         {
1657                 strcat(buff, str);
1658                 strcat(buff, "\"");
1659         }
1660
1661         /* whose ..., and which .... */
1662         if (whose_n && which_n)
1663                 strcat(buff, ", and ");
1664
1665         /* which ... */
1666         for (i = 0; i < which_n && which_str[i]; i++)
1667         {
1668                 if (i == 0)
1669                         strcat(buff, " which ");
1670                 else
1671                         strcat(buff, ", and ");
1672
1673                 strcat(buff, which_str[i]);
1674         }
1675
1676         /* Item name ; which have "str" as part of its name */
1677         if (*str && !top)
1678         {
1679                 strncat(buff, str, 80);
1680                 strcat(buff, "\" as part of its name");
1681         }
1682         strcat(buff, ".");
1683
1684         /* Describe whether it will be displayed on the full map or not */
1685         if (act & DO_DISPLAY)
1686         {
1687                 if (act & DONT_AUTOPICK)
1688                         strcat(buff, "  Display these items when you press the N key in the full 'M'ap.");
1689                 else if (act & DO_AUTODESTROY)
1690                         strcat(buff, "  Display these items when you press the K key in the full 'M'ap.");
1691                 else
1692                         strcat(buff, "  Display these items when you press the M key in the full 'M'ap.");
1693         }
1694         else
1695                 strcat(buff, " Not displayed in the full map.");
1696 #endif /* JP */
1697
1698 }
1699
1700
1701 #define MAX_LINES 3000
1702
1703 /*
1704  * Read whole lines of a file to memory
1705  */
1706 static cptr *read_text_lines(cptr filename, bool user)
1707 {
1708         cptr *lines_list = NULL;
1709         FILE *fff;
1710
1711         int lines = 0;
1712         char buf[1024];
1713
1714         if (user)
1715         {
1716                 /* Hack -- drop permissions */
1717                 safe_setuid_drop();
1718                 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
1719         }
1720         else
1721         {
1722                 path_build(buf, sizeof(buf), ANGBAND_DIR_PREF, filename);
1723         }
1724         
1725         /* Open the file */
1726         fff = my_fopen(buf, "r");
1727
1728         if (fff)
1729         {
1730                 /* Allocate list of pointers */
1731                 C_MAKE(lines_list, MAX_LINES, cptr);
1732
1733                 /* Parse it */
1734                 while (0 == my_fgets(fff, buf, sizeof(buf)))
1735                 {
1736                         lines_list[lines++] = string_make(buf);
1737                         if (lines >= MAX_LINES - 1) break;
1738                 }
1739                 if (lines == 0)
1740                         lines_list[0] = string_make("");
1741
1742                 my_fclose(fff);
1743         }
1744
1745         /* Grab priv's */
1746         safe_setuid_grab();
1747
1748         if (!fff) return NULL;
1749         return lines_list;
1750 }
1751
1752
1753 #define PT_DEFAULT 0
1754 #define PT_WITH_PNAME 1
1755
1756 static cptr *read_pickpref_text_lines(int *filename_mode_p)
1757 {
1758         char buf[1024];
1759         cptr *lines_list;
1760
1761 #ifdef JP
1762         sprintf(buf, "picktype-%s.prf", player_name);
1763 #else
1764         sprintf(buf, "pickpref-%s.prf", player_name);
1765 #endif
1766         lines_list = read_text_lines(buf, TRUE);
1767
1768         if (!lines_list)
1769         {
1770 #ifdef JP
1771                 lines_list = read_text_lines("picktype.prf", TRUE);
1772 #else
1773                 lines_list = read_text_lines("pickpref.prf", TRUE);
1774 #endif
1775                 *filename_mode_p = PT_DEFAULT;
1776         }
1777
1778         if (!lines_list)
1779         {
1780 #ifdef JP
1781                 lines_list = read_text_lines("picktype.prf", FALSE);
1782 #else
1783                 lines_list = read_text_lines("pickpref.prf", FALSE);
1784 #endif
1785                 *filename_mode_p = PT_WITH_PNAME;
1786         }
1787
1788         if (!lines_list)
1789         {
1790                 /* Allocate list of pointers */
1791                 C_MAKE(lines_list, MAX_LINES, cptr);
1792                 lines_list[0] = string_make("");
1793                 *filename_mode_p = PT_WITH_PNAME;
1794         }
1795         return lines_list;
1796 }
1797
1798 /*
1799  * Write whole lines of memory to a file.
1800  */
1801 static bool write_text_lines(cptr filename, cptr *lines_list)
1802 {
1803         FILE *fff;
1804
1805         int lines = 0;
1806         char buf[1024];
1807
1808         /* Hack -- drop permissions */
1809         safe_setuid_drop();
1810
1811         /* Build the filename */
1812         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
1813         
1814         /* Open the file */
1815         fff = my_fopen(buf, "w");
1816         if (fff)
1817         {
1818                 for (lines = 0; lines_list[lines]; lines++)
1819                         my_fputs(fff, lines_list[lines], 1024);
1820
1821                 my_fclose(fff);
1822         }
1823
1824         /* Grab priv's */
1825         safe_setuid_grab();
1826
1827         if (!fff) return FALSE;
1828         return TRUE;
1829 }
1830
1831
1832 /*
1833  * Free memory of lines_list.
1834  */
1835 static void free_text_lines(cptr *lines_list)
1836 {
1837         int lines;
1838
1839         for (lines = 0; lines_list[lines]; lines++)
1840                 string_free(lines_list[lines]);
1841
1842         /* free list of pointers */
1843         C_FREE((char **)lines_list, MAX_LINES, char *);
1844 }
1845
1846
1847 /*
1848  * Delete or insert string
1849  */
1850 static void toggle_string(cptr *lines_list, int flg, int y)
1851 {
1852         autopick_type an_entry, *entry = &an_entry;
1853
1854         if (!autopick_new_entry(entry, lines_list[y]))
1855                 return;
1856
1857         string_free(lines_list[y]);
1858         if (IS_FLG(flg)) 
1859                 REM_FLG(flg);
1860         else
1861                 ADD_FLG(flg);
1862
1863         lines_list[y] = autopick_line_from_entry_kill(entry);
1864 }
1865
1866 /*
1867  * Insert return code and split the line
1868  */
1869 static bool insert_return_code(cptr *lines_list, int cx, int cy)
1870 {
1871         char buf[MAX_LINELEN];
1872         int i, j, k;
1873
1874         for (k = 0; lines_list[k]; k++)
1875                 /* count number of lines */ ;
1876
1877         if (k >= MAX_LINES - 2) return FALSE;
1878         k--;
1879
1880         /* Move down lines */
1881         for (; cy < k; k--)
1882                 lines_list[k+1] = lines_list[k];
1883
1884         /* Split current line */
1885         for (i = j = 0; lines_list[cy][i] && i < cx; i++)
1886         {
1887 #ifdef JP
1888                 if (iskanji(lines_list[cy][i]))
1889                         buf[j++] = lines_list[cy][i++];
1890 #endif
1891                 buf[j++] = lines_list[cy][i];
1892         }
1893         buf[j] = '\0';
1894         lines_list[cy+1] = string_make(&lines_list[cy][i]);
1895         string_free(lines_list[cy]);
1896         lines_list[cy] = string_make(buf);
1897         return TRUE;
1898 }
1899
1900
1901 /*
1902  * Get auto-picker entry from o_ptr.
1903  */
1904 void autopick_entry_from_object(autopick_type *entry, object_type *o_ptr)
1905 {
1906         char o_name[MAX_NLEN];
1907         object_desc(o_name, o_ptr, FALSE, 0);
1908
1909         entry->name = string_make(o_name);
1910         entry->insc = string_make(quark_str(o_ptr->inscription));
1911         entry->action = DO_AUTOPICK | DO_DISPLAY;
1912         entry->flag[0] = entry->flag[1] = 0L;
1913         entry->dice = 0;
1914
1915         if (!object_aware_p(o_ptr))
1916                 ADD_FLG(FLG_UNAWARE);
1917         if (object_value(o_ptr) <= 0)
1918                 ADD_FLG(FLG_WORTHLESS);
1919
1920         if (object_known_p(o_ptr))
1921         {
1922                 if (o_ptr->name2)
1923                         ADD_FLG(FLG_EGO);
1924                 else if (o_ptr->name1 || o_ptr->art_name)
1925                         ADD_FLG(FLG_ARTIFACT);
1926         }
1927
1928         switch(o_ptr->tval)
1929         {
1930                 object_kind *k_ptr; 
1931         case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_DIGGING:
1932                 k_ptr = &k_info[o_ptr->k_idx];
1933                 if ((o_ptr->dd != k_ptr->dd) || (o_ptr->ds != k_ptr->ds))
1934                         ADD_FLG(FLG_BOOSTED);
1935         }
1936
1937         if (o_ptr->tval == TV_CORPSE && object_is_shoukinkubi(o_ptr))
1938         {
1939                 REM_FLG(FLG_WORTHLESS);
1940                 ADD_FLG(FLG_WANTED);
1941         }
1942
1943         if ((o_ptr->tval == TV_CORPSE || o_ptr->tval == TV_STATUE)
1944             && (r_info[o_ptr->pval].flags1 & RF1_UNIQUE))
1945         {
1946                 REM_FLG(FLG_WORTHLESS);
1947                 ADD_FLG(FLG_UNIQUE);
1948         }
1949
1950         if (o_ptr->tval == TV_CORPSE && strchr("pht", r_info[o_ptr->pval].d_char))
1951         {
1952                 REM_FLG(FLG_WORTHLESS);
1953                 ADD_FLG(FLG_HUMAN);
1954         }
1955
1956         if (o_ptr->tval >= TV_LIFE_BOOK &&
1957             !check_book_realm(o_ptr->tval, o_ptr->sval))
1958                 ADD_FLG(FLG_UNREADABLE);
1959
1960         if (REALM1_BOOK == o_ptr->tval &&
1961             p_ptr->pclass != CLASS_SORCERER &&
1962             p_ptr->pclass != CLASS_RED_MAGE)
1963                 ADD_FLG(FLG_REALM1);
1964
1965         if (REALM2_BOOK == o_ptr->tval &&
1966             p_ptr->pclass != CLASS_SORCERER &&
1967             p_ptr->pclass != CLASS_RED_MAGE)
1968                 ADD_FLG(FLG_REALM2);
1969
1970         if (o_ptr->tval >= TV_LIFE_BOOK && 0 == o_ptr->sval)
1971                 ADD_FLG(FLG_FIRST);
1972         if (o_ptr->tval >= TV_LIFE_BOOK && 1 == o_ptr->sval)
1973                 ADD_FLG(FLG_SECOND);
1974         if (o_ptr->tval >= TV_LIFE_BOOK && 2 == o_ptr->sval)
1975                 ADD_FLG(FLG_THIRD);
1976         if (o_ptr->tval >= TV_LIFE_BOOK && 3 == o_ptr->sval)
1977                 ADD_FLG(FLG_FOURTH);
1978
1979         if (o_ptr->tval == TV_SHOT || o_ptr->tval == TV_BOLT
1980                  || o_ptr->tval == TV_ARROW)
1981                 ADD_FLG(FLG_MISSILES);
1982         else if (o_ptr->tval == TV_SCROLL || o_ptr->tval == TV_STAFF
1983                  || o_ptr->tval == TV_WAND || o_ptr->tval == TV_ROD)
1984                 ADD_FLG(FLG_DEVICES);
1985         else if (o_ptr->tval == TV_LITE)
1986                 ADD_FLG(FLG_LIGHTS);
1987         else if (o_ptr->tval == TV_SKELETON || o_ptr->tval == TV_BOTTLE
1988                  || o_ptr->tval == TV_JUNK || o_ptr->tval == TV_STATUE)
1989                 ADD_FLG(FLG_JUNKS);
1990         else if (o_ptr->tval >= TV_LIFE_BOOK)
1991                 ADD_FLG(FLG_SPELLBOOKS);
1992         else if (o_ptr->tval == TV_HAFTED)
1993                 ADD_FLG(FLG_HAFTED);
1994         else if (o_ptr->tval == TV_POLEARM || o_ptr->tval == TV_SWORD
1995                  || o_ptr->tval == TV_DIGGING)
1996                 ADD_FLG(FLG_WEAPONS);
1997         else if (o_ptr->tval == TV_SHIELD)
1998                 ADD_FLG(FLG_SHIELDS);
1999         else if (o_ptr->tval == TV_BOW)
2000                 ADD_FLG(FLG_BOWS);
2001         else if (o_ptr->tval == TV_RING)
2002                 ADD_FLG(FLG_RINGS);
2003         else if (o_ptr->tval == TV_AMULET)
2004                 ADD_FLG(FLG_AMULETS);
2005         else if (o_ptr->tval == TV_DRAG_ARMOR || o_ptr->tval == TV_HARD_ARMOR ||
2006                  o_ptr->tval == TV_SOFT_ARMOR)
2007                 ADD_FLG(FLG_SUITS);
2008         else if (o_ptr->tval == TV_CLOAK)
2009                 ADD_FLG(FLG_CLOAKS);
2010         else if (o_ptr->tval == TV_HELM)
2011                 ADD_FLG(FLG_HELMS);
2012         else if (o_ptr->tval == TV_GLOVES)
2013                 ADD_FLG(FLG_GLOVES);
2014         else if (o_ptr->tval == TV_BOOTS)
2015                 ADD_FLG(FLG_BOOTS);
2016
2017         return;
2018 }
2019
2020
2021 /*
2022  * Choose an item and get auto-picker entry from it.
2023  */
2024 static object_type *choose_object(cptr q, cptr s)
2025 {
2026         int item;
2027
2028         if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EQUIP))) return NULL;
2029
2030         /* Get the item (in the pack) */
2031         if (item >= 0) return &inventory[item];
2032
2033         /* Get the item (on the floor) */
2034         else return &o_list[0 - item];
2035 }
2036
2037
2038 /*
2039  * Choose an item and get auto-picker entry from it.
2040  */
2041 static bool entry_from_choosed_object(autopick_type *entry)
2042 {
2043         object_type *o_ptr;
2044         cptr q, s;
2045
2046         /* Get an item */
2047 #ifdef JP
2048         q = "¤É¤Î¥¢¥¤¥Æ¥à¤òÅÐÏ¿¤·¤Þ¤¹¤«? ";
2049         s = "¥¢¥¤¥Æ¥à¤ò»ý¤Ã¤Æ¤¤¤Ê¤¤¡£";
2050 #else
2051         q = "Entry which item? ";
2052         s = "You have nothing to entry.";
2053 #endif
2054         o_ptr = choose_object(q, s);
2055         if (!o_ptr) return FALSE;
2056
2057         autopick_entry_from_object(entry, o_ptr);
2058         return TRUE;
2059 }
2060
2061
2062 /*
2063  * Choose an item or string for search
2064  */
2065 static bool get_string_for_search(object_type **o_handle, cptr *search_strp)
2066 {
2067         int pos = 0;
2068         cptr q, s;
2069         char buf[MAX_NLEN+20];
2070
2071 #ifdef JP
2072         int k_flag[MAX_NLEN+20];
2073         char prompt[] = "¸¡º÷(^I:»ý¤Áʪ ^L:Ç˲õ¤µ¤ì¤¿Êª): ";
2074 #else
2075         char prompt[] = "Search key(^I:inven ^L:destroyed): ";
2076 #endif
2077         int col = sizeof(prompt) - 1;
2078
2079         if (*search_strp) strcpy(buf, *search_strp);
2080         else buf[0] = '\0';
2081
2082         /* Display prompt */
2083         prt(prompt, 0, 0);
2084
2085         /* Display the default answer */
2086         Term_erase(col, 0, 255);
2087         Term_putstr(col, 0, -1, TERM_YELLOW, buf);
2088
2089         /* Process input */
2090         while (1)
2091         {
2092                 object_type *o_ptr;
2093                 int i;
2094
2095                 /* Place cursor */
2096                 Term_gotoxy(col + pos, 0);
2097
2098                 /* Do not process macros except special keys */
2099                 inkey_special = TRUE;
2100
2101                 /* Get a key */
2102                 i = inkey();
2103
2104                 /* Analyze the key */
2105                 switch (i)
2106                 {
2107                 case ESCAPE:
2108                         pos = 0;
2109                         return FALSE;
2110
2111                 case '\n':
2112                 case '\r':
2113                         if (!pos && *o_handle) return TRUE;
2114                         string_free(*search_strp);
2115                         *search_strp = string_make(buf);
2116                         *o_handle = NULL;
2117                         return TRUE;
2118
2119                 case KTRL('i'):
2120                         /* Get an item */
2121 #ifdef JP
2122                         q = "¤É¤Î¥¢¥¤¥Æ¥à¤ò¸¡º÷¤·¤Þ¤¹¤«? ";
2123                         s = "¥¢¥¤¥Æ¥à¤ò»ý¤Ã¤Æ¤¤¤Ê¤¤¡£";
2124 #else
2125                         q = "Entry which item? ";
2126                         s = "You have nothing to entry.";
2127 #endif
2128                         o_ptr = choose_object(q, s);
2129                         if (!o_ptr) return FALSE;
2130
2131                         *o_handle = o_ptr;
2132
2133                         string_free(*search_strp);
2134                         object_desc(buf, *o_handle, FALSE, 3);
2135                         *search_strp = string_make(format("<%s>", buf));
2136                         return TRUE;
2137
2138                 case KTRL('l'):
2139                         if (!autopick_last_destroyed_object.k_idx) break;
2140                         *o_handle = &autopick_last_destroyed_object;
2141
2142                         string_free(*search_strp);
2143                         object_desc(buf, *o_handle, FALSE, 3);
2144                         *search_strp = string_make(format("<%s>", buf));
2145                         return TRUE;
2146
2147                 case 0x7F:
2148                 case '\010':
2149 #ifdef JP
2150                         if (pos > 0)
2151                         {
2152                                 pos--;
2153                                 if (k_flag[pos]) pos--;
2154                         }
2155 #else
2156                         if (pos > 0) pos--;
2157 #endif
2158                         break;
2159
2160                 default:
2161 #ifdef JP
2162                         if (iskanji(i))
2163                         {
2164                                 int next;
2165
2166                                 inkey_base = TRUE;
2167                                 next = inkey ();
2168                                 if (pos + 1 < MAX_NLEN)
2169                                 {
2170                                         buf[pos++] = i;
2171                                         buf[pos] = next;
2172                                         k_flag[pos++] = 1;
2173                                 }
2174                                 else bell();
2175                         }
2176                         else if (pos < MAX_NLEN && isprint(i))
2177                         {
2178                                 buf[pos] = i;
2179                                 k_flag[pos++] = 0;
2180                         }
2181                         else bell();
2182 #else
2183                         if (pos < MAX_NLEN && isprint(i)) buf[pos++] = i;
2184                         else bell();
2185 #endif
2186                         break;
2187                 }
2188
2189                 /* Terminate */
2190                 buf[pos] = '\0';
2191
2192                 /* Update the entry */
2193                 Term_erase(col, 0, 255);
2194                 Term_putstr(col, 0, -1, TERM_WHITE, buf);
2195         }
2196
2197         /* Never reached */
2198 }
2199
2200
2201 /*
2202  * Search next line matches for o_ptr
2203  */
2204 static bool search_for_object(cptr *lines_list, object_type *o_ptr, int *cxp, int *cyp, bool forward)
2205 {
2206         int i;
2207         autopick_type an_entry, *entry = &an_entry;
2208         char o_name[MAX_NLEN];
2209
2210         object_desc(o_name, o_ptr, FALSE, 3);
2211
2212         /* Force to be lower case string */
2213         for (i = 0; o_name[i]; i++)
2214         {
2215 #ifdef JP
2216                 if (iskanji(o_name[i]))
2217                         i++;
2218                 else
2219 #endif
2220                 if (isupper(o_name[i]))
2221                         o_name[i] = tolower(o_name[i]);
2222         }
2223         
2224         i = *cyp;
2225
2226         while (1)
2227         {
2228                 if (forward)
2229                 {
2230                         if (!lines_list[++i]) break;
2231                 }
2232                 else
2233                 {
2234                         if (--i < 0) break;
2235                 }
2236
2237                 if (!autopick_new_entry(entry, lines_list[i])) continue;
2238
2239                 if (is_autopick_aux(o_ptr, entry, o_name))
2240                 {
2241                         *cxp = 0;
2242                         *cyp = i;
2243                         return TRUE;
2244                 }
2245         }
2246
2247         return FALSE;
2248 }
2249
2250
2251 /*
2252  * Search next line matches to the string
2253  */
2254 static bool search_for_string(cptr *lines_list, cptr search_str, int *cxp, int *cyp, bool forward)
2255 {
2256         int i = *cyp;
2257
2258         while (1)
2259         {
2260                 cptr pos;
2261
2262                 if (forward)
2263                 {
2264                         if (!lines_list[++i]) break;
2265                 }
2266                 else
2267                 {
2268                         if (--i < 0) break;
2269                 }
2270 #ifdef JP
2271                 pos = strstr_j(lines_list[i], search_str);
2272 #else
2273                 pos = strstr(lines_list[i], search_str);
2274 #endif
2275                 if (pos)
2276                 {
2277                         *cxp = (int)(pos - lines_list[i]);
2278                         *cyp = i;
2279                         return TRUE;
2280                 }
2281         }
2282
2283         return FALSE;
2284 }
2285
2286
2287 /*
2288  * Initialize auto-picker preference
2289  */
2290 void init_autopicker(void)
2291 {
2292         static const char easy_autopick_inscription[] = "(:=g";
2293         autopick_type entry;
2294         int i;
2295
2296         /* Clear old entries */
2297         for( i = 0; i < max_autopick; i++)
2298                 autopick_free_entry(&autopick_list[i]);
2299
2300         max_autopick = 0;
2301
2302         /* There is always one entry "=g" */
2303         autopick_new_entry(&entry, easy_autopick_inscription);
2304         autopick_list[max_autopick++] = entry;
2305 }
2306
2307
2308 /*
2309  * Get a trigger key and insert ASCII string for the trigger
2310  */
2311 static bool insert_macro_line(cptr *lines_list, int cy)
2312 {
2313         char tmp[1024];
2314         char buf[1024];
2315         int i, n = 0;
2316
2317         /* Flush */
2318         flush();
2319
2320         /* Do not process macros */
2321         inkey_base = TRUE;
2322
2323         /* First key */
2324         i = inkey();
2325
2326         /* Read the pattern */
2327         while (i)
2328         {
2329                 /* Save the key */
2330                 buf[n++] = i;
2331
2332                 /* Do not process macros */
2333                 inkey_base = TRUE;
2334
2335                 /* Do not wait for keys */
2336                 inkey_scan = TRUE;
2337
2338                 /* Attempt to read a key */
2339                 i = inkey();
2340         }
2341
2342         /* Terminate */
2343         buf[n] = '\0';
2344
2345         /* Flush */
2346         flush();
2347
2348         /* Convert the trigger */
2349         ascii_to_text(tmp, buf);
2350
2351         /* Null */
2352         if(!tmp[0]) return FALSE;
2353
2354         /* Insert preference string */
2355         insert_return_code(lines_list, 0, cy);
2356         string_free(lines_list[cy]);
2357         lines_list[cy] = string_make(format("P:%s", tmp));
2358
2359         /* Insert blank action preference line */
2360         insert_return_code(lines_list, 0, cy);
2361         string_free(lines_list[cy]);
2362         lines_list[cy] = string_make("A:");
2363
2364         return TRUE;
2365 }
2366
2367
2368 /*
2369  * Get a command key and insert ASCII string for the key
2370  */
2371 static bool insert_keymap_line(cptr *lines_list, int cy)
2372 {
2373         char tmp[1024];
2374         char buf[2];
2375         int mode;
2376
2377         /* Roguelike */
2378         if (rogue_like_commands)
2379         {
2380                 mode = KEYMAP_MODE_ROGUE;
2381         }
2382
2383         /* Original */
2384         else
2385         {
2386                 mode = KEYMAP_MODE_ORIG;
2387         }
2388
2389         /* Flush */
2390         flush();
2391
2392         /* Get a key */
2393         buf[0] = inkey();
2394         buf[1] = '\0';
2395
2396         /* Flush */
2397         flush();
2398
2399         /* Convert the trigger */
2400         ascii_to_text(tmp, buf);
2401
2402         /* Null */
2403         if(!tmp[0]) return FALSE;
2404
2405         /* Insert preference string */
2406         insert_return_code(lines_list, 0, cy);
2407         string_free(lines_list[cy]);
2408         lines_list[cy] = string_make(format("C:%d:%s", mode, tmp));
2409
2410         /* Insert blank action preference line */
2411         insert_return_code(lines_list, 0, cy);
2412         string_free(lines_list[cy]);
2413         lines_list[cy] = string_make("A:");
2414
2415         return TRUE;
2416 }
2417
2418
2419 /*
2420  * Description of control commands
2421  */
2422
2423 #define WID_DESC 31
2424
2425 static cptr ctrl_command_desc[] =
2426 {
2427 #ifdef JP
2428 #define LAST_DESTROYED 6
2429         "^P ^N ^B ^F ¾å²¼º¸±¦¤Ë°ÜÆ°",
2430         "^A ^E ¹Ô¤ÎÀèƬ¡¢½ªÃ¼",
2431         "^Q ÆþÎÏ/¥³¥Þ¥ó¥É¥â¡¼¥ÉÀÚ¤êÂؤ¨",
2432         "^R Êѹ¹¤òÁ´¤Æ¼è¤ê¾Ã¤·¤Æ¸µ¤ËÌ᤹",
2433         "------------------------------------",
2434         "^I »ý¤Áʪ/ÁõÈ÷¤«¤éÁªÂò",
2435         "^L",
2436         "^K ¥«¡¼¥½¥ë¤«¤é½ªÃ¼¤Þ¤Çºï½ü",
2437         "^Y ºï½ü(^K)¤·¤¿¹Ô¤òÁÞÆþ",
2438         "^C ¼ï²¡¢¿¦¶È¤Î¾ò·ï¼°¤òÁÞÆþ",
2439         "------------------------------------",
2440         "^S Êѹ¹ (!Ç˲õ/~ÊüÃÖ/½¦¤¦)",
2441         "^G \"(\" Á´ÂΥޥåפÇɽ¼¨¤·¤Ê¤¤",
2442         "^O \"#\" ¼«Æ°¹ï¤ß",
2443         "------------------------------------",
2444         "^U Ì¤´ÕÄê/̤ȽÌÀ/´ÕÄê/*´ÕÄê*",
2445         "^W \"̵²ÁÃͤÎ\"",
2446         "^X ÌµÌÃ/¥¨¥´/¥¢¡¼¥Æ¥£¥Õ¥¡¥¯¥È",
2447         "^Z \"¼ý½¸Ãæ¤Î\"",
2448         NULL
2449 #else
2450 #define LAST_DESTROYED 6
2451         "^P ^N ^B ^F Move Cursor",
2452         "^A ^E Beginning and End of Line",
2453         "^Q Toggle Insert/Command mode",
2454         "^R Revert to Original File",
2455         "------------------------------------",
2456         "^I Object in Inventry/Equipment",
2457         "^L",
2458         "^K Kill Rest of Line",
2459         "^Y Insert killed(^K) text",
2460         "^C Insert conditional expression",
2461         "------------------------------------",
2462         "^S Toggle(!Destroy/~Leave/Pick)",
2463         "^G \"(\" No display in the 'M'ap",
2464         "^O \"#\" Auto-Inscribe",
2465         "------------------------------------",
2466         "^U Toggle 'identified' state",
2467         "^W \"worthless\"",
2468         "^X Toggle nameless/ego/artifact",
2469         "^Z \"collecting\"",
2470         NULL
2471 #endif
2472 };
2473
2474
2475 #define MAX_YANK MAX_LINELEN
2476 #define DIRTY_ALL 0x01
2477 #define DIRTY_COMMAND 0x02
2478 #define DIRTY_MODE 0x04
2479 #define DIRTY_SCREEN 0x08
2480 #define DIRTY_NOT_FOUND 0x10
2481
2482 /*
2483  * In-game editor of Object Auto-picker/Destoryer
2484  */
2485 void do_cmd_edit_autopick(void)
2486 {
2487         static int cx = 0, cy = 0;
2488         static int upper = 0, left = 0;
2489
2490         object_type *search_o_ptr = NULL;
2491         cptr search_str = NULL;
2492         cptr last_destroyed = NULL;
2493         char last_destroyed_command[WID_DESC+3];
2494         char yank_buf[MAX_YANK];
2495         char classrace[80];
2496         autopick_type an_entry, *entry = &an_entry;
2497         char buf[MAX_LINELEN];
2498         cptr *lines_list;
2499         int filename_mode = PT_WITH_PNAME;
2500
2501         int i, j, k, len;
2502         cptr tmp;
2503
2504         int old_upper = -1, old_left = -1;
2505         int old_cy = -1;
2506         int key = -1, old_key;
2507         bool repeated_clearing = FALSE;
2508         bool edit_mode = FALSE;
2509
2510         byte dirty_flags = DIRTY_ALL | DIRTY_COMMAND | DIRTY_MODE;
2511         int dirty_line = -1;
2512
2513         int wid, hgt, old_wid = -1, old_hgt = -1;
2514
2515         static s32b old_autosave_turn = 0L;
2516
2517         /* Autosave */
2518         if (turn > old_autosave_turn + 100L)
2519         {
2520                 do_cmd_save_game(TRUE);
2521                 old_autosave_turn = turn;
2522         }
2523
2524         /* HACK -- Reset start_time to stop counting playtime while edit */
2525         update_playtime();
2526
2527         /* Free old entries */
2528         init_autopicker();
2529
2530         /* Command Description of the 'Last Destroyed Item' */
2531         if (autopick_last_destroyed_object.k_idx)
2532         {
2533                 autopick_entry_from_object(entry, &autopick_last_destroyed_object);
2534                 last_destroyed = autopick_line_from_entry_kill(entry);
2535
2536                 my_strcpy(last_destroyed_command, format("^L \"%s\"", last_destroyed), sizeof(last_destroyed_command));
2537         }
2538         else
2539         {
2540 #ifdef JP
2541                 strcpy(last_destroyed_command, "^L ºÇ¸å¤Ë¼«Æ°Ç˲õ¤·¤¿¥¢¥¤¥Æ¥à̾");
2542 #else
2543                 strcpy(last_destroyed_command, "^L Last destroyed object");
2544 #endif
2545         }
2546         ctrl_command_desc[LAST_DESTROYED] = last_destroyed_command;
2547
2548         /* Conditional Expression for Class and Race */
2549         sprintf(classrace, "?:[AND [EQU $RACE %s] [EQU $CLASS %s]]", 
2550 #ifdef JP
2551                 rp_ptr->E_title, cp_ptr->E_title
2552 #else
2553                 rp_ptr->title, cp_ptr->title
2554 #endif
2555                 );
2556
2557         /* Clear yank buffer */
2558         yank_buf[0] = '\0';
2559
2560         /* Read or initialize whole text */
2561         lines_list = read_pickpref_text_lines(&filename_mode);
2562
2563         /* Reset cursor position if needed */
2564         for (i = 0; i < cy; i++)
2565         {
2566                 if (!lines_list[i])
2567                 {
2568                         cy = cx = 0;
2569                         break;
2570                 }
2571         }
2572
2573         /* Save the screen */
2574         screen_save();
2575
2576         /* Process requests until done */
2577         while (1)
2578         {
2579                 /* Get size */
2580                 Term_get_size(&wid, &hgt);
2581
2582 #ifdef JP
2583                 /* Don't let cursor at second byte of kanji */
2584                 for (i = 0; lines_list[cy][i]; i++)
2585                         if (iskanji(lines_list[cy][i]))
2586                         {
2587                                 i++;
2588                                 if (i == cx)
2589                                 {
2590                                         cx--;
2591                                         break;
2592                                 }
2593                         }
2594 #endif
2595
2596                 /* Scroll if necessary */
2597                 if (cy < upper || upper + hgt - 4 <= cy)
2598                         upper = cy - (hgt-4)/2;
2599                 if (upper < 0)
2600                         upper = 0;
2601                 if ((cx < left + 10 && left > 0) || left + wid - WID_DESC - 5 <= cx)
2602                         left = cx - (wid - WID_DESC)*2/3;
2603                 if (left < 0)
2604                         left = 0;
2605
2606                 /* Redraw whole window after resize */
2607                 if (old_wid != wid || old_hgt != hgt)
2608                         dirty_flags |= DIRTY_SCREEN;
2609
2610                 /* Redraw all text after scroll */
2611                 else if (old_upper != upper || old_left != left)
2612                         dirty_flags |= DIRTY_ALL;
2613
2614
2615                 if (dirty_flags & DIRTY_SCREEN)
2616                 {
2617                         dirty_flags |= (DIRTY_ALL | DIRTY_COMMAND | DIRTY_MODE);
2618
2619                         /* Clear screen */
2620                         Term_clear();
2621                 }
2622
2623                 if (dirty_flags & DIRTY_COMMAND)
2624                 {
2625                         /* Display control command */
2626                         for (i = 0; ctrl_command_desc[i]; i++)
2627                                 Term_putstr(wid - WID_DESC, i + 1, WID_DESC, TERM_WHITE, ctrl_command_desc[i]);
2628                 }
2629
2630                 /* Redraw mode line */
2631                 if (dirty_flags & DIRTY_MODE)
2632                 {
2633                         int sepa_length = wid - WID_DESC;
2634
2635                         /* Separator */
2636                         for (i = 0; i < sepa_length; i++)
2637                                 buf[i] = '-';
2638                         buf[i] = '\0';
2639
2640                         /* Mode line */
2641                         if (edit_mode)
2642                                 strncpy(buf + sepa_length - 21, " (INSERT MODE)  ", 16);
2643                         else
2644                                 strncpy(buf + sepa_length - 21, " (COMMAND MODE) ", 16);
2645
2646                         Term_putstr(0, hgt - 3, sepa_length, (byte) (edit_mode ? TERM_YELLOW : TERM_WHITE), buf);
2647                 }
2648                 
2649                 /* Dump up to 20, or hgt-4, lines of messages */
2650                 for (i = 0; i < hgt - 4; i++)
2651                 {
2652                         int leftcol = 0;
2653                         cptr msg;
2654
2655                         /* clean or dirty? */
2656                         if (!(dirty_flags & DIRTY_ALL) && (dirty_line != upper+i))
2657                                 continue;
2658
2659                         msg = lines_list[upper+i];
2660                         if (!msg) break;
2661
2662                         /* Apply horizontal scroll */
2663                         for (j = 0; *msg; msg++, j++)
2664                         {
2665                                 if (j == left) break;
2666 #ifdef JP
2667                                 if (j > left)
2668                                 {
2669                                         leftcol = 1;
2670                                         break;
2671                                 }
2672                                 if (iskanji(*msg))
2673                                 {
2674                                         msg++;
2675                                         j++;
2676                                 }
2677 #endif
2678                         }
2679
2680                         /* Erase line */
2681                         Term_erase(0, i + 1, wid - WID_DESC);
2682
2683                         /* Dump the messages, bottom to top */
2684                         Term_putstr(leftcol, i + 1, wid - WID_DESC - 1, TERM_WHITE, msg);
2685                 }
2686
2687                 for (; i < hgt - 4; i++)
2688                 {
2689                         /* Erase line */
2690                         Term_erase(0, i + 1, wid - WID_DESC);
2691                 }
2692
2693                 /* Display header line */
2694 #ifdef JP
2695                 if (edit_mode)
2696                         prt("^Q ESC ¤Ç¥³¥Þ¥ó¥É¥â¡¼¥É¤Ø°Ü¹Ô¡¢Ä̾ï¤Îʸ»ú¤Ï¤½¤Î¤Þ¤ÞÆþÎÏ", 0, 0);
2697                 else
2698                         prt("q _ ¤Ç½ªÎ»¡¢hjkl2468 ¤Ç°ÜÆ°¡¢^Q a i ¤ÇÆþÎϥ⡼¥É", 0, 0);
2699 #else   
2700                 if (edit_mode)
2701                         prt("Press ^Q ESC to command mode, any letters to insert", 0, 0);
2702                 else
2703                         prt("Press q _ to quit, hjkl2468 to move, ^Q a i to insert mode", 0, 0);
2704 #endif
2705                 /* Display current position */
2706                 prt (format("(%d,%d)", cx, cy), 0, 70);
2707
2708                 /* Display information when updated */
2709                 if (old_cy != cy || (dirty_flags & (DIRTY_ALL | DIRTY_NOT_FOUND)) || dirty_line == cy)
2710                 {
2711                         /* Clear information line */
2712                         Term_erase(0, hgt - 3 + 1, wid);
2713                         Term_erase(0, hgt - 3 + 2, wid);
2714
2715                         /* Display information */
2716                         if (dirty_flags & DIRTY_NOT_FOUND)
2717                         {
2718 #ifdef JP
2719                                 prt(format("¥Ñ¥¿¡¼¥ó¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó: %s", search_str), hgt - 3 + 1, 0);
2720 #else
2721                                 prt(format("Pattern not found: %s", search_str), hgt - 3 + 1, 0);
2722 #endif
2723                         }
2724                         else if (lines_list[cy][0] == '#')
2725                         {
2726 #ifdef JP
2727                                 prt("¤³¤Î¹Ô¤Ï¥³¥á¥ó¥È¤Ç¤¹¡£", hgt - 3 + 1, 0);
2728 #else
2729                                 prt("This line is comment.", hgt - 3 + 1, 0);
2730 #endif
2731                         }
2732                         else if (lines_list[cy][1] == ':')
2733                         {
2734                                 switch(lines_list[cy][0])
2735                                 {
2736                                 case '?':
2737 #ifdef JP
2738                                         prt("¤³¤Î¹Ô¤Ï¾ò·ïʬ´ô¼°¤Ç¤¹¡£", hgt - 3 + 1, 0);
2739 #else
2740                                         prt("This line is Conditional Expression.", hgt - 3 + 1, 0);
2741 #endif
2742                                         break;
2743                                 case 'A':
2744 #ifdef JP
2745                                         prt("¤³¤Î¹Ô¤Ï¥Þ¥¯¥í¤Î¼Â¹ÔÆâÍƤòÄêµÁ¤·¤Þ¤¹¡£", hgt - 3 + 1, 0);
2746 #else
2747                                         prt("This line defines Macro action.", hgt - 3 + 1, 0);
2748 #endif
2749                                         break;
2750                                 case 'P':
2751 #ifdef JP
2752                                         prt("¤³¤Î¹Ô¤Ï¥Þ¥¯¥í¤Î¥È¥ê¥¬¡¼¡¦¥­¡¼¤òÄêµÁ¤·¤Þ¤¹¡£", hgt - 3 + 1, 0);
2753 #else
2754                                         prt("This line defines Macro trigger key.", hgt - 3 + 1, 0);
2755 #endif
2756                                         break;
2757                                 case 'C':
2758 #ifdef JP
2759                                         prt("¤³¤Î¹Ô¤Ï¥­¡¼ÇÛÃÖ¤òÄêµÁ¤·¤Þ¤¹¡£", hgt - 3 + 1, 0);
2760 #else
2761                                         prt("This line defines Keymap.", hgt - 3 + 1, 0);
2762 #endif
2763                                         break;
2764                                 }
2765                         }
2766
2767                         /* Get description of an autopicker preference line */
2768                         else if (autopick_new_entry(entry, lines_list[cy]))
2769                         {
2770                                 char temp[1024];
2771                                 cptr t;
2772
2773                                 describe_autopick(buf, entry);
2774
2775                                 roff_to_buf(buf, 81, temp);
2776                                 t = temp;
2777                                 for (i = 0; i< 2; i++)
2778                                 {
2779                                         if(t[0] == 0)
2780                                                 break; 
2781                                         else
2782                                         {
2783                                                 prt(t, hgt - 3 + 1 + i, 0);
2784                                                 t += strlen(t) + 1;
2785                                         }
2786                                 }
2787                                 autopick_free_entry(entry);
2788                         }
2789                 }
2790
2791                 /* Place cursor */
2792                 Term_gotoxy(cx - left, cy - upper + 1);
2793
2794                 /* Now clean */
2795                 dirty_flags = 0;
2796                 dirty_line = -1;
2797
2798                 /* Save old key and location */
2799                 old_cy = cy;
2800                 old_key = key;
2801                 old_upper = upper;
2802                 old_left = left;
2803                 old_wid = wid;
2804                 old_hgt = hgt;
2805
2806                 /* Do not process macros except special keys */
2807                 inkey_special = TRUE;
2808
2809                 /* Get a command */
2810                 key = inkey();
2811
2812                 if (edit_mode)
2813                 {
2814                         if (key == ESCAPE)
2815                         {
2816                                 edit_mode = FALSE;
2817
2818                                 /* Mode line is now dirty */
2819                                 dirty_flags |= DIRTY_MODE;
2820                         }
2821
2822                         /* Insert a character */
2823                         else if (!iscntrl(key&0xff))
2824                         {
2825                                 int next;
2826
2827                                 /* Save preceding string */
2828                                 for (i = j = 0; lines_list[cy][i] && i < cx; i++)
2829                                         buf[j++] = lines_list[cy][i];
2830
2831                                 /* Add a character */
2832 #ifdef JP
2833                                 if (iskanji(key))
2834                                 {
2835                                         inkey_base = TRUE;
2836                                         next = inkey();
2837                                         if (j+2 < MAX_LINELEN)
2838                                         {
2839                                                 buf[j++] = key;
2840                                                 buf[j++] = next;
2841                                                 cx += 2;
2842                                         }
2843                                         else
2844                                                 bell();
2845                                 }
2846                                 else
2847 #endif
2848                                 {
2849                                         if (j+1 < MAX_LINELEN)
2850                                                 buf[j++] = key;
2851                                         cx++;
2852                                 }
2853
2854                                 /* Add following */
2855                                 for (; lines_list[cy][i] && j + 1 < MAX_LINELEN; i++)
2856                                         buf[j++] = lines_list[cy][i];
2857                                 buf[j] = '\0';
2858
2859                                 /* Replace current line with new line */
2860                                 string_free(lines_list[cy]);
2861                                 lines_list[cy] = string_make(buf);
2862
2863                                 /* Move to correct collumn */
2864                                 len = strlen(lines_list[cy]);
2865                                 if (len < cx) cx = len;
2866
2867                                 /* Now dirty */
2868                                 dirty_line = cy;
2869                         }
2870                 }
2871                 else
2872                 {
2873                         /* Exit on 'q' */
2874                         if (key == 'q' || key == '_') break;
2875
2876                         switch(key)
2877                         {
2878                         case 'a': case 'i':
2879                                 edit_mode = TRUE;
2880
2881                                 /* Mode line is now dirty */
2882                                 dirty_flags |= DIRTY_MODE;
2883                                 break;
2884                         case '~':
2885                                 if (!autopick_new_entry(entry, lines_list[cy]))
2886                                 {
2887                                         if (old_key != key) repeated_clearing = FALSE;
2888
2889                                         /* Next line */
2890                                         if (lines_list[cy + 1]) cy++;
2891                                         cx = 0;
2892                                         break;
2893                                 }
2894                                 string_free(lines_list[cy]);
2895
2896                                 if (old_key != key)
2897                                 {
2898                                         if (entry->action & DONT_AUTOPICK)
2899                                                 repeated_clearing = TRUE;
2900                                         else
2901                                                 repeated_clearing = FALSE;
2902                                 }
2903
2904                                 entry->action &= ~DO_AUTODESTROY;
2905                                 if (!repeated_clearing)
2906                                 {
2907                                         entry->action &= ~DO_AUTOPICK;
2908                                         entry->action |= DONT_AUTOPICK;
2909                                 }
2910                                 else 
2911                                 {
2912                                         entry->action &= ~DONT_AUTOPICK;
2913                                         entry->action |= DO_AUTOPICK;
2914                                 }
2915
2916                                 lines_list[cy] = autopick_line_from_entry_kill(entry);
2917
2918                                 /* Now dirty */
2919                                 dirty_line = cy;
2920
2921                                 /* Next line */
2922                                 if (lines_list[cy + 1]) cy++;
2923                                 cx = 0;
2924                                 break;
2925                         case '!':
2926                                 if (!autopick_new_entry(entry, lines_list[cy]))
2927                                 {
2928                                         if (old_key != key) repeated_clearing = FALSE;
2929
2930                                         /* Next line */
2931                                         if (lines_list[cy + 1]) cy++;
2932                                         cx = 0;
2933                                         break;
2934                                 }
2935                                 string_free(lines_list[cy]);
2936
2937                                 if (old_key != key)
2938                                 {
2939                                         if (entry->action & DO_AUTODESTROY)
2940                                                 repeated_clearing = TRUE;
2941                                         else
2942                                                 repeated_clearing = FALSE;
2943                                 }
2944
2945                                 entry->action &= ~DONT_AUTOPICK;
2946                                 if (!repeated_clearing)
2947                                 {
2948                                         entry->action &= ~DO_AUTOPICK;
2949                                         entry->action |= DO_AUTODESTROY;
2950                                 }
2951                                 else 
2952                                 {
2953                                         entry->action &= ~DO_AUTODESTROY;
2954                                         entry->action |= DO_AUTOPICK;
2955                                 }
2956
2957                                 lines_list[cy] = autopick_line_from_entry_kill(entry);
2958
2959                                 /* Now dirty */
2960                                 dirty_line = cy;
2961
2962                                 /* Next line */
2963                                 if (lines_list[cy + 1]) cy++;
2964                                 cx = 0;
2965                                 break;
2966                         case '(':
2967                                 /* Toggle display on the 'M'ap */
2968                                 if (!autopick_new_entry(entry, lines_list[cy]))
2969                                 {
2970                                         if (old_key != key) repeated_clearing = FALSE;
2971
2972                                         /* Next line */
2973                                         if (lines_list[cy + 1]) cy++;
2974                                         cx = 0;
2975                                         break;
2976                                 }
2977                                 string_free(lines_list[cy]);
2978
2979                                 if (old_key != key)
2980                                 {
2981                                         if (entry->action & DO_DISPLAY)
2982                                                 repeated_clearing = TRUE;
2983                                         else
2984                                                 repeated_clearing = FALSE;
2985                                 }
2986
2987                                 if (!repeated_clearing)
2988                                         entry->action |= DO_DISPLAY;
2989                                 else
2990                                         entry->action &= ~DO_DISPLAY;
2991
2992                                 lines_list[cy] = autopick_line_from_entry_kill(entry);
2993
2994                                 /* Now dirty */
2995                                 dirty_line = cy;
2996
2997                                 /* Next line */
2998                                 if (lines_list[cy + 1]) cy++;
2999                                 cx = 0;
3000                                 break;
3001                         case '#':
3002                         case '{':
3003                                 key = KTRL('o');
3004                                 break;
3005                         case 'h': case '4':
3006                                 key = KTRL('b');
3007                                 break;
3008                         case 'l': case '6':
3009                                 key = KTRL('f');
3010                                 break;
3011                         case 'j': case '2':
3012                                 key = KTRL('n');
3013                                 break;
3014                         case 'k': case '8':
3015                                 key = KTRL('p');
3016                                 break;
3017                         case ' ':
3018                                 while (cy < upper + hgt-4 && lines_list[cy + 1])
3019                                         cy++;
3020                                 upper = cy;
3021                                 break;
3022                         case '-': case 'b':
3023                                 while (0 < cy && upper <= cy)
3024                                         cy--;
3025                                 while (0 < upper && cy + 1 < upper + hgt - 4)
3026                                         upper--;
3027                                 break;
3028
3029                         case 'g':
3030                                 cy = 0;
3031                                 break;
3032
3033                         case 'G':
3034                                 while (lines_list[cy + 1])
3035                                         cy++;
3036                                 break;
3037
3038                         case 'm':
3039                                 /* Erase line */
3040                                 Term_erase(0, cy - upper + 1, wid - WID_DESC);
3041
3042                                 /* Prompt */
3043 #ifdef JP
3044                                 Term_putstr(0, cy - upper + 1, wid - WID_DESC - 1, TERM_YELLOW, "P:<¥È¥ê¥¬¡¼¥­¡¼>: ");
3045 #else
3046                                 Term_putstr(0, cy - upper + 1, wid - WID_DESC - 1, TERM_YELLOW, "P:<Trigger key>: ");
3047 #endif
3048                                 if (insert_macro_line(lines_list, cy))
3049                                 {
3050                                         /* Prepare to input action */
3051                                         cx = 2;
3052                                         edit_mode = TRUE;
3053
3054                                         /* Now dirty */
3055                                         dirty_flags |= DIRTY_ALL;
3056                                         dirty_flags |= DIRTY_MODE;
3057                                 }
3058
3059                                 break;
3060
3061                         case 'c':
3062                                 /* Erase line */
3063                                 Term_erase(0, cy - upper + 1, wid - WID_DESC);
3064
3065                                 /* Prompt */
3066 #ifdef JP
3067                                 Term_putstr(0, cy - upper + 1, wid - WID_DESC - 1, TERM_YELLOW, format("C:%d:<¥³¥Þ¥ó¥É¥­¡¼>: ", (rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG)));
3068 #else
3069                                 Term_putstr(0, cy - upper + 1, wid - WID_DESC - 1, TERM_YELLOW, format("C:%d:<Keypress>: ", (rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG)));
3070 #endif
3071
3072                                 if (insert_keymap_line(lines_list, cy))
3073                                 {
3074                                         /* Prepare to input action */
3075                                         cx = 2;
3076                                         edit_mode = TRUE;
3077
3078                                         /* Now dirty */
3079                                         dirty_flags |= DIRTY_ALL;
3080                                         dirty_flags |= DIRTY_MODE;
3081                                 }                               
3082                                 break;
3083                         case '/':
3084                                 /* Become dirty because of item/equip menu */
3085                                 dirty_flags |= DIRTY_SCREEN;
3086
3087                                 if (!get_string_for_search(&search_o_ptr, &search_str))
3088                                         break;
3089
3090                                 /* fall through */
3091                         case 'n':
3092                                 if (search_o_ptr)
3093                                 {
3094                                         if (!search_for_object(lines_list, search_o_ptr, &cx, &cy, TRUE)) dirty_flags |= DIRTY_NOT_FOUND;
3095                                 }
3096                                 else if (search_str)
3097                                 {
3098                                         if (!search_for_string(lines_list, search_str, &cx, &cy, TRUE)) dirty_flags |= DIRTY_NOT_FOUND;
3099                                 }
3100                                 break;
3101                         case 'N':
3102                                 if (search_o_ptr)
3103                                 {
3104                                         if (!search_for_object(lines_list, search_o_ptr, &cx, &cy, FALSE)) dirty_flags |= DIRTY_NOT_FOUND;
3105                                 }
3106                                 else if (search_str)
3107                                 {
3108                                         if (!search_for_string(lines_list, search_str, &cx, &cy, FALSE)) dirty_flags |= DIRTY_NOT_FOUND;
3109                                 }
3110                                 break;
3111                         }
3112                 }
3113
3114                 switch(key)
3115                 {
3116                 case KTRL('a'):
3117                         /* Beginning of line */
3118                         cx = 0;
3119                         break;
3120                 case KTRL('b'):
3121                         /* Back */
3122                         if (0 < cx)
3123                         {
3124                                 cx--;
3125                                 len = strlen(lines_list[cy]);
3126                                 if (len < cx) cx = len;
3127                         }
3128                         else if (cy > 0)
3129                         {
3130                                 cy--;
3131                                 cx = strlen(lines_list[cy]);
3132                         }
3133                         break;
3134                 case KTRL('c'):
3135                         /* Insert a conditinal expression line */
3136                         insert_return_code(lines_list, 0, cy);
3137                         string_free(lines_list[cy]);
3138                         lines_list[cy] = string_make(classrace);
3139                         cy++;
3140                         insert_return_code(lines_list, 0, cy);
3141                         string_free(lines_list[cy]);
3142                         lines_list[cy] = string_make("?:1");
3143                         cx = 0;
3144
3145                         /* Now dirty */
3146                         dirty_flags |= DIRTY_ALL;
3147                         break;
3148                 case KTRL('e'):
3149                         /* End of line */
3150                         cx = strlen(lines_list[cy]);
3151                         break;
3152                 case KTRL('f'):
3153                         /* Forward */
3154 #ifdef JP
3155                         if (iskanji(lines_list[cy][cx])) cx++;
3156 #endif
3157                         cx++;
3158                         len = strlen(lines_list[cy]);
3159                         if (len < cx)
3160                         {
3161                                 if (lines_list[cy + 1])
3162                                 {
3163                                         cy++;
3164                                         cx = 0;
3165                                 }
3166                                 else
3167                                         cx = len;
3168                         }
3169                         break;
3170                 case KTRL('g'):
3171                         /* Toggle display on the 'M'ap */
3172                         if (!autopick_new_entry(entry, lines_list[cy]))
3173                                 break;
3174                         string_free(lines_list[cy]);
3175
3176                         if (entry->action & DO_DISPLAY)
3177                         {
3178                                 entry->action &= ~DO_DISPLAY;
3179                                 cx++;
3180                         }
3181                         else
3182                         {
3183                                 entry->action |= DO_DISPLAY;
3184                                 if (cx > 0) cx--;
3185                         }
3186
3187                         lines_list[cy] = autopick_line_from_entry_kill(entry);
3188
3189                         /* Now dirty */
3190                         dirty_line = cy;
3191                         break;
3192                 case KTRL('i'):
3193                         /* Insert choosen item name */
3194                         if (!entry_from_choosed_object(entry))
3195                         {
3196                                 /* Now dirty because of item/equip menu */
3197                                 dirty_flags |= DIRTY_SCREEN;
3198                                 break;
3199                         }
3200
3201                         insert_return_code(lines_list, 0, cy);
3202                         string_free(lines_list[cy]);
3203                         lines_list[cy] = autopick_line_from_entry_kill(entry);
3204                         cx = 0;
3205
3206                         /* Now dirty because of item/equip menu */
3207                         dirty_flags |= DIRTY_SCREEN;
3208
3209                         break;
3210                 case KTRL('l'):
3211                         /* Insert a name of last destroyed item */
3212                         if (last_destroyed)
3213                         {
3214                                 insert_return_code(lines_list, 0, cy);
3215                                 string_free(lines_list[cy]);
3216                                 lines_list[cy] = string_make(last_destroyed);
3217                                 cx = 0;
3218
3219                                 /* Now dirty */
3220                                 dirty_flags |= DIRTY_ALL;
3221                         }
3222                         break;
3223                 case '\n': case '\r':
3224                         /* Split a line or insert end of line */
3225                         insert_return_code(lines_list, cx, cy);
3226                         cy++;
3227                         cx = 0;
3228
3229                         /* Now dirty */
3230                         dirty_flags |= DIRTY_ALL;
3231                         break;
3232                 case KTRL('n'):
3233                         /* Next line */
3234                         if (lines_list[cy + 1]) cy++;
3235                         break;
3236                 case KTRL('o'):
3237                         /* Prepare to write auto-inscription text */
3238                         if (!autopick_new_entry(entry, lines_list[cy]))
3239                                 break;
3240                         string_free(lines_list[cy]);
3241
3242                         if (!entry->insc) entry->insc = string_make("");
3243
3244                         lines_list[cy] = autopick_line_from_entry_kill(entry);
3245
3246                         /* Move to collumn for auto inscription */
3247                         for (cx = 0; lines_list[cy][cx]; cx++)
3248                                 if (lines_list[cy][cx] == '#') break;
3249                         cx++;
3250                         edit_mode = TRUE;
3251
3252                         /* Now dirty */
3253                         dirty_line = cy;
3254                         dirty_flags |= DIRTY_MODE;
3255                         break;
3256                 case KTRL('p'):
3257                         /* Previous line */
3258                         if (cy > 0) cy--;
3259                         break;
3260                 case KTRL('q'):
3261                         /* Change mode */
3262                         edit_mode = !edit_mode;
3263                         
3264                         /* Mode line is now dirty */
3265                         dirty_flags |= DIRTY_MODE;
3266                         break;
3267                 case KTRL('r'):
3268                         /* Revert to original */
3269 #ifdef JP
3270                         if (!get_check("Á´¤Æ¤ÎÊѹ¹¤òÇË´þ¤·¤Æ¸µ¤Î¾õÂÖ¤ËÌᤷ¤Þ¤¹¡£¤è¤í¤·¤¤¤Ç¤¹¤«¡© "))
3271 #else
3272                         if (!get_check("Discard all change and revert to original file. Are you sure? "))
3273 #endif
3274                                 break;
3275
3276                         free_text_lines(lines_list);
3277                         lines_list = read_pickpref_text_lines(&filename_mode);
3278                         dirty_flags |= DIRTY_ALL | DIRTY_MODE;
3279                         cx = cy = 0;
3280                         edit_mode = FALSE;
3281                         break;
3282                 case KTRL('s'):
3283                         /* Rotate action; pickup/destroy/leave */
3284                         if (!autopick_new_entry(entry, lines_list[cy]))
3285                                 break;
3286                         string_free(lines_list[cy]);
3287
3288                         if (entry->action & DO_AUTOPICK)
3289                         {
3290                                 entry->action &= ~DO_AUTOPICK;
3291                                 entry->action |= DO_AUTODESTROY;
3292                         }
3293                         else if (entry->action & DO_AUTODESTROY)
3294                         {
3295                                 entry->action &= ~DO_AUTODESTROY;
3296                                 entry->action |= DONT_AUTOPICK;
3297                         }
3298                         else if (entry->action & DONT_AUTOPICK)
3299                         {
3300                                 entry->action &= ~DONT_AUTOPICK;
3301                                 entry->action |= DO_AUTOPICK;
3302                         }
3303
3304                         lines_list[cy] = autopick_line_from_entry_kill(entry);
3305
3306                         /* Now dirty */
3307                         dirty_line = cy;
3308
3309                         break;
3310                 case KTRL('t'):
3311                         /* Nothing */
3312                         break;
3313                 case KTRL('u'):
3314                         /* Rotate identify-state; identified/unidentified/... */
3315                         if (!autopick_new_entry(entry, lines_list[cy]))
3316                                 break;
3317                         string_free(lines_list[cy]);
3318
3319                         if (IS_FLG(FLG_UNIDENTIFIED)) 
3320                         {
3321                                 REM_FLG(FLG_UNIDENTIFIED);
3322                                 ADD_FLG(FLG_UNAWARE);
3323                                 REM_FLG(FLG_IDENTIFIED);
3324                                 REM_FLG(FLG_STAR_IDENTIFIED);
3325                         }
3326                         else if (IS_FLG(FLG_UNAWARE)) 
3327                         {
3328                                 REM_FLG(FLG_UNIDENTIFIED);
3329                                 REM_FLG(FLG_UNAWARE);
3330                                 ADD_FLG(FLG_IDENTIFIED);
3331                                 REM_FLG(FLG_STAR_IDENTIFIED);
3332                         }
3333                         else if (IS_FLG(FLG_STAR_IDENTIFIED)) 
3334                         {
3335                                 REM_FLG(FLG_UNIDENTIFIED);
3336                                 REM_FLG(FLG_UNAWARE);
3337                                 REM_FLG(FLG_IDENTIFIED);
3338                                 REM_FLG(FLG_STAR_IDENTIFIED);
3339                         }
3340                         else if (IS_FLG(FLG_IDENTIFIED)) 
3341                         {
3342                                 REM_FLG(FLG_UNIDENTIFIED);
3343                                 REM_FLG(FLG_UNAWARE);
3344                                 REM_FLG(FLG_IDENTIFIED);
3345                                 ADD_FLG(FLG_STAR_IDENTIFIED);
3346                         }
3347                         else
3348                         {
3349                                 ADD_FLG(FLG_UNIDENTIFIED);
3350                                 REM_FLG(FLG_UNAWARE);
3351                                 REM_FLG(FLG_IDENTIFIED);
3352                                 REM_FLG(FLG_STAR_IDENTIFIED);
3353                         }
3354
3355                         lines_list[cy] = autopick_line_from_entry_kill(entry);
3356
3357                         /* Now dirty */
3358                         dirty_line = cy;
3359                         break;
3360                 case KTRL('v'):
3361                         /* Scroll up */
3362                         while (cy < upper + hgt-4 && lines_list[cy + 1])
3363                                 cy++;
3364                         upper = cy;
3365                         break;
3366                 case KTRL('w'):
3367                         /* Toggle 'worthless' */
3368                         toggle_string(lines_list, FLG_WORTHLESS, cy);
3369                         /* Now dirty */
3370                         dirty_line = cy;
3371                         break;
3372                 case KTRL('x'):
3373                         /* Rotate within nameless, ego, artifact */
3374                         if (!autopick_new_entry(entry, lines_list[cy]))
3375                                 break;
3376                         string_free(lines_list[cy]);
3377
3378                         if (IS_FLG(FLG_NAMELESS)) 
3379                         {
3380                                 REM_FLG(FLG_NAMELESS);
3381                                 ADD_FLG(FLG_EGO);
3382                                 REM_FLG(FLG_ARTIFACT);
3383                         }
3384                         else if (IS_FLG(FLG_EGO)) 
3385                         {
3386                                 REM_FLG(FLG_NAMELESS);
3387                                 REM_FLG(FLG_EGO);
3388                                 ADD_FLG(FLG_ARTIFACT);
3389                         }
3390                         else if (IS_FLG(FLG_ARTIFACT)) 
3391                         {
3392                                 REM_FLG(FLG_NAMELESS);
3393                                 REM_FLG(FLG_EGO);
3394                                 REM_FLG(FLG_ARTIFACT);
3395                         }
3396                         else
3397                         {
3398                                 ADD_FLG(FLG_NAMELESS);
3399                                 REM_FLG(FLG_EGO);
3400                                 REM_FLG(FLG_ARTIFACT);
3401                         }
3402
3403                         lines_list[cy] = autopick_line_from_entry_kill(entry);
3404
3405                         /* Now dirty */
3406                         dirty_line = cy;
3407                         break;
3408
3409                 case KTRL('y'):
3410                         /* Paste killed text */
3411                         if (strlen(yank_buf))
3412                         {
3413                                 bool ret = FALSE;
3414
3415                                 for (j = 0; yank_buf[j]; j += strlen(yank_buf + j) + 1)
3416                                 {
3417                                         if (ret && '\n' == yank_buf[j])
3418                                         {
3419                                                 ret = FALSE;
3420                                                 continue;
3421                                         }
3422
3423                                         /* Split current line */
3424                                         insert_return_code(lines_list, cx, cy);
3425
3426                                         /* Save preceding string */
3427                                         for(i = 0; lines_list[cy][i]; i++)
3428                                                 buf[i] = lines_list[cy][i];
3429
3430                                         /* Paste yank buffer */
3431                                         if ('\n' != yank_buf[j])
3432                                         {
3433                                                 int k = j;
3434                                                 while (yank_buf[k] && i < MAX_LINELEN-1)
3435                                                         buf[i++] = yank_buf[k++];
3436                                                 ret = TRUE;
3437                                         }
3438
3439                                         buf[i] = '\0';
3440
3441                                         string_free(lines_list[cy]);
3442                                         lines_list[cy] = string_make(buf);
3443
3444                                         /* Move to the beggining of next line */
3445                                         cx = 0;
3446                                         cy++;
3447                                 }
3448
3449                                 /* Now dirty */
3450                                 dirty_flags |= DIRTY_ALL;
3451                         }
3452                         break;
3453                 case KTRL('z'):
3454                         /* Toggle 'collecting' */
3455                         toggle_string(lines_list, FLG_COLLECTING, cy);
3456                         /* Now dirty */
3457                         dirty_line = cy;
3458                         break;
3459
3460                 case KTRL('k'):
3461                         /* Kill rest of line */
3462                         if ((uint)cx > strlen(lines_list[cy]))
3463                                 cx = (int)strlen(lines_list[cy]);
3464
3465                         /* Save preceding string */
3466                         for (i = 0; lines_list[cy][i] && i < cx; i++)
3467                         {
3468 #ifdef JP
3469                                 if (iskanji(lines_list[cy][i]))
3470                                 {
3471                                         buf[i] = lines_list[cy][i];
3472                                         i++;
3473                                 }
3474 #endif
3475                                 buf[i] = lines_list[cy][i];
3476                         }
3477                         buf[i] = '\0';
3478
3479                         j = 0;
3480                         if (old_key == key)
3481                                 while (yank_buf[j])
3482                                         j += strlen(yank_buf + j) + 1;
3483
3484                         /* Copy following to yank buffer */
3485                         if (lines_list[cy][i])
3486                         {
3487                                 while (lines_list[cy][i] && j < MAX_YANK - 2)
3488                                         yank_buf[j++] = lines_list[cy][i++];
3489                                 i = TRUE;
3490                         }
3491                         else
3492                         {
3493                                 if (j < MAX_YANK - 2)
3494                                         yank_buf[j++] = '\n';
3495                                 i = FALSE;
3496                         }
3497                         yank_buf[j++] = '\0';
3498                         yank_buf[j] = '\0';
3499
3500                         /* Replace current line with 'preceding string' */
3501                         string_free(lines_list[cy]);
3502                         lines_list[cy] = string_make(buf);
3503
3504                         if (i)
3505                         {
3506                                 /* Now dirty */
3507                                 dirty_line = cy;
3508                                 break;
3509                         }
3510
3511                         /* fall through */
3512                 case KTRL('d'):
3513                 case 0x7F:
3514                         /* DELETE == go forward + BACK SPACE */
3515 #ifdef JP
3516                         if (iskanji(lines_list[cy][cx])) cx++;
3517 #endif
3518                         cx++;
3519
3520                         /* fall through */
3521
3522                 case '\010':
3523                         /* BACK SPACE */
3524                         len = strlen(lines_list[cy]);
3525                         if (len < cx)
3526                         {
3527                                 if (lines_list[cy + 1])
3528                                 {
3529                                         cy++;
3530                                         cx = 0;
3531                                 }
3532                                 else
3533                                 {
3534                                         cx = len;
3535                                         break;
3536                                 }
3537                         }
3538
3539                         if (cx == 0)
3540                         {
3541                                 /* delete a return code and union two lines */
3542                                 if (cy == 0) break;
3543                                 cx = strlen(lines_list[cy-1]);
3544                                 strcpy(buf, lines_list[cy-1]);
3545                                 strcat(buf, lines_list[cy]);
3546                                 string_free(lines_list[cy-1]);
3547                                 string_free(lines_list[cy]);
3548                                 lines_list[cy-1] = string_make(buf);
3549                                 for (i = cy; lines_list[i+1]; i++)
3550                                         lines_list[i] = lines_list[i+1];
3551                                 lines_list[i] = NULL;
3552                                 cy--;
3553
3554                                 /* Now dirty */
3555                                 dirty_flags |= DIRTY_ALL;
3556                                 break;
3557                         }
3558
3559                         for (i = j = k = 0; lines_list[cy][i] && i < cx; i++)
3560                         {
3561                                 k = j;
3562 #ifdef JP
3563                                 if (iskanji(lines_list[cy][i]))
3564                                         buf[j++] = lines_list[cy][i++];
3565 #endif
3566                                 buf[j++] = lines_list[cy][i];
3567                         }
3568                         while (j > k)
3569                         {
3570                                 cx--;
3571                                 j--;
3572                         }
3573                         for (; lines_list[cy][i]; i++)
3574                                 buf[j++] = lines_list[cy][i];
3575                         buf[j] = '\0';
3576                         string_free(lines_list[cy]);
3577                         lines_list[cy] = string_make(buf);
3578
3579                         /* Now dirty */
3580                         dirty_line = cy;
3581                         break;
3582                 }
3583
3584         } /* while (1) */
3585
3586         /* Restore the screen */
3587         screen_load();
3588
3589         switch (filename_mode)
3590         {
3591         case PT_DEFAULT:
3592 #ifdef JP
3593                 strcpy(buf, "picktype.prf");
3594 #else
3595                 strcpy(buf, "pickpref.prf");
3596 #endif
3597                 break;
3598
3599         case PT_WITH_PNAME:
3600 #ifdef JP
3601                 sprintf(buf, "picktype-%s.prf", player_name);
3602 #else
3603                 sprintf(buf, "pickpref-%s.prf", player_name);
3604 #endif
3605                 break;
3606         }
3607
3608         write_text_lines(buf, lines_list);
3609         free_text_lines(lines_list);
3610
3611         string_free(last_destroyed);
3612
3613         /* Reload autopick pref */
3614         process_pickpref_file(buf);
3615
3616         /* HACK -- reset start_time so that playtime is not increase while edit */
3617         start_time = time(NULL);
3618 }