OSDN Git Service

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