*** empty log message ***
authorhanda <handa>
Fri, 2 Oct 2009 00:13:13 +0000 (00:13 +0000)
committerhanda <handa>
Fri, 2 Oct 2009 00:13:13 +0000 (00:13 +0000)
MInputMethod.cs
input.txt

index 1a79af3..ecee0a1 100644 (file)
@@ -9,15 +9,14 @@ using M17N;
 using M17N.Core;
 using M17N.Input;
 
+using Xex = System.Xml.Expression.Xexpression;
+
 namespace M17N.Input
 {
-  using Xex = System.Xml.Expression.Xexpression;
-  using Mim = MInputMethod;
-
   public class MInputMethod
   {
     // Delegaes
-    public delegate bool Callback (MInputContext ic, MPlist args);
+    public delegate bool Callback (Context ic, MPlist args);
 
     // Class members
     public static Callback PreeditStart, PreeditDone, PreeditDraw;
@@ -55,7 +54,7 @@ namespace M17N.Input
     private static MSymbol Mif = "if";
     private static MSymbol Mcond = "cond";
     private static MSymbol Mchar_at = "char-at";
-    private static MSymbol Msurrounding_text_p = "surrounding-text-p";
+    private static MSymbol Msurrounding_flag = "surrounding-text-flag";
     private static MSymbol Mpushback = "pushback"; 
     private static MSymbol Mkeyseq = "keyseq"; 
 
@@ -336,34 +335,6 @@ namespace M17N.Input
          keyseq.Add (new Key ((uint) mt[i]));
       }
 
-      private static uint parse_integer (string str)
-      {
-       if (Char.IsDigit (str[0]))
-         {
-           if (str[0] == '0' && str.Length > 2 && str[1] == 'x')
-             {
-               uint i = 0;
-               for (int idx = 2; idx < str.Length; idx++)
-                 {
-                   uint c = str[idx];
-                   if (c >= '0' && c <= '9')
-                     i = i * 16 + (c - '0');
-                   else if (c >= 'A' && c <= 'F')
-                     i = i * 16 + 10 + (c - 'A');
-                   else if (c >= 'a' && c <= 'f')
-                     i = i * 16 + 10 + (c - 'a');
-                   else
-                     break;
-                 }
-               return i;
-             }
-           return UInt32.Parse (str);
-         }
-       else if (str[0] == '?')
-         return str[1];
-       return 0;
-      }
-
       public KeySeq (List<Xex.Term> list)
        {
          int len = list.Count;
@@ -407,98 +378,6 @@ namespace M17N.Input
       }
     }
 
-    public class Variable
-    {
-      public MSymbol name;
-      public MText description;
-      public Type type;
-      public object value;
-      public object[] candidates;
-
-      public Variable (MPlist p)
-      {
-       name = p.Symbol;
-       p = p.Next;
-       description = parse_description (p);
-       if (description == null)
-         description = new MText ("No description");
-       else
-         p = p.next;
-       type = (p.IsMText ? typeof (MText)
-               : p.IsInteger ? typeof (int)
-               : p.IsSymbol ? typeof (MSymbol)
-               : typeof (object));
-       value = p.val;
-       p = p.next;
-       candidates = new object[p.Count];
-       for (int i = 0; ! p.IsEmpty; i++, p = p.next)
-         candidates[i] = p.val;
-      }
-
-      private static Type parse_value (XmlNode node, out object value)
-      {
-       string typename = node.Attributes["type"].Value;
-       Type type;
-
-       if (typename == "integer")
-         {
-           int i;
-           if (! Int32.TryParse (node.InnerText, out i))
-             i = 0;
-           value = i;
-           type = typeof (int);
-         }
-       else if (typename == "string")
-         {
-           MText mt = node.InnerText;
-           value = mt;
-           type = typeof (MText);
-         }
-       else if (typename == "symbol")
-         {
-           MSymbol sym = node.InnerText;
-           value = sym;
-           type = typeof (MSymbol);
-         }
-       else
-         {
-           value = null;
-           type = typeof (object);
-         }
-       return type;
-      }
-
-      public Variable (XmlNode node)
-      {
-       name = node.Attributes["id"].Value;
-       for (node = node.FirstChild; node != null; node = node.NextSibling)
-         if (node.NodeType == XmlNodeType.Element)
-           {
-             if (node.Name == "description")
-               description = parse_description (node);
-             else if (node.Name == "value")
-               type = parse_value (node, out value);
-             else if (node.Name == "valiable-value-candidate")
-               {
-                 XmlNodeList n_list = node.ChildNodes;
-                 candidates = new object[n_list.Count];
-                 for (int i = 0; i < n_list.Count; i++)
-                   {
-                     object val;
-                     parse_value (n_list[i], out val);
-                     candidates[i] = val;
-                   }
-               }
-           }
-      }
-
-      public override string ToString ()
-      {
-       return ("(" + name + " \"" + (string) description
-               + "\" " + type + " " + value + " " + candidates + ")");
-      }
-    }
-
     public class Command
     {
       public MSymbol name;
@@ -615,14 +494,14 @@ namespace M17N.Input
          this.name = name;
        }
 
-      public abstract int Position (MInputContext ic);
-      public abstract void Mark (MInputContext ic);
+      public abstract int Position (Context ic);
+      public abstract void Mark (Context ic);
 
       public static Xex.TermValue parser (Xex.Domain domain, XmlNode node)
       {
        MSymbol name = node.InnerText;
        
-       return Get ((MInputContext) domain.context, name);
+       return Get ((Context) domain.context, name);
       }
 
       public class Named : Marker
@@ -633,9 +512,9 @@ namespace M17N.Input
 
        private Named (MSymbol name, int p) : base (name) { pos = p; }
 
-       public override int Position (MInputContext ic) { return pos; }
+       public override int Position (Context ic) { return pos; }
 
-       public override void Mark (MInputContext ic) { pos = ic.cursor_pos; } 
+       public override void Mark (Context ic) { pos = ic.cursor_pos; } 
 
        public override Xex.TermValue Clone ()
        {
@@ -647,7 +526,7 @@ namespace M17N.Input
       {
        public Predefined (MSymbol name) : base (name) { }
        
-       public override int Position (MInputContext ic)
+       public override int Position (Context ic)
        {
          switch (name.Name[1]) {
          case '<': return 0;
@@ -677,7 +556,7 @@ namespace M17N.Input
          }
        }
       
-       public override void Mark (MInputContext ic)
+       public override void Mark (Context ic)
        {
          throw new Exception ("Can't set predefined marker: " + name);
        }
@@ -700,7 +579,7 @@ namespace M17N.Input
          predefined_markers[s] = new Predefined (s);
       }
 
-      public static Marker Get (MInputContext ic, MSymbol name)
+      public static Marker Get (Context ic, MSymbol name)
       {
        Predefined pred;
        Marker m;
@@ -832,7 +711,7 @@ namespace M17N.Input
          group = new object[column];
       }
 
-      public static void Detach (MInputContext ic)
+      public static void Detach (Context ic)
       {
        ic.preedit.PopProp (0, ic.preedit.Length, Mcandidates);
        ic.candidates = null;
@@ -1011,7 +890,7 @@ namespace M17N.Input
 
        internal Predefined (MSymbol sym) { this.tag = sym.Name[1]; }
 
-       public override void Select (Candidates can)
+       public override void Select (Candidates candidates)
        {
          switch (tag)
            {
@@ -1146,22 +1025,25 @@ namespace M17N.Input
       im_domain.DefTerm ("marker", Marker.parser);
       im_domain.DefTerm ("selector", Selector.parser);
 
-      im_domain.DefSubr (Finsert, "insert", true, 1, 1);
-      im_domain.DefSubr (Finsert_candidates, "candidates", true, 1, -1);
-      im_domain.DefSubr (Fdelete, "delete", true, 1, 1);
-      im_domain.DefSubr (Fselect, "select", true, 1, 1);
-      im_domain.DefSubr (Fshow, "show", true, 0, 0);
-      im_domain.DefSubr (Fhide, "hide", true, 0, 0);
-      im_domain.DefSubr (Fmove, "move", true, 1, 1);
-      im_domain.DefSubr (Fmark, "mark", true, 1, 1);
-      im_domain.DefSubr (Fpushback, "pushback", true, 1, 1);
-      im_domain.DefSubr (Fpop, "pop", true, 0, 0);
-      im_domain.DefSubr (Fundo, "undo", true, 0, 1);
-      im_domain.DefSubr (Fcommit, "commit", true, 0, 0);
-      im_domain.DefSubr (Funhandle, "unhandle", true, 0, 0);
-      im_domain.DefSubr (Fshift, "shift", true, 1, 1);
-      im_domain.DefSubr (Fmarker, "marker", true, 1, 1);
-      im_domain.DefSubr (Fchar_at, "char-at", true, 1, 1);
+      im_domain.DefSubr (Finsert, "insert", false, 1, 1);
+      im_domain.DefSubr (Finsert_candidates, "candidates", false, 1, -1);
+      im_domain.DefSubr (Fdelete, "delete", false, 1, 1);
+      im_domain.DefSubr (Fselect, "select", false, 1, 1);
+      im_domain.DefSubr (Fshow, "show", false, 0, 0);
+      im_domain.DefSubr (Fhide, "hide", false, 0, 0);
+      im_domain.DefSubr (Fmove, "move", false, 1, 1);
+      im_domain.DefSubr (Fmark, "mark", false, 1, 1);
+      im_domain.DefSubr (Fpushback, "pushback", false, 1, 1);
+      im_domain.DefSubr (Fpop, "pop", false, 0, 0);
+      im_domain.DefSubr (Fundo, "undo", false, 0, 1);
+      im_domain.DefSubr (Fcommit, "commit", false, 0, 0);
+      im_domain.DefSubr (Funhandle, "unhandle", false, 0, 0);
+      im_domain.DefSubr (Fshift, "shift", false, 1, 1);
+      im_domain.DefSubr (Fshift_back, "shiftback", false, 0, 0);
+      im_domain.DefSubr (Fchar_at, "char-at", false, 1, 1);
+      im_domain.DefSubr (Fkey_count, "key-count", false, 1, 1);
+      im_domain.DefSubr (Fsurrounding_flag, "surrounding-text-flag",
+                        false, 0, 0);
 
       MDatabase.Tag tag = new MDatabase.Tag (Minput_method, "*", "*", "*");
       List<MDatabase> list = MDatabase.List (tag);
@@ -1504,7 +1386,7 @@ namespace M17N.Input
 
                  if (pos == 0)
                    {
-                     p.Add (MSymbol.symbol, Msurrounding_text_p);
+                     p.Add (MSymbol.symbol, Msurrounding_flag);
                    }
                  else
                    {
@@ -1999,7 +1881,7 @@ namespace M17N.Input
     private static Xex.Term Finsert (Xex.Domain domain, Xex.Variable vari,
                                     Xex.Term[] args)
     {
-      ((MInputContext) domain.context).insert (args[0]);
+      ((Context) domain.context).insert (args[0]);
       return args[0];
     }
 
@@ -2007,35 +1889,30 @@ namespace M17N.Input
                                                Xex.Variable vari,
                                                Xex.Term[] args)
     {
-      ((MInputContext) domain.context).insert_candidates (args[0]);
+      ((Context) domain.context).insert_candidates (args[0]);
       return args[0];
     }
 
-    private static Xex.Term Fmarker (Xex.Domain domain, Xex.Variable vari,
-                                    Xex.Term[] args)
-    {
-      MSymbol name = (string) args[0].Symval;
-      return new Xex.Term (Marker.Get ((MInputContext) domain.context, name));
-    }
-
     private static Xex.Term Fchar_at (Xex.Domain domain, Xex.Variable vari,
                                      Xex.Term[] args)
     {
-      int c = ((MInputContext) domain.context).char_at (args[0].Intval);
-      return new Xex.Term (c);
+      Context ic = (Context) domain.context;
+      Marker m = (Marker) args[0].Objval;
+
+      return new Xex.Term (ic.char_at (m.Position (ic)));
     }
 
     private static Xex.Term Fdelete (Xex.Domain domain, Xex.Variable vari,
                                   Xex.Term[] args)
     {
-      ((MInputContext) domain.context).delete ((int) args[0].Intval);
+      ((Context) domain.context).delete ((int) args[0].Intval);
       return args[0];
     }
 
     private static Xex.Term Fselect (Xex.Domain domain, Xex.Variable vari,
                                     Xex.Term[] args)
     {
-      Candidates can = ((MInputContext) domain.context).candidates;
+      Candidates can = ((Context) domain.context).candidates;
 
       if (can != null)
        ((Selector) args[0].Objval).Select (can);
@@ -2045,14 +1922,14 @@ namespace M17N.Input
     private static Xex.Term Fshow (Xex.Domain domain, Xex.Variable vari,
                                 Xex.Term[] args)
     {
-      ((MInputContext) domain.context).show ();
+      ((Context) domain.context).show ();
       return Tnil;
     }
 
     private static Xex.Term Fhide (Xex.Domain domain, Xex.Variable vari,
                                 Xex.Term[] args)
     {
-      ((MInputContext) domain.context).hide ();
+      ((Context) domain.context).hide ();
       return Tnil;
     }
 
@@ -2060,12 +1937,12 @@ namespace M17N.Input
                                 Xex.Term[] args)
     {
       if (args[0].IsInt)
-       ((MInputContext) domain.context).move (args[0].Intval);
+       ((Context) domain.context).move (args[0].Intval);
       else
        {
          Marker m = (Marker) args[0].Objval;
-         MInputContext ic = (MInputContext) domain.context;
-         ((MInputContext) domain.context).move (m.Position (ic));
+         Context ic = (Context) domain.context;
+         ((Context) domain.context).move (m.Position (ic));
        }
       return args[0];
     }
@@ -2074,14 +1951,14 @@ namespace M17N.Input
                                   Xex.Term[] args)
     {
       Marker m = (Marker) args[0].Objval;
-      m.Mark ((MInputContext) domain.context);
+      m.Mark ((Context) domain.context);
       return args[0];
     }
 
     private static Xex.Term Fpushback (Xex.Domain domain, Xex.Variable vari,
                                       Xex.Term[] args)
     {
-      MInputContext ic = (MInputContext) domain.context;
+      Context ic = (Context) domain.context;
 
       if (args[0].IsInt)
        ic.pushback (args[0].Intval);
@@ -2095,7 +1972,7 @@ namespace M17N.Input
     private static Xex.Term Fpop (Xex.Domain domain, Xex.Variable vari,
                                  Xex.Term[] args)
     {
-      ((MInputContext) domain.context).pop ();
+      ((Context) domain.context).pop ();
       return Tnil;
     }
 
@@ -2103,21 +1980,21 @@ namespace M17N.Input
                                   Xex.Term[] args)
     {
       int n = args.Length == 0 ? -2 : args[0].Intval;
-      ((MInputContext) domain.context).undo (n);
+      ((Context) domain.context).undo (n);
       return Tnil;
     }
 
     private static Xex.Term Fcommit (Xex.Domain domain, Xex.Variable vari,
                                     Xex.Term[] args)
     {
-      ((MInputContext) domain.context).commit ();
+      ((Context) domain.context).commit ();
       return Tnil;
     }
 
     private static Xex.Term Funhandle (Xex.Domain domain, Xex.Variable vari,
                                       Xex.Term[] args)
     {
-      ((MInputContext) domain.context).commit ();
+      ((Context) domain.context).commit ();
       args = new Xex.Term[2];
       args[0] = args[1] = Tcatch_tag;
       return Xex.Fthrow (domain, vari, args);
@@ -2126,10 +2003,30 @@ namespace M17N.Input
     private static Xex.Term Fshift (Xex.Domain domain, Xex.Variable vari,
                                    Xex.Term[] args)
     {
-      ((MInputContext) domain.context).shift (args[0].Symval);
+      ((Context) domain.context).shift (args[0].Symval);
       return args[0];
     }
 
+    private static Xex.Term Fshift_back (Xex.Domain domain, Xex.Variable vari,
+                                        Xex.Term[] args)
+    {
+      ((Context) domain.context).shift_back ();
+      return Tnil;
+    }
+
+    private static Xex.Term Fkey_count (Xex.Domain domain, Xex.Variable vari,
+                                       Xex.Term[] args)
+    {
+      return new Xex.Term (((Context) domain.context).key_head);
+    }
+
+    private static Xex.Term Fsurrounding_flag (Xex.Domain domain,
+                                              Xex.Variable vari,
+                                              Xex.Term[] args)
+    {
+      return new Xex.Term (((Context) domain.context).surrounding_flag);
+    }
+
     public override string ToString ()
     {
       string str = (String.Format ("({0} (title \"{1}\")", tag, title));
@@ -2162,412 +2059,404 @@ namespace M17N.Input
        str += " " + p.val;
       return str + "))";
     }
-  }
 
-  public class MInputContext
-  {
-    internal static Xex.Symbol Ncandidates_group_size = "candidates-group-size";
-    private static MSymbol Mat_less_than = "@<";
-    private static MSymbol Mat_greater_than = "@>";
-    private static MSymbol Mat_minus = "@-";
-    private static MSymbol Mat_plus = "@+";
-    private static MSymbol Mat_open_square_bracket = "@[";
-    private static MSymbol Mat_close_square_bracket = "@]";
-
-    public MInputMethod im;
-    private MText produced;
-    private bool active;
-    private MText status;
-    internal MText preedit;
-    internal int cursor_pos;
-    internal Mim.Candidates candidates;
-    private MPlist candidate_group;
-    private int candidate_index;
-    private int candidate_from, candidate_to;
-    private bool candidate_show;
-
-    private Stack<Mim.State> states;
-    internal Mim.KeySeq keys;
-    private int key_head;
-    private int state_key_head;
-    private object state_var_values;
-    private int commit_key_head;
-    private MText state_preedit;
-    private int state_pos;
-    internal MPlist markers = new MPlist ();
-    internal MText preceding_text = new MText ();
-    internal MText following_text = new MText ();
-    private bool key_unhandled;
-
-    internal Xex.Domain domain;
-
-    internal Mim.ChangedStatus changed;
-
-    public Mim.ChangedStatus Changed { get { return changed; } }
-
-    public MInputContext (MInputMethod im)
-    {
-      this.im = im;
-      domain = new Xex.Domain (im.domain, this);
-      states = new Stack<Mim.State> ();
-      states.Push ((Mim.State) im.states.val);
-      keys = new Mim.KeySeq ();
-    }
-
-    private void adjust_markers (int from, int to, object inserted)
-    {
-      int ins = (inserted == null ? 0
-                : inserted is int ? 1
-                : ((MText) inserted).Length);
-      int diff = ins - (to - from);
-
-      for (MPlist plist = markers; ! plist.IsEmpty; plist = plist.next)
-       {
-         int pos = plist.Integer;
-         if (pos > from)
-           {
-             if (pos >= to)
-               plist.val = pos + diff;
-             else
-               plist.val = from;
-           }
-       }
-      if (cursor_pos >= to)
-       cursor_pos += diff;
-      else if (cursor_pos > from)
-       cursor_pos = from;
-    }
+    public class Context
+    {
+      internal static Xex.Symbol Ncandidates_group_size
+        = "candidates-group-size";
+      public MInputMethod im;
+      private MText produced;
+      private bool active;
+      private MText status;
+      internal MText preedit;
+      internal int cursor_pos;
+      internal Candidates candidates;
+      private int candidate_from, candidate_to;
+      private bool candidate_show;
+
+      private Stack<State> state_stack;
+      internal KeySeq keys;
+      internal int key_head;
+      private int state_key_head;
+      private object state_var_values;
+      private int commit_key_head;
+      private MText state_preedit;
+      private int state_pos;
+      internal MPlist markers = new MPlist ();
+      internal MText preceding_text = new MText ();
+      internal MText following_text = new MText ();
+      private bool key_unhandled;
+
+      internal Xex.Domain domain;
+
+      internal ChangedStatus changed;
+
+      public ChangedStatus Changed { get { return changed; } }
+
+      public Context (MInputMethod im)
+      {
+       this.im = im;
+       domain = new Xex.Domain (im.domain, this);
+       state_stack = new Stack<State> ();
+       state_stack.Push ((State) im.states.val);
+       keys = new KeySeq ();
+      }
 
-    private void preedit_replace (int from, int to, int c)
-    {
-      preedit.Del (from, to);
-      preedit.Ins (from, c);
-      adjust_markers (from, to, c);
-    }
+      private void adjust_markers (int from, int to, object inserted)
+      {
+       int ins = (inserted == null ? 0
+                  : inserted is int ? 1
+                  : ((MText) inserted).Length);
+       int diff = ins - (to - from);
 
-    private void preedit_replace (int from, int to, MText mt)
-    {
-      preedit[from, to] = mt;
-      adjust_markers (from, to, mt);
-    }
+       for (MPlist plist = markers; ! plist.IsEmpty; plist = plist.next)
+         {
+           int pos = plist.Integer;
+           if (pos > from)
+             {
+               if (pos >= to)
+                 plist.val = pos + diff;
+               else
+                 plist.val = from;
+             }
+         }
+       if (cursor_pos >= to)
+         cursor_pos += diff;
+       else if (cursor_pos > from)
+         cursor_pos = from;
+      }
 
-    internal void insert (Xex.Term arg)
-    {
-      if (arg.IsInt)
-       preedit_replace (cursor_pos, cursor_pos, arg.Intval);
-      else
-       preedit_replace (cursor_pos, cursor_pos, new MText (arg.Strval));
-      changed |= ChangedStatus.Preedit | ChangedStatus.CursorPos;
-    }
+      private void preedit_replace (int from, int to, int c)
+      {
+       preedit.Del (from, to);
+       preedit.Ins (from, c);
+       adjust_markers (from, to, c);
+      }
 
-    private void update_candidate ()
-    {
-      object candidate = candidates.Current;
+      private void preedit_replace (int from, int to, MText mt)
+      {
+       preedit[from, to] = mt;
+       adjust_markers (from, to, mt);
+      }
 
-      if (candidate is MText)
-       {
-         preedit_replace (candidate_from, candidate_to, (MText) candidate);
-         candidate_to = candidate_from + ((MText) candidate).Length;
-       }
-      else
-       {
-         preedit_replace (candidate_from, candidate_to, (int) candidate);
-         candidate_to = candidate_from + 1;
-       }
-      preedit.PushProp (candidate_from, candidate_to,
-                       Mim.Mcandidates, this);
-      cursor_pos = candidate_from;
-      changed |= (ChangedStatus.Preedit | ChangedStatus.CursorPos
-                 | CandidateAll);
-    }
+      internal void insert (Xex.Term arg)
+      {
+       if (arg.IsInt)
+         preedit_replace (cursor_pos, cursor_pos, arg.Intval);
+       else
+         preedit_replace (cursor_pos, cursor_pos, new MText (arg.Strval));
+       changed |= ChangedStatus.Preedit | ChangedStatus.CursorPos;
+      }
 
-    internal void insert_candidates (Xex.Term arg)
-    {
-      int column = 0;
-      Xex.Variable v = domain.GetVar (Ncandidates_group_size, false);
+      private void update_candidate ()
+      {
+       object candidate = candidates.Current;
 
-      if (v != null)
-       column = v.Value.Intval;
-      candidates = new Mim.Candidates (arg.Listval, column);
-      candidate_from = candidate_to = cursor_pos;
-      update_candidate ();
-    }
+       if (candidate is MText)
+         {
+           preedit_replace (candidate_from, candidate_to, (MText) candidate);
+           candidate_to = candidate_from + ((MText) candidate).Length;
+         }
+       else
+         {
+           preedit_replace (candidate_from, candidate_to, (int) candidate);
+           candidate_to = candidate_from + 1;
+         }
+       preedit.PushProp (candidate_from, candidate_to,
+                         Mcandidates, this);
+       cursor_pos = candidate_from;
+       changed |= (ChangedStatus.Preedit | ChangedStatus.CursorPos
+                   | CandidateAll);
+      }
 
-    internal void select (int n)
-    {
-      if (candidates != null)
-       {
-         candidates.Select (n);
-         update_candidate ();
-       }
-    }
+      internal void insert_candidates (Xex.Term arg)
+      {
+       int column = 0;
+       Xex.Variable v = domain.GetVar (Ncandidates_group_size, false);
+
+       if (v != null)
+         column = v.Value.Intval;
+       candidates = new Candidates (arg.Listval, column);
+       candidate_from = candidate_to = cursor_pos;
+       update_candidate ();
+      }
 
-    internal int marker (MSymbol sym)
-    {
-      int pos = cursor_pos;
+      internal void select (int n)
+      {
+       if (candidates != null)
+         {
+           candidates.Select (n);
+           update_candidate ();
+         }
+      }
 
-      if (sym.Name.Length == 2 && sym.Name[0] == '@')
-       {
-         switch (sym.Name[0])
-           {
-           case '<': pos = 0; break;
-           case '>': pos = preedit.Length; break;
-           case '-': pos = cursor_pos - 1; break;
-           case '+': pos = cursor_pos + 1; break;
-           case '[':
-             if (pos > 0)
-               {
-                 int to;
-                 preedit.FindProp (Mim.Mcandidates, pos - 1,
-                                   out pos, out to);
-               }
-             else
-               pos = 0;
-             break;
-           case ']':
-             if (cursor_pos < preedit.Length - 1)
-               {
-                 int from;
-                 preedit.FindProp (Mim.Mcandidates, pos,
-                                   out from, out pos);
-               }
-             else
-               pos = preedit.Length;
-             break;
-           default:
-             if (sym.Name[0] >= '0' && sym.Name[0] <= '9')
-               pos = sym.Name[0];
-             break;
-           }
-       }
-      else if (sym.Name.Length >= 3 && sym.Name[0] == '@')
-       {
-         pos = int.Parse (sym.Name.Substring (2));
-       }
-      else
-       {
-         object val = markers.Get (sym);
+      internal int marker (MSymbol sym)
+      {
+       int pos = cursor_pos;
 
-         if (val is int)
-           pos = (int) val;
-       }
-      return pos;
-    }
+       if (sym.Name.Length == 2 && sym.Name[0] == '@')
+         {
+           switch (sym.Name[0])
+             {
+             case '<': pos = 0; break;
+             case '>': pos = preedit.Length; break;
+             case '-': pos = cursor_pos - 1; break;
+             case '+': pos = cursor_pos + 1; break;
+             case '[':
+               if (pos > 0)
+                 {
+                   int to;
+                   preedit.FindProp (Mcandidates, pos - 1,
+                                     out pos, out to);
+                 }
+               else
+                 pos = 0;
+               break;
+             case ']':
+               if (cursor_pos < preedit.Length - 1)
+                 {
+                   int from;
+                   preedit.FindProp (Mcandidates, pos,
+                                     out from, out pos);
+                 }
+               else
+                 pos = preedit.Length;
+               break;
+             default:
+               if (sym.Name[0] >= '0' && sym.Name[0] <= '9')
+                 pos = sym.Name[0];
+               break;
+             }
+         }
+       else if (sym.Name.Length >= 3 && sym.Name[0] == '@')
+         {
+           pos = int.Parse (sym.Name.Substring (2));
+         }
+       else
+         {
+           object val = markers.Get (sym);
 
-    internal int char_at (int pos)
-    {
-      int c;
+           if (val is int)
+             pos = (int) val;
+         }
+       return pos;
+      }
 
-      pos += cursor_pos;
-      if (pos < 0)
-       {
-         if (preceding_text.Length < -pos)
-           {
-             MPlist plist = new MPlist ();
-             plist.Push (MSymbol.integer, pos);
-             if (Mim.GetSurroundingText != null
-                 && Mim.GetSurroundingText (this, plist)
-                 && plist.IsMText
-                 && preceding_text.Length < plist.Text.Length)
-               preceding_text = plist.Text;
-           }
-         c = (-pos < preceding_text.Length
-              ? preceding_text[preceding_text.Length + pos] : -1);
-       }
-      else if (pos >= 0 && pos < preedit.Length)
-       c = preedit[pos];
-      else
-       {
-         pos -= preedit.Length;
-         if (pos >= following_text.Length)
-           {
-             MPlist plist = new MPlist ();
-             plist.Push (MSymbol.integer, pos + 1);
-             if (Mim.GetSurroundingText != null
-                 && Mim.GetSurroundingText (this, plist)
-                 && plist.IsMText
-                 && following_text.Length < plist.Text.Length)
-               following_text = plist.Text;
-           }
-         c = (pos < following_text.Length ? following_text[pos] : -1);
-       }
-      return c;
-    }
+      internal int char_at (int pos)
+      {
+       int c;
 
-    internal void delete (int pos)
-    {
-      if (pos < cursor_pos)
-       preedit_replace (pos, cursor_pos, null);
-      else
-       preedit_replace (cursor_pos, pos, null);
-      changed |= ChangedStatus.Preedit | ChangedStatus.CursorPos;
-    }
+       pos += cursor_pos;
+       if (pos < 0)
+         {
+           if (preceding_text.Length < -pos)
+             {
+               MPlist plist = new MPlist ();
+               plist.Push (MSymbol.integer, pos);
+               if (GetSurroundingText != null
+                   && GetSurroundingText (this, plist)
+                   && plist.IsMText
+                   && preceding_text.Length < plist.Text.Length)
+                 preceding_text = plist.Text;
+             }
+           c = (-pos < preceding_text.Length
+                ? preceding_text[preceding_text.Length + pos] : -1);
+         }
+       else if (pos >= 0 && pos < preedit.Length)
+         c = preedit[pos];
+       else
+         {
+           pos -= preedit.Length;
+           if (pos >= following_text.Length)
+             {
+               MPlist plist = new MPlist ();
+               plist.Push (MSymbol.integer, pos + 1);
+               if (GetSurroundingText != null
+                   && GetSurroundingText (this, plist)
+                   && plist.IsMText
+                   && following_text.Length < plist.Text.Length)
+                 following_text = plist.Text;
+             }
+           c = (pos < following_text.Length ? following_text[pos] : -1);
+         }
+       return c;
+      }
 
-    internal void show ()
-    {
-      candidate_show = true;
-      changed |= ChangedStatus.CandidateShow;
-    }
+      internal void delete (int pos)
+      {
+       if (pos < cursor_pos)
+         preedit_replace (pos, cursor_pos, null);
+       else
+         preedit_replace (cursor_pos, pos, null);
+       changed |= ChangedStatus.Preedit | ChangedStatus.CursorPos;
+      }
 
-    internal void hide ()
-    {
-      candidate_show = false;
-      changed |= ChangedStatus.CandidateShow;
-    }
+      internal void show ()
+      {
+       candidate_show = true;
+       changed |= ChangedStatus.CandidateShow;
+      }
 
-    internal void move (int pos)
-    {
-      if (pos < 0)
-       pos = 0;
-      else if (pos > preedit.Length)
-       pos = preedit.Length;
-      if (pos != cursor_pos)
-       {
-         cursor_pos = pos;
-         changed |= ChangedStatus.Preedit;
-       }
-    }
+      internal void hide ()
+      {
+       candidate_show = false;
+       changed |= ChangedStatus.CandidateShow;
+      }
 
-    internal void mark (MSymbol sym)
-    {
-      MPlist slot = markers.Find (sym);
+      internal void move (int pos)
+      {
+       if (pos < 0)
+         pos = 0;
+       else if (pos > preedit.Length)
+         pos = preedit.Length;
+       if (pos != cursor_pos)
+         {
+           cursor_pos = pos;
+           changed |= ChangedStatus.Preedit;
+         }
+      }
 
-      if (slot == null)
-       markers.Push (sym, cursor_pos);
-      else
-       slot.val = cursor_pos;
-    }
+      internal void mark (MSymbol sym)
+      {
+       MPlist slot = markers.Find (sym);
 
-    internal void pushback (int n)
-    {
-      if (n > 0)
-       {
-         key_head -= n;
-         if (key_head < 0)
-           key_head = 0;
-       }
-      else if (n == 0)
-       key_head = 0;
-      else
-       {
-         key_head = - n;
-         if (key_head > keys.keyseq.Count)
-           key_head = keys.keyseq.Count;
-       }
-    }
+       if (slot == null)
+         markers.Push (sym, cursor_pos);
+       else
+         slot.val = cursor_pos;
+      }
 
-    internal void pushback (Mim.KeySeq keyseq)
-    {
-      if (key_head > 0)
-       key_head--;
-      if (key_head < keys.keyseq.Count)
-       keys.keyseq.RemoveRange (key_head, keys.keyseq.Count - key_head);
-      for (int i = 0; i < keyseq.keyseq.Count; i++)
-       keys.keyseq.Add (keyseq.keyseq[i]);
-    }
+      internal void pushback (int n)
+      {
+       if (n > 0)
+         {
+           key_head -= n;
+           if (key_head < 0)
+             key_head = 0;
+         }
+       else if (n == 0)
+         key_head = 0;
+       else
+         {
+           key_head = - n;
+           if (key_head > keys.keyseq.Count)
+             key_head = keys.keyseq.Count;
+         }
+      }
 
-    internal void pop ()
-    {
-      if (key_head < keys.keyseq.Count)
-       keys.keyseq.RemoveRange (key_head, 1);
-    }
+      internal void pushback (KeySeq keyseq)
+      {
+       if (key_head > 0)
+         key_head--;
+       if (key_head < keys.keyseq.Count)
+         keys.keyseq.RemoveRange (key_head, keys.keyseq.Count - key_head);
+       for (int i = 0; i < keyseq.keyseq.Count; i++)
+         keys.keyseq.Add (keyseq.keyseq[i]);
+      }
 
-    internal void undo (int n)
-    {
-      if (n < 0)
-       keys.keyseq.RemoveRange (keys.keyseq.Count + n, - n);
-      else
-       keys.keyseq.RemoveRange (n, keys.keyseq.Count  - n);
-      reset ();
-    }
+      internal void pop ()
+      {
+       if (key_head < keys.keyseq.Count)
+         keys.keyseq.RemoveRange (key_head, 1);
+      }
 
-    internal void commit ()
-    {
-      produced.Cat (preedit);
-      preedit.Del ();
-      changed |= ChangedStatus.Preedit;
-    }
+      internal void undo (int n)
+      {
+       if (n < 0)
+         keys.keyseq.RemoveRange (keys.keyseq.Count + n, - n);
+       else
+         keys.keyseq.RemoveRange (n, keys.keyseq.Count  - n);
+       reset ();
+      }
 
-    internal void shift (MSymbol sym)
-    {
-      Mim.State state;
+      internal void commit ()
+      {
+       produced.Cat (preedit);
+       preedit.Del ();
+       changed |= ChangedStatus.Preedit;
+      }
 
-      if (sym == MSymbol.t)
-       {
-         if (states.Count > 1)
-           state = states.Pop ();
-         else
-           state = states.Peek ();
-       }
-      else
-       {
-         state = (Mim.State) im.states.Get (sym);
-         if (state == null)
-           throw new Exception ("Unknown state: " + state.name);
-       }
-      if (state == null)
-       state = states.Pop ();
-      if (state == (Mim.State) im.states.val)
-       {
-         commit ();
-         reset ();
-       }
-      else
-       {
-         state_key_head = key_head;
-         state_pos = cursor_pos;
-         state_preedit = preedit.Dup ();
-         if (state != states.Peek ())
-           {
-             states.Push (state);
-             state_var_values = domain.SaveValues ();
-             status = state.title;
-             if (status == null)
-               status = im.title;
-             changed |= ChangedStatus.StateTitle;
-             Xex on_entry
-               = (Xex) state.branches.Get (MSymbol.t);
-             if (on_entry != null)
-               on_entry.Eval (domain);
-           }
-       }
-    }
+      internal void shift (MSymbol sym)
+      {
+       State state;
 
-    internal void reset ()
-    {
-      preedit.Del ();
-      state_preedit.Del ();
-      produced.Del ();
-      markers.Clear ();
-      cursor_pos = 0;
-      key_head = commit_key_head = 0;
-      states.Clear ();
-      states.Push ((Mim.State) im.states.Val);
-      state_key_head = 0;
-      state_pos = 0;
-    }
+       if (sym == MSymbol.t)
+         {
+           if (state_stack.Count > 1)
+             state = state_stack.Pop ();
+           else
+             state = state_stack.Peek ();
+         }
+       else
+         {
+           state = (State) im.states.Get (sym);
+           if (state == null)
+             throw new Exception ("Unknown state: " + state.name);
+         }
+       if (state == null)
+         state = state_stack.Pop ();
+       if (state == (State) im.states.val)
+         {
+           commit ();
+           reset ();
+         }
+       else
+         {
+           state_key_head = key_head;
+           state_pos = cursor_pos;
+           state_preedit = preedit.Dup ();
+           if (state != state_stack.Peek ())
+             {
+               state_stack.Push (state);
+               state_var_values = domain.SaveValues ();
+               status = state.title;
+               if (status == null)
+                 status = im.title;
+               changed |= ChangedStatus.StateTitle;
+               Xex on_entry
+                 = (Xex) state.branches.Get (MSymbol.t);
+               if (on_entry != null)
+                 on_entry.Eval (domain);
+             }
+         }
+      }
 
-    internal object GetCandidates (out int column)
-    {
-      column = 0;
-      if (cursor_pos == 0)
-       return null;
-      Mim.Candidates candidates
-       = (Mim.Candidates) preedit.GetProp (cursor_pos - 1, Mim.Mcandidates);
-      if (candidates == null)
-       return null;
-      column = candidates.Column;
-      return candidates.Current;
-    }
+      internal void reset ()
+      {
+       preedit.Del ();
+       state_preedit.Del ();
+       produced.Del ();
+       markers.Clear ();
+       cursor_pos = 0;
+       key_head = commit_key_head = 0;
+       state_stack.Clear ();
+       state_stack.Push ((State) im.states.Val);
+       state_key_head = 0;
+       state_pos = 0;
+      }
 
-    internal void HandleKey ()
-    {
-    }
+      internal object GetCandidates (out int column)
+      {
+       column = 0;
+       if (cursor_pos == 0)
+         return null;
+       Candidates candidates
+         = (Candidates) preedit.GetProp (cursor_pos - 1, Mcandidates);
+       if (candidates == null)
+         return null;
+       column = candidates.Column;
+       return candidates.Current;
+      }
 
-    public bool Toggle ()
-    {
-      active = ! active;
-      return active;
+      internal void HandleKey ()
+      {
+      }
+
+      public bool Toggle ()
+      {
+       active = ! active;
+       return active;
+      }
     }
   }
 }
index 5dad277..13420ed 100644 (file)
--- a/input.txt
+++ b/input.txt
@@ -67,10 +67,10 @@ SELECTORTERM = SELECTOR | VAR (value is SELECTOR) | FUNCALL (return SELECTOR)
 MIM-PREDEFINED
   = INSERT | CANDIDATES | DELETE | SELECT | SHOW | HIDE
     | MARK | MOVE | PUSHBACK | POP | UNDO | COMMIT | UNHANDLE
-    | SHIFT | SHIFTBACK
+    | SHIFT | SHIFTBACK | CHAR-AT | KEY-COUNT | SURROUND-TEXT-P
 
 INSERT = '<insert>' [ INTTERM | STRTERM ] '</insert>'
-CANDIDATES = '<insert-candidates>' [ STRTERM | LISTTERM ] + '</insert-candiates>'
+CANDIDATES = '<insert-candidates>' [ STRTERM | LISTTERM ]+ '</insert-candiates>'
 DELETE = '<delete>' [ MARKERTERM | INTTERM ] '</delete>'
 SELECT = '<select>' [ SELECTORTERM | INTTERM ] '</select>'
 SHOW = '<show-candidates/>'
@@ -84,3 +84,10 @@ COMMIT = '<commit/>'
 UNHANDLE = '<unhandle/>'
 SHIFT = '<shift>' SYMTERM '</shift>'
 SHIFTBACK = '<shiftback/>'
+CHAR-AT = '<char-at>' MARKERTERM '</char-at>'
+  => <integer>C</integer>, where C is the character in the preedit text
+     at the postion of MARKERTERM
+KEY-COUNT = '<key-count/>'
+  => <integer>N</integer>, where N is the number of currently handled keys
+SURROUNDING-TEXT-AVAILABLE = '<surrounding-text-available/>'
+  => <integer>1</integer> or <integer>0</integer>