3 /* Purpose: Object Auto-picker/Destroyer */
6 * Copyright (c) 2002 Mogami
8 * This software may be copied and distributed for educational, research, and
9 * not for profit purposes provided that this copyright and statement are
10 * included in all such copies.
16 #define MAX_LINELEN 1024
22 #define FLG_COLLECTING 1
24 #define FLG_UNIDENTIFIED 3
25 #define FLG_IDENTIFIED 4
26 #define FLG_STAR_IDENTIFIED 5
28 #define FLG_MORE_DICE 7
29 #define FLG_MORE_BONUS 10
30 #define FLG_WORTHLESS 11
31 #define FLG_ARTIFACT 12
33 #define FLG_NAMELESS 14
39 #define FLG_UNREADABLE 20
48 #define FLG_WEAPONS 31
49 #define FLG_FAVORITE_WEAPONS 32
51 #define FLG_MISSILES 34
52 #define FLG_DEVICES 35
55 #define FLG_CORPSES 38
56 #define FLG_SPELLBOOKS 39
58 #define FLG_SHIELDS 41
61 #define FLG_AMULETS 44
68 #define FLG_NOUN_BEGIN FLG_ITEMS
69 #define FLG_NOUN_END FLG_BOOTS
73 #define KEY_ALL "¤¹¤Ù¤Æ¤Î"
77 * MEGA HACK -- MPW¤Î¥Ð¥°½ü¤±¡£
78 * pre-processÃæ¤Ë¡Ö¼ý¡×¤Î»ú¤Î2¥Ð¥¤¥ÈÌܤ¬¾¡¼ê¤Ë¾Ã¤¨¤Æ¤·¤Þ¤¦¡£
80 #define KEY_COLLECTING "\x8e\xfb½¸Ãæ¤Î"
82 #define KEY_COLLECTING "¼ý½¸Ãæ¤Î"
85 #define KEY_UNAWARE "̤ȽÌÀ¤Î"
86 #define KEY_UNIDENTIFIED "̤´ÕÄê¤Î"
87 #define KEY_IDENTIFIED "´ÕÄêºÑ¤ß¤Î"
88 #define KEY_STAR_IDENTIFIED "*´ÕÄê*ºÑ¤ß¤Î"
89 #define KEY_BOOSTED "¥À¥¤¥¹Ìܤΰ㤦"
90 #define KEY_MORE_THAN "¥À¥¤¥¹ÌÜ"
91 #define KEY_DICE "°Ê¾å¤Î"
92 #define KEY_MORE_BONUS "½¤ÀµÃÍ"
93 #define KEY_MORE_BONUS2 "°Ê¾å¤Î"
94 #define KEY_WORTHLESS "̵²ÁÃͤÎ"
95 #define KEY_ARTIFACT "¥¢¡¼¥Æ¥£¥Õ¥¡¥¯¥È"
96 #define KEY_EGO "¥¨¥´"
97 #define KEY_NAMELESS "̵ÌäÎ"
98 #define KEY_RARE "¥ì¥¢¤Ê"
99 #define KEY_COMMON "¤¢¤ê¤Õ¤ì¤¿"
100 #define KEY_WANTED "¾Þ¶â¼ó¤Î"
101 #define KEY_UNIQUE "¥æ¥Ë¡¼¥¯¡¦¥â¥ó¥¹¥¿¡¼¤Î"
102 #define KEY_HUMAN "¿Í´Ö¤Î"
103 #define KEY_UNREADABLE "Æɤá¤Ê¤¤"
104 #define KEY_REALM1 "Âè°ìÎΰè¤Î"
105 #define KEY_REALM2 "ÂèÆóÎΰè¤Î"
106 #define KEY_FIRST "1ºýÌܤÎ"
107 #define KEY_SECOND "2ºýÌܤÎ"
108 #define KEY_THIRD "3ºýÌܤÎ"
109 #define KEY_FOURTH "4ºýÌܤÎ"
110 #define KEY_ITEMS "¥¢¥¤¥Æ¥à"
111 #define KEY_WEAPONS "Éð´ï"
112 #define KEY_FAVORITE_WEAPONS "ÆÀ°ÕÉð´ï"
113 #define KEY_ARMORS "Ëɶñ"
114 #define KEY_MISSILES "Ìð"
115 #define KEY_DEVICES "ËâË¡¥¢¥¤¥Æ¥à"
116 #define KEY_LIGHTS "¸÷¸»"
117 #define KEY_JUNKS "¤¬¤é¤¯¤¿"
118 #define KEY_CORPSES "»àÂΤä¹ü"
119 #define KEY_SPELLBOOKS "ËâË¡½ñ"
120 #define KEY_HAFTED "Æß´ï"
121 #define KEY_SHIELDS "½â"
122 #define KEY_BOWS "µÝ"
123 #define KEY_RINGS "»ØÎØ"
124 #define KEY_AMULETS "¥¢¥ß¥å¥ì¥Ã¥È"
125 #define KEY_SUITS "³»"
126 #define KEY_CLOAKS "¥¯¥í¡¼¥¯"
127 #define KEY_HELMS "³õ"
128 #define KEY_GLOVES "äƼê"
129 #define KEY_BOOTS "·¤"
133 #define KEY_ALL "all"
134 #define KEY_COLLECTING "collecting"
135 #define KEY_UNAWARE "unaware"
136 #define KEY_UNIDENTIFIED "unidentified"
137 #define KEY_IDENTIFIED "identified"
138 #define KEY_STAR_IDENTIFIED "*identified*"
139 #define KEY_BOOSTED "dice boosted"
140 #define KEY_MORE_THAN "more than"
141 #define KEY_DICE " dice"
142 #define KEY_MORE_BONUS "more bonus than"
143 #define KEY_MORE_BONUS2 ""
144 #define KEY_WORTHLESS "worthless"
145 #define KEY_ARTIFACT "artifact"
146 #define KEY_EGO "ego"
147 #define KEY_NAMELESS "nameless"
148 #define KEY_RARE "rare"
149 #define KEY_COMMON "common"
150 #define KEY_WANTED "wanted"
151 #define KEY_UNIQUE "unique monster's"
152 #define KEY_HUMAN "human"
153 #define KEY_UNREADABLE "unreadable"
154 #define KEY_REALM1 "first realm's"
155 #define KEY_REALM2 "second realm's"
156 #define KEY_FIRST "first"
157 #define KEY_SECOND "second"
158 #define KEY_THIRD "third"
159 #define KEY_FOURTH "fourth"
160 #define KEY_ITEMS "items"
161 #define KEY_WEAPONS "weapons"
162 #define KEY_FAVORITE_WEAPONS "favorite weapons"
163 #define KEY_ARMORS "armors"
164 #define KEY_MISSILES "missiles"
165 #define KEY_DEVICES "magical devices"
166 #define KEY_LIGHTS "lights"
167 #define KEY_JUNKS "junks"
168 #define KEY_CORPSES "corpses or skeletons"
169 #define KEY_SPELLBOOKS "spellbooks"
170 #define KEY_HAFTED "hafted weapons"
171 #define KEY_SHIELDS "shields"
172 #define KEY_BOWS "bows"
173 #define KEY_RINGS "rings"
174 #define KEY_AMULETS "amulets"
175 #define KEY_SUITS "suits"
176 #define KEY_CLOAKS "cloaks"
177 #define KEY_HELMS "helms"
178 #define KEY_GLOVES "gloves"
179 #define KEY_BOOTS "boots"
183 #define MATCH_KEY(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\
184 ? (ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE)
185 #define MATCH_KEY2(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\
186 ? (prev_ptr = ptr, ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE)
189 #define ADD_KEY(KEY) strcat(ptr, KEY)
191 #define ADD_KEY(KEY) (strcat(ptr, KEY), strcat(ptr, " "))
193 #define ADD_KEY2(KEY) strcat(ptr, KEY)
195 #define ADD_FLG(FLG) (entry->flag[FLG / 32] |= (1L << (FLG % 32)))
196 #define REM_FLG(FLG) (entry->flag[FLG / 32] &= ~(1L << (FLG % 32)))
197 #define ADD_FLG_NOUN(FLG) (ADD_FLG(FLG), prev_flg = FLG)
198 #define IS_FLG(FLG) (entry->flag[FLG / 32] & (1L << (FLG % 32)))
201 static char kanji_colon[] = "¡§";
206 * A function to create new entry
208 static bool autopick_new_entry(autopick_type *entry, cptr str, bool allow_default)
213 char buf[MAX_LINELEN];
214 cptr prev_ptr, ptr, old_ptr;
217 if (str[1] == ':') switch (str[0])
220 case 'A': case 'P': case 'C':
224 entry->flag[0] = entry->flag[1] = 0L;
227 act = DO_AUTOPICK | DO_DISPLAY;
230 if ((act & DO_AUTOPICK) && *str == '!')
233 act |= DO_AUTODESTROY;
236 else if ((act & DO_AUTOPICK) && *str == '~')
239 act |= DONT_AUTOPICK;
242 else if ((act & DO_AUTOPICK) && *str == ';')
245 act |= DO_QUERY_AUTOPICK;
248 else if ((act & DO_DISPLAY) && *str == '(')
257 /* don't mind upper or lower case */
259 for (i = 0; *str; i++)
270 /* Auto-inscription? */
278 if (isupper(c)) c = tolower(c);
284 /* Skip empty line unless allow_default */
285 if (!allow_default && *buf == 0) return FALSE;
287 /* Skip comment line */
288 if (*buf == 0 && insc) return FALSE;
290 ptr = prev_ptr = buf;
293 while (old_ptr != ptr)
295 /* Save current location */
298 if (MATCH_KEY(KEY_ALL)) ADD_FLG(FLG_ALL);
299 if (MATCH_KEY(KEY_COLLECTING)) ADD_FLG(FLG_COLLECTING);
300 if (MATCH_KEY(KEY_UNAWARE)) ADD_FLG(FLG_UNAWARE);
301 if (MATCH_KEY(KEY_UNIDENTIFIED)) ADD_FLG(FLG_UNIDENTIFIED);
302 if (MATCH_KEY(KEY_IDENTIFIED)) ADD_FLG(FLG_IDENTIFIED);
303 if (MATCH_KEY(KEY_STAR_IDENTIFIED)) ADD_FLG(FLG_STAR_IDENTIFIED);
304 if (MATCH_KEY(KEY_BOOSTED)) ADD_FLG(FLG_BOOSTED);
306 /*** Weapons whose dd*ds is more than nn ***/
307 if (MATCH_KEY2(KEY_MORE_THAN))
312 /* Drop leading spaces */
313 while (' ' == *ptr) ptr++;
316 while ('0' <= *ptr && *ptr <= '9')
318 entry->dice = 10 * entry->dice + (*ptr - '0');
325 (void)MATCH_KEY(KEY_DICE);
326 ADD_FLG(FLG_MORE_DICE);
332 /*** Items whose magical bonus is more than n ***/
333 if (MATCH_KEY2(KEY_MORE_BONUS))
338 /* Drop leading spaces */
339 while (' ' == *ptr) ptr++;
342 while ('0' <= *ptr && *ptr <= '9')
344 entry->bonus = 10 * entry->bonus + (*ptr - '0');
351 (void)MATCH_KEY(KEY_MORE_BONUS2);
352 ADD_FLG(FLG_MORE_BONUS);
358 if (MATCH_KEY(KEY_WORTHLESS)) ADD_FLG(FLG_WORTHLESS);
359 if (MATCH_KEY(KEY_EGO)) ADD_FLG(FLG_EGO);
360 if (MATCH_KEY(KEY_NAMELESS)) ADD_FLG(FLG_NAMELESS);
361 if (MATCH_KEY(KEY_RARE)) ADD_FLG(FLG_RARE);
362 if (MATCH_KEY(KEY_COMMON)) ADD_FLG(FLG_COMMON);
363 if (MATCH_KEY(KEY_WANTED)) ADD_FLG(FLG_WANTED);
364 if (MATCH_KEY(KEY_UNIQUE)) ADD_FLG(FLG_UNIQUE);
365 if (MATCH_KEY(KEY_HUMAN)) ADD_FLG(FLG_HUMAN);
366 if (MATCH_KEY(KEY_UNREADABLE)) ADD_FLG(FLG_UNREADABLE);
367 if (MATCH_KEY(KEY_REALM1)) ADD_FLG(FLG_REALM1);
368 if (MATCH_KEY(KEY_REALM2)) ADD_FLG(FLG_REALM2);
369 if (MATCH_KEY(KEY_FIRST)) ADD_FLG(FLG_FIRST);
370 if (MATCH_KEY(KEY_SECOND)) ADD_FLG(FLG_SECOND);
371 if (MATCH_KEY(KEY_THIRD)) ADD_FLG(FLG_THIRD);
372 if (MATCH_KEY(KEY_FOURTH)) ADD_FLG(FLG_FOURTH);
375 /* Not yet found any noun */
378 if (MATCH_KEY2(KEY_ARTIFACT)) ADD_FLG_NOUN(FLG_ARTIFACT);
380 if (MATCH_KEY2(KEY_ITEMS)) ADD_FLG_NOUN(FLG_ITEMS);
381 else if (MATCH_KEY2(KEY_WEAPONS)) ADD_FLG_NOUN(FLG_WEAPONS);
382 else if (MATCH_KEY2(KEY_FAVORITE_WEAPONS)) ADD_FLG_NOUN(FLG_FAVORITE_WEAPONS);
383 else if (MATCH_KEY2(KEY_ARMORS)) ADD_FLG_NOUN(FLG_ARMORS);
384 else if (MATCH_KEY2(KEY_MISSILES)) ADD_FLG_NOUN(FLG_MISSILES);
385 else if (MATCH_KEY2(KEY_DEVICES)) ADD_FLG_NOUN(FLG_DEVICES);
386 else if (MATCH_KEY2(KEY_LIGHTS)) ADD_FLG_NOUN(FLG_LIGHTS);
387 else if (MATCH_KEY2(KEY_JUNKS)) ADD_FLG_NOUN(FLG_JUNKS);
388 else if (MATCH_KEY2(KEY_CORPSES)) ADD_FLG_NOUN(FLG_CORPSES);
389 else if (MATCH_KEY2(KEY_SPELLBOOKS)) ADD_FLG_NOUN(FLG_SPELLBOOKS);
390 else if (MATCH_KEY2(KEY_HAFTED)) ADD_FLG_NOUN(FLG_HAFTED);
391 else if (MATCH_KEY2(KEY_SHIELDS)) ADD_FLG_NOUN(FLG_SHIELDS);
392 else if (MATCH_KEY2(KEY_BOWS)) ADD_FLG_NOUN(FLG_BOWS);
393 else if (MATCH_KEY2(KEY_RINGS)) ADD_FLG_NOUN(FLG_RINGS);
394 else if (MATCH_KEY2(KEY_AMULETS)) ADD_FLG_NOUN(FLG_AMULETS);
395 else if (MATCH_KEY2(KEY_SUITS)) ADD_FLG_NOUN(FLG_SUITS);
396 else if (MATCH_KEY2(KEY_CLOAKS)) ADD_FLG_NOUN(FLG_CLOAKS);
397 else if (MATCH_KEY2(KEY_HELMS)) ADD_FLG_NOUN(FLG_HELMS);
398 else if (MATCH_KEY2(KEY_GLOVES)) ADD_FLG_NOUN(FLG_GLOVES);
399 else if (MATCH_KEY2(KEY_BOOTS)) ADD_FLG_NOUN(FLG_BOOTS);
401 /* Last 'keyword' must be at the correct location */
405 else if (ptr[0] == kanji_colon[0] && ptr[1] == kanji_colon[1])
408 else if (*ptr == '\0')
410 /* There was no noun */
413 /* Add extra word "items" */
414 ADD_FLG_NOUN(FLG_ITEMS);
421 /* A noun type keyword didn't end correctly */
422 entry->flag[prev_flg/32] &= ~(1L<< (prev_flg%32));
427 /* Save this auto-picker entry line */
428 entry->name = string_make(ptr);
430 entry->insc = string_make(insc);
439 static bool is_favorite(object_type *o_ptr)
441 /* Only weapons match */
442 if (!(TV_WEAPON_BEGIN <= o_ptr->tval && o_ptr->tval <= TV_WEAPON_END))
445 /* Favorite weapons are varied depend on the class */
446 switch (p_ptr->pclass)
450 u32b flgs[TR_FLAG_SIZE];
451 object_flags_known(o_ptr, flgs);
453 if (!have_flag(flgs, TR_BLESSED) &&
454 !(o_ptr->tval == TV_HAFTED))
460 case CLASS_FORCETRAINER:
462 if (!(s_info[p_ptr->pclass].w_max[o_ptr->tval-TV_WEAPON_BEGIN][o_ptr->sval]))
466 case CLASS_BEASTMASTER:
469 u32b flgs[TR_FLAG_SIZE];
470 object_flags_known(o_ptr, flgs);
472 /* Is it known to be suitable to using while riding? */
473 if (!(have_flag(flgs, TR_RIDING)))
481 if (s_info[p_ptr->pclass].w_max[o_ptr->tval-TV_WEAPON_BEGIN][o_ptr->sval] <= WEAPON_EXP_BEGINNER)
486 /* All weapons are okay for non-special classes */
495 * Rare weapons/aromors
496 * including Blade of Chaos, Dragon armors, etc.
498 static bool is_rare(object_type *o_ptr)
503 if (o_ptr->sval == SV_MACE_OF_DISRUPTION ||
504 o_ptr->sval == SV_WIZSTAFF) return TRUE;
508 if (o_ptr->sval == SV_SCYTHE_OF_SLICING ||
509 o_ptr->sval == SV_DEATH_SCYTHE) return TRUE;
513 if (o_ptr->sval == SV_BLADE_OF_CHAOS ||
514 o_ptr->sval == SV_DIAMOND_EDGE ||
515 o_ptr->sval == SV_DOKUBARI ||
516 o_ptr->sval == SV_HAYABUSA) return TRUE;
520 if (o_ptr->sval == SV_DRAGON_SHIELD ||
521 o_ptr->sval == SV_MIRROR_SHIELD) return TRUE;
525 if (o_ptr->sval == SV_DRAGON_HELM) return TRUE;
529 if (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE) return TRUE;
533 if (o_ptr->sval == SV_ELVEN_CLOAK ||
534 o_ptr->sval == SV_ETHEREAL_CLOAK ||
535 o_ptr->sval == SV_SHADOW_CLOAK) return TRUE;
539 if (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES) return TRUE;
543 if (o_ptr->sval == SV_KUROSHOUZOKU ||
544 o_ptr->sval == SV_ABUNAI_MIZUGI) return TRUE;
554 /* Any others are not "rare" objects. */
560 * Get auto-picker entry from o_ptr.
562 static void autopick_entry_from_object(autopick_type *entry, object_type *o_ptr)
564 /* Assume that object name is to be added */
568 /* ¥¨¥´Ì䬼ÙË⤫¤â¤·¤ì¤Ê¤¤¤Î¤Ç¡¢¥Ç¥Õ¥©¥ë¥È¤Ç¡Ö^¡×¤ÏÉÕ¤±¤Ê¤¤ */
569 bool bol_mark = FALSE;
571 /* We can always use the ^ mark in English */
572 bool bol_mark = TRUE;
575 char name_str[MAX_NLEN];
577 /* Initialize name string */
580 entry->insc = string_make(quark_str(o_ptr->inscription));
581 entry->action = DO_AUTOPICK | DO_DISPLAY;
582 entry->flag[0] = entry->flag[1] = 0L;
586 if (!object_aware_p(o_ptr))
588 ADD_FLG(FLG_UNAWARE);
592 /* Not really identified */
593 else if (!object_known_p(o_ptr))
595 if (!(o_ptr->ident & IDENT_SENSE))
597 ADD_FLG(FLG_UNIDENTIFIED);
602 /* Pseudo-identified */
603 switch (o_ptr->feeling)
607 ADD_FLG(FLG_NAMELESS);
613 ADD_FLG(FLG_NAMELESS);
614 ADD_FLG(FLG_WORTHLESS);
620 ADD_FLG(FLG_WORTHLESS);
628 /* XXX No appropriate flag */
633 /* Never reach here */
646 if (TV_WEAPON_BEGIN <= o_ptr->tval &&
647 o_ptr->tval <= TV_ARMOR_END)
650 * Base name of ego weapons and armors
651 * are almost meaningless.
652 * Register the ego type only.
654 ego_item_type *e_ptr = &e_info[o_ptr->name2];
656 /* ¥¨¥´ÌäˤϡÖ^¡×¥Þ¡¼¥¯¤¬»È¤¨¤ë */
657 sprintf(name_str, "^%s", e_name + e_ptr->name);
659 /* We ommit the basename and cannot use the ^ mark */
660 strcpy(name_str, e_name + e_ptr->name);
663 /* Don't use the object description */
666 if (TV_WEAPON_BEGIN <= o_ptr->tval &&
667 o_ptr->tval <= TV_ARMOR_END)
669 /* Restrict to 'common' equipments */
670 if (!is_rare(o_ptr)) ADD_FLG(FLG_COMMON);
678 else if (o_ptr->name1 || o_ptr->art_name)
679 ADD_FLG(FLG_ARTIFACT);
681 /* Non-ego, non-artifact */
684 /* Wearable nameless object */
685 if ((TV_EQUIP_BEGIN <= o_ptr->tval && o_ptr->tval <= TV_EQUIP_END))
686 ADD_FLG(FLG_NAMELESS);
697 case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_DIGGING:
698 k_ptr = &k_info[o_ptr->k_idx];
699 if ((o_ptr->dd != k_ptr->dd) || (o_ptr->ds != k_ptr->ds))
700 ADD_FLG(FLG_BOOSTED);
703 if (o_ptr->tval == TV_CORPSE && object_is_shoukinkubi(o_ptr))
705 REM_FLG(FLG_WORTHLESS);
709 if ((o_ptr->tval == TV_CORPSE || o_ptr->tval == TV_STATUE)
710 && (r_info[o_ptr->pval].flags1 & RF1_UNIQUE))
715 if (o_ptr->tval == TV_CORPSE && my_strchr("pht", r_info[o_ptr->pval].d_char))
720 if (o_ptr->tval >= TV_LIFE_BOOK &&
721 !check_book_realm(o_ptr->tval, o_ptr->sval))
723 ADD_FLG(FLG_UNREADABLE);
724 if (o_ptr->tval != TV_ARCANE_BOOK) name = FALSE;
727 if (REALM1_BOOK == o_ptr->tval &&
728 p_ptr->pclass != CLASS_SORCERER &&
729 p_ptr->pclass != CLASS_RED_MAGE)
735 if (REALM2_BOOK == o_ptr->tval &&
736 p_ptr->pclass != CLASS_SORCERER &&
737 p_ptr->pclass != CLASS_RED_MAGE)
743 if (o_ptr->tval >= TV_LIFE_BOOK && 0 == o_ptr->sval)
745 if (o_ptr->tval >= TV_LIFE_BOOK && 1 == o_ptr->sval)
747 if (o_ptr->tval >= TV_LIFE_BOOK && 2 == o_ptr->sval)
749 if (o_ptr->tval >= TV_LIFE_BOOK && 3 == o_ptr->sval)
752 if (o_ptr->tval == TV_SHOT || o_ptr->tval == TV_BOLT
753 || o_ptr->tval == TV_ARROW)
754 ADD_FLG(FLG_MISSILES);
755 else if (o_ptr->tval == TV_SCROLL || o_ptr->tval == TV_STAFF
756 || o_ptr->tval == TV_WAND || o_ptr->tval == TV_ROD)
757 ADD_FLG(FLG_DEVICES);
758 else if (o_ptr->tval == TV_LITE)
760 else if (o_ptr->tval == TV_SKELETON || o_ptr->tval == TV_BOTTLE
761 || o_ptr->tval == TV_JUNK || o_ptr->tval == TV_STATUE)
763 else if (o_ptr->tval == TV_CORPSE)
764 ADD_FLG(FLG_CORPSES);
765 else if (o_ptr->tval >= TV_LIFE_BOOK)
766 ADD_FLG(FLG_SPELLBOOKS);
767 else if (o_ptr->tval == TV_POLEARM || o_ptr->tval == TV_SWORD
768 || o_ptr->tval == TV_DIGGING || o_ptr->tval == TV_HAFTED)
769 ADD_FLG(FLG_WEAPONS);
770 else if (o_ptr->tval == TV_SHIELD)
771 ADD_FLG(FLG_SHIELDS);
772 else if (o_ptr->tval == TV_BOW)
774 else if (o_ptr->tval == TV_RING)
776 else if (o_ptr->tval == TV_AMULET)
777 ADD_FLG(FLG_AMULETS);
778 else if (o_ptr->tval == TV_DRAG_ARMOR || o_ptr->tval == TV_HARD_ARMOR ||
779 o_ptr->tval == TV_SOFT_ARMOR)
781 else if (o_ptr->tval == TV_CLOAK)
783 else if (o_ptr->tval == TV_HELM)
785 else if (o_ptr->tval == TV_GLOVES)
787 else if (o_ptr->tval == TV_BOOTS)
790 /* Prepare the object description */
793 char o_name[MAX_NLEN];
795 object_desc(o_name, o_ptr, FALSE, 0);
798 * If necessary, add a '^' which indicates the
801 sprintf(name_str, "%s%s", bol_mark ? "^" : "", o_name);
804 /* Register the name in lowercase */
805 str_tolower(name_str);
806 entry->name = string_make(name_str);
813 * A function to delete entry
815 static void autopick_free_entry(autopick_type *entry)
817 string_free(entry->name);
818 string_free(entry->insc);
823 * Initialize auto-picker preference
825 #define MAX_AUTOPICK_DEFAULT 200
827 void init_autopicker(void)
829 static const char easy_autopick_inscription[] = "(:=g";
835 max_max_autopick = MAX_AUTOPICK_DEFAULT;
836 C_MAKE(autopick_list, max_max_autopick, autopick_type);
840 /* Clear old entries */
841 for( i = 0; i < max_autopick; i++)
842 autopick_free_entry(&autopick_list[i]);
846 /* There is always one entry "=g" */
847 autopick_new_entry(&entry, easy_autopick_inscription, TRUE);
848 autopick_list[max_autopick++] = entry;
853 * Add one line to autopick_list[]
855 static void add_autopick_list(autopick_type *entry)
857 /* There is no enough space to add one line */
858 if (max_autopick >= max_max_autopick)
860 int old_max_max_autopick = max_max_autopick;
861 autopick_type *old_autopick_list = autopick_list;
863 /* Increase size of list */
864 max_max_autopick += MAX_AUTOPICK_DEFAULT;
867 C_MAKE(autopick_list, max_max_autopick, autopick_type);
869 /* Copy from old list to new list */
870 C_COPY(autopick_list, old_autopick_list, old_max_max_autopick, autopick_type);
873 C_FREE(old_autopick_list, old_max_max_autopick, autopick_type);
877 autopick_list[max_autopick] = *entry;
884 * Process line for auto picker/destroyer.
886 errr process_pickpref_file_line(char *buf)
888 autopick_type an_entry, *entry = &an_entry;
891 /* Nuke illegal char */
892 for(i = 0; buf[i]; i++)
901 if (isspace(buf[i]) && buf[i] != ' ')
906 if (!autopick_new_entry(entry, buf, FALSE)) return 0;
908 /* Already has the same entry? */
909 for(i = 0; i < max_autopick; i++)
910 if(!strcmp(entry->name, autopick_list[i].name)
911 && entry->flag[0] == autopick_list[i].flag[0]
912 && entry->flag[1] == autopick_list[i].flag[1]
913 && entry->dice == autopick_list[i].dice
914 && entry->bonus == autopick_list[i].bonus) return 0;
916 add_autopick_list(entry);
922 * Reconstruct preference line from entry
924 cptr autopick_line_from_entry(autopick_type *entry)
926 char buf[MAX_LINELEN];
928 bool sepa_flag = TRUE;
931 if (!(entry->action & DO_DISPLAY)) strcat(buf, "(");
932 if (entry->action & DO_QUERY_AUTOPICK) strcat(buf, ";");
933 if (entry->action & DO_AUTODESTROY) strcat(buf, "!");
934 if (entry->action & DONT_AUTOPICK) strcat(buf, "~");
938 if (IS_FLG(FLG_ALL)) ADD_KEY(KEY_ALL);
939 if (IS_FLG(FLG_COLLECTING)) ADD_KEY(KEY_COLLECTING);
940 if (IS_FLG(FLG_UNAWARE)) ADD_KEY(KEY_UNAWARE);
941 if (IS_FLG(FLG_UNIDENTIFIED)) ADD_KEY(KEY_UNIDENTIFIED);
942 if (IS_FLG(FLG_IDENTIFIED)) ADD_KEY(KEY_IDENTIFIED);
943 if (IS_FLG(FLG_STAR_IDENTIFIED)) ADD_KEY(KEY_STAR_IDENTIFIED);
944 if (IS_FLG(FLG_BOOSTED)) ADD_KEY(KEY_BOOSTED);
946 if (IS_FLG(FLG_MORE_DICE))
948 ADD_KEY(KEY_MORE_THAN);
949 strcat(ptr, format("%d", entry->dice));
953 if (IS_FLG(FLG_MORE_BONUS))
955 ADD_KEY(KEY_MORE_BONUS);
956 strcat(ptr, format("%d", entry->bonus));
957 ADD_KEY(KEY_MORE_BONUS2);
960 if (IS_FLG(FLG_UNREADABLE)) ADD_KEY(KEY_UNREADABLE);
961 if (IS_FLG(FLG_REALM1)) ADD_KEY(KEY_REALM1);
962 if (IS_FLG(FLG_REALM2)) ADD_KEY(KEY_REALM2);
963 if (IS_FLG(FLG_FIRST)) ADD_KEY(KEY_FIRST);
964 if (IS_FLG(FLG_SECOND)) ADD_KEY(KEY_SECOND);
965 if (IS_FLG(FLG_THIRD)) ADD_KEY(KEY_THIRD);
966 if (IS_FLG(FLG_FOURTH)) ADD_KEY(KEY_FOURTH);
967 if (IS_FLG(FLG_WANTED)) ADD_KEY(KEY_WANTED);
968 if (IS_FLG(FLG_UNIQUE)) ADD_KEY(KEY_UNIQUE);
969 if (IS_FLG(FLG_HUMAN)) ADD_KEY(KEY_HUMAN);
970 if (IS_FLG(FLG_WORTHLESS)) ADD_KEY(KEY_WORTHLESS);
971 if (IS_FLG(FLG_NAMELESS)) ADD_KEY(KEY_NAMELESS);
972 if (IS_FLG(FLG_RARE)) ADD_KEY(KEY_RARE);
973 if (IS_FLG(FLG_COMMON)) ADD_KEY(KEY_COMMON);
974 if (IS_FLG(FLG_EGO)) ADD_KEY(KEY_EGO);
976 if (IS_FLG(FLG_ARTIFACT)) ADD_KEY(KEY_ARTIFACT);
978 if (IS_FLG(FLG_ITEMS)) ADD_KEY2(KEY_ITEMS);
979 else if (IS_FLG(FLG_WEAPONS)) ADD_KEY2(KEY_WEAPONS);
980 else if (IS_FLG(FLG_FAVORITE_WEAPONS)) ADD_KEY2(KEY_FAVORITE_WEAPONS);
981 else if (IS_FLG(FLG_ARMORS)) ADD_KEY2(KEY_ARMORS);
982 else if (IS_FLG(FLG_MISSILES)) ADD_KEY2(KEY_MISSILES);
983 else if (IS_FLG(FLG_DEVICES)) ADD_KEY2(KEY_DEVICES);
984 else if (IS_FLG(FLG_LIGHTS)) ADD_KEY2(KEY_LIGHTS);
985 else if (IS_FLG(FLG_JUNKS)) ADD_KEY2(KEY_JUNKS);
986 else if (IS_FLG(FLG_CORPSES)) ADD_KEY2(KEY_CORPSES);
987 else if (IS_FLG(FLG_SPELLBOOKS)) ADD_KEY2(KEY_SPELLBOOKS);
988 else if (IS_FLG(FLG_HAFTED)) ADD_KEY2(KEY_HAFTED);
989 else if (IS_FLG(FLG_SHIELDS)) ADD_KEY2(KEY_SHIELDS);
990 else if (IS_FLG(FLG_BOWS)) ADD_KEY2(KEY_BOWS);
991 else if (IS_FLG(FLG_RINGS)) ADD_KEY2(KEY_RINGS);
992 else if (IS_FLG(FLG_AMULETS)) ADD_KEY2(KEY_AMULETS);
993 else if (IS_FLG(FLG_SUITS)) ADD_KEY2(KEY_SUITS);
994 else if (IS_FLG(FLG_CLOAKS)) ADD_KEY2(KEY_CLOAKS);
995 else if (IS_FLG(FLG_HELMS)) ADD_KEY2(KEY_HELMS);
996 else if (IS_FLG(FLG_GLOVES)) ADD_KEY2(KEY_GLOVES);
997 else if (IS_FLG(FLG_BOOTS)) ADD_KEY2(KEY_BOOTS);
999 /* You don't need sepalator after adjective */
1000 /* 'artifact' is not true adjective */
1001 else if (!IS_FLG(FLG_ARTIFACT))
1004 if (entry->name && entry->name[0])
1008 if (sepa_flag) strcat(buf, ":");
1011 while (entry->name[j] && i < MAX_LINELEN - 2 - 1)
1014 if (iskanji(entry->name[j]))
1015 buf[i++] = entry->name[j++];
1017 buf[i++] = entry->name[j++];
1028 while (entry->insc[j] && i < MAX_LINELEN - 2)
1031 if (iskanji(entry->insc[j]))
1032 buf[i++] = entry->insc[j++];
1034 buf[i++] = entry->insc[j++];
1039 return string_make(buf);
1044 * Reconstruct preference line from entry and kill entry
1046 static cptr autopick_line_from_entry_kill(autopick_type *entry)
1048 cptr ptr = autopick_line_from_entry(entry);
1050 /* Free memory for original entry */
1051 autopick_free_entry(entry);
1058 * A function for Auto-picker/destroyer
1059 * Examine whether the object matches to the entry
1061 static bool is_autopick_aux(object_type *o_ptr, autopick_type *entry, cptr o_name)
1064 cptr ptr = entry->name;
1066 /*** Unaware items ***/
1067 if (IS_FLG(FLG_UNAWARE) && object_aware_p(o_ptr))
1070 /*** Unidentified ***/
1071 if (IS_FLG(FLG_UNIDENTIFIED)
1072 && (object_known_p(o_ptr) || (o_ptr->ident & IDENT_SENSE)))
1075 /*** Identified ***/
1076 if (IS_FLG(FLG_IDENTIFIED) && !object_known_p(o_ptr))
1079 /*** *Identified* ***/
1080 if (IS_FLG(FLG_STAR_IDENTIFIED) &&
1081 (!object_known_p(o_ptr) || !(o_ptr->ident & IDENT_MENTAL)))
1084 /*** Dice boosted (weapon of slaying) ***/
1085 if (IS_FLG(FLG_BOOSTED))
1087 object_kind *k_ptr = &k_info[o_ptr->k_idx];
1089 switch( o_ptr->tval )
1095 if ((o_ptr->dd != k_ptr->dd) || (o_ptr->ds != k_ptr->ds))
1104 /*** Weapons which dd*ds is more than nn ***/
1105 if (IS_FLG(FLG_MORE_DICE))
1107 if (o_ptr->dd * o_ptr->ds < entry->dice)
1111 /*** Weapons whic dd*ds is more than nn ***/
1112 if (IS_FLG(FLG_MORE_BONUS))
1114 if (!object_known_p(o_ptr)) return FALSE;
1118 if (o_ptr->pval < entry->bonus) return FALSE;
1122 if (o_ptr->to_h < entry->bonus &&
1123 o_ptr->to_d < entry->bonus &&
1124 o_ptr->to_a < entry->bonus &&
1125 o_ptr->pval < entry->bonus)
1130 /*** Worthless items ***/
1131 if (IS_FLG(FLG_WORTHLESS) && object_value(o_ptr) > 0)
1134 /*** Artifact object ***/
1135 if (IS_FLG(FLG_ARTIFACT))
1137 if (!object_known_p(o_ptr) || (!o_ptr->name1 && !o_ptr->art_name))
1141 /*** Ego object ***/
1142 if (IS_FLG(FLG_EGO))
1144 /* Need to be an ego item */
1145 if (!o_ptr->name2) return FALSE;
1147 /* Need to be known to be an ego */
1148 if (!object_known_p(o_ptr) &&
1149 !((o_ptr->ident & IDENT_SENSE) && o_ptr->feeling == FEEL_EXCELLENT))
1154 if (IS_FLG(FLG_NAMELESS))
1156 if (!(TV_EQUIP_BEGIN <= o_ptr->tval && o_ptr->tval <= TV_EQUIP_END))
1160 if (object_known_p(o_ptr))
1162 /* Artifacts and Ego objects are not okay */
1163 if (o_ptr->name1 || o_ptr->art_name || o_ptr->name2)
1167 /* Pseudo-identified */
1168 else if (o_ptr->ident & IDENT_SENSE)
1170 switch (o_ptr->feeling)
1180 /* It's not nameless */
1188 /* Not known to be nameless */
1193 /*** Rere equpiments ***/
1194 if (IS_FLG(FLG_RARE) && !is_rare(o_ptr))
1197 /*** Common equpiments ***/
1198 if (IS_FLG(FLG_COMMON) && is_rare(o_ptr))
1201 /*** Wanted monster's corpse/skeletons ***/
1202 if (IS_FLG(FLG_WANTED) &&
1203 (o_ptr->tval != TV_CORPSE || !object_is_shoukinkubi(o_ptr)))
1206 /*** Unique monster's corpse/skeletons/statues ***/
1207 if (IS_FLG(FLG_UNIQUE) &&
1208 ((o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_STATUE) ||
1209 !(r_info[o_ptr->pval].flags1 & RF1_UNIQUE)))
1212 /*** Human corpse/skeletons (for Daemon magic) ***/
1213 if (IS_FLG(FLG_HUMAN) &&
1214 (o_ptr->tval != TV_CORPSE ||
1215 !my_strchr("pht", r_info[o_ptr->pval].d_char)))
1218 /*** Unreadable spellbooks ***/
1219 if (IS_FLG(FLG_UNREADABLE) &&
1220 (o_ptr->tval < TV_LIFE_BOOK ||
1221 check_book_realm(o_ptr->tval, o_ptr->sval)))
1224 /*** First realm spellbooks ***/
1225 if (IS_FLG(FLG_REALM1) &&
1226 (REALM1_BOOK != o_ptr->tval ||
1227 p_ptr->pclass == CLASS_SORCERER ||
1228 p_ptr->pclass == CLASS_RED_MAGE))
1231 /*** Second realm spellbooks ***/
1232 if (IS_FLG(FLG_REALM2) &&
1233 (REALM2_BOOK != o_ptr->tval ||
1234 p_ptr->pclass == CLASS_SORCERER ||
1235 p_ptr->pclass == CLASS_RED_MAGE))
1238 /*** First rank spellbooks ***/
1239 if (IS_FLG(FLG_FIRST) &&
1240 (o_ptr->tval < TV_LIFE_BOOK || 0 != o_ptr->sval))
1243 /*** Second rank spellbooks ***/
1244 if (IS_FLG(FLG_SECOND) &&
1245 (o_ptr->tval < TV_LIFE_BOOK || 1 != o_ptr->sval))
1248 /*** Third rank spellbooks ***/
1249 if (IS_FLG(FLG_THIRD) &&
1250 (o_ptr->tval < TV_LIFE_BOOK || 2 != o_ptr->sval))
1253 /*** Fourth rank spellbooks ***/
1254 if (IS_FLG(FLG_FOURTH) &&
1255 (o_ptr->tval < TV_LIFE_BOOK || 3 != o_ptr->sval))
1259 if (IS_FLG(FLG_WEAPONS))
1261 if (!(TV_WEAPON_BEGIN <= o_ptr->tval && o_ptr->tval <= TV_WEAPON_END))
1264 else if (IS_FLG(FLG_FAVORITE_WEAPONS))
1266 if (!is_favorite(o_ptr))
1269 else if (IS_FLG(FLG_ARMORS))
1271 if (!(TV_ARMOR_BEGIN <= o_ptr->tval && o_ptr->tval <= TV_ARMOR_END))
1274 else if (IS_FLG(FLG_MISSILES))
1278 case TV_SHOT: case TV_BOLT: case TV_ARROW:
1280 default: return FALSE;
1283 else if (IS_FLG(FLG_DEVICES))
1287 case TV_SCROLL: case TV_STAFF: case TV_WAND: case TV_ROD:
1289 default: return FALSE;
1292 else if (IS_FLG(FLG_LIGHTS))
1294 if (!(o_ptr->tval == TV_LITE))
1297 else if (IS_FLG(FLG_JUNKS))
1301 case TV_SKELETON: case TV_BOTTLE:
1302 case TV_JUNK: case TV_STATUE:
1304 default: return FALSE;
1307 else if (IS_FLG(FLG_CORPSES))
1309 if (o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_SKELETON)
1312 else if (IS_FLG(FLG_SPELLBOOKS))
1314 if (!(o_ptr->tval >= TV_LIFE_BOOK))
1317 else if (IS_FLG(FLG_HAFTED))
1319 if (!(o_ptr->tval == TV_HAFTED))
1322 else if (IS_FLG(FLG_SHIELDS))
1324 if (!(o_ptr->tval == TV_SHIELD))
1327 else if (IS_FLG(FLG_BOWS))
1329 if (!(o_ptr->tval == TV_BOW))
1332 else if (IS_FLG(FLG_RINGS))
1334 if (!(o_ptr->tval == TV_RING))
1337 else if (IS_FLG(FLG_AMULETS))
1339 if (!(o_ptr->tval == TV_AMULET))
1342 else if (IS_FLG(FLG_SUITS))
1344 if (!(o_ptr->tval == TV_DRAG_ARMOR ||
1345 o_ptr->tval == TV_HARD_ARMOR ||
1346 o_ptr->tval == TV_SOFT_ARMOR))
1349 else if (IS_FLG(FLG_CLOAKS))
1351 if (!(o_ptr->tval == TV_CLOAK))
1354 else if (IS_FLG(FLG_HELMS))
1356 if (!(o_ptr->tval == TV_CROWN || o_ptr->tval == TV_HELM))
1359 else if (IS_FLG(FLG_GLOVES))
1361 if (!(o_ptr->tval == TV_GLOVES))
1364 else if (IS_FLG(FLG_BOOTS))
1366 if (!(o_ptr->tval == TV_BOOTS))
1370 /* Keyword don't match */
1374 if (strncmp(o_name, ptr, strlen(ptr))) return FALSE;
1378 if (!my_strstr(o_name, ptr)) return FALSE;
1381 /* TRUE when it need not to be 'collecting' */
1382 if (!IS_FLG(FLG_COLLECTING)) return TRUE;
1384 /* Check if there is a same item */
1385 for (j = 0; j < INVEN_PACK; j++)
1388 * 'Collecting' means the item must be absorbed
1389 * into an inventory slot.
1390 * But an item can not be absorbed into itself!
1392 if ((&inventory[j] != o_ptr) &&
1393 object_similar(&inventory[j], o_ptr))
1397 /* Not collecting */
1403 * A function for Auto-picker/destroyer
1404 * Examine whether the object matches to the list of keywords or not.
1406 int is_autopick(object_type *o_ptr)
1409 char o_name[MAX_NLEN];
1411 if (o_ptr->tval == TV_GOLD) return -1;
1413 /* Prepare object name string first */
1414 object_desc(o_name, o_ptr, FALSE, 3);
1416 /* Convert the string to lower case */
1417 str_tolower(o_name);
1419 /* Look for a matching entry in the list */
1420 for (i=0; i < max_autopick; i++)
1422 autopick_type *entry = &autopick_list[i];
1424 if (is_autopick_aux(o_ptr, entry, o_name)) return i;
1427 /* No matching entry */
1435 static void auto_inscribe_item(object_type *o_ptr, int idx)
1437 /* Are there auto-inscription? */
1438 if (idx < 0 || !autopick_list[idx].insc) return;
1440 if (!o_ptr->inscription)
1441 o_ptr->inscription = quark_add(autopick_list[idx].insc);
1443 /* Redraw inscription */
1444 p_ptr->window |= (PW_EQUIP | PW_INVEN);
1446 /* {.} and {$} effect p_ptr->warning and TRC_TELEPORT_SELF */
1447 p_ptr->update |= (PU_BONUS);
1452 * Automatically destroy items in this grid.
1454 static bool is_opt_confirm_destroy(object_type *o_ptr)
1456 if (!destroy_items) return FALSE;
1458 /* Known to be worthless? */
1460 if (object_value(o_ptr) > 0) return FALSE;
1463 if ((o_ptr->tval >= TV_MISSILE_BEGIN) && (o_ptr->tval <= TV_ARMOR_END)) return FALSE;
1466 if ((o_ptr->tval == TV_CHEST) && o_ptr->pval) return FALSE;
1470 if (o_ptr->tval == TV_CORPSE
1471 && object_is_shoukinkubi(o_ptr)) return FALSE;
1475 if (o_ptr->tval == TV_CORPSE) return FALSE;
1478 if ((o_ptr->tval == TV_SKELETON) || (o_ptr->tval == TV_BOTTLE) || (o_ptr->tval == TV_JUNK) || (o_ptr->tval == TV_STATUE)) return FALSE;
1482 if (p_ptr->prace == RACE_DEMON)
1484 if (o_ptr->tval == TV_CORPSE &&
1485 o_ptr->sval == SV_CORPSE &&
1486 my_strchr("pht", r_info[o_ptr->pval].d_char))
1490 if (p_ptr->pclass == CLASS_ARCHER)
1492 if (o_ptr->tval == TV_SKELETON ||
1493 (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_SKELETON))
1496 else if (p_ptr->pclass == CLASS_NINJA)
1498 if (o_ptr->tval == TV_LITE &&
1499 o_ptr->name2 == EGO_LITE_DARKNESS)
1502 else if (p_ptr->pclass == CLASS_BEASTMASTER ||
1503 p_ptr->pclass == CLASS_CAVALRY)
1505 if (o_ptr->tval == TV_WAND &&
1506 o_ptr->sval == SV_WAND_HEAL_MONSTER)
1511 if (o_ptr->tval == TV_GOLD) return FALSE;
1518 * Automatically destroy an item if it is to be destroyed
1520 * When always_pickup is 'yes', we disable auto-destroyer function of
1521 * auto-picker/destroyer, and do only easy-auto-destroyer.
1523 static object_type autopick_last_destroyed_object;
1525 static void auto_destroy_item(object_type *o_ptr, int autopick_idx)
1527 bool destroy = FALSE;
1529 /* Easy-Auto-Destroyer (3rd priority) */
1530 if (is_opt_confirm_destroy(o_ptr)) destroy = TRUE;
1532 /* Protected by auto-picker (2nd priotity) */
1533 if (autopick_idx >= 0 &&
1534 !(autopick_list[autopick_idx].action & DO_AUTODESTROY))
1537 /* Auto-destroyer works only when !always_pickup */
1540 /* Auto-picker/destroyer (1st priority) */
1541 if (autopick_idx >= 0 &&
1542 (autopick_list[autopick_idx].action & DO_AUTODESTROY))
1546 /* Not to be destroyed */
1547 if (!destroy) return;
1549 /* Now decided to destroy */
1554 if (!can_player_destroy_object(o_ptr))
1556 char o_name[MAX_NLEN];
1558 /* Describe the object (with {terrible/special}) */
1559 object_desc(o_name, o_ptr, TRUE, 3);
1563 msg_format("%s¤ÏÇ˲õÉÔǽ¤À¡£", o_name);
1565 msg_format("You cannot auto-destroy %s.", o_name);
1572 /* Record name of destroyed item */
1573 COPY(&autopick_last_destroyed_object, o_ptr, object_type);
1576 o_ptr->marked |= OM_AUTODESTROY;
1577 p_ptr->notice |= PN_AUTODESTROY;
1584 * Auto-destroy marked item
1586 static void delayed_auto_destroy_aux(int item)
1590 /* Get the item (in the pack) */
1591 if (item >= 0) o_ptr = &inventory[item];
1593 /* Get the item (on the floor) */
1594 else o_ptr = &o_list[0 - item];
1596 if (o_ptr->k_idx && o_ptr->marked & OM_AUTODESTROY)
1598 char o_name[MAX_NLEN];
1600 /* Describe the object (with {terrible/special}) */
1601 object_desc(o_name, o_ptr, TRUE, 3);
1603 /* Eliminate the item (from the pack) */
1606 inven_item_increase(item, -(o_ptr->number));
1607 inven_item_optimize(item);
1610 /* Eliminate the item (from the floor) */
1613 delete_object_idx(0 - item);
1616 /* Print a message */
1618 msg_format("%s¤ò¼«Æ°Ç˲õ¤·¤Þ¤¹¡£", o_name);
1620 msg_format("Auto-destroying %s.", o_name);
1627 * Auto-destroy marked items in inventry and on floor
1629 void delayed_auto_destroy(void)
1634 * Scan inventry in reverse order to prevent
1635 * skipping after inven_item_optimize()
1637 for (item = INVEN_TOTAL - 1; item >= 0 ; item--)
1638 delayed_auto_destroy_aux(item);
1640 /* Scan the pile of objects */
1641 item = cave[py][px].o_idx;
1644 int next = o_list[item].next_o_idx;
1645 delayed_auto_destroy_aux(-item);
1652 * Auto-inscription and/or destroy
1654 * Auto-destroyer works only on inventory or on floor stack only when
1657 void auto_do_item(int item, bool destroy)
1662 /* Get the item (in the pack) */
1663 if (item >= 0) o_ptr = &inventory[item];
1665 /* Get the item (on the floor) */
1666 else o_ptr = &o_list[0 - item];
1668 /* Get the index in the auto-pick/destroy list */
1669 idx = is_autopick(o_ptr);
1671 /* Do auto-inscription */
1672 auto_inscribe_item(o_ptr, idx);
1674 /* Do auto-destroy if needed */
1675 if (destroy && item <= INVEN_PACK)
1676 auto_destroy_item(o_ptr, idx);
1681 * Automatically pickup/destroy items in this grid.
1683 void auto_pickup_items(cave_type *c_ptr)
1685 s16b this_o_idx, next_o_idx = 0;
1687 /* Scan the pile of objects */
1688 for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1692 /* Acquire object */
1693 object_type *o_ptr = &o_list[this_o_idx];
1695 /* Acquire next object */
1696 next_o_idx = o_ptr->next_o_idx;
1698 idx = is_autopick(o_ptr);
1700 /* Item index for floor -1,-2,-3,... */
1701 auto_inscribe_item(o_ptr, idx);
1704 (autopick_list[idx].action & (DO_AUTOPICK | DO_QUERY_AUTOPICK)))
1708 if (!inven_carry_okay(o_ptr))
1710 char o_name[MAX_NLEN];
1712 /* Describe the object */
1713 object_desc(o_name, o_ptr, TRUE, 3);
1717 msg_format("¥¶¥Ã¥¯¤Ë¤Ï%s¤òÆþ¤ì¤ë·ä´Ö¤¬¤Ê¤¤¡£", o_name);
1719 msg_format("You have no room for %s.", o_name);
1721 /* Hack - remember that the item has given a message here. */
1722 o_ptr->marked |= OM_NOMSG;
1726 else if (autopick_list[idx].action & DO_QUERY_AUTOPICK)
1728 char out_val[MAX_NLEN+20];
1729 char o_name[MAX_NLEN];
1731 if (o_ptr->marked & OM_NO_QUERY)
1733 /* Already answered as 'No' */
1737 /* Describe the object */
1738 object_desc(o_name, o_ptr, TRUE, 3);
1741 sprintf(out_val, "%s¤ò½¦¤¤¤Þ¤¹¤«? ", o_name);
1743 sprintf(out_val, "Pick up %s? ", o_name);
1746 if (!get_check(out_val))
1748 /* Hack - remember that the item has given a message here. */
1749 o_ptr->marked |= (OM_NOMSG | OM_NO_QUERY);
1754 py_pickup_aux(this_o_idx);
1759 * When always_pickup is 'yes', we disable
1760 * auto-destroyer from autopick function, and do only
1761 * easy-auto-destroyer.
1765 auto_destroy_item(o_ptr, idx);
1771 #define PT_DEFAULT 0
1772 #define PT_WITH_PNAME 1
1775 * Get file name for autopick preference
1777 static cptr pickpref_filename(int filename_mode)
1780 static const char namebase[] = "picktype";
1782 static const char namebase[] = "pickpref";
1785 switch (filename_mode)
1788 return format("%s.prf", namebase);
1791 return format("%s-%s.prf", namebase, player_name);
1799 static const char autoregister_header[] = "?:$AUTOREGISTER";
1802 * Clear auto registered lines in the picktype.prf .
1804 static bool clear_auto_register(void)
1806 char tmp_file[1024];
1807 char pref_file[1024];
1812 bool autoregister = FALSE;
1815 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(PT_WITH_PNAME));
1816 pref_fff = my_fopen(pref_file, "r");
1820 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(PT_DEFAULT));
1821 pref_fff = my_fopen(pref_file, "r");
1830 /* Open a new (temporary) file */
1831 tmp_fff = my_fopen_temp(tmp_file, sizeof(tmp_file));
1835 /* Close the preference file */
1839 msg_format("°ì»þ¥Õ¥¡¥¤¥ë %s ¤òºîÀ®¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿¡£", tmp_file);
1841 msg_format("Failed to create temporary file %s.", tmp_file);
1848 /* Loop for every line */
1852 if (my_fgets(pref_fff, buf, sizeof(buf))) break;
1856 /* Delete auto-registered line */
1858 /* Count auto-destroy preference lines */
1859 if (buf[0] != '#' && buf[0] != '?') num++;
1862 /* We are looking for auto-registered line */
1865 if (streq(buf, autoregister_header))
1867 /* Delete all further lines */
1868 autoregister = TRUE;
1872 /* Copy orginally lines */
1873 fprintf(tmp_fff, "%s\n", buf);
1879 my_fclose(pref_fff);
1885 msg_format("°ÊÁ°¤Î¥¥ã¥é¥¯¥¿¡¼ÍѤμ«Æ°ÀßÄê(%d¹Ô)¤¬»Ä¤Ã¤Æ¤¤¤Þ¤¹¡£", num);
1886 strcpy(buf, "¸Å¤¤ÀßÄê¹Ô¤Ïºï½ü¤·¤Þ¤¹¡£¤è¤í¤·¤¤¤Ç¤¹¤«¡©");
1888 msg_format("Auto registered lines (%d lines) for previous character are remaining.", num);
1889 strcpy(buf, "These lines will be deleted. Are you sure? ");
1892 /* You can cancel it */
1893 if (!get_check(buf))
1896 autoregister = FALSE;
1899 msg_print("¥¨¥Ç¥£¥¿¤Î¥«¥Ã¥È&¥Ú¡¼¥¹¥ÈÅù¤ò»È¤Ã¤ÆɬÍפʹԤòÈòÆñ¤·¤Æ¤¯¤À¤µ¤¤¡£");
1901 msg_print("Use cut & paste of auto picker editor (_) to keep old prefs.");
1907 /* If there are some changes, overwrite the original file with new one */
1910 /* Copy contents of temporary file */
1912 tmp_fff = my_fopen(tmp_file, "r");
1913 pref_fff = my_fopen(pref_file, "w");
1915 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
1916 fprintf(pref_fff, "%s\n", buf);
1918 my_fclose(pref_fff);
1922 /* Kill the temporary file */
1930 * Automatically register an auto-destroy preference line
1932 bool add_auto_register(object_type *o_ptr)
1935 char pref_file[1024];
1937 autopick_type an_entry, *entry = &an_entry;
1939 int match_autopick = is_autopick(o_ptr);
1941 /* Already registered */
1942 if (match_autopick != -1)
1945 byte act = autopick_list[match_autopick].action;
1948 if (act & DO_AUTOPICK) what = "¼«Æ°¤Ç½¦¤¦";
1949 else if (act & DO_AUTODESTROY) what = "¼«Æ°Ç˲õ¤¹¤ë";
1950 else if (act & DONT_AUTOPICK) what = "ÊüÃÖ¤¹¤ë";
1951 else /* if (act & DO_QUERY_AUTOPICK) */ what = "³Îǧ¤·¤Æ½¦¤¦";
1953 msg_format("¤½¤Î¥¢¥¤¥Æ¥à¤Ï´û¤Ë%s¤è¤¦¤ËÀßÄꤵ¤ì¤Æ¤¤¤Þ¤¹¡£", what);
1955 if (act & DO_AUTOPICK) what = "auto-pickup";
1956 else if (act & DO_AUTODESTROY) what = "auto-destroy";
1957 else if (act & DONT_AUTOPICK) what = "leave on floor";
1958 else /* if (act & DO_QUERY_AUTOPICK) */ what = "query auto-pickup";
1960 msg_format("The object is already registered to %s.", what);
1966 /* Known to be an artifact? */
1967 if ((object_known_p(o_ptr) &&
1968 (artifact_p(o_ptr) || o_ptr->art_name)) ||
1969 ((o_ptr->ident & IDENT_SENSE) &&
1970 (o_ptr->feeling == FEEL_TERRIBLE || o_ptr->feeling == FEEL_SPECIAL)))
1972 char o_name[MAX_NLEN];
1974 /* Describe the object (with {terrible/special}) */
1975 object_desc(o_name, o_ptr, TRUE, 3);
1979 msg_format("%s¤ÏÇ˲õÉÔǽ¤À¡£", o_name);
1981 msg_format("You cannot auto-destroy %s.", o_name);
1989 if (!p_ptr->autopick_autoregister)
1991 /* Clear old auto registered lines */
1992 if (!clear_auto_register()) return FALSE;
1995 /* Try a filename with player name */
1996 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(PT_WITH_PNAME));
1997 pref_fff = my_fopen(pref_file, "r");
2001 /* Use default name */
2002 path_build(pref_file, sizeof(pref_file), ANGBAND_DIR_USER, pickpref_filename(PT_DEFAULT));
2003 pref_fff = my_fopen(pref_file, "r");
2006 /* Check the header */
2010 if (my_fgets(pref_fff, buf, sizeof(buf)))
2012 /* No header found */
2013 p_ptr->autopick_autoregister = FALSE;
2018 if (streq(buf, autoregister_header))
2020 /* Found the header */
2021 p_ptr->autopick_autoregister = TRUE;
2027 /* Close read only FILE* */
2030 /* Open for append */
2031 pref_fff = my_fopen(pref_file, "a");
2036 msg_format("%s ¤ò³«¤¯¤³¤È¤¬¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿¡£", pref_file);
2038 msg_format("Failed to open %s.", pref_file);
2046 if (!p_ptr->autopick_autoregister)
2048 /* Add the header */
2049 fprintf(pref_fff, "%s\n", autoregister_header);
2052 fprintf(pref_fff, "%s\n", "# *·Ù¹ð!!* °Ê¹ß¤Î¹Ô¤Ï¼«Æ°ÅÐÏ¿¤µ¤ì¤¿¤â¤Î¤Ç¤¹¡£");
2053 fprintf(pref_fff, "%s\n", "# ¸å¤Ç¼«Æ°Åª¤Ëºï½ü¤µ¤ì¤Þ¤¹¤Î¤Ç¡¢É¬ÍפʹԤϾå¤ÎÊý¤Ø°ÜÆ°¤·¤Æ¤ª¤¤¤Æ¤¯¤À¤µ¤¤¡£");
2055 fprintf(pref_fff, "%s\n", "# *Waring!* The lines below will be deleated later.");
2056 fprintf(pref_fff, "%s\n", "# Keep it by cut & paste if you need these lines for future characters.");
2059 /* Now auto register is in-use */
2060 p_ptr->autopick_autoregister = TRUE;
2063 /* Get a preference entry */
2064 autopick_entry_from_object(entry, o_ptr);
2066 /* Set to auto-destroy (with no-display) */
2067 entry->action = DO_AUTODESTROY;
2069 /* Load the new line as preference */
2070 add_autopick_list(entry);
2072 /* Add a line to the file */
2073 /* Don't kill "entry" */
2074 fprintf(pref_fff, "%s\n", autopick_line_from_entry(entry));
2076 /* Close the file */
2083 /******** Auto-picker/destroyer editor **********/
2085 #define MAX_YANK MAX_LINELEN
2086 #define MAX_LINES 3000
2088 #define MARK_MARK 0x01
2089 #define MARK_BY_SHIFT 0x02
2091 #define LSTAT_BYPASS 0x01
2092 #define LSTAT_EXPRESSION 0x02
2093 #define LSTAT_AUTOREGISTER 0x04
2095 #define QUIT_WITHOUT_SAVE 1
2096 #define QUIT_AND_SAVE 2
2099 * Struct for yank buffer
2101 typedef struct chain_str {
2102 struct chain_str *next;
2108 * Data struct for text editor
2114 int old_wid, old_hgt;
2116 int old_upper, old_left;
2120 object_type *search_o_ptr;
2122 cptr last_destroyed;
2124 chain_str_type *yank;
2128 byte states[MAX_LINES];
2140 * Dirty flag for text editor
2142 #define DIRTY_ALL 0x0001
2143 #define DIRTY_MODE 0x0004
2144 #define DIRTY_SCREEN 0x0008
2145 #define DIRTY_NOT_FOUND 0x0010
2146 #define DIRTY_NO_SEARCH 0x0020
2147 #define DIRTY_EXPRESSION 0x0040
2148 #define DIRTY_SKIP_INACTIVE 0x0080
2149 #define DIRTY_INACTIVE 0x0100
2152 * Describe which kind of object is Auto-picked/destroyed
2154 static void describe_autopick(char *buff, autopick_type *entry)
2156 cptr str = entry->name;
2157 byte act = entry->action;
2158 cptr insc = entry->insc;
2164 cptr before_str[100], body_str;
2167 body_str = "¥¢¥¤¥Æ¥à";
2169 /*** Collecting items ***/
2170 /*** Which can be absorbed into a slot as a bundle ***/
2171 if (IS_FLG(FLG_COLLECTING))
2172 before_str[before_n++] = "¼ý½¸Ãæ¤Ç´û¤Ë»ý¤Ã¤Æ¤¤¤ë¥¹¥í¥Ã¥È¤Ë¤Þ¤È¤á¤é¤ì¤ë";
2174 /*** Unaware items ***/
2175 if (IS_FLG(FLG_UNAWARE))
2176 before_str[before_n++] = "̤´ÕÄê¤Ç¤½¤Î¸ú²Ì¤âȽÌÀ¤·¤Æ¤¤¤Ê¤¤";
2178 /*** Unidentified ***/
2179 if (IS_FLG(FLG_UNIDENTIFIED))
2180 before_str[before_n++] = "̤´ÕÄê¤Î";
2182 /*** Identified ***/
2183 if (IS_FLG(FLG_IDENTIFIED))
2184 before_str[before_n++] = "´ÕÄêºÑ¤ß¤Î";
2186 /*** *Identified* ***/
2187 if (IS_FLG(FLG_STAR_IDENTIFIED))
2188 before_str[before_n++] = "´°Á´¤Ë´ÕÄêºÑ¤ß¤Î";
2190 /*** Dice boosted (weapon of slaying) ***/
2191 if (IS_FLG(FLG_BOOSTED))
2193 before_str[before_n++] = "¥À¥á¡¼¥¸¥À¥¤¥¹¤¬Ä̾ï¤è¤êÂ礤¤";
2197 /*** Weapons whose dd*ds is more than nn ***/
2198 if (IS_FLG(FLG_MORE_DICE))
2200 static char more_than_desc_str[] = "___";
2201 before_str[before_n++] = "¥À¥á¡¼¥¸¥À¥¤¥¹¤ÎºÇÂçÃͤ¬";
2204 sprintf(more_than_desc_str,"%d", entry->dice);
2205 before_str[before_n++] = more_than_desc_str;
2206 before_str[before_n++] = "°Ê¾å¤Î";
2209 /*** Items whose magical bonus is more than nn ***/
2210 if (IS_FLG(FLG_MORE_BONUS))
2212 static char more_bonus_desc_str[] = "___";
2213 before_str[before_n++] = "½¤ÀµÃͤ¬(+";
2215 sprintf(more_bonus_desc_str,"%d", entry->bonus);
2216 before_str[before_n++] = more_bonus_desc_str;
2217 before_str[before_n++] = ")°Ê¾å¤Î";
2220 /*** Worthless items ***/
2221 if (IS_FLG(FLG_WORTHLESS))
2222 before_str[before_n++] = "Ź¤Ç̵²ÁÃͤÈȽÄꤵ¤ì¤ë";
2225 if (IS_FLG(FLG_ARTIFACT))
2227 before_str[before_n++] = "¥¢¡¼¥Æ¥£¥Õ¥¡¥¯¥È¤Î";
2232 if (IS_FLG(FLG_EGO))
2234 before_str[before_n++] = "¥¨¥´¥¢¥¤¥Æ¥à¤Î";
2239 if (IS_FLG(FLG_NAMELESS))
2241 before_str[before_n++] = "¥¨¥´¤Ç¤â¥¢¡¼¥Æ¥£¥Õ¥¡¥¯¥È¤Ç¤â¤Ê¤¤";
2245 /*** Rare equpiments ***/
2246 if (IS_FLG(FLG_RARE))
2248 before_str[before_n++] = "¥É¥é¥´¥óÁõÈ÷¤ä¥«¥ª¥¹¡¦¥Ö¥ì¡¼¥ÉÅù¤ò´Þ¤àÄÁ¤·¤¤";
2252 /*** Common equpiments ***/
2253 if (IS_FLG(FLG_COMMON))
2255 before_str[before_n++] = "¤¢¤ê¤Õ¤ì¤¿(¥É¥é¥´¥óÁõÈ÷¤ä¥«¥ª¥¹¡¦¥Ö¥ì¡¼¥ÉÅù¤ÎÄÁ¤·¤¤Êª¤Ç¤Ï¤Ê¤¤)";
2259 /*** Wanted monster's corpse/skeletons ***/
2260 if (IS_FLG(FLG_WANTED))
2262 before_str[before_n++] = "¥Ï¥ó¥¿¡¼»ö̳½ê¤Ç¾Þ¶â¼ó¤È¤µ¤ì¤Æ¤¤¤ë";
2263 body_str = "»àÂΤä¹ü";
2266 /*** Human corpse/skeletons (for Daemon magic) ***/
2267 if (IS_FLG(FLG_HUMAN))
2269 before_str[before_n++] = "°ËâËâË¡¤Ç»È¤¦¤¿¤á¤Î¿Í´Ö¤ä¥Ò¥å¡¼¥Þ¥Î¥¤¥É¤Î";
2270 body_str = "»àÂΤä¹ü";
2273 /*** Unique monster's corpse/skeletons/statues ***/
2274 if (IS_FLG(FLG_UNIQUE))
2276 before_str[before_n++] = "¥æ¥Ë¡¼¥¯¥â¥ó¥¹¥¿¡¼¤Î";
2277 body_str = "»àÂΤä¹ü";
2280 /*** Unreadable spellbooks ***/
2281 if (IS_FLG(FLG_UNREADABLE))
2283 before_str[before_n++] = "¤¢¤Ê¤¿¤¬Æɤá¤Ê¤¤Îΰè¤Î";
2284 body_str = "ËâË¡½ñ";
2287 /*** First realm spellbooks ***/
2288 if (IS_FLG(FLG_REALM1))
2290 before_str[before_n++] = "Âè°ìÎΰè¤Î";
2291 body_str = "ËâË¡½ñ";
2294 /*** Second realm spellbooks ***/
2295 if (IS_FLG(FLG_REALM2))
2297 before_str[before_n++] = "ÂèÆóÎΰè¤Î";
2298 body_str = "ËâË¡½ñ";
2301 /*** First rank spellbooks ***/
2302 if (IS_FLG(FLG_FIRST))
2304 before_str[before_n++] = "Á´4ºý¤ÎÆâ¤Î1ºýÌܤÎ";
2305 body_str = "ËâË¡½ñ";
2308 /*** Second rank spellbooks ***/
2309 if (IS_FLG(FLG_SECOND))
2311 before_str[before_n++] = "Á´4ºý¤ÎÆâ¤Î2ºýÌܤÎ";
2312 body_str = "ËâË¡½ñ";
2315 /*** Third rank spellbooks ***/
2316 if (IS_FLG(FLG_THIRD))
2318 before_str[before_n++] = "Á´4ºý¤ÎÆâ¤Î3ºýÌܤÎ";
2319 body_str = "ËâË¡½ñ";
2322 /*** Fourth rank spellbooks ***/
2323 if (IS_FLG(FLG_FOURTH))
2325 before_str[before_n++] = "Á´4ºý¤ÎÆâ¤Î4ºýÌܤÎ";
2326 body_str = "ËâË¡½ñ";
2330 if (IS_FLG(FLG_ITEMS))
2331 ; /* Nothing to do */
2332 else if (IS_FLG(FLG_WEAPONS))
2334 else if (IS_FLG(FLG_FAVORITE_WEAPONS))
2335 body_str = "ÆÀ°ÕÉð´ï";
2336 else if (IS_FLG(FLG_ARMORS))
2338 else if (IS_FLG(FLG_MISSILES))
2339 body_str = "ÃƤäÌð¤ä¥¯¥í¥¹¥Ü¥¦¤ÎÌð";
2340 else if (IS_FLG(FLG_DEVICES))
2341 body_str = "´¬Êª¤äËâË¡ËÀ¤ä¾ó¤ä¥í¥Ã¥É";
2342 else if (IS_FLG(FLG_LIGHTS))
2343 body_str = "¸÷¸»ÍѤΥ¢¥¤¥Æ¥à";
2344 else if (IS_FLG(FLG_JUNKS))
2345 body_str = "Àޤ줿ËÀÅù¤Î¥¬¥é¥¯¥¿";
2346 else if (IS_FLG(FLG_CORPSES))
2347 body_str = "»àÂΤä¹ü";
2348 else if (IS_FLG(FLG_SPELLBOOKS))
2349 body_str = "ËâË¡½ñ";
2350 else if (IS_FLG(FLG_HAFTED))
2352 else if (IS_FLG(FLG_SHIELDS))
2354 else if (IS_FLG(FLG_BOWS))
2355 body_str = "¥¹¥ê¥ó¥°¤äµÝ¤ä¥¯¥í¥¹¥Ü¥¦";
2356 else if (IS_FLG(FLG_RINGS))
2358 else if (IS_FLG(FLG_AMULETS))
2359 body_str = "¥¢¥ß¥å¥ì¥Ã¥È";
2360 else if (IS_FLG(FLG_SUITS))
2362 else if (IS_FLG(FLG_CLOAKS))
2363 body_str = "¥¯¥í¡¼¥¯";
2364 else if (IS_FLG(FLG_HELMS))
2365 body_str = "¥Ø¥ë¥á¥Ã¥È¤ä´§";
2366 else if (IS_FLG(FLG_GLOVES))
2368 else if (IS_FLG(FLG_BOOTS))
2369 body_str = "¥Ö¡¼¥Ä";
2373 strcat(buff, "Á´¤Æ¤Î");
2374 else for (i = 0; i < before_n && before_str[i]; i++)
2375 strcat(buff, before_str[i]);
2377 strcat(buff, body_str);
2387 strcat(buff, "¤Ç¡¢Ì¾Á°¤¬¡Ö");
2388 strncat(buff, str, 80);
2390 strcat(buff, "¡×¤Ç»Ï¤Þ¤ë¤â¤Î");
2392 strcat(buff, "¡×¤ò´Þ¤à¤â¤Î");
2397 strncat(buff, format("¤Ë¡Ö%s¡×", insc), 80);
2399 if (my_strstr(insc, "%%all"))
2400 strcat(buff, "(%%all¤ÏÁ´Ç½ÎϤòɽ¤¹±Ñ»ú¤Îµ¹æ¤ÇÃÖ´¹)");
2401 else if (my_strstr(insc, "%all"))
2402 strcat(buff, "(%all¤ÏÁ´Ç½ÎϤòɽ¤¹µ¹æ¤ÇÃÖ´¹)");
2403 else if (my_strstr(insc, "%%"))
2404 strcat(buff, "(%%¤ÏÄɲÃǽÎϤòɽ¤¹±Ñ»ú¤Îµ¹æ¤ÇÃÖ´¹)");
2405 else if (my_strstr(insc, "%"))
2406 strcat(buff, "(%¤ÏÄɲÃǽÎϤòɽ¤¹µ¹æ¤ÇÃÖ´¹)");
2408 strcat(buff, "¤È¹ï¤ó¤Ç");
2413 if (act & DONT_AUTOPICK)
2414 strcat(buff, "ÊüÃÖ¤¹¤ë¡£");
2415 else if (act & DO_AUTODESTROY)
2416 strcat(buff, "Ç˲õ¤¹¤ë¡£");
2417 else if (act & DO_QUERY_AUTOPICK)
2418 strcat(buff, "³Îǧ¤Î¸å¤Ë½¦¤¦¡£");
2420 strcat(buff, "½¦¤¦¡£");
2422 if (act & DO_DISPLAY)
2424 if (act & DONT_AUTOPICK)
2425 strcat(buff, "Á´ÂΥޥå×('M')¤Ç'N'¤ò²¡¤·¤¿¤È¤¤Ëɽ¼¨¤¹¤ë¡£");
2426 else if (act & DO_AUTODESTROY)
2427 strcat(buff, "Á´ÂΥޥå×('M')¤Ç'K'¤ò²¡¤·¤¿¤È¤¤Ëɽ¼¨¤¹¤ë¡£");
2429 strcat(buff, "Á´ÂΥޥå×('M')¤Ç'M'¤ò²¡¤·¤¿¤È¤¤Ëɽ¼¨¤¹¤ë¡£");
2432 strcat(buff, "Á´ÂΥޥåפˤÏɽ¼¨¤·¤Ê¤¤¡£");
2436 cptr before_str[20], after_str[20], which_str[20], whose_str[20], body_str;
2437 int before_n = 0, after_n = 0, which_n = 0, whose_n = 0;
2441 /*** Collecting items ***/
2442 /*** Which can be absorbed into a slot as a bundle ***/
2443 if (IS_FLG(FLG_COLLECTING))
2444 which_str[which_n++] = "can be absorbed into an existing inventory slot";
2446 /*** Unaware items ***/
2447 if (IS_FLG(FLG_UNAWARE))
2449 before_str[before_n++] = "unidentified";
2450 whose_str[whose_n++] = "basic abilities are not known";
2453 /*** Unidentified ***/
2454 if (IS_FLG(FLG_UNIDENTIFIED))
2455 before_str[before_n++] = "unidentified";
2457 /*** Identified ***/
2458 if (IS_FLG(FLG_IDENTIFIED))
2459 before_str[before_n++] = "identified";
2461 /*** *Identified* ***/
2462 if (IS_FLG(FLG_STAR_IDENTIFIED))
2463 before_str[before_n++] = "fully identified";
2465 /*** Rare equpiments ***/
2466 if (IS_FLG(FLG_RARE))
2468 before_str[before_n++] = "very rare";
2469 body_str = "equipments";
2470 after_str[after_n++] = "such like Dragon armors, Blades of Chaos, etc.";
2473 /*** Common equpiments ***/
2474 if (IS_FLG(FLG_COMMON))
2476 before_str[before_n++] = "relatively common";
2477 body_str = "equipments";
2478 after_str[after_n++] = "compared to very rare Dragon armors, Blades of Chaos, etc.";
2481 /*** Worthless items ***/
2482 if (IS_FLG(FLG_WORTHLESS))
2484 before_str[before_n++] = "worthless";
2485 which_str[which_n++] = "can not be sold at stores";
2489 if (IS_FLG(FLG_ARTIFACT))
2491 before_str[before_n++] = "artifact";
2495 if (IS_FLG(FLG_EGO))
2497 before_str[before_n++] = "ego";
2501 if (IS_FLG(FLG_NAMELESS))
2503 body_str = "equipment";
2504 which_str[which_n++] = "is neither ego-item nor artifact";
2507 /*** Dice boosted (weapon of slaying) ***/
2508 if (IS_FLG(FLG_BOOSTED))
2510 body_str = "weapons";
2511 whose_str[whose_n++] = "damage dice is bigger than normal";
2514 /*** Weapons whose dd*ds is more than nn ***/
2515 if (IS_FLG(FLG_MORE_DICE))
2517 static char more_than_desc_str[] =
2518 "maximum damage from dice is bigger than __";
2519 body_str = "weapons";
2521 sprintf(more_than_desc_str + sizeof(more_than_desc_str) - 3,
2523 whose_str[whose_n++] = more_than_desc_str;
2526 /*** Items whose magical bonus is more than nn ***/
2527 if (IS_FLG(FLG_MORE_BONUS))
2529 static char more_bonus_desc_str[] =
2530 "magical bonus is bigger than (+__)";
2532 sprintf(more_bonus_desc_str + sizeof(more_bonus_desc_str) - 4,
2533 "%d)", entry->bonus);
2534 whose_str[whose_n++] = more_bonus_desc_str;
2537 /*** Wanted monster's corpse/skeletons ***/
2538 if (IS_FLG(FLG_WANTED))
2540 body_str = "corpse or skeletons";
2541 which_str[which_n++] = "is wanted at the Hunter's Office";
2544 /*** Human corpse/skeletons (for Daemon magic) ***/
2545 if (IS_FLG(FLG_HUMAN))
2547 before_str[before_n++] = "humanoid";
2548 body_str = "corpse or skeletons";
2549 which_str[which_n++] = "can be used for Daemon magic";
2552 /*** Unique monster's corpse/skeletons/statues ***/
2553 if (IS_FLG(FLG_UNIQUE))
2555 before_str[before_n++] = "unique monster's";
2556 body_str = "corpse or skeletons";
2559 /*** Unreadable spellbooks ***/
2560 if (IS_FLG(FLG_UNREADABLE))
2562 body_str = "spellbooks";
2563 after_str[after_n++] = "of different realms from yours";
2566 /*** First realm spellbooks ***/
2567 if (IS_FLG(FLG_REALM1))
2569 body_str = "spellbooks";
2570 after_str[after_n++] = "of your first realm";
2573 /*** Second realm spellbooks ***/
2574 if (IS_FLG(FLG_REALM2))
2576 body_str = "spellbooks";
2577 after_str[after_n++] = "of your second realm";
2580 /*** First rank spellbooks ***/
2581 if (IS_FLG(FLG_FIRST))
2583 before_str[before_n++] = "first one of four";
2584 body_str = "spellbooks";
2587 /*** Second rank spellbooks ***/
2588 if (IS_FLG(FLG_SECOND))
2590 before_str[before_n++] = "second one of four";
2591 body_str = "spellbooks";
2594 /*** Third rank spellbooks ***/
2595 if (IS_FLG(FLG_THIRD))
2597 before_str[before_n++] = "third one of four";
2598 body_str = "spellbooks";
2601 /*** Fourth rank spellbooks ***/
2602 if (IS_FLG(FLG_FOURTH))
2604 before_str[before_n++] = "fourth one of four";
2605 body_str = "spellbooks";
2609 if (IS_FLG(FLG_ITEMS))
2610 ; /* Nothing to do */
2611 else if (IS_FLG(FLG_WEAPONS))
2612 body_str = "weapons";
2613 else if (IS_FLG(FLG_FAVORITE_WEAPONS))
2614 body_str = "favorite weapons";
2615 else if (IS_FLG(FLG_ARMORS))
2616 body_str = "armors";
2617 else if (IS_FLG(FLG_MISSILES))
2618 body_str = "shots, arrows or crossbow bolts";
2619 else if (IS_FLG(FLG_DEVICES))
2620 body_str = "scrolls, wands, staves or rods";
2621 else if (IS_FLG(FLG_LIGHTS))
2622 body_str = "light sources";
2623 else if (IS_FLG(FLG_JUNKS))
2624 body_str = "junk such as broken sticks";
2625 else if (IS_FLG(FLG_CORPSES))
2626 body_str = "corpses or skeletons";
2627 else if (IS_FLG(FLG_SPELLBOOKS))
2628 body_str = "spellbooks";
2629 else if (IS_FLG(FLG_HAFTED))
2630 body_str = "hafted weapons";
2631 else if (IS_FLG(FLG_SHIELDS))
2632 body_str = "shields";
2633 else if (IS_FLG(FLG_BOWS))
2634 body_str = "slings, bows or crossbows";
2635 else if (IS_FLG(FLG_RINGS))
2637 else if (IS_FLG(FLG_AMULETS))
2638 body_str = "amulets";
2639 else if (IS_FLG(FLG_SUITS))
2640 body_str = "body armors";
2641 else if (IS_FLG(FLG_CLOAKS))
2642 body_str = "cloaks";
2643 else if (IS_FLG(FLG_HELMS))
2644 body_str = "helms or crowns";
2645 else if (IS_FLG(FLG_GLOVES))
2646 body_str = "gloves";
2647 else if (IS_FLG(FLG_BOOTS))
2650 /* Prepare a string for item name */
2657 whose_str[whose_n++] = "name is beginning with \"";
2660 which_str[which_n++] = "have \"";
2664 /* Describe action flag */
2665 if (act & DONT_AUTOPICK)
2666 strcpy(buff, "Leave on floor ");
2667 else if (act & DO_AUTODESTROY)
2668 strcpy(buff, "Destroy ");
2669 else if (act & DO_QUERY_AUTOPICK)
2670 strcpy(buff, "Ask to pick up ");
2672 strcpy(buff, "Pickup ");
2674 /* Auto-insctiption */
2677 strncat(buff, format("and inscribe \"%s\"", insc), 80);
2679 if (my_strstr(insc, "%all"))
2680 strcat(buff, ", replacing %all with code string representing all abilities,");
2681 else if (my_strstr(insc, "%"))
2682 strcat(buff, ", replacing % with code string representing extra random abilities,");
2684 strcat(buff, " on ");
2689 strcat(buff, "all ");
2690 else for (i = 0; i < before_n && before_str[i]; i++)
2692 strcat(buff, before_str[i]);
2697 strcat(buff, body_str);
2700 for (i = 0; i < after_n && after_str[i]; i++)
2703 strcat(buff, after_str[i]);
2707 for (i = 0; i < whose_n && whose_str[i]; i++)
2710 strcat(buff, " whose ");
2712 strcat(buff, ", and ");
2714 strcat(buff, whose_str[i]);
2717 /* Item name ; whose name is beginning with "str" */
2724 /* whose ..., and which .... */
2725 if (whose_n && which_n)
2726 strcat(buff, ", and ");
2729 for (i = 0; i < which_n && which_str[i]; i++)
2732 strcat(buff, " which ");
2734 strcat(buff, ", and ");
2736 strcat(buff, which_str[i]);
2739 /* Item name ; which have "str" as part of its name */
2742 strncat(buff, str, 80);
2743 strcat(buff, "\" as part of its name");
2747 /* Describe whether it will be displayed on the full map or not */
2748 if (act & DO_DISPLAY)
2750 if (act & DONT_AUTOPICK)
2751 strcat(buff, " Display these items when you press the N key in the full 'M'ap.");
2752 else if (act & DO_AUTODESTROY)
2753 strcat(buff, " Display these items when you press the K key in the full 'M'ap.");
2755 strcat(buff, " Display these items when you press the M key in the full 'M'ap.");
2758 strcat(buff, " Not displayed in the full map.");
2765 * Read whole lines of a file to memory
2767 static cptr *read_text_lines(cptr filename, bool user)
2769 cptr *lines_list = NULL;
2777 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2781 path_build(buf, sizeof(buf), ANGBAND_DIR_PREF, filename);
2785 fff = my_fopen(buf, "r");
2789 /* Allocate list of pointers */
2790 C_MAKE(lines_list, MAX_LINES, cptr);
2793 while (0 == my_fgets(fff, buf, sizeof(buf)))
2795 lines_list[lines++] = string_make(buf);
2796 if (lines >= MAX_LINES - 1) break;
2799 lines_list[0] = string_make("");
2804 if (!fff) return NULL;
2809 static cptr *read_pickpref_text_lines(int *filename_mode_p)
2814 *filename_mode_p = PT_WITH_PNAME;
2815 strcpy(buf, pickpref_filename(*filename_mode_p));
2816 lines_list = read_text_lines(buf, TRUE);
2820 *filename_mode_p = PT_DEFAULT;
2821 strcpy(buf, pickpref_filename(*filename_mode_p));
2822 lines_list = read_text_lines(buf, TRUE);
2827 strcpy(buf, pickpref_filename(*filename_mode_p));
2828 lines_list = read_text_lines(buf, FALSE);
2833 /* Allocate list of pointers */
2834 C_MAKE(lines_list, MAX_LINES, cptr);
2835 lines_list[0] = string_make("");
2842 * Write whole lines of memory to a file.
2844 static bool write_text_lines(cptr filename, cptr *lines_list)
2851 /* Build the filename */
2852 path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
2855 fff = my_fopen(buf, "w");
2858 for (lines = 0; lines_list[lines]; lines++)
2859 my_fputs(fff, lines_list[lines], 1024);
2864 if (!fff) return FALSE;
2870 * Free memory of lines_list.
2872 static void free_text_lines(cptr *lines_list)
2876 for (lines = 0; lines_list[lines]; lines++)
2877 string_free(lines_list[lines]);
2879 /* free list of pointers */
2880 C_FREE((char **)lines_list, MAX_LINES, char *);
2885 * Delete or insert string
2887 static void toggle_keyword(text_body_type *tb, int flg)
2893 /* Some lines are selected */
2896 by1 = MIN(tb->my, tb->cy);
2897 by2 = MAX(tb->my, tb->cy);
2900 /* No mark -- Select current line */
2901 else /* if (!tb->mark) */
2907 /* Set/Reset flag of each line */
2908 for (y = by1; y <= by2; y++)
2910 autopick_type an_entry, *entry = &an_entry;
2912 if (!autopick_new_entry(entry, tb->lines_list[y], !fixed)) continue;
2914 string_free(tb->lines_list[y]);
2918 /* Add? or Remove? */
2919 if (!IS_FLG(flg)) add = TRUE;
2922 /* No more change */
2926 /* You can use only one noun flag */
2927 if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
2930 for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
2934 /* You can use only one identify state flag */
2935 else if (FLG_UNAWARE <= flg && flg <= FLG_STAR_IDENTIFIED)
2938 for (i = FLG_UNAWARE; i <= FLG_STAR_IDENTIFIED; i++)
2942 /* You can use only one flag in artifact/ego/nameless */
2943 else if (FLG_ARTIFACT <= flg && flg <= FLG_NAMELESS)
2946 for (i = FLG_ARTIFACT; i <= FLG_NAMELESS; i++)
2950 /* You can use only one flag in rare/common */
2951 else if (FLG_RARE <= flg && flg <= FLG_COMMON)
2954 for (i = FLG_RARE; i <= FLG_COMMON; i++)
2958 if (add) ADD_FLG(flg);
2961 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
2964 tb->dirty_flags |= DIRTY_ALL;
2966 /* Text is changed */
2973 * Change command letter
2975 static void toggle_command_letter(text_body_type *tb, byte flg)
2977 autopick_type an_entry, *entry = &an_entry;
2982 /* Some lines are selected */
2985 by1 = MIN(tb->my, tb->cy);
2986 by2 = MAX(tb->my, tb->cy);
2989 /* No mark -- Select current line */
2990 else /* if (!tb->mark) */
2996 /* Set/Reset flag of each line */
2997 for (y = by1; y <= by2; y++)
3001 if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue;
3003 string_free(tb->lines_list[y]);
3007 /* Add? or Remove? */
3008 if (!(entry->action & flg)) add = TRUE;
3011 /* No more change */
3015 /* Count number of letter (by negative number) */
3016 if (entry->action & DONT_AUTOPICK) wid--;
3017 else if (entry->action & DO_AUTODESTROY) wid--;
3018 else if (entry->action & DO_QUERY_AUTOPICK) wid--;
3019 if (!(entry->action & DO_DISPLAY)) wid--;
3021 /* Set/Reset the flag */
3022 if (flg != DO_DISPLAY)
3024 entry->action &= ~(DO_AUTOPICK | DONT_AUTOPICK | DO_AUTODESTROY | DO_QUERY_AUTOPICK);
3025 if (add) entry->action |= flg;
3026 else entry->action |= DO_AUTOPICK;
3030 entry->action &= ~(DO_DISPLAY);
3031 if (add) entry->action |= flg;
3034 /* Correct cursor location */
3037 if (entry->action & DONT_AUTOPICK) wid++;
3038 else if (entry->action & DO_AUTODESTROY) wid++;
3039 else if (entry->action & DO_QUERY_AUTOPICK) wid++;
3040 if (!(entry->action & DO_DISPLAY)) wid++;
3042 if (wid > 0) tb->cx++;
3043 if (wid < 0 && tb->cx > 0) tb->cx--;
3046 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
3049 tb->dirty_flags |= DIRTY_ALL;
3051 /* Text is changed */
3057 * Delete or insert string
3059 static void add_keyword(text_body_type *tb, int flg)
3063 /* Some lines are selected */
3066 by1 = MIN(tb->my, tb->cy);
3067 by2 = MAX(tb->my, tb->cy);
3070 /* No mark -- Select current line */
3071 else /* if (!tb->mark) */
3077 /* Set/Reset flag of each line */
3078 for (y = by1; y <= by2; y++)
3080 autopick_type an_entry, *entry = &an_entry;
3082 if (!autopick_new_entry(entry, tb->lines_list[y], FALSE)) continue;
3084 /* There is the flag already */
3087 /* Free memory for the entry */
3088 autopick_free_entry(entry);
3093 string_free(tb->lines_list[y]);
3095 /* Remove all noun flag */
3096 if (FLG_NOUN_BEGIN <= flg && flg <= FLG_NOUN_END)
3099 for (i = FLG_NOUN_BEGIN; i <= FLG_NOUN_END; i++)
3105 tb->lines_list[y] = autopick_line_from_entry_kill(entry);
3108 tb->dirty_flags |= DIRTY_ALL;
3110 /* Text is changed */
3117 * Check if this line is expression or not.
3118 * And update it if it is.
3120 static void check_expression_line(text_body_type *tb, int y)
3122 cptr s = tb->lines_list[y];
3124 if ((s[0] == '?' && s[1] == ':') ||
3125 (tb->states[y] & LSTAT_BYPASS))
3127 /* Expressions need re-evaluation */
3128 tb->dirty_flags |= DIRTY_EXPRESSION;
3134 * Insert return code and split the line
3136 static bool insert_return_code(text_body_type *tb)
3138 char buf[MAX_LINELEN];
3141 for (k = 0; tb->lines_list[k]; k++)
3142 /* count number of lines */ ;
3144 if (k >= MAX_LINES - 2) return FALSE;
3147 /* Move down lines */
3148 for (; tb->cy < k; k--)
3150 tb->lines_list[k+1] = tb->lines_list[k];
3151 tb->states[k+1] = tb->states[k];
3154 /* Split current line */
3155 for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
3158 if (iskanji(tb->lines_list[tb->cy][i]))
3159 buf[j++] = tb->lines_list[tb->cy][i++];
3161 buf[j++] = tb->lines_list[tb->cy][i];
3164 tb->lines_list[tb->cy+1] = string_make(&tb->lines_list[tb->cy][i]);
3165 string_free(tb->lines_list[tb->cy]);
3166 tb->lines_list[tb->cy] = string_make(buf);
3168 /* Expressions need re-evaluation */
3169 tb->dirty_flags |= DIRTY_EXPRESSION;
3171 /* Text is changed */
3179 * Choose an item and get auto-picker entry from it.
3181 static object_type *choose_object(cptr q, cptr s)
3185 if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EQUIP))) return NULL;
3187 /* Get the item (in the pack) */
3188 if (item >= 0) return &inventory[item];
3190 /* Get the item (on the floor) */
3191 else return &o_list[0 - item];
3196 * Choose an item and get auto-picker entry from it.
3198 static bool entry_from_choosed_object(autopick_type *entry)
3205 q = "¤É¤Î¥¢¥¤¥Æ¥à¤òÅÐÏ¿¤·¤Þ¤¹¤«? ";
3206 s = "¥¢¥¤¥Æ¥à¤ò»ý¤Ã¤Æ¤¤¤Ê¤¤¡£";
3208 q = "Enter which item? ";
3209 s = "You have nothing to enter.";
3211 o_ptr = choose_object(q, s);
3212 if (!o_ptr) return FALSE;
3214 autopick_entry_from_object(entry, o_ptr);
3220 * Choose an item for search
3222 static byte get_object_for_search(object_type **o_handle, cptr *search_strp)
3224 char buf[MAX_NLEN+20];
3230 q = "¤É¤Î¥¢¥¤¥Æ¥à¤ò¸¡º÷¤·¤Þ¤¹¤«? ";
3231 s = "¥¢¥¤¥Æ¥à¤ò»ý¤Ã¤Æ¤¤¤Ê¤¤¡£";
3233 q = "Enter which item? ";
3234 s = "You have nothing to enter.";
3236 o_ptr = choose_object(q, s);
3237 if (!o_ptr) return 0;
3241 string_free(*search_strp);
3242 object_desc(buf, *o_handle, FALSE, 3);
3243 *search_strp = string_make(format("<%s>", buf));
3249 * Prepare for search by destroyed object
3251 static byte get_destroyed_object_for_search(object_type **o_handle, cptr *search_strp)
3253 char buf[MAX_NLEN+20];
3255 if (!autopick_last_destroyed_object.k_idx) return 0;
3257 *o_handle = &autopick_last_destroyed_object;
3259 string_free(*search_strp);
3260 object_desc(buf, *o_handle, FALSE, 3);
3261 *search_strp = string_make(format("<%s>", buf));
3267 * Choose an item or string for search
3269 static byte get_string_for_search(object_type **o_handle, cptr *search_strp)
3275 * TERM_YELLOW : Overwrite mode
3276 * TERM_WHITE : Insert mode
3278 byte color = TERM_YELLOW;
3279 char buf[MAX_NLEN+20];
3283 char prompt[] = "¸¡º÷(^I:»ý¤Áʪ ^L:Ç˲õ¤µ¤ì¤¿Êª): ";
3285 char prompt[] = "Search key(^I:inven ^L:destroyed): ";
3287 int col = sizeof(prompt) - 1;
3289 /* Prepare string buffer for edit */
3290 if (*search_strp) strcpy(buf, *search_strp);
3293 /* Object searching mode */
3296 color = TERM_L_GREEN;
3299 /* Display prompt */
3309 /* Display the string */
3310 Term_erase(col, 0, 255);
3311 Term_putstr(col, 0, -1, color, buf);
3314 Term_gotoxy(col + pos, 0);
3316 /* Get a special key code */
3317 skey = inkey_special();
3319 /* Analyze the key */
3327 /* Now on insert mode */
3330 /* No move at beginning of line */
3331 if (0 == pos) break;
3335 int next_pos = i + 1;
3338 if (iskanji(buf[i])) next_pos++;
3341 /* Is there the cursor at next position? */
3342 if (next_pos >= pos) break;
3348 /* Get previous position */
3356 /* Now on insert mode */
3359 /* No move at end of line */
3360 if ('\0' == buf[pos]) break;
3364 if (iskanji(buf[pos])) pos += 2;
3382 if (*o_handle) return (back ? -1 : 1);
3383 string_free(*search_strp);
3384 *search_strp = string_make(buf);
3386 return (back ? -1 : 1);
3390 return get_object_for_search(o_handle, search_strp);
3393 /* Prepare string for destroyed object if there is one. */
3394 if (get_destroyed_object_for_search(o_handle, search_strp))
3404 /* Now on insert mode */
3407 /* No move at beginning of line */
3408 if (0 == pos) break;
3412 int next_pos = i + 1;
3415 if (iskanji(buf[i])) next_pos++;
3418 /* Is there the cursor at next position? */
3419 if (next_pos >= pos) break;
3425 /* Get previous position */
3428 /* Fall through to 'Delete key' */
3437 /* Now on insert mode */
3440 /* No move at end of line */
3441 if ('\0' == buf[pos]) break;
3443 /* Position of next character */
3447 /* Next character is one more byte away */
3448 if (iskanji(buf[pos])) src++;
3453 /* Move characters at src to dst */
3454 while ('\0' != (buf[dst++] = buf[src++]))
3462 /* Insert a character */
3467 /* Ignore special keys */
3468 if (skey & SKEY_MASK) break;
3470 /* Get a character code */
3473 /* Was non insert mode? */
3474 if (color != TERM_WHITE)
3476 /* Was object searching mode */
3477 if (color == TERM_L_GREEN)
3479 /* Cancel the mode */
3482 /* Remove indicating string */
3483 string_free(*search_strp);
3484 *search_strp = NULL;
3487 /* Overwrite default string */
3490 /* Go to insert mode */
3494 /* Save right part of string */
3495 strcpy(tmp, buf + pos);
3501 /* Bypass macro processing */
3519 if (pos < len && (isprint(c) || iskana(c)))
3521 if (pos < len && isprint(c))
3535 /* Write back the left part of string */
3536 my_strcat(buf, tmp, len + 1);
3543 /* Object searching mode was cancelled? */
3544 if (*o_handle && color != TERM_L_GREEN)
3546 /* Cancel the mode */
3549 /* Remove indicating string */
3551 string_free(*search_strp);
3552 *search_strp = NULL;
3557 } /* while (TRUE) */
3562 * Search next line matches for o_ptr
3564 static void search_for_object(text_body_type *tb, object_type *o_ptr, bool forward)
3566 autopick_type an_entry, *entry = &an_entry;
3567 char o_name[MAX_NLEN];
3568 int bypassed_cy = -1;
3570 /* Start searching from current cursor position */
3573 /* Prepare object name string first */
3574 object_desc(o_name, o_ptr, FALSE, 3);
3576 /* Convert the string to lower case */
3577 str_tolower(o_name);
3584 if (!tb->lines_list[++i]) break;
3591 /* Is this line is a correct entry? */
3592 if (!autopick_new_entry(entry, tb->lines_list[i], FALSE)) continue;
3594 /* Does this line match to the object? */
3595 if (!is_autopick_aux(o_ptr, entry, o_name)) continue;
3598 /* Found a line but it's inactive */
3599 if (tb->states[i] & LSTAT_BYPASS)
3601 /* If it is first found, remember it */
3602 if (bypassed_cy == -1) bypassed_cy = i;
3605 /* Found an active line! */
3608 /* Move to this line */
3612 if (bypassed_cy != -1)
3614 /* Mark as some lines are skipped */
3615 tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
3623 if (bypassed_cy != -1)
3625 /* Move to the remembered line */
3627 tb->cy = bypassed_cy;
3629 /* Mark as this line is inactive */
3630 tb->dirty_flags |= DIRTY_INACTIVE;
3635 /* Mark as NOT FOUND */
3636 tb->dirty_flags |= DIRTY_NOT_FOUND;
3644 * Search next line matches to the string
3646 static void search_for_string(text_body_type *tb, cptr search_str, bool forward)
3648 int bypassed_cy = -1;
3649 int bypassed_cx = 0;
3651 /* Start searching from current cursor position */
3661 if (!tb->lines_list[++i]) break;
3668 /* Look for the string pattern */
3669 pos = my_strstr(tb->lines_list[i], search_str);
3674 /* Found a line but it's inactive */
3675 if ((tb->states[i] & LSTAT_BYPASS) &&
3676 !(tb->states[i] & LSTAT_EXPRESSION))
3678 /* If it is first found, remember it */
3679 if (bypassed_cy == -1)
3682 bypassed_cx = (int)(pos - tb->lines_list[i]);
3686 /* Found an active line! */
3689 /* Move to this location */
3690 tb->cx = (int)(pos - tb->lines_list[i]);
3693 if (bypassed_cy != -1)
3695 /* Mark as some lines are skipped */
3696 tb->dirty_flags |= DIRTY_SKIP_INACTIVE;
3704 if (bypassed_cy != -1)
3706 /* Move to the remembered line */
3707 tb->cx = bypassed_cx;
3708 tb->cy = bypassed_cy;
3710 /* Mark as this line is inactive */
3711 tb->dirty_flags |= DIRTY_INACTIVE;
3716 /* Mark as NOT FOUND */
3717 tb->dirty_flags |= DIRTY_NOT_FOUND;
3727 * Editor command id's
3730 #define EC_SAVEQUIT 2
3741 #define EC_PGDOWN 13
3743 #define EC_BOTTOM 15
3748 #define EC_KILL_LINE 20
3749 #define EC_DELETE_CHAR 21
3750 #define EC_BACKSPACE 22
3751 #define EC_SEARCH_STR 23
3752 #define EC_SEARCH_FORW 24
3753 #define EC_SEARCH_BACK 25
3754 #define EC_SEARCH_OBJ 26
3755 #define EC_SEARCH_DESTROYED 27
3756 #define EC_INSERT_OBJECT 28
3757 #define EC_INSERT_DESTROYED 29
3758 #define EC_INSERT_BLOCK 30
3759 #define EC_INSERT_MACRO 31
3760 #define EC_INSERT_KEYMAP 32
3761 #define EC_CL_AUTOPICK 33
3762 #define EC_CL_DESTROY 34
3763 #define EC_CL_LEAVE 35
3764 #define EC_CL_QUERY 36
3765 #define EC_CL_NO_DISP 37
3766 #define EC_OK_COLLECTING 38
3767 #define EC_IK_UNAWARE 39
3768 #define EC_IK_UNIDENTIFIED 40
3769 #define EC_IK_IDENTIFIED 41
3770 #define EC_IK_STAR_IDENTIFIED 42
3771 #define EC_OK_BOOSTED 43
3772 #define EC_OK_MORE_DICE 44
3773 #define EC_OK_MORE_BONUS 45
3774 #define EC_OK_WORTHLESS 46
3775 #define EC_OK_ARTIFACT 47
3776 #define EC_OK_EGO 48
3777 #define EC_OK_NAMELESS 49
3778 #define EC_OK_RARE 50
3779 #define EC_OK_COMMON 51
3780 #define EC_OK_WANTED 52
3781 #define EC_OK_UNIQUE 53
3782 #define EC_OK_HUMAN 54
3783 #define EC_OK_UNREADABLE 55
3784 #define EC_OK_REALM1 56
3785 #define EC_OK_REALM2 57
3786 #define EC_OK_FIRST 58
3787 #define EC_OK_SECOND 59
3788 #define EC_OK_THIRD 60
3789 #define EC_OK_FOURTH 61
3790 #define EC_KK_WEAPONS 62
3791 #define EC_KK_FAVORITE_WEAPONS 63
3792 #define EC_KK_ARMORS 64
3793 #define EC_KK_MISSILES 65
3794 #define EC_KK_DEVICES 66
3795 #define EC_KK_LIGHTS 67
3796 #define EC_KK_JUNKS 68
3797 #define EC_KK_CORPSES 69
3798 #define EC_KK_SPELLBOOKS 70
3799 #define EC_KK_SHIELDS 71
3800 #define EC_KK_BOWS 72
3801 #define EC_KK_RINGS 73
3802 #define EC_KK_AMULETS 74
3803 #define EC_KK_SUITS 75
3804 #define EC_KK_CLOAKS 76
3805 #define EC_KK_HELMS 77
3806 #define EC_KK_GLOVES 78
3807 #define EC_KK_BOOTS 79
3813 #define MN_QUIT "¥»¡¼¥Ö̵¤·¤Ç½ªÎ»"
3814 #define MN_SAVEQUIT "¥»¡¼¥Ö¤·¤Æ½ªÎ»"
3815 #define MN_REVERT "Á´¤Æ¤ÎÊѹ¹¤òÇË´þ"
3816 #define MN_HELP "¥Ø¥ë¥×"
3818 #define MN_MOVE "¥«¡¼¥½¥ë°ÜÆ°"
3819 #define MN_LEFT "º¸ (¢«Ìð°õ¥¡¼)"
3820 #define MN_DOWN "²¼ (¢Ìð°õ¥¡¼)"
3821 #define MN_UP "¾å (¢¬Ìð°õ¥¡¼)"
3822 #define MN_RIGHT "±¦ (¢ªÌð°õ¥¡¼)"
3823 #define MN_BOL "¹Ô¤ÎÀèƬ"
3824 #define MN_EOL "¹Ô¤Î½ªÃ¼"
3825 #define MN_PGUP "¾å¤Î¥Ú¡¼¥¸ (PageUp¥¡¼)"
3826 #define MN_PGDOWN "²¼¤Î¥Ú¡¼¥¸ (PageDown¥¡¼)"
3827 #define MN_TOP "1¹ÔÌܤذÜÆ° (Home¥¡¼)"
3828 #define MN_BOTTOM "ºÇ²¼¹Ô¤Ø°ÜÆ°(End¥¡¼)"
3830 #define MN_EDIT "ÊÔ½¸"
3831 #define MN_CUT "¥«¥Ã¥È"
3832 #define MN_COPY "¥³¥Ô¡¼"
3833 #define MN_PASTE "¥Ú¡¼¥¹¥È"
3834 #define MN_BLOCK "ÁªÂòÈϰϤλØÄê"
3835 #define MN_KILL_LINE "¹Ô¤Î»Ä¤ê¤òºï½ü"
3836 #define MN_DELETE_CHAR "1ʸ»úºï½ü"
3837 #define MN_BACKSPACE "¥Ð¥Ã¥¯¥¹¥Ú¡¼¥¹"
3838 #define MN_RETURN "²þ¹Ô"
3839 #define MN_RETURN "²þ¹Ô"
3841 #define MN_SEARCH "¸¡º÷"
3842 #define MN_SEARCH_STR "ʸ»úÎó¤Ç¸¡º÷"
3843 #define MN_SEARCH_FORW "Á°Êý¤ØºÆ¸¡º÷"
3844 #define MN_SEARCH_BACK "¸åÊý¤ØºÆ¸¡º÷"
3845 #define MN_SEARCH_OBJ "¥¢¥¤¥Æ¥à¤òÁªÂò¤·¤Æ¸¡º÷"
3846 #define MN_SEARCH_DESTROYED "¼«Æ°Ç˲õ¤µ¤ì¤¿¥¢¥¤¥Æ¥à¤Ç¸¡º÷"
3848 #define MN_INSERT "¿§¡¹ÁÞÆþ"
3849 #define MN_INSERT_OBJECT "ÁªÂò¤·¤¿¥¢¥¤¥Æ¥à¤Î̾Á°¤òÁÞÆþ"
3850 #define MN_INSERT_DESTROYED "¼«Æ°Ç˲õ¤µ¤ì¤¿¥¢¥¤¥Æ¥à¤Î̾Á°¤òÁÞÆþ"
3851 #define MN_INSERT_BLOCK "¾ò·ïʬ´ô¥Ö¥í¥Ã¥¯¤ÎÎã¤òÁÞÆþ"
3852 #define MN_INSERT_MACRO "¥Þ¥¯¥íÄêµÁ¤òÁÞÆþ"
3853 #define MN_INSERT_KEYMAP "¥¡¼¥Þ¥Ã¥×ÄêµÁ¤òÁÞÆþ"
3856 #define MN_COMMAND_LETTER "½¦¤¤/Ç˲õ/\x95\xfaÃÖ¤ÎÁªÂò"
3858 #define MN_COMMAND_LETTER "½¦¤¤/Ç˲õ/ÊüÃÖ¤ÎÁªÂò"
3860 #define MN_CL_AUTOPICK "¡Ö ¡× (¼«Æ°½¦¤¤)"
3861 #define MN_CL_DESTROY "¡Ö!¡× (¼«Æ°Ç˲õ)"
3863 #define MN_CL_LEAVE "¡Ö~¡× (\x95\xfaÃÖ)"
3865 #define MN_CL_LEAVE "¡Ö~¡× (ÊüÃÖ)"
3867 #define MN_CL_QUERY "¡Ö;¡× (³Îǧ¤·¤Æ½¦¤¦)"
3868 #define MN_CL_NO_DISP "¡Ö(¡× (¥Þ¥Ã¥×¥³¥Þ¥ó¥É¤Çɽ¼¨¤·¤Ê¤¤)"
3870 #define MN_ADJECTIVE_GEN "·ÁÍÆ»ì(°ìÈÌ)¤ÎÁªÂò"
3872 #define MN_ADJECTIVE_SPECIAL "·ÁÍÆ»ì(Æüì)¤ÎÁªÂò"
3873 #define MN_BOOSTED "¥À¥¤¥¹Ìܤΰ㤦 (Éð´ï)"
3874 #define MN_MORE_DICE "¥À¥¤¥¹ÌÜ # °Ê¾å¤Î (Éð´ï)"
3875 #define MN_MORE_BONUS "½¤ÀµÃÍ # °Ê¾å¤Î (»ØÎØÅù)"
3876 #define MN_ARTIFACT "¥¢¡¼¥Æ¥£¥Õ¥¡¥¯¥È (ÁõÈ÷)"
3877 #define MN_EGO "¥¨¥´ (ÁõÈ÷)"
3878 #define MN_NAMELESS "̵ÌäΠ(ÁõÈ÷)"
3879 #define MN_RARE "¥ì¥¢¤Ê (ÁõÈ÷)"
3880 #define MN_COMMON "¤¢¤ê¤Õ¤ì¤¿ (ÁõÈ÷)"
3881 #define MN_WANTED "¾Þ¶â¼ó¤Î (»àÂÎ)"
3882 #define MN_UNIQUE "¥æ¥Ë¡¼¥¯¡¦¥â¥ó¥¹¥¿¡¼¤Î (»àÂÎ)"
3883 #define MN_HUMAN "¿Í´Ö¤Î (»àÂÎ)"
3884 #define MN_UNREADABLE "Æɤá¤Ê¤¤ (ËâË¡½ñ)"
3885 #define MN_REALM1 "Âè°ìÎΰè¤Î (ËâË¡½ñ)"
3886 #define MN_REALM2 "ÂèÆóÎΰè¤Î (ËâË¡½ñ)"
3887 #define MN_FIRST "1ºýÌܤΠ(ËâË¡½ñ)"
3888 #define MN_SECOND "2ºýÌܤΠ(ËâË¡½ñ)"
3889 #define MN_THIRD "3ºýÌܤΠ(ËâË¡½ñ)"
3890 #define MN_FOURTH "4ºýÌܤΠ(ËâË¡½ñ)"
3892 #define MN_NOUN "̾»ì¤ÎÁªÂò"
3896 #define MN_QUIT "Quit without save"
3897 #define MN_SAVEQUIT "Save & Quit"
3898 #define MN_REVERT "Revert all changes"
3899 #define MN_HELP "Help"
3901 #define MN_MOVE "Move cursor"
3902 #define MN_LEFT "Left (Left Arrow key)"
3903 #define MN_DOWN "Down (Down Arrow key)"
3904 #define MN_UP "Up (Up Arrow key)"
3905 #define MN_RIGHT "Right (Right Arrow key)"
3906 #define MN_BOL "Beggining of line"
3907 #define MN_EOL "End of line"
3908 #define MN_PGUP "Page up (PageUp key)"
3909 #define MN_PGDOWN "Page down(PageDown key)"
3910 #define MN_TOP "Top (Home key)"
3911 #define MN_BOTTOM "Bottom (End key)"
3913 #define MN_EDIT "Edit"
3914 #define MN_CUT "Cut"
3915 #define MN_COPY "Copy"
3916 #define MN_PASTE "Paste"
3917 #define MN_BLOCK "Select block"
3918 #define MN_KILL_LINE "Kill rest of line"
3919 #define MN_DELETE_CHAR "Delete character"
3920 #define MN_BACKSPACE "Backspace"
3921 #define MN_RETURN "Return"
3922 #define MN_RETURN "Return"
3924 #define MN_SEARCH "Search"
3925 #define MN_SEARCH_STR "Search by string"
3926 #define MN_SEARCH_FORW "Search forward"
3927 #define MN_SEARCH_BACK "Search backward"
3928 #define MN_SEARCH_OBJ "Search by inventory object"
3929 #define MN_SEARCH_DESTROYED "Search by destroyed object"
3931 #define MN_INSERT "Insert..."
3932 #define MN_INSERT_OBJECT "Insert name of choosen object"
3933 #define MN_INSERT_DESTROYED "Insert name of destroyed object"
3934 #define MN_INSERT_BLOCK "Insert conditional block"
3935 #define MN_INSERT_MACRO "Insert a macro definition"
3936 #define MN_INSERT_KEYMAP "Insert a keymap definition"
3938 #define MN_COMMAND_LETTER "Command letter"
3939 #define MN_CL_AUTOPICK "' ' (Auto pick)"
3940 #define MN_CL_DESTROY "'!' (Auto destroy)"
3941 #define MN_CL_LEAVE "'~' (Leave it on the floor)"
3942 #define MN_CL_QUERY "';' (Query to pick up)"
3943 #define MN_CL_NO_DISP "'(' (No display on the large map)"
3945 #define MN_ADJECTIVE_GEN "Adjective (general)"
3947 #define MN_ADJECTIVE_SPECIAL "Adjective (special)"
3948 #define MN_BOOSTED "dice boosted (weapons)"
3949 #define MN_MORE_DICE "more than # dice (weapons)"
3950 #define MN_MORE_BONUS "more bonus than # (rings etc.)"
3951 #define MN_ARTIFACT "artifact (equipments)"
3952 #define MN_EGO "ego (equipments)"
3953 #define MN_NAMELESS "nameless (equipments)"
3954 #define MN_RARE "rare (equipments)"
3955 #define MN_COMMON "common (equipments)"
3956 #define MN_WANTED "wanted (corpse)"
3957 #define MN_UNIQUE "unique (corpse)"
3958 #define MN_HUMAN "human (corpse)"
3959 #define MN_UNREADABLE "unreadable (spellbooks)"
3960 #define MN_REALM1 "realm1 (spellbooks)"
3961 #define MN_REALM2 "realm2 (spellbooks)"
3962 #define MN_FIRST "first (spellbooks)"
3963 #define MN_SECOND "second (spellbooks)"
3964 #define MN_THIRD "third (spellbooks)"
3965 #define MN_FOURTH "fourth (spellbooks)"
3967 #define MN_NOUN "Keywords (noun)"
3977 } command_menu_type;
3980 command_menu_type menu_data[] =
3982 {MN_HELP, 0, -1, EC_HELP},
3983 {MN_QUIT, 0, KTRL('q'), EC_QUIT},
3984 {MN_SAVEQUIT, 0, KTRL('w'), EC_SAVEQUIT},
3985 {MN_REVERT, 0, KTRL('z'), EC_REVERT},
3987 {MN_EDIT, 0, -1, -1},
3988 {MN_CUT, 1, KTRL('x'), EC_CUT},
3989 {MN_COPY, 1, KTRL('c'), EC_COPY},
3990 {MN_PASTE, 1, KTRL('v'), EC_PASTE},
3991 {MN_BLOCK, 1, KTRL('g'), EC_BLOCK},
3992 {MN_KILL_LINE, 1, KTRL('k'), EC_KILL_LINE},
3993 {MN_DELETE_CHAR, 1, KTRL('d'), EC_DELETE_CHAR},
3994 {MN_BACKSPACE, 1, KTRL('h'), EC_BACKSPACE},
3995 {MN_RETURN, 1, KTRL('j'), EC_RETURN},
3996 {MN_RETURN, 1, KTRL('m'), EC_RETURN},
3998 {MN_SEARCH, 0, -1, -1},
3999 {MN_SEARCH_STR, 1, KTRL('s'), EC_SEARCH_STR},
4000 {MN_SEARCH_FORW, 1, -1, EC_SEARCH_FORW},
4001 {MN_SEARCH_BACK, 1, KTRL('r'), EC_SEARCH_BACK},
4002 {MN_SEARCH_OBJ, 1, KTRL('y'), EC_SEARCH_OBJ},
4003 {MN_SEARCH_DESTROYED, 1, -1, EC_SEARCH_DESTROYED},
4005 {MN_MOVE, 0, -1, -1},
4006 {MN_LEFT, 1, KTRL('b'), EC_LEFT},
4007 {MN_DOWN, 1, KTRL('n'), EC_DOWN},
4008 {MN_UP, 1, KTRL('p'), EC_UP},
4009 {MN_RIGHT, 1, KTRL('f'), EC_RIGHT},
4010 {MN_BOL, 1, KTRL('a'), EC_BOL},
4011 {MN_EOL, 1, KTRL('e'), EC_EOL},
4012 {MN_PGUP, 1, KTRL('o'), EC_PGUP},
4013 {MN_PGDOWN, 1, KTRL('l'), EC_PGDOWN},
4014 {MN_TOP, 1, KTRL('t'), EC_TOP},
4015 {MN_BOTTOM, 1, KTRL('u'), EC_BOTTOM},
4017 {MN_INSERT, 0, -1, -1},
4018 {MN_INSERT_OBJECT, 1, KTRL('i'), EC_INSERT_OBJECT},
4019 {MN_INSERT_DESTROYED, 1, -1, EC_INSERT_DESTROYED},
4020 {MN_INSERT_BLOCK, 1, -1, EC_INSERT_BLOCK},
4021 {MN_INSERT_MACRO, 1, -1, EC_INSERT_MACRO},
4022 {MN_INSERT_KEYMAP, 1, -1, EC_INSERT_KEYMAP},
4024 {MN_ADJECTIVE_GEN, 0, -1, -1},
4025 {KEY_UNAWARE, 1, -1, EC_IK_UNAWARE},
4026 {KEY_UNIDENTIFIED, 1, -1, EC_IK_UNIDENTIFIED},
4027 {KEY_IDENTIFIED, 1, -1, EC_IK_IDENTIFIED},
4028 {KEY_STAR_IDENTIFIED, 1, -1, EC_IK_STAR_IDENTIFIED},
4029 {KEY_COLLECTING, 1, -1, EC_OK_COLLECTING},
4030 {KEY_WORTHLESS, 1, -1, EC_OK_WORTHLESS},
4032 {MN_ADJECTIVE_SPECIAL, 0, -1, -1},
4033 {MN_BOOSTED, 1, -1, EC_OK_BOOSTED},
4034 {MN_MORE_DICE, 1, -1, EC_OK_MORE_DICE},
4035 {MN_MORE_BONUS, 1, -1, EC_OK_MORE_BONUS},
4036 {MN_ARTIFACT, 1, -1, EC_OK_ARTIFACT},
4037 {MN_EGO, 1, -1, EC_OK_EGO},
4038 {MN_NAMELESS, 1, -1, EC_OK_NAMELESS},
4039 {MN_RARE, 1, -1, EC_OK_RARE},
4040 {MN_COMMON, 1, -1, EC_OK_COMMON},
4041 {MN_WANTED, 1, -1, EC_OK_WANTED},
4042 {MN_UNIQUE, 1, -1, EC_OK_UNIQUE},
4043 {MN_HUMAN, 1, -1, EC_OK_HUMAN},
4044 {MN_UNREADABLE, 1, -1, EC_OK_UNREADABLE},
4045 {MN_REALM1, 1, -1, EC_OK_REALM1},
4046 {MN_REALM2, 1, -1, EC_OK_REALM2},
4047 {MN_FIRST, 1, -1, EC_OK_FIRST},
4048 {MN_SECOND, 1, -1, EC_OK_SECOND},
4049 {MN_THIRD, 1, -1, EC_OK_THIRD},
4050 {MN_FOURTH, 1, -1, EC_OK_FOURTH},
4052 {MN_NOUN, 0, -1, -1},
4053 {KEY_WEAPONS, 1, -1, EC_KK_WEAPONS},
4054 {KEY_FAVORITE_WEAPONS, 1, -1, EC_KK_FAVORITE_WEAPONS},
4055 {KEY_ARMORS, 1, -1, EC_KK_ARMORS},
4056 {KEY_MISSILES, 1, -1, EC_KK_MISSILES},
4057 {KEY_DEVICES, 1, -1, EC_KK_DEVICES},
4058 {KEY_LIGHTS, 1, -1, EC_KK_LIGHTS},
4059 {KEY_JUNKS, 1, -1, EC_KK_JUNKS},
4060 {KEY_CORPSES, 1, -1, EC_KK_CORPSES},
4061 {KEY_SPELLBOOKS, 1, -1, EC_KK_SPELLBOOKS},
4062 {KEY_SHIELDS, 1, -1, EC_KK_SHIELDS},
4063 {KEY_BOWS, 1, -1, EC_KK_BOWS},
4064 {KEY_RINGS, 1, -1, EC_KK_RINGS},
4065 {KEY_AMULETS, 1, -1, EC_KK_AMULETS},
4066 {KEY_SUITS, 1, -1, EC_KK_SUITS},
4067 {KEY_CLOAKS, 1, -1, EC_KK_CLOAKS},
4068 {KEY_HELMS, 1, -1, EC_KK_HELMS},
4069 {KEY_GLOVES, 1, -1, EC_KK_GLOVES},
4070 {KEY_BOOTS, 1, -1, EC_KK_BOOTS},
4072 {MN_COMMAND_LETTER, 0, -1, -1},
4073 {MN_CL_AUTOPICK, 1, -1, EC_CL_AUTOPICK},
4074 {MN_CL_DESTROY, 1, -1, EC_CL_DESTROY},
4075 {MN_CL_LEAVE, 1, -1, EC_CL_LEAVE},
4076 {MN_CL_QUERY, 1, -1, EC_CL_QUERY},
4077 {MN_CL_NO_DISP, 1, -1, EC_CL_NO_DISP},
4079 {MN_DELETE_CHAR, -1, 0x7F, EC_DELETE_CHAR},
4086 * Find a command by 'key'.
4088 static int get_com_id(char key)
4092 for (i = 0; menu_data[i].name; i++)
4094 if (menu_data[i].key == key)
4096 return menu_data[i].com_id;
4105 * Display the menu, and get a command
4107 static int do_command_menu(int level, int start)
4112 int col0 = 5 + level*7;
4113 int row0 = 1 + level*3;
4115 int menu_id_list[26];
4117 char linestr[MAX_LINELEN];
4119 /* Get max length */
4121 for (i = start; menu_data[i].level >= level; i++)
4125 /* Ignore lower level sub menus */
4126 if (menu_data[i].level > level) continue;
4128 len = strlen(menu_data[i].name);
4129 if (len > max_len) max_len = len;
4131 menu_id_list[menu_key] = i;
4135 while (menu_key < 26)
4137 menu_id_list[menu_key] = -1;
4141 /* Extra space for displaying menu key and command key */
4142 max_menu_wid = max_len + 3 + 3;
4144 /* Prepare box line */
4146 strcat(linestr, "+");
4147 for (i = 0; i < max_menu_wid + 2; i++)
4149 strcat(linestr, "-");
4151 strcat(linestr, "+");
4161 int row1 = row0 + 1;
4164 Term_putstr(col0, row0, -1, TERM_WHITE, linestr);
4166 /* Draw menu items */
4168 for (i = start; menu_data[i].level >= level; i++)
4170 char com_key_str[3];
4173 /* Ignore lower level sub menus */
4174 if (menu_data[i].level > level) continue;
4176 if (menu_data[i].com_id == -1)
4179 strcpy(com_key_str, "¢§");
4181 strcpy(com_key_str, ">");
4184 else if (menu_data[i].key != -1)
4186 com_key_str[0] = '^';
4187 com_key_str[1] = menu_data[i].key + '@';
4188 com_key_str[2] = '\0';
4192 com_key_str[0] = '\0';
4195 str = format("| %c) %-*s %2s | ", menu_key + 'a', max_len, menu_data[i].name, com_key_str);
4197 Term_putstr(col0, row1++, -1, TERM_WHITE, str);
4202 /* Draw bottom line */
4203 Term_putstr(col0, row1, -1, TERM_WHITE, linestr);
4205 /* The menu was shown */
4209 prt(format("(a-%c) ¥³¥Þ¥ó¥É:", menu_key + 'a' - 1), 0, 0);
4211 prt(format("(a-%c) Command:", menu_key + 'a' - 1), 0, 0);
4215 if (key == ESCAPE) return 0;
4217 if ('a' <= key && key <= 'z')
4219 menu_id = menu_id_list[key - 'a'];
4223 com_id = menu_data[menu_id].com_id;
4227 com_id = do_command_menu(level + 1, menu_id + 1);
4229 if (com_id) return com_id;
4241 com_id = get_com_id(key);
4242 if (com_id) return com_id;
4249 static chain_str_type *new_chain_str(cptr str)
4251 chain_str_type *chain;
4253 size_t len = strlen(str);
4255 chain = (chain_str_type *)ralloc(sizeof(chain_str_type) + len * sizeof(char));
4257 strcpy(chain->s, str);
4264 static void kill_yank_chain(text_body_type *tb)
4266 chain_str_type *chain = tb->yank;
4268 tb->yank_eol = TRUE;
4272 chain_str_type *next = chain->next;
4273 size_t len = strlen(chain->s);
4275 rnfree(chain, sizeof(chain_str_type) + len * sizeof(char));
4282 static void add_str_to_yank(text_body_type *tb, cptr str)
4284 chain_str_type *chain;
4286 tb->yank_eol = FALSE;
4288 if (NULL == tb->yank)
4290 tb->yank = new_chain_str(str);
4300 chain->next = new_chain_str(str);
4305 chain = chain->next;
4310 #define DESCRIPT_HGT 3
4315 static void draw_text_editor(text_body_type *tb)
4318 int by1 = 0, by2 = 0;
4321 Term_get_size(&tb->wid, &tb->hgt);
4324 * Top line (-1), description line (-3), separator (-1)
4327 tb->hgt -= 2 + DESCRIPT_HGT;
4330 /* Don't let cursor at second byte of kanji */
4331 for (i = 0; tb->lines_list[tb->cy][i]; i++)
4332 if (iskanji(tb->lines_list[tb->cy][i]))
4343 /* Scroll if necessary */
4344 if (tb->cy < tb->upper || tb->upper + tb->hgt <= tb->cy)
4345 tb->upper = tb->cy - (tb->hgt)/2;
4348 if ((tb->cx < tb->left + 10 && tb->left > 0) || tb->left + tb->wid - 5 <= tb->cx)
4349 tb->left = tb->cx - (tb->wid)*2/3;
4353 /* Redraw whole window after resize */
4354 if (tb->old_wid != tb->wid || tb->old_hgt != tb->hgt)
4355 tb->dirty_flags |= DIRTY_SCREEN;
4357 /* Redraw all text after scroll */
4358 else if (tb->old_upper != tb->upper || tb->old_left != tb->left)
4359 tb->dirty_flags |= DIRTY_ALL;
4362 if (tb->dirty_flags & DIRTY_SCREEN)
4364 tb->dirty_flags |= (DIRTY_ALL | DIRTY_MODE);
4370 /* Redraw mode line */
4371 if (tb->dirty_flags & DIRTY_MODE)
4373 char buf[MAX_LINELEN];
4375 int sepa_length = tb->wid;
4378 for (i = 0; i < sepa_length; i++)
4382 Term_putstr(0, tb->hgt + 1, sepa_length, TERM_WHITE, buf);
4385 if (tb->dirty_flags & DIRTY_EXPRESSION)
4390 for (y = 0; tb->lines_list[y]; y++)
4394 cptr s = tb->lines_list[y];
4396 /* Update this line's state */
4397 tb->states[y] = state;
4399 if (*s++ != '?') continue;
4400 if (*s++ != ':') continue;
4402 /* Lines below this line are auto-registered */
4403 if (streq(s, "$AUTOREGISTER"))
4404 state |= LSTAT_AUTOREGISTER;
4406 /* Parse the expr */
4407 v = process_pref_file_expr(&s, &f);
4410 if (streq(v, "0")) state |= LSTAT_BYPASS;
4411 else state &= ~LSTAT_BYPASS;
4413 /* Re-update this line's state */
4414 tb->states[y] = state | LSTAT_EXPRESSION;
4417 tb->dirty_flags |= DIRTY_ALL;
4422 int tmp_cx = tb->cx;
4423 int len = strlen(tb->lines_list[tb->cy]);
4425 /* Correct cursor location */
4426 if (tb->cx > len) tmp_cx = len;
4428 tb->dirty_flags |= DIRTY_ALL;
4430 by1 = MIN(tb->my, tb->cy);
4431 by2 = MAX(tb->my, tb->cy);
4434 /* Dump up to tb->hgt lines of messages */
4435 for (i = 0; i < tb->hgt; i++)
4441 int y = tb->upper+i;
4443 /* clean or dirty? */
4444 if (!(tb->dirty_flags & DIRTY_ALL) && (tb->dirty_line != y))
4447 msg = tb->lines_list[y];
4450 /* Apply horizontal scroll */
4451 for (j = 0; *msg; msg++, j++)
4453 if (j == tb->left) break;
4469 Term_erase(0, i + 1, tb->wid);
4471 if (tb->states[y] & LSTAT_AUTOREGISTER)
4473 /* Warning color -- These lines will be deleted later */
4478 /* Bypassed line will be displayed by darker color */
4479 if (tb->states[y] & LSTAT_BYPASS) color = TERM_SLATE;
4480 else color = TERM_WHITE;
4483 /* No mark or Out of mark */
4484 if (!tb->mark || (y < by1 || by2 < y))
4486 /* Dump the messages, bottom to top */
4487 Term_putstr(leftcol, i + 1, tb->wid - 1, color, msg);
4490 /* Multiple lines selected */
4491 else if (by1 != by2)
4493 /* Dump the messages, bottom to top */
4494 Term_putstr(leftcol, i + 1, tb->wid - 1, TERM_YELLOW, msg);
4497 /* Single line selected */
4500 int x0 = leftcol + tb->left;
4501 int len = strlen(tb->lines_list[tb->cy]);
4502 int bx1 = MIN(tb->mx, tb->cx);
4503 int bx2 = MAX(tb->mx, tb->cx);
4505 /* Correct cursor location */
4506 if (bx2 > len) bx2 = len;
4508 Term_gotoxy(leftcol, i + 1);
4509 if (x0 < bx1) Term_addstr(bx1 - x0, color, msg);
4510 if (x0 < bx2) Term_addstr(bx2 - bx1, TERM_YELLOW, msg + (bx1 - x0));
4511 Term_addstr(-1, color, msg + (bx2 - x0));
4515 for (; i < tb->hgt; i++)
4518 Term_erase(0, i + 1, tb->wid);
4521 /* Display information when updated */
4522 if (tb->old_cy != tb->cy || (tb->dirty_flags & (DIRTY_ALL | DIRTY_NOT_FOUND | DIRTY_NO_SEARCH)) || tb->dirty_line == tb->cy)
4524 autopick_type an_entry, *entry = &an_entry;
4525 cptr str1 = NULL, str2 = NULL;
4528 /* Clear information line */
4529 for (i = 0; i < DESCRIPT_HGT; i++)
4532 Term_erase(0, tb->hgt + 2 + i, tb->wid);
4535 /* Display information */
4536 if (tb->dirty_flags & DIRTY_NOT_FOUND)
4539 str1 = format("¥Ñ¥¿¡¼¥ó¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó: %s", tb->search_str);
4541 str1 = format("Pattern not found: %s", tb->search_str);
4544 else if (tb->dirty_flags & DIRTY_SKIP_INACTIVE)
4547 str1 = format("̵¸ú¾õÂ֤ιԤò¥¹¥¥Ã¥×¤·¤Þ¤·¤¿¡£(%s¤ò¸¡º÷Ãæ)", tb->search_str);
4549 str1 = format("Some inactive lines are skipped. (Searching %s)", tb->search_str);
4552 else if (tb->dirty_flags & DIRTY_INACTIVE)
4555 str1 = format("̵¸ú¾õÂ֤ιԤÀ¤±¤¬¸«ÉÕ¤«¤ê¤Þ¤·¤¿¡£(%s¤ò¸¡º÷Ãæ)", tb->search_str);
4557 str1 = format("Found only an inactive line. (Searching %s)", tb->search_str);
4560 else if (tb->dirty_flags & DIRTY_NO_SEARCH)
4563 str1 = "¸¡º÷¤¹¤ë¥Ñ¥¿¡¼¥ó¤¬¤¢¤ê¤Þ¤»¤ó(^S ¤Ç¸¡º÷)¡£";
4565 str1 = "No pattern to search. (Press ^S to search.)";
4568 else if (tb->lines_list[tb->cy][0] == '#')
4571 str1 = "¤³¤Î¹Ô¤Ï¥³¥á¥ó¥È¤Ç¤¹¡£";
4573 str1 = "This line is a comment.";
4576 else if (tb->lines_list[tb->cy][1] == ':')
4578 switch(tb->lines_list[tb->cy][0])
4582 str1 = "¤³¤Î¹Ô¤Ï¾ò·ïʬ´ô¼°¤Ç¤¹¡£";
4584 str1 = "This line is a Conditional Expression.";
4590 str1 = "¤³¤Î¹Ô¤Ï¥Þ¥¯¥í¤Î¼Â¹ÔÆâÍƤòÄêµÁ¤·¤Þ¤¹¡£";
4592 str1 = "This line defines a Macro action.";
4597 str1 = "¤³¤Î¹Ô¤Ï¥Þ¥¯¥í¤Î¥È¥ê¥¬¡¼¡¦¥¡¼¤òÄêµÁ¤·¤Þ¤¹¡£";
4599 str1 = "This line defines a Macro trigger key.";
4604 str1 = "¤³¤Î¹Ô¤Ï¥¡¼ÇÛÃÖ¤òÄêµÁ¤·¤Þ¤¹¡£";
4606 str1 = "This line defines a Keymap.";
4611 switch(tb->lines_list[tb->cy][0])
4614 if (tb->states[tb->cy] & LSTAT_BYPASS)
4617 str2 = "¸½ºß¤Î¼°¤ÎÃͤϡֵ¶(=0)¡×¤Ç¤¹¡£";
4619 str2 = "The expression is 'False'(=0) currently.";
4625 str2 = "¸½ºß¤Î¼°¤ÎÃͤϡֿ¿(=1)¡×¤Ç¤¹¡£";
4627 str2 = "The expression is 'True'(=1) currently.";
4633 if (tb->states[tb->cy] & LSTAT_AUTOREGISTER)
4636 str2 = "¤³¤Î¹Ô¤Ï¸å¤Çºï½ü¤µ¤ì¤Þ¤¹¡£";
4638 str2 = "This line will be delete later.";
4642 else if (tb->states[tb->cy] & LSTAT_BYPASS)
4645 str2 = "¤³¤Î¹Ô¤Ï¸½ºß¤Ï̵¸ú¤Ê¾õÂ֤Ǥ¹¡£";
4647 str2 = "This line is bypassed currently.";
4654 /* Get description of an autopicker preference line */
4655 else if (autopick_new_entry(entry, tb->lines_list[tb->cy], FALSE))
4657 char buf[MAX_LINELEN];
4658 char temp[MAX_LINELEN];
4661 describe_autopick(buf, entry);
4663 if (tb->states[tb->cy] & LSTAT_AUTOREGISTER)
4666 strcat(buf, "¤³¤Î¹Ô¤Ï¸å¤Çºï½ü¤µ¤ì¤Þ¤¹¡£");
4668 strcat(buf, " This line will be delete later.");
4672 if (tb->states[tb->cy] & LSTAT_BYPASS)
4675 strcat(buf, "¤³¤Î¹Ô¤Ï¸½ºß¤Ï̵¸ú¤Ê¾õÂ֤Ǥ¹¡£");
4677 strcat(buf, " This line is bypassed currently.");
4681 roff_to_buf(buf, 81, temp, sizeof(temp));
4683 for (i = 0; i < 3; i++)
4689 prt(t, tb->hgt +1 + 1 + i, 0);
4693 autopick_free_entry(entry);
4696 /* Draw the first line */
4697 if (str1) prt(str1, tb->hgt +1 + 1, 0);
4699 /* Draw the second line */
4700 if (str2) prt(str2, tb->hgt +1 + 2, 0);
4706 * Kill segment of a line
4708 static void kill_line_segment(text_body_type *tb, int y, int x0, int x1, bool whole)
4710 char buf[MAX_LINELEN];
4711 cptr s = tb->lines_list[y];
4715 /* Kill whole line? */
4716 if (whole && x0 == 0 && s[x1] == '\0' && tb->lines_list[y+1])
4720 string_free(tb->lines_list[y]);
4722 /* Shift lines up */
4723 for (i = y; tb->lines_list[i+1]; i++)
4724 tb->lines_list[i] = tb->lines_list[i+1];
4725 tb->lines_list[i] = NULL;
4727 /* Expressions need re-evaluation */
4728 tb->dirty_flags |= DIRTY_EXPRESSION;
4734 if (x0 == x1) return;
4736 /* Before the segment */
4737 for (x = 0; x < x0; x++)
4740 /* After the segment */
4741 for (x = x1; s[x]; x++)
4747 string_free(tb->lines_list[y]);
4748 tb->lines_list[y] = string_make(buf);
4750 /* Expressions may need re-evaluation */
4751 check_expression_line(tb, y);
4753 /* Text is changed */
4759 * Get a trigger key and insert ASCII string for the trigger
4761 static bool insert_macro_line(text_body_type *tb)
4770 /* Do not process macros */
4776 /* Read the pattern */
4782 /* Do not process macros */
4785 /* Do not wait for keys */
4788 /* Attempt to read a key */
4798 /* Convert the trigger */
4799 ascii_to_text(tmp, buf);
4802 if(!tmp[0]) return FALSE;
4806 /* Insert preference string */
4807 insert_return_code(tb);
4808 string_free(tb->lines_list[tb->cy]);
4809 tb->lines_list[tb->cy] = string_make(format("P:%s", tmp));
4811 /* Acquire action */
4812 i = macro_find_exact(buf);
4816 /* Nothing defined */
4821 /* Analyze the current action */
4822 ascii_to_text(tmp, macro__act[i]);
4825 /* Insert blank action preference line */
4826 insert_return_code(tb);
4827 string_free(tb->lines_list[tb->cy]);
4828 tb->lines_list[tb->cy] = string_make(format("A:%s", tmp));
4835 * Get a command key and insert ASCII string for the key
4837 static bool insert_keymap_line(text_body_type *tb)
4845 if (rogue_like_commands)
4847 mode = KEYMAP_MODE_ROGUE;
4853 mode = KEYMAP_MODE_ORIG;
4866 /* Convert the trigger */
4867 ascii_to_text(tmp, buf);
4870 if(!tmp[0]) return FALSE;
4874 /* Insert preference string */
4875 insert_return_code(tb);
4876 string_free(tb->lines_list[tb->cy]);
4877 tb->lines_list[tb->cy] = string_make(format("C:%d:%s", mode, tmp));
4879 /* Look up the keymap */
4880 act = keymap_act[mode][(byte)(buf[0])];
4882 /* Insert blank action preference line */
4883 insert_return_code(tb);
4884 string_free(tb->lines_list[tb->cy]);
4885 tb->lines_list[tb->cy] = string_make(format("A:%s", act));
4892 * Execute a single editor command
4894 static bool do_editor_command(text_body_type *tb, int com_id)
4902 if (!get_check("Á´¤Æ¤ÎÊѹ¹¤òÇË´þ¤·¤Æ¤«¤é½ªÎ»¤·¤Þ¤¹¡£¤è¤í¤·¤¤¤Ç¤¹¤«¡© ")) break;
4904 if (!get_check("Discard all changes and quit. Are you sure? ")) break;
4907 return QUIT_WITHOUT_SAVE;
4910 return QUIT_AND_SAVE;
4913 /* Revert to original */
4915 if (!get_check("Á´¤Æ¤ÎÊѹ¹¤òÇË´þ¤·¤Æ¸µ¤Î¾õÂÖ¤ËÌᤷ¤Þ¤¹¡£¤è¤í¤·¤¤¤Ç¤¹¤«¡© ")) break;
4917 if (!get_check("Discard all changes and revert to original file. Are you sure? ")) break;
4920 free_text_lines(tb->lines_list);
4921 tb->lines_list = read_pickpref_text_lines(&tb->filename_mode);
4922 tb->dirty_flags |= DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
4923 tb->cx = tb->cy = 0;
4926 /* Text is not changed */
4927 tb->changed = FALSE;
4931 /* Peruse the main help file */
4933 (void)show_file(TRUE, "jeditor.txt", NULL, 0, 0);
4935 (void)show_file(TRUE, "editor.txt", NULL, 0, 0);
4938 tb->dirty_flags |= DIRTY_SCREEN;
4943 /* Split a line or insert end of line */
4945 /* Ignore selection */
4951 tb->dirty_flags |= DIRTY_ALL;
4954 insert_return_code(tb);
4959 tb->dirty_flags |= DIRTY_ALL;
4969 len = strlen(tb->lines_list[tb->cy]);
4970 if (len < tb->cx) tb->cx = len;
4972 else if (tb->cy > 0)
4975 tb->cx = strlen(tb->lines_list[tb->cy]);
4981 if (tb->lines_list[tb->cy + 1]) tb->cy++;
4986 if (tb->cy > 0) tb->cy--;
4995 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
4998 len = strlen(tb->lines_list[tb->cy]);
5001 if (tb->lines_list[tb->cy + 1])
5013 /* Beginning of line */
5019 tb->cx = strlen(tb->lines_list[tb->cy]);
5023 while (0 < tb->cy && tb->upper <= tb->cy)
5025 while (0 < tb->upper && tb->cy + 1 < tb->upper + tb->hgt)
5031 while (tb->cy < tb->upper + tb->hgt && tb->lines_list[tb->cy + 1])
5041 while (tb->lines_list[tb->cy + 1])
5047 /* Copy the text first */
5048 do_editor_command(tb, EC_COPY);
5050 /* Single line case */
5051 if (tb->my == tb->cy)
5053 int bx1 = MIN(tb->mx, tb->cx);
5054 int bx2 = MAX(tb->mx, tb->cx);
5055 int len = strlen(tb->lines_list[tb->cy]);
5057 /* Correct fake cursor position */
5058 if (bx2 > len) bx2 = len;
5060 kill_line_segment(tb, tb->cy, bx1, bx2, TRUE);
5062 /* New cursor position */
5066 /* Multiple lines case */
5067 else /* if (tb->my != tb->cy) */
5071 int by1 = MIN(tb->my, tb->cy);
5072 int by2 = MAX(tb->my, tb->cy);
5074 /* Kill lines in reverse order */
5075 for (y = by2; y >= by1; y--)
5077 int len = strlen(tb->lines_list[y]);
5079 kill_line_segment(tb, y, 0, len, TRUE);
5082 /* New cursor position */
5088 /* Disable selection */
5092 tb->dirty_flags |= DIRTY_ALL;
5099 int len = strlen(tb->lines_list[tb->cy]);
5101 /* Correct cursor location */
5102 if (tb->cx > len) tb->cx = len;
5104 /* Use single line? */
5107 /* Select a single line */
5113 /* Kill old yank buffer */
5114 kill_yank_chain(tb);
5117 /* Single line case */
5118 if (tb->my == tb->cy)
5121 char buf[MAX_LINELEN];
5122 int bx1 = MIN(tb->mx, tb->cx);
5123 int bx2 = MAX(tb->mx, tb->cx);
5125 /* Correct fake cursor position */
5126 if (bx2 > len) bx2 = len;
5128 /* Whole part of this line is selected */
5129 if (bx1 == 0 && bx2 == len)
5131 /* Copy this line */
5132 add_str_to_yank(tb, tb->lines_list[tb->cy]);
5134 /* Add end of line to the buffer */
5135 add_str_to_yank(tb, "");
5138 /* Segment of this line is selected */
5141 for (i = 0; i < bx2 - bx1; i++)
5143 buf[i] = tb->lines_list[tb->cy][bx1 + i];
5147 /* Copy this segment of line */
5148 add_str_to_yank(tb, buf);
5152 /* Multiple lines case */
5153 else /* if (tb->my != tb->cy) */
5157 int by1 = MIN(tb->my, tb->cy);
5158 int by2 = MAX(tb->my, tb->cy);
5161 for (y = by1; y <= by2; y++)
5163 /* Copy this line */
5164 add_str_to_yank(tb, tb->lines_list[y]);
5167 /* Add final end of line to the buffer */
5168 add_str_to_yank(tb, "");
5171 /* Disable selection */
5175 tb->dirty_flags |= DIRTY_ALL;
5181 /* Paste killed text */
5183 chain_str_type *chain = tb->yank;
5184 int len = strlen(tb->lines_list[tb->cy]);
5186 /* Nothing to do? */
5189 /* Correct cursor location */
5190 if (tb->cx > len) tb->cx = len;
5192 /* Ignore selection */
5198 tb->dirty_flags |= DIRTY_ALL;
5204 cptr yank_str = chain->s;
5206 char buf[MAX_LINELEN];
5208 char rest[MAX_LINELEN], *rest_ptr = rest;
5210 /* Save preceding string */
5211 for(i = 0; i < tb->cx; i++)
5212 buf[i] = tb->lines_list[tb->cy][i];
5214 strcpy(rest, &(tb->lines_list[tb->cy][i]));
5216 /* Paste yank buffer */
5217 while (*yank_str && i < MAX_LINELEN-1)
5219 buf[i++] = *yank_str++;
5225 chain = chain->next;
5227 if (chain || tb->yank_eol)
5229 /* There is an end of line between chain nodes */
5231 insert_return_code(tb);
5233 /* Replace this line with new one */
5234 string_free(tb->lines_list[tb->cy]);
5235 tb->lines_list[tb->cy] = string_make(buf);
5237 /* Move to next line */
5244 /* Final line doesn't have end of line */
5246 tb->cx = strlen(buf);
5248 /* Rest of original line */
5249 while (*rest_ptr && i < MAX_LINELEN-1)
5251 buf[i++] = *rest_ptr++;
5257 /* Replace this line with new one */
5258 string_free(tb->lines_list[tb->cy]);
5259 tb->lines_list[tb->cy] = string_make(buf);
5266 tb->dirty_flags |= DIRTY_ALL;
5268 /* Expressions need re-evaluation */
5269 tb->dirty_flags |= DIRTY_EXPRESSION;
5271 /* Text is changed */
5280 /* Disable the selection */
5284 tb->dirty_flags |= DIRTY_ALL;
5288 tb->mark = MARK_MARK;
5290 /* Repeating this command swaps cursor position */
5291 if (com_id == tb->old_com_id)
5303 tb->dirty_flags |= DIRTY_ALL;
5307 int len = strlen(tb->lines_list[tb->cy]);
5309 /* Mark the point 1 */
5313 /* Correct cursor location */
5314 if (tb->cx > len) tb->mx = len;
5321 /* Kill rest of line */
5323 int len = strlen(tb->lines_list[tb->cy]);
5325 /* Correct cursor location */
5326 if (tb->cx > len) tb->cx = len;
5328 /* Ignore selection */
5334 tb->dirty_flags |= DIRTY_ALL;
5337 /* Append only if this command is repeated. */
5338 if (tb->old_com_id != com_id)
5340 kill_yank_chain(tb);
5344 /* Really deleted some text */
5347 /* Add deleted string to yank buffer */
5348 add_str_to_yank(tb, &(tb->lines_list[tb->cy][tb->cx]));
5350 kill_line_segment(tb, tb->cy, tb->cx, len, FALSE);
5353 tb->dirty_line = tb->cy;
5355 /* Leave end of line character */
5359 /* Cut the end of line character only */
5360 if (tb->yank_eol) add_str_to_yank(tb, "");
5362 /* Cut end of line */
5363 tb->yank_eol = TRUE;
5365 do_editor_command(tb, EC_DELETE_CHAR);
5369 case EC_DELETE_CHAR:
5370 /* DELETE == go forward + BACK SPACE */
5372 /* Ignore selection */
5378 tb->dirty_flags |= DIRTY_ALL;
5382 if (iskanji(tb->lines_list[tb->cy][tb->cx])) tb->cx++;
5386 do_editor_command(tb, EC_BACKSPACE);
5394 char buf[MAX_LINELEN];
5396 /* Ignore selection */
5402 tb->dirty_flags |= DIRTY_ALL;
5405 len = strlen(tb->lines_list[tb->cy]);
5408 if (tb->lines_list[tb->cy + 1])
5422 /* delete a return code and union two lines */
5423 if (tb->cy == 0) break;
5424 tb->cx = strlen(tb->lines_list[tb->cy-1]);
5425 strcpy(buf, tb->lines_list[tb->cy-1]);
5426 strcat(buf, tb->lines_list[tb->cy]);
5427 string_free(tb->lines_list[tb->cy-1]);
5428 string_free(tb->lines_list[tb->cy]);
5429 tb->lines_list[tb->cy-1] = string_make(buf);
5431 for (i = tb->cy; tb->lines_list[i+1]; i++)
5432 tb->lines_list[i] = tb->lines_list[i+1];
5434 tb->lines_list[i] = NULL;
5438 tb->dirty_flags |= DIRTY_ALL;
5440 /* Expressions need re-evaluation */
5441 tb->dirty_flags |= DIRTY_EXPRESSION;
5443 /* Text is changed */
5449 for (i = j = k = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
5453 if (iskanji(tb->lines_list[tb->cy][i]))
5454 buf[j++] = tb->lines_list[tb->cy][i++];
5456 buf[j++] = tb->lines_list[tb->cy][i];
5463 for (; tb->lines_list[tb->cy][i]; i++)
5464 buf[j++] = tb->lines_list[tb->cy][i];
5466 string_free(tb->lines_list[tb->cy]);
5467 tb->lines_list[tb->cy] = string_make(buf);
5470 tb->dirty_line = tb->cy;
5472 /* Expressions may need re-evaluation */
5473 check_expression_line(tb, tb->cy);
5475 /* Text is changed */
5485 /* Become dirty because of item/equip menu */
5486 tb->dirty_flags |= DIRTY_SCREEN;
5488 search_dir = get_string_for_search(&tb->search_o_ptr, &tb->search_str);
5490 if (!search_dir) break;
5492 if (search_dir == 1) do_editor_command(tb, EC_SEARCH_FORW);
5493 else do_editor_command(tb, EC_SEARCH_BACK);
5497 case EC_SEARCH_FORW:
5498 if (tb->search_o_ptr)
5500 search_for_object(tb, tb->search_o_ptr, TRUE);
5502 else if (tb->search_str && tb->search_str[0])
5504 search_for_string(tb, tb->search_str, TRUE);
5508 tb->dirty_flags |= DIRTY_NO_SEARCH;
5512 case EC_SEARCH_BACK:
5513 if (tb->search_o_ptr)
5515 search_for_object(tb, tb->search_o_ptr, FALSE);
5517 else if (tb->search_str && tb->search_str[0])
5519 search_for_string(tb, tb->search_str, FALSE);
5523 tb->dirty_flags |= DIRTY_NO_SEARCH;
5528 /* Become dirty because of item/equip menu */
5529 tb->dirty_flags |= DIRTY_SCREEN;
5531 if (!get_object_for_search(&tb->search_o_ptr, &tb->search_str)) break;
5533 do_editor_command(tb, EC_SEARCH_FORW);
5536 case EC_SEARCH_DESTROYED:
5537 if (!get_destroyed_object_for_search(&tb->search_o_ptr, &tb->search_str))
5539 /* There is no object to search */
5540 tb->dirty_flags |= DIRTY_NO_SEARCH;
5545 do_editor_command(tb, EC_SEARCH_FORW);
5548 case EC_INSERT_OBJECT:
5550 /* Insert choosen item name */
5552 autopick_type an_entry, *entry = &an_entry;
5554 if (!entry_from_choosed_object(entry))
5556 /* Now dirty because of item/equip menu */
5557 tb->dirty_flags |= DIRTY_SCREEN;
5562 insert_return_code(tb);
5563 string_free(tb->lines_list[tb->cy]);
5564 tb->lines_list[tb->cy] = autopick_line_from_entry_kill(entry);
5566 /* Now dirty because of item/equip menu */
5567 tb->dirty_flags |= DIRTY_SCREEN;
5572 case EC_INSERT_DESTROYED:
5573 /* Insert a name of last destroyed item */
5574 if (tb->last_destroyed)
5577 insert_return_code(tb);
5578 string_free(tb->lines_list[tb->cy]);
5579 tb->lines_list[tb->cy] = string_make(tb->last_destroyed);
5582 tb->dirty_flags |= DIRTY_ALL;
5584 /* Text is changed */
5589 case EC_INSERT_BLOCK:
5591 /* Insert a conditinal expression line */
5592 char expression[80];
5594 /* Conditional Expression for Class and Race */
5595 sprintf(expression, "?:[AND [EQU $RACE %s] [EQU $CLASS %s] [GEQ $LEVEL %02d]]",
5597 rp_ptr->E_title, cp_ptr->E_title,
5599 rp_ptr->title, cp_ptr->title,
5605 insert_return_code(tb);
5606 string_free(tb->lines_list[tb->cy]);
5607 tb->lines_list[tb->cy] = string_make(expression);
5609 insert_return_code(tb);
5610 string_free(tb->lines_list[tb->cy]);
5611 tb->lines_list[tb->cy] = string_make("?:1");
5614 tb->dirty_flags |= DIRTY_ALL;
5616 /* Text is changed */
5622 case EC_INSERT_MACRO:
5623 /* Draw_everythig (delete menu) */
5624 draw_text_editor(tb);
5627 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
5631 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, "P:<¥È¥ê¥¬¡¼¥¡¼>: ");
5633 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, "P:<Trigger key>: ");
5635 if (insert_macro_line(tb))
5637 /* Prepare to input action */
5641 tb->dirty_flags |= DIRTY_ALL;
5643 /* Text is changed */
5649 case EC_INSERT_KEYMAP:
5650 /* Draw_everythig (delete menu) */
5651 draw_text_editor(tb);
5654 Term_erase(0, tb->cy - tb->upper + 1, tb->wid);
5658 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, format("C:%d:<¥³¥Þ¥ó¥É¥¡¼>: ", (rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG)));
5660 Term_putstr(0, tb->cy - tb->upper + 1, tb->wid - 1, TERM_YELLOW, format("C:%d:<Keypress>: ", (rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG)));
5663 if (insert_keymap_line(tb))
5665 /* Prepare to input action */
5669 tb->dirty_flags |= DIRTY_ALL;
5671 /* Text is changed */
5676 case EC_CL_AUTOPICK: toggle_command_letter(tb, DO_AUTOPICK); break;
5677 case EC_CL_DESTROY: toggle_command_letter(tb, DO_AUTODESTROY); break;
5678 case EC_CL_LEAVE: toggle_command_letter(tb, DONT_AUTOPICK); break;
5679 case EC_CL_QUERY: toggle_command_letter(tb, DO_QUERY_AUTOPICK); break;
5680 case EC_CL_NO_DISP: toggle_command_letter(tb, DO_DISPLAY); break;
5682 case EC_IK_UNAWARE: toggle_keyword(tb, FLG_UNAWARE); break;
5683 case EC_IK_UNIDENTIFIED: toggle_keyword(tb, FLG_UNIDENTIFIED); break;
5684 case EC_IK_IDENTIFIED: toggle_keyword(tb, FLG_IDENTIFIED); break;
5685 case EC_IK_STAR_IDENTIFIED: toggle_keyword(tb, FLG_STAR_IDENTIFIED); break;
5686 case EC_KK_WEAPONS: toggle_keyword(tb, FLG_WEAPONS); break;
5687 case EC_KK_FAVORITE_WEAPONS: toggle_keyword(tb, FLG_FAVORITE_WEAPONS); break;
5688 case EC_KK_ARMORS: toggle_keyword(tb, FLG_ARMORS); break;
5689 case EC_KK_MISSILES: toggle_keyword(tb, FLG_MISSILES); break;
5690 case EC_KK_DEVICES: toggle_keyword(tb, FLG_DEVICES); break;
5691 case EC_KK_LIGHTS: toggle_keyword(tb, FLG_LIGHTS); break;
5692 case EC_KK_JUNKS: toggle_keyword(tb, FLG_JUNKS); break;
5693 case EC_KK_CORPSES: toggle_keyword(tb, FLG_CORPSES); break;
5694 case EC_KK_SPELLBOOKS: toggle_keyword(tb, FLG_SPELLBOOKS); break;
5695 case EC_KK_SHIELDS: toggle_keyword(tb, FLG_SHIELDS); break;
5696 case EC_KK_BOWS: toggle_keyword(tb, FLG_BOWS); break;
5697 case EC_KK_RINGS: toggle_keyword(tb, FLG_RINGS); break;
5698 case EC_KK_AMULETS: toggle_keyword(tb, FLG_AMULETS); break;
5699 case EC_KK_SUITS: toggle_keyword(tb, FLG_SUITS); break;
5700 case EC_KK_CLOAKS: toggle_keyword(tb, FLG_CLOAKS); break;
5701 case EC_KK_HELMS: toggle_keyword(tb, FLG_HELMS); break;
5702 case EC_KK_GLOVES: toggle_keyword(tb, FLG_GLOVES); break;
5703 case EC_KK_BOOTS: toggle_keyword(tb, FLG_BOOTS); break;
5704 case EC_OK_COLLECTING: toggle_keyword(tb, FLG_COLLECTING); break;
5705 case EC_OK_BOOSTED: toggle_keyword(tb, FLG_BOOSTED); break;
5706 case EC_OK_MORE_DICE: toggle_keyword(tb, FLG_MORE_DICE); break;
5707 case EC_OK_MORE_BONUS: toggle_keyword(tb, FLG_MORE_BONUS); break;
5708 case EC_OK_WORTHLESS: toggle_keyword(tb, FLG_WORTHLESS); break;
5709 case EC_OK_ARTIFACT: toggle_keyword(tb, FLG_ARTIFACT); break;
5710 case EC_OK_EGO: toggle_keyword(tb, FLG_EGO); break;
5711 case EC_OK_NAMELESS: toggle_keyword(tb, FLG_NAMELESS); break;
5712 case EC_OK_RARE: toggle_keyword(tb, FLG_RARE); break;
5713 case EC_OK_COMMON: toggle_keyword(tb, FLG_COMMON); break;
5714 case EC_OK_WANTED: toggle_keyword(tb, FLG_WANTED); break;
5715 case EC_OK_UNIQUE: toggle_keyword(tb, FLG_UNIQUE); break;
5716 case EC_OK_HUMAN: toggle_keyword(tb, FLG_HUMAN); break;
5717 case EC_OK_UNREADABLE:
5718 toggle_keyword(tb, FLG_UNREADABLE);
5719 add_keyword(tb, FLG_SPELLBOOKS);
5722 toggle_keyword(tb, FLG_REALM1);
5723 add_keyword(tb, FLG_SPELLBOOKS);
5726 toggle_keyword(tb, FLG_REALM2);
5727 add_keyword(tb, FLG_SPELLBOOKS);
5730 toggle_keyword(tb, FLG_FIRST);
5731 add_keyword(tb, FLG_SPELLBOOKS);
5734 toggle_keyword(tb, FLG_SECOND);
5735 add_keyword(tb, FLG_SPELLBOOKS);
5738 toggle_keyword(tb, FLG_THIRD);
5739 add_keyword(tb, FLG_SPELLBOOKS);
5742 toggle_keyword(tb, FLG_FOURTH);
5743 add_keyword(tb, FLG_SPELLBOOKS);
5747 /* Save old command */
5748 tb->old_com_id = com_id;
5755 * Insert single letter at cursor position.
5757 static void insert_single_letter(text_body_type *tb, int key)
5760 char buf[MAX_LINELEN];
5762 /* Save preceding string */
5763 for (i = j = 0; tb->lines_list[tb->cy][i] && i < tb->cx; i++)
5764 buf[j++] = tb->lines_list[tb->cy][i];
5766 /* Add a character */
5774 if (j+2 < MAX_LINELEN)
5786 if (j+1 < MAX_LINELEN)
5792 for (; tb->lines_list[tb->cy][i] && j + 1 < MAX_LINELEN; i++)
5793 buf[j++] = tb->lines_list[tb->cy][i];
5796 /* Replace current line with new line */
5797 string_free(tb->lines_list[tb->cy]);
5798 tb->lines_list[tb->cy] = string_make(buf);
5800 /* Move to correct collumn */
5801 len = strlen(tb->lines_list[tb->cy]);
5802 if (len < tb->cx) tb->cx = len;
5805 tb->dirty_line = tb->cy;
5807 /* Expressions may need re-evaluation */
5808 check_expression_line(tb, tb->cy);
5810 /* Text is changed */
5816 * Check special key code and get a movement command id
5818 static int analyze_move_key(text_body_type *tb, int skey)
5822 /* Not a special key */
5823 if (!(skey & SKEY_MASK)) return 0;
5825 /* Convert from a special key code to an editor command */
5826 switch(skey & ~SKEY_MOD_MASK)
5828 case SKEY_DOWN: com_id = EC_DOWN; break;
5829 case SKEY_LEFT: com_id = EC_LEFT; break;
5830 case SKEY_RIGHT: com_id = EC_RIGHT; break;
5831 case SKEY_UP: com_id = EC_UP; break;
5832 case SKEY_PGUP: com_id = EC_PGUP; break;
5833 case SKEY_PGDOWN: com_id = EC_PGDOWN; break;
5834 case SKEY_TOP: com_id = EC_TOP; break;
5835 case SKEY_BOTTOM: com_id = EC_BOTTOM; break;
5838 /* Not a special movement key */
5842 /* Without shift modifier */
5843 if (!(skey & SKEY_MOD_SHIFT))
5846 * Un-shifted cursor keys cancells
5847 * selection created by shift+cursor.
5849 if (tb->mark & MARK_BY_SHIFT)
5854 tb->dirty_flags |= DIRTY_ALL;
5858 /* With shift modifier */
5861 /* Start selection by shift + cursor keys */
5864 int len = strlen(tb->lines_list[tb->cy]);
5866 tb->mark = MARK_MARK | MARK_BY_SHIFT;
5870 /* Correct cursor location */
5871 if (tb->cx > len) tb->mx = len;
5873 /* Need to redraw text */
5874 if (com_id == EC_UP || com_id == EC_DOWN)
5876 /* Redraw all text */
5877 tb->dirty_flags |= DIRTY_ALL;
5881 tb->dirty_line = tb->cy;
5890 * In-game editor of Object Auto-picker/Destoryer
5892 void do_cmd_edit_autopick(void)
5894 static int cx_save = 0;
5895 static int cy_save = 0;
5897 text_body_type text_body, *tb = &text_body;
5899 autopick_type an_entry, *entry = &an_entry;
5900 char buf[MAX_LINELEN];
5905 static s32b old_autosave_turn = 0L;
5908 tb->changed = FALSE;
5911 tb->upper = tb->left = 0;
5913 tb->mx = tb->my = 0;
5914 tb->old_cy = tb->old_upper = tb->old_left = -1;
5915 tb->old_wid = tb->old_hgt = -1;
5919 tb->search_o_ptr = NULL;
5920 tb->search_str = NULL;
5921 tb->last_destroyed = NULL;
5922 tb->dirty_flags = DIRTY_ALL | DIRTY_MODE | DIRTY_EXPRESSION;
5923 tb->dirty_line = -1;
5924 tb->filename_mode = PT_DEFAULT;
5927 if (turn > old_autosave_turn + 100L)
5929 do_cmd_save_game(TRUE);
5930 old_autosave_turn = turn;
5933 /* HACK -- Reset start_time to stop counting playtime while edit */
5936 /* Free old entries */
5939 /* Command Description of the 'Last Destroyed Item' */
5940 if (autopick_last_destroyed_object.k_idx)
5942 autopick_entry_from_object(entry, &autopick_last_destroyed_object);
5943 tb->last_destroyed = autopick_line_from_entry_kill(entry);
5946 /* Read or initialize whole text */
5947 tb->lines_list = read_pickpref_text_lines(&tb->filename_mode);
5949 /* Reset cursor position if needed */
5950 for (i = 0; i < tb->cy; i++)
5952 if (!tb->lines_list[i])
5954 tb->cy = tb->cx = 0;
5959 /* Save the screen */
5962 /* Process requests until done */
5967 /* Draw_everythig */
5968 draw_text_editor(tb);
5970 /* Display header line */
5972 prt("(^Q:½ªÎ» ^W:¥»¡¼¥Ö¤·¤Æ½ªÎ», ESC:¥á¥Ë¥å¡¼, ¤½¤Î¾:ÆþÎÏ)", 0, 0);
5974 prt("(^Q:Quit, ^W:Save&Quit, ESC:Menu, Other:Input text)", 0, 0);
5978 /* Display current position */
5979 prt (format("(%d,%d)", tb->cx, tb->cy), 0, 60);
5983 /* Display current position and mark position */
5984 prt (format("(%d,%d)-(%d,%d)", tb->mx, tb->my, tb->cx, tb->cy), 0, 60);
5988 Term_gotoxy(tb->cx - tb->left, tb->cy - tb->upper + 1);
5991 tb->dirty_flags = 0;
5992 tb->dirty_line = -1;
5994 /* Save old key and location */
5995 tb->old_cy = tb->cy;
5996 tb->old_upper = tb->upper;
5997 tb->old_left = tb->left;
5998 tb->old_wid = tb->wid;
5999 tb->old_hgt = tb->hgt;
6002 key = inkey_special();
6005 if (key & SKEY_MASK)
6007 /* Get a movement command */
6008 com_id = analyze_move_key(tb, key);
6012 else if (key == ESCAPE)
6014 com_id = do_command_menu(0, 0);
6016 /* Redraw all text later */
6017 tb->dirty_flags |= DIRTY_SCREEN;
6020 /* Insert a character */
6021 else if (!iscntrl((unsigned char)key))
6023 /* Ignore selection */
6029 tb->dirty_flags |= DIRTY_ALL;
6032 insert_single_letter(tb, key);
6038 /* Other commands */
6041 com_id = get_com_id(key);
6044 if (com_id) quit = do_editor_command(tb, com_id);
6045 } /* while (TRUE) */
6047 /* Restore the screen */
6050 /* Get the filename of preference */
6051 strcpy(buf, pickpref_filename(tb->filename_mode));
6053 if (quit == QUIT_AND_SAVE)
6054 write_text_lines(buf, tb->lines_list);
6056 free_text_lines(tb->lines_list);
6058 string_free(tb->last_destroyed);
6060 /* Destroy string chain */
6061 kill_yank_chain(tb);
6063 /* Reload autopick pref */
6064 process_pickpref_file(buf);
6066 /* HACK -- reset start_time so that playtime is not increase while edit */
6067 start_time = time(NULL);
6069 /* Save cursor location */