OSDN Git Service

[Refactor] #37353 object-ego.c/h を作成して関連構造体と変数を移動.
[hengband/hengband.git] / src / autopick.c
1 /*!
2  * @file autopick.c
3  * @brief 自動拾い機能の実装 / Object Auto-picker/Destroyer
4  * @date 2014/01/02
5  * @author
6  * Copyright (c) 2002  Mogami\n
7  *\n
8  * This software may be copied and distributed for educational, research, and\n
9  * not for profit purposes provided that this copyright and statement are\n
10  * included in all such copies.\n
11  * 2014 Deskull rearranged comment for Doxygen.\n
12  */
13
14 #include "angband.h"
15 #include "util.h"
16 #include "autopick.h"
17
18 #include "mind.h"
19
20 #include "store.h"
21 #include "player-status.h"
22 #include "player-move.h"
23 #include "player-class.h"
24 #include "objectkind.h"
25 #include "object-ego.h"
26 #include "object-flavor.h"
27 #include "object-hook.h"
28
29 #include "files.h"
30 #include "floor.h"
31 #include "world.h"
32 #include "monster.h"
33 #include "monsterrace.h"
34
35 #define MAX_LINELEN 1024
36
37 /*
38  * Macros for Keywords
39  */
40 #define FLG_ALL                         0
41 #define FLG_UNAWARE                     1
42 #define FLG_UNIDENTIFIED        2
43 #define FLG_IDENTIFIED          3
44 #define FLG_STAR_IDENTIFIED     4
45 #define FLG_COLLECTING          5
46 #define FLG_ARTIFACT            6
47 #define FLG_EGO              7 
48 #define FLG_GOOD             10
49 #define FLG_NAMELESS     11
50 #define FLG_AVERAGE          12
51 #define FLG_WORTHLESS    13
52 #define FLG_RARE             14
53 #define FLG_COMMON           15
54 #define FLG_BOOSTED          16
55 #define FLG_MORE_DICE    17
56 #define FLG_MORE_BONUS   18
57 #define FLG_WANTED           19
58 #define FLG_UNIQUE           20
59 #define FLG_HUMAN            21
60 #define FLG_UNREADABLE   22
61 #define FLG_REALM1           23
62 #define FLG_REALM2           24
63 #define FLG_FIRST            25
64 #define FLG_SECOND           26
65 #define FLG_THIRD            27
66 #define FLG_FOURTH           28
67
68 #define FLG_ITEMS            30
69 #define FLG_WEAPONS          31
70 #define FLG_FAVORITE_WEAPONS 32
71 #define FLG_ARMORS           33
72 #define FLG_MISSILES         34
73 #define FLG_DEVICES          35
74 #define FLG_LIGHTS           36
75 #define FLG_JUNKS            37
76 #define FLG_CORPSES          38
77 #define FLG_SPELLBOOKS       39
78 #define FLG_HAFTED           40
79 #define FLG_SHIELDS          41
80 #define FLG_BOWS             42
81 #define FLG_RINGS            43
82 #define FLG_AMULETS          44
83 #define FLG_SUITS            45
84 #define FLG_CLOAKS           46
85 #define FLG_HELMS            47
86 #define FLG_GLOVES           48
87 #define FLG_BOOTS            49
88
89 #define FLG_NOUN_BEGIN      FLG_ITEMS
90 #define FLG_NOUN_END        FLG_BOOTS
91
92 #ifdef JP
93
94 static GAME_TEXT KEY_ALL[] = "すべての";
95 static GAME_TEXT KEY_UNAWARE[] = "未判明の";
96 static GAME_TEXT KEY_UNIDENTIFIED[] = "未鑑定の";
97 static GAME_TEXT KEY_IDENTIFIED[] = "鑑定済みの";
98 static GAME_TEXT KEY_STAR_IDENTIFIED[] = "*鑑定*済みの";
99 static GAME_TEXT KEY_COLLECTING[] = "収集中の";
100 static GAME_TEXT KEY_ARTIFACT[] = "アーティファクト";
101 static GAME_TEXT KEY_EGO[] = "エゴ";
102 static GAME_TEXT KEY_GOOD[] = "上質の";
103 static GAME_TEXT KEY_NAMELESS[] = "無銘の";
104 static GAME_TEXT KEY_AVERAGE[] = "並の";
105 static GAME_TEXT KEY_WORTHLESS[] = "無価値の";
106 static GAME_TEXT KEY_RARE[] = "レアな";
107 static GAME_TEXT KEY_COMMON[] = "ありふれた";
108 static GAME_TEXT KEY_BOOSTED[] = "ダイス目の違う";
109 static GAME_TEXT KEY_MORE_THAN[] =  "ダイス目";
110 static GAME_TEXT KEY_DICE[] =  "以上の";
111 static GAME_TEXT KEY_MORE_BONUS[] =  "修正値";
112 static GAME_TEXT KEY_MORE_BONUS2[] =  "以上の";
113 static GAME_TEXT KEY_WANTED[] = "賞金首の";
114 static GAME_TEXT KEY_UNIQUE[] = "ユニーク・モンスターの";
115 static GAME_TEXT KEY_HUMAN[] = "人間の";
116 static GAME_TEXT KEY_UNREADABLE[] = "読めない";
117 static GAME_TEXT KEY_REALM1[] = "第一領域の";
118 static GAME_TEXT KEY_REALM2[] = "第二領域の";
119 static GAME_TEXT KEY_FIRST[] = "1冊目の";
120 static GAME_TEXT KEY_SECOND[] = "2冊目の";
121 static GAME_TEXT KEY_THIRD[] = "3冊目の";
122 static GAME_TEXT KEY_FOURTH[] = "4冊目の";
123 static GAME_TEXT KEY_ITEMS[] = "アイテム";
124 static GAME_TEXT KEY_WEAPONS[] = "武器";
125 static GAME_TEXT KEY_FAVORITE_WEAPONS[] = "得意武器";
126 static GAME_TEXT KEY_ARMORS[] = "防具";
127 static GAME_TEXT KEY_MISSILES[] = "矢";
128 static GAME_TEXT KEY_DEVICES[] = "魔法アイテム";
129 static GAME_TEXT KEY_LIGHTS[] = "光源";
130 static GAME_TEXT KEY_JUNKS[] = "がらくた";
131 static GAME_TEXT KEY_CORPSES[] = "死体や骨";
132 static GAME_TEXT KEY_SPELLBOOKS[] = "魔法書";
133 static GAME_TEXT KEY_HAFTED[] = "鈍器";
134 static GAME_TEXT KEY_SHIELDS[] = "盾";
135 static GAME_TEXT KEY_BOWS[] = "弓";
136 static GAME_TEXT KEY_RINGS[] = "指輪";
137 static GAME_TEXT KEY_AMULETS[] = "アミュレット";
138 static GAME_TEXT KEY_SUITS[] = "鎧";
139 static GAME_TEXT KEY_CLOAKS[] = "クローク";
140 static GAME_TEXT KEY_HELMS[] = "兜";
141 static GAME_TEXT KEY_GLOVES[] = "籠手";
142 static GAME_TEXT KEY_BOOTS[] = "靴";
143
144 #else 
145
146 static GAME_TEXT KEY_ALL[] = "all";
147 static GAME_TEXT KEY_UNAWARE[] = "unaware";
148 static GAME_TEXT KEY_UNIDENTIFIED[] = "unidentified";
149 static GAME_TEXT KEY_IDENTIFIED[] = "identified";
150 static GAME_TEXT KEY_STAR_IDENTIFIED[] = "*identified*";
151 static GAME_TEXT KEY_COLLECTING[] = "collecting";
152 static GAME_TEXT KEY_ARTIFACT[] = "artifact";
153 static GAME_TEXT KEY_EGO[] = "ego";
154 static GAME_TEXT KEY_GOOD[] = "good";
155 static GAME_TEXT KEY_nameLESS[] = "nameless";
156 static GAME_TEXT KEY_AVERAGE[] = "average";
157 static GAME_TEXT KEY_WORTHLESS[] = "worthless";
158 static GAME_TEXT KEY_RARE[] = "rare";
159 static GAME_TEXT KEY_COMMON[] = "common";
160 static GAME_TEXT KEY_BOOSTED[] = "dice boosted";
161 static GAME_TEXT KEY_MORE_THAN[] =  "more than";
162 static GAME_TEXT KEY_DICE[] =  " dice";
163 static GAME_TEXT KEY_MORE_BONUS[] =  "more bonus than";
164 static GAME_TEXT KEY_MORE_BONUS2[] =  "";
165 static GAME_TEXT KEY_WANTED[] = "wanted";
166 static GAME_TEXT KEY_UNIQUE[] = "unique monster's";
167 static GAME_TEXT KEY_HUMAN[] = "human";
168 static GAME_TEXT KEY_UNREADABLE[] = "unreadable";
169 static GAME_TEXT KEY_REALM1[] = "first realm's";
170 static GAME_TEXT KEY_REALM2[] = "second realm's";
171 static GAME_TEXT KEY_FIRST[] = "first";
172 static GAME_TEXT KEY_SECOND[] = "second";
173 static GAME_TEXT KEY_THIRD[] = "third";
174 static GAME_TEXT KEY_FOURTH[] = "fourth";
175 static GAME_TEXT KEY_ITEMS[] = "items";
176 static GAME_TEXT KEY_WEAPONS[] = "weapons";
177 static GAME_TEXT KEY_FAVORITE_WEAPONS[] = "favorite weapons";
178 static GAME_TEXT KEY_ARMORS[] = "armors";
179 static GAME_TEXT KEY_MISSILES[] = "missiles";
180 static GAME_TEXT KEY_DEVICES[] = "magical devices";
181 static GAME_TEXT KEY_LIGHTS[] = "lights";
182 static GAME_TEXT KEY_JUNKS[] = "junks";
183 static GAME_TEXT KEY_CORPSES[] = "corpses or skeletons";
184 static GAME_TEXT KEY_SPELLBOOKS[] = "spellbooks";
185 static GAME_TEXT KEY_HAFTED[] = "hafted weapons";
186 static GAME_TEXT KEY_SHIELDS[] = "shields";
187 static GAME_TEXT KEY_BOWS[] = "bows";
188 static GAME_TEXT KEY_RINGS[] = "rings";
189 static GAME_TEXT KEY_AMULETS[] = "amulets";
190 static GAME_TEXT KEY_SUITS[] = "suits";
191 static GAME_TEXT KEY_CLOAKS[] = "cloaks";
192 static GAME_TEXT KEY_HELMS[] = "helms";
193 static GAME_TEXT KEY_GLOVES[] = "gloves";
194 static GAME_TEXT KEY_BOOTS[] = "boots";
195
196 #endif /* JP */
197
198 #define MATCH_KEY(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\
199      ? (ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE)
200 #define MATCH_KEY2(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\
201      ? (prev_ptr = ptr, ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE)
202
203 #ifdef JP
204 #define ADD_KEY(KEY) strcat(ptr, KEY)
205 #else
206 #define ADD_KEY(KEY) (strcat(ptr, KEY), strcat(ptr, " "))
207 #endif
208 #define ADD_KEY2(KEY) strcat(ptr, KEY)
209
210 #define ADD_FLG(FLG) (entry->flag[FLG / 32] |= (1L << (FLG % 32)))
211 #define REM_FLG(FLG) (entry->flag[FLG / 32] &= ~(1L << (FLG % 32)))
212 #define ADD_FLG_NOUN(FLG) (ADD_FLG(FLG), prev_flg = FLG)
213 #define IS_FLG(FLG) (entry->flag[FLG / 32] & (1L << (FLG % 32)))
214
215 #ifdef JP
216         static char kanji_colon[] = ":";
217 #endif
218
219
220 /*
221  * 自動拾い/破壊設定のリストに関する変数 / List for auto-picker/destroyer entries
222  */
223 int max_autopick = 0; /*!< 現在登録している自動拾い/破壊設定の数 */
224 int max_max_autopick = 0; /*!< 自動拾い/破壊設定の限界数 */
225 autopick_type *autopick_list = NULL; /*!< 自動拾い/破壊設定構造体のポインタ配列 */
226
227 /*
228  * A function to create new entry
229  */
230 static bool autopick_new_entry(autopick_type *entry, concptr str, bool allow_default)
231 {
232         concptr insc;
233         int i;
234         byte act = 0;
235         char buf[MAX_LINELEN];
236         concptr prev_ptr, ptr, old_ptr;
237         int prev_flg;
238
239         if (str[0] && str[1] == ':') switch (str[0])
240         {
241         case '?': case '%':
242         case 'A': case 'P': case 'C':
243                 return FALSE;
244         }
245
246         entry->flag[0] = entry->flag[1] = 0L;
247         entry->dice = 0;
248         entry->bonus = 0;
249
250         act = DO_AUTOPICK | DO_DISPLAY;
251         while (TRUE)
252         {
253                 if ((act & DO_AUTOPICK) && *str == '!')
254                 {
255                         act &= ~DO_AUTOPICK;
256                         act |= DO_AUTODESTROY;
257                         str++;
258                 }
259                 else if ((act & DO_AUTOPICK) && *str == '~')
260                 {
261                         act &= ~DO_AUTOPICK;
262                         act |= DONT_AUTOPICK;
263                         str++;
264                 }
265                 else if ((act & DO_AUTOPICK) && *str == ';')
266                 {
267                         act &= ~DO_AUTOPICK;
268                         act |= DO_QUERY_AUTOPICK;
269                         str++;
270                 }
271                 else if ((act & DO_DISPLAY) && *str == '(')
272                 {
273                         act &= ~DO_DISPLAY;
274                         str++;
275                 }
276                 else
277                         break;
278         }
279
280         /* don't mind upper or lower case */
281         insc = NULL;
282         for (i = 0; *str; i++)
283         {
284                 char c = *str++;
285 #ifdef JP
286                 if (iskanji(c))
287                 {
288                         buf[i++] = c;
289                         buf[i] = *str++;
290                         continue;
291                 }
292 #endif
293                 /* Auto-inscription? */
294                 if (c == '#')
295                 {
296                         buf[i] = '\0';
297                         insc = str;
298                         break;
299                 }
300
301                 if (isupper(c)) c = (char)tolower(c);
302
303                 buf[i] = c;
304         }
305         buf[i] = '\0';
306
307         /* Skip empty line unless allow_default */
308         if (!allow_default && *buf == 0) return FALSE;
309
310         /* Skip comment line */
311         if (*buf == 0 && insc) return FALSE;
312
313         ptr = prev_ptr = buf;
314         old_ptr = NULL;
315
316         while (old_ptr != ptr)
317         {
318                 /* Save current location */
319                 old_ptr = ptr;
320
321                 if (MATCH_KEY(KEY_ALL)) ADD_FLG(FLG_ALL);
322                 if (MATCH_KEY(KEY_COLLECTING)) ADD_FLG(FLG_COLLECTING);
323                 if (MATCH_KEY(KEY_UNAWARE)) ADD_FLG(FLG_UNAWARE);
324                 if (MATCH_KEY(KEY_UNIDENTIFIED)) ADD_FLG(FLG_UNIDENTIFIED);
325                 if (MATCH_KEY(KEY_IDENTIFIED)) ADD_FLG(FLG_IDENTIFIED);
326                 if (MATCH_KEY(KEY_STAR_IDENTIFIED)) ADD_FLG(FLG_STAR_IDENTIFIED);
327                 if (MATCH_KEY(KEY_BOOSTED)) ADD_FLG(FLG_BOOSTED);
328
329                 /*** Weapons whose dd*ds is more than nn ***/
330                 if (MATCH_KEY2(KEY_MORE_THAN))
331                 {
332                         int k = 0;
333                         entry->dice = 0;
334
335                         /* Drop leading spaces */
336                         while (' ' == *ptr) ptr++;
337
338                         /* Read number */
339                         while ('0' <= *ptr && *ptr <= '9')
340                         {
341                                 entry->dice = 10 * entry->dice + (*ptr - '0');
342                                 ptr++;
343                                 k++;
344                         }
345
346                         if (k > 0 && k <= 2)
347                         {
348                                 (void)MATCH_KEY(KEY_DICE);
349                                 ADD_FLG(FLG_MORE_DICE);
350                         }
351                         else
352                                 ptr = prev_ptr;
353                 }
354
355                 /*** Items whose magical bonus is more than n ***/
356                 if (MATCH_KEY2(KEY_MORE_BONUS))
357                 {
358                         int k = 0;
359                         entry->bonus = 0;
360
361                         /* Drop leading spaces */
362                         while (' ' == *ptr) ptr++;
363
364                         /* Read number */
365                         while ('0' <= *ptr && *ptr <= '9')
366                         {
367                                 entry->bonus = 10 * entry->bonus + (*ptr - '0');
368                                 ptr++;
369                                 k++;
370                         }
371
372                         if (k > 0 && k <= 2)
373                         {
374 #ifdef JP
375                                 (void)MATCH_KEY(KEY_MORE_BONUS2);
376 #else
377                                 if (' ' == *ptr) ptr++;
378 #endif
379                                 ADD_FLG(FLG_MORE_BONUS);
380                         }
381                         else
382                                 ptr = prev_ptr;
383                 }
384
385                 if (MATCH_KEY(KEY_WORTHLESS)) ADD_FLG(FLG_WORTHLESS);
386                 if (MATCH_KEY(KEY_EGO)) ADD_FLG(FLG_EGO);
387                 if (MATCH_KEY(KEY_GOOD)) ADD_FLG(FLG_GOOD);
388                 if (MATCH_KEY(KEY_NAMELESS)) ADD_FLG(FLG_NAMELESS);
389                 if (MATCH_KEY(KEY_AVERAGE)) ADD_FLG(FLG_AVERAGE);
390                 if (MATCH_KEY(KEY_RARE)) ADD_FLG(FLG_RARE);
391                 if (MATCH_KEY(KEY_COMMON)) ADD_FLG(FLG_COMMON);
392                 if (MATCH_KEY(KEY_WANTED)) ADD_FLG(FLG_WANTED);
393                 if (MATCH_KEY(KEY_UNIQUE)) ADD_FLG(FLG_UNIQUE);
394                 if (MATCH_KEY(KEY_HUMAN)) ADD_FLG(FLG_HUMAN);
395                 if (MATCH_KEY(KEY_UNREADABLE)) ADD_FLG(FLG_UNREADABLE);
396                 if (MATCH_KEY(KEY_REALM1)) ADD_FLG(FLG_REALM1);
397                 if (MATCH_KEY(KEY_REALM2)) ADD_FLG(FLG_REALM2);
398                 if (MATCH_KEY(KEY_FIRST)) ADD_FLG(FLG_FIRST);
399                 if (MATCH_KEY(KEY_SECOND)) ADD_FLG(FLG_SECOND);
400                 if (MATCH_KEY(KEY_THIRD)) ADD_FLG(FLG_THIRD);
401                 if (MATCH_KEY(KEY_FOURTH)) ADD_FLG(FLG_FOURTH);
402         }
403
404         /* Not yet found any noun */
405         prev_flg = -1;
406
407         if (MATCH_KEY2(KEY_ARTIFACT)) ADD_FLG_NOUN(FLG_ARTIFACT);
408
409         if (MATCH_KEY2(KEY_ITEMS)) ADD_FLG_NOUN(FLG_ITEMS);
410         else if (MATCH_KEY2(KEY_WEAPONS)) ADD_FLG_NOUN(FLG_WEAPONS);
411         else if (MATCH_KEY2(KEY_FAVORITE_WEAPONS)) ADD_FLG_NOUN(FLG_FAVORITE_WEAPONS);
412         else if (MATCH_KEY2(KEY_ARMORS)) ADD_FLG_NOUN(FLG_ARMORS);
413         else if (MATCH_KEY2(KEY_MISSILES)) ADD_FLG_NOUN(FLG_MISSILES);
414         else if (MATCH_KEY2(KEY_DEVICES)) ADD_FLG_NOUN(FLG_DEVICES);
415         else if (MATCH_KEY2(KEY_LIGHTS)) ADD_FLG_NOUN(FLG_LIGHTS);
416         else if (MATCH_KEY2(KEY_JUNKS)) ADD_FLG_NOUN(FLG_JUNKS);
417         else if (MATCH_KEY2(KEY_CORPSES)) ADD_FLG_NOUN(FLG_CORPSES);
418         else if (MATCH_KEY2(KEY_SPELLBOOKS)) ADD_FLG_NOUN(FLG_SPELLBOOKS);
419         else if (MATCH_KEY2(KEY_HAFTED)) ADD_FLG_NOUN(FLG_HAFTED);
420         else if (MATCH_KEY2(KEY_SHIELDS)) ADD_FLG_NOUN(FLG_SHIELDS);
421         else if (MATCH_KEY2(KEY_BOWS)) ADD_FLG_NOUN(FLG_BOWS);
422         else if (MATCH_KEY2(KEY_RINGS)) ADD_FLG_NOUN(FLG_RINGS);
423         else if (MATCH_KEY2(KEY_AMULETS)) ADD_FLG_NOUN(FLG_AMULETS);
424         else if (MATCH_KEY2(KEY_SUITS)) ADD_FLG_NOUN(FLG_SUITS);
425         else if (MATCH_KEY2(KEY_CLOAKS)) ADD_FLG_NOUN(FLG_CLOAKS);
426         else if (MATCH_KEY2(KEY_HELMS)) ADD_FLG_NOUN(FLG_HELMS);
427         else if (MATCH_KEY2(KEY_GLOVES)) ADD_FLG_NOUN(FLG_GLOVES);
428         else if (MATCH_KEY2(KEY_BOOTS)) ADD_FLG_NOUN(FLG_BOOTS);
429
430         /* Last 'keyword' must be at the correct location */
431         if (*ptr == ':')
432                 ptr++;
433 #ifdef JP
434         else if (ptr[0] == kanji_colon[0] && ptr[1] == kanji_colon[1])
435                 ptr += 2;
436 #endif
437         else if (*ptr == '\0')
438         {
439                 /* There was no noun */
440                 if (prev_flg == -1)
441
442                 /* Add extra word "items" */
443                 ADD_FLG_NOUN(FLG_ITEMS);
444         }
445         else
446         {
447                 /* Noun type? */
448                 if (prev_flg != -1)
449                 {
450                         /* A noun type keyword didn't end correctly */
451                         entry->flag[prev_flg/32] &= ~(1L<< (prev_flg%32));
452                         ptr = prev_ptr;
453                 }
454         }
455
456         /* Save this auto-picker entry line */
457         entry->name = string_make(ptr);
458         entry->action = act;
459         entry->insc = string_make(insc);
460
461         return TRUE;
462 }
463
464
465 /*
466  * Get auto-picker entry from o_ptr.
467  */
468 static void autopick_entry_from_object(autopick_type *entry, object_type *o_ptr)
469 {
470         /* Assume that object name is to be added */
471         bool name = TRUE;
472
473 #ifdef JP
474         /* エゴ銘が邪魔かもしれないので、デフォルトで「^」は付けない */
475         bool bol_mark = FALSE;
476 #else
477         /* We can always use the ^ mark in English */
478         bool bol_mark = TRUE;
479 #endif
480
481         GAME_TEXT name_str[MAX_NLEN];
482
483         /* Initialize name string */
484         name_str[0] = '\0';
485
486         entry->insc = string_make(quark_str(o_ptr->inscription));
487         entry->action = DO_AUTOPICK | DO_DISPLAY;
488         entry->flag[0] = entry->flag[1] = 0L;
489         entry->dice = 0;
490
491         /* Unaware */
492         if (!object_is_aware(o_ptr))
493         {
494                 ADD_FLG(FLG_UNAWARE);
495                 bol_mark = TRUE;
496         }
497
498         /* Not really identified */
499         else if (!object_is_known(o_ptr))
500         {
501                 if (!(o_ptr->ident & IDENT_SENSE))
502                 {
503                         ADD_FLG(FLG_UNIDENTIFIED);
504                         bol_mark = TRUE;
505                 }
506                 else
507                 {
508                         /* Pseudo-identified */
509                         switch (o_ptr->feeling)
510                         {
511                         case FEEL_AVERAGE:
512                         case FEEL_GOOD:
513                                 ADD_FLG(FLG_NAMELESS);
514                                 bol_mark = TRUE;
515                                 break;
516
517                         case FEEL_BROKEN:
518                         case FEEL_CURSED:
519                                 ADD_FLG(FLG_NAMELESS);
520                                 ADD_FLG(FLG_WORTHLESS);
521                                 bol_mark = TRUE;
522                                 break;
523
524                         case FEEL_TERRIBLE:
525                         case FEEL_WORTHLESS:
526                                 ADD_FLG(FLG_WORTHLESS);
527                                 break;
528
529                         case FEEL_EXCELLENT:
530                                 ADD_FLG(FLG_EGO);
531                                 break;
532
533                         case FEEL_UNCURSED:
534                                 /* XXX No appropriate flag */
535                                 /* ADD_FLG(); */
536                                 break;
537
538                         default:
539                                 /* Never reach here */
540                                 break;
541                         }
542                 }
543         }
544
545         /* Identified */
546         else
547         {
548                 /* Ego objects */
549                 if (object_is_ego(o_ptr))
550                 {
551                         if (object_is_weapon_armour_ammo(o_ptr))
552                         {
553                                 /*
554                                  * Base name of ego weapons and armors
555                                  * are almost meaningless.
556                                  * Register the ego type only.
557                                  */
558                                 ego_item_type *e_ptr = &e_info[o_ptr->name2];
559 #ifdef JP
560                                 /* エゴ銘には「^」マークが使える */
561                                 sprintf(name_str, "^%s", e_name + e_ptr->name);
562 #else
563                                 /* We ommit the basename and cannot use the ^ mark */
564                                 strcpy(name_str, e_name + e_ptr->name);
565 #endif
566
567                                 /* Don't use the object description */
568                                 name = FALSE;
569
570                                 /* Restrict to 'common' equipments */
571                                 if (!object_is_rare(o_ptr)) ADD_FLG(FLG_COMMON);
572                         }
573
574                         ADD_FLG(FLG_EGO);
575                 }
576
577                 /* Artifact */
578                 else if (object_is_artifact(o_ptr))
579                         ADD_FLG(FLG_ARTIFACT);
580
581                 /* Non-ego, non-artifact */
582                 else
583                 {
584                         /* Wearable nameless object */
585                         if (object_is_equipment(o_ptr))
586                                 ADD_FLG(FLG_NAMELESS);
587
588                         bol_mark = TRUE;
589                 }
590
591         }
592
593         /* Melee weapon with boosted dice */
594         if (object_is_melee_weapon(o_ptr))
595         {
596                 object_kind *k_ptr = &k_info[o_ptr->k_idx];
597
598                 if ((o_ptr->dd != k_ptr->dd) || (o_ptr->ds != k_ptr->ds))
599                         ADD_FLG(FLG_BOOSTED);
600         }
601
602         /* Wanted monster's corpse */
603         if (object_is_shoukinkubi(o_ptr))
604         {
605                 REM_FLG(FLG_WORTHLESS);
606                 ADD_FLG(FLG_WANTED);
607         }
608
609         if ((o_ptr->tval == TV_CORPSE || o_ptr->tval == TV_STATUE)
610             && (r_info[o_ptr->pval].flags1 & RF1_UNIQUE))
611         {
612                 ADD_FLG(FLG_UNIQUE);
613         }
614
615         if (o_ptr->tval == TV_CORPSE && my_strchr("pht", r_info[o_ptr->pval].d_char))
616         {
617                 ADD_FLG(FLG_HUMAN);
618         }
619
620         if (o_ptr->tval >= TV_LIFE_BOOK &&
621             !check_book_realm(o_ptr->tval, o_ptr->sval))
622         {
623                 ADD_FLG(FLG_UNREADABLE);
624                 if (o_ptr->tval != TV_ARCANE_BOOK) name = FALSE;
625         }
626
627         if (REALM1_BOOK == o_ptr->tval &&
628             p_ptr->pclass != CLASS_SORCERER &&
629             p_ptr->pclass != CLASS_RED_MAGE)
630         {
631                 ADD_FLG(FLG_REALM1);
632                 name = FALSE;
633         }
634
635         if (REALM2_BOOK == o_ptr->tval &&
636             p_ptr->pclass != CLASS_SORCERER &&
637             p_ptr->pclass != CLASS_RED_MAGE)
638         {
639                 ADD_FLG(FLG_REALM2);
640                 name = FALSE;
641         }
642
643         if (o_ptr->tval >= TV_LIFE_BOOK && 0 == o_ptr->sval)
644                 ADD_FLG(FLG_FIRST);
645         if (o_ptr->tval >= TV_LIFE_BOOK && 1 == o_ptr->sval)
646                 ADD_FLG(FLG_SECOND);
647         if (o_ptr->tval >= TV_LIFE_BOOK && 2 == o_ptr->sval)
648                 ADD_FLG(FLG_THIRD);
649         if (o_ptr->tval >= TV_LIFE_BOOK && 3 == o_ptr->sval)
650                 ADD_FLG(FLG_FOURTH);
651
652         if (object_is_ammo(o_ptr))
653                 ADD_FLG(FLG_MISSILES);
654         else if (o_ptr->tval == TV_SCROLL || o_ptr->tval == TV_STAFF
655                  || o_ptr->tval == TV_WAND || o_ptr->tval == TV_ROD)
656                 ADD_FLG(FLG_DEVICES);
657         else if (o_ptr->tval == TV_LITE)
658                 ADD_FLG(FLG_LIGHTS);
659         else if (o_ptr->tval == TV_SKELETON || o_ptr->tval == TV_BOTTLE
660                  || o_ptr->tval == TV_JUNK || o_ptr->tval == TV_STATUE)
661                 ADD_FLG(FLG_JUNKS);
662         else if (o_ptr->tval == TV_CORPSE)
663                 ADD_FLG(FLG_CORPSES);
664         else if (o_ptr->tval >= TV_LIFE_BOOK)
665                 ADD_FLG(FLG_SPELLBOOKS);
666         else if (o_ptr->tval == TV_POLEARM || o_ptr->tval == TV_SWORD
667                  || o_ptr->tval == TV_DIGGING || o_ptr->tval == TV_HAFTED)
668                 ADD_FLG(FLG_WEAPONS);
669         else if (o_ptr->tval == TV_SHIELD)
670                 ADD_FLG(FLG_SHIELDS);
671         else if (o_ptr->tval == TV_BOW)
672                 ADD_FLG(FLG_BOWS);
673         else if (o_ptr->tval == TV_RING)
674                 ADD_FLG(FLG_RINGS);
675         else if (o_ptr->tval == TV_AMULET)
676                 ADD_FLG(FLG_AMULETS);
677         else if (o_ptr->tval == TV_DRAG_ARMOR || o_ptr->tval == TV_HARD_ARMOR ||
678                  o_ptr->tval == TV_SOFT_ARMOR)
679                 ADD_FLG(FLG_SUITS);
680         else if (o_ptr->tval == TV_CLOAK)
681                 ADD_FLG(FLG_CLOAKS);
682         else if (o_ptr->tval == TV_HELM)
683                 ADD_FLG(FLG_HELMS);
684         else if (o_ptr->tval == TV_GLOVES)
685                 ADD_FLG(FLG_GLOVES);
686         else if (o_ptr->tval == TV_BOOTS)
687                 ADD_FLG(FLG_BOOTS);
688
689         /* Prepare the object description */
690         if (name)
691         {
692                 GAME_TEXT o_name[MAX_NLEN];
693
694                 object_desc(o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL | OD_NAME_ONLY));
695
696                 /*
697                  * If necessary, add a '^' which indicates the
698                  * beginning of line.
699                  */
700                 sprintf(name_str, "%s%s", bol_mark ? "^" : "", o_name);
701         }
702
703         /* Register the name in lowercase */
704         str_tolower(name_str);
705         entry->name = string_make(name_str);
706
707         return;
708 }
709
710
711 /*
712  * A function to delete entry
713  */
714 static void autopick_free_entry(autopick_type *entry)
715 {
716         string_free(entry->name);
717         string_free(entry->insc);
718         entry->name = NULL;
719         entry->insc = NULL;
720 }
721
722
723 #define MAX_AUTOPICK_DEFAULT 200
724
725 /*
726  * Initialize the autopick
727  */
728 static void init_autopick(void)
729 {
730         static const char easy_autopick_inscription[] = "(:=g";
731         autopick_type entry;
732         int i;
733
734         if (!autopick_list)
735         {
736                 max_max_autopick = MAX_AUTOPICK_DEFAULT;
737                 C_MAKE(autopick_list, max_max_autopick, autopick_type);
738                 max_autopick = 0;
739         }
740
741         /* Clear old entries */
742         for( i = 0; i < max_autopick; i++)
743                 autopick_free_entry(&autopick_list[i]);
744
745         max_autopick = 0;
746
747         /* There is always one entry "=g" */
748         autopick_new_entry(&entry, easy_autopick_inscription, TRUE);
749         autopick_list[max_autopick++] = entry;
750 }
751
752
753 #define PT_DEFAULT 0
754 #define PT_WITH_PNAME 1
755
756 /*
757  *  Get file name for autopick preference
758  */
759 static concptr pickpref_filename(int filename_mode)
760 {
761         static const char namebase[] = _("picktype", "pickpref");
762
763         switch (filename_mode)
764         {
765         case PT_DEFAULT:
766                 return format("%s.prf", namebase);
767
768         case PT_WITH_PNAME:
769                 return format("%s-%s.prf", namebase, player_base);
770
771         default:
772                 return NULL;
773         }
774 }
775
776
777 /*
778  * Load an autopick preference file
779  */
780 void autopick_load_pref(bool disp_mes)
781 {
782         GAME_TEXT buf[80];
783         errr err;
784
785         /* Free old entries */
786         init_autopick();
787
788         /* Try a filename with player name */
789         my_strcpy(buf, pickpref_filename(PT_WITH_PNAME), sizeof(buf));
790
791         /* Load the file */
792         err = process_autopick_file(buf);
793
794         if (err == 0 && disp_mes)
795         {
796                 /* Success */
797                 msg_format(_("%sを読み込みました。", "Loaded '%s'."), buf);
798         }
799
800         /* No file found */
801         if (0 > err)
802         {
803                 /* Use default name */
804                 my_strcpy(buf, pickpref_filename(PT_DEFAULT), sizeof(buf));
805
806                 /* Load the file */
807                 err = process_autopick_file(buf);
808
809                 if (err == 0 && disp_mes)
810                 {
811                         /* Success */
812                         msg_format(_("%sを読み込みました。", "Loaded '%s'."), buf);
813                 }
814         }
815
816         if (err && disp_mes)
817         {
818                 /* Failed */
819                 msg_print(_("自動拾い設定ファイルの読み込みに失敗しました。", "Failed to reload autopick preference."));
820         }
821 }
822
823
824 /*
825  * Add one line to autopick_list[]
826  */
827 static void add_autopick_list(autopick_type *entry)
828 {
829         /* There is no enough space to add one line */
830         if (max_autopick >= max_max_autopick)
831         {
832                 int old_max_max_autopick = max_max_autopick;
833                 autopick_type *old_autopick_list = autopick_list;
834
835                 /* Increase size of list */
836                 max_max_autopick += MAX_AUTOPICK_DEFAULT;
837
838                 /* Allocate */
839                 C_MAKE(autopick_list, max_max_autopick, autopick_type);
840
841                 /* Copy from old list to new list */
842                 (void)C_COPY(autopick_list, old_autopick_list, old_max_max_autopick, autopick_type);
843
844                 /* Kill old list */
845                 C_KILL(old_autopick_list, old_max_max_autopick, autopick_type);
846         }
847
848         /* Add one line */
849         autopick_list[max_autopick] = *entry;
850
851         max_autopick++;
852 }
853
854
855 /*
856  *  Process line for auto picker/destroyer.
857  */
858 errr process_autopick_file_command(char *buf)
859 {
860         autopick_type an_entry, *entry = &an_entry;
861         int i;
862
863         /* Nuke illegal char */
864         for(i = 0; buf[i]; i++)
865         {
866 #ifdef JP
867                 if (iskanji(buf[i]))
868                 {
869                         i++;
870                         continue;
871                 }
872 #endif
873                 if (iswspace(buf[i]) && buf[i] != ' ')
874                         break;
875         }
876         buf[i] = 0;
877         
878         if (!autopick_new_entry(entry, buf, FALSE)) return 0;
879
880         /* Already has the same entry? */ 
881         for(i = 0; i < max_autopick; i++)
882                 if(!strcmp(entry->name, autopick_list[i].name)
883                    && entry->flag[0] == autopick_list[i].flag[0]
884                    && entry->flag[1] == autopick_list[i].flag[1]
885                    && entry->dice == autopick_list[i].dice
886                    && entry->bonus == autopick_list[i].bonus)
887                 {
888                         autopick_free_entry(entry);
889                         return 0;
890                 }
891
892         add_autopick_list(entry);
893         return 0;
894 }
895
896
897 /*
898  * Reconstruct preference line from entry
899  */
900 concptr autopick_line_from_entry(autopick_type *entry)
901 {
902         char buf[MAX_LINELEN];
903         char *ptr;
904         bool sepa_flag = TRUE;
905
906         *buf = '\0';
907         if (!(entry->action & DO_DISPLAY)) strcat(buf, "(");
908         if (entry->action & DO_QUERY_AUTOPICK) strcat(buf, ";");
909         if (entry->action & DO_AUTODESTROY) strcat(buf, "!");
910         if (entry->action & DONT_AUTOPICK) strcat(buf, "~");
911
912         ptr = buf;
913
914         if (IS_FLG(FLG_ALL)) ADD_KEY(KEY_ALL);
915         if (IS_FLG(FLG_COLLECTING)) ADD_KEY(KEY_COLLECTING);
916         if (IS_FLG(FLG_UNAWARE)) ADD_KEY(KEY_UNAWARE);
917         if (IS_FLG(FLG_UNIDENTIFIED)) ADD_KEY(KEY_UNIDENTIFIED);
918         if (IS_FLG(FLG_IDENTIFIED)) ADD_KEY(KEY_IDENTIFIED);
919         if (IS_FLG(FLG_STAR_IDENTIFIED)) ADD_KEY(KEY_STAR_IDENTIFIED);
920         if (IS_FLG(FLG_BOOSTED)) ADD_KEY(KEY_BOOSTED);
921
922         if (IS_FLG(FLG_MORE_DICE))
923         {
924                 ADD_KEY(KEY_MORE_THAN);
925                 strcat(ptr, format("%d", entry->dice));
926                 ADD_KEY(KEY_DICE);
927         }
928
929         if (IS_FLG(FLG_MORE_BONUS))
930         {
931                 ADD_KEY(KEY_MORE_BONUS);
932                 strcat(ptr, format("%d", entry->bonus));
933                 ADD_KEY(KEY_MORE_BONUS2);
934         }
935
936         if (IS_FLG(FLG_UNREADABLE)) ADD_KEY(KEY_UNREADABLE);
937         if (IS_FLG(FLG_REALM1)) ADD_KEY(KEY_REALM1);
938         if (IS_FLG(FLG_REALM2)) ADD_KEY(KEY_REALM2);
939         if (IS_FLG(FLG_FIRST)) ADD_KEY(KEY_FIRST);
940         if (IS_FLG(FLG_SECOND)) ADD_KEY(KEY_SECOND);
941         if (IS_FLG(FLG_THIRD)) ADD_KEY(KEY_THIRD);
942         if (IS_FLG(FLG_FOURTH)) ADD_KEY(KEY_FOURTH);
943         if (IS_FLG(FLG_WANTED)) ADD_KEY(KEY_WANTED);
944         if (IS_FLG(FLG_UNIQUE)) ADD_KEY(KEY_UNIQUE);
945         if (IS_FLG(FLG_HUMAN)) ADD_KEY(KEY_HUMAN);
946         if (IS_FLG(FLG_WORTHLESS)) ADD_KEY(KEY_WORTHLESS);
947         if (IS_FLG(FLG_GOOD)) ADD_KEY(KEY_GOOD);
948         if (IS_FLG(FLG_NAMELESS)) ADD_KEY(KEY_NAMELESS);
949         if (IS_FLG(FLG_AVERAGE)) ADD_KEY(KEY_AVERAGE);
950         if (IS_FLG(FLG_RARE)) ADD_KEY(KEY_RARE);
951         if (IS_FLG(FLG_COMMON)) ADD_KEY(KEY_COMMON);
952         if (IS_FLG(FLG_EGO)) ADD_KEY(KEY_EGO);
953
954         if (IS_FLG(FLG_ARTIFACT)) ADD_KEY(KEY_ARTIFACT);
955
956         if (IS_FLG(FLG_ITEMS)) ADD_KEY2(KEY_ITEMS);
957         else if (IS_FLG(FLG_WEAPONS)) ADD_KEY2(KEY_WEAPONS);
958         else if (IS_FLG(FLG_FAVORITE_WEAPONS)) ADD_KEY2(KEY_FAVORITE_WEAPONS);
959         else if (IS_FLG(FLG_ARMORS)) ADD_KEY2(KEY_ARMORS);
960         else if (IS_FLG(FLG_MISSILES)) ADD_KEY2(KEY_MISSILES);
961         else if (IS_FLG(FLG_DEVICES)) ADD_KEY2(KEY_DEVICES);
962         else if (IS_FLG(FLG_LIGHTS)) ADD_KEY2(KEY_LIGHTS);
963         else if (IS_FLG(FLG_JUNKS)) ADD_KEY2(KEY_JUNKS);
964         else if (IS_FLG(FLG_CORPSES)) ADD_KEY2(KEY_CORPSES);
965         else if (IS_FLG(FLG_SPELLBOOKS)) ADD_KEY2(KEY_SPELLBOOKS);
966         else if (IS_FLG(FLG_HAFTED)) ADD_KEY2(KEY_HAFTED);
967         else if (IS_FLG(FLG_SHIELDS)) ADD_KEY2(KEY_SHIELDS);
968         else if (IS_FLG(FLG_BOWS)) ADD_KEY2(KEY_BOWS);
969         else if (IS_FLG(FLG_RINGS)) ADD_KEY2(KEY_RINGS);
970         else if (IS_FLG(FLG_AMULETS)) ADD_KEY2(KEY_AMULETS);
971         else if (IS_FLG(FLG_SUITS)) ADD_KEY2(KEY_SUITS);
972         else if (IS_FLG(FLG_CLOAKS)) ADD_KEY2(KEY_CLOAKS);
973         else if (IS_FLG(FLG_HELMS)) ADD_KEY2(KEY_HELMS);
974         else if (IS_FLG(FLG_GLOVES)) ADD_KEY2(KEY_GLOVES);
975         else if (IS_FLG(FLG_BOOTS)) ADD_KEY2(KEY_BOOTS);
976
977         /* You don't need sepalator after adjective */
978         /* 'artifact' is not true adjective */
979         else if (!IS_FLG(FLG_ARTIFACT))
980                 sepa_flag = FALSE;
981
982         if (entry->name && entry->name[0])
983         {
984                 int i, j = 0;
985
986                 if (sepa_flag) strcat(buf, ":");
987
988                 i = strlen(buf);
989                 while (entry->name[j] && i < MAX_LINELEN - 2 - 1)
990                 {
991 #ifdef JP
992                         if (iskanji(entry->name[j]))
993                                 buf[i++] = entry->name[j++];
994 #endif
995                         buf[i++] = entry->name[j++];
996                 }
997                 buf[i] = '\0';
998         }
999
1000         if (entry->insc)
1001         {
1002                 int i, j = 0;
1003                 strcat(buf, "#");
1004                 i = strlen(buf);
1005
1006                 while (entry->insc[j] && i < MAX_LINELEN - 2)
1007                 {
1008 #ifdef JP
1009                         if (iskanji(entry->insc[j]))
1010                                 buf[i++] = entry->insc[j++];
1011 #endif
1012                         buf[i++] = entry->insc[j++];
1013                 }
1014                 buf[i] = '\0';
1015         }
1016
1017         return string_make(buf);
1018 }
1019
1020
1021 /*
1022  * Reconstruct preference line from entry and kill entry
1023  */
1024 static concptr autopick_line_from_entry_kill(autopick_type *entry)
1025 {
1026         concptr ptr = autopick_line_from_entry(entry);
1027
1028         /* Free memory for original entry */
1029         autopick_free_entry(entry);
1030
1031         return ptr;
1032 }
1033
1034
1035 /*
1036  * A function for Auto-picker/destroyer
1037  * Examine whether the object matches to the entry
1038  */
1039 static bool is_autopick_aux(object_type *o_ptr, autopick_type *entry, concptr o_name)
1040 {
1041         int j;
1042         concptr ptr = entry->name;
1043
1044         /*** Unaware items ***/
1045         if (IS_FLG(FLG_UNAWARE) && object_is_aware(o_ptr))
1046                 return FALSE;
1047
1048         /*** Unidentified ***/
1049         if (IS_FLG(FLG_UNIDENTIFIED)
1050             && (object_is_known(o_ptr) || (o_ptr->ident & IDENT_SENSE)))
1051                 return FALSE;
1052
1053         /*** Identified ***/
1054         if (IS_FLG(FLG_IDENTIFIED) && !object_is_known(o_ptr))
1055                 return FALSE;
1056
1057         /*** *Identified* ***/
1058         if (IS_FLG(FLG_STAR_IDENTIFIED) &&
1059             (!object_is_known(o_ptr) || !(o_ptr->ident & IDENT_MENTAL)))
1060                 return FALSE;
1061
1062         /*** Dice boosted (weapon of slaying) ***/
1063         if (IS_FLG(FLG_BOOSTED))
1064         {
1065                 object_kind *k_ptr = &k_info[o_ptr->k_idx];
1066
1067                 /* Require melee weapon */
1068                 if (!object_is_melee_weapon(o_ptr))
1069                         return FALSE;
1070
1071                 /* Require boosted dice */
1072                 if ((o_ptr->dd == k_ptr->dd) && (o_ptr->ds == k_ptr->ds))
1073                         return FALSE;
1074                 
1075                 /* In Vault Quest, Dice must be hide.*/
1076                 if(!object_is_known(o_ptr) && object_is_quest_target(o_ptr))
1077                 {
1078                         return FALSE;
1079                 }
1080         }
1081
1082         /*** Weapons which dd*ds is more than nn ***/
1083         if (IS_FLG(FLG_MORE_DICE))
1084         {
1085                 if (o_ptr->dd * o_ptr->ds < entry->dice)
1086                         return FALSE;
1087         }
1088                                 
1089         /*** Weapons whic dd*ds is more than nn ***/
1090         if (IS_FLG(FLG_MORE_BONUS))
1091         {
1092                 if (!object_is_known(o_ptr)) return FALSE;
1093
1094                 if (o_ptr->pval)
1095                 {
1096                         if (o_ptr->pval < entry->bonus) return FALSE;
1097                 }
1098                 else
1099                 {
1100                         if (o_ptr->to_h < entry->bonus &&
1101                             o_ptr->to_d < entry->bonus &&
1102                             o_ptr->to_a < entry->bonus &&
1103                             o_ptr->pval < entry->bonus)
1104                                 return FALSE;
1105                 }
1106         }
1107                                 
1108         /*** Worthless items ***/
1109         if (IS_FLG(FLG_WORTHLESS) && object_value(o_ptr) > 0)
1110                 return FALSE;
1111
1112         /*** Artifact object ***/
1113         if (IS_FLG(FLG_ARTIFACT))
1114         {
1115                 if (!object_is_known(o_ptr) || !object_is_artifact(o_ptr))
1116                         return FALSE;
1117         }
1118
1119         /*** Ego object ***/
1120         if (IS_FLG(FLG_EGO))
1121         {
1122                 /* Need to be an ego item */
1123                 if (!object_is_ego(o_ptr)) return FALSE;
1124
1125                 /* Need to be known to be an ego */
1126                 if (!object_is_known(o_ptr) &&
1127                     !((o_ptr->ident & IDENT_SENSE) && o_ptr->feeling == FEEL_EXCELLENT))
1128                         return FALSE;
1129         }
1130
1131         /*** Good ***/
1132         if (IS_FLG(FLG_GOOD))
1133         {
1134                 if (!object_is_equipment(o_ptr)) return FALSE;
1135
1136                 /* Identified */
1137                 if (object_is_known(o_ptr))
1138                 {
1139                         /* Artifacts and Ego objects are not okay */
1140                         if (!object_is_nameless(o_ptr))
1141                                 return FALSE;
1142
1143                         /* Average are not okay */
1144                         if (o_ptr->to_a <= 0 && (o_ptr->to_h + o_ptr->to_d) <= 0)
1145                                 return FALSE;
1146                 }
1147
1148                 /* Pseudo-identified */
1149                 else if (o_ptr->ident & IDENT_SENSE)
1150                 {
1151                         switch (o_ptr->feeling)
1152                         {
1153                         case FEEL_GOOD:
1154                                 /* It's good */
1155                                 break;
1156
1157                         default:
1158                                 /* It's not good */
1159                                 return FALSE;
1160                         }
1161                 }
1162
1163                 /* Unidentified */
1164                 else
1165                 {
1166                         /* Not known to be good */
1167                         return FALSE;
1168                 }
1169         }
1170
1171         /*** Nameless ***/
1172         if (IS_FLG(FLG_NAMELESS))
1173         {
1174                 if (!object_is_equipment(o_ptr)) return FALSE;
1175
1176                 /* Identified */
1177                 if (object_is_known(o_ptr))
1178                 {
1179                         /* Artifacts and Ego objects are not okay */
1180                         if (!object_is_nameless(o_ptr))
1181                                 return FALSE;
1182                 }
1183
1184                 /* Pseudo-identified */
1185                 else if (o_ptr->ident & IDENT_SENSE)
1186                 {
1187                         switch (o_ptr->feeling)
1188                         {
1189                         case FEEL_AVERAGE:
1190                         case FEEL_GOOD:
1191                         case FEEL_BROKEN:
1192                         case FEEL_CURSED:
1193                                 /* It's nameless */
1194                                 break;
1195
1196                         default:
1197                                 /* It's not nameless */
1198                                 return FALSE;
1199                         }
1200                 }
1201
1202                 /* Unidentified */
1203                 else
1204                 {
1205                         /* Not known to be nameless */
1206                         return FALSE;
1207                 }
1208         }
1209
1210         /*** Average ***/
1211         if (IS_FLG(FLG_AVERAGE))
1212         {
1213                 if (!object_is_equipment(o_ptr)) return FALSE;
1214
1215                 /* Identified */
1216                 if (object_is_known(o_ptr))
1217                 {
1218                         /* Artifacts and Ego objects are not okay */
1219                         if (!object_is_nameless(o_ptr))
1220                                 return FALSE;
1221
1222                         /* Cursed or broken objects are not okay */
1223                         if (object_is_cursed(o_ptr) || object_is_broken(o_ptr))
1224                                 return FALSE;
1225
1226                         /* Good are not okay */
1227                         if (o_ptr->to_a > 0 || (o_ptr->to_h + o_ptr->to_d) > 0)
1228                                 return FALSE;
1229                 }
1230
1231                 /* Pseudo-identified */
1232                 else if (o_ptr->ident & IDENT_SENSE)
1233                 {
1234                         switch (o_ptr->feeling)
1235                         {
1236                         case FEEL_AVERAGE:
1237                                 /* It's average */
1238                                 break;
1239
1240                         default:
1241                                 /* It's not average */
1242                                 return FALSE;
1243                         }
1244                 }
1245
1246                 /* Unidentified */
1247                 else
1248                 {
1249                         /* Not known to be average */
1250                         return FALSE;
1251                 }
1252         }
1253
1254         /*** Rere equipments ***/
1255         if (IS_FLG(FLG_RARE) && !object_is_rare(o_ptr))
1256                 return FALSE;
1257
1258         /*** Common equipments ***/
1259         if (IS_FLG(FLG_COMMON) && object_is_rare(o_ptr))
1260                 return FALSE;
1261
1262         /*** Wanted monster's corpse/skeletons ***/
1263         if (IS_FLG(FLG_WANTED) && !object_is_shoukinkubi(o_ptr))
1264                 return FALSE;
1265
1266         /*** Unique monster's corpse/skeletons/statues ***/
1267         if (IS_FLG(FLG_UNIQUE) &&
1268             ((o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_STATUE) ||
1269              !(r_info[o_ptr->pval].flags1 & RF1_UNIQUE)))
1270                 return FALSE;
1271
1272         /*** Human corpse/skeletons (for Daemon magic) ***/
1273         if (IS_FLG(FLG_HUMAN) &&
1274             (o_ptr->tval != TV_CORPSE ||
1275              !my_strchr("pht", r_info[o_ptr->pval].d_char)))
1276                 return FALSE;
1277
1278         /*** Unreadable spellbooks ***/
1279         if (IS_FLG(FLG_UNREADABLE) &&
1280             (o_ptr->tval < TV_LIFE_BOOK ||
1281              check_book_realm(o_ptr->tval, o_ptr->sval)))
1282                 return FALSE;
1283
1284         /*** First realm spellbooks ***/
1285         if (IS_FLG(FLG_REALM1) && 
1286             (REALM1_BOOK != o_ptr->tval ||
1287              p_ptr->pclass == CLASS_SORCERER ||
1288              p_ptr->pclass == CLASS_RED_MAGE))
1289                 return FALSE;
1290
1291         /*** Second realm spellbooks ***/
1292         if (IS_FLG(FLG_REALM2) &&
1293             (REALM2_BOOK != o_ptr->tval ||
1294              p_ptr->pclass == CLASS_SORCERER ||
1295              p_ptr->pclass == CLASS_RED_MAGE))
1296                 return FALSE;
1297
1298         /*** First rank spellbooks ***/
1299         if (IS_FLG(FLG_FIRST) &&
1300             (o_ptr->tval < TV_LIFE_BOOK || 0 != o_ptr->sval))
1301                 return FALSE;
1302
1303         /*** Second rank spellbooks ***/
1304         if (IS_FLG(FLG_SECOND) &&
1305             (o_ptr->tval < TV_LIFE_BOOK || 1 != o_ptr->sval))
1306                 return FALSE;
1307
1308         /*** Third rank spellbooks ***/
1309         if (IS_FLG(FLG_THIRD) && 
1310             (o_ptr->tval < TV_LIFE_BOOK || 2 != o_ptr->sval))
1311                 return FALSE;
1312
1313         /*** Fourth rank spellbooks ***/
1314         if (IS_FLG(FLG_FOURTH) &&
1315             (o_ptr->tval < TV_LIFE_BOOK || 3 != o_ptr->sval))
1316                 return FALSE;
1317
1318         /*** Items ***/
1319         if (IS_FLG(FLG_WEAPONS))
1320         {
1321                 if (!object_is_weapon(o_ptr))
1322                         return FALSE;
1323         }
1324         else if (IS_FLG(FLG_FAVORITE_WEAPONS))
1325         {
1326                 if (!object_is_favorite(o_ptr))
1327                         return FALSE;
1328         }
1329         else if (IS_FLG(FLG_ARMORS))
1330         {
1331                 if (!object_is_armour(o_ptr))
1332                         return FALSE;
1333         }
1334         else if (IS_FLG(FLG_MISSILES))
1335         {
1336                 if (!object_is_ammo(o_ptr)) return FALSE;
1337         }
1338         else if (IS_FLG(FLG_DEVICES))
1339         {
1340                 switch(o_ptr->tval)
1341                 {
1342                 case TV_SCROLL: case TV_STAFF: case TV_WAND: case TV_ROD:
1343                         break;
1344                 default: return FALSE;
1345                 }
1346         }
1347         else if (IS_FLG(FLG_LIGHTS))
1348         {
1349                 if (!(o_ptr->tval == TV_LITE))
1350                         return FALSE;
1351         }
1352         else if (IS_FLG(FLG_JUNKS))
1353         {
1354                 switch(o_ptr->tval)
1355                 {
1356                 case TV_SKELETON: case TV_BOTTLE:
1357                 case TV_JUNK: case TV_STATUE:
1358                         break;
1359                 default: return FALSE;
1360                 }
1361         }
1362         else if (IS_FLG(FLG_CORPSES))
1363         {
1364                 if (o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_SKELETON)
1365                         return FALSE;
1366         }
1367         else if (IS_FLG(FLG_SPELLBOOKS))
1368         {
1369                 if (!(o_ptr->tval >= TV_LIFE_BOOK))
1370                         return FALSE;
1371         }
1372         else if (IS_FLG(FLG_HAFTED))
1373         {
1374                 if (!(o_ptr->tval == TV_HAFTED))
1375                         return FALSE;
1376         }
1377         else if (IS_FLG(FLG_SHIELDS))
1378         {
1379                 if (!(o_ptr->tval == TV_SHIELD))
1380                         return FALSE;
1381         }
1382         else if (IS_FLG(FLG_BOWS))
1383         {
1384                 if (!(o_ptr->tval == TV_BOW))
1385                         return FALSE;
1386         }
1387         else if (IS_FLG(FLG_RINGS))
1388         {
1389                 if (!(o_ptr->tval == TV_RING))
1390                         return FALSE;
1391         }
1392         else if (IS_FLG(FLG_AMULETS))
1393         {
1394                 if (!(o_ptr->tval == TV_AMULET))
1395                         return FALSE;
1396         }
1397         else if (IS_FLG(FLG_SUITS))
1398         {
1399                 if (!(o_ptr->tval == TV_DRAG_ARMOR ||
1400                       o_ptr->tval == TV_HARD_ARMOR ||
1401                       o_ptr->tval == TV_SOFT_ARMOR))
1402                         return FALSE;
1403         }
1404         else if (IS_FLG(FLG_CLOAKS))
1405         {
1406                 if (!(o_ptr->tval == TV_CLOAK))
1407                         return FALSE;
1408         }
1409         else if (IS_FLG(FLG_HELMS))
1410         {
1411                 if (!(o_ptr->tval == TV_CROWN || o_ptr->tval == TV_HELM))
1412                         return FALSE;
1413         }
1414         else if (IS_FLG(FLG_GLOVES))
1415         {
1416                 if (!(o_ptr->tval == TV_GLOVES))
1417                         return FALSE;
1418         }
1419         else if (IS_FLG(FLG_BOOTS))
1420         {
1421                 if (!(o_ptr->tval == TV_BOOTS))
1422                         return FALSE;
1423         }
1424
1425         /* Keyword don't match */
1426         if (*ptr == '^')
1427         {
1428                 ptr++;
1429                 if (strncmp(o_name, ptr, strlen(ptr))) return FALSE;
1430         }
1431         else
1432         {
1433                 if (!my_strstr(o_name, ptr)) return FALSE;
1434         }
1435
1436         /* TRUE when it need not to be 'collecting' */
1437         if (!IS_FLG(FLG_COLLECTING)) return TRUE;
1438
1439         /* Check if there is a same item */
1440         for (j = 0; j < INVEN_PACK; j++)
1441         {
1442                 /*
1443                  * 'Collecting' means the item must be absorbed 
1444                  * into an p_ptr->inventory_list slot.
1445                  * But an item can not be absorbed into itself!
1446                  */
1447                 if ((&p_ptr->inventory_list[j] != o_ptr) &&
1448                     object_similar(&p_ptr->inventory_list[j], o_ptr))
1449                         return TRUE;
1450         }
1451
1452         /* Not collecting */
1453         return FALSE;
1454 }
1455
1456
1457 /*
1458  * A function for Auto-picker/destroyer
1459  * Examine whether the object matches to the list of keywords or not.
1460  */
1461 int is_autopick(object_type *o_ptr)
1462 {
1463         int i;
1464         GAME_TEXT o_name[MAX_NLEN];
1465
1466         if (o_ptr->tval == TV_GOLD) return -1;
1467
1468         /* Prepare object name string first */
1469         object_desc(o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
1470
1471         /* Convert the string to lower case */
1472         str_tolower(o_name);
1473
1474         /* Look for a matching entry in the list */     
1475         for (i=0; i < max_autopick; i++)
1476         {
1477                 autopick_type *entry = &autopick_list[i];
1478
1479                 if (is_autopick_aux(o_ptr, entry, o_name)) return i;
1480         }
1481
1482         /* No matching entry */
1483         return -1;
1484 }
1485
1486
1487 /*
1488  *  Auto inscription
1489  */
1490 static void auto_inscribe_item(object_type *o_ptr, int idx)
1491 {
1492         /* Are there auto-inscription? */
1493         if (idx < 0 || !autopick_list[idx].insc) return;
1494
1495         if (!o_ptr->inscription)
1496                 o_ptr->inscription = quark_add(autopick_list[idx].insc);
1497
1498         /* Redraw inscription */
1499         p_ptr->window |= (PW_EQUIP | PW_INVEN);
1500
1501         /* {.} and {$} effect p_ptr->warning and TRC_TELEPORT_SELF */
1502         p_ptr->update |= (PU_BONUS);
1503 }
1504
1505
1506 /*
1507  * Automatically destroy items in this grid.
1508  */
1509 static bool is_opt_confirm_destroy(object_type *o_ptr)
1510 {
1511         if (!destroy_items) return FALSE;
1512
1513         /* Known to be worthless? */
1514         if (leave_worth)
1515                 if (object_value(o_ptr) > 0) return FALSE;
1516
1517         if (leave_equip)
1518                 if (object_is_weapon_armour_ammo(o_ptr)) return FALSE;
1519
1520         if (leave_chest)
1521                 if ((o_ptr->tval == TV_CHEST) && o_ptr->pval) return FALSE;
1522
1523         if (leave_wanted)
1524         {
1525                 if (object_is_shoukinkubi(o_ptr)) return FALSE;
1526         }
1527
1528         if (leave_corpse)
1529                 if (o_ptr->tval == TV_CORPSE) return FALSE;
1530
1531         if (leave_junk)
1532                 if ((o_ptr->tval == TV_SKELETON) || (o_ptr->tval == TV_BOTTLE) || (o_ptr->tval == TV_JUNK) || (o_ptr->tval == TV_STATUE)) return FALSE;
1533
1534         if (leave_special)
1535         {
1536                 if (p_ptr->prace == RACE_DEMON)
1537                 {
1538                         if (o_ptr->tval == TV_CORPSE &&
1539                             o_ptr->sval == SV_CORPSE &&
1540                             my_strchr("pht", r_info[o_ptr->pval].d_char))
1541                                 return FALSE;
1542                 }
1543
1544                 if (p_ptr->pclass == CLASS_ARCHER)
1545                 {
1546                         if (o_ptr->tval == TV_SKELETON ||
1547                             (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_SKELETON))
1548                                 return FALSE;
1549                 }
1550                 else if (p_ptr->pclass == CLASS_NINJA)
1551                 {
1552                         if (o_ptr->tval == TV_LITE &&
1553                             o_ptr->name2 == EGO_LITE_DARKNESS && object_is_known(o_ptr))
1554                                 return FALSE;
1555                 }
1556                 else if (p_ptr->pclass == CLASS_BEASTMASTER ||
1557                          p_ptr->pclass == CLASS_CAVALRY)
1558                 {
1559                         if (o_ptr->tval == TV_WAND &&
1560                             o_ptr->sval == SV_WAND_HEAL_MONSTER && object_is_aware(o_ptr))
1561                                 return FALSE;
1562                 }
1563         }
1564
1565         if (o_ptr->tval == TV_GOLD) return FALSE;
1566
1567         return TRUE;
1568 }
1569
1570
1571 /*
1572  * Automatically destroy an item if it is to be destroyed
1573  *
1574  * When always_pickup is 'yes', we disable auto-destroyer function of
1575  * auto-picker/destroyer, and do only easy-auto-destroyer.
1576  */
1577 static object_type autopick_last_destroyed_object;
1578
1579 static void auto_destroy_item(object_type *o_ptr, int autopick_idx)
1580 {
1581         bool destroy = FALSE;
1582
1583         /* Easy-Auto-Destroyer (3rd priority) */
1584         if (is_opt_confirm_destroy(o_ptr)) destroy = TRUE;
1585
1586         /* Protected by auto-picker (2nd priotity) */
1587         if (autopick_idx >= 0 &&
1588             !(autopick_list[autopick_idx].action & DO_AUTODESTROY))
1589                 destroy = FALSE;
1590
1591         /* Auto-destroyer works only when !always_pickup */
1592         if (!always_pickup)
1593         {
1594                 /* Auto-picker/destroyer (1st priority) */
1595                 if (autopick_idx >= 0 &&
1596                     (autopick_list[autopick_idx].action & DO_AUTODESTROY))
1597                         destroy = TRUE;
1598         }
1599
1600         /* Not to be destroyed */
1601         if (!destroy) return;
1602
1603         /* Now decided to destroy */
1604
1605         disturb(FALSE, FALSE);
1606
1607         /* Artifact? */
1608         if (!can_player_destroy_object(o_ptr))
1609         {
1610                 GAME_TEXT o_name[MAX_NLEN];
1611
1612                 /* Describe the object (with {terrible/special}) */
1613                 object_desc(o_name, o_ptr, 0);
1614
1615                 msg_format(_("%sは破壊不能だ。", "You cannot auto-destroy %s."), o_name);
1616
1617                 return;
1618         }
1619
1620         /* Record name of destroyed item */
1621         (void)COPY(&autopick_last_destroyed_object, o_ptr, object_type);
1622
1623         /* Destroy Later */
1624         o_ptr->marked |= OM_AUTODESTROY;
1625         p_ptr->update |= PU_AUTODESTROY;
1626
1627         return;
1628 }
1629
1630
1631 /*
1632  *  Auto-destroy marked item
1633  */
1634 static void autopick_delayed_alter_aux(INVENTORY_IDX item)
1635 {
1636         object_type *o_ptr;
1637
1638         /* Get the item (in the pack) */
1639         if (item >= 0) o_ptr = &p_ptr->inventory_list[item];
1640
1641         /* Get the item (on the floor) */
1642         else o_ptr = &current_floor_ptr->o_list[0 - item];
1643
1644         if (o_ptr->k_idx && (o_ptr->marked & OM_AUTODESTROY))
1645         {
1646                 GAME_TEXT o_name[MAX_NLEN];
1647
1648                 /* Describe the object (with {terrible/special}) */
1649                 object_desc(o_name, o_ptr, 0);
1650
1651                 /* Eliminate the item (from the pack) */
1652                 if (item >= 0)
1653                 {
1654                         inven_item_increase(item, -(o_ptr->number));
1655                         inven_item_optimize(item);
1656                 }
1657
1658                 /* Eliminate the item (from the floor) */
1659                 else
1660                 {
1661                         delete_object_idx(0 - item);
1662                 }
1663
1664                 msg_format(_("%sを自動破壊します。", "Auto-destroying %s."), o_name);
1665         }
1666 }
1667
1668
1669 /*
1670  *  Auto-destroy marked items in inventry and on floor
1671  */
1672 void autopick_delayed_alter(void)
1673 {
1674         INVENTORY_IDX item;
1675
1676         /* 
1677          * Scan inventry in reverse order to prevent
1678          * skipping after inven_item_optimize()
1679          */
1680         for (item = INVEN_TOTAL - 1; item >= 0 ; item--)
1681                 autopick_delayed_alter_aux(item);
1682
1683         /* Scan the pile of objects */
1684         item = current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].o_idx;
1685         while (item)
1686         {
1687                 OBJECT_IDX next = current_floor_ptr->o_list[item].next_o_idx;
1688                 autopick_delayed_alter_aux(-item);
1689                 item = next;
1690         }
1691 }
1692
1693
1694 /*
1695  * Auto-inscription and/or destroy
1696  *
1697  * Auto-destroyer works only on p_ptr->inventory_list or on floor stack only when
1698  * requested.
1699  */
1700 void autopick_alter_item(INVENTORY_IDX item, bool destroy)
1701 {
1702         object_type *o_ptr;
1703         int idx;
1704
1705         /* Get the item (in the pack) */
1706         if (item >= 0) o_ptr = &p_ptr->inventory_list[item];
1707
1708         /* Get the item (on the floor) */
1709         else o_ptr = &current_floor_ptr->o_list[0 - item];
1710
1711         /* Get the index in the auto-pick/destroy list */
1712         idx = is_autopick(o_ptr);
1713
1714         /* Do auto-inscription */
1715         auto_inscribe_item(o_ptr, idx);
1716
1717         /* Do auto-destroy if needed */
1718         if (destroy && item <= INVEN_PACK)
1719                 auto_destroy_item(o_ptr, idx);
1720 }
1721
1722
1723 /*
1724  * Automatically pickup/destroy items in this grid.
1725  */
1726 void autopick_pickup_items(grid_type *g_ptr)
1727 {
1728         OBJECT_IDX this_o_idx, next_o_idx = 0;
1729         
1730         /* Scan the pile of objects */
1731         for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1732         {
1733                 int idx;
1734                         object_type *o_ptr = &current_floor_ptr->o_list[this_o_idx];
1735                                 next_o_idx = o_ptr->next_o_idx;
1736
1737                 idx = is_autopick(o_ptr);
1738
1739                 /* Item index for floor -1,-2,-3,...  */
1740                 auto_inscribe_item(o_ptr, idx);
1741
1742                 if (idx >= 0 &&
1743                         (autopick_list[idx].action & (DO_AUTOPICK | DO_QUERY_AUTOPICK)))
1744                 {
1745                         disturb(FALSE, FALSE);
1746
1747                         if (!inven_carry_okay(o_ptr))
1748                         {
1749                                 GAME_TEXT o_name[MAX_NLEN];
1750
1751                                 object_desc(o_name, o_ptr, 0);
1752
1753                                 msg_format(_("ザックには%sを入れる隙間がない。", "You have no room for %s."), o_name);
1754                                 /* Hack - remember that the item has given a message here. */
1755                                 o_ptr->marked |= OM_NOMSG;
1756
1757                                 continue;
1758                         }
1759                         else if (autopick_list[idx].action & DO_QUERY_AUTOPICK)
1760                         {
1761                                 char out_val[MAX_NLEN+20];
1762                                 GAME_TEXT o_name[MAX_NLEN];
1763
1764                                 if (o_ptr->marked & OM_NO_QUERY)
1765                                 {
1766                                         /* Already answered as 'No' */
1767                                         continue;
1768                                 }
1769
1770                                 object_desc(o_name, o_ptr, 0);
1771
1772                                 sprintf(out_val, _("%sを拾いますか? ", "Pick up %s? "), o_name);
1773
1774                                 if (!get_check(out_val))
1775                                 {
1776                                         /* Hack - remember that the item has given a message here. */
1777                                         o_ptr->marked |= (OM_NOMSG | OM_NO_QUERY);
1778                                         continue;
1779                                 }
1780
1781                         }
1782                         py_pickup_aux(this_o_idx);
1783                 }
1784                 
1785                 /*
1786                  * Do auto-destroy;
1787                  * When always_pickup is 'yes', we disable
1788                  * auto-destroyer from autopick function, and do only
1789                  * easy-auto-destroyer.
1790                  */
1791                 else
1792                 {
1793                         auto_destroy_item(o_ptr, idx);
1794                 }
1795         } /* for () */
1796 }
1797
1798
1799 static const char autoregister_header[] = "?:$AUTOREGISTER";
1800
1801 /*
1802  *  Clear auto registered lines in the picktype.prf .
1803  */
1804 static bool clear_auto_register(void)
1805 {
1806         char tmp_file[1024];
1807         char pref_file[1024];
1808         char buf[1024];
1809         FILE *pref_fff;
1810         FILE *tmp_fff;
1811         int num = 0;
1812         bool autoregister = FALSE;
1813         bool okay = TRUE;
1814
1815         path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(PT_WITH_PNAME));
1816         pref_fff = my_fopen(pref_file, "r");
1817
1818         if (!pref_fff)
1819         {
1820                 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(PT_DEFAULT));
1821                 pref_fff = my_fopen(pref_file, "r");
1822         }
1823
1824         if (!pref_fff)
1825         {
1826                 /* No file yet */
1827                 return TRUE;
1828         }
1829
1830         /* Open a new (temporary) file */
1831         tmp_fff = my_fopen_temp(tmp_file, sizeof(tmp_file));
1832
1833         if (!tmp_fff)
1834         {
1835                 /* Close the preference file */
1836                 fclose(pref_fff);
1837                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file);
1838                 msg_print(NULL);
1839                 return FALSE;
1840         }
1841
1842         
1843         /* Loop for every line */
1844         while (TRUE)
1845         {
1846                 /* Read a line */
1847                 if (my_fgets(pref_fff, buf, sizeof(buf))) break;
1848
1849                 if (autoregister)
1850                 {
1851                         /* Delete auto-registered line */
1852
1853                         /* Count auto-destroy preference lines */
1854                         if (buf[0] != '#' && buf[0] != '?') num++;
1855                 }
1856
1857                 /* We are looking for auto-registered line */
1858                 else
1859                 {
1860                         if (streq(buf, autoregister_header))
1861                         {
1862                                 /* Delete all further lines */
1863                                 autoregister = TRUE;
1864                         }
1865                         else
1866                         {
1867                                 /* Copy orginally lines */
1868                                 fprintf(tmp_fff, "%s\n", buf);
1869                         }
1870                 }
1871         }
1872
1873         /* Close files */
1874         my_fclose(pref_fff);
1875         my_fclose(tmp_fff);
1876
1877         if (num)
1878         {
1879                 msg_format(_("以前のキャラクター用の自動設定(%d行)が残っています。",
1880                                          "Auto registered lines (%d lines) for previous character are remaining."), num);
1881                 strcpy(buf, _("古い設定行は削除します。よろしいですか?", "These lines will be deleted.  Are you sure? "));
1882
1883                 /* You can cancel it */
1884                 if (!get_check(buf))
1885                 {
1886                         okay = FALSE;
1887                         autoregister = FALSE;
1888
1889                         msg_print(_("エディタのカット&ペースト等を使って必要な行を避難してください。",
1890                                                 "Use cut & paste of auto picker editor (_) to keep old prefs."));
1891                 }
1892         }
1893
1894
1895         /* If there are some changes, overwrite the original file with new one */
1896         if (autoregister)
1897         {
1898                 /* Copy contents of temporary file */
1899
1900                 tmp_fff = my_fopen(tmp_file, "r");
1901                 pref_fff = my_fopen(pref_file, "w");
1902
1903                 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
1904                         fprintf(pref_fff, "%s\n", buf);
1905
1906                 my_fclose(pref_fff);
1907                 my_fclose(tmp_fff);
1908         }
1909
1910         /* Kill the temporary file */
1911         fd_kill(tmp_file);
1912
1913         return okay;
1914 }
1915
1916
1917 /*
1918  *  Automatically register an auto-destroy preference line
1919  */
1920 bool autopick_autoregister(object_type *o_ptr)
1921 {
1922         char buf[1024];
1923         char pref_file[1024];
1924         FILE *pref_fff;
1925         autopick_type an_entry, *entry = &an_entry;
1926
1927         int match_autopick = is_autopick(o_ptr);
1928
1929         /* Already registered */
1930         if (match_autopick != -1)
1931         {
1932                 concptr what;
1933                 byte act = autopick_list[match_autopick].action;
1934
1935                 if (act & DO_AUTOPICK) what = _("自動で拾う", "auto-pickup");
1936                 else if (act & DO_AUTODESTROY) what = _("自動破壊する", "auto-destroy");
1937                 else if (act & DONT_AUTOPICK) what = _("放置する", "leave on floor");
1938                 else /* if (act & DO_QUERY_AUTOPICK) */ what = _("確認して拾う", "query auto-pickup");
1939
1940                 msg_format(_("そのアイテムは既に%sように設定されています。", "The object is already registered to %s."), what);
1941                 return FALSE;
1942         }
1943
1944         /* Known to be an artifact? */
1945         if ((object_is_known(o_ptr) && object_is_artifact(o_ptr)) ||
1946             ((o_ptr->ident & IDENT_SENSE) &&
1947              (o_ptr->feeling == FEEL_TERRIBLE || o_ptr->feeling == FEEL_SPECIAL)))
1948         {
1949                 GAME_TEXT o_name[MAX_NLEN];
1950
1951                 /* Describe the object (with {terrible/special}) */
1952                 object_desc(o_name, o_ptr, 0);
1953
1954                 msg_format(_("%sは破壊不能だ。", "You cannot auto-destroy %s."), o_name);
1955
1956                 return FALSE;
1957         }
1958
1959
1960         if (!p_ptr->autopick_autoregister)
1961         {
1962                 /* Clear old auto registered lines */
1963                 if (!clear_auto_register()) return FALSE;
1964         }
1965
1966         /* Try a filename with player name */
1967         path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(PT_WITH_PNAME));
1968         pref_fff = my_fopen(pref_file, "r");
1969
1970         if (!pref_fff)
1971         {
1972                 /* Use default name */
1973                 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(PT_DEFAULT));
1974                 pref_fff = my_fopen(pref_file, "r");
1975         }
1976
1977         /* Check the header */
1978         while (TRUE)
1979         {
1980                 /* Read a line */
1981                 if (my_fgets(pref_fff, buf, sizeof(buf)))
1982                 {
1983                         /* No header found */
1984                         p_ptr->autopick_autoregister = FALSE;
1985
1986                         break;
1987                 }
1988
1989                 if (streq(buf, autoregister_header))
1990                 {
1991                         /* Found the header */
1992                         p_ptr->autopick_autoregister = TRUE;
1993
1994                         break;
1995                 }
1996         }
1997
1998         /* Close read only FILE* */
1999         fclose(pref_fff);
2000
2001         /* Open for append */
2002         pref_fff = my_fopen(pref_file, "a");
2003
2004         /* Failure */
2005         if (!pref_fff) {
2006                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), pref_file);
2007                 msg_print(NULL);
2008
2009                 /* Failed */
2010                 return FALSE;
2011         }
2012
2013         if (!p_ptr->autopick_autoregister)
2014         {
2015                 /* Add the header */
2016                 fprintf(pref_fff, "%s\n", autoregister_header);
2017
2018                 fprintf(pref_fff, "%s\n", _("# *警告!!* 以降の行は自動登録されたものです。",
2019                                                             "# *Waring!* The lines below will be deleated later."));
2020                 fprintf(pref_fff, "%s\n", _("# 後で自動的に削除されますので、必要な行は上の方へ移動しておいてください。", 
2021                                                             "# Keep it by cut & paste if you need these lines for future characters."));
2022
2023                 /* Now auto register is in-use */
2024                 p_ptr->autopick_autoregister = TRUE;
2025         }
2026
2027         /* Get a preference entry */
2028         autopick_entry_from_object(entry, o_ptr);
2029
2030         /* Set to auto-destroy (with no-display) */
2031         entry->action = DO_AUTODESTROY;
2032
2033         /* Load the new line as preference */
2034         add_autopick_list(entry);
2035
2036         /* Add a line to the file */
2037         /* Don't kill "entry" */
2038         fprintf(pref_fff, "%s\n", autopick_line_from_entry(entry));
2039         fclose(pref_fff);
2040
2041         return TRUE;
2042 }
2043
2044
2045 /********  Auto-picker/destroyer editor  **********/
2046
2047 #define MAX_YANK MAX_LINELEN
2048 #define MAX_LINES 3000
2049
2050 #define MARK_MARK     0x01
2051 #define MARK_BY_SHIFT 0x02
2052
2053 #define LSTAT_BYPASS        0x01
2054 #define LSTAT_EXPRESSION    0x02
2055 #define LSTAT_AUTOREGISTER  0x04
2056
2057 #define QUIT_WITHOUT_SAVE 1
2058 #define QUIT_AND_SAVE     2
2059
2060 /* 
2061  * Struct for yank buffer
2062  */
2063 typedef struct chain_str {
2064         struct chain_str *next;
2065         char s[1];
2066 } chain_str_type;
2067
2068
2069 /*
2070  * Data struct for text editor
2071  */
2072 typedef struct {
2073         int wid, hgt;
2074         int cx, cy;
2075         int upper, left;
2076         int old_wid, old_hgt;
2077         int old_cy;
2078         int old_upper, old_left;
2079         int mx, my;
2080         byte mark;
2081
2082         object_type *search_o_ptr;
2083         concptr search_str;
2084         concptr last_destroyed;
2085
2086         chain_str_type *yank;
2087         bool yank_eol;
2088
2089         concptr *lines_list;
2090         byte states[MAX_LINES];
2091
2092         u16b dirty_flags;
2093         int dirty_line;
2094         int filename_mode;
2095         int old_com_id;
2096
2097         bool changed;
2098 } text_body_type;
2099
2100
2101 /*
2102  * Dirty flag for text editor
2103  */
2104 #define DIRTY_ALL           0x0001
2105 #define DIRTY_MODE          0x0004
2106 #define DIRTY_SCREEN        0x0008
2107 #define DIRTY_NOT_FOUND     0x0010
2108 #define DIRTY_NO_SEARCH     0x0020
2109 #define DIRTY_EXPRESSION    0x0040
2110 #define DIRTY_SKIP_INACTIVE 0x0080
2111 #define DIRTY_INACTIVE      0x0100
2112
2113 /*
2114  * Describe which kind of object is Auto-picked/destroyed
2115  */
2116 static void describe_autopick(char *buff, autopick_type *entry)
2117 {
2118         concptr str = entry->name;
2119         byte act = entry->action;
2120         concptr insc = entry->insc;
2121         int i;
2122
2123         bool top = FALSE;
2124
2125 #ifdef JP
2126         concptr before_str[100], body_str;
2127         int before_n = 0;
2128
2129         body_str = "アイテム";
2130
2131         /*** Collecting items ***/
2132         /*** Which can be absorbed into a slot as a bundle ***/
2133         if (IS_FLG(FLG_COLLECTING))
2134                 before_str[before_n++] = "収集中で既に持っているスロットにまとめられる";
2135         
2136         /*** Unaware items ***/
2137         if (IS_FLG(FLG_UNAWARE))
2138                 before_str[before_n++] = "未鑑定でその効果も判明していない";
2139
2140         /*** Unidentified ***/
2141         if (IS_FLG(FLG_UNIDENTIFIED))
2142                 before_str[before_n++] = "未鑑定の";
2143
2144         /*** Identified ***/
2145         if (IS_FLG(FLG_IDENTIFIED))
2146                 before_str[before_n++] = "鑑定済みの";
2147
2148         /*** *Identified* ***/
2149         if (IS_FLG(FLG_STAR_IDENTIFIED))
2150                 before_str[before_n++] = "完全に鑑定済みの";
2151
2152         /*** Dice boosted (weapon of slaying) ***/
2153         if (IS_FLG(FLG_BOOSTED))
2154         {
2155                 before_str[before_n++] = "ダメージダイスが通常より大きい";
2156                 body_str = "武器";
2157         }
2158
2159         /*** Weapons whose dd*ds is more than nn ***/
2160         if (IS_FLG(FLG_MORE_DICE))
2161         {
2162                 static char more_than_desc_str[] = "___";
2163                 before_str[before_n++] = "ダメージダイスの最大値が";
2164                 body_str = "武器";
2165                         
2166                 sprintf(more_than_desc_str,"%d", entry->dice);
2167                 before_str[before_n++] = more_than_desc_str;
2168                 before_str[before_n++] = "以上の";
2169         }
2170
2171         /*** Items whose magical bonus is more than nn ***/
2172         if (IS_FLG(FLG_MORE_BONUS))
2173         {
2174                 static char more_bonus_desc_str[] = "___";
2175                 before_str[before_n++] = "修正値が(+";
2176                         
2177                 sprintf(more_bonus_desc_str,"%d", entry->bonus);
2178                 before_str[before_n++] = more_bonus_desc_str;
2179                 before_str[before_n++] = ")以上の";
2180         }
2181
2182         /*** Worthless items ***/
2183         if (IS_FLG(FLG_WORTHLESS))
2184                 before_str[before_n++] = "店で無価値と判定される";
2185
2186         /*** Artifact ***/
2187         if (IS_FLG(FLG_ARTIFACT))
2188         {
2189                 before_str[before_n++] = "アーティファクトの";
2190                 body_str = "装備";
2191         }
2192
2193         /*** Ego ***/
2194         if (IS_FLG(FLG_EGO))
2195         {
2196                 before_str[before_n++] = "エゴアイテムの";
2197                 body_str = "装備";
2198         }
2199
2200         /*** Good ***/
2201         if (IS_FLG(FLG_GOOD))
2202         {
2203                 before_str[before_n++] = "上質の";
2204                 body_str = "装備";
2205         }
2206
2207         /*** Nameless ***/
2208         if (IS_FLG(FLG_NAMELESS))
2209         {
2210                 before_str[before_n++] = "エゴでもアーティファクトでもない";
2211                 body_str = "装備";
2212         }
2213
2214         /*** Average ***/
2215         if (IS_FLG(FLG_AVERAGE))
2216         {
2217                 before_str[before_n++] = "並の";
2218                 body_str = "装備";
2219         }
2220
2221         /*** Rare equipments ***/
2222         if (IS_FLG(FLG_RARE))
2223         {
2224                 before_str[before_n++] = "ドラゴン装備やカオス・ブレード等を含む珍しい";
2225                 body_str = "装備";
2226         }
2227
2228         /*** Common equipments ***/
2229         if (IS_FLG(FLG_COMMON))
2230         {
2231                 before_str[before_n++] = "ありふれた(ドラゴン装備やカオス・ブレード等の珍しい物ではない)";
2232                 body_str = "装備";
2233         }
2234
2235         /*** Wanted monster's corpse/skeletons ***/
2236         if (IS_FLG(FLG_WANTED))
2237         {
2238                 before_str[before_n++] = "ハンター事務所で賞金首とされている";
2239                 body_str = "死体や骨";
2240         }
2241
2242         /*** Human corpse/skeletons (for Daemon magic) ***/
2243         if (IS_FLG(FLG_HUMAN))
2244         {
2245                 before_str[before_n++] = "悪魔魔法で使うための人間やヒューマノイドの";
2246                 body_str = "死体や骨";
2247         }
2248
2249         /*** Unique monster's corpse/skeletons/statues ***/
2250         if (IS_FLG(FLG_UNIQUE))
2251         {
2252                 before_str[before_n++] = "ユニークモンスターの";
2253                 body_str = "死体や骨";
2254         }
2255
2256         /*** Unreadable spellbooks ***/
2257         if (IS_FLG(FLG_UNREADABLE))
2258         {
2259                 before_str[before_n++] = "あなたが読めない領域の";
2260                 body_str = "魔法書";
2261         }
2262
2263         /*** First realm spellbooks ***/
2264         if (IS_FLG(FLG_REALM1))
2265         {
2266                 before_str[before_n++] = "第一領域の";
2267                 body_str = "魔法書";
2268         }
2269
2270         /*** Second realm spellbooks ***/
2271         if (IS_FLG(FLG_REALM2))
2272         {
2273                 before_str[before_n++] = "第二領域の";
2274                 body_str = "魔法書";
2275         }
2276
2277         /*** First rank spellbooks ***/
2278         if (IS_FLG(FLG_FIRST))
2279         {
2280                 before_str[before_n++] = "全4冊の内の1冊目の";
2281                 body_str = "魔法書";
2282         }
2283
2284         /*** Second rank spellbooks ***/
2285         if (IS_FLG(FLG_SECOND))
2286         {
2287                 before_str[before_n++] = "全4冊の内の2冊目の";
2288                 body_str = "魔法書";
2289         }
2290
2291         /*** Third rank spellbooks ***/
2292         if (IS_FLG(FLG_THIRD))
2293         {
2294                 before_str[before_n++] = "全4冊の内の3冊目の";
2295                 body_str = "魔法書";
2296         }
2297
2298         /*** Fourth rank spellbooks ***/
2299         if (IS_FLG(FLG_FOURTH))
2300         {
2301                 before_str[before_n++] = "全4冊の内の4冊目の";
2302                 body_str = "魔法書";
2303         }
2304
2305         /*** Items ***/
2306         if (IS_FLG(FLG_ITEMS))
2307                 ; /* Nothing to do */
2308         else if (IS_FLG(FLG_WEAPONS))
2309                 body_str = "武器";
2310         else if (IS_FLG(FLG_FAVORITE_WEAPONS))
2311                 body_str = "得意武器";
2312         else if (IS_FLG(FLG_ARMORS))
2313                 body_str = "防具";
2314         else if (IS_FLG(FLG_MISSILES))
2315                 body_str = "弾や矢やクロスボウの矢";
2316         else if (IS_FLG(FLG_DEVICES))
2317                 body_str = "巻物や魔法棒や杖やロッド";
2318         else if (IS_FLG(FLG_LIGHTS))
2319                 body_str = "光源用のアイテム";
2320         else if (IS_FLG(FLG_JUNKS))
2321                 body_str = "折れた棒等のガラクタ";
2322         else if (IS_FLG(FLG_CORPSES))
2323                 body_str = "死体や骨";
2324         else if (IS_FLG(FLG_SPELLBOOKS))
2325                 body_str = "魔法書";
2326         else if (IS_FLG(FLG_HAFTED))
2327                 body_str = "鈍器";
2328         else if (IS_FLG(FLG_SHIELDS))
2329                 body_str = "盾";
2330         else if (IS_FLG(FLG_BOWS))
2331                 body_str = "スリングや弓やクロスボウ";
2332         else if (IS_FLG(FLG_RINGS))
2333                 body_str = "指輪";
2334         else if (IS_FLG(FLG_AMULETS))
2335                 body_str = "アミュレット";
2336         else if (IS_FLG(FLG_SUITS))
2337                 body_str = "鎧";
2338         else if (IS_FLG(FLG_CLOAKS))
2339                 body_str = "クローク";
2340         else if (IS_FLG(FLG_HELMS))
2341                 body_str = "ヘルメットや冠";
2342         else if (IS_FLG(FLG_GLOVES))
2343                 body_str = "籠手";
2344         else if (IS_FLG(FLG_BOOTS))
2345                 body_str = "ブーツ";
2346
2347         *buff = '\0';
2348         if (!before_n) 
2349                 strcat(buff, "全ての");
2350         else for (i = 0; i < before_n && before_str[i]; i++)
2351                 strcat(buff, before_str[i]);
2352
2353         strcat(buff, body_str);
2354
2355         if (*str)
2356         {
2357                 if (*str == '^')
2358                 {
2359                         str++;
2360                         top = TRUE;
2361                 }
2362
2363                 strcat(buff, "で、名前が「");
2364                 strncat(buff, str, 80);
2365                 if (top)
2366                         strcat(buff, "」で始まるもの");
2367                 else
2368                         strcat(buff, "」を含むもの");
2369         }
2370
2371         if (insc)
2372         {
2373                 strncat(buff, format("に「%s」", insc), 80);
2374
2375                 if (my_strstr(insc, "%%all"))
2376                         strcat(buff, "(%%allは全能力を表す英字の記号で置換)");
2377                 else if (my_strstr(insc, "%all"))
2378                         strcat(buff, "(%allは全能力を表す記号で置換)");
2379                 else if (my_strstr(insc, "%%"))
2380                         strcat(buff, "(%%は追加能力を表す英字の記号で置換)");
2381                 else if (my_strstr(insc, "%"))
2382                         strcat(buff, "(%は追加能力を表す記号で置換)");
2383
2384                 strcat(buff, "と刻んで");
2385         }
2386         else
2387                 strcat(buff, "を");
2388
2389         if (act & DONT_AUTOPICK)
2390                 strcat(buff, "放置する。");
2391         else if (act & DO_AUTODESTROY)
2392                 strcat(buff, "破壊する。");
2393         else if (act & DO_QUERY_AUTOPICK)
2394                 strcat(buff, "確認の後に拾う。");
2395         else
2396                 strcat(buff, "拾う。");
2397
2398         if (act & DO_DISPLAY)
2399         {
2400                 if (act & DONT_AUTOPICK)
2401                         strcat(buff, "全体マップ('M')で'N'を押したときに表示する。");
2402                 else if (act & DO_AUTODESTROY)
2403                         strcat(buff, "全体マップ('M')で'K'を押したときに表示する。");
2404                 else
2405                         strcat(buff, "全体マップ('M')で'M'を押したときに表示する。");
2406         }
2407         else
2408                 strcat(buff, "全体マップには表示しない。");
2409
2410 #else /* JP */
2411
2412         concptr before_str[20], after_str[20], which_str[20], whose_str[20], body_str;
2413         int before_n = 0, after_n = 0, which_n = 0, whose_n = 0;
2414
2415         body_str = "items";
2416
2417         /*** Collecting items ***/
2418         /*** Which can be absorbed into a slot as a bundle ***/
2419         if (IS_FLG(FLG_COLLECTING))
2420                 which_str[which_n++] = "can be absorbed into an existing p_ptr->inventory_list slot";
2421         
2422         /*** Unaware items ***/
2423         if (IS_FLG(FLG_UNAWARE))
2424         {
2425                 before_str[before_n++] = "unidentified";
2426                 whose_str[whose_n++] = "basic abilities are not known";
2427         }
2428
2429         /*** Unidentified ***/
2430         if (IS_FLG(FLG_UNIDENTIFIED))
2431                 before_str[before_n++] = "unidentified";
2432
2433         /*** Identified ***/
2434         if (IS_FLG(FLG_IDENTIFIED))
2435                 before_str[before_n++] = "identified";
2436
2437         /*** *Identified* ***/
2438         if (IS_FLG(FLG_STAR_IDENTIFIED))
2439                 before_str[before_n++] = "fully identified";
2440
2441         /*** Rare equipments ***/
2442         if (IS_FLG(FLG_RARE))
2443         {
2444                 before_str[before_n++] = "very rare";
2445                 body_str = "equipments";
2446                 after_str[after_n++] = "such like Dragon armors, Blades of Chaos, etc.";
2447         }
2448
2449         /*** Common equipments ***/
2450         if (IS_FLG(FLG_COMMON))
2451         {
2452                 before_str[before_n++] = "relatively common";
2453                 body_str = "equipments";
2454                 after_str[after_n++] = "compared to very rare Dragon armors, Blades of Chaos, etc.";
2455         }
2456
2457         /*** Worthless items ***/
2458         if (IS_FLG(FLG_WORTHLESS))
2459         {
2460                 before_str[before_n++] = "worthless";
2461                 which_str[which_n++] = "can not be sold at stores";
2462         }
2463
2464         /*** Artifacto ***/
2465         if (IS_FLG(FLG_ARTIFACT))
2466         {
2467                 before_str[before_n++] = "artifact";
2468         }
2469
2470         /*** Ego ***/
2471         if (IS_FLG(FLG_EGO))
2472         {
2473                 before_str[before_n++] = "ego";
2474         }
2475
2476         /*** Good ***/
2477         if (IS_FLG(FLG_GOOD))
2478         {
2479                 body_str = "equipment";
2480                 which_str[which_n++] = "have good quality";
2481         }
2482
2483         /*** Nameless ***/
2484         if (IS_FLG(FLG_NAMELESS))
2485         {
2486                 body_str = "equipment";
2487                 which_str[which_n++] = "is neither ego-item nor artifact";
2488         }
2489
2490         /*** Average ***/
2491         if (IS_FLG(FLG_AVERAGE))
2492         {
2493                 body_str = "equipment";
2494                 which_str[which_n++] = "have average quality";
2495         }
2496
2497         /*** Dice boosted (weapon of slaying) ***/
2498         if (IS_FLG(FLG_BOOSTED))
2499         {
2500                 body_str = "weapons";
2501                 whose_str[whose_n++] = "damage dice is bigger than normal";
2502         }
2503
2504         /*** Weapons whose dd*ds is more than nn ***/
2505         if (IS_FLG(FLG_MORE_DICE))
2506         {
2507                 static char more_than_desc_str[] =
2508                         "maximum damage from dice is bigger than __";
2509                 body_str = "weapons";
2510                         
2511                 sprintf(more_than_desc_str + sizeof(more_than_desc_str) - 3,
2512                         "%d", entry->dice);
2513                 whose_str[whose_n++] = more_than_desc_str;
2514         }
2515
2516         /*** Items whose magical bonus is more than nn ***/
2517         if (IS_FLG(FLG_MORE_BONUS))
2518         {
2519                 static char more_bonus_desc_str[] =
2520                         "magical bonus is bigger than (+__)";
2521                         
2522                 sprintf(more_bonus_desc_str + sizeof(more_bonus_desc_str) - 4,
2523                         "%d)", entry->bonus);
2524                 whose_str[whose_n++] = more_bonus_desc_str;
2525         }
2526
2527         /*** Wanted monster's corpse/skeletons ***/
2528         if (IS_FLG(FLG_WANTED))
2529         {
2530                 body_str = "corpse or skeletons";
2531                 which_str[which_n++] = "is wanted at the Hunter's Office";
2532         }
2533
2534         /*** Human corpse/skeletons (for Daemon magic) ***/
2535         if (IS_FLG(FLG_HUMAN))
2536         {
2537                 before_str[before_n++] = "humanoid";
2538                 body_str = "corpse or skeletons";
2539                 which_str[which_n++] = "can be used for Daemon magic";
2540         }
2541
2542         /*** Unique monster's corpse/skeletons/statues ***/
2543         if (IS_FLG(FLG_UNIQUE))
2544         {
2545                 before_str[before_n++] = "unique monster's";
2546                 body_str = "corpse or skeletons";
2547         }
2548
2549         /*** Unreadable spellbooks ***/
2550         if (IS_FLG(FLG_UNREADABLE))
2551         {
2552                 body_str = "spellbooks";
2553                 after_str[after_n++] = "of different realms from yours";
2554         }
2555
2556         /*** First realm spellbooks ***/
2557         if (IS_FLG(FLG_REALM1))
2558         {
2559                 body_str = "spellbooks";
2560                 after_str[after_n++] = "of your first realm";
2561         }
2562
2563         /*** Second realm spellbooks ***/
2564         if (IS_FLG(FLG_REALM2))
2565         {
2566                 body_str = "spellbooks";
2567                 after_str[after_n++] = "of your second realm";
2568         }
2569
2570         /*** First rank spellbooks ***/
2571         if (IS_FLG(FLG_FIRST))
2572         {
2573                 before_str[before_n++] = "first one of four";
2574                 body_str = "spellbooks";
2575         }
2576
2577         /*** Second rank spellbooks ***/
2578         if (IS_FLG(FLG_SECOND))
2579         {
2580                 before_str[before_n++] = "second one of four";
2581                 body_str = "spellbooks";
2582         }
2583
2584         /*** Third rank spellbooks ***/
2585         if (IS_FLG(FLG_THIRD))
2586         {
2587                 before_str[before_n++] = "third one of four";
2588                 body_str = "spellbooks";
2589         }
2590
2591         /*** Fourth rank spellbooks ***/
2592         if (IS_FLG(FLG_FOURTH))
2593         {
2594                 before_str[before_n++] = "fourth one of four";
2595                 body_str = "spellbooks";
2596         }
2597
2598         /*** Items ***/
2599         if (IS_FLG(FLG_ITEMS))
2600                 ; /* Nothing to do */
2601         else if (IS_FLG(FLG_WEAPONS))
2602                 body_str = "weapons";
2603         else if (IS_FLG(FLG_FAVORITE_WEAPONS))
2604                 body_str = "favorite weapons";
2605         else if (IS_FLG(FLG_ARMORS))
2606                 body_str = "armors";
2607         else if (IS_FLG(FLG_MISSILES))
2608                 body_str = "shots, arrows or crossbow bolts";
2609         else if (IS_FLG(FLG_DEVICES))
2610                 body_str = "scrolls, wands, staves or rods";
2611         else if (IS_FLG(FLG_LIGHTS))
2612                 body_str = "light sources";
2613         else if (IS_FLG(FLG_JUNKS))
2614                 body_str = "junk such as broken sticks";
2615         else if (IS_FLG(FLG_CORPSES))
2616                 body_str = "corpses or skeletons";
2617         else if (IS_FLG(FLG_SPELLBOOKS))
2618                 body_str = "spellbooks";
2619         else if (IS_FLG(FLG_HAFTED))
2620                 body_str = "hafted weapons";
2621         else if (IS_FLG(FLG_SHIELDS))
2622                 body_str = "shields";
2623         else if (IS_FLG(FLG_BOWS))
2624                 body_str = "slings, bows or crossbows";
2625         else if (IS_FLG(FLG_RINGS))
2626                 body_str = "rings";
2627         else if (IS_FLG(FLG_AMULETS))
2628                 body_str = "amulets";
2629         else if (IS_FLG(FLG_SUITS))
2630                 body_str = "body armors";
2631         else if (IS_FLG(FLG_CLOAKS))
2632                 body_str = "cloaks";
2633         else if (IS_FLG(FLG_HELMS))
2634                 body_str = "helms or crowns";
2635         else if (IS_FLG(FLG_GLOVES))
2636                 body_str = "gloves";
2637         else if (IS_FLG(FLG_BOOTS))
2638                 body_str = "boots";
2639
2640         /* Prepare a string for item name */
2641         if (*str)
2642         {
2643                 if (*str == '^')
2644                 {
2645                         str++;
2646                         top = TRUE;
2647                         whose_str[whose_n++] = "name is beginning with \"";
2648                 }
2649                 else
2650                         which_str[which_n++] = "have \"";
2651         }
2652
2653
2654         /* Describe action flag */
2655         if (act & DONT_AUTOPICK)
2656                 strcpy(buff, "Leave on floor ");
2657         else if (act & DO_AUTODESTROY)
2658                 strcpy(buff, "Destroy ");
2659         else if (act & DO_QUERY_AUTOPICK)
2660                 strcpy(buff, "Ask to pick up ");
2661         else
2662                 strcpy(buff, "Pickup ");
2663
2664         /* Auto-insctiption */
2665         if (insc)
2666         {
2667                 strncat(buff, format("and inscribe \"%s\"", insc), 80);
2668
2669                 if (my_strstr(insc, "%all"))
2670                         strcat(buff, ", replacing %all with code string representing all abilities,");
2671                 else if (my_strstr(insc, "%"))
2672                         strcat(buff, ", replacing % with code string representing extra random abilities,");
2673
2674                 strcat(buff, " on ");
2675         }
2676
2677         /* Adjective */
2678         if (!before_n) 
2679                 strcat(buff, "all ");
2680         else for (i = 0; i < before_n && before_str[i]; i++)
2681         {
2682                 strcat(buff, before_str[i]);
2683                 strcat(buff, " ");
2684         }
2685
2686         /* Item class */
2687         strcat(buff, body_str);
2688
2689         /* of ... */
2690         for (i = 0; i < after_n && after_str[i]; i++)
2691         {
2692                 strcat(buff, " ");
2693                 strcat(buff, after_str[i]);
2694         }
2695
2696         /* which ... */
2697         for (i = 0; i < whose_n && whose_str[i]; i++)
2698         {
2699                 if (i == 0)
2700                         strcat(buff, " whose ");
2701                 else
2702                         strcat(buff, ", and ");
2703
2704                 strcat(buff, whose_str[i]);
2705         }
2706
2707         /* Item name ; whose name is beginning with "str" */
2708         if (*str && top)
2709         {
2710                 strcat(buff, str);
2711                 strcat(buff, "\"");
2712         }
2713
2714         /* whose ..., and which .... */
2715         if (whose_n && which_n)
2716                 strcat(buff, ", and ");
2717
2718         /* which ... */
2719         for (i = 0; i < which_n && which_str[i]; i++)
2720         {
2721                 if (i == 0)
2722                         strcat(buff, " which ");
2723                 else
2724                         strcat(buff, ", and ");
2725
2726                 strcat(buff, which_str[i]);
2727         }
2728
2729         /* Item name ; which have "str" as part of its name */
2730         if (*str && !top)
2731         {
2732                 strncat(buff, str, 80);
2733                 strcat(buff, "\" as part of its name");
2734         }
2735         strcat(buff, ".");
2736
2737         /* Describe whether it will be displayed on the full map or not */
2738         if (act & DO_DISPLAY)
2739         {
2740                 if (act & DONT_AUTOPICK)
2741                         strcat(buff, "  Display these items when you press the N key in the full 'M'ap.");
2742                 else if (act & DO_AUTODESTROY)
2743                         strcat(buff, "  Display these items when you press the K key in the full 'M'ap.");
2744                 else
2745                         strcat(buff, "  Display these items when you press the M key in the full 'M'ap.");
2746         }
2747         else
2748                 strcat(buff, " Not displayed in the full map.");
2749 #endif /* JP */
2750
2751 }
2752
2753
2754 /*
2755  * Read whole lines of a file to memory
2756  */
2757 static concptr *read_text_lines(concptr filename)
2758 {
2759         concptr *lines_list = NULL;
2760         FILE *fff;
2761
2762         int lines = 0;
2763         char buf[1024];
2764
2765         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2766         
2767         /* Open the file */
2768         fff = my_fopen(buf, "r");
2769
2770         if (fff)
2771         {
2772                 /* Allocate list of pointers */
2773                 C_MAKE(lines_list, MAX_LINES, concptr);
2774
2775                 /* Parse it */
2776                 while (0 == my_fgets(fff, buf, sizeof(buf)))
2777                 {
2778                         lines_list[lines++] = string_make(buf);
2779                         if (lines >= MAX_LINES - 1) break;
2780                 }
2781                 if (lines == 0)
2782                         lines_list[0] = string_make("");
2783
2784                 my_fclose(fff);
2785         }
2786
2787         if (!fff) return NULL;
2788         return lines_list;
2789 }
2790
2791
2792 /*
2793  * Copy the default autopick file to the user directory
2794  */
2795 static void prepare_default_pickpref(void)
2796 {
2797         const concptr messages[] = {
2798                 _("あなたは「自動拾いエディタ」を初めて起動しました。", "You have activated the Auto-Picker Editor for the first time."),
2799                 _("自動拾いのユーザー設定ファイルがまだ書かれていないので、", "Since user pref file for autopick is not yet created,"),
2800                 _("基本的な自動拾い設定ファイルをlib/pref/picktype.prfからコピーします。", "the default setting is loaded from lib/pref/pickpref.prf ."),
2801                 NULL
2802         };
2803
2804         char buf[1024];
2805         FILE *pref_fp;
2806         FILE *user_fp;
2807         int i;
2808         concptr filename = pickpref_filename(PT_DEFAULT);
2809
2810         /* Display messages */
2811         for (i = 0; messages[i]; i++) msg_print(messages[i]);
2812         msg_print(NULL);
2813
2814
2815         /* Open new file */
2816         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2817         user_fp = my_fopen(buf, "w");
2818
2819         /* Failed */
2820         if (!user_fp) return;
2821
2822         /* Write header messages for a notification */
2823         fprintf(user_fp, "#***\n");
2824         for (i = 0; messages[i]; i++)
2825         {
2826                 fprintf(user_fp, "#***  %s\n", messages[i]);
2827         }
2828         fprintf(user_fp, "#***\n\n\n");
2829
2830
2831         /* Open the default file */
2832         path_build(buf, sizeof(buf), ANGBAND_DIR_PREF, filename);
2833         pref_fp = my_fopen(buf, "r");
2834
2835         /* Failed */
2836         if (!pref_fp)
2837         {
2838                 my_fclose(user_fp);
2839                 return;
2840         }
2841
2842         /* Copy the contents of default file */
2843         while (!my_fgets(pref_fp, buf, sizeof(buf)))
2844                 fprintf(user_fp, "%s\n", buf);
2845
2846         my_fclose(user_fp);
2847         my_fclose(pref_fp);
2848 }
2849
2850 /*
2851  * Read an autopick prefence file to memory
2852  * Prepare default if no user file is found
2853  */
2854 static concptr *read_pickpref_text_lines(int *filename_mode_p)
2855 {
2856         char buf[1024];
2857         concptr *lines_list;
2858
2859         /* Try a filename with player name */
2860         *filename_mode_p = PT_WITH_PNAME;
2861         strcpy(buf, pickpref_filename(*filename_mode_p));
2862         lines_list = read_text_lines(buf);
2863
2864         if (!lines_list)
2865         {
2866                 /* Use default name */
2867                 *filename_mode_p = PT_DEFAULT;
2868                 strcpy(buf, pickpref_filename(*filename_mode_p));
2869                 lines_list = read_text_lines(buf);
2870         }
2871
2872         if (!lines_list)
2873         {
2874                 /* There is no preference file in the user directory */
2875
2876                 /* Copy the default autopick file to the user directory */
2877                 prepare_default_pickpref();
2878
2879                 /* Use default name again */
2880                 lines_list = read_text_lines(buf);
2881         }
2882
2883         if (!lines_list)
2884         {
2885                 /* Allocate list of pointers */
2886                 C_MAKE(lines_list, MAX_LINES, concptr);
2887                 lines_list[0] = string_make("");
2888         }
2889         return lines_list;
2890 }
2891
2892
2893 /*
2894  * Write whole lines of memory to a file.
2895  */
2896 static bool write_text_lines(concptr filename, concptr *lines_list)
2897 {
2898         FILE *fff;
2899
2900         int lines = 0;
2901         char buf[1024];
2902
2903         /* Build the filename */
2904         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2905         
2906         /* Open the file */
2907         fff = my_fopen(buf, "w");
2908         if (fff)
2909         {
2910                 for (lines = 0; lines_list[lines]; lines++)
2911                         my_fputs(fff, lines_list[lines], 1024);
2912
2913                 my_fclose(fff);
2914         }
2915
2916         if (!fff) return FALSE;
2917         return TRUE;
2918 }
2919
2920
2921 /*
2922  * Free memory of lines_list.
2923  */
2924 static void free_text_lines(concptr *lines_list)
2925 {
2926         int lines;
2927
2928         for (lines = 0; lines_list[lines]; lines++)
2929                 string_free(lines_list[lines]);
2930
2931         /* free list of pointers */
2932         C_KILL(lines_list, MAX_LINES, concptr);
2933 }
2934
2935
2936 /*
2937  * Delete or insert string
2938  */
2939 static void toggle_keyword(text_body_type *tb, BIT_FLAGS flg)
2940 {
2941         int by1, by2, y;
2942         bool add = TRUE;
2943         bool fixed = FALSE;
2944
2945         /* Some lines are selected */
2946         if (tb->mark)
2947         {
2948                 by1 = MIN(tb->my, tb->cy);
2949                 by2 = MAX(tb->my, tb->cy);
2950         }
2951
2952         /* No mark -- Select current line */
2953         else /* if (!tb->mark) */
2954         {
2955                 by1 = by2 = tb->cy;
2956         }
2957
2958
2959         /* Set/Reset flag of each line */
2960         for (y = by1; y <= by2; y++)
2961         {
2962                 autopick_type an_entry, *entry = &an_entry;
2963
2964                 if (!autopick_new_entry(entry, tb->lines_list[y], !fixed)) continue;
2965
2966                 string_free(tb->lines_list[y]);
2967
2968                 if (!fixed)
2969                 {
2970                         /* Add? or Remove? */
2971                         if (!IS_FLG(flg)) add = TRUE;
2972                         else add = FALSE;
2973
2974                         /* No more change */
2975                         fixed = TRUE;
2976                 }
2977
2978                 /* You can use only one noun flag */
2979                 if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
2980                 {
2981                         int i;
2982                         for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
2983                                 REM_FLG(i);
2984                 }
2985                 
2986                 /* You can use only one identify state flag */
2987                 else if (FLG_UNAWARE <= flg && flg <= FLG_STAR_IDENTIFIED)
2988                 {
2989                         int i;
2990                         for (i = FLG_UNAWARE; i <= FLG_STAR_IDENTIFIED; i++)
2991                                 REM_FLG(i);
2992                 }
2993                 
2994                 /* You can use only one flag in artifact/ego/nameless */
2995                 else if (FLG_ARTIFACT <= flg && flg <= FLG_AVERAGE)
2996                 {
2997                         int i;
2998                         for (i = FLG_ARTIFACT; i <= FLG_AVERAGE; i++)
2999                                 REM_FLG(i);
3000                 }
3001                 
3002                 /* You can use only one flag in rare/common */
3003                 else if (FLG_RARE <= flg && flg <= FLG_COMMON)
3004                 {
3005                         int i;
3006                         for (i = FLG_RARE; i <= FLG_COMMON; i++)
3007                                 REM_FLG(i);
3008                 }
3009                 
3010                 if (add) ADD_FLG(flg);
3011                 else REM_FLG(flg);
3012                 
3013                 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
3014                 
3015                 /* Now dirty */
3016                 tb->dirty_flags |= DIRTY_ALL;
3017
3018                 /* Text is changed */
3019                 tb->changed = TRUE;
3020         }
3021 }
3022
3023
3024 /*
3025  * Change command letter
3026  */
3027 static void toggle_command_letter(text_body_type *tb, byte flg)
3028 {
3029         autopick_type an_entry, *entry = &an_entry;
3030         int by1, by2, y;
3031         bool add = TRUE;
3032         bool fixed = FALSE;
3033
3034         /* Some lines are selected */
3035         if (tb->mark)
3036         {
3037                 by1 = MIN(tb->my, tb->cy);
3038                 by2 = MAX(tb->my, tb->cy);
3039         }
3040
3041         /* No mark -- Select current line */
3042         else /* if (!tb->mark) */
3043         {
3044                 by1 = by2 = tb->cy;
3045         }
3046
3047
3048         /* Set/Reset flag of each line */
3049         for (y = by1; y <= by2; y++)
3050         {
3051                 int wid = 0;
3052
3053                 if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue;
3054
3055                 string_free(tb->lines_list[y]);
3056
3057                 if (!fixed)
3058                 {
3059                         /* Add? or Remove? */
3060                         if (!(entry->action & flg)) add = TRUE;
3061                         else add = FALSE;
3062
3063                         /* No more change */
3064                         fixed = TRUE;
3065                 }
3066
3067                 /* Count number of letter (by negative number) */
3068                 if (entry->action & DONT_AUTOPICK) wid--;
3069                 else if (entry->action & DO_AUTODESTROY) wid--;
3070                 else if (entry->action & DO_QUERY_AUTOPICK) wid--;
3071                 if (!(entry->action & DO_DISPLAY)) wid--;
3072
3073                 /* Set/Reset the flag */
3074                 if (flg != DO_DISPLAY)
3075                 {
3076                         entry->action &= ~(DO_AUTOPICK | DONT_AUTOPICK | DO_AUTODESTROY | DO_QUERY_AUTOPICK);
3077                         if (add) entry->action |= flg;
3078                         else entry->action |= DO_AUTOPICK;
3079                 }
3080                 else
3081                 {
3082                         entry->action &= ~(DO_DISPLAY);
3083                         if (add) entry->action |= flg;
3084                 }
3085
3086                 /* Correct cursor location */
3087                 if (tb->cy == y)
3088                 {
3089                         if (entry->action & DONT_AUTOPICK) wid++;
3090                         else if (entry->action & DO_AUTODESTROY) wid++;
3091                         else if (entry->action & DO_QUERY_AUTOPICK) wid++;
3092                         if (!(entry->action & DO_DISPLAY)) wid++;
3093
3094                         if (wid > 0) tb->cx++;
3095                         if (wid < 0 && tb->cx > 0) tb->cx--;
3096                 }
3097                         
3098                 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
3099                         
3100                 /* Now dirty */
3101                 tb->dirty_flags |= DIRTY_ALL;
3102
3103                 /* Text is changed */
3104                 tb->changed = TRUE;
3105         }
3106 }
3107
3108 /*
3109  * Delete or insert string
3110  */
3111 static void add_keyword(text_body_type *tb, BIT_FLAGS flg)
3112 {
3113         int by1, by2, y;
3114
3115         /* Some lines are selected */
3116         if (tb->mark)
3117         {
3118                 by1 = MIN(tb->my, tb->cy);
3119                 by2 = MAX(tb->my, tb->cy);
3120         }
3121
3122         /* No mark -- Select current line */
3123         else /* if (!tb->mark) */
3124         {
3125                 by1 = by2 = tb->cy;
3126         }
3127
3128
3129         /* Set/Reset flag of each line */
3130         for (y = by1; y <= by2; y++)
3131         {
3132                 autopick_type an_entry, *entry = &an_entry;
3133
3134                 if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue;
3135
3136                 /* There is the flag already */
3137                 if (IS_FLG(flg))
3138                 {
3139                         /* Free memory for the entry */
3140                         autopick_free_entry(entry);
3141                         
3142                         continue;
3143                 }
3144                 
3145                 string_free(tb->lines_list[y]);
3146                 
3147                 /* Remove all noun flag */
3148                 if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
3149                 {
3150                         int i;
3151                         for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
3152                                 REM_FLG(i);
3153                 }
3154                 
3155                 ADD_FLG(flg);
3156                 
3157                 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
3158
3159                 /* Now dirty */
3160                 tb->dirty_flags |= DIRTY_ALL;
3161
3162                 /* Text is changed */
3163                 tb->changed = TRUE;
3164         }
3165 }
3166
3167
3168 /*
3169  * Check if this line is expression or not.
3170  * And update it if it is.
3171  */
3172 static void check_expression_line(text_body_type *tb, int y)
3173 {
3174         concptr s = tb->lines_list[y];
3175
3176         if ((s[0] == '?' && s[1] == ':') ||
3177             (tb->states[y] & LSTAT_BYPASS))
3178         {
3179                 /* Expressions need re-evaluation */
3180                 tb->dirty_flags |= DIRTY_EXPRESSION;
3181         }
3182 }
3183
3184
3185 /*
3186  * Add an empty line at the last of the file
3187  */
3188 static bool add_empty_line(text_body_type *tb)
3189 {
3190         int k;
3191
3192         for (k = 0; tb->lines_list[k]; k++)
3193                 /* count number of lines */ ;
3194
3195         /* Too many lines! */
3196         if (k >= MAX_LINES - 2) return FALSE;
3197
3198         /* The last line is already empty */
3199         if (!tb->lines_list[k-1][0]) return FALSE;
3200
3201         /* Create new empty line */
3202         tb->lines_list[k] = string_make("");
3203
3204         /* Expressions need re-evaluation */
3205         tb->dirty_flags |= DIRTY_EXPRESSION;
3206
3207         /* Text is changed */
3208         tb->changed = TRUE;
3209
3210         /* A line is added */
3211         return TRUE;
3212 }
3213
3214
3215 /*
3216  * Insert return code and split the line
3217  */
3218 static bool insert_return_code(text_body_type *tb)
3219 {
3220         char buf[MAX_LINELEN];
3221         int i, j, k;
3222
3223         for (k = 0; tb->lines_list[k]; k++)
3224                 /* count number of lines */ ;
3225
3226         if (k >= MAX_LINES - 2) return FALSE;
3227         k--;
3228
3229         /* Move down lines */
3230         for (; tb->cy < k; k--)
3231         {
3232                 tb->lines_list[k+1] = tb->lines_list[k];
3233                 tb->states[k+1] = tb->states[k];
3234         }
3235
3236         /* Split current line */
3237         for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
3238         {
3239 #ifdef JP
3240                 if (iskanji(tb->lines_list[tb->cy][i]))
3241                         buf[j++] = tb->lines_list[tb->cy][i++];
3242 #endif
3243                 buf[j++] = tb->lines_list[tb->cy][i];
3244         }
3245         buf[j] = '\0';
3246         tb->lines_list[tb->cy+1] = string_make(&tb->lines_list[tb->cy][i]);
3247         string_free(tb->lines_list[tb->cy]);
3248         tb->lines_list[tb->cy] = string_make(buf);
3249
3250         /* Expressions need re-evaluation */
3251         tb->dirty_flags |= DIRTY_EXPRESSION;
3252
3253         /* Text is changed */
3254         tb->changed = TRUE;
3255
3256         return TRUE;
3257 }
3258
3259
3260 /*
3261  * Choose an item and get auto-picker entry from it.
3262  */
3263 static bool entry_from_choosed_object(autopick_type *entry)
3264 {
3265         object_type *o_ptr;
3266         concptr q, s;
3267
3268         q = _("どのアイテムを登録しますか? ", "Enter which item? ");
3269         s = _("アイテムを持っていない。", "You have nothing to enter.");
3270         o_ptr = choose_object(NULL, q, s, USE_INVEN | USE_FLOOR | USE_EQUIP);
3271         if (!o_ptr) return FALSE;
3272
3273         autopick_entry_from_object(entry, o_ptr);
3274         return TRUE;
3275 }
3276
3277
3278 /*
3279  * Choose an item for search
3280  */
3281 static byte get_object_for_search(object_type **o_handle, concptr *search_strp)
3282 {
3283         char buf[MAX_NLEN+20];
3284         object_type *o_ptr;
3285         concptr q, s;
3286
3287         q = _("どのアイテムを検索しますか? ", "Enter which item? ");
3288         s = _("アイテムを持っていない。", "You have nothing to enter.");
3289         o_ptr = choose_object(NULL, q, s, USE_INVEN | USE_FLOOR | USE_EQUIP);
3290         if (!o_ptr) return 0;
3291
3292         *o_handle = o_ptr;
3293
3294         string_free(*search_strp);
3295         object_desc(buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
3296         *search_strp = string_make(format("<%s>", buf));
3297         return 1;
3298 }
3299
3300
3301 /*
3302  * Prepare for search by destroyed object
3303  */
3304 static byte get_destroyed_object_for_search(object_type **o_handle, concptr *search_strp)
3305 {
3306         char buf[MAX_NLEN+20];
3307
3308         if (!autopick_last_destroyed_object.k_idx) return 0;
3309
3310         *o_handle = &autopick_last_destroyed_object;
3311
3312         string_free(*search_strp);
3313         object_desc(buf, *o_handle, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
3314         *search_strp = string_make(format("<%s>", buf));
3315         return 1;
3316 }
3317
3318
3319 /*
3320  * Choose an item or string for search
3321  */
3322 static byte get_string_for_search(object_type **o_handle, concptr *search_strp)
3323 {
3324         int pos = 0;
3325
3326         /*
3327          * Text color
3328          * TERM_YELLOW : Overwrite mode
3329          * TERM_WHITE : Insert mode
3330          */
3331         byte color = TERM_YELLOW;
3332         char buf[MAX_NLEN+20];
3333         const int len = 80;
3334
3335         char prompt[] = _("検索(^I:持ち物 ^L:破壊された物): ", "Search key(^I:inven ^L:destroyed): ");
3336         int col = sizeof(prompt) - 1;
3337
3338         /* Prepare string buffer for edit */
3339         if (*search_strp) strcpy(buf, *search_strp);
3340         else buf[0] = '\0';
3341
3342         /* Object searching mode */
3343         if (*o_handle)
3344         {
3345                 color = TERM_L_GREEN;
3346         }
3347
3348         /* Display prompt */
3349         prt(prompt, 0, 0);
3350
3351
3352         /* Process input */
3353         while (TRUE)
3354         {
3355                 bool back = FALSE;
3356                 int skey;
3357
3358                 /* Display the string */
3359                 Term_erase(col, 0, 255);
3360                 Term_putstr(col, 0, -1, color, buf);
3361
3362                 /* Place cursor */
3363                 Term_gotoxy(col + pos, 0);
3364
3365                 /* Get a special key code */
3366                 skey = inkey_special(TRUE);
3367
3368                 /* Analyze the key */
3369                 switch (skey)
3370                 {
3371                 case SKEY_LEFT:
3372                 case KTRL('b'):
3373                 {
3374                         int i = 0;
3375
3376                         /* Now on insert mode */
3377                         color = TERM_WHITE;
3378
3379                         /* No move at beginning of line */
3380                         if (0 == pos) break;
3381
3382                         while (TRUE)
3383                         {
3384                                 int next_pos = i + 1;
3385
3386 #ifdef JP
3387                                 if (iskanji(buf[i])) next_pos++;
3388 #endif
3389
3390                                 /* Is there the cursor at next position? */ 
3391                                 if (next_pos >= pos) break;
3392
3393                                 /* Move to next */
3394                                 i = next_pos;
3395                         }
3396
3397                         /* Get previous position */
3398                         pos = i;
3399
3400                         break;
3401                 }
3402
3403                 case SKEY_RIGHT:
3404                 case KTRL('f'):
3405                         /* Now on insert mode */
3406                         color = TERM_WHITE;
3407
3408                         /* No move at end of line */
3409                         if ('\0' == buf[pos]) break;
3410
3411 #ifdef JP
3412                         /* Move right */
3413                         if (iskanji(buf[pos])) pos += 2;
3414                         else pos++;
3415 #else
3416                         pos++;
3417 #endif
3418
3419                         break;
3420
3421                 case ESCAPE:
3422                         return 0;
3423
3424                 case KTRL('r'):
3425                         back = TRUE;
3426                         /* Fall through */
3427
3428                 case '\n':
3429                 case '\r':
3430                 case KTRL('s'):
3431                         if (*o_handle) return (back ? -1 : 1);
3432                         string_free(*search_strp);
3433                         *search_strp = string_make(buf);
3434                         *o_handle = NULL;
3435                         return (back ? -1 : 1);
3436
3437                 case KTRL('i'):
3438                         return get_object_for_search(o_handle, search_strp);
3439
3440                 case KTRL('l'):
3441                         /* Prepare string for destroyed object if there is one. */
3442                         if (get_destroyed_object_for_search(o_handle, search_strp))
3443                                 return 1;
3444                         break;
3445
3446                 case '\010':
3447                 {
3448                         /* Backspace */
3449
3450                         int i = 0;
3451
3452                         /* Now on insert mode */
3453                         color = TERM_WHITE;
3454
3455                         /* No move at beginning of line */
3456                         if (0 == pos) break;
3457
3458                         while (TRUE)
3459                         {
3460                                 int next_pos = i + 1;
3461
3462 #ifdef JP
3463                                 if (iskanji(buf[i])) next_pos++;
3464 #endif
3465
3466                                 /* Is there the cursor at next position? */ 
3467                                 if (next_pos >= pos) break;
3468
3469                                 /* Move to next */
3470                                 i = next_pos;
3471                         }
3472
3473                         /* Get previous position */
3474                         pos = i;
3475
3476                         /* Fall through to 'Delete key' */
3477                 }
3478
3479                 case 0x7F:
3480                 case KTRL('d'):
3481                         /* Delete key */
3482                 {
3483                         int dst, src;
3484
3485                         /* Now on insert mode */
3486                         color = TERM_WHITE;
3487
3488                         /* No move at end of line */
3489                         if ('\0' == buf[pos]) break;
3490
3491                         /* Position of next character */
3492                         src = pos + 1;
3493
3494 #ifdef JP
3495                         /* Next character is one more byte away */
3496                         if (iskanji(buf[pos])) src++;
3497 #endif
3498
3499                         dst = pos;
3500
3501                         /* Move characters at src to dst */
3502                         while ('\0' != (buf[dst++] = buf[src++]))
3503                                 /* loop */;
3504
3505                         break;
3506                 }
3507
3508                 default:
3509                 {
3510                         /* Insert a character */
3511
3512                         char tmp[100];
3513                         char c;
3514
3515                         /* Ignore special keys */
3516                         if (skey & SKEY_MASK) break;
3517
3518                         /* Get a character code */
3519                         c = (char)skey;
3520
3521                         /* Was non insert mode? */
3522                         if (color != TERM_WHITE)
3523                         {
3524                                 /* Was object searching mode */
3525                                 if (color == TERM_L_GREEN)
3526                                 {
3527                                         /* Cancel the mode */
3528                                         *o_handle = NULL;
3529
3530                                         /* Remove indicating string */
3531                                         string_free(*search_strp);
3532                                         *search_strp = NULL;
3533                                 }
3534
3535                                 /* Overwrite default string */
3536                                 buf[0] = '\0';
3537
3538                                 /* Go to insert mode */
3539                                 color = TERM_WHITE;
3540                         }
3541
3542                         /* Save right part of string */
3543                         strcpy(tmp, buf + pos);
3544 #ifdef JP
3545                         if (iskanji(c))
3546                         {
3547                                 char next;
3548
3549                                 /* Bypass macro processing */
3550                                 inkey_base = TRUE;
3551                                 next = inkey();
3552
3553                                 if (pos + 1 < len)
3554                                 {
3555                                         buf[pos++] = c;
3556                                         buf[pos++] = next;
3557                                 }
3558                                 else
3559                                 {
3560                                         bell();
3561                                 }
3562                         }
3563                         else
3564 #endif
3565                         {
3566 #ifdef JP
3567                                 if (pos < len && (isprint(c) || iskana(c)))
3568 #else
3569                                 if (pos < len && isprint(c))
3570 #endif
3571                                 {
3572                                         buf[pos++] = c;
3573                                 }
3574                                 else
3575                                 {
3576                                         bell();
3577                                 }
3578                         }
3579
3580                         /* Terminate */
3581                         buf[pos] = '\0';
3582
3583                         /* Write back the left part of string */
3584                         my_strcat(buf, tmp, len + 1);
3585
3586                         break;
3587                 } /* default: */
3588
3589                 }
3590
3591                 /* Object searching mode was cancelled? */
3592                 if (*o_handle && color != TERM_L_GREEN)
3593                 {
3594                         /* Cancel the mode */
3595                         *o_handle = NULL;
3596
3597                         /* Remove indicating string */
3598                         buf[0] = '\0';
3599                         string_free(*search_strp);
3600                         *search_strp = NULL;
3601
3602                 }
3603
3604
3605         } /* while (TRUE) */
3606 }
3607
3608
3609 /*
3610  * Search next line matches for o_ptr
3611  */
3612 static void search_for_object(text_body_type *tb, object_type *o_ptr, bool forward)
3613 {
3614         autopick_type an_entry, *entry = &an_entry;
3615         GAME_TEXT o_name[MAX_NLEN];
3616         int bypassed_cy = -1;
3617
3618         /* Start searching from current cursor position */
3619         int i = tb->cy;
3620
3621         /* Prepare object name string first */
3622         object_desc(o_name, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NO_PLURAL));
3623
3624         /* Convert the string to lower case */
3625         str_tolower(o_name);
3626
3627         while (TRUE)
3628         {
3629                 bool match;
3630
3631                 /* End of list? */
3632                 if (forward)
3633                 {
3634                         if (!tb->lines_list[++i]) break;
3635                 }
3636                 else
3637                 {
3638                         if (--i < 0) break;
3639                 }
3640
3641                 /* Is this line is a correct entry? */
3642                 if (!autopick_new_entry(entry, tb->lines_list[i], FALSE)) continue;
3643
3644                 /* Does this line match to the object? */
3645                 match = is_autopick_aux(o_ptr, entry, o_name);
3646                 autopick_free_entry(entry);
3647                 if (!match)     continue;
3648
3649                 /* Found a line but it's inactive */
3650                 if (tb->states[i] & LSTAT_BYPASS)
3651                 {
3652                         /* If it is first found, remember it */
3653                         if (bypassed_cy == -1) bypassed_cy = i;
3654                 }
3655
3656                 /* Found an active line! */
3657                 else
3658                 {
3659                         /* Move to this line */
3660                         tb->cx = 0;
3661                         tb->cy = i;
3662
3663                         if (bypassed_cy != -1)
3664                         {
3665                                 /* Mark as some lines are skipped */
3666                                 tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
3667                         }
3668
3669                         /* Found it! */
3670                         return;
3671                 }
3672         }
3673
3674         if (bypassed_cy != -1)
3675         {
3676                 /* Move to the remembered line */
3677                 tb->cx = 0;
3678                 tb->cy = bypassed_cy;
3679
3680                 /* Mark as this line is inactive */
3681                 tb->dirty_flags |= DIRTY_INACTIVE;
3682         }
3683
3684         else
3685         {
3686                 /* Mark as NOT FOUND */
3687                 tb->dirty_flags |= DIRTY_NOT_FOUND;
3688         }
3689
3690         return;
3691 }
3692
3693
3694 /*
3695  * Search next line matches to the string
3696  */
3697 static void search_for_string(text_body_type *tb, concptr search_str, bool forward)
3698 {
3699         int bypassed_cy = -1;
3700         int bypassed_cx = 0;
3701
3702         /* Start searching from current cursor position */
3703         int i = tb->cy;
3704
3705         while (TRUE)
3706         {
3707                 concptr pos;
3708
3709                 /* End of list? */
3710                 if (forward)
3711                 {
3712                         if (!tb->lines_list[++i]) break;
3713                 }
3714                 else
3715                 {
3716                         if (--i < 0) break;
3717                 }
3718
3719                 /* Look for the string pattern */
3720                 pos = my_strstr(tb->lines_list[i], search_str);
3721
3722                 /* Not found! */
3723                 if (!pos) continue;
3724
3725                 /* Found a line but it's inactive */
3726                 if ((tb->states[i] & LSTAT_BYPASS) &&
3727                     !(tb->states[i] & LSTAT_EXPRESSION))
3728                 {
3729                         /* If it is first found, remember it */
3730                         if (bypassed_cy == -1)
3731                         {
3732                                 bypassed_cy = i;
3733                                 bypassed_cx = (int)(pos - tb->lines_list[i]);
3734                         }
3735                 }
3736
3737                 /* Found an active line! */
3738                 else
3739                 {
3740                         /* Move to this location */
3741                         tb->cx = (int)(pos - tb->lines_list[i]);
3742                         tb->cy = i;
3743
3744                         if (bypassed_cy != -1)
3745                         {
3746                                 /* Mark as some lines are skipped */
3747                                 tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
3748                         }
3749
3750                         /* Found it! */
3751                         return;
3752                 }
3753         }
3754
3755         if (bypassed_cy != -1)
3756         {
3757                 /* Move to the remembered line */
3758                 tb->cx = bypassed_cx;
3759                 tb->cy = bypassed_cy;
3760
3761                 /* Mark as this line is inactive */
3762                 tb->dirty_flags |= DIRTY_INACTIVE;
3763         }
3764
3765         else
3766         {
3767                 /* Mark as NOT FOUND */
3768                 tb->dirty_flags |= DIRTY_NOT_FOUND;
3769         }
3770
3771         return;
3772 }
3773
3774
3775
3776
3777 /*
3778  * Editor command id's
3779  */
3780 #define EC_QUIT            1
3781 #define EC_SAVEQUIT        2
3782 #define EC_REVERT              3
3783 #define EC_HELP            4
3784 #define EC_RETURN              5
3785 #define EC_LEFT                6 
3786 #define EC_DOWN                7 
3787 #define EC_UP                  8 
3788 #define EC_RIGHT               9 
3789 #define EC_BOL                 10
3790 #define EC_EOL                 11
3791 #define EC_PGUP                12
3792 #define EC_PGDOWN              13
3793 #define EC_TOP                 14
3794 #define EC_BOTTOM              15
3795 #define EC_CUT                 16
3796 #define EC_COPY                17
3797 #define EC_PASTE               18
3798 #define EC_BLOCK               19
3799 #define EC_KILL_LINE           20
3800 #define EC_DELETE_CHAR         21
3801 #define EC_BACKSPACE           22
3802 #define EC_SEARCH_STR          23
3803 #define EC_SEARCH_FORW         24
3804 #define EC_SEARCH_BACK         25
3805 #define EC_SEARCH_OBJ          26
3806 #define EC_SEARCH_DESTROYED    27
3807 #define EC_INSERT_OBJECT       28
3808 #define EC_INSERT_DESTROYED    29
3809 #define EC_INSERT_BLOCK        30
3810 #define EC_INSERT_MACRO        31
3811 #define EC_INSERT_KEYMAP       32
3812 #define EC_CL_AUTOPICK         33
3813 #define EC_CL_DESTROY          34
3814 #define EC_CL_LEAVE            35
3815 #define EC_CL_QUERY            36
3816 #define EC_CL_NO_DISP          37
3817 #define EC_OK_COLLECTING       38
3818 #define EC_IK_UNAWARE          39
3819 #define EC_IK_UNIDENTIFIED     40
3820 #define EC_IK_IDENTIFIED       41
3821 #define EC_IK_STAR_IDENTIFIED  42
3822 #define EC_OK_BOOSTED          43
3823 #define EC_OK_MORE_DICE        44
3824 #define EC_OK_MORE_BONUS       45
3825 #define EC_OK_WORTHLESS        46
3826 #define EC_OK_ARTIFACT         47
3827 #define EC_OK_EGO              48
3828 #define EC_OK_GOOD             49
3829 #define EC_OK_NAMELESS         50
3830 #define EC_OK_AVERAGE          51
3831 #define EC_OK_RARE             52       
3832 #define EC_OK_COMMON           53
3833 #define EC_OK_WANTED           54
3834 #define EC_OK_UNIQUE           55
3835 #define EC_OK_HUMAN            56
3836 #define EC_OK_UNREADABLE       57
3837 #define EC_OK_REALM1           58
3838 #define EC_OK_REALM2           59
3839 #define EC_OK_FIRST            60
3840 #define EC_OK_SECOND           61
3841 #define EC_OK_THIRD            62
3842 #define EC_OK_FOURTH           63
3843 #define EC_KK_WEAPONS          64
3844 #define EC_KK_FAVORITE_WEAPONS 65
3845 #define EC_KK_ARMORS           66
3846 #define EC_KK_MISSILES         67
3847 #define EC_KK_DEVICES          68
3848 #define EC_KK_LIGHTS           69
3849 #define EC_KK_JUNKS            70
3850 #define EC_KK_CORPSES          71
3851 #define EC_KK_SPELLBOOKS       72
3852 #define EC_KK_SHIELDS          73
3853 #define EC_KK_BOWS             74
3854 #define EC_KK_RINGS            75
3855 #define EC_KK_AMULETS          76
3856 #define EC_KK_SUITS            77
3857 #define EC_KK_CLOAKS           78
3858 #define EC_KK_HELMS            79
3859 #define EC_KK_GLOVES           80
3860 #define EC_KK_BOOTS            81
3861
3862
3863 /* Manu names */
3864 #ifdef JP
3865
3866 static GAME_TEXT MN_QUIT[] = "セーブ無しで終了";
3867 static GAME_TEXT MN_SAVEQUIT[] = "セーブして終了";
3868 static GAME_TEXT MN_REVERT[] = "全ての変更を破棄";
3869 static GAME_TEXT MN_HELP[] = "ヘルプ";
3870
3871 static GAME_TEXT MN_MOVE[] = "カーソル移動";
3872 static GAME_TEXT MN_LEFT[] =   "左          (←矢印キー)";
3873 static GAME_TEXT MN_DOWN[] =   "下          (↓矢印キー)";
3874 static GAME_TEXT MN_UP[] =     "上          (↑矢印キー)";
3875 static GAME_TEXT MN_RIGHT[] =  "右          (→矢印キー)";
3876 static GAME_TEXT MN_BOL[] =    "行の先頭";
3877 static GAME_TEXT MN_EOL[] =    "行の終端";
3878 static GAME_TEXT MN_PGUP[] =   "上のページ  (PageUpキー)";
3879 static GAME_TEXT MN_PGDOWN[] = "下のページ  (PageDownキー)";
3880 static GAME_TEXT MN_TOP[] =    "1行目へ移動 (Homeキー)";
3881 static GAME_TEXT MN_BOTTOM[] = "最下行へ移動(Endキー)";
3882
3883 static GAME_TEXT MN_EDIT[] = "編集";
3884 static GAME_TEXT MN_CUT[] = "カット";
3885 static GAME_TEXT MN_COPY[] = "コピー";
3886 static GAME_TEXT MN_PASTE[] = "ペースト";
3887 static GAME_TEXT MN_BLOCK[] = "選択範囲の指定";
3888 static GAME_TEXT MN_KILL_LINE[] = "行の残りを削除";
3889 static GAME_TEXT MN_DELETE_CHAR[] = "1文字削除";
3890 static GAME_TEXT MN_BACKSPACE[] = "バックスペース";
3891 static GAME_TEXT MN_RETURN[] = "改行";
3892
3893 static GAME_TEXT MN_SEARCH[] = "検索";
3894 static GAME_TEXT MN_SEARCH_STR[] = "文字列で検索";
3895 static GAME_TEXT MN_SEARCH_FORW[] = "前方へ再検索";
3896 static GAME_TEXT MN_SEARCH_BACK[] = "後方へ再検索";
3897 static GAME_TEXT MN_SEARCH_OBJ[] = "アイテムを選択して検索";
3898 static GAME_TEXT MN_SEARCH_DESTROYED[] = "自動破壊されたアイテムで検索";
3899
3900 static GAME_TEXT MN_INSERT[] = "色々挿入";
3901 static GAME_TEXT MN_INSERT_OBJECT[] = "選択したアイテムの名前を挿入";
3902 static GAME_TEXT MN_INSERT_DESTROYED[] = "自動破壊されたアイテムの名前を挿入";
3903 static GAME_TEXT MN_INSERT_BLOCK[] = "条件分岐ブロックの例を挿入";
3904 static GAME_TEXT MN_INSERT_MACRO[] = "マクロ定義を挿入";
3905 static GAME_TEXT MN_INSERT_KEYMAP[] = "キーマップ定義を挿入";
3906
3907 static GAME_TEXT MN_COMMAND_LETTER[] = "拾い/破壊/放置の選択";
3908 static GAME_TEXT MN_CL_AUTOPICK[] = "「 」 (自動拾い)";
3909 static GAME_TEXT MN_CL_DESTROY[] = "「!」 (自動破壊)";
3910 static GAME_TEXT MN_CL_LEAVE[] = "「~」 (放置)";
3911 static GAME_TEXT MN_CL_QUERY[] = "「;」 (確認して拾う)";
3912 static GAME_TEXT MN_CL_NO_DISP[] = "「(」 (マップコマンドで表示しない)";
3913
3914 static GAME_TEXT MN_ADJECTIVE_GEN[] = "形容詞(一般)の選択";
3915 static GAME_TEXT MN_RARE[] = "レアな (装備)";
3916 static GAME_TEXT MN_COMMON[] = "ありふれた (装備)";
3917
3918 static GAME_TEXT MN_ADJECTIVE_SPECIAL[] = "形容詞(特殊)の選択";
3919 static GAME_TEXT MN_BOOSTED[] = "ダイス目の違う (武器)";
3920 static GAME_TEXT MN_MORE_DICE[] = "ダイス目 # 以上の (武器)";
3921 static GAME_TEXT MN_MORE_BONUS[] = "修正値 # 以上の (指輪等)";
3922 static GAME_TEXT MN_WANTED[] = "賞金首の (死体)";
3923 static GAME_TEXT MN_UNIQUE[] = "ユニーク・モンスターの (死体)";
3924 static GAME_TEXT MN_HUMAN[] = "人間の (死体)";
3925 static GAME_TEXT MN_UNREADABLE[] = "読めない (魔法書)";
3926 static GAME_TEXT MN_REALM1[] = "第一領域の (魔法書)";
3927 static GAME_TEXT MN_REALM2[] = "第二領域の (魔法書)";
3928 static GAME_TEXT MN_FIRST[] = "1冊目の (魔法書)";
3929 static GAME_TEXT MN_SECOND[] = "2冊目の (魔法書)";
3930 static GAME_TEXT MN_THIRD[] = "3冊目の (魔法書)";
3931 static GAME_TEXT MN_FOURTH[] = "4冊目の (魔法書)";
3932
3933 static GAME_TEXT MN_NOUN[] = "名詞の選択";
3934
3935 #else
3936
3937 static GAME_TEXT MN_QUIT[] = "Quit without save";
3938 static GAME_TEXT MN_SAVEQUIT[] = "Save & Quit";
3939 static GAME_TEXT MN_REVERT[] = "Revert all changes";
3940 static GAME_TEXT MN_HELP[] = "Help";
3941
3942 static GAME_TEXT MN_MOVE[] =   "Move cursor";
3943 static GAME_TEXT MN_LEFT[] =   "Left     (Left Arrow key)";
3944 static GAME_TEXT MN_DOWN[] =   "Down     (Down Arrow key)";
3945 static GAME_TEXT MN_UP[] =     "Up       (Up Arrow key)";
3946 static GAME_TEXT MN_RIGHT[] =  "Right    (Right Arrow key)";
3947 static GAME_TEXT MN_BOL[] =    "Beggining of line";
3948 static GAME_TEXT MN_EOL[] =    "End of line";
3949 static GAME_TEXT MN_PGUP[] =   "Page up  (PageUp key)";
3950 static GAME_TEXT MN_PGDOWN[] = "Page down(PageDown key)";
3951 static GAME_TEXT MN_TOP[] =    "Top      (Home key)";
3952 static GAME_TEXT MN_BOTTOM[] = "Bottom   (End key)";
3953
3954 static GAME_TEXT MN_EDIT[] = "Edit";
3955 static GAME_TEXT MN_CUT[] = "Cut";
3956 static GAME_TEXT MN_COPY[] = "Copy";
3957 static GAME_TEXT MN_PASTE[] = "Paste";
3958 static GAME_TEXT MN_BLOCK[] = "Select block";
3959 static GAME_TEXT MN_KILL_LINE[] = "Kill rest of line";
3960 static GAME_TEXT MN_DELETE_CHAR[] = "Delete character";
3961 static GAME_TEXT MN_BACKSPACE[] = "Backspace";
3962 static GAME_TEXT MN_RETURN[] = "Return";
3963
3964 static GAME_TEXT MN_SEARCH[] = "Search";
3965 static GAME_TEXT MN_SEARCH_STR[] = "Search by string";
3966 static GAME_TEXT MN_SEARCH_FORW[] = "Search forward";
3967 static GAME_TEXT MN_SEARCH_BACK[] = "Search backward";
3968 static GAME_TEXT MN_SEARCH_OBJ[] = "Search by p_ptr->inventory_list object";
3969 static GAME_TEXT MN_SEARCH_DESTROYED[] = "Search by destroyed object";
3970
3971 static GAME_TEXT MN_INSERT[] = "Insert...";
3972 static GAME_TEXT MN_INSERT_OBJECT[] = "Insert name of choosen object";
3973 static GAME_TEXT MN_INSERT_DESTROYED[] = "Insert name of destroyed object";
3974 static GAME_TEXT MN_INSERT_BLOCK[] = "Insert conditional block";
3975 static GAME_TEXT MN_INSERT_MACRO[] = "Insert a macro definition";
3976 static GAME_TEXT MN_INSERT_KEYMAP[] = "Insert a keymap definition";
3977
3978 static GAME_TEXT MN_COMMAND_LETTER[] = "Command letter";
3979 static GAME_TEXT MN_CL_AUTOPICK[] = "' ' (Auto pick)";
3980 static GAME_TEXT MN_CL_DESTROY[] = "'!' (Auto destroy)";
3981 static GAME_TEXT MN_CL_LEAVE[] = "'~' (Leave it on the floor)";
3982 static GAME_TEXT MN_CL_QUERY[] = "';' (Query to pick up)";
3983 static GAME_TEXT MN_CL_NO_DISP[] = "'(' (No display on the large map)";
3984
3985 static GAME_TEXT MN_ADJECTIVE_GEN[] = "Adjective (general)";
3986 static GAME_TEXT MN_RARE[] = "rare (equipments)";
3987 static GAME_TEXT MN_COMMON[] = "common (equipments)";
3988
3989 static GAME_TEXT MN_ADJECTIVE_SPECIAL[] = "Adjective (special)";
3990 static GAME_TEXT MN_BOOSTED[] = "dice boosted (weapons)";
3991 static GAME_TEXT MN_MORE_DICE[] = "more than # dice (weapons)";
3992 static GAME_TEXT MN_MORE_BONUS[] = "more bonus than # (rings etc.)";
3993 static GAME_TEXT MN_WANTED[] = "wanted (corpse)";
3994 static GAME_TEXT MN_UNIQUE[] = "unique (corpse)";
3995 static GAME_TEXT MN_HUMAN[] = "human (corpse)";
3996 static GAME_TEXT MN_UNREADABLE[] = "unreadable (spellbooks)";
3997 static GAME_TEXT MN_REALM1[] = "realm1 (spellbooks)";
3998 static GAME_TEXT MN_REALM2[] = "realm2 (spellbooks)";
3999 static GAME_TEXT MN_FIRST[] = "first (spellbooks)";
4000 static GAME_TEXT MN_SECOND[] = "second (spellbooks)";
4001 static GAME_TEXT MN_THIRD[] = "third (spellbooks)";
4002 static GAME_TEXT MN_FOURTH[] = "fourth (spellbooks)";
4003
4004 static GAME_TEXT MN_NOUN[] = "Keywords (noun)";
4005
4006 #endif
4007
4008
4009 typedef struct {
4010         concptr name;
4011         int level;
4012         int key;
4013         int com_id;
4014 } command_menu_type;
4015
4016
4017 command_menu_type menu_data[] =
4018 {
4019         {MN_HELP, 0, -1, EC_HELP},
4020         {MN_QUIT, 0, KTRL('q'), EC_QUIT}, 
4021         {MN_SAVEQUIT, 0, KTRL('w'), EC_SAVEQUIT}, 
4022         {MN_REVERT, 0, KTRL('z'), EC_REVERT},
4023
4024         {MN_EDIT, 0, -1, -1},
4025         {MN_CUT, 1, KTRL('x'), EC_CUT},
4026         {MN_COPY, 1, KTRL('c'), EC_COPY},
4027         {MN_PASTE, 1, KTRL('v'), EC_PASTE},
4028         {MN_BLOCK, 1, KTRL('g'), EC_BLOCK},
4029         {MN_KILL_LINE, 1, KTRL('k'), EC_KILL_LINE},
4030         {MN_DELETE_CHAR, 1, KTRL('d'), EC_DELETE_CHAR},
4031         {MN_BACKSPACE, 1, KTRL('h'), EC_BACKSPACE},
4032         {MN_RETURN, 1, KTRL('j'), EC_RETURN},
4033         {MN_RETURN, 1, KTRL('m'), EC_RETURN},
4034
4035         {MN_SEARCH, 0, -1, -1},
4036         {MN_SEARCH_STR, 1, KTRL('s'), EC_SEARCH_STR},
4037         {MN_SEARCH_FORW, 1, -1, EC_SEARCH_FORW},
4038         {MN_SEARCH_BACK, 1, KTRL('r'), EC_SEARCH_BACK},
4039         {MN_SEARCH_OBJ, 1, KTRL('y'), EC_SEARCH_OBJ},
4040         {MN_SEARCH_DESTROYED, 1, -1, EC_SEARCH_DESTROYED},
4041
4042         {MN_MOVE, 0, -1, -1},
4043         {MN_LEFT, 1, KTRL('b'), EC_LEFT},
4044         {MN_DOWN, 1, KTRL('n'), EC_DOWN},
4045         {MN_UP, 1, KTRL('p'), EC_UP},
4046         {MN_RIGHT, 1, KTRL('f'), EC_RIGHT},
4047         {MN_BOL, 1, KTRL('a'), EC_BOL},
4048         {MN_EOL, 1, KTRL('e'), EC_EOL},
4049         {MN_PGUP, 1, KTRL('o'), EC_PGUP},
4050         {MN_PGDOWN, 1, KTRL('l'), EC_PGDOWN},
4051         {MN_TOP, 1, KTRL('t'), EC_TOP},
4052         {MN_BOTTOM, 1, KTRL('u'), EC_BOTTOM},
4053
4054         {MN_INSERT, 0, -1, -1},
4055         {MN_INSERT_OBJECT, 1, KTRL('i'), EC_INSERT_OBJECT},
4056         {MN_INSERT_DESTROYED, 1, -1, EC_INSERT_DESTROYED},
4057         {MN_INSERT_BLOCK, 1, -1, EC_INSERT_BLOCK},
4058         {MN_INSERT_MACRO, 1, -1, EC_INSERT_MACRO},
4059         {MN_INSERT_KEYMAP, 1, -1, EC_INSERT_KEYMAP},
4060
4061         {MN_ADJECTIVE_GEN, 0, -1, -1},
4062         {KEY_UNAWARE, 1, -1, EC_IK_UNAWARE},
4063         {KEY_UNIDENTIFIED, 1, -1, EC_IK_UNIDENTIFIED},
4064         {KEY_IDENTIFIED, 1, -1, EC_IK_IDENTIFIED},
4065         {KEY_STAR_IDENTIFIED, 1, -1, EC_IK_STAR_IDENTIFIED},
4066         {KEY_COLLECTING, 1, -1, EC_OK_COLLECTING},
4067         {KEY_ARTIFACT, 1, -1, EC_OK_ARTIFACT},
4068         {KEY_EGO, 1, -1, EC_OK_EGO},
4069         {KEY_GOOD, 1, -1, EC_OK_GOOD},
4070         {KEY_NAMELESS, 1, -1, EC_OK_NAMELESS},
4071         {KEY_AVERAGE, 1, -1, EC_OK_AVERAGE},
4072         {KEY_WORTHLESS, 1, -1, EC_OK_WORTHLESS},
4073         {MN_RARE, 1, -1, EC_OK_RARE},
4074         {MN_COMMON, 1, -1, EC_OK_COMMON},
4075
4076         {MN_ADJECTIVE_SPECIAL, 0, -1, -1},
4077         {MN_BOOSTED, 1, -1, EC_OK_BOOSTED},
4078         {MN_MORE_DICE, 1, -1, EC_OK_MORE_DICE},
4079         {MN_MORE_BONUS, 1, -1, EC_OK_MORE_BONUS},
4080         {MN_WANTED, 1, -1, EC_OK_WANTED},
4081         {MN_UNIQUE, 1, -1, EC_OK_UNIQUE},
4082         {MN_HUMAN, 1, -1, EC_OK_HUMAN},
4083         {MN_UNREADABLE, 1, -1, EC_OK_UNREADABLE},
4084         {MN_REALM1, 1, -1, EC_OK_REALM1},
4085         {MN_REALM2, 1, -1, EC_OK_REALM2},
4086         {MN_FIRST, 1, -1, EC_OK_FIRST},
4087         {MN_SECOND, 1, -1, EC_OK_SECOND},
4088         {MN_THIRD, 1, -1, EC_OK_THIRD},
4089         {MN_FOURTH, 1, -1, EC_OK_FOURTH},
4090
4091         {MN_NOUN, 0, -1, -1},
4092         {KEY_WEAPONS, 1, -1, EC_KK_WEAPONS},
4093         {KEY_FAVORITE_WEAPONS, 1, -1, EC_KK_FAVORITE_WEAPONS},
4094         {KEY_ARMORS, 1, -1, EC_KK_ARMORS},
4095         {KEY_MISSILES, 1, -1, EC_KK_MISSILES},
4096         {KEY_DEVICES, 1, -1, EC_KK_DEVICES},
4097         {KEY_LIGHTS, 1, -1, EC_KK_LIGHTS},
4098         {KEY_JUNKS, 1, -1, EC_KK_JUNKS},
4099         {KEY_CORPSES, 1, -1, EC_KK_CORPSES},
4100         {KEY_SPELLBOOKS, 1, -1, EC_KK_SPELLBOOKS},
4101         {KEY_SHIELDS, 1, -1, EC_KK_SHIELDS},
4102         {KEY_BOWS, 1, -1, EC_KK_BOWS},
4103         {KEY_RINGS, 1, -1, EC_KK_RINGS},
4104         {KEY_AMULETS, 1, -1, EC_KK_AMULETS},
4105         {KEY_SUITS, 1, -1, EC_KK_SUITS},
4106         {KEY_CLOAKS, 1, -1, EC_KK_CLOAKS},
4107         {KEY_HELMS, 1, -1, EC_KK_HELMS},
4108         {KEY_GLOVES, 1, -1, EC_KK_GLOVES},
4109         {KEY_BOOTS, 1, -1, EC_KK_BOOTS},
4110
4111         {MN_COMMAND_LETTER, 0, -1, -1},
4112         {MN_CL_AUTOPICK, 1, -1, EC_CL_AUTOPICK},
4113         {MN_CL_DESTROY, 1, -1, EC_CL_DESTROY},
4114         {MN_CL_LEAVE, 1, -1, EC_CL_LEAVE},
4115         {MN_CL_QUERY, 1, -1, EC_CL_QUERY},
4116         {MN_CL_NO_DISP, 1, -1, EC_CL_NO_DISP},
4117
4118         {MN_DELETE_CHAR, -1, 0x7F, EC_DELETE_CHAR},
4119
4120         {NULL, -1, -1, 0}
4121 };
4122
4123
4124 /*
4125  * Find a command by 'key'.
4126  */
4127 static int get_com_id(char key)
4128 {
4129         int i;
4130
4131         for (i = 0; menu_data[i].name; i++)
4132         {
4133                 if (menu_data[i].key == key)
4134                 {
4135                         return menu_data[i].com_id;
4136                 }
4137         }
4138
4139         return 0;
4140 }
4141
4142
4143 /*
4144  * Display the menu, and get a command 
4145  */
4146 static int do_command_menu(int level, int start)
4147 {
4148         int i;
4149         int max_len = 0;
4150         int max_menu_wid;
4151         int col0 = 5 + level*7;
4152         int row0 = 1 + level*3;
4153         byte menu_key = 0;
4154         int menu_id_list[26];
4155         bool redraw = TRUE;
4156         char linestr[MAX_LINELEN];
4157
4158         /* Get max length */
4159         menu_key = 0;
4160         for (i = start; menu_data[i].level >= level; i++)
4161         {
4162                 int len;
4163
4164                 /* Ignore lower level sub menus */
4165                 if (menu_data[i].level > level) continue;
4166
4167                 len = strlen(menu_data[i].name);
4168                 if (len > max_len) max_len = len;
4169
4170                 menu_id_list[menu_key] = i;
4171                 menu_key++;
4172         }
4173
4174         while (menu_key < 26)
4175         {
4176                 menu_id_list[menu_key] = -1;
4177                 menu_key++;
4178         }
4179
4180         /* Extra space for displaying menu key and command key */
4181         max_menu_wid = max_len + 3 + 3;
4182
4183         /* Prepare box line */
4184         linestr[0] = '\0';
4185         strcat(linestr, "+");
4186         for (i = 0; i < max_menu_wid + 2; i++)
4187         {
4188                 strcat(linestr, "-");
4189         }
4190         strcat(linestr, "+");
4191
4192         while (TRUE)
4193         {
4194                 int com_id;
4195                 char key;
4196                 int menu_id;
4197
4198                 if (redraw)
4199                 {
4200                         int row1 = row0 + 1;
4201
4202                         /* Draw top line */
4203                         Term_putstr(col0, row0, -1, TERM_WHITE, linestr);
4204
4205                         /* Draw menu items */
4206                         menu_key = 0;
4207                         for (i = start; menu_data[i].level >= level; i++)
4208                         {
4209                                 char com_key_str[3];
4210                                 concptr str;
4211
4212                                 /* Ignore lower level sub menus */
4213                                 if (menu_data[i].level > level) continue;
4214
4215                                 if (menu_data[i].com_id == -1)
4216                                 {
4217                                         strcpy(com_key_str, _("▼", ">"));
4218                                 }
4219                                 else if (menu_data[i].key != -1)
4220                                 {
4221                                         com_key_str[0] = '^';
4222                                         com_key_str[1] = menu_data[i].key + '@';
4223                                         com_key_str[2] = '\0';
4224                                 }
4225                                 else
4226                                 {
4227                                         com_key_str[0] = '\0';
4228                                 }
4229
4230                                 str = format("| %c) %-*s %2s | ", menu_key + 'a', max_len, menu_data[i].name, com_key_str);
4231
4232                                 Term_putstr(col0, row1++, -1, TERM_WHITE, str);
4233
4234                                 menu_key++;
4235                         }
4236
4237                         /* Draw bottom line */
4238                         Term_putstr(col0, row1, -1, TERM_WHITE, linestr);
4239
4240                         /* The menu was shown */
4241                         redraw = FALSE;
4242                 }
4243                 prt(format(_("(a-%c) コマンド:", "(a-%c) Command:"), menu_key + 'a' - 1), 0, 0);
4244                 key = inkey();
4245
4246                 if (key == ESCAPE) return 0;
4247
4248                 if ('a' <= key && key <= 'z')
4249                 {
4250                         menu_id = menu_id_list[key - 'a'];
4251
4252                         if (menu_id >= 0)
4253                         {
4254                                 com_id = menu_data[menu_id].com_id;
4255
4256                                 if (com_id == -1)
4257                                 {
4258                                         com_id = do_command_menu(level + 1, menu_id + 1);
4259
4260                                         if (com_id) return com_id;
4261                                         else redraw = TRUE;
4262                                 }
4263                                 else if (com_id)
4264                                 {
4265                                         return com_id;
4266                                 }
4267                         }
4268                 }
4269
4270                 else
4271                 {
4272                         com_id = get_com_id(key);
4273                         if (com_id) return com_id;
4274                         else continue;
4275                 }
4276         }
4277 }
4278
4279
4280 static chain_str_type *new_chain_str(concptr str)
4281 {
4282         chain_str_type *chain;
4283
4284         size_t len = strlen(str);
4285
4286         chain = (chain_str_type *)ralloc(sizeof(chain_str_type) + len * sizeof(char));
4287
4288         strcpy(chain->s, str);
4289         chain->next = NULL;
4290
4291         return chain;
4292 }
4293
4294
4295 static void kill_yank_chain(text_body_type *tb)
4296 {
4297         chain_str_type *chain = tb->yank;
4298         tb->yank = NULL;
4299         tb->yank_eol = TRUE;
4300
4301         while (chain)
4302         {
4303                 chain_str_type *next = chain->next;
4304                 size_t len = strlen(chain->s);
4305
4306                 rnfree(chain, sizeof(chain_str_type) + len * sizeof(char));
4307
4308                 chain = next;
4309         }
4310 }
4311
4312
4313 static void add_str_to_yank(text_body_type *tb, concptr str)
4314 {
4315         chain_str_type *chain;
4316
4317         tb->yank_eol = FALSE;
4318
4319         if (NULL == tb->yank)
4320         {
4321                 tb->yank = new_chain_str(str);
4322                 return;
4323         }
4324
4325         chain = tb->yank;
4326
4327         while (TRUE)
4328         {
4329                 if (!chain->next)
4330                 {
4331                         chain->next = new_chain_str(str);
4332                         return;
4333                 }
4334
4335                 /* Go to next */
4336                 chain = chain->next;
4337         }
4338 }
4339
4340
4341 /*
4342  * Do work for the copy editor-command
4343  */
4344 static void copy_text_to_yank(text_body_type *tb)
4345 {
4346         int len = strlen(tb->lines_list[tb->cy]);
4347
4348         /* Correct cursor location */
4349         if (tb->cx > len) tb->cx = len;
4350
4351         /* Use single line? */
4352         if (!tb->mark)
4353         {
4354                 /* Select a single line */
4355                 tb->cx = 0;
4356                 tb->my = tb->cy;
4357                 tb->mx = len;
4358         }
4359
4360         /* Kill old yank buffer */
4361         kill_yank_chain(tb);
4362
4363
4364         /* Single line case */
4365         if (tb->my == tb->cy)
4366         {
4367                 int i;
4368                 char buf[MAX_LINELEN];
4369                 int bx1 = MIN(tb->mx, tb->cx);
4370                 int bx2 = MAX(tb->mx, tb->cx);
4371
4372                 /* Correct fake cursor position */
4373                 if (bx2 > len) bx2 = len;
4374
4375                 /* Whole part of this line is selected */
4376                 if (bx1 == 0 && bx2 == len)
4377                 {
4378                         /* Copy this line */
4379                         add_str_to_yank(tb, tb->lines_list[tb->cy]);
4380
4381                         /* Add end of line to the buffer */
4382                         add_str_to_yank(tb, "");
4383                 }
4384
4385                 /* Segment of this line is selected */
4386                 else
4387                 {
4388                         for (i = 0; i < bx2 - bx1; i++)
4389                         {
4390                                 buf[i] = tb->lines_list[tb->cy][bx1 + i];
4391                         }
4392                         buf[i] = '\0';
4393
4394                         /* Copy this segment of line */
4395                         add_str_to_yank(tb, buf);
4396                 }
4397         }
4398
4399         /* Multiple lines case */
4400         else /* if (tb->my != tb->cy) */
4401         {
4402                 int y;
4403
4404                 int by1 = MIN(tb->my, tb->cy);
4405                 int by2 = MAX(tb->my, tb->cy);
4406
4407                 /* Copy lines */
4408                 for (y = by1; y <= by2; y++)
4409                 {
4410                         /* Copy this line */
4411                         add_str_to_yank(tb, tb->lines_list[y]);
4412                 }
4413
4414                 /* Add final end of line to the buffer */
4415                 add_str_to_yank(tb, "");
4416         }
4417
4418         /* Disable selection */
4419         tb->mark = 0;
4420
4421         /* Now dirty */
4422         tb->dirty_flags |= DIRTY_ALL;
4423 }
4424
4425
4426 #define DESCRIPT_HGT 3
4427
4428 /*
4429  * Draw text
4430  */
4431 static void draw_text_editor(text_body_type *tb)
4432 {
4433         int i;
4434         int by1 = 0, by2 = 0;
4435
4436         Term_get_size(&tb->wid, &tb->hgt);
4437
4438         /*
4439          * Top line (-1), description line (-3), separator (-1)
4440          *  == -5
4441          */
4442         tb->hgt -= 2 + DESCRIPT_HGT;
4443
4444 #ifdef JP
4445         /* Don't let cursor at second byte of kanji */
4446         for (i = 0; tb->lines_list[tb->cy][i]; i++)
4447                 if (iskanji(tb->lines_list[tb->cy][i]))
4448                 {
4449                         i++;
4450                         if (i == tb->cx)
4451                         {
4452                                 /*
4453                                  * Move to a correct position in the
4454                                  * left or right
4455                                  */
4456                                 if (i & 1) tb->cx--;
4457                                 else tb->cx++;
4458                                 break;
4459                         }
4460                 }
4461 #endif
4462
4463         /* Scroll if necessary */
4464         if (tb->cy < tb->upper || tb->upper + tb->hgt <= tb->cy)
4465                 tb->upper = tb->cy - (tb->hgt)/2;
4466         if (tb->upper < 0)
4467                 tb->upper = 0;
4468         if ((tb->cx < tb->left + 10 && tb->left > 0) || tb->left + tb->wid - 5 <= tb->cx)
4469                 tb->left = tb->cx - (tb->wid)*2/3;
4470         if (tb->left < 0)
4471                 tb->left = 0;
4472
4473         /* Redraw whole window after resize */
4474         if (tb->old_wid != tb->wid || tb->old_hgt != tb->hgt)
4475                 tb->dirty_flags |= DIRTY_SCREEN;
4476
4477         /* Redraw all text after scroll */
4478         else if (tb->old_upper != tb->upper || tb->old_left != tb->left)
4479                 tb->dirty_flags |= DIRTY_ALL;
4480
4481
4482         if (tb->dirty_flags & DIRTY_SCREEN)
4483         {
4484                 tb->dirty_flags |= (DIRTY_ALL | DIRTY_MODE);
4485                 Term_clear();
4486         }
4487
4488         /* Redraw mode line */
4489         if (tb->dirty_flags & DIRTY_MODE)
4490         {
4491                 char buf[MAX_LINELEN];
4492
4493                 int sepa_length = tb->wid;
4494
4495                 /* Separator */
4496                 for (i = 0; i < sepa_length; i++)
4497                         buf[i] = '-';
4498                 buf[i] = '\0';
4499
4500                 Term_putstr(0, tb->hgt + 1, sepa_length, TERM_WHITE, buf);
4501         }
4502
4503         if (tb->dirty_flags & DIRTY_EXPRESSION)
4504         {
4505                 int y;
4506                 byte state = 0;
4507
4508                 for (y = 0; tb->lines_list[y]; y++)
4509                 {
4510                         char f;
4511                         concptr v;
4512                         concptr s = tb->lines_list[y];
4513                         char *ss, *s_keep;
4514                         int s_len;
4515
4516                         /* Update this line's state */
4517                         tb->states[y] = state;
4518
4519                         if (*s++ != '?') continue;
4520                         if (*s++ != ':') continue;
4521
4522                         /* Lines below this line are auto-registered */
4523                         if (streq(s, "$AUTOREGISTER"))
4524                                 state |= LSTAT_AUTOREGISTER;
4525
4526                         s_len = strlen(s);
4527                         ss = (char *)string_make(s);
4528                         s_keep = ss;
4529
4530                         /* Parse the expr */
4531                         v = process_pref_file_expr(&ss, &f);
4532
4533                         /* Set flag */
4534                         if (streq(v, "0")) state |= LSTAT_BYPASS;
4535                         else state &= ~LSTAT_BYPASS;
4536
4537                         /* Cannot use string_free() because the string was "destroyed" */
4538                         C_KILL(s_keep, s_len + 1, char);
4539
4540                         /* Re-update this line's state */
4541                         tb->states[y] = state | LSTAT_EXPRESSION;
4542                 }
4543
4544                 tb->dirty_flags |= DIRTY_ALL;
4545         }
4546
4547         if (tb->mark)
4548         {
4549                 tb->dirty_flags |= DIRTY_ALL;
4550
4551                 by1 = MIN(tb->my, tb->cy);
4552                 by2 = MAX(tb->my, tb->cy);
4553         }
4554
4555         /* Dump up to tb->hgt lines of messages */
4556         for (i = 0; i < tb->hgt; i++)
4557         {
4558                 int j;
4559                 int leftcol = 0;
4560                 concptr msg;
4561                 byte color;
4562                 int y = tb->upper+i;
4563
4564                 /* clean or dirty? */
4565                 if (!(tb->dirty_flags & DIRTY_ALL) && (tb->dirty_line != y))
4566                         continue;
4567
4568                 msg = tb->lines_list[y];
4569                 if (!msg) break;
4570
4571                 /* Apply horizontal scroll */
4572                 for (j = 0; *msg; msg++, j++)
4573                 {
4574                         if (j == tb->left) break;
4575 #ifdef JP
4576                         if (j > tb->left)
4577                         {
4578                                 leftcol = 1;
4579                                 break;
4580                         }
4581                         if (iskanji(*msg))
4582                         {
4583                                 msg++;
4584                                 j++;
4585                         }
4586 #endif
4587                 }
4588
4589                 /* Erase line */
4590                 Term_erase(0, i + 1, tb->wid);
4591
4592                 if (tb->states[y] & LSTAT_AUTOREGISTER)
4593                 {
4594                         /* Warning color -- These lines will be deleted later */
4595                         color = TERM_L_RED;
4596                 }
4597                 else
4598                 {
4599                         /* Bypassed line will be displayed by darker color */
4600                         if (tb->states[y] & LSTAT_BYPASS) color = TERM_SLATE;
4601                         else color = TERM_WHITE;
4602                 }
4603
4604                 /* No mark or Out of mark */
4605                 if (!tb->mark || (y < by1 || by2 < y))
4606                 {
4607                         /* Dump the messages, bottom to top */
4608                         Term_putstr(leftcol, i + 1, tb->wid - 1, color, msg);
4609                 }
4610
4611                 /* Multiple lines selected */
4612                 else if (by1 != by2)
4613                 {
4614                         /* Dump the messages, bottom to top */
4615                         Term_putstr(leftcol, i + 1, tb->wid - 1, TERM_YELLOW, msg);
4616                 }
4617
4618                 /* Single line selected */
4619                 else
4620                 {
4621                         int x0 = leftcol + tb->left;
4622                         int len = strlen(tb->lines_list[tb->cy]);
4623                         int bx1 = MIN(tb->mx, tb->cx);
4624                         int bx2 = MAX(tb->mx, tb->cx);
4625
4626                         /* Correct cursor location */
4627                         if (bx2 > len) bx2 = len;
4628
4629                         Term_gotoxy(leftcol, i + 1);
4630                         if (x0 < bx1) Term_addstr(bx1 - x0, color, msg);
4631                         if (x0 < bx2) Term_addstr(bx2 - bx1, TERM_YELLOW, msg + (bx1 - x0));
4632                         Term_addstr(-1, color, msg + (bx2 - x0));
4633                 }
4634         }
4635
4636         for (; i < tb->hgt; i++)
4637         {
4638                 /* Erase line */
4639                 Term_erase(0, i + 1, tb->wid);
4640         }
4641
4642         /* Display information when updated */
4643         if (tb->old_cy != tb->cy || (tb->dirty_flags & (DIRTY_ALL | DIRTY_NOT_FOUND | DIRTY_NO_SEARCH)) || tb->dirty_line == tb->cy)
4644         {
4645                 autopick_type an_entry, *entry = &an_entry;
4646                 concptr str1 = NULL, str2 = NULL;
4647
4648
4649                 /* Clear information line */
4650                 for (i = 0; i < DESCRIPT_HGT; i++)
4651                 {
4652                         /* Erase line */
4653                         Term_erase(0, tb->hgt + 2 + i, tb->wid);
4654                 }
4655
4656                 /* Display information */
4657                 if (tb->dirty_flags & DIRTY_NOT_FOUND)
4658                 {
4659                         str1 = format(_("パターンが見つかりません: %s", "Pattern not found: %s"), tb->search_str);
4660                 }
4661                 else if (tb->dirty_flags & DIRTY_SKIP_INACTIVE)
4662                 {
4663                         str1 = format(_("無効状態の行をスキップしました。(%sを検索中)", 
4664                                                         "Some inactive lines are skipped. (Searching %s)"), tb->search_str);
4665                 }
4666                 else if (tb->dirty_flags & DIRTY_INACTIVE)
4667                 {
4668                         str1 = format(_("無効状態の行だけが見付かりました。(%sを検索中)",
4669                                                         "Found only an inactive line. (Searching %s)"), tb->search_str);
4670                 }
4671                 else if (tb->dirty_flags & DIRTY_NO_SEARCH)
4672                 {
4673                         str1 = _("検索するパターンがありません(^S で検索)。", "No pattern to search. (Press ^S to search.)");
4674                 }
4675                 else if (tb->lines_list[tb->cy][0] == '#')
4676                 {
4677                         str1 = _("この行はコメントです。", "This line is a comment.");
4678                 }
4679                 else if (tb->lines_list[tb->cy][0] && tb->lines_list[tb->cy][1] == ':')
4680                 {
4681                         switch(tb->lines_list[tb->cy][0])
4682                         {
4683                         case '?':
4684                                 str1 = _("この行は条件分岐式です。", "This line is a Conditional Expression.");
4685                                 break;
4686                         case 'A':
4687                                 str1 = _("この行はマクロの実行内容を定義します。", "This line defines a Macro action.");
4688                                 break;
4689                         case 'P':
4690                                 str1 = _("この行はマクロのトリガー・キーを定義します。", "This line defines a Macro trigger key.");
4691                                 break;
4692                         case 'C':
4693                                 str1 = _("この行はキー配置を定義します。", "This line defines a Keymap.");
4694                                 break;
4695                         }
4696
4697                         switch(tb->lines_list[tb->cy][0])
4698                         {
4699                         case '?':
4700                                 if (tb->states[tb->cy] & LSTAT_BYPASS)
4701                                 {
4702                                         str2 = _("現在の式の値は「偽(=0)」です。", "The expression is 'False'(=0) currently.");
4703                                 }
4704                                 else
4705                                 {
4706                                         str2 = _("現在の式の値は「真(=1)」です。", "The expression is 'True'(=1) currently.");
4707                                 }
4708                                 break;
4709
4710                         default:
4711                                 if (tb->states[tb->cy] & LSTAT_AUTOREGISTER)
4712                                 {
4713                                         str2 = _("この行は後で削除されます。", "This line will be delete later.");
4714                                 }
4715
4716                                 else if (tb->states[tb->cy] & LSTAT_BYPASS)
4717                                 {
4718                                         str2 = _("この行は現在は無効な状態です。", "This line is bypassed currently.");
4719                                 }
4720                                 break;
4721                         }
4722                 }
4723
4724                 /* Get description of an autopicker preference line */
4725                 else if (autopick_new_entry(entry, tb->lines_list[tb->cy], FALSE))
4726                 {
4727                         char buf[MAX_LINELEN];
4728                         char temp[MAX_LINELEN];
4729                         concptr t;
4730
4731                         describe_autopick(buf, entry);
4732
4733                         if (tb->states[tb->cy] & LSTAT_AUTOREGISTER)
4734                         {
4735                                 strcat(buf, _("この行は後で削除されます。", "  This line will be delete later."));
4736                         }
4737
4738                         if (tb->states[tb->cy] & LSTAT_BYPASS)
4739                         {
4740                                 strcat(buf, _("この行は現在は無効な状態です。", "  This line is bypassed currently."));
4741                         }
4742
4743                         roff_to_buf(buf, 81, temp, sizeof(temp));
4744                         t = temp;
4745                         for (i = 0; i < 3; i++)
4746                         {
4747                                 if(t[0] == 0)
4748                                         break; 
4749                                 else
4750                                 {
4751                                         prt(t, tb->hgt +1 + 1 + i, 0);
4752                                         t += strlen(t) + 1;
4753                                 }
4754                         }
4755                         autopick_free_entry(entry);
4756                 }
4757
4758                 /* Draw the first line */
4759                 if (str1) prt(str1, tb->hgt +1 + 1, 0);
4760
4761                 /* Draw the second line */
4762                 if (str2) prt(str2, tb->hgt +1 + 2, 0);
4763         }
4764 }
4765
4766
4767 /*
4768  * Kill segment of a line
4769  */
4770 static void kill_line_segment(text_body_type *tb, int y, int x0, int x1, bool whole)
4771 {
4772         char buf[MAX_LINELEN];
4773         concptr s = tb->lines_list[y];
4774         char *d = buf;
4775         int x;
4776
4777         /* Kill whole line? */
4778         if (whole && x0 == 0 && s[x1] == '\0' && tb->lines_list[y+1])
4779         {
4780                 int i;
4781
4782                 string_free(tb->lines_list[y]);
4783
4784                 /* Shift lines up */
4785                 for (i = y; tb->lines_list[i+1]; i++)
4786                         tb->lines_list[i] = tb->lines_list[i+1];
4787                 tb->lines_list[i] = NULL;
4788
4789                 /* Expressions need re-evaluation */
4790                 tb->dirty_flags |= DIRTY_EXPRESSION;
4791
4792                 return;
4793         }
4794
4795         /* No segment? */
4796         if (x0 == x1) return;
4797
4798         /* Before the segment */
4799         for (x = 0; x < x0; x++)
4800                 *(d++) = s[x];
4801
4802         /* After the segment */
4803         for (x = x1; s[x]; x++)
4804                 *(d++) = s[x];
4805
4806         *d = '\0';
4807
4808         /* Replace */
4809         string_free(tb->lines_list[y]);
4810         tb->lines_list[y] = string_make(buf);
4811
4812         /* Expressions may need re-evaluation */
4813         check_expression_line(tb, y);
4814
4815         /* Text is changed */
4816         tb->changed = TRUE;
4817 }
4818
4819
4820 /*
4821  * Get a trigger key and insert ASCII string for the trigger
4822  */
4823 static bool insert_macro_line(text_body_type *tb)
4824 {
4825         char tmp[1024];
4826         char buf[1024];
4827         int i, n = 0;
4828
4829         /* Flush */
4830         flush();
4831
4832         /* Do not process macros */
4833         inkey_base = TRUE;
4834
4835         /* First key */
4836         i = inkey();
4837
4838         /* Read the pattern */
4839         while (i)
4840         {
4841                 /* Save the key */
4842                 buf[n++] = (char)i;
4843
4844                 /* Do not process macros */
4845                 inkey_base = TRUE;
4846
4847                 /* Do not wait for keys */
4848                 inkey_scan = TRUE;
4849
4850                 /* Attempt to read a key */
4851                 i = inkey();
4852         }
4853
4854         /* Terminate */
4855         buf[n] = '\0';
4856
4857         flush();
4858
4859         /* Convert the trigger */
4860         ascii_to_text(tmp, buf);
4861
4862         /* Null */
4863         if(!tmp[0]) return FALSE;
4864
4865         tb->cx = 0;
4866
4867         /* Insert preference string */
4868         insert_return_code(tb);
4869         string_free(tb->lines_list[tb->cy]);
4870         tb->lines_list[tb->cy] = string_make(format("P:%s", tmp));
4871
4872         /* Acquire action */
4873         i = macro_find_exact(buf);
4874
4875         if (i == -1)
4876         {
4877                 /* Nothing defined */
4878                 tmp[0] = '\0';
4879         }
4880         else
4881         {
4882                 /* Analyze the current action */
4883                 ascii_to_text(tmp, macro__act[i]);
4884         }
4885
4886         /* Insert blank action preference line */
4887         insert_return_code(tb);
4888         string_free(tb->lines_list[tb->cy]);
4889         tb->lines_list[tb->cy] = string_make(format("A:%s", tmp));
4890
4891         return TRUE;
4892 }
4893
4894
4895 /*
4896  * Get a command key and insert ASCII string for the key
4897  */
4898 static bool insert_keymap_line(text_body_type *tb)
4899 {
4900         char tmp[1024];
4901         char buf[2];
4902         BIT_FLAGS mode;
4903         concptr act;
4904
4905         /* Roguelike */
4906         if (rogue_like_commands)
4907         {
4908                 mode = KEYMAP_MODE_ROGUE;
4909         }
4910
4911         /* Original */
4912         else
4913         {
4914                 mode = KEYMAP_MODE_ORIG;
4915         }
4916
4917         flush();
4918
4919         /* Get a key */
4920         buf[0] = inkey();
4921         buf[1] = '\0';
4922
4923         flush();
4924
4925         /* Convert the trigger */
4926         ascii_to_text(tmp, buf);
4927
4928         /* Null */
4929         if(!tmp[0]) return FALSE;
4930
4931         tb->cx = 0;
4932
4933         /* Insert preference string */
4934         insert_return_code(tb);
4935         string_free(tb->lines_list[tb->cy]);
4936         tb->lines_list[tb->cy] = string_make(format("C:%d:%s", mode, tmp));
4937
4938         /* Look up the keymap */
4939         act = keymap_act[mode][(byte)(buf[0])];
4940
4941         if (act)
4942         {
4943                 /* Analyze the current action */
4944                 ascii_to_text(tmp, act);
4945         }
4946         else
4947         {
4948                 /* No keymap defined -- Use trigger key itself as a default */
4949
4950                 /* Nothing to do (use tmp) */
4951         }
4952
4953         /* Insert blank action preference line */
4954         insert_return_code(tb);
4955         string_free(tb->lines_list[tb->cy]);
4956         tb->lines_list[tb->cy] = string_make(format("A:%s", tmp));
4957
4958         return TRUE;
4959 }
4960
4961
4962 /*
4963  * Execute a single editor command
4964  */
4965 static bool do_editor_command(text_body_type *tb, int com_id)
4966 {
4967         switch(com_id)
4968         {
4969         case EC_QUIT:
4970                 if (tb->changed)
4971                 {
4972                         if (!get_check(_("全ての変更を破棄してから終了します。よろしいですか? ",
4973                                                          "Discard all changes and quit. Are you sure? "))) break;
4974                 }
4975                 return QUIT_WITHOUT_SAVE;
4976
4977         case EC_SAVEQUIT:
4978                 return QUIT_AND_SAVE;
4979
4980         case EC_REVERT:
4981                 /* Revert to original */
4982                 if (!get_check(_("全ての変更を破棄して元の状態に戻します。よろしいですか? ",
4983                                                  "Discard all changes and revert to original file. Are you sure? "))) break;
4984
4985                 free_text_lines(tb->lines_list);
4986                 tb->lines_list = read_pickpref_text_lines(&tb->filename_mode);
4987                 tb->dirty_flags |= DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
4988                 tb->cx = tb->cy = 0;
4989                 tb->mark = 0;
4990
4991                 /* Text is not changed */
4992                 tb->changed = FALSE;
4993                 break;
4994
4995         case EC_HELP:
4996                 /* Peruse the main help file */
4997                 (void)show_file(TRUE, _("jeditor.txt", "editor.txt"), NULL, 0, 0);
4998                 /* Redraw all */
4999                 tb->dirty_flags |= DIRTY_SCREEN;
5000
5001                 break;
5002
5003         case EC_RETURN:
5004                 /* Split a line or insert end of line */
5005
5006                 /* Ignore selection */
5007                 if (tb->mark)
5008                 {
5009                         tb->mark = 0;
5010
5011                         /* Now dirty */
5012                         tb->dirty_flags |= DIRTY_ALL;
5013                 }
5014
5015                 insert_return_code(tb);
5016                 tb->cy++;
5017                 tb->cx = 0;
5018
5019                 /* Now dirty */
5020                 tb->dirty_flags |= DIRTY_ALL;
5021                 break;
5022
5023         case EC_LEFT:
5024                 /* Back */
5025                 if (0 < tb->cx)
5026                 {
5027                         int len;
5028 #ifdef JP
5029                         int i;
5030 #endif
5031
5032                         tb->cx--;
5033                         len = strlen(tb->lines_list[tb->cy]);
5034                         if (len < tb->cx) tb->cx = len;
5035
5036 #ifdef JP
5037                         /* Don't let cursor at second byte of kanji */
5038                         for (i = 0; tb->lines_list[tb->cy][i]; i++)
5039                         {
5040                                 if (iskanji(tb->lines_list[tb->cy][i]))
5041                                 {
5042                                         i++;
5043                                         if (i == tb->cx)
5044                                         {
5045                                                 /* Move to the left */
5046                                                 tb->cx--;
5047                                                 break;
5048                                         }
5049                                 }
5050                         }
5051 #endif
5052                 }
5053                 else if (tb->cy > 0)
5054                 {
5055                         tb->cy--;
5056                         tb->cx = strlen(tb->lines_list[tb->cy]);
5057                 }
5058                 break;
5059
5060         case EC_DOWN:
5061                 /* Next line */
5062
5063                 /* Is this the last line? */
5064                 if (!tb->lines_list[tb->cy + 1])
5065                 {
5066                         /* Add one more empty line if possible */
5067                         if (!add_empty_line(tb)) break;
5068                 }
5069
5070                 /* Go down */
5071                 tb->cy++;
5072
5073                 break;
5074
5075         case EC_UP:
5076                 /* Previous line */
5077                 if (tb->cy > 0) tb->cy--;
5078                 break;
5079
5080         case EC_RIGHT:
5081         {
5082                 /* Forward */
5083
5084                 int len;
5085 #ifdef JP
5086                 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
5087 #endif
5088                 tb->cx++;
5089                 len = strlen(tb->lines_list[tb->cy]);
5090                 if (len < tb->cx)
5091                 {
5092                         /* Correct the cursor position */
5093                         tb->cx = len;
5094
5095                         /* Is this the last line? */
5096                         if (!tb->lines_list[tb->cy + 1])
5097                         {
5098                                 /* Add one more empty line if possible */
5099                                 if (!add_empty_line(tb)) break;
5100                         }
5101
5102                         /* Move to the beginning of next line */
5103                         tb->cy++;
5104                         tb->cx = 0;
5105                 }
5106                 break;
5107         }
5108
5109         case EC_BOL:
5110                 /* Beginning of line */
5111                 tb->cx = 0;
5112                 break;
5113
5114         case EC_EOL:
5115                 /* End of line */
5116                 tb->cx = strlen(tb->lines_list[tb->cy]);
5117                 break;
5118
5119         case EC_PGUP:
5120                 while (0 < tb->cy && tb->upper <= tb->cy)
5121                         tb->cy--;
5122                 while (0 < tb->upper && tb->cy + 1 < tb->upper + tb->hgt)
5123                         tb->upper--;
5124                 break;
5125
5126         case EC_PGDOWN:
5127                 /* Page down */
5128                 while (tb->cy < tb->upper + tb->hgt)
5129                 {
5130                         /* Is this the last line? */
5131                         if (!tb->lines_list[tb->cy + 1])
5132                         {
5133                                 /* Add one more empty line if possible */
5134                                 if (!add_empty_line(tb)) break;
5135                         }
5136
5137                         tb->cy++;
5138                 }
5139
5140                 tb->upper = tb->cy;
5141                 break;
5142
5143         case EC_TOP:
5144                 tb->cy = 0;
5145                 break;
5146
5147         case EC_BOTTOM:
5148                 while (TRUE)
5149                 {
5150                         /* Is this the last line? */
5151                         if (!tb->lines_list[tb->cy + 1])
5152                         {
5153                                 /* Add one more empty line if possible */
5154                                 if (!add_empty_line(tb)) break;
5155                         }
5156
5157                         tb->cy++;
5158                 }
5159
5160                 /* Always at the biginning of the last line */
5161                 tb->cx = 0;
5162
5163                 break;
5164
5165         case EC_CUT:
5166         {       
5167                 /* Copy the text first */
5168                 copy_text_to_yank(tb);
5169
5170                 /* Single line case */
5171                 if (tb->my == tb->cy)
5172                 {
5173                         int bx1 = MIN(tb->mx, tb->cx);
5174                         int bx2 = MAX(tb->mx, tb->cx);
5175                         int len = strlen(tb->lines_list[tb->cy]);
5176
5177                         /* Correct fake cursor position */
5178                         if (bx2 > len) bx2 = len;
5179
5180                         kill_line_segment(tb, tb->cy, bx1, bx2, TRUE);
5181
5182                         /* New cursor position */
5183                         tb->cx = bx1;
5184                 }
5185
5186                 /* Multiple lines case */
5187                 else /* if (tb->my != tb->cy) */
5188                 {
5189                         int y;
5190
5191                         int by1 = MIN(tb->my, tb->cy);
5192                         int by2 = MAX(tb->my, tb->cy);
5193
5194                         /* Kill lines in reverse order */
5195                         for (y = by2; y >= by1; y--)
5196                         {
5197                                 int len = strlen(tb->lines_list[y]);
5198                                 
5199                                 kill_line_segment(tb, y, 0, len, TRUE);
5200                         }
5201
5202                         /* New cursor position */
5203                         tb->cy = by1;
5204                         tb->cx = 0;
5205                 }
5206
5207
5208                 /* Disable selection */
5209                 tb->mark = 0;
5210
5211                 /* Now dirty */
5212                 tb->dirty_flags |= DIRTY_ALL;
5213
5214                 /* Text is changed */
5215                 tb->changed = TRUE;
5216
5217                 break;
5218         }
5219
5220         case EC_COPY:
5221                 copy_text_to_yank(tb);
5222
5223                 /*
5224                  * Move cursor position to the end of the selection
5225                  *
5226                  * Pressing ^C ^V correctly duplicates the selection.
5227                  */
5228                 if (tb->my == tb->cy)
5229                 {
5230                         tb->cx = MAX(tb->cx, tb->mx);
5231
5232                         /*
5233                          * When whole line is selected, the end of
5234                          * line code is also copyed.
5235                          */
5236                         if (!tb->lines_list[tb->cy][tb->cx])
5237                         {
5238                                 /* Is this the last line? */
5239                                 if (!tb->lines_list[tb->cy + 1])
5240                                 {
5241                                         /* Add one more empty line if possible */
5242                                         if (!add_empty_line(tb)) break;
5243                                 }
5244
5245                                 /* Go to the beginning of next line */
5246                                 tb->cy++;
5247                                 tb->cx = 0;
5248                         }
5249                 }
5250                 else
5251                 {
5252                         tb->cy = MAX(tb->cy, tb->my);
5253
5254                         /* Is this the last line? */
5255                         if (!tb->lines_list[tb->cy + 1])
5256                         {
5257                                 /* Add one more empty line if possible */
5258                                 if (!add_empty_line(tb)) break;
5259                         }
5260
5261                         /* Go down */
5262                         tb->cy++;
5263                 }
5264
5265                 break;
5266
5267         case EC_PASTE:
5268         {
5269                 /* Paste killed text */
5270
5271                 chain_str_type *chain = tb->yank;
5272                 int len = strlen(tb->lines_list[tb->cy]);
5273
5274                 /* Nothing to do? */
5275                 if (!chain) break;
5276
5277                 /* Correct cursor location */
5278                 if (tb->cx > len) tb->cx = len;
5279
5280                 /* Ignore selection */
5281                 if (tb->mark)
5282                 {
5283                         tb->mark = 0;
5284
5285                         /* Now dirty */
5286                         tb->dirty_flags |= DIRTY_ALL;
5287                 }
5288
5289                 /* Paste text */
5290                 while (chain)
5291                 {
5292                         concptr yank_str = chain->s;
5293
5294                         char buf[MAX_LINELEN];
5295                         int i;
5296                         char rest[MAX_LINELEN], *rest_ptr = rest;
5297
5298                         /* Save preceding string */
5299                         for(i = 0; i < tb->cx; i++)
5300                                 buf[i] = tb->lines_list[tb->cy][i];
5301
5302                         strcpy(rest, &(tb->lines_list[tb->cy][i]));
5303
5304                         /* Paste yank buffer */
5305                         while (*yank_str && i < MAX_LINELEN-1)
5306                         {
5307                                 buf[i++] = *yank_str++;
5308                         }
5309
5310                         /* Terminate */
5311                         buf[i] = '\0';
5312
5313                         chain = chain->next;
5314
5315                         if (chain || tb->yank_eol)
5316                         {
5317                                 /* There is an end of line between chain nodes */
5318
5319                                 insert_return_code(tb);
5320
5321                                 /* Replace this line with new one */
5322                                 string_free(tb->lines_list[tb->cy]);
5323                                 tb->lines_list[tb->cy] = string_make(buf);
5324
5325                                 /* Move to next line */
5326                                 tb->cx = 0;
5327                                 tb->cy++;
5328
5329                                 continue;
5330                         }
5331
5332                         /* Final line doesn't have end of line */
5333
5334                         tb->cx = strlen(buf);
5335
5336                         /* Rest of original line */
5337                         while (*rest_ptr && i < MAX_LINELEN-1)
5338                         {
5339                                 buf[i++] = *rest_ptr++;
5340                         }
5341
5342                         /* Terminate */
5343                         buf[i] = '\0';
5344
5345                         /* Replace this line with new one */
5346                         string_free(tb->lines_list[tb->cy]);
5347                         tb->lines_list[tb->cy] = string_make(buf);
5348
5349                         /* Finish */
5350                         break;
5351                 }
5352
5353                 /* Now dirty */
5354                 tb->dirty_flags |= DIRTY_ALL;
5355
5356                 /* Expressions need re-evaluation */
5357                 tb->dirty_flags |= DIRTY_EXPRESSION;
5358
5359                 /* Text is changed */
5360                 tb->changed = TRUE;
5361
5362                 break;
5363         }
5364
5365         case EC_BLOCK:
5366                 if (tb->mark)
5367                 {
5368                         /* Disable the selection */
5369                         tb->mark = 0;
5370
5371                         /* Redraw text */
5372                         tb->dirty_flags |= DIRTY_ALL;
5373                 }
5374                 else
5375                 {
5376                         tb->mark = MARK_MARK;
5377
5378                         /* Repeating this command swaps cursor position */
5379                         if (com_id == tb->old_com_id)
5380                         {
5381                                 int tmp;
5382
5383                                 tmp = tb->cy;
5384                                 tb->cy = tb->my;
5385                                 tb->my = tmp;
5386                                 tmp = tb->cx;
5387                                 tb->cx = tb->mx;
5388                                 tb->mx = tmp;
5389
5390                                 /* Redraw text */
5391                                 tb->dirty_flags |= DIRTY_ALL;
5392                         }
5393                         else
5394                         {
5395                                 int len = strlen(tb->lines_list[tb->cy]);
5396
5397                                 /* Mark the point 1 */
5398                                 tb->my = tb->cy;
5399                                 tb->mx = tb->cx;
5400
5401                                 /* Correct cursor location */
5402                                 if (tb->cx > len) tb->mx = len;
5403                         }
5404                 }
5405                 break;
5406
5407         case EC_KILL_LINE:
5408         {
5409                 /* Kill rest of line */
5410
5411                 int len = strlen(tb->lines_list[tb->cy]);
5412
5413                 /* Correct cursor location */
5414                 if (tb->cx > len) tb->cx = len;
5415
5416                 /* Ignore selection */
5417                 if (tb->mark)
5418                 {
5419                         tb->mark = 0;
5420
5421                         /* Now dirty */
5422                         tb->dirty_flags |= DIRTY_ALL;
5423                 }
5424
5425                 /* Append only if this command is repeated. */
5426                 if (tb->old_com_id != com_id)
5427                 {
5428                         kill_yank_chain(tb);
5429                         tb->yank = NULL;
5430                 }
5431
5432                 /* Really deleted some text */
5433                 if (tb->cx < len)
5434                 {
5435                         /* Add deleted string to yank buffer */
5436                         add_str_to_yank(tb, &(tb->lines_list[tb->cy][tb->cx]));
5437
5438                         kill_line_segment(tb, tb->cy, tb->cx, len, FALSE);
5439
5440                         /* Now dirty */
5441                         tb->dirty_line = tb->cy;
5442
5443                         /* Leave end of line character */
5444                         break;
5445                 }
5446
5447                 /* Cut the end of line character only */
5448                 if (tb->yank_eol) add_str_to_yank(tb, "");
5449
5450                 /* Cut end of line */
5451                 tb->yank_eol = TRUE;
5452
5453                 do_editor_command(tb, EC_DELETE_CHAR);
5454                 break;
5455         }
5456
5457         case EC_DELETE_CHAR:
5458         {
5459                 /* DELETE == go forward + BACK SPACE */
5460
5461                 int len;
5462
5463                 /* Ignore selection */
5464                 if (tb->mark)
5465                 {
5466                         tb->mark = 0;
5467
5468                         /* Now dirty */
5469                         tb->dirty_flags |= DIRTY_ALL;
5470                 }
5471
5472 #ifdef JP
5473                 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
5474 #endif
5475                 tb->cx++;
5476
5477                 /* Pass through the end of line to next line */
5478                 len = strlen(tb->lines_list[tb->cy]);
5479                 if (len < tb->cx)
5480                 {
5481                         if (tb->lines_list[tb->cy + 1])
5482                         {
5483                                 tb->cy++;
5484                                 tb->cx = 0;
5485                         }
5486                         else
5487                         {
5488                                 tb->cx = len;
5489                                 break;
5490                         }
5491                 }
5492
5493                 do_editor_command(tb, EC_BACKSPACE);
5494                 break;
5495         }
5496
5497         case EC_BACKSPACE:
5498         {
5499                 /* BACK SPACE */
5500
5501                 int len, i, j, k;
5502                 char buf[MAX_LINELEN];
5503
5504                 /* Ignore selection */
5505                 if (tb->mark)
5506                 {
5507                         tb->mark = 0;
5508
5509                         /* Now dirty */
5510                         tb->dirty_flags |= DIRTY_ALL;
5511                 }
5512
5513                 /* Move to correct collumn */
5514                 len = strlen(tb->lines_list[tb->cy]);
5515                 if (len < tb->cx) tb->cx = len;
5516
5517                 if (tb->cx == 0)
5518                 {
5519                         /* delete a return code and union two lines */
5520                         if (tb->cy == 0) break;
5521                         tb->cx = strlen(tb->lines_list[tb->cy-1]);
5522                         strcpy(buf, tb->lines_list[tb->cy-1]);
5523                         strcat(buf, tb->lines_list[tb->cy]);
5524                         string_free(tb->lines_list[tb->cy-1]);
5525                         string_free(tb->lines_list[tb->cy]);
5526                         tb->lines_list[tb->cy-1] = string_make(buf);
5527
5528                         for (i = tb->cy; tb->lines_list[i+1]; i++)
5529                                 tb->lines_list[i] = tb->lines_list[i+1];
5530
5531                         tb->lines_list[i] = NULL;
5532                         tb->cy--;
5533
5534                         /* Now dirty */
5535                         tb->dirty_flags |= DIRTY_ALL;
5536
5537                         /* Expressions need re-evaluation */
5538                         tb->dirty_flags |= DIRTY_EXPRESSION;
5539
5540                         /* Text is changed */
5541                         tb->changed = TRUE;
5542
5543                         break;
5544                 }
5545
5546                 for (i = j = k = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
5547                 {
5548                         k = j;
5549 #ifdef JP
5550                         if (iskanji(tb->lines_list[tb->cy][i]))
5551                                 buf[j++] = tb->lines_list[tb->cy][i++];
5552 #endif
5553                         buf[j++] = tb->lines_list[tb->cy][i];
5554                 }
5555                 while (j > k)
5556                 {
5557                         tb->cx--;
5558                         j--;
5559                 }
5560                 for (; tb->lines_list[tb->cy][i]; i++)
5561                         buf[j++] = tb->lines_list[tb->cy][i];
5562                 buf[j] = '\0';
5563                 string_free(tb->lines_list[tb->cy]);
5564                 tb->lines_list[tb->cy] = string_make(buf);
5565
5566                 /* Now dirty */
5567                 tb->dirty_line = tb->cy;
5568
5569                 /* Expressions may need re-evaluation */
5570                 check_expression_line(tb, tb->cy);
5571
5572                 /* Text is changed */
5573                 tb->changed = TRUE;
5574
5575                 break;
5576         }
5577
5578         case EC_SEARCH_STR:
5579         {
5580                 byte search_dir;
5581
5582                 /* Become dirty because of item/equip menu */
5583                 tb->dirty_flags |= DIRTY_SCREEN;
5584
5585                 search_dir = get_string_for_search(&tb->search_o_ptr, &tb->search_str);
5586
5587                 if (!search_dir) break;
5588
5589                 if (search_dir == 1) do_editor_command(tb, EC_SEARCH_FORW);
5590                 else do_editor_command(tb, EC_SEARCH_BACK);
5591                 break;
5592         }
5593
5594         case EC_SEARCH_FORW:
5595                 if (tb->search_o_ptr)
5596                 {
5597                         search_for_object(tb, tb->search_o_ptr, TRUE);
5598                 }
5599                 else if (tb->search_str && tb->search_str[0])
5600                 {
5601                         search_for_string(tb, tb->search_str, TRUE);
5602                 }
5603                 else
5604                 {
5605                         tb->dirty_flags |= DIRTY_NO_SEARCH;
5606                 }
5607                 break;
5608
5609         case EC_SEARCH_BACK:
5610                 if (tb->search_o_ptr)
5611                 {
5612                         search_for_object(tb, tb->search_o_ptr, FALSE);
5613                 }
5614                 else if (tb->search_str && tb->search_str[0])
5615                 {
5616                         search_for_string(tb, tb->search_str, FALSE);
5617                 }
5618                 else
5619                 {
5620                         tb->dirty_flags |= DIRTY_NO_SEARCH;
5621                 }
5622                 break;
5623
5624         case EC_SEARCH_OBJ:
5625                 /* Become dirty because of item/equip menu */
5626                 tb->dirty_flags |= DIRTY_SCREEN;
5627
5628                 if (!get_object_for_search(&tb->search_o_ptr, &tb->search_str)) break;
5629
5630                 do_editor_command(tb, EC_SEARCH_FORW);
5631                 break;
5632
5633         case EC_SEARCH_DESTROYED:
5634                 if (!get_destroyed_object_for_search(&tb->search_o_ptr, &tb->search_str))
5635                 {
5636                         /* There is no object to search */
5637                         tb->dirty_flags |= DIRTY_NO_SEARCH;
5638
5639                         break;
5640                 }
5641
5642                 do_editor_command(tb, EC_SEARCH_FORW);
5643                 break;
5644
5645         case EC_INSERT_OBJECT:
5646         {
5647                 /* Insert choosen item name */
5648
5649                 autopick_type an_entry, *entry = &an_entry;
5650
5651                 if (!entry_from_choosed_object(entry))
5652                 {
5653                         /* Now dirty because of item/equip menu */
5654                         tb->dirty_flags |= DIRTY_SCREEN;
5655                         break;
5656                 }
5657
5658                 tb->cx = 0;
5659                 insert_return_code(tb);
5660                 string_free(tb->lines_list[tb->cy]);
5661                 tb->lines_list[tb->cy] = autopick_line_from_entry_kill(entry);
5662
5663                 /* Now dirty because of item/equip menu */
5664                 tb->dirty_flags |= DIRTY_SCREEN;
5665
5666                 break;
5667         }
5668
5669         case EC_INSERT_DESTROYED:
5670                 /* Insert a name of last destroyed item */
5671                 if (tb->last_destroyed)
5672                 {
5673                         tb->cx = 0;
5674                         insert_return_code(tb);
5675                         string_free(tb->lines_list[tb->cy]);
5676                         tb->lines_list[tb->cy] = string_make(tb->last_destroyed);
5677
5678                         /* Now dirty */
5679                         tb->dirty_flags |= DIRTY_ALL;
5680
5681                         /* Text is changed */
5682                         tb->changed = TRUE;
5683                 }
5684                 break;
5685
5686         case EC_INSERT_BLOCK:
5687         {
5688                 /* Insert a conditinal expression line */
5689                 char expression[80];
5690
5691                 /* Conditional Expression for Class and Race */
5692                 sprintf(expression, "?:[AND [EQU $RACE %s] [EQU $CLASS %s] [GEQ $LEVEL %02d]]", 
5693 #ifdef JP
5694                         rp_ptr->E_title, cp_ptr->E_title,
5695 #else
5696                         rp_ptr->title, cp_ptr->title,
5697 #endif
5698                         p_ptr->lev
5699                         );
5700
5701                 tb->cx = 0;
5702                 insert_return_code(tb);
5703                 string_free(tb->lines_list[tb->cy]);
5704                 tb->lines_list[tb->cy] = string_make(expression);
5705                 tb->cy++;
5706                 insert_return_code(tb);
5707                 string_free(tb->lines_list[tb->cy]);
5708                 tb->lines_list[tb->cy] = string_make("?:1");
5709
5710                 /* Now dirty */
5711                 tb->dirty_flags |= DIRTY_ALL;
5712
5713                 /* Text is changed */
5714                 tb->changed = TRUE;
5715
5716                 break;
5717         }
5718
5719         case EC_INSERT_MACRO:
5720                 /* Draw_everythig (delete menu) */
5721                 draw_text_editor(tb);
5722
5723                 /* Erase line */
5724                 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
5725
5726                 /* Prompt */
5727                 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, _("P:<トリガーキー>: ", "P:<Trigger key>: "));
5728                 if (insert_macro_line(tb))
5729                 {
5730                         /* Prepare to input action */
5731                         tb->cx = 2;
5732
5733                         /* Now dirty */
5734                         tb->dirty_flags |= DIRTY_ALL;
5735
5736                         /* Text is changed */
5737                         tb->changed = TRUE;
5738                 }
5739
5740                 break;
5741
5742         case EC_INSERT_KEYMAP:
5743                 /* Draw_everythig (delete menu) */
5744                 draw_text_editor(tb);
5745
5746                 /* Erase line */
5747                 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
5748
5749                 /* Prompt */
5750                 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, 
5751                                         format(_("C:%d:<コマンドキー>: ", "C:%d:<Keypress>: "), (rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG)));
5752
5753                 if (insert_keymap_line(tb))
5754                 {
5755                         /* Prepare to input action */
5756                         tb->cx = 2;
5757
5758                         /* Now dirty */
5759                         tb->dirty_flags |= DIRTY_ALL;
5760
5761                         /* Text is changed */
5762                         tb->changed = TRUE;
5763                 }                               
5764                 break;
5765
5766         case EC_CL_AUTOPICK: toggle_command_letter(tb, DO_AUTOPICK); break;
5767         case EC_CL_DESTROY: toggle_command_letter(tb, DO_AUTODESTROY); break;
5768         case EC_CL_LEAVE: toggle_command_letter(tb, DONT_AUTOPICK); break;
5769         case EC_CL_QUERY: toggle_command_letter(tb, DO_QUERY_AUTOPICK); break;
5770         case EC_CL_NO_DISP: toggle_command_letter(tb, DO_DISPLAY); break;
5771
5772         case EC_IK_UNAWARE: toggle_keyword(tb, FLG_UNAWARE); break;
5773         case EC_IK_UNIDENTIFIED: toggle_keyword(tb, FLG_UNIDENTIFIED); break;
5774         case EC_IK_IDENTIFIED: toggle_keyword(tb, FLG_IDENTIFIED); break;
5775         case EC_IK_STAR_IDENTIFIED: toggle_keyword(tb, FLG_STAR_IDENTIFIED); break;
5776         case EC_KK_WEAPONS: toggle_keyword(tb, FLG_WEAPONS); break;
5777         case EC_KK_FAVORITE_WEAPONS: toggle_keyword(tb, FLG_FAVORITE_WEAPONS); break;
5778         case EC_KK_ARMORS: toggle_keyword(tb, FLG_ARMORS); break;
5779         case EC_KK_MISSILES: toggle_keyword(tb, FLG_MISSILES); break;
5780         case EC_KK_DEVICES: toggle_keyword(tb, FLG_DEVICES); break;
5781         case EC_KK_LIGHTS: toggle_keyword(tb, FLG_LIGHTS); break;
5782         case EC_KK_JUNKS: toggle_keyword(tb, FLG_JUNKS); break;
5783         case EC_KK_CORPSES: toggle_keyword(tb, FLG_CORPSES); break;
5784         case EC_KK_SPELLBOOKS: toggle_keyword(tb, FLG_SPELLBOOKS); break;
5785         case EC_KK_SHIELDS: toggle_keyword(tb, FLG_SHIELDS); break;
5786         case EC_KK_BOWS: toggle_keyword(tb, FLG_BOWS); break;
5787         case EC_KK_RINGS: toggle_keyword(tb, FLG_RINGS); break;
5788         case EC_KK_AMULETS: toggle_keyword(tb, FLG_AMULETS); break;
5789         case EC_KK_SUITS: toggle_keyword(tb, FLG_SUITS); break;
5790         case EC_KK_CLOAKS: toggle_keyword(tb, FLG_CLOAKS); break;
5791         case EC_KK_HELMS: toggle_keyword(tb, FLG_HELMS); break;
5792         case EC_KK_GLOVES: toggle_keyword(tb, FLG_GLOVES); break;
5793         case EC_KK_BOOTS: toggle_keyword(tb, FLG_BOOTS); break;
5794         case EC_OK_COLLECTING: toggle_keyword(tb, FLG_COLLECTING); break;
5795         case EC_OK_BOOSTED: toggle_keyword(tb, FLG_BOOSTED); break;
5796         case EC_OK_MORE_DICE: toggle_keyword(tb, FLG_MORE_DICE); break;
5797         case EC_OK_MORE_BONUS: toggle_keyword(tb, FLG_MORE_BONUS); break;
5798         case EC_OK_WORTHLESS: toggle_keyword(tb, FLG_WORTHLESS); break;
5799         case EC_OK_ARTIFACT: toggle_keyword(tb, FLG_ARTIFACT); break;
5800         case EC_OK_EGO: toggle_keyword(tb, FLG_EGO); break;
5801         case EC_OK_GOOD: toggle_keyword(tb, FLG_GOOD); break;
5802         case EC_OK_NAMELESS: toggle_keyword(tb, FLG_NAMELESS); break;
5803         case EC_OK_AVERAGE: toggle_keyword(tb, FLG_AVERAGE); break;
5804         case EC_OK_RARE: toggle_keyword(tb, FLG_RARE); break;
5805         case EC_OK_COMMON: toggle_keyword(tb, FLG_COMMON); break;
5806         case EC_OK_WANTED: toggle_keyword(tb, FLG_WANTED); break;
5807         case EC_OK_UNIQUE: toggle_keyword(tb, FLG_UNIQUE); break;
5808         case EC_OK_HUMAN: toggle_keyword(tb, FLG_HUMAN); break;
5809         case EC_OK_UNREADABLE:
5810                 toggle_keyword(tb, FLG_UNREADABLE);
5811                 add_keyword(tb, FLG_SPELLBOOKS);
5812                 break;
5813         case EC_OK_REALM1:
5814                 toggle_keyword(tb, FLG_REALM1);
5815                 add_keyword(tb, FLG_SPELLBOOKS);
5816                 break;
5817         case EC_OK_REALM2:
5818                 toggle_keyword(tb, FLG_REALM2);
5819                 add_keyword(tb, FLG_SPELLBOOKS);
5820                 break;
5821         case EC_OK_FIRST:
5822                 toggle_keyword(tb, FLG_FIRST);
5823                 add_keyword(tb, FLG_SPELLBOOKS);
5824                 break;
5825         case EC_OK_SECOND:
5826                 toggle_keyword(tb, FLG_SECOND);
5827                 add_keyword(tb, FLG_SPELLBOOKS);
5828                 break;
5829         case EC_OK_THIRD:
5830                 toggle_keyword(tb, FLG_THIRD);
5831                 add_keyword(tb, FLG_SPELLBOOKS);
5832                 break;
5833         case EC_OK_FOURTH:
5834                 toggle_keyword(tb, FLG_FOURTH);
5835                 add_keyword(tb, FLG_SPELLBOOKS);
5836                 break;
5837         }
5838
5839         /* Save old command */
5840         tb->old_com_id = com_id;
5841
5842         return FALSE;
5843 }
5844
5845
5846 /*
5847  * Insert single letter at cursor position.
5848  */
5849 static void insert_single_letter(text_body_type *tb, int key)
5850 {
5851         int i, j, len;
5852         char buf[MAX_LINELEN];
5853
5854         /* Save preceding string */
5855         for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
5856                 buf[j++] = tb->lines_list[tb->cy][i];
5857
5858         /* Add a character */
5859 #ifdef JP
5860         if (iskanji(key))
5861         {
5862                 int next;
5863
5864                 inkey_base = TRUE;
5865                 next = inkey();
5866                 if (j+2 < MAX_LINELEN)
5867                 {
5868                         buf[j++] = (char)key;
5869                         buf[j++] = (char)next;
5870                         tb->cx += 2;
5871                 }
5872                 else
5873                         bell();
5874         }
5875         else
5876 #endif
5877         {
5878                 if (j+1 < MAX_LINELEN)
5879                         buf[j++] = (char)key;
5880                 tb->cx++;
5881         }
5882
5883         /* Add following */
5884         for (; tb->lines_list[tb->cy][i] && j + 1 < MAX_LINELEN; i++)
5885                 buf[j++] = tb->lines_list[tb->cy][i];
5886         buf[j] = '\0';
5887
5888         /* Replace current line with new line */
5889         string_free(tb->lines_list[tb->cy]);
5890         tb->lines_list[tb->cy] = string_make(buf);
5891
5892         /* Move to correct collumn */
5893         len = strlen(tb->lines_list[tb->cy]);
5894         if (len < tb->cx) tb->cx = len;
5895
5896         /* Now dirty */
5897         tb->dirty_line = tb->cy;
5898
5899         /* Expressions may need re-evaluation */
5900         check_expression_line(tb, tb->cy);
5901
5902         /* Text is changed */
5903         tb->changed = TRUE;
5904 }
5905
5906
5907 /*
5908  * Check special key code and get a movement command id
5909  */
5910 static int analyze_move_key(text_body_type *tb, int skey)
5911 {
5912         int com_id;
5913
5914         /* Not a special key */
5915         if (!(skey & SKEY_MASK)) return 0;
5916
5917         /* Convert from a special key code to an editor command */
5918         switch(skey & ~SKEY_MOD_MASK)
5919         {
5920         case SKEY_DOWN:   com_id = EC_DOWN;   break;
5921         case SKEY_LEFT:   com_id = EC_LEFT;   break;
5922         case SKEY_RIGHT:  com_id = EC_RIGHT;  break;
5923         case SKEY_UP:     com_id = EC_UP;     break;
5924         case SKEY_PGUP:   com_id = EC_PGUP;   break;
5925         case SKEY_PGDOWN: com_id = EC_PGDOWN; break;
5926         case SKEY_TOP:    com_id = EC_TOP;    break;
5927         case SKEY_BOTTOM: com_id = EC_BOTTOM; break;
5928
5929         default:
5930                 /* Not a special movement key */
5931                 return 0;
5932         }
5933
5934         /* Without shift modifier */
5935         if (!(skey & SKEY_MOD_SHIFT))
5936         {
5937                 /*
5938                  * Un-shifted cursor keys cancells
5939                  * selection created by shift+cursor.
5940                  */
5941                 if (tb->mark & MARK_BY_SHIFT)
5942                 {
5943                         tb->mark = 0;
5944
5945                         /* Now dirty */
5946                         tb->dirty_flags |= DIRTY_ALL;
5947                 }
5948         }
5949
5950         /* With shift modifier */
5951         else
5952         {
5953                 /* Start selection by shift + cursor keys */
5954                 if (!tb->mark)
5955                 {
5956                         int len = strlen(tb->lines_list[tb->cy]);
5957
5958                         tb->mark = MARK_MARK | MARK_BY_SHIFT;
5959                         tb->my = tb->cy;
5960                         tb->mx = tb->cx;
5961
5962                         /* Correct cursor location */
5963                         if (tb->cx > len) tb->mx = len;
5964                                                 
5965                         /* Need to redraw text */
5966                         if (com_id == EC_UP || com_id == EC_DOWN)
5967                         {
5968                                 /* Redraw all text */
5969                                 tb->dirty_flags |= DIRTY_ALL;
5970                         }
5971                         else
5972                         {
5973                                 tb->dirty_line = tb->cy;
5974                         }
5975                 }
5976         }
5977
5978         return com_id;
5979 }
5980
5981 /*
5982  * In-game editor of Object Auto-picker/Destoryer
5983  */
5984 void do_cmd_edit_autopick(void)
5985 {
5986         static int cx_save = 0;
5987         static int cy_save = 0;
5988
5989         text_body_type text_body, *tb = &text_body;
5990
5991         autopick_type an_entry, *entry = &an_entry;
5992         char buf[MAX_LINELEN];
5993
5994         int i;
5995         int key = -1;
5996
5997         static s32b old_autosave_turn = 0L;
5998         byte quit = 0;
5999
6000         tb->changed = FALSE;
6001         tb->cx = cx_save;
6002         tb->cy = cy_save;
6003         tb->upper = tb->left = 0;
6004         tb->mark = 0;
6005         tb->mx = tb->my = 0;
6006         tb->old_cy = tb->old_upper = tb->old_left = -1;
6007         tb->old_wid = tb->old_hgt = -1;
6008         tb->old_com_id = 0;
6009
6010         tb->yank = NULL;
6011         tb->search_o_ptr = NULL;
6012         tb->search_str = NULL;
6013         tb->last_destroyed = NULL;
6014         tb->dirty_flags = DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
6015         tb->dirty_line = -1;
6016         tb->filename_mode = PT_DEFAULT;
6017
6018         if (current_world_ptr->game_turn < old_autosave_turn)
6019         {
6020                 while (old_autosave_turn > current_world_ptr->game_turn) old_autosave_turn -= TURNS_PER_TICK * TOWN_DAWN;
6021         }
6022
6023         /* Autosave */
6024         if (current_world_ptr->game_turn > old_autosave_turn + 100L)
6025         {
6026                 do_cmd_save_game(TRUE);
6027                 old_autosave_turn = current_world_ptr->game_turn;
6028         }
6029
6030         /* HACK -- Reset start_time to stop counting current_world_ptr->play_time while edit */
6031         update_playtime();
6032
6033         /* Free old entries */
6034         init_autopick();
6035
6036         /* Command Description of the 'Last Destroyed Item' */
6037         if (autopick_last_destroyed_object.k_idx)
6038         {
6039                 autopick_entry_from_object(entry, &autopick_last_destroyed_object);
6040                 tb->last_destroyed = autopick_line_from_entry_kill(entry);
6041         }
6042
6043         /* Read or initialize whole text */
6044         tb->lines_list = read_pickpref_text_lines(&tb->filename_mode);
6045
6046         /* Reset cursor position if needed */
6047         for (i = 0; i < tb->cy; i++)
6048         {
6049                 if (!tb->lines_list[i])
6050                 {
6051                         tb->cy = tb->cx = 0;
6052                         break;
6053                 }
6054         }
6055         screen_save();
6056
6057         /* Process requests until done */
6058         while (!quit)
6059         {
6060                 int com_id = 0;
6061
6062                 /* Draw_everythig */
6063                 draw_text_editor(tb);
6064
6065                 /* Display header line */
6066                 prt(_("(^Q:終了 ^W:セーブして終了, ESC:メニュー, その他:入力)", 
6067                       "(^Q:Quit, ^W:Save&Quit, ESC:Menu, Other:Input text)"), 0, 0);
6068                 if (!tb->mark)
6069                 {
6070                         /* Display current position */
6071                         prt (format("(%d,%d)", tb->cx, tb->cy), 0, 60);
6072                 }
6073                 else
6074                 {
6075                         /* Display current position and mark position */
6076                         prt (format("(%d,%d)-(%d,%d)", tb->mx, tb->my, tb->cx, tb->cy), 0, 60);
6077                 }
6078
6079                 /* Place cursor */
6080                 Term_gotoxy(tb->cx - tb->left, tb->cy - tb->upper + 1);
6081
6082                 /* Now clean */
6083                 tb->dirty_flags = 0;
6084                 tb->dirty_line = -1;
6085
6086                 /* Save old key and location */
6087                 tb->old_cy = tb->cy;
6088                 tb->old_upper = tb->upper;
6089                 tb->old_left = tb->left;
6090                 tb->old_wid = tb->wid;
6091                 tb->old_hgt = tb->hgt;
6092
6093                 key = inkey_special(TRUE);
6094
6095                 /* Special keys */
6096                 if (key & SKEY_MASK)
6097                 {
6098                         /* Get a movement command */
6099                         com_id = analyze_move_key(tb, key);
6100                 }
6101
6102                 /* Open the menu */
6103                 else if (key == ESCAPE)
6104                 {
6105                         com_id = do_command_menu(0, 0);
6106
6107                         /* Redraw all text later */
6108                         tb->dirty_flags |= DIRTY_SCREEN;
6109                 }
6110
6111                 /* Insert a character */
6112                 else if (!iscntrl((unsigned char)key))
6113                 {
6114                         /* Ignore selection */
6115                         if (tb->mark)
6116                         {
6117                                 tb->mark = 0;
6118
6119                                 /* Now dirty */
6120                                 tb->dirty_flags |= DIRTY_ALL;
6121                         }
6122
6123                         insert_single_letter(tb, key);
6124
6125                         /* Next loop */
6126                         continue;
6127                 }
6128
6129                 /* Other commands */
6130                 else
6131                 {
6132                         com_id = get_com_id((char)key);
6133                 }
6134
6135                 if (com_id) quit = do_editor_command(tb, com_id);
6136         } /* while (TRUE) */
6137         screen_load();
6138
6139         /* Get the filename of preference */
6140         strcpy(buf, pickpref_filename(tb->filename_mode));
6141
6142         if (quit == QUIT_AND_SAVE)
6143                 write_text_lines(buf, tb->lines_list);
6144
6145         free_text_lines(tb->lines_list);
6146
6147         string_free(tb->search_str);
6148         string_free(tb->last_destroyed);
6149
6150         /* Destroy string chain */
6151         kill_yank_chain(tb);
6152
6153         /* Reload autopick pref */
6154         process_autopick_file(buf);
6155
6156         /* HACK -- reset start_time so that current_world_ptr->play_time is not increase while edit */
6157         start_time = (u32b)time(NULL);
6158
6159         /* Save cursor location */
6160         cx_save = tb->cx;
6161         cy_save = tb->cy;
6162 }