*** empty log message ***
[m17n/m17n-lib.git] / src / input.c
index e7bbcff..9edb55e 100644 (file)
@@ -1448,14 +1448,12 @@ update_custom_info (void)
       if (! MPLIST_SYMBOL_P (p))
        continue;
       name = MPLIST_SYMBOL (p);
-      if (language == Mnil || name == Mnil)
-       continue;
       p = MPLIST_NEXT (p);
       if (MPLIST_TAIL_P (p))
        extra = Mnil;
       else if (MPLIST_SYMBOL_P (p))
        extra = MPLIST_SYMBOL (p);
-      else
+      if (language == Mnil || (name == Mnil && extra == Mnil))
        continue;
       im_info = new_im_info (NULL, language, name, extra, im_custom_list);
       load_im_info (im_data, im_info);
@@ -1746,52 +1744,52 @@ config_command (MPlist *plist, MPlist *global_cmds, MPlist *custom_cmds,
   MPlist *global = NULL, *custom = NULL, *config = NULL;
   MSymbol name;
   MSymbol status;
-  MPlist *description = NULL, *keyseq;
+  MPlist *description, *keyseq;
+
+  if (global_cmds && (global = mplist__assq (global_cmds, name)))
+    global = MPLIST_NEXT (MPLIST_PLIST (global));  
 
   name = MPLIST_SYMBOL (plist);
   plist = MPLIST_NEXT (plist);
   if (MPLIST_MTEXT_P (plist) || MPLIST_PLIST_P (plist))
-    description = plist;
-  else if (global_cmds && ((global = mplist__assq (global_cmds, name))))
-    description = global = MPLIST_NEXT (MPLIST_PLIST (global));
-  if (MPLIST_TAIL_P (plist))
     {
-      if (! global
-         && global_cmds && ((global = mplist__assq (global_cmds, name))))
-       global = MPLIST_NEXT (MPLIST_PLIST (global));
-      if (global)
-       {
-         keyseq = MPLIST_NEXT (global);
-         status = Minherited;
-       }
-      else
-       {
-         keyseq = plist;
-         status = Mnil;
-       }
+      description = plist;
+      plist = MPLIST_NEXT (plist);
     }
   else
     {
-      keyseq = MPLIST_NEXT (plist);
+      description = global;
+      if (! MPLIST_TAIL_P (plist))
+       plist = MPLIST_NEXT (plist);
+    }
+  if (MPLIST_TAIL_P (plist) && global)
+    {
+      keyseq = MPLIST_NEXT (global);
+      status = Minherited;
+    }
+  else
+    {
+      keyseq = plist;
       status = Mnil;
     }
 
   if (config_cmds && (config = mplist__assq (config_cmds, name)))
     {
+      status = Mconfigured;
       config = MPLIST_NEXT (MPLIST_PLIST (config));
       if (! MPLIST_TAIL_P (config))
-       {
-         keyseq = MPLIST_NEXT (config);
-         status = Mconfigured;
-       }
+       keyseq = config;
     }
   else if (custom_cmds && (custom = mplist__assq (custom_cmds, name)))
     {
-      custom = MPLIST_NEXT (MPLIST_PLIST (custom));
-      if (! MPLIST_TAIL_P (custom))
+      MPlist *this_keyseq = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (custom)));
+
+      if (MPLIST_TAIL_P (this_keyseq))
+       mplist__pop_unref (custom);
+      else
        {
-         keyseq = MPLIST_NEXT (custom);
          status = Mcustomized;
+         keyseq = this_keyseq;
        }
     }
   
@@ -2069,21 +2067,24 @@ config_variable (MPlist *plist, MPlist *global_vars, MPlist *custom_vars,
 
   if (config_vars && (config = mplist__assq (config_vars, name)))
     {
+      status = Mconfigured;
       config = MPLIST_NEXT (MPLIST_PLIST (config));
       if (! MPLIST_TAIL_P (config))
        {
-         value = MPLIST_NEXT (config);
+         value = config;
          if (MFAILP (check_variable_value (value, global ? global : plist)))
            value = NULL;
-         status = Mconfigured;
        }
     }
   else if (custom_vars && (custom = mplist__assq (custom_vars, name)))
     {
-      custom = MPLIST_NEXT (MPLIST_PLIST (custom));
-      if (! MPLIST_TAIL_P (custom))
+      MPlist *this_value = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (custom)));
+
+      if (MPLIST_TAIL_P (this_value))
+       mplist__pop_unref (custom);
+      else
        {
-         value = MPLIST_NEXT (custom);
+         value = this_value;
          if (MFAILP (check_variable_value (value, global ? global : plist)))
            value = NULL;
          status = Mcustomized;
@@ -2757,7 +2758,8 @@ get_candidate_list (MInputContextInfo *ic_info, MPlist *args)
                  next = MPLIST_NEXT (next);
                }
            }
-         M17N_OBJECT_UNREF (plist);
+         if (charset)
+           M17N_OBJECT_UNREF (plist);
          plist = mplist ();
          len = mtext_nchars (mt);
          if (len <= column)
@@ -3178,8 +3180,8 @@ take_action_list (MInputContext *ic, MPlist *action_list)
                = (MIMExternalModule *) mplist_get (im_info->externals,
                                                    module);
              if (external)
-               func = (MIMExternalFunc) mplist_get (external->func_list,
-                                                    func_name);
+               func = ((MIMExternalFunc)
+                       mplist_get_func (external->func_list, func_name));
            }
          if (! func)
            continue;
@@ -3544,7 +3546,7 @@ init_ic_info (MInputContext *ic)
        {
          MIMExternalModule *external = MPLIST_VAL (plist);
          MIMExternalFunc func
-           = (MIMExternalFunc) mplist_get (external->func_list, Minit);
+           = (MIMExternalFunc) mplist_get_func (external->func_list, Minit);
 
          if (func)
            (func) (func_args);
@@ -3573,7 +3575,7 @@ fini_ic_info (MInputContext *ic)
        {
          MIMExternalModule *external = MPLIST_VAL (plist);
          MIMExternalFunc func
-           = (MIMExternalFunc) mplist_get (external->func_list, Mfini);
+           = (MIMExternalFunc) mplist_get_func (external->func_list, Mfini);
 
          if (func)
            (func) (func_args);
@@ -3947,8 +3949,8 @@ minput__init ()
   minput_default_driver.filter = filter;
   minput_default_driver.lookup = lookup;
   minput_default_driver.callback_list = mplist ();
-  mplist_put (minput_default_driver.callback_list, Minput_reset,
-             (void *) reset_ic);
+  mplist_put_func (minput_default_driver.callback_list, Minput_reset,
+                  M17N_FUNC (reset_ic));
   minput_driver = &minput_default_driver;
 
   fully_initialized = 0;
@@ -4785,7 +4787,7 @@ minput_get_description (MSymbol language, MSymbol name)
 
     @c STATUS is a symbol representing how the key assignment is decided.
     The value is #Mnil (the default key assignment), #Mcustomized (the
-    key assignment is customized by per-user configuration file), or
+    key assignment is customized by per-user customization file), or
     #Mconfigured (the key assignment is set by the call of
     minput_config_command ()).  For a local command only, it may also
     be #Minherited (the key assignment is inherited from the
@@ -4837,12 +4839,13 @@ minput_get_description (MSymbol language, MSymbol name)
     @c DESCRIPTION ¤Ï¥³¥Þ¥ó¥É¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¤«¡¢ÀâÌÀ¤¬Ìµ¤¤¾ì¹ç¤Ë
     ¤Ï #Mnil ¤Ç¤¢¤ë¡£
 
-    @c STATUS ¤Ï¥­¡¼³ä¤êÅö¤Æ¤¬¤É¤Î¤è¤¦¤ËÄê¤á¤é¤ì¤ë¤«¤ò¤¢¤é¤ï¤¹¥·¥ó¥Ü¥ë¤Ç¤¢
-    ¤ê¡¢¤½¤ÎÃͤϠ#Mnil ¡Ê¥Ç¥Õ¥©¥ë¥È¤Î³ä¤êÅö¤Æ¡Ë, #Mcustomized ¡Ê¥æ¡¼¥¶
-    Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤Ë¤è¤Ã¤Æ¥«¥¹¥¿¥Þ¥¤¥º¤µ¤ì¤¿³ä¤êÅö¤Æ¡Ë, #Mconfigured
-    ¡Êminput_config_command ()¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÀßÄꤵ¤ì¤ë³ä¤êÅö¤Æ¡Ë¤Î
-    ¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤Î¾ì¹ç¤Ë¤Ï¡¢#Minherited ¡ÊÂбþ¤¹¤ë
-    ¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤«¤é¤Î·Ñ¾µ¤Ë¤è¤ë³ä¤êÅö¤Æ¡Ë¤Ç¤â¤è¤¤¡£
+    @c STATUS ¤Ï¥­¡¼³ä¤êÅö¤Æ¤¬¤É¤Î¤è¤¦¤ËÄê¤á¤é¤ì¤ë¤«¤ò¤¢¤é¤ï¤¹¥·¥ó¥Ü¥ë
+    ¤Ç¤¢¤ê¡¢¤½¤ÎÃͤϠ#Mnil ¡Ê¥Ç¥Õ¥©¥ë¥È¤Î³ä¤êÅö¤Æ¡Ë, #Mcustomized ¡Ê¥æ¡¼
+    ¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤Ë¤è¤Ã¤Æ¥«¥¹¥¿¥Þ¥¤¥º¤µ¤ì¤¿³ä¤êÅö¤Æ¡Ë,
+    #Mconfigured ¡Êminput_config_command ()¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÀßÄꤵ¤ì¤ë
+    ³ä¤êÅö¤Æ¡Ë¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤Î¾ì¹ç¤Ë¤Ï¡¢
+    #Minherited ¡ÊÂбþ¤¹¤ë¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤«¤é¤Î·Ñ¾µ¤Ë¤è¤ë³ä¤êÅö¤Æ¡Ë
+    ¤Ç¤â¤è¤¤¡£
 
     @c KEYSEQ ¤Ï£±¤Ä°Ê¾å¤Î¥·¥ó¥Ü¥ë¤«¤é¤Ê¤ë plist ¤Ç¤¢¤ê¡¢³Æ¥·¥ó¥Ü¥ë¤Ï¥³¥Þ
     ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤òɽ¤¹¡£KEYSEQ ¤¬Ìµ¤¤¾ì¹ç¤Ï¡¢
@@ -4872,8 +4875,8 @@ get_im_command_description (MSymbol language, MSymbol name, MSymbol command)
 
   if (! cmds)
     return NULL;
-  plist = mplist_value (cmds); /* (NAME DESCRIPTION KEY-SEQ ...) */
-  plist = mplist_next (plist); /* (DESCRIPTION KEY-SEQ ...) */
+  plist = mplist_value (cmds); /* (NAME DESCRIPTION STATUS KEY-SEQ ...) */
+  plist = mplist_next (plist); /* (DESCRIPTION STATUS KEY-SEQ ...) */
   return  (mplist_key (plist) == Mtext
           ? (MText *) mplist_value (plist)
           : NULL);
@@ -4909,12 +4912,16 @@ minput_get_command (MSymbol language, MSymbol name, MSymbol command)
     If $KEYSEQLIST is a non-empty plist, it must be a list of key
     sequences, and each key sequence must be a plist of symbols.
 
-    If $KEYSEQLIST is an empty plist, the command becomes unusable.
+    If $KEYSEQLIST is an empty plist, any configuration and
+    customization of the command are cancelled, and default key
+    sequences become effective.
+
+    If $KEYSEQLIST is NULL, the configuration of the command is
+    canceled, and the original key sequences (what saved in per-user
+    customization file, or the default one) become effective.
 
-    If $KEYSEQLIST is NULL, the configuration of the command for the
-    input method is canceled, and the default key sequences become
-    effective.  In such case, if $COMMAND is #Mnil, configurations for
-    all commands of the input method are canceled.
+    In the latter two cases, $COMMAND can be #Mnil to make all the
+    commands of the input method the target of the operation.
 
     If $NAME is #Mnil, this function configures the key assignment of a
     global command, not that of a specific input method.
@@ -4922,11 +4929,10 @@ minput_get_command (MSymbol language, MSymbol name, MSymbol command)
     The configuration takes effect for input methods opened or
     re-opened later in the current session.  In order to make the
     configuration take effect for the future session, it must be saved
-    in a per-user configuration file by the function
+    in a per-user customization file by the function
     minput_save_config ().
 
     @return
-
     If the operation was successful, this function returns 0,
     otherwise returns -1.  The operation fails in these cases:
     <ul>
@@ -4948,20 +4954,23 @@ minput_get_command (MSymbol language, MSymbol name, MSymbol command)
     $KEYSEQLIST ¤¬¶õ¥ê¥¹¥È¤Ç¤Ê¤±¤ì¤Ð¡¢¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Î¥ê¥¹¥È¤Ç¤¢¤ê¡¢
     ³Æ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥·¥ó¥Ü¥ë¤Î plist ¤Ç¤¢¤ë¡£
 
-    $KEYSEQLIST ¤¬¶õ¤Î plist ¤Ê¤é¤Ð¡¢¥³¥Þ¥ó¥É¤Ï»ÈÍѤǤ­¤Ê¤¯¤Ê¤ë¡£
+    $KEYSEQLIST ¤¬¶õ¤Î plist ¤Ê¤é¤Ð¡¢¤½¤Î¥³¥Þ¥ó¥É¤ÎÀßÄê¤ä¥«¥¹¥¿¥Þ¥¤¥º¤Ï
+    ¤¹¤Ù¤Æ¥­¥ã¥ó¥»¥ë¤µ¤ì¡¢¥Ç¥Õ¥©¥ë¥È¤Î¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬Í­¸ú¤Ë¤Ê¤ë¡£
+
+    $KEYSEQLIST ¤¬ NULL ¤Ç¤¢¤ì¤Ð¡¢¤½¤Î¥³¥Þ¥ó¥É¤ÎÀßÄê¤Ï¥­¥ã¥ó¥»¥ë¤µ¤ì¡¢
+    ¸µ¤Î¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¡Ê¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤ËÊݸ¤µ¤ì¤Æ¤¤
+    ¤ë¤â¤Î¡¢¤¢¤ë¤¤¤Ï¥Ç¥Õ¥©¥ë¥È¤Î¤â¤Î¡Ë¤¬Í­¸ú¤Ë¤Ê¤ë¡£
 
-    $KEYSEQLIST ¤¬ NULL ¤Ç¤¢¤ì¤Ð¡¢»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤ÎÀßÄê¤Ï
-    ¥­¥ã¥ó¥»¥ë¤µ¤ì¡¢¥Ç¥Õ¥©¥ë¥È¤Î¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬Í­¸ú¤Ë¤Ê¤ë¡£¤³¤Î¾ì¹ç¡¢
-    $COMMAND ¤¬ #Mnil ¤Ê¤é¤Ð»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÁ´¤Æ¤Î¥³¥Þ¥ó¥É¤ÎÀßÄ꤬
-    ¥­¥ã¥ó¥»¥ë¤µ¤ì¤ë¡£
+    ¸å¤Î¤Õ¤¿¤Ä¤Î¾ì¹ç¤Ë¤Ï¡¢$COMMAND ¤Ï #Mnil ¤ò¤È¤ë¤³¤È¤¬¤Ç¤­¡¢»ØÄê¤ÎÆþ
+    Îϥ᥽¥Ã¥É¤ÎÁ´¤Æ¤Î¥³¥Þ¥ó¥ÉÀßÄê¤Î¥­¥ã¥ó¥»¥ë¤ò°ÕÌ£¤¹¤ë¡£
 
     $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¤Ê¤¯¥°¥í¡¼¥Ð
     ¥ë¤Ê¥³¥Þ¥ó¥É¤Î¥­¡¼³ä¤êÅö¤Æ¤òÀßÄꤹ¤ë¡£
 
     ¤³¤ì¤é¤ÎÀßÄê¤Ï¡¢¸½¹Ô¤Î¥»¥Ã¥·¥ç¥óÃæ¤ÇÆþÎϥ᥽¥Ã¥É¤¬¥ª¡¼¥×¥ó¡Ê¤Þ¤¿¤Ï
     ºÆ¥ª¡¼¥×¥ó¡Ë¤µ¤ì¤¿»þÅÀ¤ÇÍ­¸ú¤Ë¤Ê¤ë¡£¾­Íè¤Î¥»¥Ã¥·¥ç¥óÃæ¤Ç¤âÍ­¸ú¤Ë¤¹
-    ¤ë¤¿¤á¤Ë¤Ï¡¢´Ø¿ô minput_save_config () ¤òÍѤ¤¤Æ¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤
-    ¥ë¤ËÊݸ¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+    ¤ë¤¿¤á¤Ë¤Ï¡¢´Ø¿ô minput_save_config () ¤òÍѤ¤¤Æ¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤
+    ¥º¥Õ¥¡¥¤¥ë¤ËÊݸ¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
 
     @return
 
@@ -4984,18 +4993,17 @@ minput_get_command (MSymbol language, MSymbol name, MSymbol command)
   MPlist *cmd, *plist, *key_seq_list, *key_seq;
 
   /* At first get the current key-sequence assignment.  */
-  cmd = mplist_get_command (Mt, unicode, start_command);
+  cmd = minput_get_command (Mt, unicode, start_command);
   if (! cmd)
     {
       /* The input method does not have the command "start".  Here
         should come some error handling code.  */
     }
-  /* Now CMD == ((start DESCRIPTION KEY-SEQUENCE ...) ...).  Extract
-     the part (KEY-SEQUENCE ...).  */
-  plist = mplist_next (mplist_next (mplist_value (cmd)));
+  /* Now CMD == ((start DESCRIPTION STATUS KEY-SEQUENCE ...) ...).
+     Extract the part (KEY-SEQUENCE ...).  */
+  plist = mplist_next (mplist_next (mplist_next (mplist_value (cmd))));
   /* Copy it because we should not modify it directly.  */
   key_seq_list = mplist_copy (plist);
-  m17n_object_unref (cmds);
   
   key_seq = mplist ();
   mplist_add (key_seq, Msymbol, msymbol ("C-x"));
@@ -5017,23 +5025,19 @@ minput_config_command (MSymbol language, MSymbol name, MSymbol command,
 
   MINPUT__INIT ();
 
-  if (keyseqlist)
-    {
-      if (command == Mnil)
-       MERROR (MERROR_IM, -1);
-      MPLIST_DO (plist, keyseqlist)
-       if (! MPLIST_PLIST_P (plist)
-           || ! check_command_keyseq (plist))
-         MERROR (MERROR_IM, -1);
-    }
-
   im_info = get_im_info (language, name, Mnil, Mcommand);
   if (! im_info)
     MERROR (MERROR_IM, -1);
-  if (command != Mnil
-      && (! im_info->cmds
-         || ! mplist__assq (im_info->cmds, command)))
+  if (command == Mnil ? (keyseqlist && ! MPLIST_TAIL_P (keyseqlist))
+      : (! im_info->cmds
+        || ! mplist__assq (im_info->configured_cmds, command)))
     MERROR (MERROR_IM, -1);
+  if (keyseqlist && ! MPLIST_TAIL_P (keyseqlist))
+    {
+      MPLIST_DO (plist, keyseqlist)
+       if (! check_command_keyseq (plist))
+         MERROR (MERROR_IM, -1);
+    }
 
   config = get_config_info (im_info);
   if (! config)
@@ -5045,13 +5049,29 @@ minput_config_command (MSymbol language, MSymbol name, MSymbol command,
       config->vars = mplist ();
     }
 
+  if (! keyseqlist && MPLIST_TAIL_P (config->cmds))
+    /* Nothing to do.  */
+    return 0;
+
   if (command == Mnil)
     {
-      MInputMethodInfo *custom = get_custom_info (im_info);
-
-      mplist_set (config->cmds, Mnil, NULL);
-      if (custom && custom->cmds)
+      if (! keyseqlist)
        {
+         /* Cancal the configuration. */
+         if (MPLIST_TAIL_P (config->cmds))
+           return 0;
+         mplist_set (config->cmds, Mnil, NULL);
+       }
+      else
+       {
+         /* Cancal the customization. */
+         MInputMethodInfo *custom = get_custom_info (im_info);
+
+         if (MPLIST_TAIL_P (config->cmds)
+             && (! custom || ! custom->cmds || MPLIST_TAIL_P (custom->cmds)))
+           /* Nothing to do.  */
+           return 0;
+         mplist_set (config->cmds, Mnil, NULL);
          MPLIST_DO (plist, custom->cmds)
            {
              command = MPLIST_SYMBOL (MPLIST_PLIST (plist));
@@ -5065,26 +5085,58 @@ minput_config_command (MSymbol language, MSymbol name, MSymbol command,
   else
     {
       plist = mplist__assq (config->cmds, command);
-      if (plist)
+      if (! keyseqlist)
        {
-         plist = MPLIST_PLIST (plist); /* (NAME [nil KEY-SEQUENCE ...])  */
-         plist = MPLIST_NEXT (plist);  /* ([nil ...]) */
-         if (! MPLIST_TAIL_P (plist))
-           mplist_set (plist, Mnil, NULL); /* () */
+         /* Cancel the configuration.  */
+         if (! plist)
+           return 0;
+         mplist__pop_unref (plist);
        }
-      else
+      else if (MPLIST_TAIL_P (keyseqlist))
        {
-         plist = mplist ();
-         mplist_add (config->cmds, Mplist, plist);
-         M17N_OBJECT_UNREF (plist);
-         plist = mplist_add (plist, Msymbol, command);
-         plist = MPLIST_NEXT (plist);
+         /* Cancel the customization.  */
+         MInputMethodInfo *custom = get_custom_info (im_info);
+         int no_custom = (! custom || ! custom->cmds
+                          || ! mplist__assq (custom->cmds, command));
+         if (! plist)
+           {
+             if (no_custom)
+               return 0;
+             plist = mplist ();
+             mplist_add (config->cmds, Mplist, plist);
+             M17N_OBJECT_UNREF (plist);
+             plist = mplist_add (plist, Msymbol, command);
+           }
+         else
+           {
+             if (no_custom)
+               mplist__pop_unref (plist);
+             else
+               {
+                 plist = MPLIST_PLIST (plist); /* (NAME nil KEYSEQ ...) */
+                 plist = MPLIST_NEXT (plist);
+                 mplist_set (plist, Mnil, NULL);
+               }
+           }
        }
-      if (keyseqlist)
+      else
        {
          MPlist *pl;
 
-         plist = mplist_add (plist, Msymbol, Mnil);
+         if (plist)
+           {
+             plist = MPLIST_NEXT (MPLIST_PLIST (plist));
+             if (! MPLIST_TAIL_P (plist))
+               mplist_set (plist, Mnil, NULL);
+           }
+         else
+           {
+             plist = mplist ();
+             mplist_add (config->cmds, Mplist, plist);
+             M17N_OBJECT_UNREF (plist);
+             plist = mplist_add (plist, Msymbol, command);
+             plist = MPLIST_NEXT (plist);
+           }
          MPLIST_DO (keyseqlist, keyseqlist)
            {
              pl = mplist_copy (MPLIST_VAL (keyseqlist));
@@ -5104,7 +5156,7 @@ minput_config_command (MSymbol language, MSymbol name, MSymbol command,
     @brief Get information about input method variable(s).
 
     The minput_get_variable () function returns information about
-    the variable $VARIABLE of the input method specified by $LANGUAGE and $NAME.
+    variable $VARIABLE of the input method specified by $LANGUAGE and $NAME.
     An input method variable controls behavior of an input method.
 
     There are two kinds of variables, global and local.  A global
@@ -5133,7 +5185,7 @@ minput_config_command (MSymbol language, MSymbol name, MSymbol command,
 
     @c STATUS is a symbol representing how the value is decided.  The
     value is #Mnil (the default value), #Mcustomized (the value is
-    customized by per-user configuration file), or #Mconfigured (the
+    customized by per-user customization file), or #Mconfigured (the
     value is set by the call of minput_config_variable ()).  For a
     local variable only, it may also be #Minherited (the value is
     inherited from the corresponding global variable).
@@ -5192,8 +5244,8 @@ minput_config_command (MSymbol language, MSymbol name, MSymbol command,
     #Mnil ¤Ç¤¢¤ë¡£
 
     @c STATUS ¤ÏÃͤ¬¤É¤Î¤è¤¦¤ËÄê¤á¤é¤ì¤ë¤«¤ò¤¢¤é¤ï¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢
-    @c STATUS ¤ÎÃͤϠ#Mnil ¡Ê¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¡Ë, #Mcustomized ¡Ê¥æ¡¼¥¶Ëè¤ÎÀß
-    Äê¥Õ¥¡¥¤¥ë¤Ë¤è¤Ã¤Æ¥«¥¹¥¿¥Þ¥¤¥º¤µ¤ì¤¿ÃÍ¡Ë, #Mconfigured
+    @c STATUS ¤ÎÃͤϠ#Mnil ¡Ê¥Ç¥Õ¥©¥ë¥È¤ÎÃÍ¡Ë, #Mcustomized ¡Ê¥æ¡¼¥¶Ëè¤Î
+    ¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤Ë¤è¤Ã¤Æ¥«¥¹¥¿¥Þ¥¤¥º¤µ¤ì¤¿ÃÍ¡Ë, #Mconfigured
     ¡Êminput_config_variable ()¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÀßÄꤵ¤ì¤ëÃ͡ˤΤ¤¤º¤ì
     ¤«¤Ç¤¢¤ë¡£¥í¡¼¥«¥ëÊÑ¿ô¤Î¾ì¹ç¤Ë¤Ï¡¢#Minherited ¡ÊÂбþ¤¹¤ë¥°¥í¡¼¥Ð¥ë
     ÊÑ¿ô¤«¤é·Ñ¾µ¤·¤¿Ã͡ˤǤâ¤è¤¤¡£
@@ -5246,22 +5298,28 @@ minput_get_variable (MSymbol language, MSymbol name, MSymbol variable)
     variable $VARIABLE of the input method specified by $LANGUAGE and
     $NAME.
 
-    If $VALUE is not NULL, it must be a plist of one element whose key
-    is #Minteger, #Msymbol, or #Mtext, and the value is of the
-    corresponding type.
+    If $VALUE is a non-empty plist, it must be a plist of one element
+    whose key is #Minteger, #Msymbol, or #Mtext, and the value is of
+    the corresponding type.  That value is assigned to the variable.
 
-    If $VALUE is NULL, a configuration for the variable for the input
-    method is canceled, and the variable is initialized to the default
-    value.  In that case, if $VARIABLE is #Mnil, configurations for
-    all variables of the input method are canceled.
+    If $VALUE is an empty plist, any configuration and customization
+    of the variable are canceled, and the default value is assigned to
+    the variable.
 
-    If $NAME is #Mnil, this function configure the value of global
+    If $VALUE is NULL, the configuration of the variable is canceled,
+    and the original value (what saved in per-user customization file,
+    or the default value) is assigned to the variable.
+
+    In the latter two cases, $VARIABLE can be #Mnil to make all the
+    variables of the input method the target of the operation.
+
+    If $NAME is #Mnil, this function configures the value of global
     variable, not that of a specific input method.
 
     The configuration takes effect for input methods opened or
     re-opened later in the current session.  To make the configuration
     take effect for the future session, it must be saved in a per-user
-    configuration file by the function minput_save_config ().
+    customization file by the function minput_save_config ().
 
     @return
 
@@ -5282,20 +5340,26 @@ minput_get_variable (MSymbol language, MSymbol name, MSymbol variable)
     ´Ø¿ô minput_config_variable () ¤ÏÃÍ $VALUE ¤ò¡¢$LANGUAGE ¤È $NAME
     ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô $VARIABLE ¤Ë³ä¤êÅö¤Æ¤ë¡£
 
-    $VALUE ¤¬ NULL¤Ç¤Ê¤±¤ì¤Ð¡¢£±Í×ÁǤΠplist ¤Ç¤¢¤ê¡¢¤½¤Î¥­¡¼¤Ï
+    $VALUE ¤¬ ¶õ¥ê¥¹¥È¤Ç¤Ê¤±¤ì¤Ð¡¢£±Í×ÁǤΠplist ¤Ç¤¢¤ê¡¢¤½¤Î¥­¡¼¤Ï
     #Minteger, #Msymbol, #Mtext ¤Î¤¤¤º¤ì¤«¡¢ÃͤÏÂбþ¤¹¤ë·¿¤Î¤â¤Î¤Ç¤¢¤ë¡£
+    ¤³¤ÎÃͤ¬ÊÑ¿ô $VARIABLE ¤Ë³ä¤êÅö¤Æ¤é¤ì¤ë¡£
+
+    $VALUE ¤¬ ¶õ¥ê¥¹¥È¤Ç¤¢¤ì¤Ð¡¢ÊÑ¿ô¤ÎÀßÄê¤È¥«¥¹¥¿¥Þ¥¤¥º¤¬¥­¥ã¥ó¥»¥ë¤µ
+    ¤ì¡¢¥Ç¥Õ¥©¥ë¥ÈÃͤ¬ÊÑ¿ô $VARIABLE ¤Ë³ä¤êÅö¤Æ¤é¤ì¤ë¡£
 
-    $VALUE ¤¬ NULL ¤Ç¤¢¤ì¤Ð¡¢»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÊÑ¿ô¤ÎÀßÄê¤Ï¥­¥ã¥ó¥»¥ë
-    ¤µ¤ì¡¢ÊÑ¿ô¤Ï¥Ç¥Õ¥©¥ë¥ÈÃͤ˽é´ü²½¤µ¤ì¤ë¡£¤³¤Î¾ì¹ç¡¢$VARIABLE ¤¬
-    #Mnil ¤Ê¤é¤Ð»ØÄê¤ÎÆþÎϥ᥽¥Ã¥É¤ÎÁ´¤Æ¤ÎÊÑ¿ô¤ÎÀßÄ꤬¥­¥ã¥ó¥»¥ë¤µ¤ì¤ë¡£
+    $VALUE ¤¬ NULL ¤Ç¤¢¤ì¤Ð¡¢ÊÑ¿ô¤ÎÀßÄê¤Ï¥­¥ã¥ó¥»¥ë¤µ¤ì¡¢¸µ¤ÎÃ͡ʥ桼¥¶
+    Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ëÃæ¤ÎÃÍ¡¢¤Þ¤¿¤Ï¥Ç¥Õ¥©¥ë¥È¤ÎÃ͡ˤ¬³ä¤êÅö¤Æ¤é¤ì¤ë¡£
+
+    ¸å¤Î¤Õ¤¿¤Ä¤Î¾ì¹ç¤Ë¤Ï¡¢$VARIABLE ¤Ï #Mnil ¤ò¤È¤ë¤³¤È¤¬¤Ç¤­¡¢»ØÄꤵ¤ì
+    ¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÁ´¤Æ¤ÎÊÑ¿ôÀßÄê¤Î¥­¥ã¥ó¥»¥ë¤ò°ÕÌ£¤¹¤ë¡£
 
     $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢¤³¤Î´Ø¿ô¤Ï¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¤Ê¤¯¥°¥í¡¼¥Ð
     ¥ë¤ÊÊÑ¿ô¤ÎÃͤòÀßÄꤹ¤ë¡£
 
     ¤³¤ì¤é¤ÎÀßÄê¤Ï¡¢¸½¹Ô¤Î¥»¥Ã¥·¥ç¥óÃæ¤ÇÆþÎϥ᥽¥Ã¥É¤¬¥ª¡¼¥×¥ó¡Ê¤Þ¤¿¤Ï
     ºÆ¥ª¡¼¥×¥ó¡Ë¤µ¤ì¤¿»þÅÀ¤ÇÍ­¸ú¤Ë¤Ê¤ë¡£¾­Íè¤Î¥»¥Ã¥·¥ç¥óÃæ¤Ç¤âÍ­¸ú¤Ë¤¹
-    ¤ë¤¿¤á¤Ë¤Ï¡¢´Ø¿ô minput_save_config () ¤òÍѤ¤¤Æ¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤
-    ¥ë¤ËÊݸ¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+    ¤ë¤¿¤á¤Ë¤Ï¡¢´Ø¿ô minput_save_config () ¤òÍѤ¤¤Æ¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤
+    ¥º¥Õ¥¡¥¤¥ë¤ËÊݸ¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
 
     @return
 
@@ -5321,16 +5385,12 @@ minput_config_variable (MSymbol language, MSymbol name, MSymbol variable,
   im_info = get_im_info (language, name, Mnil, Mvariable);
   if (! im_info)
     MERROR (MERROR_IM, -1);
-  if (variable == Mnil)
-    {
-      if (value)
-       MERROR (MERROR_IM, -1);
-    }
-  else if (! im_info->vars
-          || ! (plist = mplist__assq (im_info->configured_vars, variable)))
+  if (variable == Mnil ? (value && ! MPLIST_TAIL_P (value))
+      : (! im_info->vars
+        || ! (plist = mplist__assq (im_info->configured_vars, variable))))
     MERROR (MERROR_IM, -1);
 
-  if (variable != Mnil && value)
+  if (value && ! MPLIST_TAIL_P (value))
     {
       plist = MPLIST_PLIST (plist);
       plist = MPLIST_NEXT (plist); /* (DESC STATUS VALUE VALIDS ...) */
@@ -5351,13 +5411,29 @@ minput_config_variable (MSymbol language, MSymbol name, MSymbol variable,
       config->vars = mplist ();
     }
 
+  if (! value && MPLIST_TAIL_P (config->vars))
+    /* Nothing to do.  */
+    return 0;
+
   if (variable == Mnil)
     {
-      MInputMethodInfo *custom = get_custom_info (im_info);
-
-      mplist_set (config->vars, Mnil, NULL);
-      if (custom && custom->cmds)
+      if (! value)
+       {
+         /* Cancel the configuration.  */
+         if (MPLIST_TAIL_P (config->vars))
+           return 0;
+         mplist_set (config->vars, Mnil, NULL);
+       }
+      else
        {
+         /* Cancel the customization.  */
+         MInputMethodInfo *custom = get_custom_info (im_info);
+
+         if (MPLIST_TAIL_P (config->vars)
+             && (! custom || ! custom->vars || MPLIST_TAIL_P (custom->vars)))
+           /* Nothing to do.  */
+           return 0;
+         mplist_set (config->vars, Mnil, NULL);
          MPLIST_DO (plist, custom->vars)
            {
              variable = MPLIST_SYMBOL (MPLIST_PLIST (plist));
@@ -5371,24 +5447,56 @@ minput_config_variable (MSymbol language, MSymbol name, MSymbol variable,
   else
     {
       plist = mplist__assq (config->vars, variable);
-      if (plist)
+      if (! value)
        {
-         plist = MPLIST_PLIST (plist); /* (NAME nil VALUE) */
-         plist = MPLIST_NEXT (plist);  /* ([nil VALUE]) */
-         if (! MPLIST_TAIL_P (plist))
-           mplist_set (plist, Mnil ,NULL); /* () */
+         /* Cancel the configuration.  */
+         if (! plist)
+           return 0;
+         mplist__pop_unref (plist);
        }
-      else
+      else if (MPLIST_TAIL_P (value))
        {
-         plist = mplist ();
-         mplist_add (config->vars, Mplist, plist);
-         M17N_OBJECT_UNREF (plist);
-         plist = mplist_add (plist, Msymbol, variable);
-         plist = MPLIST_NEXT (plist);
+         /* Cancel the customization.  */
+         MInputMethodInfo *custom = get_custom_info (im_info);
+         int no_custom = (! custom || ! custom->vars
+                          || ! mplist__assq (custom->vars, variable));
+         if (! plist)
+           {
+             if (no_custom)
+               return 0;
+             plist = mplist ();
+             mplist_add (config->vars, Mplist, plist);
+             M17N_OBJECT_UNREF (plist);
+             plist = mplist_add (plist, Msymbol, variable);
+           }
+         else
+           {
+             if (no_custom)
+               mplist__pop_unref (plist);
+             else
+               {
+                 plist = MPLIST_PLIST (plist); /* (NAME nil VALUE) */
+                 plist = MPLIST_NEXT (plist);  /* ([nil VALUE]) */
+                 mplist_set (plist, Mnil ,NULL);
+               }
+           }
        }
-      if (value)
+      else
        {
-         plist = mplist_add (plist, Msymbol, Mnil);
+         if (plist)
+           {
+             plist = MPLIST_NEXT (MPLIST_PLIST (plist));
+             if (! MPLIST_TAIL_P (plist))
+               mplist_set (plist, Mnil, NULL);
+           }
+         else
+           {
+             plist = mplist ();
+             mplist_add (config->vars, Mplist, plist);
+             M17N_OBJECT_UNREF (plist);
+             plist = mplist_add (plist, Msymbol, variable);
+             plist = MPLIST_NEXT (plist);
+           }
          mplist_add (plist, MPLIST_KEY (value), MPLIST_VAL (value));
        }
     }
@@ -5400,10 +5508,10 @@ minput_config_variable (MSymbol language, MSymbol name, MSymbol variable,
 /*=*/
 
 /***en
-    @brief Get the name of per-user configuration file.
+    @brief Get the name of per-user customization file.
     
     The minput_config_file () function returns the absolute path name
-    of per-user configuration file into which minput_save_config ()
+    of per-user customization file into which minput_save_config ()
     save configurations.  It is usually @c "config.mic" under the
     directory @c ".m17n.d" of user's home directory.  It is not assured
     that the file of the returned name exists nor is
@@ -5420,10 +5528,10 @@ minput_config_variable (MSymbol language, MSymbol name, MSymbol variable,
     minput_save_config ()
 */
 /***ja
-    @brief ¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤Î̾Á°¤òÆÀ¤ë.
+    @brief ¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤Î̾Á°¤òÆÀ¤ë.
     
     ´Ø¿ô minput_config_file () ¤Ï¡¢´Ø¿ô minput_save_config () ¤¬ÀßÄê¤ò
-    Êݸ¤¹¤ë¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤Ø¤ÎÀäÂХѥ¹Ì¾¤òÊÖ¤¹¡£Ä̾ï¤Ï¡¢¥æ¡¼¥¶
+    Êݸ¤¹¤ë¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤Ø¤ÎÀäÂХѥ¹Ì¾¤òÊÖ¤¹¡£Ä̾ï¤Ï¡¢¥æ¡¼¥¶
     ¤Î¥Û¡¼¥à¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¤Î¥Ç¥£¥ì¥¯¥È¥ê @c ".m17n.d" ¤Ë¤¢¤ë@c
     "config.mic" ¤È¤Ê¤ë¡£ÊÖ¤µ¤ì¤¿Ì¾Á°¤Î¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ë¤«¡¢Æɤ߽ñ¤­¤Ç
     ¤­¤ë¤«¤ÏÊݾڤµ¤ì¤Ê¤¤¡£´Ø¿ôminput_save_config () ¤¬¼ºÇÔ¤·¤Æ -1 ¤òÊÖ
@@ -5451,16 +5559,16 @@ minput_config_file ()
 /*=*/
 
 /***en
-    @brief Save configurations in per-user configuration file.
+    @brief Save configurations in per-user customization file.
 
     The minput_save_config () function saves the configurations done
-    so far in the current session into the per-user configuration
+    so far in the current session into the per-user customization
     file.
 
     @return
 
     If the operation was successful, 1 is returned.  If the per-user
-    configuration file is currently locked, 0 is returned.  In that
+    customization file is currently locked, 0 is returned.  In that
     case, the caller may wait for a while and try again.  If the
     configuration file is not writable, -1 is returned.  In that case,
     the caller may check the name of the file by calling
@@ -5470,18 +5578,18 @@ minput_config_file ()
     @seealso
     minput_config_file ()  */
 /***ja
-    @brief ÀßÄê¤ò¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤ËÊݸ¤¹¤ë.
+    @brief ÀßÄê¤ò¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤ËÊݸ¤¹¤ë.
 
     ´Ø¿ô minput_save_config () ¤Ï¸½¹Ô¤Î¥»¥Ã¥·¥ç¥ó¤Ç¤³¤ì¤Þ¤Ç¤Ë¹Ô¤Ã¤¿ÀßÄê
-    ¤ò¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤ËÊݸ¤¹¤ë¡£
+    ¤ò¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤ËÊݸ¤¹¤ë¡£
 
     @return
 
-    À®¸ù¤¹¤ì¤Ð 1 ¤òÊÖ¤¹¡£¥æ¡¼¥¶Ëè¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤¬¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤ì¤Ð 0
-    ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢¸Æ½Ð¦¤Ï¤·¤Ð¤é¤¯ÂԤäƺƻî¹Ô¤Ç¤­¤ë¡£ÀßÄê¥Õ¥¡¥¤¥ë
-    ¤¬½ñ¤­¹þ¤ßÉԲĤξì¹ç¡¢-1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢minput_config_file () ¤ò
-    ¸Æ¤ó¤Ç¥Õ¥¡¥¤¥ë̾¤ò¥Á¥§¥Ã¥¯¤·¡¢¤Ç¤­¤ì¤Ð½ñ¤­¹þ¤ß²Äǽ¤Ë¤·¡¢ºÆ»î¹Ô¤Ç¤­
-    ¤ë¡£
+    À®¸ù¤¹¤ì¤Ð 1 ¤òÊÖ¤¹¡£¥æ¡¼¥¶Ëè¤Î¥«¥¹¥¿¥Þ¥¤¥º¥Õ¥¡¥¤¥ë¤¬¥í¥Ã¥¯¤µ¤ì¤Æ¤¤
+    ¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢¸Æ½Ð¦¤Ï¤·¤Ð¤é¤¯ÂԤäƺƻî¹Ô¤Ç¤­¤ë¡£ÀßÄê¥Õ¥¡
+    ¥¤¥ë¤¬½ñ¤­¹þ¤ßÉԲĤξì¹ç¡¢-1 ¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢minput_config_file
+    () ¤ò¸Æ¤ó¤Ç¥Õ¥¡¥¤¥ë̾¤ò¥Á¥§¥Ã¥¯¤·¡¢¤Ç¤­¤ì¤Ð½ñ¤­¹þ¤ß²Äǽ¤Ë¤·¡¢ºÆ»î¹Ô
+    ¤Ç¤­¤ë¡£
 
     @seealso
     minput_config_file ()  */
@@ -5501,8 +5609,8 @@ minput_save_config (void)
   update_custom_info ();
   if (! im_custom_list)
     im_custom_list = mplist ();
-  data = tail = mplist ();
 
+  /* At first, reflect configuration in customization.  */
   MPLIST_DO (plist, im_config_list)
     {
       MPlist *pl = MPLIST_PLIST (plist);
@@ -5529,26 +5637,20 @@ minput_save_config (void)
            else
              custom->cmds = mplist (), p = NULL;
            elt = MPLIST_NEXT (elt);
-           if (MPLIST_TAIL_P (elt))
+           if (p)
              {
-               if (p)
-                 mplist__pop_unref (p);
+               p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p)));
+               mplist_set (p, Mnil, NULL);
              }
            else
              {
-               elt = MPLIST_NEXT (elt);
-               if (p)
-                 {
-                   p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p)));
-                   mplist_set (p, Mnil, NULL);
-                   mplist__conc (p, elt);
-                 }
-               else
-                 {
-                   p = MPLIST_PLIST (pl);
-                   mplist_add (custom->cmds, Mplist, p);
-                 }
+               p = mplist ();
+               mplist_add (custom->cmds, Mplist, p);
+               mplist_add (p, Msymbol, command);
+               p = mplist_add (p, Msymbol, Mnil);
+               p = MPLIST_NEXT (p);
              }
+           mplist__conc (p, elt);
          }
       if (config->vars)
        MPLIST_DO (pl, config->vars)
@@ -5560,30 +5662,26 @@ minput_save_config (void)
            else
              custom->vars = mplist (), p = NULL;
            elt = MPLIST_NEXT (elt);
-           if (MPLIST_TAIL_P (elt))
+           if (p)
              {
-               if (p)
-                 mplist__pop_unref (p);
+               p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p)));
+               mplist_set (p, Mnil, NULL);
              }
            else
              {
-               elt = MPLIST_NEXT (elt);
-               if (p)
-                 {
-                   p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p)));
-                   mplist_set (p, Mnil, NULL);
-                   mplist__conc (p, elt);
-                 }
-               else
-                 {
-                   p = MPLIST_PLIST (pl);
-                   mplist_add (custom->vars, Mplist, p);
-                 }
+               p = mplist ();
+               mplist_add (custom->vars, Mplist, p);
+               mplist_add (p, Msymbol, variable);
+               p = mplist_add (p, Msymbol, Mnil);
+               p = MPLIST_NEXT (p);
              }
+           mplist__conc (p, elt);
          }
     }
   M17N_OBJECT_UNREF (im_config_list);
 
+  /* Next, reflect customization to the actual plist to be written.  */
+  data = tail = mplist ();
   MPLIST_DO (plist, im_custom_list)
     {
       MPlist *pl = MPLIST_PLIST (plist);
@@ -5597,6 +5695,9 @@ minput_save_config (void)
       extra = MPLIST_SYMBOL (pl);
       pl = MPLIST_NEXT (pl);
       custom = MPLIST_VAL (pl);
+      if ((! custom->cmds || MPLIST_TAIL_P (custom->cmds))
+         && (! custom->vars || MPLIST_TAIL_P (custom->vars)))
+       continue;
       im_info = lookup_im_info (im_info_list, language, name, extra);
       if (im_info)
        {
@@ -5606,34 +5707,54 @@ minput_save_config (void)
            config_all_variables (im_info);
        }
       
-      elt = mplist ();
-      tail = mplist_add (tail, Mplist, elt);
-      M17N_OBJECT_UNREF (elt);
-      pl = mplist ();
-      elt = mplist_add (elt, Mplist, pl);
-      M17N_OBJECT_UNREF (pl);
-      pl = mplist_add (pl, Msymbol, Minput_method);
-      pl = mplist_add (pl, Msymbol, language);
-      pl = mplist_add (pl, Msymbol, name);
-      if (extra != Mnil)
-       pl = mplist_add (pl, Msymbol, extra);
+      elt = NULL;
       if (custom->cmds && ! MPLIST_TAIL_P (custom->cmds))
        {
-         pl = mplist ();
-         elt = mplist_add (elt, Mplist, pl);
-         M17N_OBJECT_UNREF (pl);
-         pl = mplist_add (pl, Msymbol, Mcommand);
          MPLIST_DO (p, custom->cmds)
-           pl = mplist_add (pl, Mplist, MPLIST_PLIST (p));
+           if (! MPLIST_TAIL_P (MPLIST_NEXT (MPLIST_PLIST (p))))
+             break;
+         if (! MPLIST_TAIL_P (p))
+           {
+             elt = mplist ();
+             pl = mplist ();
+             mplist_add (elt, Mplist, pl);
+             M17N_OBJECT_UNREF (pl);
+             pl = mplist_add (pl, Msymbol, Mcommand);
+             MPLIST_DO (p, custom->cmds)
+               if (! MPLIST_TAIL_P (MPLIST_NEXT (MPLIST_PLIST (p))))
+                 pl = mplist_add (pl, Mplist, MPLIST_PLIST (p));
+           }
        }
       if (custom->vars && ! MPLIST_TAIL_P (custom->vars))
        {
+         MPLIST_DO (p, custom->vars)
+           if (! MPLIST_TAIL_P (MPLIST_NEXT (MPLIST_PLIST (p))))
+             break;
+         if (! MPLIST_TAIL_P (p))
+           {
+             if (! elt)
+               elt = mplist ();
+             pl = mplist ();
+             mplist_add (elt, Mplist, pl);
+             M17N_OBJECT_UNREF (pl);
+             pl = mplist_add (pl, Msymbol, Mvariable);
+             MPLIST_DO (p, custom->vars)
+               if (! MPLIST_TAIL_P (MPLIST_NEXT (MPLIST_PLIST (p))))
+                 pl = mplist_add (pl, Mplist, MPLIST_PLIST (p));
+           }
+       }
+      if (elt)
+       {
          pl = mplist ();
-         elt = mplist_add (elt, Mplist, pl);
+         mplist_push (elt, Mplist, pl);
          M17N_OBJECT_UNREF (pl);
-         pl = mplist_add (pl, Msymbol, Mvariable);
-         MPLIST_DO (p, custom->vars)
-           pl = mplist_add (pl, Mplist, MPLIST_PLIST (p));
+         pl = mplist_add (pl, Msymbol, Minput_method);
+         pl = mplist_add (pl, Msymbol, language);
+         pl = mplist_add (pl, Msymbol, name);
+         if (extra != Mnil)
+           pl = mplist_add (pl, Msymbol, extra);
+         tail = mplist_add (tail, Mplist, elt);
+         M17N_OBJECT_UNREF (elt);
        }
     }
 
@@ -6053,8 +6174,8 @@ minput_callback (MInputContext *ic, MSymbol command)
 
   if (! ic->im->driver.callback_list)
     return -1;
-  func = (MInputCallbackFunc) mplist_get (ic->im->driver.callback_list,
-                                         command);
+  func = ((MInputCallbackFunc)
+         mplist_get_func (ic->im->driver.callback_list, command));
   if (! func)
     return -1;
   (func) (ic, command);