private static MSymbol Mmap_list = "map-list";
     private static MSymbol Mstate = "state";
     internal static MSymbol Mcandidates = "candidates";
+    private static MSymbol Mat_minus_zero = "@-0";
 
     private static Xex.Symbol Qmap = "map";
     private static Xex.Symbol Qrule = "rule";
     private static Xex.Symbol Qinsert = "insert";
     private static Xex.Symbol Qinsert_candidates = "insert-candidates";
     private static Xex.Symbol Qchar_at = "char-at";
-    private static Xex.Symbol Qat_minus_zero = "@-0";
     private static Xex.Symbol Qselect = "select";
     private static Xex.Symbol Qdelete = "delete";
     private static Xex.Symbol Qshift = "shift";
 
     internal abstract class Marker : Xex.TermValue
     {
-      private Xex.Symbol name;
+      private MSymbol name;
 
-      private Marker (Xex.Symbol name)
+      private Marker (MSymbol name)
        {
          this.name = name;
        }
 
       public abstract int Position (Context ic);
+
       public virtual void Mark (Context ic)
        {
          throw new Exception ("Can't set predefined marker: " + name);
        {
          return ic.preedit[Position (ic)];
        }
-      public override Xex.TermValue Clone () { return this; }
+
+      public override string ToString () { return name.Name; }
 
       public static Xex.TermValue parser (Xex.Domain domain, XmlNode node)
       {
-       return Get ((Xex.Symbol) node.InnerText);
+       return Get ((MSymbol) node.InnerText);
       }
 
       public class Named : Marker
       {
-       public Named (Xex.Symbol name) : base (name) { }
+       public Named (MSymbol name) : base (name) { }
 
        public override int Position (Context ic)
        {
-         int pos;
-
-         if (ic.marker_positions.TryGetValue (this, out pos))
-           return pos;
-         return 0;
+         MPlist p =  ic.marker_positions.Find (name);
+         return (p == null ? 0 : p.Integer);
        }
 
        public override void Mark (Context ic)
        {
-         ic.marker_positions[this] = ic.cursor_pos;
+         ic.marker_positions.Put (name, ic.cursor_pos);
        }
       }
      
       public class Predefined : Marker
       {
        char tag;
-       public Predefined (Xex.Symbol name) : base (name)
+
+       public Predefined (MSymbol name) : base (name)
          {
            tag = ((string) name)[1];
          }
       {
        private int pos;
 
-       public PredefinedAbsolute (Xex.Symbol name) : base (name)
+       public PredefinedAbsolute (MSymbol name) : base (name)
          {
            if (! int.TryParse (((string) name).Substring (1), out pos))
              throw new Exception ("Invalid marker name: " + name);
       {
        private int distance;
 
-       public PredefinedSurround (Xex.Symbol name) : base (name)
+       public PredefinedSurround (MSymbol name) : base (name)
          {
            if (! int.TryParse (((string) name).Substring (2), out distance))
              throw new Exception ("Invalid marker name: " + name);
          }
       }
 
-      static internal Dictionary<Xex.Symbol,Predefined> predefined_markers;
+      static internal Dictionary<MSymbol,Predefined> predefined_markers;
 
       static Marker ()
       {
-       predefined_markers = new Dictionary<Xex.Symbol, Predefined> ();
-       Xex.Symbol[] symlist
-         = new Xex.Symbol[] {"@<", "@>", "@-", "@+", "@[", "@]" };
-       foreach (Xex.Symbol s in symlist)
+       predefined_markers = new Dictionary<MSymbol, Predefined> ();
+       MSymbol[] symlist = new MSymbol[] {"@<", "@>", "@-", "@+", "@[", "@]" };
+       foreach (MSymbol s in symlist)
          predefined_markers[s] = new Predefined (s);
       }
 
-      public static Marker Get (Xex.Symbol name)
+      public static Marker Get (MSymbol name)
       {
-       string str = name;
+       string str = name.Name;
        if (str[0] == '@')
          {
            Predefined pred;
              throw new Exception ("Invalid marker name: " + name);
            if (Char.IsDigit (str[1]))
              return new PredefinedAbsolute (name);
-           if (str.Length == 2 || name == Qat_minus_zero
+           if (str.Length == 2 || name == Mat_minus_zero
                || ! (str[1] == '-' || str[1] == '+'))
              throw new Exception ("Invalid marker name: " + name);
            return new PredefinedSurround (name);
        return selector;
       }
 
-      public override Xex.TermValue Clone () { return this; }
-
       public void Select (Candidates candidates)
       {
        switch (tag)
       if (plist.IsInteger && func != Qmark)
        args[0] = new Xex.Term (plist.Integer);
       else if (plist.IsSymbol)
-       args[0] = new Xex.Term (Marker.Get ((Xex.Symbol) plist.Symbol.Name));
+       args[0] = new Xex.Term (Marker.Get (plist.Symbol));
       else
        throw new Exception ("Invalid arg to " + func + ": " + plist);
       return new Xex.Term (domain, func, args);
     }
 
-    private Xex.Term parse_char_at (Xex.Symbol name)
+    private Xex.Term parse_char_at (MSymbol name)
     {
       Xex.Term[] args = new Xex.Term[1];
       args[0] = new Xex.Term (Marker.Get (name));
            return parse_insert (plist);
          if (! p.IsSymbol)
            throw new Exception ("Invalid action: " + p);
-         Xex.Symbol name = p.Symbol.Name;
+         MSymbol sym = p.Symbol;
+         Xex.Symbol name = sym.Name;
          p = p.next;
          if (name == Qcond)
            return parse_cond (p);
          if (name == Qshift)
            return parse_shift (p);
          if (((string) name)[0] == '@')
-           return parse_char_at (name);
+           return parse_char_at (sym);
          if (name == Qset || name == Qadd || name == Qsub
                   || name == Qmul || name == Qdiv)
            {
       Candidates can = ((Context) domain.context).candidates;
 
       if (can != null)
-       ((Selector) args[0].Objval).Select (can);
+       {
+         if (args[0].IsInt)
+           can.Select (args[0].Intval);
+         else
+           ((Selector) args[0].Objval).Select (can);
+       }
       return args[0];
     }
 
       private MText produced = new MText ();
       internal MText preedit = new MText ();
       internal int cursor_pos;
-      internal Dictionary<Marker, int> marker_positions
-       = new Dictionary<Marker, int> ();
+      internal MPlist marker_positions = new MPlist ();
 
       internal Candidates candidates;
       private int candidate_from, candidate_to;
       // Index into KEYS specifying the next key to handle.
       internal int key_head;
 
-      private int commit_key_head;
       internal MText preceding_text = new MText ();
       internal MText following_text = new MText ();
 
 
       internal ChangedStatus changed;
 
+      private void set_cursor (string prefix, int pos)
+      {
+       cursor_pos = pos;
+      }
+
       internal void reset ()
       {
        status = im.initial_state.title;
        produced.Del ();
        preedit.Del ();
 
-       cursor_pos = 0;
+       set_cursor ("reset", 0);
        marker_positions.Clear ();
        candidates = null;
        candidate_show = false;
 
        keymap = im.initial_state.keymap;
        keys.keyseq.Clear ();
-       key_head = commit_key_head = 0;
 
        preceding_text.Del ();
        following_text.Del ();
                   : ((MText) inserted).Length);
        int diff = ins - (to - from);
 
-       foreach (Marker m in marker_positions.Keys)
+       for (MPlist p = marker_positions; ! p.IsEmpty; p = p.next)
          {
-           int pos = marker_positions[m];
+           int pos = p.Integer;
            if (pos > from)
-             {
-               if (pos >= to)
-                 marker_positions[m] = pos + diff;
-               else
-                 marker_positions[m] = from;
-             }
+             p.Set (p.Key, pos >= to ? pos + diff : from);
          }
        if (cursor_pos >= to)
-         cursor_pos += diff;
+         set_cursor ("adjust", cursor_pos + diff);
        else if (cursor_pos > from)
-         cursor_pos = from;
+         set_cursor ("adjust", from);
       }
 
       private void preedit_replace (int from, int to, int c)
          }
        preedit.PushProp (candidate_from, candidate_to,
                          Mcandidates, this);
-       cursor_pos = candidate_from;
+       set_cursor ("update-candidate", candidate_to);
        changed |= (ChangedStatus.Preedit | ChangedStatus.CursorPos
                    | CandidateAll);
       }
          pos = preedit.Length;
        if (pos != cursor_pos)
          {
-           cursor_pos = pos;
+           set_cursor ("move", pos);
            changed |= ChangedStatus.Preedit;
          }
       }
       internal void commit ()
       {
        produced.Cat (preedit);
-       preedit.Del ();
+       preedit_replace (0, preedit.Length, null);
        changed |= ChangedStatus.Preedit;
       }
 
        if (this.state.title != state.title)
          this.changed |= ChangedStatus.StateTitle;
        this.state = state;
+       keymap = state.keymap;
       }
 
       public Context (MInputMethod im)
        domain.RestoreValues (state_var_values);
        preedit.Del ();
        preedit.Ins (0, state_preedit);
-       key_head = state_key_head;
-       cursor_pos = state_pos;
+       set_cursor ("restore", state_pos);
       }
 
       private bool handle_key ()
       {
-       State current_state = state;
+       Console.Write ("\nHandle ({0}[{1}]) in {2}",
+                      keys, key_head, state.name);
+
        Keymap sub = keymap.Lookup (keys, ref key_head);
 
        if (sub != keymap)
          {
+           restore_state ();
            keymap = sub;
            if (keymap.map_actions != null)
              {
-               restore_state ();
                if (! take_actions (keymap.map_actions))
                  return false;
              }
          }
        else
          {
+           State current_state = state;
+
            if (keymap.branch_actions != null)
              {
                if (! take_actions (keymap.branch_actions))
        return key_unhandled;
       }
 
-      public bool Produced (out MText mt)
-      {
-       mt = produced;
-       return (produced.Length > 0);
-      }
+      public MText Preedit { get { return preedit; } }
+      public MText Produced { get { return produced; } }
 
       // Return value:
       //   true: All keys are handled and there's no text to commit.
                key_unhandled = true;
                break;
              }
-           if (++count == 100)
+           if (++count == 10)
              break;
          }
        keys.keyseq.RemoveRange (0, key_head);
+       key_head = 0;
 
        if ((changed & ChangedStatus.Preedit) != ChangedStatus.None
            && PreeditChanged != null)
            CandidateChanged (this, callback_arg);
          }
 
+       Console.Write ("\nPreedit(\"{0}\"/{1}), Produced({2})",
+                      preedit, cursor_pos, produced);
+
        return (! key_unhandled && produced.Length == 0);
       }
     }
 
 
        public override Term Call (Domain domain, Variable vari, Term[] args)
        {
-         args = (Term[]) args.Clone ();
-         for (int i = 0; i < args.Length; i++)
+         if (args != null)
            {
-             args[i] = args[i].Eval (domain);
-             if (domain.Thrown)
-               return args[i];
+             args = (Term[]) args.Clone ();
+             for (int i = 0; i < args.Length; i++)
+               {
+                 args[i] = args[i].Eval (domain);
+                 if (domain.Thrown)
+                   return args[i];
+               }
            }
          return builtin (domain, vari, args);
        }
              }
          }
 
-       public Lambda (Domain domain, Symbol name, bool args_evalled, Symbol[] args)
+       public Lambda (Domain domain, Symbol name,
+                      bool args_evalled, Symbol[] args)
          {
            int nfixed = 0;
            int noptional = 0;
     public abstract class TermValue
     {
       public virtual Term Eval (Domain domain) { return new Term (this); }
-      public abstract TermValue Clone ();
+      public virtual TermValue Clone () { return this; }
     }
 
     private class Funcall : TermValue
 
       public override Term Eval (Domain domain)
       {
-       domain.DebugWrite (true, "(({0}", func.name);
-       for (int i = 0; i < args.Length; i++)
-         domain.DebugWrite (false, " {0}", args[i].ToString ());
-       domain.DebugWrite (false, ")");
+       domain.DebugWrite (true, ToString ());
        domain.depth++;
        Term result = func.Call (domain, vari, args);
        domain.depth--;
       {
        string str = "<" + func.name;
        if (vari != null)
-         str += " \"vname=" + vari.name + "\"";
+         str += " vname=\"" + vari.name + "\"";
        if (args == null)
          return str + "/>";
        str += ">";
-       foreach (Term e in args)
-         str += e;
+       if (func is Function.SpecialForm)
+         str += "...";
+       else
+         foreach (Term e in args)
+           str += e;
        return (str + "</" + func.name + ">");
       }
     }