OSDN Git Service

'~'の自動拾いリストからも使用している autopick_line_from_entry() の仕様を
[hengbandforosx/hengbandosx.git] / src / autopick.c
index ab3d047..14b8b5e 100644 (file)
 
 #include "angband.h"
 
+#define MAX_LINELEN 1024
+
+static object_type autopick_last_destroyed_object;
+
 /*
  * Macros for Keywords
  */
 #endif /* JP */
 
 #define MATCH_KEY(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\
+     ? (ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE)
+#define MATCH_KEY2(KEY) (!strncmp(ptr, KEY, sizeof(KEY)-1)\
      ? (prev_ptr = ptr, ptr += sizeof(KEY)-1, (' '==*ptr) ? ptr++ : 0, TRUE) : FALSE)
 
 #ifdef JP
 
 #define ADD_FLG(FLG) (entry->flag[FLG / 32] |= (1L << (FLG % 32)))
 #define REM_FLG(FLG) (entry->flag[FLG / 32] &= ~(1L << (FLG % 32)))
-#define ADD_FLG2(FLG) (entry->flag[FLG / 32] |= (1L << (FLG % 32)), prev_flg = FLG)
+#define ADD_FLG_NOUN(FLG) (ADD_FLG(FLG), prev_flg = FLG)
 #define IS_FLG(FLG) (entry->flag[FLG / 32] & (1L << (FLG % 32)))
 
 #ifdef JP
  */
 cptr autopick_line_from_entry(autopick_type *entry)
 {
-       char buf[1024];
+       char buf[MAX_LINELEN];
        char *ptr;
        bool sepa_flag = TRUE;
 
@@ -195,6 +201,7 @@ cptr autopick_line_from_entry(autopick_type *entry)
        if (IS_FLG(FLG_UNIDENTIFIED)) ADD_KEY(KEY_UNIDENTIFIED);
        if (IS_FLG(FLG_IDENTIFIED)) ADD_KEY(KEY_IDENTIFIED);
        if (IS_FLG(FLG_STAR_IDENTIFIED)) ADD_KEY(KEY_STAR_IDENTIFIED);
+       if (IS_FLG(FLG_UNAWARE)) ADD_KEY(KEY_UNAWARE);
        if (IS_FLG(FLG_BOOSTED)) ADD_KEY(KEY_BOOSTED);
 
        if (IS_FLG(FLG_MORE_THAN))
@@ -211,14 +218,6 @@ cptr autopick_line_from_entry(autopick_type *entry)
                ADD_KEY(KEY_MORE_BONUS2);
        }
 
-       if (IS_FLG(FLG_WORTHLESS)) ADD_KEY(KEY_WORTHLESS);
-       if (IS_FLG(FLG_ARTIFACT)) ADD_KEY(KEY_ARTIFACT);
-       if (IS_FLG(FLG_EGO)) ADD_KEY(KEY_EGO);
-       if (IS_FLG(FLG_NAMELESS)) ADD_KEY(KEY_NAMELESS);
-       if (IS_FLG(FLG_UNAWARE)) ADD_KEY(KEY_UNAWARE);
-       if (IS_FLG(FLG_WANTED)) ADD_KEY(KEY_WANTED);
-       if (IS_FLG(FLG_UNIQUE)) ADD_KEY(KEY_UNIQUE);
-       if (IS_FLG(FLG_HUMAN)) ADD_KEY(KEY_HUMAN);
        if (IS_FLG(FLG_UNREADABLE)) ADD_KEY(KEY_UNREADABLE);
        if (IS_FLG(FLG_REALM1)) ADD_KEY(KEY_REALM1);
        if (IS_FLG(FLG_REALM2)) ADD_KEY(KEY_REALM2);
@@ -226,6 +225,14 @@ cptr autopick_line_from_entry(autopick_type *entry)
        if (IS_FLG(FLG_SECOND)) ADD_KEY(KEY_SECOND);
        if (IS_FLG(FLG_THIRD)) ADD_KEY(KEY_THIRD);
        if (IS_FLG(FLG_FOURTH)) ADD_KEY(KEY_FOURTH);
+       if (IS_FLG(FLG_WANTED)) ADD_KEY(KEY_WANTED);
+       if (IS_FLG(FLG_UNIQUE)) ADD_KEY(KEY_UNIQUE);
+       if (IS_FLG(FLG_HUMAN)) ADD_KEY(KEY_HUMAN);
+       if (IS_FLG(FLG_WORTHLESS)) ADD_KEY(KEY_WORTHLESS);
+       if (IS_FLG(FLG_NAMELESS)) ADD_KEY(KEY_NAMELESS);
+       if (IS_FLG(FLG_EGO)) ADD_KEY(KEY_EGO);
+
+       if (IS_FLG(FLG_ARTIFACT)) ADD_KEY(KEY_ARTIFACT);
 
        if (IS_FLG(FLG_ITEMS)) ADD_KEY2(KEY_ITEMS);
        else if (IS_FLG(FLG_WEAPONS)) ADD_KEY2(KEY_WEAPONS);
@@ -245,14 +252,28 @@ cptr autopick_line_from_entry(autopick_type *entry)
        else if (IS_FLG(FLG_HELMS)) ADD_KEY2(KEY_HELMS);
        else if (IS_FLG(FLG_GLOVES)) ADD_KEY2(KEY_GLOVES);
        else if (IS_FLG(FLG_BOOTS)) ADD_KEY2(KEY_BOOTS);
-       else
+
+        /* You don't need sepalator after adjective */
+        /* 'artifact' is not true adjective */
+       else if (!IS_FLG(FLG_ARTIFACT))
                sepa_flag = FALSE;
 
-       if (entry->name && *entry->name)
+       if (entry->name && entry->name[0])
        {
-               if (sepa_flag)
-                       strcat(buf, ":");
-               strcat(buf, entry->name);
+                int i, j = 0;
+
+               if (sepa_flag) strcat(buf, ":");
+
+                i = strlen(buf);
+                while (entry->name[j] && i < MAX_LINELEN - 2 - 1)
+                {
+#ifdef JP
+                        if (iskanji(entry->name[j]))
+                                buf[i++] = entry->name[j++];
+#endif
+                        buf[i++] = entry->name[j++];
+                }
+                buf[i] = '\0';
        }
        else
        {
@@ -262,13 +283,39 @@ cptr autopick_line_from_entry(autopick_type *entry)
 
        if (entry->insc)
        {
+                int i, j = 0;
                strcat(buf, "#");
-               strcat(buf, entry->insc);
+                i = strlen(buf);
+
+                while (entry->insc[j] && i < MAX_LINELEN - 2)
+                {
+#ifdef JP
+                        if (iskanji(entry->insc[j]))
+                                buf[i++] = entry->insc[j++];
+#endif
+                        buf[i++] = entry->insc[j++];
+                }
+                buf[i] = '\0';
        }
 
        return string_make(buf);
 }
 
+
+/*
+ * Reconstruct preference line from entry and kill entry
+ */
+static cptr autopick_line_from_entry_kill(autopick_type *entry)
+{
+        cptr ptr = autopick_line_from_entry(entry);
+
+        /* Free memory for original entry */
+        autopick_free_entry(entry);
+
+        return ptr;
+}
+
+
 /*
  * A function to create new entry
  */
@@ -277,8 +324,8 @@ bool autopick_new_entry(autopick_type *entry, cptr str)
        cptr insc;
        int i;
        byte act = 0;
-       char buf[1024];
-       cptr prev_ptr, ptr;
+       char buf[MAX_LINELEN];
+       cptr prev_ptr, ptr, old_ptr;
        int prev_flg;
 
        if (str[1] == ':') switch (str[0])
@@ -345,121 +392,134 @@ bool autopick_new_entry(autopick_type *entry, cptr str)
        /* Skip empty line */
        if (*buf == 0) return FALSE;
 
-       /* Found flags */
-       prev_ptr = ptr = buf;
+       ptr = buf;
+        old_ptr = NULL;
+
+        while (old_ptr != ptr)
+        {
+                /* Save current location */
+                old_ptr = ptr;
+
+                if (MATCH_KEY(KEY_ALL)) ADD_FLG(FLG_ALL);
+                if (MATCH_KEY(KEY_COLLECTING)) ADD_FLG(FLG_COLLECTING);
+                if (MATCH_KEY(KEY_UNIDENTIFIED)) ADD_FLG(FLG_UNIDENTIFIED);
+                if (MATCH_KEY(KEY_IDENTIFIED)) ADD_FLG(FLG_IDENTIFIED);
+                if (MATCH_KEY(KEY_STAR_IDENTIFIED)) ADD_FLG(FLG_STAR_IDENTIFIED);
+                if (MATCH_KEY(KEY_BOOSTED)) ADD_FLG(FLG_BOOSTED);
+
+                /*** Weapons whose dd*ds is more than nn ***/
+                if (MATCH_KEY2(KEY_MORE_THAN))
+                {
+                        int k = 0;
+                        entry->dice = 0;
+
+                        /* Drop leading spaces */
+                        while (' ' == *ptr) ptr++;
+
+                        /* Read number */
+                        while (isdigit(*ptr))
+                        {
+                                entry->dice = 10 * entry->dice + (*ptr - '0');
+                                ptr++;
+                                k++;
+                        }
+
+                        if (k > 0 && k <= 2)
+                        {
+                                (void)MATCH_KEY(KEY_DICE);
+                                ADD_FLG(FLG_MORE_THAN);
+                        }
+                        else
+                                ptr = prev_ptr;
+                }
+
+                /*** Items whose magical bonus is more than n ***/
+                if (MATCH_KEY2(KEY_MORE_BONUS))
+                {
+                        int k = 0;
+                        entry->bonus = 0;
+
+                        /* Drop leading spaces */
+                        while (' ' == *ptr) ptr++;
+
+                        /* Read number */
+                        while (isdigit(*ptr))
+                        {
+                                entry->bonus = 10 * entry->bonus + (*ptr - '0');
+                                ptr++;
+                                k++;
+                        }
+
+                        if (k > 0 && k <= 2)
+                        {
+                                (void)MATCH_KEY(KEY_MORE_BONUS2);
+                                ADD_FLG(FLG_MORE_BONUS);
+                        }
+                        else
+                                ptr = prev_ptr;
+                }
+
+                if (MATCH_KEY(KEY_WORTHLESS)) ADD_FLG(FLG_WORTHLESS);
+                if (MATCH_KEY(KEY_EGO)) ADD_FLG(FLG_EGO);
+                if (MATCH_KEY(KEY_NAMELESS)) ADD_FLG(FLG_NAMELESS);
+                if (MATCH_KEY(KEY_UNAWARE)) ADD_FLG(FLG_UNAWARE);
+                if (MATCH_KEY(KEY_WANTED)) ADD_FLG(FLG_WANTED);
+                if (MATCH_KEY(KEY_UNIQUE)) ADD_FLG(FLG_UNIQUE);
+                if (MATCH_KEY(KEY_HUMAN)) ADD_FLG(FLG_HUMAN);
+                if (MATCH_KEY(KEY_UNREADABLE)) ADD_FLG(FLG_UNREADABLE);
+                if (MATCH_KEY(KEY_REALM1)) ADD_FLG(FLG_REALM1);
+                if (MATCH_KEY(KEY_REALM2)) ADD_FLG(FLG_REALM2);
+                if (MATCH_KEY(KEY_FIRST)) ADD_FLG(FLG_FIRST);
+                if (MATCH_KEY(KEY_SECOND)) ADD_FLG(FLG_SECOND);
+                if (MATCH_KEY(KEY_THIRD)) ADD_FLG(FLG_THIRD);
+                if (MATCH_KEY(KEY_FOURTH)) ADD_FLG(FLG_FOURTH);
+        }
+
+       /* Not yet found any noun */
        prev_flg = -1;
-       if (MATCH_KEY(KEY_ALL)) ADD_FLG(FLG_ALL);
-       if (MATCH_KEY(KEY_COLLECTING)) ADD_FLG(FLG_COLLECTING);
-       if (MATCH_KEY(KEY_UNIDENTIFIED)) ADD_FLG(FLG_UNIDENTIFIED);
-       if (MATCH_KEY(KEY_IDENTIFIED)) ADD_FLG(FLG_IDENTIFIED);
-       if (MATCH_KEY(KEY_STAR_IDENTIFIED)) ADD_FLG(FLG_STAR_IDENTIFIED);
-       if (MATCH_KEY(KEY_BOOSTED)) ADD_FLG(FLG_BOOSTED);
-
-       /*** Weapons whose dd*ds is more than nn ***/
-       if (MATCH_KEY(KEY_MORE_THAN))
-       {
-               int k = 0;
-               entry->dice = 0;
-
-               /* Drop leading spaces */
-               while (' ' == *ptr) ptr++;
-
-               /* Read number */
-               while (isdigit(*ptr))
-               {
-                       entry->dice = 10 * entry->dice + (*ptr - '0');
-                       ptr++;
-                       k++;
-               }
-
-               if (k > 0 && k <= 2)
-               {
-                       (void)MATCH_KEY(KEY_DICE);
-                       ADD_FLG(FLG_MORE_THAN);
-               }
-               else
-                       ptr = prev_ptr;
-       }
-
-       /*** Items whose magical bonus is more than n ***/
-       if (MATCH_KEY(KEY_MORE_BONUS))
-       {
-               int k = 0;
-               entry->bonus = 0;
 
-               /* Drop leading spaces */
-               while (' ' == *ptr) ptr++;
-
-               /* Read number */
-               while (isdigit(*ptr))
-               {
-                       entry->bonus = 10 * entry->bonus + (*ptr - '0');
-                       ptr++;
-                       k++;
-               }
-
-               if (k > 0 && k <= 2)
-               {
-                       (void)MATCH_KEY(KEY_MORE_BONUS2);
-                       ADD_FLG(FLG_MORE_BONUS);
-               }
-               else
-                       ptr = prev_ptr;
-       }
-
-       if (MATCH_KEY(KEY_WORTHLESS)) ADD_FLG(FLG_WORTHLESS);
-       if (MATCH_KEY(KEY_ARTIFACT)) ADD_FLG(FLG_ARTIFACT);
-       if (MATCH_KEY(KEY_EGO)) ADD_FLG(FLG_EGO);
-       if (MATCH_KEY(KEY_NAMELESS)) ADD_FLG(FLG_NAMELESS);
-       if (MATCH_KEY(KEY_UNAWARE)) ADD_FLG(FLG_UNAWARE);
-       if (MATCH_KEY(KEY_WANTED)) ADD_FLG(FLG_WANTED);
-       if (MATCH_KEY(KEY_UNIQUE)) ADD_FLG(FLG_UNIQUE);
-       if (MATCH_KEY(KEY_HUMAN)) ADD_FLG(FLG_HUMAN);
-       if (MATCH_KEY(KEY_UNREADABLE)) ADD_FLG(FLG_UNREADABLE);
-       if (MATCH_KEY(KEY_REALM1)) ADD_FLG(FLG_REALM1);
-       if (MATCH_KEY(KEY_REALM2)) ADD_FLG(FLG_REALM2);
-       if (MATCH_KEY(KEY_FIRST)) ADD_FLG(FLG_FIRST);
-       if (MATCH_KEY(KEY_SECOND)) ADD_FLG(FLG_SECOND);
-       if (MATCH_KEY(KEY_THIRD)) ADD_FLG(FLG_THIRD);
-       if (MATCH_KEY(KEY_FOURTH)) ADD_FLG(FLG_FOURTH);
-
-       /* Reset previous word location */
-       prev_ptr = ptr;
-
-       if (MATCH_KEY(KEY_ITEMS)) ADD_FLG2(FLG_ITEMS);
-       else if (MATCH_KEY(KEY_WEAPONS)) ADD_FLG2(FLG_WEAPONS);
-       else if (MATCH_KEY(KEY_ARMORS)) ADD_FLG2(FLG_ARMORS);
-       else if (MATCH_KEY(KEY_MISSILES)) ADD_FLG2(FLG_MISSILES);
-       else if (MATCH_KEY(KEY_DEVICES)) ADD_FLG2(FLG_DEVICES);
-       else if (MATCH_KEY(KEY_LIGHTS)) ADD_FLG2(FLG_LIGHTS);
-       else if (MATCH_KEY(KEY_JUNKS)) ADD_FLG2(FLG_JUNKS);
-       else if (MATCH_KEY(KEY_SPELLBOOKS)) ADD_FLG2(FLG_SPELLBOOKS);
-       else if (MATCH_KEY(KEY_HAFTED)) ADD_FLG2(FLG_HAFTED);
-       else if (MATCH_KEY(KEY_SHIELDS)) ADD_FLG2(FLG_SHIELDS);
-       else if (MATCH_KEY(KEY_BOWS)) ADD_FLG2(FLG_BOWS);
-       else if (MATCH_KEY(KEY_RINGS)) ADD_FLG2(FLG_RINGS);
-       else if (MATCH_KEY(KEY_AMULETS)) ADD_FLG2(FLG_AMULETS);
-       else if (MATCH_KEY(KEY_SUITS)) ADD_FLG2(FLG_SUITS);
-       else if (MATCH_KEY(KEY_CLOAKS)) ADD_FLG2(FLG_CLOAKS);
-       else if (MATCH_KEY(KEY_HELMS)) ADD_FLG2(FLG_HELMS);
-       else if (MATCH_KEY(KEY_GLOVES)) ADD_FLG2(FLG_GLOVES);
-       else if (MATCH_KEY(KEY_BOOTS)) ADD_FLG2(FLG_BOOTS);
+       if (MATCH_KEY2(KEY_ARTIFACT)) ADD_FLG_NOUN(FLG_ARTIFACT);
+
+       if (MATCH_KEY2(KEY_ITEMS)) ADD_FLG_NOUN(FLG_ITEMS);
+       else if (MATCH_KEY2(KEY_WEAPONS)) ADD_FLG_NOUN(FLG_WEAPONS);
+       else if (MATCH_KEY2(KEY_ARMORS)) ADD_FLG_NOUN(FLG_ARMORS);
+       else if (MATCH_KEY2(KEY_MISSILES)) ADD_FLG_NOUN(FLG_MISSILES);
+       else if (MATCH_KEY2(KEY_DEVICES)) ADD_FLG_NOUN(FLG_DEVICES);
+       else if (MATCH_KEY2(KEY_LIGHTS)) ADD_FLG_NOUN(FLG_LIGHTS);
+       else if (MATCH_KEY2(KEY_JUNKS)) ADD_FLG_NOUN(FLG_JUNKS);
+       else if (MATCH_KEY2(KEY_SPELLBOOKS)) ADD_FLG_NOUN(FLG_SPELLBOOKS);
+       else if (MATCH_KEY2(KEY_HAFTED)) ADD_FLG_NOUN(FLG_HAFTED);
+       else if (MATCH_KEY2(KEY_SHIELDS)) ADD_FLG_NOUN(FLG_SHIELDS);
+       else if (MATCH_KEY2(KEY_BOWS)) ADD_FLG_NOUN(FLG_BOWS);
+       else if (MATCH_KEY2(KEY_RINGS)) ADD_FLG_NOUN(FLG_RINGS);
+       else if (MATCH_KEY2(KEY_AMULETS)) ADD_FLG_NOUN(FLG_AMULETS);
+       else if (MATCH_KEY2(KEY_SUITS)) ADD_FLG_NOUN(FLG_SUITS);
+       else if (MATCH_KEY2(KEY_CLOAKS)) ADD_FLG_NOUN(FLG_CLOAKS);
+       else if (MATCH_KEY2(KEY_HELMS)) ADD_FLG_NOUN(FLG_HELMS);
+       else if (MATCH_KEY2(KEY_GLOVES)) ADD_FLG_NOUN(FLG_GLOVES);
+       else if (MATCH_KEY2(KEY_BOOTS)) ADD_FLG_NOUN(FLG_BOOTS);
 
        /* Last 'keyword' must be at the correct location */
        if (*ptr == ':')
                ptr++;
-       else if (*ptr == '\0')
-               ; /* nothing to do */
 #ifdef JP
        else if (ptr[0] == kanji_colon[0] && ptr[1] == kanji_colon[1])
                ptr += 2;
 #endif
+       else if (*ptr == '\0')
+               ; /* nothing to do */
        else
        {
+               /* Noun type? */
                if (prev_flg != -1)
+               {
+                       /* A noun type keyword didn't end correctly */
                        entry->flag[prev_flg/32] &= ~(1L<< (prev_flg%32));
-               ptr = prev_ptr;
+                       ptr = prev_ptr;
+               }
        }
+
+       /* Save this auto-picker entry line */
        entry->name = string_make(ptr);
        entry->action = act;
        entry->insc = string_make(insc);
@@ -476,6 +536,327 @@ void autopick_free_entry(autopick_type *entry)
        string_free(entry->insc);
 }
 
+
+/*
+ * A function for Auto-picker/destroyer
+ * Examine whether the object matches to the entry
+ */
+static bool is_autopick_aux(object_type *o_ptr, autopick_type *entry, cptr o_name)
+{
+        int j;
+        cptr ptr = entry->name;
+
+        /*** Unidentified ***/
+        if (IS_FLG(FLG_UNIDENTIFIED)
+            && (object_known_p(o_ptr) || (o_ptr->ident & IDENT_SENSE)))
+                return FALSE;
+
+        /*** Identified ***/
+        if (IS_FLG(FLG_IDENTIFIED) && !object_known_p(o_ptr))
+                return FALSE;
+
+        /*** *Identified* ***/
+        if (IS_FLG(FLG_STAR_IDENTIFIED) &&
+            (!object_known_p(o_ptr) || !(o_ptr->ident & IDENT_MENTAL)))
+                return FALSE;
+
+        /*** Dice boosted (weapon of slaying) ***/
+        if (IS_FLG(FLG_BOOSTED))
+        {
+                object_kind *k_ptr = &k_info[o_ptr->k_idx];
+                       
+                switch( o_ptr->tval )
+                {
+                case TV_HAFTED:
+                case TV_POLEARM:
+                case TV_SWORD:
+                case TV_DIGGING:
+                        if ((o_ptr->dd != k_ptr->dd) || (o_ptr->ds != k_ptr->ds))
+                                break;
+                        else
+                                return FALSE;
+                default:
+                        return FALSE;
+                }
+        }
+
+        /*** Weapons whic dd*ds is more than nn ***/
+        if (IS_FLG(FLG_MORE_THAN))
+        {
+                if (o_ptr->dd * o_ptr->ds < entry->dice)
+                        return FALSE;
+        }
+                               
+        /*** Weapons whic dd*ds is more than nn ***/
+        if (IS_FLG(FLG_MORE_BONUS))
+        {
+                if (!object_known_p(o_ptr)) return FALSE;
+
+                if (k_info[o_ptr->k_idx].pval ||
+                    (o_ptr->name2 && e_info[o_ptr->name2].max_pval))
+                {
+                        if (o_ptr->pval < entry->bonus) return FALSE;
+                }
+                else
+                {
+                        if (o_ptr->to_h < entry->bonus &&
+                            o_ptr->to_d < entry->bonus &&
+                            o_ptr->to_a < entry->bonus &&
+                            o_ptr->pval < entry->bonus)
+                                return FALSE;
+                }
+        }
+                               
+        /*** Worthless items ***/
+        if (IS_FLG(FLG_WORTHLESS) && object_value(o_ptr) > 0)
+                return FALSE;
+
+        /*** Artifact object ***/
+        if (IS_FLG(FLG_ARTIFACT))
+        {
+                if (!object_known_p(o_ptr) || (!o_ptr->name1 && !o_ptr->art_name))
+                        return FALSE;
+        }
+
+        /*** Ego object ***/
+        if (IS_FLG(FLG_EGO))
+        {
+                if (!object_known_p(o_ptr) || !o_ptr->name2)
+                        return FALSE;
+        }
+
+        /*** Nameless ***/
+        if (IS_FLG(FLG_NAMELESS))
+        {
+                switch (o_ptr->tval)
+                {
+                case TV_WHISTLE:
+                case TV_SHOT: case TV_ARROW: case TV_BOLT: case TV_BOW:
+                case TV_DIGGING: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: 
+                case TV_BOOTS: case TV_GLOVES: case TV_HELM: case TV_CROWN:
+                case TV_SHIELD: case TV_CLOAK:
+                case TV_SOFT_ARMOR: case TV_HARD_ARMOR: case TV_DRAG_ARMOR:
+                case TV_LITE: case TV_AMULET: case TV_RING: case TV_CARD:
+                        if ((!object_known_p(o_ptr) || o_ptr->inscription
+                             || o_ptr->name1 || o_ptr->name2 || o_ptr->art_name))
+                                return FALSE;
+                        break;
+                default:
+                        /* don't match */
+                        return FALSE;
+                }
+        }
+
+        /*** Unaware items ***/
+        if (IS_FLG(FLG_UNAWARE) && object_aware_p(o_ptr))
+                return FALSE;
+
+        /*** Wanted monster's corpse/skeletons ***/
+        if (IS_FLG(FLG_WANTED) &&
+            (o_ptr->tval != TV_CORPSE || !object_is_shoukinkubi(o_ptr)))
+                return FALSE;
+
+        /*** Unique monster's corpse/skeletons/statues ***/
+        if (IS_FLG(FLG_UNIQUE) &&
+            ((o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_STATUE) ||
+             !(r_info[o_ptr->pval].flags1 & RF1_UNIQUE)))
+                return FALSE;
+
+        /*** Human corpse/skeletons (for Daemon magic) ***/
+        if (IS_FLG(FLG_HUMAN) &&
+            (o_ptr->tval != TV_CORPSE ||
+             !strchr("pht", r_info[o_ptr->pval].d_char)))
+                return FALSE;
+
+        /*** Unreadable spellbooks ***/
+        if (IS_FLG(FLG_UNREADABLE) &&
+            (o_ptr->tval < TV_LIFE_BOOK ||
+             check_book_realm(o_ptr->tval, o_ptr->sval)))
+                return FALSE;
+
+        /*** First realm spellbooks ***/
+        if (IS_FLG(FLG_REALM1) && 
+            (REALM1_BOOK != o_ptr->tval ||
+             p_ptr->pclass == CLASS_SORCERER ||
+             p_ptr->pclass == CLASS_RED_MAGE))
+                return FALSE;
+
+        /*** Second realm spellbooks ***/
+        if (IS_FLG(FLG_REALM2) &&
+            (REALM2_BOOK != o_ptr->tval ||
+             p_ptr->pclass == CLASS_SORCERER ||
+             p_ptr->pclass == CLASS_RED_MAGE))
+                return FALSE;
+
+        /*** First rank spellbooks ***/
+        if (IS_FLG(FLG_FIRST) &&
+            (o_ptr->tval < TV_LIFE_BOOK || 0 != o_ptr->sval))
+                return FALSE;
+
+        /*** Second rank spellbooks ***/
+        if (IS_FLG(FLG_SECOND) &&
+            (o_ptr->tval < TV_LIFE_BOOK || 1 != o_ptr->sval))
+                return FALSE;
+
+        /*** Third rank spellbooks ***/
+        if (IS_FLG(FLG_THIRD) && 
+            (o_ptr->tval < TV_LIFE_BOOK || 2 != o_ptr->sval))
+                return FALSE;
+
+        /*** Fourth rank spellbooks ***/
+        if (IS_FLG(FLG_FOURTH) &&
+            (o_ptr->tval < TV_LIFE_BOOK || 3 != o_ptr->sval))
+                return FALSE;
+
+        /*** Items ***/
+        if (IS_FLG(FLG_WEAPONS))
+        {
+                switch(o_ptr->tval)
+                {
+                case TV_BOW: case TV_HAFTED: case TV_POLEARM:
+                case TV_SWORD: case TV_DIGGING:
+                        break;
+                default: return FALSE;
+                }
+        }
+        else if (IS_FLG(FLG_ARMORS))
+        {
+                switch(o_ptr->tval)
+                {
+                case TV_BOOTS: case TV_GLOVES: case TV_CLOAK: case TV_CROWN:
+                case TV_HELM: case TV_SHIELD: case TV_SOFT_ARMOR:
+                case TV_HARD_ARMOR: case TV_DRAG_ARMOR:
+                        break;
+                default: return FALSE;
+                }
+        }
+        else if (IS_FLG(FLG_MISSILES))
+        {
+                switch(o_ptr->tval)
+                {
+                case TV_SHOT: case TV_BOLT: case TV_ARROW:
+                        break;
+                default: return FALSE;
+                }
+        }
+        else if (IS_FLG(FLG_DEVICES))
+        {
+                switch(o_ptr->tval)
+                {
+                case TV_SCROLL: case TV_STAFF: case TV_WAND: case TV_ROD:
+                        break;
+                default: return FALSE;
+                }
+        }
+        else if (IS_FLG(FLG_LIGHTS))
+        {
+                if (!(o_ptr->tval == TV_LITE))
+                        return FALSE;
+        }
+        else if (IS_FLG(FLG_JUNKS))
+        {
+                switch(o_ptr->tval)
+                {
+                case TV_SKELETON: case TV_BOTTLE:
+                case TV_JUNK: case TV_STATUE:
+                        break;
+                default: return FALSE;
+                }
+        }
+        else if (IS_FLG(FLG_SPELLBOOKS))
+        {
+                if (!(o_ptr->tval >= TV_LIFE_BOOK))
+                        return FALSE;
+        }
+        else if (IS_FLG(FLG_HAFTED))
+        {
+                if (!(o_ptr->tval == TV_HAFTED))
+                        return FALSE;
+        }
+        else if (IS_FLG(FLG_SHIELDS))
+        {
+                if (!(o_ptr->tval == TV_SHIELD))
+                        return FALSE;
+        }
+        else if (IS_FLG(FLG_BOWS))
+        {
+                if (!(o_ptr->tval == TV_BOW))
+                        return FALSE;
+        }
+        else if (IS_FLG(FLG_RINGS))
+        {
+                if (!(o_ptr->tval == TV_RING))
+                        return FALSE;
+        }
+        else if (IS_FLG(FLG_AMULETS))
+        {
+                if (!(o_ptr->tval == TV_AMULET))
+                        return FALSE;
+        }
+        else if (IS_FLG(FLG_SUITS))
+        {
+                if (!(o_ptr->tval == TV_DRAG_ARMOR ||
+                      o_ptr->tval == TV_HARD_ARMOR ||
+                      o_ptr->tval == TV_SOFT_ARMOR))
+                        return FALSE;
+        }
+        else if (IS_FLG(FLG_CLOAKS))
+        {
+                if (!(o_ptr->tval == TV_CLOAK))
+                        return FALSE;
+        }
+        else if (IS_FLG(FLG_HELMS))
+        {
+                if (!(o_ptr->tval == TV_CROWN || o_ptr->tval == TV_HELM))
+                        return FALSE;
+        }
+        else if (IS_FLG(FLG_GLOVES))
+        {
+                if (!(o_ptr->tval == TV_GLOVES))
+                        return FALSE;
+        }
+        else if (IS_FLG(FLG_BOOTS))
+        {
+                if (!(o_ptr->tval == TV_BOOTS))
+                        return FALSE;
+        }
+
+        /* Keyword don't match */
+        if (*ptr == '^')
+        {
+                ptr++;
+                if (strncmp(o_name, ptr, strlen(ptr))) return FALSE;
+        }
+        else
+        {
+#ifdef JP
+                if (!strstr_j(o_name, ptr)) return FALSE;
+#else
+                if (!strstr(o_name, ptr)) return FALSE;
+#endif
+        }
+
+        /* TRUE when it need not to be 'collecting' */
+        if (!IS_FLG(FLG_COLLECTING)) return TRUE;
+
+        /* Check if there is a same item */
+        for (j = 0; j < INVEN_PACK; j++)
+        {
+                /*
+                 * 'Collecting' means the item must be absorbed 
+                 * into an inventory slot.
+                 * But an item can not be absorbed into itself!
+                 */
+                if ((&inventory[j] != o_ptr) &&
+                    object_similar(&inventory[j], o_ptr))
+                        return TRUE;
+        }
+
+        /* Not collecting */
+        return FALSE;
+}
+
+
 /*
  * A function for Auto-picker/destroyer
  * Examine whether the object matches to the list of keywords or not.
@@ -504,321 +885,11 @@ int is_autopick(object_type *o_ptr)
        for (i=0; i < max_autopick; i++)
        {
                autopick_type *entry = &autopick_list[i];
-               bool flag = FALSE;
-               cptr ptr = autopick_list[i].name;
-
-               /*** Unidentified ***/
-               if (IS_FLG(FLG_UNIDENTIFIED)
-                   && (object_known_p(o_ptr) || (o_ptr->ident & IDENT_SENSE)))
-                       continue;
-
-               /*** Identified ***/
-               if (IS_FLG(FLG_IDENTIFIED) && !object_known_p(o_ptr))
-                       continue;
-
-               /*** *Identified* ***/
-               if (IS_FLG(FLG_STAR_IDENTIFIED) &&
-                   (!object_known_p(o_ptr) || !(o_ptr->ident & IDENT_MENTAL)))
-                       continue;
-
-               /*** Dice boosted (weapon of slaying) ***/
-               if (IS_FLG(FLG_BOOSTED))
-               {
-                       object_kind *k_ptr = &k_info[o_ptr->k_idx];
-                       
-                       switch( o_ptr->tval )
-                       {
-                       case TV_HAFTED:
-                       case TV_POLEARM:
-                       case TV_SWORD:
-                       case TV_DIGGING:
-                               if ((o_ptr->dd != k_ptr->dd) || (o_ptr->ds != k_ptr->ds))
-                                       break;
-                               else
-                                       continue;
-                       default:
-                               continue;
-                       }
-               }
-
-               /*** Weapons whic dd*ds is more than nn ***/
-               if (IS_FLG(FLG_MORE_THAN))
-               {
-                       if (o_ptr->dd * o_ptr->ds < entry->dice)
-                               continue;
-               }
-                               
-               /*** Weapons whic dd*ds is more than nn ***/
-               if (IS_FLG(FLG_MORE_BONUS))
-               {
-                       if (!object_known_p(o_ptr)) continue;
-
-                       if (k_info[o_ptr->k_idx].pval ||
-                           (o_ptr->name2 && e_info[o_ptr->name2].max_pval))
-                       {
-                               if (o_ptr->pval < entry->bonus) continue;
-                       }
-                       else
-                       {
-                               if (o_ptr->to_h < entry->bonus &&
-                                   o_ptr->to_d < entry->bonus &&
-                                   o_ptr->to_a < entry->bonus &&
-                                   o_ptr->pval < entry->bonus)
-                                       continue;
-                       }
-               }
-                               
-               /*** Worthless items ***/
-               if (IS_FLG(FLG_WORTHLESS) && object_value(o_ptr) > 0)
-                       continue;
-
-               /*** Artifact object ***/
-               if (IS_FLG(FLG_ARTIFACT))
-               {
-                       if (!object_known_p(o_ptr) || (!o_ptr->name1 && !o_ptr->art_name))
-                               continue;
-               }
-
-               /*** Ego object ***/
-               if (IS_FLG(FLG_EGO))
-               {
-                       if (!object_known_p(o_ptr) || !o_ptr->name2)
-                               continue;
-               }
-
-               /*** Nameless ***/
-               if (IS_FLG(FLG_NAMELESS))
-               {
-                       switch (o_ptr->tval)
-                       {
-                       case TV_WHISTLE:
-                       case TV_SHOT: case TV_ARROW: case TV_BOLT: case TV_BOW:
-                       case TV_DIGGING: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: 
-                       case TV_BOOTS: case TV_GLOVES: case TV_HELM: case TV_CROWN:
-                       case TV_SHIELD: case TV_CLOAK:
-                       case TV_SOFT_ARMOR: case TV_HARD_ARMOR: case TV_DRAG_ARMOR:
-                       case TV_LITE: case TV_AMULET: case TV_RING: case TV_CARD:
-                               if ((!object_known_p(o_ptr) || o_ptr->inscription
-                                    || o_ptr->name1 || o_ptr->name2 || o_ptr->art_name))
-                                       continue;
-                               break;
-                       default:
-                               /* don't match */
-                               continue;
-                       }
-               }
-
-               /*** Unaware items ***/
-               if (IS_FLG(FLG_UNAWARE) && object_aware_p(o_ptr))
-                       continue;
-
-               /*** Wanted monster's corpse/skeletons ***/
-               if (IS_FLG(FLG_WANTED) &&
-                   (o_ptr->tval != TV_CORPSE || !object_is_shoukinkubi(o_ptr)))
-                       continue;
-
-               /*** Unique monster's corpse/skeletons/statues ***/
-               if (IS_FLG(FLG_UNIQUE) &&
-                   ((o_ptr->tval != TV_CORPSE && o_ptr->tval != TV_STATUE) ||
-                   !(r_info[o_ptr->pval].flags1 & RF1_UNIQUE)))
-                       continue;
-
-               /*** Human corpse/skeletons (for Daemon magic) ***/
-               if (IS_FLG(FLG_HUMAN) &&
-                   (o_ptr->tval != TV_CORPSE ||
-                   !strchr("pht", r_info[o_ptr->pval].d_char)))
-                       continue;
-
-               /*** Unreadable spellbooks ***/
-               if (IS_FLG(FLG_UNREADABLE) &&
-                   (o_ptr->tval < TV_LIFE_BOOK ||
-                   check_book_realm(o_ptr->tval, o_ptr->sval)))
-                       continue;
-
-               /*** First realm spellbooks ***/
-               if (IS_FLG(FLG_REALM1) && 
-                   (REALM1_BOOK != o_ptr->tval ||
-                   p_ptr->pclass == CLASS_SORCERER ||
-                   p_ptr->pclass == CLASS_RED_MAGE))
-                       continue;
-
-               /*** Second realm spellbooks ***/
-               if (IS_FLG(FLG_REALM2) &&
-                   (REALM2_BOOK != o_ptr->tval ||
-                   p_ptr->pclass == CLASS_SORCERER ||
-                   p_ptr->pclass == CLASS_RED_MAGE))
-                       continue;
-
-               /*** First rank spellbooks ***/
-               if (IS_FLG(FLG_FIRST) &&
-                   (o_ptr->tval < TV_LIFE_BOOK || 0 != o_ptr->sval))
-                       continue;
-
-               /*** Second rank spellbooks ***/
-               if (IS_FLG(FLG_SECOND) &&
-                   (o_ptr->tval < TV_LIFE_BOOK || 1 != o_ptr->sval))
-                       continue;
-
-               /*** Third rank spellbooks ***/
-               if (IS_FLG(FLG_THIRD) && 
-                   (o_ptr->tval < TV_LIFE_BOOK || 2 != o_ptr->sval))
-                       continue;
-
-               /*** Fourth rank spellbooks ***/
-               if (IS_FLG(FLG_FOURTH) &&
-                   (o_ptr->tval < TV_LIFE_BOOK || 3 != o_ptr->sval))
-                       continue;
-
-               /*** Items ***/
-               if (IS_FLG(FLG_WEAPONS))
-               {
-                       switch(o_ptr->tval)
-                       {
-                       case TV_BOW: case TV_HAFTED: case TV_POLEARM:
-                       case TV_SWORD: case TV_DIGGING:
-                               break;
-                       default: continue;
-                       }
-               }
-               else if (IS_FLG(FLG_ARMORS))
-               {
-                       switch(o_ptr->tval)
-                       {
-                       case TV_BOOTS: case TV_GLOVES: case TV_CLOAK: case TV_CROWN:
-                       case TV_HELM: case TV_SHIELD: case TV_SOFT_ARMOR:
-                       case TV_HARD_ARMOR: case TV_DRAG_ARMOR:
-                               break;
-                       default: continue;
-                       }
-               }
-               else if (IS_FLG(FLG_MISSILES))
-               {
-                       switch(o_ptr->tval)
-                       {
-                       case TV_SHOT: case TV_BOLT: case TV_ARROW:
-                               break;
-                       default: continue;
-                       }
-               }
-               else if (IS_FLG(FLG_DEVICES))
-               {
-                       switch(o_ptr->tval)
-                       {
-                       case TV_SCROLL: case TV_STAFF: case TV_WAND: case TV_ROD:
-                               break;
-                       default: continue;
-                       }
-               }
-               else if (IS_FLG(FLG_LIGHTS))
-               {
-                       if (!(o_ptr->tval == TV_LITE))
-                               continue;
-               }
-               else if (IS_FLG(FLG_JUNKS))
-               {
-                       switch(o_ptr->tval)
-                       {
-                       case TV_SKELETON: case TV_BOTTLE:
-                       case TV_JUNK: case TV_STATUE:
-                               break;
-                       default: continue;
-                       }
-               }
-               else if (IS_FLG(FLG_SPELLBOOKS))
-               {
-                       if (!(o_ptr->tval >= TV_LIFE_BOOK))
-                               continue;
-               }
-               else if (IS_FLG(FLG_HAFTED))
-               {
-                       if (!(o_ptr->tval == TV_HAFTED))
-                               continue;
-               }
-               else if (IS_FLG(FLG_SHIELDS))
-               {
-                       if (!(o_ptr->tval == TV_SHIELD))
-                               continue;
-               }
-               else if (IS_FLG(FLG_BOWS))
-               {
-                       if (!(o_ptr->tval == TV_BOW))
-                               continue;
-               }
-               else if (IS_FLG(FLG_RINGS))
-               {
-                       if (!(o_ptr->tval == TV_RING))
-                               continue;
-               }
-               else if (IS_FLG(FLG_AMULETS))
-               {
-                       if (!(o_ptr->tval == TV_AMULET))
-                               continue;
-               }
-               else if (IS_FLG(FLG_SUITS))
-               {
-                       if (!(o_ptr->tval == TV_DRAG_ARMOR ||
-                             o_ptr->tval == TV_HARD_ARMOR ||
-                             o_ptr->tval == TV_SOFT_ARMOR))
-                               continue;
-               }
-               else if (IS_FLG(FLG_CLOAKS))
-               {
-                       if (!(o_ptr->tval == TV_CLOAK))
-                               continue;
-               }
-               else if (IS_FLG(FLG_HELMS))
-               {
-                       if (!(o_ptr->tval == TV_CROWN || o_ptr->tval == TV_HELM))
-                               continue;
-               }
-               else if (IS_FLG(FLG_GLOVES))
-               {
-                       if (!(o_ptr->tval == TV_GLOVES))
-                               continue;
-               }
-               else if (IS_FLG(FLG_BOOTS))
-               {
-                       if (!(o_ptr->tval == TV_BOOTS))
-                               continue;
-               }
-
-
-               if (*ptr == '^')
-               {
-                       ptr++;
-                       if (!strncmp(o_name, ptr, strlen(ptr)))
-                               flag = TRUE;
-               }
-               else
-#ifdef JP
-                       if (strstr_j(o_name, ptr))
-#else
-                       if (strstr(o_name, ptr))
-#endif
-               {
-                       flag = TRUE;
-               }
 
-               if (flag)
-               {
-                       int j;
-                       if (!IS_FLG(FLG_COLLECTING))
-                               return i;
-                       /* Check if there is a same item */
-                       for (j = 0; j < INVEN_PACK; j++)
-                       {
-                               /*
-                                * 'Collecting' means the item must be absorbed 
-                                * into an inventory slot.
-                                * But an item can not be absorbed into itself!
-                                */
-                               if ((&inventory[j] != o_ptr) &&
-                                   object_similar(&inventory[j], o_ptr))
-                                       return i;
-                       }
-               }
-       }/* for */
+                if (is_autopick_aux(o_ptr, entry, o_name)) return i;
+       }
 
+        /* No matching entry */
        return -1;
 }
 
@@ -955,8 +1026,7 @@ bool auto_destroy_item(int item, int autopick_idx, bool wait_optimize)
        }
 
        /* Record name of destroyed item */
-       autopick_free_entry(&autopick_entry_last_destroyed);
-       autopick_entry_from_object(&autopick_entry_last_destroyed, o_ptr);
+        COPY(&autopick_last_destroyed_object, o_ptr, object_type);
 
        /* Eliminate the item (from the pack) */
        if (item >= 0)
@@ -964,8 +1034,8 @@ bool auto_destroy_item(int item, int autopick_idx, bool wait_optimize)
                inven_item_increase(item, -(o_ptr->number));
 
                /*
-                * Optimize equipment when wait_optimize is TRUE.
-                * Optimize inventry later.
+                * always optimize equipment.
+                * optimize inventry only when wait_optimize is FALSE.
                 */
                if (!wait_optimize || item > INVEN_PACK)
                        inven_item_optimize(item);
@@ -1260,7 +1330,7 @@ static void describe_autopick(char *buff, autopick_type *entry)
        else if (IS_FLG(FLG_HELMS))
                body_str = "¥Ø¥ë¥á¥Ã¥È¤ä´§";
        else if (IS_FLG(FLG_GLOVES))
-               body_str = "¾®¼ê";
+               body_str = "äƼê";
        else if (IS_FLG(FLG_BOOTS))
                body_str = "¥Ö¡¼¥Ä";
 
@@ -1289,7 +1359,20 @@ static void describe_autopick(char *buff, autopick_type *entry)
        }
 
        if (insc)
-               strncat(buff, format("¤Ë¡Ö%s¡×¤È¹ï¤ó¤Ç", insc), 80);
+        {
+               strncat(buff, format("¤Ë¡Ö%s¡×", insc), 80);
+
+                if (strstr(insc, "%%all"))
+                        strcat(buff, "(%%all¤ÏÁ´Ç½ÎϤòɽ¤¹±Ñ»ú¤Îµ­¹æ¤ÇÃÖ´¹)");
+                else if (strstr(insc, "%all"))
+                        strcat(buff, "(%all¤ÏÁ´Ç½ÎϤòɽ¤¹µ­¹æ¤ÇÃÖ´¹)");
+                else if (strstr(insc, "%%"))
+                        strcat(buff, "(%%¤ÏÄɲÃǽÎϤòɽ¤¹±Ñ»ú¤Îµ­¹æ¤ÇÃÖ´¹)");
+                else if (strstr(insc, "%"))
+                        strcat(buff, "(%¤ÏÄɲÃǽÎϤòɽ¤¹µ­¹æ¤ÇÃÖ´¹)");
+
+               strcat(buff, "¤È¹ï¤ó¤Ç");
+        }
        else
                strcat(buff, "¤ò");
 
@@ -1532,7 +1615,16 @@ static void describe_autopick(char *buff, autopick_type *entry)
 
        /* Auto-insctiption */
        if (insc)
-               strncat(buff, format("and inscribe \"%s\" on ", insc), 80);
+        {
+               strncat(buff, format("and inscribe \"%s\"", insc), 80);
+
+                if (strstr(insc, "%all"))
+                        strcat(buff, ", replacing %all with code string representing all abilities,");
+                else if (strstr(insc, "%"))
+                        strcat(buff, ", replacing % with code string representing extra random abilities,");
+
+               strcat(buff, " on ");
+        }
 
        /* Adjective */
        if (!before_n) 
@@ -1598,11 +1690,11 @@ static void describe_autopick(char *buff, autopick_type *entry)
        if (act & DO_DISPLAY)
        {
                if (act & DONT_AUTOPICK)
-                       strcat(buff, "  Display these items when you press 'N' in the full map('M').");
+                       strcat(buff, "  Display these items when you press the N key in the full 'M'ap.");
                else if (act & DO_AUTODESTROY)
-                       strcat(buff, "  Display these items when you press 'K' in the full map('M').");
+                       strcat(buff, "  Display these items when you press the K key in the full 'M'ap.");
                else
-                       strcat(buff, "  Display these items when you press 'M' in the full map('M').");
+                       strcat(buff, "  Display these items when you press the M key in the full 'M'ap.");
        }
        else
                strcat(buff, " Not displayed in the full map.");
@@ -1766,7 +1858,7 @@ static void toggle_string(cptr *lines_list, int flg, int y)
        else
                ADD_FLG(flg);
 
-       lines_list[y] = autopick_line_from_entry(entry);
+       lines_list[y] = autopick_line_from_entry_kill(entry);
 }
 
 /*
@@ -1774,7 +1866,7 @@ static void toggle_string(cptr *lines_list, int flg, int y)
  */
 static bool insert_return_code(cptr *lines_list, int cx, int cy)
 {
-       char buf[1024];
+       char buf[MAX_LINELEN];
        int i, j, k;
 
        for (k = 0; lines_list[k]; k++)
@@ -1923,12 +2015,29 @@ void autopick_entry_from_object(autopick_type *entry, object_type *o_ptr)
        return;
 }
 
+
 /*
  * Choose an item and get auto-picker entry from it.
  */
-static bool entry_from_choosed_object(autopick_type *entry)
+static object_type *choose_object(cptr q, cptr s)
 {
        int item;
+
+       if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EQUIP))) return NULL;
+
+       /* Get the item (in the pack) */
+       if (item >= 0) return &inventory[item];
+
+       /* Get the item (on the floor) */
+       else return &o_list[0 - item];
+}
+
+
+/*
+ * Choose an item and get auto-picker entry from it.
+ */
+static bool entry_from_choosed_object(autopick_type *entry)
+{
        object_type *o_ptr;
        cptr q, s;
 
@@ -1940,22 +2049,236 @@ static bool entry_from_choosed_object(autopick_type *entry)
        q = "Entry which item? ";
        s = "You have nothing to entry.";
 #endif
-       if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EQUIP))) return FALSE;
+        o_ptr = choose_object(q, s);
+       if (!o_ptr) return FALSE;
 
-       /* Get the item (in the pack) */
-       if (item >= 0)
+       autopick_entry_from_object(entry, o_ptr);
+       return TRUE;
+}
+
+
+/*
+ * Choose an item or string for search
+ */
+static bool get_string_for_search(object_type **o_handle, cptr *search_strp)
+{
+        int pos = 0;
+       cptr q, s;
+        char buf[MAX_NLEN+20];
+
+#ifdef JP
+        int k_flag[MAX_NLEN+20];
+        char prompt[] = "¸¡º÷(^I:»ý¤Áʪ ^L:Ç˲õ¤µ¤ì¤¿Êª): ";
+#else
+        char prompt[] = "Search key(^I:inven ^L:destroyed): ";
+#endif
+        int col = sizeof(prompt) - 1;
+
+        if (*search_strp) strcpy(buf, *search_strp);
+        else buf[0] = '\0';
+
+       /* Display prompt */
+       prt(prompt, 0, 0);
+
+       /* Display the default answer */
+        Term_erase(col, 0, 255);
+       Term_putstr(col, 0, -1, TERM_YELLOW, buf);
+
+       /* Process input */
+       while (1)
        {
-               o_ptr = &inventory[item];
+                object_type *o_ptr;
+                int i;
+
+                /* Place cursor */
+               Term_gotoxy(col + pos, 0);
+
+               /* Do not process macros except special keys */
+               inkey_special = TRUE;
+
+               /* Get a key */
+               i = inkey();
+
+               /* Analyze the key */
+               switch (i)
+               {
+               case ESCAPE:
+                       pos = 0;
+                       return FALSE;
+
+               case '\n':
+               case '\r':
+                        if (!pos && *o_handle) return TRUE;
+                        string_free(*search_strp);
+                        *search_strp = string_make(buf);
+                        *o_handle = NULL;
+                        return TRUE;
+
+                case KTRL('i'):
+                        /* Get an item */
+#ifdef JP
+                        q = "¤É¤Î¥¢¥¤¥Æ¥à¤ò¸¡º÷¤·¤Þ¤¹¤«? ";
+                        s = "¥¢¥¤¥Æ¥à¤ò»ý¤Ã¤Æ¤¤¤Ê¤¤¡£";
+#else
+                        q = "Entry which item? ";
+                        s = "You have nothing to entry.";
+#endif
+                        o_ptr = choose_object(q, s);
+                        if (!o_ptr) return FALSE;
+
+                        *o_handle = o_ptr;
+
+                        string_free(*search_strp);
+                        object_desc(buf, *o_handle, FALSE, 3);
+                        *search_strp = string_make(format("<%s>", buf));
+                        return TRUE;
+
+                case KTRL('l'):
+                        if (!autopick_last_destroyed_object.k_idx) break;
+                        *o_handle = &autopick_last_destroyed_object;
+
+                        string_free(*search_strp);
+                        object_desc(buf, *o_handle, FALSE, 3);
+                        *search_strp = string_make(format("<%s>", buf));
+                        return TRUE;
+
+               case 0x7F:
+               case '\010':
+#ifdef JP
+                        if (pos > 0)
+                        {
+                                pos--;
+                                if (k_flag[pos]) pos--;
+                        }
+#else
+                       if (pos > 0) pos--;
+#endif
+                       break;
+
+               default:
+#ifdef JP
+                        if (iskanji(i))
+                        {
+                                int next;
+
+                                inkey_base = TRUE;
+                                next = inkey ();
+                                if (pos + 1 < MAX_NLEN)
+                                {
+                                        buf[pos++] = i;
+                                        buf[pos] = next;
+                                        k_flag[pos++] = 1;
+                                }
+                                else bell();
+                        }
+                        else if (pos < MAX_NLEN && isprint(i))
+                        {
+                                buf[pos] = i;
+                                k_flag[pos++] = 0;
+                        }
+                        else bell();
+#else
+                       if (pos < MAX_NLEN && isprint(i)) buf[pos++] = i;
+                       else bell();
+#endif
+                       break;
+               }
+
+                /* Terminate */
+                buf[pos] = '\0';
+
+                /* Update the entry */
+                Term_erase(col, 0, 255);
+                Term_putstr(col, 0, -1, TERM_WHITE, buf);
        }
 
-       /* Get the item (on the floor) */
-       else
+        /* Never reached */
+}
+
+
+/*
+ * Search next line matches for o_ptr
+ */
+static bool search_for_object(cptr *lines_list, object_type *o_ptr, int *cxp, int *cyp, bool forward)
+{
+        int i;
+       autopick_type an_entry, *entry = &an_entry;
+       char o_name[MAX_NLEN];
+
+       object_desc(o_name, o_ptr, FALSE, 3);
+
+       /* Force to be lower case string */
+       for (i = 0; o_name[i]; i++)
        {
-               o_ptr = &o_list[0 - item];
+#ifdef JP
+               if (iskanji(o_name[i]))
+                       i++;
+               else
+#endif
+               if (isupper(o_name[i]))
+                       o_name[i] = tolower(o_name[i]);
        }
+       
+        i = *cyp;
+
+        while (1)
+        {
+                if (forward)
+                {
+                        if (!lines_list[++i]) break;
+                }
+                else
+                {
+                        if (--i < 0) break;
+                }
+
+                if (!autopick_new_entry(entry, lines_list[i])) continue;
+
+                if (is_autopick_aux(o_ptr, entry, o_name))
+                {
+                        *cxp = 0;
+                        *cyp = i;
+                        return TRUE;
+                }
+        }
+
+        return FALSE;
+}
 
-       autopick_entry_from_object(entry, o_ptr);
-       return TRUE;
+
+/*
+ * Search next line matches to the string
+ */
+static bool search_for_string(cptr *lines_list, cptr search_str, int *cxp, int *cyp, bool forward)
+{
+        int i = *cyp;
+
+        while (1)
+        {
+                cptr pos;
+
+                if (forward)
+                {
+                        if (!lines_list[++i]) break;
+                }
+                else
+                {
+                        if (--i < 0) break;
+                }
+#ifdef JP
+                pos = strstr_j(lines_list[i], search_str);
+#else
+               pos = strstr(lines_list[i], search_str);
+#endif
+                if (pos)
+                {
+                        *cxp = (int)(pos - lines_list[i]);
+                        *cyp = i;
+                        return TRUE;
+                }
+        }
+
+        return FALSE;
 }
 
 
@@ -1981,6 +2304,117 @@ void init_autopicker(void)
 
 
 /*
+ * Get a trigger key and insert ASCII string for the trigger
+ */
+static bool insert_macro_line(cptr *lines_list, int cy)
+{
+       char tmp[1024];
+       char buf[1024];
+       int i, n = 0;
+
+       /* Flush */
+       flush();
+
+       /* Do not process macros */
+       inkey_base = TRUE;
+
+       /* First key */
+       i = inkey();
+
+       /* Read the pattern */
+       while (i)
+       {
+               /* Save the key */
+               buf[n++] = i;
+
+               /* Do not process macros */
+               inkey_base = TRUE;
+
+               /* Do not wait for keys */
+               inkey_scan = TRUE;
+
+               /* Attempt to read a key */
+               i = inkey();
+       }
+
+       /* Terminate */
+       buf[n] = '\0';
+
+       /* Flush */
+       flush();
+
+       /* Convert the trigger */
+       ascii_to_text(tmp, buf);
+
+       /* Null */
+       if(!tmp[0]) return FALSE;
+
+       /* Insert preference string */
+       insert_return_code(lines_list, 0, cy);
+       string_free(lines_list[cy]);
+       lines_list[cy] = string_make(format("P:%s", tmp));
+
+       /* Insert blank action preference line */
+       insert_return_code(lines_list, 0, cy);
+       string_free(lines_list[cy]);
+       lines_list[cy] = string_make("A:");
+
+       return TRUE;
+}
+
+
+/*
+ * Get a command key and insert ASCII string for the key
+ */
+static bool insert_keymap_line(cptr *lines_list, int cy)
+{
+       char tmp[1024];
+       char buf[2];
+       int mode;
+
+       /* Roguelike */
+       if (rogue_like_commands)
+       {
+               mode = KEYMAP_MODE_ROGUE;
+       }
+
+       /* Original */
+       else
+       {
+               mode = KEYMAP_MODE_ORIG;
+       }
+
+       /* Flush */
+       flush();
+
+       /* Get a key */
+       buf[0] = inkey();
+       buf[1] = '\0';
+
+       /* Flush */
+       flush();
+
+       /* Convert the trigger */
+       ascii_to_text(tmp, buf);
+
+       /* Null */
+       if(!tmp[0]) return FALSE;
+
+       /* Insert preference string */
+       insert_return_code(lines_list, 0, cy);
+       string_free(lines_list[cy]);
+       lines_list[cy] = string_make(format("C:%d:%s", mode, tmp));
+
+       /* Insert blank action preference line */
+       insert_return_code(lines_list, 0, cy);
+       string_free(lines_list[cy]);
+       lines_list[cy] = string_make("A:");
+
+       return TRUE;
+}
+
+
+/*
  * Description of control commands
  */
 
@@ -2036,12 +2470,12 @@ static cptr ctrl_command_desc[] =
 };
 
 
-#define MAX_YANK 1024
-#define MAX_LINELEN 1024
+#define MAX_YANK MAX_LINELEN
 #define DIRTY_ALL 0x01
 #define DIRTY_COMMAND 0x02
 #define DIRTY_MODE 0x04
-#define DIRTY_SCREEN 0x04
+#define DIRTY_SCREEN 0x08
+#define DIRTY_NOT_FOUND 0x10
 
 /*
  * In-game editor of Object Auto-picker/Destoryer
@@ -2051,7 +2485,9 @@ void do_cmd_edit_autopick(void)
        static int cx = 0, cy = 0;
        static int upper = 0, left = 0;
 
-       cptr last_destroyed;
+        object_type *search_o_ptr = NULL;
+        cptr search_str = NULL;
+        cptr last_destroyed = NULL;
        char last_destroyed_command[WID_DESC+3];
        char yank_buf[MAX_YANK];
        char classrace[80];
@@ -2065,7 +2501,7 @@ void do_cmd_edit_autopick(void)
        int old_upper = -1, old_left = -1;
        int old_cy = -1;
        int key = -1, old_key;
-
+        bool repeated_clearing = FALSE;
        bool edit_mode = FALSE;
 
        byte dirty_flags = DIRTY_ALL | DIRTY_COMMAND | DIRTY_MODE;
@@ -2077,13 +2513,16 @@ void do_cmd_edit_autopick(void)
        init_autopicker();
 
        /* Name of the Last Destroyed Item */
-       last_destroyed = autopick_line_from_entry(&autopick_entry_last_destroyed);
+        if (autopick_last_destroyed_object.k_idx)
+        {
+                autopick_entry_from_object(entry, &autopick_last_destroyed_object);
+                last_destroyed = autopick_line_from_entry_kill(entry);
+        }
 
        /* Command Description of the Last Destroyed Item */
        if (last_destroyed)
        {
-               strcpy(last_destroyed_command, "^L \"");
-               strncpy(last_destroyed_command + 4, last_destroyed, WID_DESC-4);
+               strncpy(last_destroyed_command, format("^L \"%s\"", last_destroyed), WID_DESC+2);
                last_destroyed_command[WID_DESC+2] = '\0';
        }
        else
@@ -2165,7 +2604,7 @@ void do_cmd_edit_autopick(void)
 
                if (dirty_flags & DIRTY_SCREEN)
                {
-                       dirty_flags = DIRTY_ALL | DIRTY_COMMAND | DIRTY_MODE;
+                       dirty_flags |= (DIRTY_ALL | DIRTY_COMMAND | DIRTY_MODE);
 
                        /* Clear screen */
                        Term_clear();
@@ -2257,14 +2696,22 @@ void do_cmd_edit_autopick(void)
                prt (format("(%d,%d)", cx, cy), 0, 70);
 
                /* Display information when updated */
-               if (old_cy != cy || (dirty_flags & DIRTY_ALL) || dirty_line == cy)
+               if (old_cy != cy || (dirty_flags & (DIRTY_ALL | DIRTY_NOT_FOUND)) || dirty_line == cy)
                {
                        /* Clear information line */
                        Term_erase(0, hgt - 3 + 1, wid);
                        Term_erase(0, hgt - 3 + 2, wid);
 
                        /* Display information */
-                       if (lines_list[cy][0] == '#')
+                        if (dirty_flags & DIRTY_NOT_FOUND)
+                        {
+#ifdef JP
+                               prt(format("¥Ñ¥¿¡¼¥ó¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó: %s", search_str), hgt - 3 + 1, 0);
+#else
+                               prt(format("Pattern not found: %s", search_str), hgt - 3 + 1, 0);
+#endif
+                        }
+                       else if (lines_list[cy][0] == '#')
                        {
 #ifdef JP
                                prt("¤³¤Î¹Ô¤Ï¥³¥á¥ó¥È¤Ç¤¹¡£", hgt - 3 + 1, 0);
@@ -2426,11 +2873,26 @@ void do_cmd_edit_autopick(void)
                                break;
                        case '~':
                                if (!autopick_new_entry(entry, lines_list[cy]))
+                                {
+                                        if (old_key != key) repeated_clearing = FALSE;
+
+                                        /* Next line */
+                                        if (lines_list[cy + 1]) cy++;
+                                        cx = 0;
                                        break;
+                                }
                                string_free(lines_list[cy]);
 
+                                if (old_key != key)
+                                {
+                                        if (entry->action & DONT_AUTOPICK)
+                                                repeated_clearing = TRUE;
+                                        else
+                                                repeated_clearing = FALSE;
+                                }
+
                                entry->action &= ~DO_AUTODESTROY;
-                               if (entry->action & DO_AUTOPICK)
+                               if (!repeated_clearing)
                                {
                                        entry->action &= ~DO_AUTOPICK;
                                        entry->action |= DONT_AUTOPICK;
@@ -2441,18 +2903,37 @@ void do_cmd_edit_autopick(void)
                                        entry->action |= DO_AUTOPICK;
                                }
 
-                               lines_list[cy] = autopick_line_from_entry(entry);
+                               lines_list[cy] = autopick_line_from_entry_kill(entry);
 
                                /* Now dirty */
                                dirty_line = cy;
+
+                                /* Next line */
+                                if (lines_list[cy + 1]) cy++;
+                                cx = 0;
                                break;
                        case '!':
                                if (!autopick_new_entry(entry, lines_list[cy]))
+                                {
+                                        if (old_key != key) repeated_clearing = FALSE;
+
+                                        /* Next line */
+                                        if (lines_list[cy + 1]) cy++;
+                                        cx = 0;
                                        break;
+                                }
                                string_free(lines_list[cy]);
 
+                                if (old_key != key)
+                                {
+                                        if (entry->action & DO_AUTODESTROY)
+                                                repeated_clearing = TRUE;
+                                        else
+                                                repeated_clearing = FALSE;
+                                }
+
                                entry->action &= ~DONT_AUTOPICK;
-                               if (entry->action & DO_AUTOPICK)
+                               if (!repeated_clearing)
                                {
                                        entry->action &= ~DO_AUTOPICK;
                                        entry->action |= DO_AUTODESTROY;
@@ -2463,13 +2944,49 @@ void do_cmd_edit_autopick(void)
                                        entry->action |= DO_AUTOPICK;
                                }
 
-                               lines_list[cy] = autopick_line_from_entry(entry);
+                               lines_list[cy] = autopick_line_from_entry_kill(entry);
 
                                /* Now dirty */
                                dirty_line = cy;
+
+                                /* Next line */
+                                if (lines_list[cy + 1]) cy++;
+                                cx = 0;
                                break;
                        case '(':
-                               key = KTRL('g');
+                                /* Toggle display on the 'M'ap */
+                                if (!autopick_new_entry(entry, lines_list[cy]))
+                                {
+                                        if (old_key != key) repeated_clearing = FALSE;
+
+                                        /* Next line */
+                                        if (lines_list[cy + 1]) cy++;
+                                        cx = 0;
+                                        break;
+                                }
+                                string_free(lines_list[cy]);
+
+                                if (old_key != key)
+                                {
+                                        if (entry->action & DO_DISPLAY)
+                                                repeated_clearing = TRUE;
+                                        else
+                                                repeated_clearing = FALSE;
+                                }
+
+                               if (!repeated_clearing)
+                                        entry->action |= DO_DISPLAY;
+                                else
+                                        entry->action &= ~DO_DISPLAY;
+
+                                lines_list[cy] = autopick_line_from_entry_kill(entry);
+
+                                /* Now dirty */
+                                dirty_line = cy;
+
+                                /* Next line */
+                                if (lines_list[cy + 1]) cy++;
+                                cx = 0;
                                break;
                        case '#':
                        case '{':
@@ -2498,6 +3015,89 @@ void do_cmd_edit_autopick(void)
                                while (0 < upper && cy + 1 < upper + hgt - 4)
                                        upper--;
                                break;
+
+                       case 'g':
+                               cy = 0;
+                               break;
+
+                       case 'G':
+                               while (lines_list[cy + 1])
+                                       cy++;
+                               break;
+
+                       case 'm':
+                               /* Erase line */
+                               Term_erase(0, cy - upper + 1, wid - WID_DESC);
+
+                               /* Prompt */
+#ifdef JP
+                               Term_putstr(0, cy - upper + 1, wid - WID_DESC - 1, TERM_YELLOW, "P:<¥È¥ê¥¬¡¼¥­¡¼>: ");
+#else
+                               Term_putstr(0, cy - upper + 1, wid - WID_DESC - 1, TERM_YELLOW, "P:<Trigger key>: ");
+#endif
+                               if (insert_macro_line(lines_list, cy))
+                               {
+                                       /* Prepare to input action */
+                                       cx = 2;
+                                       edit_mode = TRUE;
+
+                                       /* Now dirty */
+                                       dirty_flags |= DIRTY_ALL;
+                                       dirty_flags |= DIRTY_MODE;
+                               }
+
+                               break;
+
+                       case 'c':
+                               /* Erase line */
+                               Term_erase(0, cy - upper + 1, wid - WID_DESC);
+
+                               /* Prompt */
+#ifdef JP
+                               Term_putstr(0, cy - upper + 1, wid - WID_DESC - 1, TERM_YELLOW, format("C:%d:<¥³¥Þ¥ó¥É¥­¡¼>: ", (rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG)));
+#else
+                               Term_putstr(0, cy - upper + 1, wid - WID_DESC - 1, TERM_YELLOW, format("C:%d:<Keypress>: ", (rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG)));
+#endif
+
+                               if (insert_keymap_line(lines_list, cy))
+                               {
+                                       /* Prepare to input action */
+                                       cx = 2;
+                                       edit_mode = TRUE;
+
+                                       /* Now dirty */
+                                       dirty_flags |= DIRTY_ALL;
+                                       dirty_flags |= DIRTY_MODE;
+                               }                               
+                               break;
+                        case '/':
+                               /* Become dirty because of item/equip menu */
+                               dirty_flags |= DIRTY_SCREEN;
+
+                                if (!get_string_for_search(&search_o_ptr, &search_str))
+                                        break;
+
+                                /* fall through */
+                        case 'n':
+                                if (search_o_ptr)
+                                {
+                                        if (!search_for_object(lines_list, search_o_ptr, &cx, &cy, TRUE)) dirty_flags |= DIRTY_NOT_FOUND;
+                                }
+                                else if (search_str)
+                                {
+                                        if (!search_for_string(lines_list, search_str, &cx, &cy, TRUE)) dirty_flags |= DIRTY_NOT_FOUND;
+                                }
+                                break;
+                        case 'N':
+                                if (search_o_ptr)
+                                {
+                                        if (!search_for_object(lines_list, search_o_ptr, &cx, &cy, FALSE)) dirty_flags |= DIRTY_NOT_FOUND;
+                                }
+                                else if (search_str)
+                                {
+                                        if (!search_for_string(lines_list, search_str, &cx, &cy, FALSE)) dirty_flags |= DIRTY_NOT_FOUND;
+                                }
+                                break;
                        }
                }
 
@@ -2572,7 +3172,7 @@ void do_cmd_edit_autopick(void)
                                if (cx > 0) cx--;
                        }
 
-                       lines_list[cy] = autopick_line_from_entry(entry);
+                       lines_list[cy] = autopick_line_from_entry_kill(entry);
 
                        /* Now dirty */
                        dirty_line = cy;
@@ -2585,8 +3185,8 @@ void do_cmd_edit_autopick(void)
                                dirty_flags |= DIRTY_SCREEN;
                                break;
                        }
-                       tmp = autopick_line_from_entry(entry);
-                       autopick_free_entry(entry);
+                       tmp = autopick_line_from_entry_kill(entry);
+
                        if (tmp)
                        {
                                insert_return_code(lines_list, 0, cy);
@@ -2630,7 +3230,7 @@ void do_cmd_edit_autopick(void)
 
                        if (!entry->insc) entry->insc = string_make("");
 
-                       lines_list[cy] = autopick_line_from_entry(entry);
+                       lines_list[cy] = autopick_line_from_entry_kill(entry);
 
                        /* Move to collumn for auto inscription */
                        for (cx = 0; lines_list[cy][cx]; cx++)
@@ -2690,7 +3290,8 @@ void do_cmd_edit_autopick(void)
                                entry->action |= DO_AUTOPICK;
                        }
 
-                       lines_list[cy] = autopick_line_from_entry(entry);
+                       lines_list[cy] = autopick_line_from_entry_kill(entry);
+
                        /* Now dirty */
                        dirty_line = cy;
 
@@ -2740,7 +3341,7 @@ void do_cmd_edit_autopick(void)
                                REM_FLG(FLG_STAR_IDENTIFIED);
                        }
 
-                       lines_list[cy] = autopick_line_from_entry(entry);
+                       lines_list[cy] = autopick_line_from_entry_kill(entry);
 
                        /* Now dirty */
                        dirty_line = cy;
@@ -2788,7 +3389,7 @@ void do_cmd_edit_autopick(void)
                                REM_FLG(FLG_ARTIFACT);
                        }
 
-                       lines_list[cy] = autopick_line_from_entry(entry);
+                       lines_list[cy] = autopick_line_from_entry_kill(entry);
 
                        /* Now dirty */
                        dirty_line = cy;
@@ -2798,18 +3399,32 @@ void do_cmd_edit_autopick(void)
                        /* Paste killed text */
                        if (strlen(yank_buf))
                        {
+                                bool ret = FALSE;
+
                                for (j = 0; yank_buf[j]; j += strlen(yank_buf + j) + 1)
                                {
-                                       int k = j;
+                                        if (ret && '\n' == yank_buf[j])
+                                        {
+                                                ret = FALSE;
+                                                continue;
+                                        }
 
                                        /* Split current line */
                                        insert_return_code(lines_list, cx, cy);
 
-                                       /* Paste yank buffer */
+                                       /* Save preceding string */
                                        for(i = 0; lines_list[cy][i]; i++)
                                                buf[i] = lines_list[cy][i];
-                                       while (yank_buf[k] && i < MAX_LINELEN)
-                                               buf[i++] = yank_buf[k++];
+
+                                       /* Paste yank buffer */
+                                        if ('\n' != yank_buf[j])
+                                        {
+                                                int k = j;
+                                                while (yank_buf[k] && i < MAX_LINELEN-1)
+                                                        buf[i++] = yank_buf[k++];
+                                                ret = TRUE;
+                                        }
+
                                        buf[i] = '\0';
 
                                        string_free(lines_list[cy]);
@@ -2833,41 +3448,55 @@ void do_cmd_edit_autopick(void)
 
                case KTRL('k'):
                        /* Kill rest of line */
-                       if (lines_list[cy][0] != '\0' && (uint)cx < strlen(lines_list[cy]))
-                       {
-                               /* Save preceding string */
-                               for (i = 0; lines_list[cy][i] && i < cx; i++)
-                               {
+                       if ((uint)cx > strlen(lines_list[cy]))
+                                cx = (int)strlen(lines_list[cy]);
+
+                        /* Save preceding string */
+                        for (i = 0; lines_list[cy][i] && i < cx; i++)
+                        {
 #ifdef JP
-                                       if (iskanji(lines_list[cy][i]))
-                                       {
-                                               buf[i] = lines_list[cy][i];
-                                               i++;
-                                       }
+                                if (iskanji(lines_list[cy][i]))
+                                {
+                                        buf[i] = lines_list[cy][i];
+                                        i++;
+                                }
 #endif
-                                       buf[i] = lines_list[cy][i];
-                               }
-                               buf[i] = '\0';
-
-                               j = 0;
-                               if (old_key == KTRL('k'))
-                                       while (yank_buf[j])
-                                               j += strlen(yank_buf + j) + 1;
+                                buf[i] = lines_list[cy][i];
+                        }
+                        buf[i] = '\0';
+
+                        j = 0;
+                        if (old_key == key)
+                                while (yank_buf[j])
+                                        j += strlen(yank_buf + j) + 1;
+
+                        /* Copy following to yank buffer */
+                        if (lines_list[cy][i])
+                        {
+                                while (lines_list[cy][i] && j < MAX_YANK - 2)
+                                        yank_buf[j++] = lines_list[cy][i++];
+                                i = TRUE;
+                        }
+                        else
+                        {
+                                if (j < MAX_YANK - 2)
+                                        yank_buf[j++] = '\n';
+                                i = FALSE;
+                        }
+                        yank_buf[j++] = '\0';
+                        yank_buf[j] = '\0';
+
+                        /* Replace current line with 'preceding string' */
+                        string_free(lines_list[cy]);
+                        lines_list[cy] = string_make(buf);
+
+                        if (i)
+                        {
+                                /* Now dirty */
+                                dirty_line = cy;
+                                break;
+                        }
 
-                               /* Copy following to yank buffer */
-                               while (lines_list[cy][i] && j < MAX_YANK - 2)
-                                       yank_buf[j++] = lines_list[cy][i++];
-                               yank_buf[j++] = '\0';
-                               yank_buf[j] = '\0';
-
-                               /* Replace current line with 'preceding string' */
-                               string_free(lines_list[cy]);
-                               lines_list[cy] = string_make(buf);
-
-                               /* Now dirty */
-                               dirty_line = cy;
-                               break;                  
-                       }
                        /* fall through */
                case KTRL('d'):
                case 0x7F: