Include "charset.h".
authorhanda <handa>
Tue, 18 Oct 2005 02:01:57 +0000 (02:01 +0000)
committerhanda <handa>
Tue, 18 Oct 2005 02:01:57 +0000 (02:01 +0000)
(M_candidates, Mcandidates_group_size, Mcandidates_charset): New
variables.
(MIMState): New member (M17NObject control).
(lookup_nested_list, set_nested_list, parse_nested_list_value)
(get_nested_list, resolve_variable): New functions.
(integer_value): New arg (MPlist **value).  Set it to the plist
element containing the value.
(resolve_command): New function.
(load_translation): New arg (MPlist *map_actions).
(load_branch): New args language and name.  If `keylist' is a
symbol, resolved that as a command name.
(free_map): New arg top.  Free map->map_actions only if top is
nonzero.
(free_state): New function.
(load_state): New arg name.
(im_info_list): New variable.
(free_im_info, get_im_info_by_tags): New functions.
(load_im_info): Arg key changed to plist.  Handle `include'.
Return (MInputMethodInfo *).
(preedit_commit): Ref ic->candidate_list.
(get_select_charset, adjust_candidate_command): New functions.
(take_action_list): Handle `include'.  Adjust candidate action
properly.  Handle control variables `candidates-charset' and
`candidates-group-size'.
(open_im): Use get_im_info.
(create_ic): Get global variables.
(load_partial_im_info): New function.
(get_im_info): New function.
(check_command_keyseq, check_command_list, check_variable_list):
New functions.
(minput__init): Don't handle M_database_hook and Mdetail_text.
Initialize M_candidates, Mcandidates_group_size,
Mcandidates_charset.
(parse_variable_list, get_variable_list, parse_command_list)
(get_command_list): Delete them.
(MDatabaseStatList, imdir_stat_list, input_method_hook): Delete them.
(minput__fini): Simply unref command_list and variable_list.
(minput_get_description): Adjusted for the new form of description.
(minput_get_commands): Use get_nested_list.
(minput_assign_command_keys): Likewise.
(minput_get_variables, minput_set_variable): Likewise.

src/input.c

index 039a1f0..d9c2959 100644 (file)
 #include "symbol.h"
 #include "plist.h"
 #include "database.h"
+#include "charset.h"
 
 static int mdebug_mask = MDEBUG_INPUT;
 
@@ -169,11 +170,15 @@ static MSymbol Mtitle, Mmacro, Mmodule, Mstate, Minclude;
 static MSymbol Minsert, Mdelete, Mmark, Mmove, Mpushback, Mundo, Mcall, Mshift;
 static MSymbol Mselect, Mshow, Mhide, Mcommit, Munhandle;
 static MSymbol Mset, Madd, Msub, Mmul, Mdiv, Mequal, Mless, Mgreater;
+static MSymbol M_candidates;
 
 static MSymbol Mcandidate_list, Mcandidate_index;
 
 static MSymbol Minit, Mfini;
 
+/** Symbols for variables.  */
+static MSymbol Mcandidates_group_size, Mcandidates_charset;
+
 /** Symbols for key events.  */
 static MSymbol one_char_symbol[256];
 
@@ -208,6 +213,8 @@ typedef struct
 
 struct MIMState
 {
+  M17NObject control;
+
   /** Name of the state.  */
   MSymbol name;
 
@@ -219,6 +226,204 @@ struct MIMState
   MIMMap *map;
 };
 
+/* Lookup keys KEY1,2,3 in the nested plist PLIST, and return the
+   value.  */
+
+static MPlist *
+lookup_nested_list (MPlist *plist, MSymbol key1, MSymbol key2, MSymbol key3)
+{
+  MSymbol key[3];
+  int i;
+
+  key[0] = key1, key[1] = key2, key[2] = key3;
+  for (i = 0; i < 3; i++)
+    {
+      plist = mplist_find_by_value (plist, key[i]);
+      if (! plist)
+       return NULL;
+      plist = MPLIST_NEXT (plist);
+      plist = MPLIST_PLIST (plist);
+    }
+  return plist;
+}
+
+/* Set VAL for keys KEY1,2,3 in the nested plist PLIST.  */
+
+static MPlist *
+set_nested_list (MPlist *plist, MSymbol key1, MSymbol key2, MSymbol key3,
+                MPlist *val)
+{
+  MSymbol key[3];
+  int i;
+  MPlist *pl;
+
+  key[0] = key1, key[1] = key2, key[2] = key3;
+  for (i = 0; i < 3; i++)
+    {
+      pl = mplist_find_by_value (plist, key[i]);
+      if (pl)
+       {
+         pl = MPLIST_NEXT (pl);
+         plist = MPLIST_PLIST (pl);
+       }
+      else
+       {
+         pl = mplist_add (plist, Msymbol, key[i]);
+         plist = mplist ();
+         pl = mplist_add (pl, Mplist, plist);
+         M17N_OBJECT_UNREF (plist);
+       }
+    }
+  mplist_set (pl, Mplist, val);
+  M17N_OBJECT_UNREF (val);
+  return pl;
+}
+
+/* Parse PLIST as a value of nested list and return an adjusted list.
+
+   PLIST has this form;
+     (symbol:command
+      plist:(symbol:KEY
+            [ mtext:DESCRIPTION | symbol:nil ]
+            ;; The remaining elements are checked CHECK_FUNC.
+            ...)
+      plist:(symbol:KEY
+            [ mtext:DESCRIPTION | symbol:nil ]
+            ;; The remaining elements are checked CHECK_FUNC.
+            ...)
+      ...)
+
+   GLOBAL is a global list.  If a description text is missing, it is
+   extracted from GLOBAL.
+
+   The return value is a plist of this format:
+     (symbol:KEY
+      plist:([ mtext:DESCRIPTION | symbol:nil ]
+            ...)
+      symbol:KEY
+      plist:([ mtext:DESCRIPTION | symbol:nil ]
+            ...)
+      ...)
+
+   PLIST itself is unref-ed.  */
+
+static MPlist *
+parse_nested_list_value (MPlist *plist, MPlist *global, MSymbol key,
+                        int (*check_func) (MPlist *))
+{
+  MPlist *val, *pl;
+
+  val = mplist ();
+  if (! MPLIST_PLIST_P (plist))
+    {
+      M17N_OBJECT_UNREF (plist);
+      return val;
+    }
+  pl = MPLIST_PLIST (plist);
+  if (! MPLIST_SYMBOL_P (pl)
+      || MPLIST_SYMBOL (pl) != key)
+    {
+      M17N_OBJECT_UNREF (plist);
+      return val;
+    }
+
+  MPLIST_DO (pl, MPLIST_NEXT (pl))
+    {
+      MSymbol cmd;
+      MPlist *p;
+
+      if (! MPLIST_PLIST_P (pl))
+       continue;
+      p = MPLIST_PLIST (pl);
+      if (! MPLIST_SYMBOL_P (p))
+       continue;
+      cmd = MPLIST_SYMBOL (p);
+      p = MPLIST_NEXT (p);
+      if (! MPLIST_MTEXT_P (p))
+       {
+         mplist_set (p, Msymbol, Mnil);
+         if (global)
+           {
+             MPlist *p0 = mplist_find_by_value (global, cmd);
+             MText *description;
+
+             if (p0)
+               {
+                 p0 = MPLIST_NEXT (p0);
+                 if (MPLIST_MTEXT_P (p0))
+                   {
+                     description = MPLIST_MTEXT (p0);
+                     mplist_set (p, Mtext, description);
+                   }
+               }
+           }
+       }
+      if ((*check_func) (MPLIST_NEXT (p)) < 0)
+       continue;
+      mplist_add (val, Msymbol, cmd);
+      mplist_add (val, Mplist, p);
+    }
+
+  M17N_OBJECT_UNREF (plist);
+  return val;
+}
+
+static MPlist *variable_list, *command_list;
+static int check_variable_list (MPlist *plist);
+static int check_command_list (MPlist *plist);
+static MPlist *load_partial_im_info (MSymbol language, MSymbol name,
+                                    MSymbol extra, MSymbol key);
+
+static MPlist *
+get_nested_list (MSymbol language, MSymbol name, MSymbol extra, MSymbol key)
+{
+  MPlist *total_list;
+  int (*check_func) (MPlist *);
+  MPlist *plist, *global;
+
+  if (key == M_variable)
+    {
+      if (! variable_list)
+       variable_list = mplist ();
+      total_list = variable_list;
+      check_func = check_variable_list;
+    }
+  else
+    {
+      if (! command_list)
+       command_list = mplist ();
+      total_list = command_list;
+      check_func = check_command_list;
+    }
+
+  if (MPLIST_TAIL_P (total_list))
+    {
+      MDatabase *mdb = mdatabase_find (Minput_method, Mt, Mnil, key);
+
+      if (mdb && (plist = mdatabase_load (mdb)))
+       global = parse_nested_list_value (plist, NULL, key, check_func);
+      else
+       global = mplist ();
+      set_nested_list (total_list, Mt, Mnil, key, global);
+    }
+  else
+    global = lookup_nested_list (total_list, Mt, Mnil, key);
+
+  if (name == Mnil)
+    return global;
+
+  plist = lookup_nested_list (total_list, language, name, extra);
+  if (plist)
+    return plist;
+
+  plist = load_partial_im_info (language, name, extra, key);
+  if (plist)
+    plist = parse_nested_list_value (plist, global, key, check_func);
+  else
+    plist = mplist ();
+  set_nested_list (total_list, language, name, extra, plist);
+  return plist;
+}
 
 static int
 marker_code (MSymbol sym)
@@ -237,19 +442,49 @@ marker_code (MSymbol sym)
          ? name[1] : -1);
 }
 
+
+static MPlist *
+resolve_variable (MInputContextInfo *ic_info, MSymbol var)
+{
+  MPlist *p;
+
+  MPLIST_DO (p, ic_info->vars)
+    {
+      if (MPLIST_SYMBOL (p) == var)
+       break;
+      p = MPLIST_NEXT (p);
+    }
+  if (MPLIST_TAIL_P (p))
+    {
+      p = ic_info->vars;
+      mplist_push (p, Minteger, (void *) 0);
+      mplist_push (p, Msymbol, var);
+    }
+  return (MPLIST_NEXT (p));
+}
+
+
 int
-integer_value (MInputContext *ic, MPlist *arg)
+integer_value (MInputContext *ic, MPlist *arg, MPlist **value)
 {
   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
   int code;
   MText *preedit = ic->preedit;
   int len = mtext_nchars (preedit);
 
+  if (value)
+    *value = NULL;
   if (MPLIST_INTEGER_P (arg))
     return MPLIST_INTEGER (arg);
   code = marker_code (MPLIST_SYMBOL (arg));
   if (code < 0)
-    return (int) mplist_get (ic_info->vars, MPLIST_SYMBOL (arg));
+    {
+      MPlist *val = resolve_variable (ic_info, MPLIST_SYMBOL (arg));
+
+      if (value)
+       *value = val;
+      return (MPLIST_INTEGER_P (val) ? MPLIST_INTEGER (val) : 0);
+    }
   if (code >= '0' && code <= '9')
     code -= '0';
   else if (code == '=')
@@ -266,8 +501,7 @@ integer_value (MInputContext *ic, MPlist *arg)
 }
 
 
-/* Parse PLIST as an action list while modifying the list to regularize
-   actions.  PLIST should have this form:
+/* Parse PLIST as an action list.  PLIST should have this form:
       PLIST ::= ( (ACTION-NAME ACTION-ARG *) *).
    Return 0 if successfully parsed, otherwise return -1.  */
 
@@ -437,21 +671,36 @@ parse_action_list (MPlist *plist, MPlist *macros)
   return 0;
 }
 
+static MPlist *
+resolve_command (MSymbol language, MSymbol name, MSymbol command)
+{
+  MPlist *plist = get_nested_list (language, name, Mnil, M_command);
+
+  if (! plist
+      || ! (plist = mplist_get (plist, command)))
+    return NULL;
+  plist = MPLIST_NEXT (plist);
+  if (! MPLIST_PLIST_P (plist))
+    return NULL;
+  return plist;
+}
+
+
 
 /* Load a translation into MAP from PLIST.
    PLIST has this form:
       PLIST ::= ( KEYSEQ MAP-ACTION * )  */
 
 static int
-load_translation (MIMMap *map, MPlist *plist, MPlist *branch_actions,
-                 MPlist *macros)
+load_translation (MIMMap *map, MPlist *keylist, MPlist *map_actions,
+                 MPlist *branch_actions, MPlist *macros)
 {
   MSymbol *keyseq;
   int len, i;
 
-  if (MPLIST_MTEXT_P (plist))
+  if (MPLIST_MTEXT_P (keylist))
     {
-      MText *mt = MPLIST_MTEXT (plist);
+      MText *mt = MPLIST_MTEXT (keylist);
 
       len = mtext_nchars (mt);
       if (len == 0 || len != mtext_nbytes (mt))
@@ -460,9 +709,9 @@ load_translation (MIMMap *map, MPlist *plist, MPlist *branch_actions,
       for (i = 0; i < len; i++)
        keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]];
     }
-  else if (MPLIST_PLIST_P (plist))
+  else if (MPLIST_PLIST_P (keylist))
     {
-      MPlist *elt = MPLIST_PLIST (plist);
+      MPlist *elt = MPLIST_PLIST (keylist);
          
       len = MPLIST_LENGTH (elt);
       if (len == 0)
@@ -510,13 +759,11 @@ load_translation (MIMMap *map, MPlist *plist, MPlist *branch_actions,
     /* This map is already defined.  We avoid overriding it.  */
     return 0;
 
-  plist = MPLIST_NEXT (plist);
-  if (! MPLIST_TAIL_P (plist))
+  if (! MPLIST_TAIL_P (map_actions))
     {
-      if (parse_action_list (plist, macros) < 0)
+      if (parse_action_list (map_actions, macros) < 0)
        MERROR (MERROR_IM, -1);
-      map->map_actions = plist;
-      M17N_OBJECT_REF (plist);
+      map->map_actions = map_actions;
     }
   if (branch_actions)
     {
@@ -533,7 +780,8 @@ load_translation (MIMMap *map, MPlist *plist, MPlist *branch_actions,
    STATE is the current state.  */
 
 static int
-load_branch (MPlist *plist, MPlist *maps, MIMMap *map, MPlist *macros)
+load_branch (MPlist *plist, MPlist *maps, MIMMap *map,
+            MSymbol language, MSymbol name, MPlist *macros)
 {
   MSymbol map_name;
   MPlist *branch_actions;
@@ -566,11 +814,30 @@ load_branch (MPlist *plist, MPlist *maps, MIMMap *map, MPlist *macros)
       if (! plist || ! MPLIST_PLIST_P (plist))
        MERROR (MERROR_IM, -1);
       MPLIST_DO (plist, plist)
-       if (! MPLIST_PLIST_P (plist)
-           || (load_translation (map, MPLIST_PLIST (plist), branch_actions,
-                                 macros)
-               < 0))
-         MERROR (MERROR_IM, -1);
+       {
+         MPlist *keylist, *map_actions;
+
+         if (! MPLIST_PLIST_P (plist))
+           MERROR (MERROR_IM, -1);
+         keylist = MPLIST_PLIST (plist);
+         map_actions = MPLIST_NEXT (keylist);
+         if (MPLIST_SYMBOL_P (keylist))
+           {
+             MSymbol command = MPLIST_SYMBOL (keylist);
+             MPlist *pl = resolve_command (language, name, command);
+
+             if (! pl)
+               return -1;
+             MPLIST_DO (pl, pl)
+               if (load_translation (map, pl, map_actions, branch_actions,
+                                     macros) < 0)
+                 MERROR (MERROR_IM, -1);
+           }
+         else
+           if (load_translation (map, keylist, map_actions, branch_actions,
+                                 macros) < 0)
+             MERROR (MERROR_IM, -1);
+       }
     }
 
   return 0;
@@ -649,6 +916,34 @@ load_external_module (MPlist *plist, MPlist *externals)
   return -1;
 }
 
+static void
+free_map (MIMMap *map, int top)
+{
+  MPlist *plist;
+
+  if (top)
+    M17N_OBJECT_UNREF (map->map_actions);
+  if (map->submaps)
+    {
+      MPLIST_DO (plist, map->submaps)
+       free_map ((MIMMap *) MPLIST_VAL (plist), 0);
+      M17N_OBJECT_UNREF (map->submaps);
+    }
+  M17N_OBJECT_UNREF (map->branch_actions);
+  free (map);
+}
+
+static void
+free_state (void *object)
+{
+  MIMState *state = object;
+
+  if (state->title)
+    M17N_OBJECT_UNREF (state->title);
+  if (state->map)
+    free_map (state->map, 1);
+  free (state);
+}
 
 /** Load a state from PLIST into a newly allocated state object.
     PLIST has this form:
@@ -658,13 +953,14 @@ load_external_module (MPlist *plist, MPlist *externals)
    Return the state object.  */
 
 static MIMState *
-load_state (MPlist *plist, MPlist *maps, MSymbol language, MPlist *macros)
+load_state (MPlist *plist, MPlist *maps, MSymbol language, MSymbol name,
+           MPlist *macros)
 {
   MIMState *state;
 
-  MSTRUCT_CALLOC (state, MERROR_IM);
   if (! MPLIST_SYMBOL_P (plist))
     MERROR (MERROR_IM, NULL);
+  M17N_OBJECT (state, free_state, MERROR_IM);
   state->name = MPLIST_SYMBOL (plist);
   plist = MPLIST_NEXT (plist);
   if (MPLIST_MTEXT_P (plist))
@@ -678,37 +974,92 @@ load_state (MPlist *plist, MPlist *maps, MSymbol language, MPlist *macros)
   MSTRUCT_CALLOC (state->map, MERROR_IM);
   MPLIST_DO (plist, plist)
     if (! MPLIST_PLIST_P (plist)
-       || load_branch (MPLIST_PLIST (plist), maps, state->map, macros) < 0)
+       || load_branch (MPLIST_PLIST (plist), maps, state->map, language, name,
+                       macros) < 0)
       MERROR (MERROR_IM, NULL);
   return state;
 }
 
 
+static MPlist *im_info_list;
+
 static void
-free_map (MIMMap *map)
+free_im_info (MInputMethodInfo *im_info)
 {
   MPlist *plist;
 
-  M17N_OBJECT_UNREF (map->map_actions);
-  if (map->submaps)
+  if (im_info->title)
+    M17N_OBJECT_UNREF (im_info->title);
+  if (im_info->states)
     {
-      MPLIST_DO (plist, map->submaps)
-       free_map ((MIMMap *) MPLIST_VAL (plist));
-      M17N_OBJECT_UNREF (map->submaps);
+      MPLIST_DO (plist, im_info->states)
+       {
+         MIMState *state = (MIMState *) MPLIST_VAL (plist);
+
+         M17N_OBJECT_UNREF (state);
+       }
+      M17N_OBJECT_UNREF (im_info->states);
     }
-  M17N_OBJECT_UNREF (map->branch_actions);
-  free (map);
+
+  if (im_info->macros)
+    {
+      MPLIST_DO (plist, im_info->macros)
+       M17N_OBJECT_UNREF (MPLIST_VAL (plist)); 
+      M17N_OBJECT_UNREF (im_info->macros);
+    }
+
+  if (im_info->externals)
+    {
+      MPLIST_DO (plist, im_info->externals)
+       {
+         MIMExternalModule *external = MPLIST_VAL (plist);
+
+         dlclose (external->handle);
+         M17N_OBJECT_UNREF (external->func_list);
+         free (external);
+         MPLIST_KEY (plist) = Mt;
+       }
+      M17N_OBJECT_UNREF (im_info->externals);
+    }
+  if (im_info->maps)
+    {
+      MPLIST_DO (plist, im_info->maps)
+       {
+         MPlist *p = MPLIST_PLIST (plist);
+
+         M17N_OBJECT_UNREF (p);
+       }
+      M17N_OBJECT_UNREF (im_info->maps);
+    }
+
+  free (im_info);
 }
 
-static MPlist *load_im_info_keys;
-static MPlist *load_im_info (MSymbol language, MSymbol name, MSymbol key);
+static MInputMethodInfo *get_im_info (MSymbol language, MSymbol name,
+                                     MSymbol extra);
+
+static MInputMethodInfo *
+get_im_info_by_tags (MPlist *plist)
+{
+  MSymbol tag[3];
+  int i;
+
+  for (i = 0; i < 3 && MPLIST_SYMBOL_P (plist);
+       i++, plist = MPLIST_NEXT (plist))
+    tag[i] = MPLIST_SYMBOL (plist);
+  if (i < 2)
+    return NULL;
+  for (; i < 3; i++)
+    tag[i] = Mnil;
+  return get_im_info (tag[0], tag[1], tag[2]);
+}
 
 /* Load an input method from PLIST into IM_INTO, and return it.  */
 
-static int
-load_input_method (MSymbol language, MSymbol name, MPlist *plist,
-                  MInputMethodInfo *im_info)
+static MInputMethodInfo *
+load_im_info (MSymbol language, MSymbol name, MPlist *plist)
 {
+  MInputMethodInfo *im_info;
   MText *title = NULL;
   MPlist *maps = NULL;
   MPlist *states = NULL;
@@ -716,6 +1067,8 @@ load_input_method (MSymbol language, MSymbol name, MPlist *plist,
   MPlist *macros = NULL;
   MPlist *elt;
 
+  MSTRUCT_CALLOC (im_info, MERROR_IM);
+
   while (MPLIST_PLIST_P (plist))
     {
       elt = MPLIST_PLIST (plist);
@@ -726,7 +1079,7 @@ load_input_method (MSymbol language, MSymbol name, MPlist *plist,
          elt = MPLIST_NEXT (elt);
          if (! MPLIST_MTEXT_P (elt))
            MERROR_GOTO (MERROR_IM, err);
-         title = MPLIST_MTEXT (elt);
+         im_info->title = title = MPLIST_MTEXT (elt);
          M17N_OBJECT_REF (title);
        }
       else if (MPLIST_SYMBOL (elt) == Mmap)
@@ -736,14 +1089,14 @@ load_input_method (MSymbol language, MSymbol name, MPlist *plist,
          if (! pl)
            MERROR_GOTO (MERROR_IM, err);
          if (! maps)
-           maps = pl;
+           im_info->maps = maps = pl;
          else
-           maps = mplist_conc (maps, pl);
+           maps = mplist__conc (maps, pl);
        }
       else if (MPLIST_SYMBOL (elt) == Mmacro)
        {
          if (! macros)
-           macros = mplist ();
+           im_info->macros = macros = mplist ();
          MPLIST_DO (elt, MPLIST_NEXT (elt))
            {
              if (! MPLIST_PLIST_P (elt)
@@ -754,7 +1107,7 @@ load_input_method (MSymbol language, MSymbol name, MPlist *plist,
       else if (MPLIST_SYMBOL (elt) == Mmodule)
        {
          if (! externals)
-           externals = mplist ();
+           im_info->externals = externals = mplist ();
          MPLIST_DO (elt, MPLIST_NEXT (elt))
            {
              if (! MPLIST_PLIST_P (elt)
@@ -770,136 +1123,85 @@ load_input_method (MSymbol language, MSymbol name, MPlist *plist,
 
              if (! MPLIST_PLIST_P (elt))
                MERROR_GOTO (MERROR_IM, err);
-             state = load_state (MPLIST_PLIST (elt), maps, language, macros);
+             state = load_state (MPLIST_PLIST (elt), maps, language, name,
+                                 macros);
              if (! state)
                MERROR_GOTO (MERROR_IM, err);
              if (! states)
-               states = mplist ();
+               im_info->states = states = mplist ();
              mplist_put (states, state->name, state);
            }
        }
       else if (MPLIST_SYMBOL (elt) == Minclude)
        {
-         MSymbol lang, name, key;
-         MPlist *pl, *p, *p0;
+         /* elt ::= include (tag1 tag2 ...) key item ... */
+         MSymbol key;
+         MInputMethodInfo *temp;
+         MPlist *pl, *p;
 
          elt = MPLIST_NEXT (elt);
-         if (! MPLIST_SYMBOL_P (elt))
+         if (! MPLIST_PLIST_P (elt))
            MERROR_GOTO (MERROR_IM, err);
-         lang = MPLIST_SYMBOL (elt);
-         elt = MPLIST_NEXT (elt);
-         if (! MPLIST_SYMBOL_P (elt))
-           MERROR_GOTO (MERROR_IM, err);
-         name = MPLIST_SYMBOL (elt);
-         if (language == Mnil || name == Mnil)
+         temp = get_im_info_by_tags (MPLIST_PLIST (elt));
+         if (! temp)
            MERROR_GOTO (MERROR_IM, err);
          elt = MPLIST_NEXT (elt);
          if (! MPLIST_SYMBOL_P (elt))
            MERROR_GOTO (MERROR_IM, err);
          key = MPLIST_SYMBOL (elt);
          elt = MPLIST_NEXT (elt);
-         if (MPLIST_TAIL_P (elt))
-           elt = NULL;
-         pl = load_im_info (lang, name, key);
-         if (! pl)
-           MERROR_GOTO (MERROR_IM, err);
-         if (! MPLIST_PLIST_P (pl))
-           MERROR_GOTO (MERROR_IM, include_err);
-         p = MPLIST_PLIST (pl);
-         if (! MPLIST_SYMBOL_P (p) || MPLIST_SYMBOL (p) != key)
-           MERROR_GOTO (MERROR_IM, include_err);
-         p = MPLIST_NEXT (p);
-         while (! MPLIST_TAIL_P (p))
+         if (key == Mmap)
            {
-             if (MPLIST_PLIST_P (p))
+             if (! maps)
+               im_info->maps = maps = mplist ();
+             MPLIST_DO (pl, temp->maps)
                {
-                 p0 = MPLIST_PLIST (p);
-
-                 if (! MPLIST_SYMBOL_P (p0))
-                   MERROR_GOTO (MERROR_IM, include_err);
-                 if (elt)
-                   {
-                     p0 = mplist_find_by_value (elt, MPLIST_SYMBOL (p0));
-                     if (p0)
-                       {
-                         mplist_pop (p0);
-                         p = MPLIST_NEXT (p);
-                       }
-                     else
-                       mplist_pop (p);
-                   }
-                 else
-                   p = MPLIST_NEXT (p);
+                 p = MPLIST_VAL (pl);
+                 MPLIST_ADD_PLIST (maps, MPLIST_KEY (pl), p);
+                 M17N_OBJECT_REF (p);
                }
-             else
-               mplist_pop (p);
            }
-         if (! MPLIST_TAIL_P (p))
-           MERROR_GOTO (MERROR_IM, include_err);
-         mplist_set (plist, Mplist, MPLIST_PLIST (pl));
-         continue;
+         else if (key == Mmacro)
+           {
+             if (! macros)
+               im_info->macros = macros = mplist ();
+             MPLIST_DO (pl, temp->macros)
+               {
+                 p = MPLIST_VAL (pl);
+                 MPLIST_ADD_PLIST (macros, MPLIST_KEY (pl), p);
+                 M17N_OBJECT_REF (p);
+               }
+           }
+         else if (key == Mstate)
+           {
+             if (! states)
+               im_info->states = states = mplist ();
+             MPLIST_DO (pl, temp->states)
+               {
+                 MIMState *state = MPLIST_VAL (pl);
 
-       include_err:
-         M17N_OBJECT_REF (pl);
-         MERROR_GOTO (MERROR_IM, err);
+                 MPLIST_ADD_PLIST (states, MPLIST_KEY (pl), state);
+                 M17N_OBJECT_REF (state);
+               }
+           }
+         else
+           MERROR_GOTO (MERROR_IM, err);
        }
       plist = MPLIST_NEXT (plist);
     }
 
-  if (maps)
-    {
-      MPLIST_DO (elt, maps)
-       M17N_OBJECT_UNREF (MPLIST_VAL (elt));
-      M17N_OBJECT_UNREF (maps);
-    }
-  if (! title)
-    title = mtext_from_data (MSYMBOL_NAME (name), MSYMBOL_NAMELEN (name),
-                            MTEXT_FORMAT_US_ASCII);
   if (! states)
     goto err;
-  im_info->title = title;
-  im_info->externals = externals;
-  im_info->macros = macros;
-  im_info->states = states;
-  return 0;
+  if (! title)
+    im_info->title
+      = title = mtext_from_data (MSYMBOL_NAME (im_info->im->name),
+                                MSYMBOL_NAMELEN (im_info->im->name),
+                                MTEXT_FORMAT_US_ASCII);
+  return im_info;
 
  err:
-  if (maps)
-    {
-      MPLIST_DO (elt, maps)
-       M17N_OBJECT_UNREF (MPLIST_VAL (elt));
-      M17N_OBJECT_UNREF (maps);
-    }
-  if (title)
-    M17N_OBJECT_UNREF (title);
-  if (states)
-    {
-      MPLIST_DO (plist, states)
-      {
-       MIMState *state = (MIMState *) MPLIST_VAL (plist);
-
-       if (state->title)
-         M17N_OBJECT_UNREF (state->title);
-       if (state->map)
-         free_map (state->map);
-       free (state);
-      }
-      M17N_OBJECT_UNREF (states);
-    }
-  if (externals)
-    {
-      MPLIST_DO (plist, externals)
-      {
-       MIMExternalModule *external = MPLIST_VAL (plist);
-
-       dlclose (external->handle);
-       M17N_OBJECT_UNREF (external->func_list);
-       free (external);
-       MPLIST_KEY (plist) = Mt;
-      }
-      M17N_OBJECT_UNREF (externals);
-    }
-  return -1;
+  free_im_info (im_info);
+  return NULL;
 }
 
 \f
@@ -1072,6 +1374,7 @@ preedit_commit (MInputContext *ic)
     }
   if (ic->candidate_list)
     {
+      M17N_OBJECT_UNREF (ic->candidate_list);
       ic->candidate_list = NULL;
       ic->candidate_show = 0;
       ic->candidates_changed = 1;
@@ -1153,6 +1456,118 @@ update_candidate (MInputContext *ic, MTextProperty *prop, int idx)
   ic->cursor_pos = to;
 }
 
+static MCharset *
+get_select_charset (MInputContextInfo * ic_info)
+{
+  MPlist *plist = resolve_variable (ic_info, Mcandidates_charset);
+  MSymbol sym;
+
+  if (! MPLIST_VAL (plist))
+    return NULL;
+  sym = MPLIST_SYMBOL (plist);
+  if (sym == Mnil)
+    return NULL;
+  return MCHARSET (sym);
+}
+
+static MPlist *
+adjust_candidate_command (MInputContextInfo *ic_info, MPlist *args,
+                         MCharset *charset)
+{
+  MPlist *plist, *pl;
+
+  /* args ::= ((MTEXT ...) ...) | ((PLIST ...) ...) */
+  plist = mplist_copy (MPLIST_PLIST (args));
+  if (MPLIST_MTEXT_P (plist))
+    {
+      pl = plist;
+      while (! MPLIST_TAIL_P (pl))
+       {
+         /* pl ::= (MTEXT ...) */
+         MText *mt = MPLIST_MTEXT (pl);
+         int mt_copied = 0;
+         int i, c;
+
+         for (i = mtext_nchars (mt) - 1; i >= 0; i--)
+           {
+             c = mtext_ref_char (mt, i);
+             if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE)
+               {
+                 if (! mt_copied)
+                   {
+                     mt = mtext_dup (mt);
+                     mplist_set (pl, Mtext, mt);
+                     M17N_OBJECT_UNREF (mt);
+                     mt_copied = 1;
+                   }
+                 mtext_del (mt, i, i + 1);
+               }
+           }
+         if (mtext_len (mt) > 0)
+           pl = MPLIST_NEXT (pl);
+         else
+           {
+             mplist_pop (pl);
+             M17N_OBJECT_UNREF (mt);
+           }
+       }
+    }
+  else                         /* MPLIST_PLIST_P (plist) */
+    {
+      pl = plist;
+      while (! MPLIST_TAIL_P (pl))
+       {
+         /* pl ::= ((MTEXT ...) ...) */
+         MPlist *p = MPLIST_PLIST (pl);
+         /* p ::= (MTEXT ...) */
+         int pl_copied = 0;
+         int n = 0;
+
+         while (MPLIST_TAIL_P (p))
+           {
+             MText *mt = MPLIST_MTEXT (p);
+             int i, c;
+
+             for (i = mtext_nchars (mt) - 1; i >= 0; i--)
+               {
+                 c = mtext_ref_char (mt, i);
+                 if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE)
+                   break;
+               }
+             if (i >= 0)
+               {
+                 if (! pl_copied)
+                   {
+                     p = mplist_copy (MPLIST_PLIST (pl));
+                     mplist_set (pl, Mplist, pl);
+                     M17N_OBJECT_UNREF (p);
+                     pl_copied = 1;
+                     while (n-- > 0)
+                       p = MPLIST_NEXT (p);
+                   }     
+                 mplist_pop (p);
+                 M17N_OBJECT_UNREF (mt);
+               }
+           }
+         if (MPLIST_TAIL_P (p))
+           pl = MPLIST_NEXT (pl);
+         else
+           {
+             p = mplist_pop (pl);
+             M17N_OBJECT_UNREF (p);
+           }
+       }
+    }
+  if (MPLIST_TAIL_P (plist))
+    {
+      M17N_OBJECT_UNREF (plist);
+      return NULL;
+    }      
+  args = mplist ();
+  mplist_add (args, Mplist, plist);
+  M17N_OBJECT_UNREF (plist);
+  return args;
+}
 
 static int
 take_action_list (MInputContext *ic, MPlist *action_list)
@@ -1169,59 +1584,171 @@ take_action_list (MInputContext *ic, MPlist *action_list)
       MSymbol name;
       MPlist *args;
 
-      if (MPLIST_MTEXT_P (action_list)
-         || MPLIST_INTEGER_P (action_list))
-       name = Minsert, args = action_list;
-      else if (MPLIST_PLIST_P (action_list)
-              && (MPLIST_MTEXT_P (MPLIST_PLIST (action_list))
-                  || MPLIST_PLIST_P (MPLIST_PLIST (action_list))))
-       name = Minsert, args = action_list;
-      else
+      if (MPLIST_PLIST_P (action_list)
+         && MPLIST_SYMBOL_P (MPLIST_PLIST (action_list)))
        {
          action = MPLIST_PLIST (action_list);
          name = MPLIST_SYMBOL (action);
          args = MPLIST_NEXT (action);
+         if (name == Minsert
+             && MPLIST_PLIST_P (args))
+           {
+             name = M_candidates;
+             mplist_set (action, Msymbol, name);
+           }
+       }
+      else if (MPLIST_MTEXT_P (action_list)
+              || MPLIST_INTEGER_P (action_list))
+       {
+         action = mplist ();
+         mplist_push (action, MPLIST_KEY (action_list),
+                      MPLIST_VAL (action_list));
+         mplist_push (action, Msymbol, Minsert);
+         mplist_set (action_list, Mplist, action);
+         M17N_OBJECT_UNREF (action);
+         name = Minsert;
+         args = MPLIST_NEXT (action);
+       }
+      else
+       {
+         /* (MPLIST_PLIST_P (action_list)
+             && (MPLIST_MTEXT_P (MPLIST_PLIST (action_list))
+                 || MPLIST_PLIST_P (MPLIST_PLIST (action_list)))) */
+         action = mplist ();
+         mplist_push (action, Mplist, MPLIST_VAL (action_list));
+         mplist_push (action, Msymbol, M_candidates);
+         mplist_set (action_list, Mplist, action);
+         M17N_OBJECT_UNREF (action);
+         name = M_candidates;
+         args = MPLIST_NEXT (action);
        }
 
       MDEBUG_PRINT1 (" %s", MSYMBOL_NAME (name));
       if (name == Minsert)
        {
+         if (MPLIST_SYMBOL_P (args))
+           {
+             args = resolve_variable (ic_info, MPLIST_SYMBOL (args));
+             if (! MPLIST_MTEXT_P (args) && ! MPLIST_INTEGER_P (args))
+               continue;
+           }
          if (MPLIST_MTEXT_P (args))
            preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0);
-         else if (MPLIST_INTEGER_P (args))
+         else                  /* MPLIST_INTEGER_P (args)) */
            preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args));
-         else if (MPLIST_SYMBOL_P (args))
-           {
-             int c = integer_value (ic, args);
+       }
+      else if (name == M_candidates)
+       {
+         MCharset *charset = get_select_charset (ic_info);
+         MPlist *plist = resolve_variable (ic_info, Mcandidates_group_size);
+         int column = MPLIST_INTEGER (plist);
+         MText *mt;
+         int i, len;
 
-             if (c >= 0 && c <= MCHAR_MAX)
-               preedit_insert (ic, ic->cursor_pos, NULL, c);
+         if (charset)
+           {
+             if (! (args = adjust_candidate_command (ic_info, args, charset)))
+               continue;
            }
          else
+           /* Avoid freeing ARGS later.  */
+           M17N_OBJECT_REF (args);
+
+         plist = MPLIST_PLIST (args);
+         if (column > 0)
            {
-             MText *mt;
-             int len;
+             MPlist *next = MPLIST_NEXT (plist);
 
-             args = MPLIST_PLIST (args);
-             if (MPLIST_MTEXT_P (args))
+             if (MPLIST_MTEXT_P (plist))
                {
-                 preedit_insert (ic, ic->cursor_pos, NULL,
-                                 mtext_ref_char (MPLIST_MTEXT (args), 0));
-                 len = 1;
+                 MText *mt = MPLIST_MTEXT (plist);
+
+                 if (MPLIST_TAIL_P (next))
+                   M17N_OBJECT_REF (mt);
+                 else
+                   {
+                     mt = mtext_dup (mt);
+                     while (! MPLIST_TAIL_P (next))
+                       {
+                         mt = mtext_cat (mt, MPLIST_MTEXT (next));
+                         next = MPLIST_NEXT (next);
+                       }
+                   }
+                 len = mtext_nchars (mt);
+                 if (len > column)
+                   {
+                     plist = mplist ();
+                     for (i = 0; i < len; i += column)
+                       {
+                         int to = (i + column < len ? i + column : len);
+                         MText *sub = mtext_copy (mtext (), 0, mt, i, to);
+                                                      
+                         mplist_add (plist, Mtext, sub);
+                         M17N_OBJECT_UNREF (sub);
+                       }
+                   }
+                 M17N_OBJECT_UNREF (mt);
                }
-             else
+             else              /* MPLIST_PLIST_P (plist) */
                {
-                 mt = MPLIST_MTEXT (MPLIST_PLIST (args));
-                 preedit_insert (ic, ic->cursor_pos, mt, 0);
-                 len = mtext_nchars (mt);
+                 MPlist *pl = MPLIST_PLIST (plist), *p;
+                 int j;
+
+                 if (MPLIST_TAIL_P (next))
+                   M17N_OBJECT_REF (pl);
+                 else
+                   {
+                     pl = mplist_copy (pl);
+                     while (! MPLIST_TAIL_P (next))
+                       {
+                         pl = mplist__conc (pl, MPLIST_PLIST (next));
+                         next = MPLIST_NEXT (next);
+                       }
+                   }
+                 len = mplist_length (pl);
+                 if (len > column)
+                   {
+                     MPlist *p0 = pl;
+
+                     plist = mplist ();
+                     for (i = 0; i < len; i += column)
+                       {
+                         p = mplist ();
+                         mplist_add (plist, Mplist, p);
+                         M17N_OBJECT_UNREF (p);
+                         for (j = 0; j < column && i + j < len; j++)
+                           {
+                             p = mplist_add (p, Mtext, MPLIST_VAL (p0));
+                             p0 = MPLIST_NEXT (p0);
+                           }
+                       }
+                   }
+                 M17N_OBJECT_UNREF (pl);
                }
-             mtext_put_prop (ic->preedit,
-                             ic->cursor_pos - len, ic->cursor_pos,
-                             Mcandidate_list, args);
-             mtext_put_prop (ic->preedit,
-                             ic->cursor_pos - len, ic->cursor_pos,
-                             Mcandidate_index, (void *) 0);
            }
+
+         if (plist == MPLIST_PLIST (args))
+           M17N_OBJECT_REF (plist);
+         if (MPLIST_MTEXT_P (plist))
+           {
+             preedit_insert (ic, ic->cursor_pos, NULL,
+                             mtext_ref_char (MPLIST_MTEXT (plist), 0));
+             len = 1;
+           }
+         else
+           {
+             mt = MPLIST_MTEXT (MPLIST_PLIST (plist));
+             preedit_insert (ic, ic->cursor_pos, mt, 0);
+             len = mtext_nchars (mt);
+           }
+         mtext_put_prop (ic->preedit,
+                         ic->cursor_pos - len, ic->cursor_pos,
+                         Mcandidate_list, plist);
+         mtext_put_prop (ic->preedit,
+                         ic->cursor_pos - len, ic->cursor_pos,
+                         Mcandidate_index, (void *) 0);
+         M17N_OBJECT_UNREF (plist);
+         M17N_OBJECT_UNREF (args);
        }
       else if (name == Mselect)
        {
@@ -1466,11 +1993,13 @@ take_action_list (MInputContext *ic, MPlist *action_list)
               || name == Mmul || name == Mdiv)
        {
          MSymbol sym = MPLIST_SYMBOL (args);
-         int val1 = (int) mplist_get (ic_info->vars, sym), val2;
+         int val1, val2;
+         MPlist *value;
          char *op;
 
+         val1 = integer_value (ic, args, &value);
          args = MPLIST_NEXT (args);
-         val2 = integer_value (ic, args);
+         val2 = integer_value (ic, args, NULL);
          if (name == Mset)
            val1 = val2, op = "=";
          else if (name == Madd)
@@ -1481,7 +2010,7 @@ take_action_list (MInputContext *ic, MPlist *action_list)
            val1 *= val2, op = "*=";
          else
            val1 /= val2, op = "/=";
-         mplist_put (ic_info->vars, sym, (void *) val1);
+         mplist_set (value, Minteger, (void *) val1);
          MDEBUG_PRINT3 ("(%s %s %d)", MSYMBOL_NAME (sym), op, val1);
        }
       else if (name == Mequal || name == Mless || name == Mgreater)
@@ -1490,9 +2019,9 @@ take_action_list (MInputContext *ic, MPlist *action_list)
          MPlist *actions1, *actions2;
          int ret = 0;
 
-         val1 = integer_value (ic, args);
+         val1 = integer_value (ic, args, NULL);
          args = MPLIST_NEXT (args);
-         val2 = integer_value (ic, args);
+         val2 = integer_value (ic, args, NULL);
          args = MPLIST_NEXT (args);
          actions1 = MPLIST_PLIST (args);
          args = MPLIST_NEXT (args);
@@ -1542,12 +2071,17 @@ take_action_list (MInputContext *ic, MPlist *action_list)
     }
 
   prop = NULL;
-  ic->candidate_list = NULL;
+  if (ic->candidate_list)
+    {
+      M17N_OBJECT_UNREF (ic->candidate_list);
+      ic->candidate_list = NULL;
+    }
   if (ic->cursor_pos > 0
       && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1,
                                     Mcandidate_list)))
     {
       ic->candidate_list = mtext_property_value (prop);
+      M17N_OBJECT_REF (ic->candidate_list);
       ic->candidate_index
        = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1,
                                Mcandidate_index);
@@ -1729,6 +2263,7 @@ reset_ic (MInputContext *ic, MSymbol ignore)
       ic->candidate_show = 0;
       if (ic->candidate_list)
        {
+         M17N_OBJECT_UNREF (ic->candidate_list);
          ic->candidate_list = NULL;
          ic->candidates_changed = 1;
        }
@@ -1747,80 +2282,28 @@ reset_ic (MInputContext *ic, MSymbol ignore)
 static int
 open_im (MInputMethod *im)
 {
-  MDatabase *mdb;
-  MInputMethodInfo *im_info;
-  MPlist *plist;
-  int result;
+  MInputMethodInfo *im_info = get_im_info (im->language, im->name, Mnil);
 
-  mdb = mdatabase_find (Minput_method, im->language, im->name, Mnil);
-  if (! mdb)
-    return -1;
-  plist = mdatabase_load (mdb);
-  if (! plist)
+  if (! im_info)
     MERROR (MERROR_IM, -1);
-  MSTRUCT_CALLOC (im_info, MERROR_IM);
   im->info = im_info;
-  result = load_input_method (im->language, im->name, plist, im_info);
-  M17N_OBJECT_UNREF (plist);
-  if (result < 0)
-    MERROR (MERROR_IM, -1);
+  im_info->im = im;
   return 0;
 }
 
 static void
 close_im (MInputMethod *im)
 {
-  MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
-  MPlist *plist;
-
-  if (im_info->title)
-    M17N_OBJECT_UNREF (im_info->title);
-  if (im_info->states)
-    {
-      MPLIST_DO (plist, im_info->states)
-       {
-         MIMState *state = (MIMState *) MPLIST_VAL (plist);
-
-         if (state->title)
-           M17N_OBJECT_UNREF (state->title);
-         if (state->map)
-           free_map (state->map);
-         free (state);
-       }
-      M17N_OBJECT_UNREF (im_info->states);
-    }
-
-  if (im_info->macros)
-    {
-      MPLIST_DO (plist, im_info->macros)
-       M17N_OBJECT_UNREF (MPLIST_VAL (plist)); 
-      M17N_OBJECT_UNREF (im_info->macros);
-    }
-
-  if (im_info->externals)
-    {
-      MPLIST_DO (plist, im_info->externals)
-       {
-         MIMExternalModule *external = MPLIST_VAL (plist);
-
-         dlclose (external->handle);
-         M17N_OBJECT_UNREF (external->func_list);
-         free (external);
-         MPLIST_KEY (plist) = Mt;
-       }
-      M17N_OBJECT_UNREF (im_info->externals);
-    }
-  free (im_info);
   im->info = NULL;
 }
 
-
 static int
 create_ic (MInputContext *ic)
 {
   MInputMethod *im = ic->im;
   MInputMethodInfo *im_info = (MInputMethodInfo *) im->info;
   MInputContextInfo *ic_info;
+  MPlist *plist;
 
   if (ic->info)
     ic_info = (MInputContextInfo *) ic->info;
@@ -1832,6 +2315,23 @@ create_ic (MInputContext *ic)
   MLIST_INIT1 (ic_info, keys, 8);
   ic_info->markers = mplist ();
   ic_info->vars = mplist ();
+  plist = get_nested_list (im->language, im->name, Mnil, M_variable);
+  MPLIST_DO (plist, plist)
+    {
+      MSymbol var = MPLIST_SYMBOL (plist);
+      MPlist *pl;
+
+      plist = MPLIST_NEXT (plist);
+      pl = MPLIST_PLIST (plist);
+      pl = MPLIST_NEXT (pl);   /* Skip description.  */
+      mplist_push (ic_info->vars, MPLIST_KEY (pl), MPLIST_VAL (pl));
+      mplist_push (ic_info->vars, Msymbol, var);
+    }
+  plist = resolve_variable (ic_info, Mcandidates_group_size);
+  if (! MPLIST_INTEGER_P (plist))
+    mplist_set (plist, Minteger, (void *) 10);
+  plist = resolve_variable (ic_info, Mcandidates_charset);
+
   ic_info->preedit_saved = mtext ();
   if (im_info->externals)
     {
@@ -1964,28 +2464,68 @@ lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
   return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0);
 }
 
+static MPlist *load_im_info_keys;
+
 static MPlist *
-load_im_info (MSymbol language, MSymbol name, MSymbol key)
+load_partial_im_info (MSymbol language, MSymbol name,
+                     MSymbol extra, MSymbol key)
 {
   MDatabase *mdb;
   MPlist *plist;
 
   if (language == Mnil || name == Mnil)
     MERROR (MERROR_IM, NULL);
-
   mdb = mdatabase_find (Minput_method, language, name, Mnil);
   if (! mdb)
     MERROR (MERROR_IM, NULL);
-  if (key != Mstate)
-    mplist_push (load_im_info_keys, Mmap, Mt);
+
   mplist_push (load_im_info_keys, key, Mt);
   plist = mdatabase__load_for_keys (mdb, load_im_info_keys);
   mplist_pop (load_im_info_keys);
-  if (key != Mstate)
-    mplist_pop (load_im_info_keys);    
   return plist;
 }
 
+
+static MInputMethodInfo *
+get_im_info (MSymbol language, MSymbol name, MSymbol extra)
+{
+  MDatabase *mdb;
+  MPlist *plist;
+  MInputMethodInfo *im_info = NULL;
+
+  if (language == Mnil)
+    MERROR (MERROR_IM, NULL);
+  mdb = mdatabase_find (Minput_method, language, name, extra);
+  if (! mdb)
+    MERROR (MERROR_IM, NULL);
+
+  if (! im_info_list)
+    im_info_list = mplist ();
+  else if ((plist = mplist_find_by_value (im_info_list, mdb)))
+    {
+      if (mdatabase__check (mdb))
+       {
+         plist = MPLIST_NEXT (plist);
+         im_info = MPLIST_VAL (plist);
+         return im_info;
+       }
+      mplist_pop (plist);
+      free_im_info (MPLIST_VAL (plist));
+      mplist_pop (plist);
+    }
+
+  plist = mdatabase_load (mdb);
+  if (! plist)
+    MERROR (MERROR_IM, NULL);
+  im_info = load_im_info (language, name, plist);
+  M17N_OBJECT_UNREF (plist);
+  if (! im_info)
+    MERROR (MERROR_IM, NULL);
+  mplist_push (im_info_list, Mt, im_info);
+  mplist_push (im_info_list, Mt, mdb);
+  return im_info;
+}
+
 \f
 /* Input method command handler.  */
 
@@ -1993,7 +2533,6 @@ load_im_info (MSymbol language, MSymbol name, MSymbol key)
    (LANG:(IM-NAME:(COMMAND ...) ...) ...) ...
    COMMAND is CMD-NAME:(mtext:DESCRIPTION plist:KEYSEQ ...))
    Global commands are storead as (t (t COMMAND ...))  */
-static MPlist *command_list;
 
 /* Check if PLIST is a valid command key sequence.
    PLIST must be NULL or:
@@ -2023,333 +2562,62 @@ check_command_keyseq (MPlist *plist)
   return 0;
 }
 
-static MText *
-get_description_advance (MPlist *plist)
-{
-  MText *mt;
-  int pos;
-
-  if (! MPLIST_MTEXT_P (plist))
-    return NULL;
-  mt = mplist_pop (plist);
-  pos = mtext_chr (mt, '\n'); 
-  if (pos > 0)
-    {
-      MText *detail = mtext_copy (mtext (), 0, mt, pos + 1, mtext_nchars (mt));
-      mtext_del (mt, pos, mtext_nchars (mt));
-      mtext_put_prop (mt, 0, pos, Mdetail_text, detail);
-      M17N_OBJECT_UNREF (detail);
-    }
-  return mt;
-}
+/* Check if PLIST has this form:
+     ([ plist:([ symbol:KEY | integer:KEY ]) | mtext:KEYSEQ ]
+      ...)
+   If the form of PLIST matches, return 0, otherwise return -1.  */
 
-static MPlist *
-parse_command_list (MPlist *plist, MPlist *global_list)
+static int
+check_command_list (MPlist *plist)
 {
-  MPlist *val = mplist ();
-
-  /* PLIST ::= (sym:CMD mtext:DESCRIPTION ? (sym:KEY ...) ...) ... */
   MPLIST_DO (plist, plist)
     {
-      MSymbol cmd;
-      MText *mt;
-      MPlist *this_val, *pl, *p;
-
-      if (! MPLIST_PLIST_P (plist))
-       continue;
-      pl = MPLIST_PLIST (plist);
-      if (! MPLIST_SYMBOL_P (pl))
-       continue;
-      cmd = MPLIST_SYMBOL (pl);
-      pl = MPLIST_NEXT (pl);
-      mt = get_description_advance (pl);
-      this_val = mplist ();
-
-      if (! mt && global_list)
+      if (MPLIST_PLIST_P (plist))
        {
-         /* Get the description from global_list.  */
-         p = mplist_get (global_list, cmd);
-         if (p && MPLIST_MTEXT (p))
-           {
-             mt = MPLIST_MTEXT (p);
-             M17N_OBJECT_REF (mt);
-           }
-       }
-      if (! mt)
-       mt = mtext ();
-      mplist_add (this_val, Mtext, mt);
-      M17N_OBJECT_UNREF (mt);
+         MPlist *pl = MPLIST_PLIST (plist);
 
-      /* PL ::= (sym:KEY ...) ... */
-      MPLIST_DO (pl, pl)
-       {
-         if (MPLIST_PLIST_P (pl)
-             && check_command_keyseq (MPLIST_PLIST (pl)) >= 0)
-           /* All the elements are valid keys.  */
-           mplist_add (this_val, Mplist, MPLIST_PLIST (pl));
+         MPLIST_DO (pl, pl)
+           if (! MPLIST_SYMBOL_P (pl) && ! MPLIST_INTEGER_P (pl))
+             return -1;
        }
-
-      mplist_put (val, cmd, this_val);
+      else if (! MPLIST_MTEXT_P (plist))
+       return -1;
     }
-  return val;
+  return 0;
 }
 
-static MPlist *
-get_command_list (MSymbol language, MSymbol name)
-{
-  MPlist *per_lang;
-  MPlist *plist, *pl;
-
-  if (name == Mnil)
-    language = name = Mt;
-
-  if (! command_list)
-    {
-      MDatabase *mdb = mdatabase_find (msymbol ("input"), M_command,
-                                      Mnil, Mnil);
-
-      if (mdb && (plist = mdatabase_load (mdb)))
-       {
-         pl = parse_command_list (plist, NULL);
-         M17N_OBJECT_UNREF (plist);
-       }
-      else
-       pl = mplist ();
-      plist = mplist ();
-      mplist_add (plist, Mt, pl);
-      command_list = mplist ();
-      mplist_add (command_list, Mt, plist);
-    }
-
-  per_lang = mplist_get (command_list, language);
-  if (per_lang)
-    {
-      plist = mplist_find_by_key (per_lang, name);
-      if (plist)
-       return (MPLIST_VAL (plist));
-    }
-  else
-    {
-      per_lang = mplist ();
-      mplist_add (command_list, language, per_lang);
-    }
-
-  /* Now we are sure that we are loading per-im info.  */
-  /* Get the global command list.  */
-  plist = load_im_info (language, name, M_command);
-  if (! plist || mplist_key (plist) == Mnil)
-    {
-      if (! plist)
-       plist = mplist ();
-      mplist_add (per_lang, name, plist);
-      return plist;
-    }
-  pl = parse_command_list (mplist_value (plist),
-                          mplist_get ((MPlist *) mplist_get (command_list, Mt),
-                                      Mt));
-  M17N_OBJECT_UNREF (plist);
-  mplist_put (per_lang, name, pl);
-  return pl;
-}
 
 \f
 /* Input method variable handler.  */
 
-/* List of all variables. 
-   (LANG:(IM-NAME:(VAR ...) ...) ...) ...
-   VAR is VAR-NAME:(mtext:DESCRIPTION TYPE:VALUE ...))  */
-
-static MPlist *variable_list;
-
-static MPlist *
-parse_variable_list (MPlist *plist)
-{
-  MPlist *val = mplist (), *pl, *p;
-
-  /* PLIST ::= (sym:VAR mtext:DESCRIPTION TYPE:INIT-VAL ...) ...  */
-  MPLIST_DO (plist, plist)
-    {
-      MSymbol var, type;
-      MText *mt;
-      MPlist *this_val;
-
-      if (! MPLIST_PLIST_P (plist))
-       continue;
-      pl = MPLIST_PLIST (plist);
-      if (! MPLIST_SYMBOL_P (pl))
-       continue;
-      var = MPLIST_SYMBOL (pl);
-      pl = MPLIST_NEXT (pl);
-      mt = get_description_advance (pl);
-      if (! mt || MPLIST_TAIL_P (pl))
-       continue;
-      this_val = mplist ();
-      mplist_add (this_val, Mtext, mt);
-      M17N_OBJECT_UNREF (mt);
-      type = MPLIST_KEY (pl);
-      mplist_add (this_val, type, MPLIST_VAL (pl));
-      MPLIST_DO (pl, MPLIST_NEXT (pl))
-       {
-         if (type != MPLIST_KEY (pl)
-             && (type != Minteger || ! MPLIST_PLIST_P (pl)))
-           break;
-         if (MPLIST_PLIST_P (pl))
-           {
-             MPLIST_DO (p, MPLIST_PLIST (pl))
-               if (! MPLIST_INTEGER_P (p))
-                 break;
-             if (! MPLIST_TAIL_P (p))
-               break;
-           }
-         mplist_add (this_val, MPLIST_KEY (pl), MPLIST_VAL (pl));
-       }
-
-      mplist_put (val, var, this_val);
-    }
-  return val;
-}
-
+/* Check if PLIST has this form:
+     (TYPE:VAL   ;; TYPE ::= integer | mtext | symbol
+      VALID-VALUE
+      ...)
+   If the form of PLIST matches, return 0, otherwise return -1.  */
 
-static MPlist *
-get_variable_list (MSymbol language, MSymbol name)
+static int
+check_variable_list (MPlist *plist)
 {
-  MPlist *per_lang;
-  MPlist *plist, *pl;
+  MSymbol type = MPLIST_KEY (plist);
+  MPlist *p; 
 
-  if (language == Mnil || name == Mnil)
-    MERROR (MERROR_IM, NULL);
-  if (! variable_list)
-    variable_list = mplist ();
-  per_lang = mplist_get (variable_list, language);
-  if (per_lang)
-    {
-      plist = mplist_find_by_key (per_lang, name);
-      if (plist)
-       return (MPLIST_VAL (plist));
-    }
-  else
-    {
-      per_lang = mplist ();
-      mplist_add (variable_list, language, per_lang);
-    }
-  plist = load_im_info (language, name, M_variable);
-  if (! plist || mplist_key (plist) == Mnil)
+  if (type != Minteger && type != Mtext && type != Msymbol)
+    return -1;
+  MPLIST_DO (plist, MPLIST_NEXT (plist))
     {
-      if (! plist)
-       plist = mplist ();
-      mplist_add (per_lang, name, plist);
-      return plist;
-    }
-  pl = parse_variable_list (mplist_value (plist));
-  M17N_OBJECT_UNREF (plist);
-  mplist_put (per_lang, name, pl);
-  return pl;
-}
-
-typedef struct _MDatabaseStatList
-{
-  char *dirname;
-  time_t mtime, ctime;
-  struct _MDatabaseStatList *next;
-} MDatabaseStatList;
-
-static MDatabaseStatList *imdir_stat_list;
-
-/* This function is called before any operation with tag0 specified as
-   `input-method' on the m17n database.  It lists all *.mim files and
-   add them to the database.  */
-
-static void
-input_method_hook (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
-{
-  MPlist *plist, *pl, *p;
-  char path[PATH_MAX];
-
-  tag3 = Mnil;
-  mplist_push (load_im_info_keys, Mmap, Mt);
-  mplist_push (load_im_info_keys, M_description, Mt);
-  MPLIST_DO (plist, mdatabase__dir_list)
-    {
-      char *dirname = (char *) MPLIST_VAL (plist);
-      struct stat st;
-      MDatabaseStatList *stlist;
-      int dirlen;
-      DIR *dir;
-      struct dirent *dp;
-      
-      if (stat (dirname, &st) < 0
-         || ! S_ISDIR (st.st_mode))
-       continue;
-      for (stlist = imdir_stat_list; stlist; stlist = stlist->next)
-       if (strcmp (stlist->dirname, dirname) == 0)
-         break;
-      if (! stlist)
-       {
-         MSTRUCT_MALLOC (stlist, MERROR_IM);
-         stlist->dirname = strdup (dirname);
-         stlist->next = imdir_stat_list;
-         imdir_stat_list = stlist;
-       }
-      else if (stlist->mtime == st.st_mtime
-              && stlist->ctime == st.st_ctime)
-       /* This directory is not changed since we checked last
-          time.  */
-       continue;
-      stlist->mtime = st.st_mtime;
-      stlist->ctime = st.st_ctime;
-
-      dir = opendir (dirname);
-      if (! dir)
-       continue;
-      dirlen = strlen (dirname);
-      strcpy (path, dirname);
-      while ((dp = readdir (dir)) != NULL)
+      if (type == Minteger && MPLIST_PLIST_P (plist))
        {
-         /* We can't trust dp->d_nameln.  */
-         int len = strlen (dp->d_name);
-         FILE *fp;
-
-         if (len > 4 && memcmp (dp->d_name + len - 4, ".mim", 4) == 0)
-           {
-             strcpy (path + dirlen, dp->d_name);
-             fp = fopen (path, "r");
-             if (! fp)
-               continue;
-             pl = mplist__from_file (fp, load_im_info_keys);
-             fclose (fp);
-             if (pl)
-               {
-                 if (MPLIST_PLIST_P (pl))
-                   {
-                     p = MPLIST_PLIST (pl);
-                     p = MPLIST_NEXT (p);
-                     if (MPLIST_SYMBOL_P (p))
-                       {
-                         tag1 = MPLIST_VAL (p);
-                         p = MPLIST_NEXT (p);
-                         if (MPLIST_SYMBOL_P (p))
-                           {
-                             MDatabase *mdb;
-
-                             tag2 = MPLIST_VAL (p);
-                             mdb = mdatabase_find (tag0, tag2, tag2, tag3);
-                             if (! mdb)
-                               mdatabase_define (tag0, tag1, tag2, tag3,
-                                                 NULL, path);
-                           }
-                       }
-                   }
-                 M17N_OBJECT_UNREF (pl);
-               }
-           }
+         MPLIST_DO (p, MPLIST_PLIST (plist))
+           if (! MPLIST_INTEGER_P (p))
+             return -1;
        }
-      closedir (dir);
+      else if (type != MPLIST_KEY (plist))
+       return -1;
     }
-  mplist_pop (load_im_info_keys);
-  mplist_pop (load_im_info_keys);
+  return 0;
 }
 
-
 /* Support functions for mdebug_dump_im.  */
 
 static void
@@ -2421,7 +2689,6 @@ minput__init ()
   MPlist *plist;
 
   Minput_method = msymbol ("input-method");
-  msymbol_put (Minput_method, M_database_hook, (void *) input_method_hook);
   Minput_driver = msymbol ("input-driver");
   Mtitle = msymbol ("title");
   Mmacro = msymbol ("macro");
@@ -2430,6 +2697,7 @@ minput__init ()
   Mstate = msymbol ("state");
   Minclude = msymbol ("include");
   Minsert = msymbol ("insert");
+  M_candidates = msymbol ("  candidates");
   Mdelete = msymbol ("delete");
   Mmove = msymbol ("move");
   Mmark = msymbol ("mark");
@@ -2451,6 +2719,9 @@ minput__init ()
   Mless = msymbol ("<");
   Mgreater = msymbol (">");
 
+  Mcandidates_group_size = msymbol ("candidates-group-size");
+  Mcandidates_charset = msymbol ("candidates-charset");
+
   Minput_preedit_start = msymbol ("input-preedit-start");
   Minput_preedit_done = msymbol ("input-preedit-done");
   Minput_preedit_draw = msymbol ("input-preedit-draw");
@@ -2478,8 +2749,6 @@ minput__init ()
   M_command = msymbol ("command");
   M_variable = msymbol ("variable");
 
-  Mdetail_text = msymbol_as_managing_key ("  detail-text");
-
   load_im_info_keys = mplist ();
   plist = mplist_add (load_im_info_keys, Mstate, Mnil);
 
@@ -2541,35 +2810,13 @@ minput__init ()
 void
 minput__fini ()
 {
-  MPlist *par_lang, *par_im, *p;
-
   if (command_list)
     {
-      MPLIST_DO (par_lang, command_list)
-       {
-         MPLIST_DO (par_im, MPLIST_VAL (par_lang))
-           {
-             MPLIST_DO (p, MPLIST_VAL (par_im))
-               M17N_OBJECT_UNREF (MPLIST_VAL (p));
-             M17N_OBJECT_UNREF (MPLIST_VAL (par_im));
-           }
-         M17N_OBJECT_UNREF (MPLIST_VAL (par_lang));
-       }
       M17N_OBJECT_UNREF (command_list);
       command_list = NULL;
     }
   if (variable_list)
     {
-      MPLIST_DO (par_lang, variable_list)
-       {
-         MPLIST_DO (par_im, MPLIST_VAL (par_lang))
-           {
-             MPLIST_DO (p, MPLIST_VAL (par_im))
-               M17N_OBJECT_UNREF (MPLIST_VAL (p));
-             M17N_OBJECT_UNREF (MPLIST_VAL (par_im));
-           }
-         M17N_OBJECT_UNREF (MPLIST_VAL (par_lang));
-       }
       M17N_OBJECT_UNREF (variable_list);
       variable_list = NULL;
     }
@@ -2585,16 +2832,21 @@ minput__fini ()
       minput_driver->callback_list = NULL;
     }
 
-  M17N_OBJECT_UNREF (load_im_info_keys);
-
-  while (imdir_stat_list)
+  if (im_info_list)
     {
-      MDatabaseStatList *next = imdir_stat_list->next;
-
-      free (imdir_stat_list->dirname);
-      free (imdir_stat_list);
-      imdir_stat_list = next;
+      while (! MPLIST_TAIL_P (im_info_list))
+       {
+         /* Pop (t . mdb) */
+         mplist_pop (im_info_list);
+         free_im_info ((MInputMethodInfo *) MPLIST_VAL (im_info_list));
+         /* Pop (t . im_info) */
+         mplist_pop (im_info_list);
+       }
+      M17N_OBJECT_UNREF (im_info_list);
+      im_info_list = NULL;
     }
+  M17N_OBJECT_UNREF (load_im_info_keys);
 }
 
 void
@@ -3170,29 +3422,11 @@ minput_reset_ic (MInputContext *ic)
     minput__callback (ic, Minput_reset);
 }
 
-/*=*/
-/***en
-    @brief Key of a text property for detailed description.
-
-    The symbol #Mdetail_text is a managing key usually used for a
-    text property whose value is an M-text that contains detailed
-    description.  */
-/***ja
-    @brief ¾ÜºÙÀâÌÀÍѥƥ­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼.
-
-    ¥·¥ó¥Ü¥ë #Mdetail_text ¤Ï´ÉÍý¥­¡¼¤Ç¤¢¤ê¡¢Ä̾ï¾ÜºÙ¤ÊÀâÌÀ¤ò´Þ¤à 
-    M-text ¤òÃͤȤ·¤Æ»ý¤Ä¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ËÍѤ¤¤é¤ì¤ë¡£
-    */
-MSymbol Mdetail_text;
-
 /***en
     @brief Get description text of an input method.
 
     The minput_get_description () function returns an M-text that
-    briefly describes the input method specified by $LANGUAGE and
-    $NAME.  The returned M-text may have a text property, from its
-    beginning to end, #Mdetail_text whose value is an M-text
-    describing the input method in more detail.
+    describes the input method specified by $LANGUAGE and $NAME.
 
     @return
     If the specified input method has a description text, a pointer to
@@ -3202,36 +3436,30 @@ MSymbol Mdetail_text;
 /***ja
     @brief ÆþÎϥ᥽¥Ã¥É¤ÎÀâÌÀ¥Æ¥­¥¹¥È¤òÆÀ¤ë.
 
-    ´Ø¿ô minput_get_description () ¤Ï¡¢$LANGUAGE ¤È $NAME 
-    ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ò´Êñ¤ËÀâÌÀ¤¹¤ë M-text ¤òÊÖ¤¹¡£ÊÖ¤µ¤ì¤ë M-text 
-    ¤Ë¤Ï¡¢¤½¤ÎÁ´ÂΤËÂФ·¤Æ #Mdetail_text 
-    ¤È¤¤¤¦¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬Éղ䵤ì¤Æ¤¤¤ë¾ì¹ç¤¬¤¢¤ê¡¢¤½¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤÏÆþÎϥ᥽¥Ã¥É¤ò¤µ¤é¤Ë¾ÜºÙ¤ËÀâÌÀ¤¹¤ë
-    M-text ¤Ç¤¢¤ë¡£
+    ´Ø¿ô minput_get_description () ¤Ï¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄê
+    ¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤òÀâÌÀ¤¹¤ë M-text ¤òÊÖ¤¹¡£
 
-    @return 
-    »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤¬ÀâÌÀ¤¹¤ë¥Æ¥­¥¹¥È¤ò»ý¤Ã¤Æ¤¤¤ì¤Ð¡¢ 
+    @return »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤¬ÀâÌÀ¤¹¤ë¥Æ¥­¥¹¥È¤ò»ý¤Ã¤Æ¤¤¤ì¤Ð¡¢
     #MText ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¸Æ¤Ó½Ð¤·Â¦¤Ï¡¢¤½¤ì¤ò m17n_object_unref
-    () ¤òÍѤ¤¤Æ²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ÆþÎϥ᥽¥Ã¥É¤ËÀâÌÀ¥Æ¥­¥¹¥È¤¬Ìµ¤±¤ì¤Ð@c NULL ¤òÊÖ¤¹¡£ */
+    () ¤òÍѤ¤¤Æ²òÊü¤·¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ÆþÎϥ᥽¥Ã¥É¤ËÀâÌÀ¥Æ¥­¥¹¥È¤¬Ìµ¤±
+    ¤ì¤Ð@c NULL ¤òÊÖ¤¹¡£ */
 
 MText *
 minput_get_description (MSymbol language, MSymbol name)
 {
-  MPlist *plist = load_im_info (language, name, M_description);
+  MPlist *plist = load_partial_im_info (language, name, Mnil, M_description);
   MPlist *pl;
-  MText *mt = NULL;
+  MText *mt;
 
   if (! plist)
     return NULL;
-  if (! MPLIST_PLIST_P (plist))
-    {
-      M17N_OBJECT_UNREF (plist);      
-      return NULL;
-    }
   pl = MPLIST_PLIST (plist);
-  while (! MPLIST_TAIL_P (pl) && ! MPLIST_MTEXT_P (pl))
-    pl = MPLIST_NEXT (pl);
+  pl = MPLIST_NEXT (pl);
   if (MPLIST_MTEXT_P (pl))
-    mt = get_description_advance (pl);
+    {
+      mt = MPLIST_MTEXT (pl);
+      M17N_OBJECT_REF (mt);
+    }
   M17N_OBJECT_UNREF (plist);
   return mt;
 }
@@ -3269,9 +3497,7 @@ minput_get_description (MSymbol language, MSymbol name)
     value is a plist of the form COMMAND-INFO described below.
 
     The first element of COMMAND-INFO has the key #Mtext, and the
-    value is an M-text describing the command briefly.  This M-text
-    may have a text property whose key is #Mdetail_text and whose
-    value is an M-text describing the command in more detail.
+    value is an M-text describing the command.
 
     If there are no more elements, that means no key sequences are
     assigned to the command.  Otherwise, each of the remaining
@@ -3284,50 +3510,55 @@ minput_get_description (MSymbol language, MSymbol name)
 /***ja
     @brief ÆþÎϥ᥽¥Ã¥É¤Î¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÆÀ¤ë.
 
-    ´Ø¿ô minput_get_commands () ¤Ï¡¢ $LANGUAGE ¤È $NAME 
-    ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
-    ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤È¤Ï¡¢µ¿»÷¥­¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì¤Ë£±¤Ä°Ê¾å¤Î¼ÂºÝ¤ÎÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¤â¤Î¤ò»Ø¤¹¡£
+    ´Ø¿ô minput_get_commands () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ
+    ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤ÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£ÆþÎϥ᥽¥Ã
+    ¥É¥³¥Þ¥ó¥É¤È¤Ï¡¢µ¿»÷¥­¡¼¥¤¥Ù¥ó¥È¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì¤Ë£±¤Ä°Ê¾å¤Î¼ÂºÝ¤Î
+    ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ë¤â¤Î¤ò»Ø¤¹¡£
 
-    ¥³¥Þ¥ó¥É¤Ë¤Ï¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£
-    ¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤ÏÊ£¿ô¤ÎÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¡¢Æ±¤¸ÌÜŪ¤Ç¡¢¥°¥í¡¼¥Ð¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ¤ÇÍѤ¤¤é¤ì¤ë¡£
-    ¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤ÏÆÃÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Î¤ß¡¢¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤Ç»ÈÍѤµ¤ì¤ë¡£
+    ¥³¥Þ¥ó¥É¤Ë¤Ï¥°¥í¡¼¥Ð¥ë¤È¥í¡¼¥«¥ë¤Î£²¼ïÎब¤¢¤ë¡£¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É
+    ¤ÏÊ£¿ô¤ÎÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¡¢Æ±¤¸ÌÜŪ¤Ç¡¢¥°¥í¡¼¥Ð¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ
+    ¤ÇÍѤ¤¤é¤ì¤ë¡£¥í¡¼¥«¥ë¥³¥Þ¥ó¥É¤ÏÆÃÄê¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Î¤ß¡¢¥í¡¼¥«¥ë
+    ¤Ê¥­¡¼³äÅö¤Ç»ÈÍѤµ¤ì¤ë¡£
 
-    ¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ï¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Î¥­¡¼³äÅö¤òÊѹ¹¤¹¤ë¤³¤È¤â¤Ç¤­¤ë¡£
-    ¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥ÉÍѤΥ°¥í¡¼¥Ð¥ë¥­¡¼³ä¤êÅö¤Æ¤Ï¡¢»ÈÍѤ¹¤ëÆþÎϥ᥽¥Ã¥É¤Ë¤ª¤¤¤Æ¤½¤Î¥³¥Þ¥ó¥ÉÍÑ¤Î¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç¤Ë¤Î¤ßÍ­¸ú¤Ç¤¢¤ë¡£
+    ¸Ä¡¹¤ÎÆþÎϥ᥽¥Ã¥É¤Ï¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Î¥­¡¼³äÅö¤òÊѹ¹¤¹¤ë¤³¤È¤â¤Ç
+    ¤­¤ë¡£¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥ÉÍѤΥ°¥í¡¼¥Ð¥ë¥­¡¼³ä¤êÅö¤Æ¤Ï¡¢»ÈÍѤ¹¤ëÆþÎÏ
+    ¥á¥½¥Ã¥É¤Ë¤ª¤¤¤Æ¤½¤Î¥³¥Þ¥ó¥ÉÍÑ¤Î¥í¡¼¥«¥ë¤Ê¥­¡¼³äÅö¤¬Â¸ºß¤·¤Ê¤¤¾ì¹ç
+    ¤Ë¤Î¤ßÍ­¸ú¤Ç¤¢¤ë¡£
 
-    $NAME ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
-    ¤³¤Î¾ì¹ç¡¢$LANGUAGE ¤Ï̵»ë¤µ¤ì¤ë¡£
+    $NAME ¤¬ #Mnil ¤Ç¤¢¤ì¤Ð¡¢¥°¥í¡¼¥Ð¥ë¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£¤³¤Î
+    ¾ì¹ç¡¢$LANGUAGE ¤Ï̵»ë¤µ¤ì¤ë¡£
 
-    $NAME ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤È $NAME 
-    ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþÎϥ᥽¥Ã¥É¤ËÃÖ¤±¤ë¥í¡¼¥«¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ¤ò»ý¤Ä¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó¤òÊÖ¤¹¡£
+    $NAME ¤¬ #Mnil ¤Ç¤Ê¤±¤ì¤Ð¡¢$LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤ëÆþ
+    Îϥ᥽¥Ã¥É¤ËÃÖ¤±¤ë¥í¡¼¥«¥ë¤Ê¥­¡¼³ä¤êÅö¤Æ¤ò»ý¤Ä¥³¥Þ¥ó¥É¤Ë´Ø¤¹¤ë¾ðÊó
+    ¤òÊÖ¤¹¡£
 
     @return
     ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤¬¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï @c NULL ¤òÊÖ¤¹¡£
 
-    ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
-    ¥ê¥¹¥È¤Î³ÆÍ×ÁǤΥ­¡¼¤Ï¸Ä¡¹¤Î¥³¥Þ¥ó¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢Ãͤϲ¼µ­¤Î 
-    COMMAND-INFO ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ë¡£
+    ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥ê¥¹¥È¤Î³ÆÍ×ÁǤÎ
+    ¥­¡¼¤Ï¸Ä¡¹¤Î¥³¥Þ¥ó¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢Ãͤϲ¼µ­¤Î COMMAND-INFO
+    ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ë¡£
 
-    COMMAND-INFO ¤ÎÂè°ìÍ×ÁǤϥ­¡¼¤È¤·¤Æ #Mtext 
-    ¤ò¡¢ÃͤȤ·¤Æ¤½¤Î¥³¥Þ¥ó¥É¤ò´Êñ¤ËÀâÌÀ¤¹¤ë M-text ¤ò»ý¤Ä¡£¤³¤Î M-text 
-    ¤Ï¡¢#Mdetail_text 
-    ¤ò¥­¡¼¤È¤¹¤ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¡¢¤½¤ÎÃͤϤ½¤Î¥³¥Þ¥ó¥É¤ò¤è¤ê¾ÜºÙ¤ËÀâÌÀ¤¹¤ë
-    M-text ¤Ç¤¢¤ë¡£
+    COMMAND-INFO ¤ÎÂè°ìÍ×ÁǤΥ­¡¼¤Ï #Mtext ¤Þ¤¿¤Ï #Msymbol ¤Ç¤¢¤ë¡£¥­¡¼
+    ¤¬ #Mtext ¤Ê¤é¡¢ÃͤϤ½¤Î¥³¥Þ¥ó¥É¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£¥­¡¼¤¬
+    #Msymbol ¤Ê¤éÃͤϠ#Mnil ¤Ç¤¢¤ê¡¢¤³¤Î¥³¥Þ¥ó¥É¤ÏÀâÌÀ¥Æ¥­¥¹¥È¤ò»ý¤¿¤Ê
+    ¤¤¤³¤È¤Ë¤Ê¤ë¡£
 
-    ¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢¤³¤Î¥³¥Þ¥ó¥É¤ËÂФ·¤Æ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤Ê¤¤¤³¤È¤ò°ÕÌ£¤¹¤ë¡£
-    ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢»Ä¤ê¤Î³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ#Mplist 
-    ¤ò¡¢ÃͤȤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò»ý¤Ä¡£
-    ¤³¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Î¥­¡¼¤Ï #Msymbol 
-    ¤Ç¤¢¤ê¡¢Ãͤϸ½ºß¤½¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì¤Æ¤¤¤ëÆþÎÏ¥­¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
+    ¤½¤ì°Ê³°¤ÎÍ×ÁǤ¬Ìµ¤±¤ì¤Ð¡¢¤³¤Î¥³¥Þ¥ó¥É¤ËÂФ·¤Æ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤¬³ä
+    ¤êÅö¤Æ¤é¤ì¤Æ¤¤¤Ê¤¤¤³¤È¤ò°ÕÌ£¤¹¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢»Ä¤ê¤Î³ÆÍ×ÁǤϥ­
+    ¡¼¤È¤·¤Æ#Mplist ¤ò¡¢ÃͤȤ·¤Æ¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤ò»ý¤Ä¡£¤³¤Î¥×¥í¥Ñ¥Æ¥£
+    ¥ê¥¹¥È¤Î¥­¡¼¤Ï #Msymbol ¤Ç¤¢¤ê¡¢Ãͤϸ½ºß¤½¤Î¥³¥Þ¥ó¥É¤Ë³ä¤êÅö¤Æ¤é¤ì
+    ¤Æ¤¤¤ëÆþÎÏ¥­¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
 
-    ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
+    ÊÖ¤µ¤ì¤ë¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ï¥é¥¤¥Ö¥é¥ê¤Ë¤è¤Ã¤Æ´ÉÍý¤µ¤ì¤Æ¤ª¤ê¡¢¸Æ¤Ó½Ð
+    ¤·Â¦¤ÇÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£*/
 
 MPlist *
 minput_get_commands (MSymbol language, MSymbol name)
 {
-  MPlist *plist = get_command_list (language, name);
+  MPlist *plist = get_nested_list (language, name, Mnil, M_command);
 
-  return (! plist || MPLIST_TAIL_P (plist) ? NULL : plist);
+  return (MPLIST_TAIL_P (plist) ? NULL : plist);
 }
 
 /***en
@@ -3353,22 +3584,22 @@ minput_get_commands (MSymbol language, MSymbol name)
 /***ja
     @brief ÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É¤Ë¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤ò³ä¤êÅö¤Æ¤ë.
 
-    ´Ø¿ô minput_assign_command_keys () ¤Ï¡¢ $LANGUAGE ¤È $NAME 
-    ¤Ë¤è¤Ã¤Æ»ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É $COMMAND 
-    ¤ËÂФ·¤Æ¡¢ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹ $KEYSEQ ¤ò³ä¤êÅö¤Æ¤ë¡£ $NAME ¤¬ #Mnil
-    ¤Ê¤é¤Ð¡¢$LANGUAGE ¤Ë´Ø·¸¤Ê¤¯¡¢ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥°¥í¡¼¥Ð¥ë¤Ë³ä¤êÅö¤Æ¤é¤ì¤ë¡£
-    ¤½¤¦¤Ç¤Ê¤ì¤Ð¡¢³ä¤êÅö¤Æ¤Ï¥í¡¼¥«¥ë¤Ç¤¢¤ë¡£
+    ´Ø¿ô minput_assign_command_keys () ¤Ï¡¢ $LANGUAGE ¤È $NAME ¤Ë¤è¤Ã¤Æ
+    »ØÄꤵ¤ì¤¿ÆþÎϥ᥽¥Ã¥ÉÍѤÎÆþÎϥ᥽¥Ã¥É¥³¥Þ¥ó¥É $COMMAND ¤ËÂФ·¤Æ¡¢
+    ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹ $KEYSEQ ¤ò³ä¤êÅö¤Æ¤ë¡£ $NAME ¤¬ #Mnil ¤Ê¤é¤Ð¡¢
+    $LANGUAGE ¤Ë´Ø·¸¤Ê¤¯¡¢ÆþÎÏ¥­¡¼¥·¡¼¥¯¥¨¥ó¥¹¤Ï¥°¥í¡¼¥Ð¥ë¤Ë³ä¤êÅö¤Æ¤é
+    ¤ì¤ë¡£¤½¤¦¤Ç¤Ê¤ì¤Ð¡¢³ä¤êÅö¤Æ¤Ï¥í¡¼¥«¥ë¤Ç¤¢¤ë¡£
 
-    $KEYSEQ ¤Î³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ $Msymbol 
-    ¤ò¡¢ÃͤȤ·¤ÆÆþÎÏ¥­¡¼¤òɽ¤¹¥·¥ó¥Ü¥ë¤ò»ý¤¿¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+    $KEYSEQ ¤Î³ÆÍ×ÁǤϥ­¡¼¤È¤·¤Æ $Msymbol ¤ò¡¢ÃͤȤ·¤ÆÆþÎÏ¥­¡¼¤òɽ¤¹¥·
+    ¥ó¥Ü¥ë¤ò»ý¤¿¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
 
-    $KEYSEQ ¤Ï @c NULL ¤Ç¤â¤è¤¤¡£
-    ¤³¤Î¾ì¹ç¡¢¥°¥í¡¼¥Ð¥ë¤â¤·¤¯¤Ï¥í¡¼¥«¥ë¤Ê¤¹¤Ù¤Æ¤Î³ä¤êÅö¤Æ¤¬¾Ãµî¤µ¤ì¤ë¡£
+    $KEYSEQ ¤Ï @c NULL ¤Ç¤â¤è¤¤¡£¤³¤Î¾ì¹ç¡¢¥°¥í¡¼¥Ð¥ë¤â¤·¤¯¤Ï¥í¡¼¥«¥ë¤Ê
+    ¤¹¤Ù¤Æ¤Î³ä¤êÅö¤Æ¤¬¾Ãµî¤µ¤ì¤ë¡£
 
-    ¤³¤Î³ä¤êÅö¤Æ¤Ï¡¢³ä¤êÅö¤Æ°Ê¹ß¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­¸ú¤Ë¤Ê¤ë¡£
+    ¤³¤Î³ä¤êÅö¤Æ¤Ï¡¢³ä¤êÅö¤Æ°Ê¹ß¿·¤·¤¯¥ª¡¼¥×¥ó¤µ¤ì¤¿ÆþÎϥ᥽¥Ã¥É¤«¤éÍ­
+    ¸ú¤Ë¤Ê¤ë¡£
 
-    @return 
-    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
+    @return ½èÍý¤¬À®¸ù¤¹¤ì¤Ð 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢
     #merror_code ¤ò #MERROR_IM ¤ËÀßÄꤹ¤ë¡£  */
 
 int
@@ -3378,7 +3609,7 @@ minput_assign_command_keys (MSymbol language, MSymbol name,
   MPlist *plist, *pl, *p;
 
   if (check_command_keyseq (keyseq) < 0
-      || ! (plist = get_command_list (language, name)))
+      || ! (plist = get_nested_list (language, name, Mnil, M_command)))
     MERROR (MERROR_IM, -1);
   pl = mplist_get (plist, command);
   if (pl)
@@ -3400,7 +3631,8 @@ minput_assign_command_keys (MSymbol language, MSymbol name,
        MERROR (MERROR_IM, -1);
       if (! keyseq)
        return 0;
-      pl = get_command_list (Mnil, Mnil); /* Get global commands.  */
+      /* Get global commands.  */
+      pl = get_nested_list (Mnil, Mnil, Mnil, M_command);
       pl = mplist_get (pl, command);
       if (! pl)
        MERROR (MERROR_IM, -1);
@@ -3424,10 +3656,10 @@ minput_assign_command_keys (MSymbol language, MSymbol name,
     plist of the form VAR-INFO (described below) that carries the
     information about the variable.
 
-    The first element of VAR-INFO has the key #Mtext, and the value is
-    an M-text describing the variable briefly.  This M-text may have a
-    text property #Mdetail_text whose value is an M-text describing
-    the variable in more detail.
+    The first element of VAR-INFO has the key #Mtext or #Msymbol.  If
+    the key is #Mtext, the value is an M-text describing the variable.
+    If the key is #Msymbol, that value is #Mnil which means the
+    variable has no description text.
 
     The second element of VAR-INFO is for the value of the variable.
     The key is #Minteger, #Msymbol, or #Mtext, and the value is an
@@ -3452,20 +3684,20 @@ minput_assign_command_keys (MSymbol language, MSymbol name,
 
     For instance, suppose an input method has the variables:
 
-    @li name:intvar, description: "value is an integer",
+    @li name:intvar, description:"value is an integer",
          initial value:0, value-range:0..3,10,20
 
-    @li name:symvar, description: "value is a symbol",
+    @li name:symvar, description:"value is a symbol",
          initial value:nil, value-range:a, b, c, nil
 
-    @li name:txtvar, description: "value is an M-text",
+    @li name:txtvar, description:"value is an M-text",
          initial value:empty text, no value-range (i.e. any text)
 
     Then, the returned plist has this form ('X:Y' means X is a key and Y is
     a value, and '(...)' means a plist):
 
 @verbatim
-    plist:(intvar:(mtext:'value is an integer'
+    plist:(intvar:(mtext:"value is an integer"
                    integer:0
                   plist:(integer:0 integer:3)
                    integer:10
@@ -3494,10 +3726,9 @@ minput_assign_command_keys (MSymbol language, MSymbol name,
     ³ÆÍ×ÁǤÎÃͤϲ¼µ­¤Î VAR-INFO 
     ¤Î·Á¼°¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ç¤¢¤ê¡¢³ÆÊÑ¿ô¤Ë´Ø¤¹¤ë¾ðÊó¤ò¼¨¤·¤Æ¤¤¤ë¡£
 
-    VAR-INFO ¤ÎÂè°ìÍ×ÁǤϥ­¡¼¤È¤·¤Æ #Mtext ¤ò¡¢ÃͤȤ·¤Æ¤½¤ÎÊÑ¿ô¤ò´Êñ¤ËÀâÌÀ¤¹¤ë
-    M-text ¤ò»ý¤Ä¡£¤³¤Î M-text ¤Ï¡¢#Mdetail_text 
-    ¤ò¥­¡¼¤È¤¹¤ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¡¢¤½¤ÎÃͤϤ½¤ÎÊÑ¿ô¤ò¤è¤ê¾ÜºÙ¤ËÀâÌÀ¤¹¤ë
-    M-text ¤Ç¤¢¤ë¡£
+    VAR-INFO ¤ÎÂè°ìÍ×ÁǤΥ­¡¼¤Ï #Mtext ¤Þ¤¿¤Ï #Msymbol ¤Ç¤¢¤ë¡£¥­¡¼¤¬
+    #Mtext ¤Ê¤é¡¢ÃͤϤ½¤ÎÊÑ¿ô¤òÀâÌÀ¤¹¤ë M-text ¤Ç¤¢¤ë¡£¥­¡¼¤¬ #Msymbol
+    ¤Ê¤éÃͤϠ#Mnil ¤Ç¤¢¤ê¡¢¤³¤ÎÊÑ¿ô¤ÏÀâÌÀ¥Æ¥­¥¹¥È¤ò»ý¤¿¤Ê¤¤¤³¤È¤Ë¤Ê¤ë¡£
 
     VAR-INFO ¤ÎÂèÆóÍ×ÁǤÏÊÑ¿ô¤ÎÃͤò¼¨¤¹¡£¥­¡¼¤Ï #Minteger, #Msymbol,
     #Mtext ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ê¡¢ÃͤϤ½¤ì¤¾¤ìÀ°¿ôÃÍ¡¢¥·¥ó¥Ü¥ë¡¢M-text  ¤Ç¤¢¤ë¡£
@@ -3552,9 +3783,9 @@ minput_assign_command_keys (MSymbol language, MSymbol name,
 MPlist *
 minput_get_variables (MSymbol language, MSymbol name)
 {
-  MPlist *plist = get_variable_list (language, name);
+  MPlist *plist = get_nested_list (language, name, Mnil, M_variable);
 
-  return (! plist || MPLIST_TAIL_P (plist) ? NULL : plist);
+  return (MPLIST_TAIL_P (plist) ? NULL : plist);
 }
 
 /***en
@@ -3595,7 +3826,7 @@ minput_set_variable (MSymbol language, MSymbol name,
 
   if (language == Mnil || name == Mnil)
     MERROR (MERROR_IM, -1);
-  plist = get_variable_list (language, name);
+  plist = get_nested_list (language, name, Mnil, M_variable);
   if (! plist)
     MERROR (MERROR_IM, -1);
   plist = (MPlist *) mplist_get (plist, variable);