OSDN Git Service

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