*** empty log message ***
authorhanda <handa>
Fri, 9 Oct 2009 13:04:03 +0000 (13:04 +0000)
committerhanda <handa>
Fri, 9 Oct 2009 13:04:03 +0000 (13:04 +0000)
MInputMethod.cs
input.cs

index bd93150..3f80c2f 100644 (file)
@@ -19,12 +19,9 @@ namespace M17N.Input
     public delegate bool Callback (Context ic, MPlist args);
 
     // Class members
-    public static Callback PreeditStart, PreeditDone, PreeditDraw;
-    public static Callback StatusStart, StatusDone, StatusDraw;
-    public static Callback CandidateStart, CandidateDone, CandidateDraw;
-    public static Callback SetSpot;
-    public static Callback Toggle;
-    public static Callback Reset;
+    public static event Callback PreeditChanged;
+    public static event Callback StatusChanged;
+    public static event Callback CandidateChanged;
     public static Callback GetSurroundingText;
     public static Callback DeleteSurroundingText;
 
@@ -42,10 +39,6 @@ namespace M17N.Input
     private static MSymbol Mstate = "state";
     internal static MSymbol Mcandidates = "candidates";
 
-
-    private static MSymbol Mget_surrounding_text = "get-surrounding-text";
-    private static MSymbol Mdel_surrounding_text = "del-surrounding-text";
-
     private static Xex.Symbol Qmap = "map";
     private static Xex.Symbol Qrule = "rule";
     private static Xex.Symbol Qkeyseq = "keyseq";
@@ -86,7 +79,7 @@ namespace M17N.Input
     internal static MInputMethod im_global = null;
 
     [FlagsAttribute]
-    private enum LoadStatus
+    protected enum LoadStatus
     {
       None =   0x00,
       Header = 0x01,
@@ -100,11 +93,13 @@ namespace M17N.Input
     {
       None =           0x00,
       StateTitle =     0x01,
-      Preedit   =      0x02,
+      PreeditText =    0x02,
       CursorPos =      0x04,
       CandidateList =  0x08,
       CandidateIndex = 0x10,
       CandidateShow =  0x20,
+      Preedit =                PreeditText | CursorPos,
+      Candidate =      CandidateList | CandidateIndex | CandidateShow,
     }
 
     private static ChangedStatus CandidateAll = (ChangedStatus.CandidateList
@@ -1217,8 +1212,8 @@ namespace M17N.Input
     // Instance members
     internal Xex.Domain domain = new Xex.Domain (im_domain, null);
 
-    private LoadStatus load_status = LoadStatus.None;
-    private MDatabase.Tag tag;
+    protected LoadStatus load_status = LoadStatus.None;
+    protected MDatabase.Tag tag;
     private MDatabase mdb;
 
     private MText description;
@@ -1318,7 +1313,7 @@ namespace M17N.Input
       return (im_table.TryGetValue (tag, out im) ? im : null);
     }
 
-    public bool Open ()
+    private bool Open ()
     {
       return ((load_status == LoadStatus.Full) || load_body ());
     }
@@ -1382,7 +1377,7 @@ namespace M17N.Input
     private void add_default_state ()
     {
       Xex.Symbol Qinit = "init";
-      State state = new State (Qinit, im.title);
+      State state = new State (Qinit, title);
       foreach (KeyValuePair<MSymbol, Map>kv in maps)
        state.keymap.AddMap (kv.Value, null);
       states[Qinit] = initial_state = state;
@@ -1769,6 +1764,8 @@ namespace M17N.Input
          {
            State state = new State (this, plist.Plist);
            states[state.name] = state;     
+           if (initial_state == null)
+             initial_state = state;
          }
     }
 
@@ -1779,6 +1776,8 @@ namespace M17N.Input
          {
            State state = new State (this, node);
            states[state.name] = state;
+           if (initial_state == null)
+             initial_state = state;
          }
     }
 
@@ -2100,7 +2099,7 @@ namespace M17N.Input
       Context ic = (Context) domain.context;
       Marker m = (Marker) args[0].Objval;
 
-      return new Xex.Term (ic.char_at (m.Position (ic)));
+      return new Xex.Term (m.CharAt (ic));
     }
 
     private static Xex.Term Fdelete (Xex.Domain domain, Xex.Variable vari,
@@ -2116,8 +2115,7 @@ namespace M17N.Input
          Marker m = (Marker) args[0].Objval;
          pos = m.Position (ic);
        }
-      ic.delete (pos);
-      return args[0];
+      return new Xex.Term (ic.delete (pos));
     }
 
     private static Xex.Term Fselect (Xex.Domain domain, Xex.Variable vari,
@@ -2236,11 +2234,12 @@ namespace M17N.Input
                                               Xex.Variable vari,
                                               Xex.Term[] args)
     {
-      return new Xex.Term (((Context) domain.context).SurroundingFlag);
+      return new Xex.Term (GetSurroundingText == null ? 0 : 1);
     }
 
     public override string ToString ()
     {
+      this.Open ();
       string str = (String.Format ("({0} (title \"{1}\")", tag, title));
       if (commands != null)
        {
@@ -2278,8 +2277,6 @@ namespace M17N.Input
     {
       internal MInputMethod im;
       internal Xex.Domain domain;
-      private Dictionary<MSymbol, Callback> callbacks
-       = new Dictionary<MSymbol, Callback> ();
       private bool active;
 
       private MText status;
@@ -2288,25 +2285,25 @@ namespace M17N.Input
       internal int cursor_pos;
       internal Dictionary<Marker, int> marker_positions
        = new Dictionary<Marker, int> ();
+
       internal Candidates candidates;
       private int candidate_from, candidate_to;
       private bool candidate_show;
       public bool CandidateShow { get { return candidate_show; } }
 
-      private List<State> state_list = new List<State> ();
-      private Keymap keymap;
+      private State state, prev_state;
+      private MText state_preedit = new MText ();
+      private int state_key_head;
+      private object state_var_values, state_initial_var_values;
+      private int state_pos;
 
+      private Keymap keymap;
       // Sequence of input keys.
       internal KeySeq keys = new KeySeq ();
-
       // Index into KEYS specifying the next key to handle.
       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 MText preceding_text = new MText ();
       internal MText following_text = new MText ();
 
@@ -2325,25 +2322,32 @@ namespace M17N.Input
        status = im.initial_state.title;
        produced.Del ();
        preedit.Del ();
+
        cursor_pos = 0;
        marker_positions.Clear ();
        candidates = null;
        candidate_show = false;
-       keys.keyseq.Clear ();
+
+       state = im.initial_state;
+       prev_state = null;
        state_preedit.Del ();
-       key_head = commit_key_head = 0;
-       state_list.Clear ();
-       state_list.Add (im.initial_state);
-       keymap = im.initial_state.keymap;
-       key_head = state_key_head = 0;
+       state_key_head = 0;
+       state_var_values = state_initial_var_values;
        state_pos = 0;
-      }
 
-      static MPlist callback_arg = new MPlist ();
+       keymap = im.initial_state.keymap;
+       keys.keyseq.Clear ();
+       key_head = commit_key_head = 0;
+
+       preceding_text.Del ();
+       following_text.Del ();
+
+       changed = ChangedStatus.None;
+      }
 
       static Xex.Term[] catch_args = new Xex.Term[2];
 
-      private bool take_action (Xex.Term[] actions)
+      private bool take_actions (Xex.Term[] actions)
       {
        catch_args[0] = Tcatch_tag;
        catch_args[1]= new Xex.Term (domain, Qprogn, actions);
@@ -2352,22 +2356,17 @@ namespace M17N.Input
        return (! term.IsSymbol || term.Symval != Tcatch_tag.Symval);
       }
 
-
-      private bool call_callback (MSymbol name, MPlist arg)
-      {
-       Callback callback;
-       if (! callbacks.TryGetValue (name, out callback))
-         return false;
-       return callback (this, arg);
-      }
+      static MPlist callback_arg = new MPlist ();
 
       private bool get_surrounding_text (int len)
       {
        if (len < 0 ? -len <= preceding_text.Length
            : len <= following_text.Length)
          return true;
+       if (GetSurroundingText == null)
+         return false;
        callback_arg.Set (MSymbol.integer, len);
-       if (! call_callback (Mget_surrounding_text, callback_arg)
+       if (! GetSurroundingText (this, callback_arg)
            || ! callback_arg.IsMText)
          return false;
        if (len < 0)
@@ -2379,11 +2378,6 @@ namespace M17N.Input
        return (len <= following_text.Length);
       }
 
-      internal int SurroundingFlag
-      {
-       get { return (callbacks.ContainsKey (Mget_surrounding_text) ? 1 : 0); }
-      }
-
       internal int GetSurroundingChar (int pos)
       {
        if (! get_surrounding_text (pos < 0 ? pos : pos + 1))
@@ -2479,53 +2473,55 @@ namespace M17N.Input
          }
       }
 
-      internal int char_at (int pos)
+      internal int delete (int pos)
       {
-       int c;
+       int deleted = pos - cursor_pos;
 
-       pos += cursor_pos;
-       if (pos < 0)
+       if (pos < cursor_pos)
          {
-           if (preceding_text.Length < -pos)
+           if (pos < 0)
              {
-               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;
+               if (DeleteSurroundingText != null)
+                 {
+                   callback_arg.Set (MSymbol.integer, pos);
+                   if (DeleteSurroundingText (this, callback_arg))
+                     {
+                       if (callback_arg.IsInteger)
+                         deleted = callback_arg.Integer - cursor_pos;
+                       preceding_text.Del ();
+                     }
+                   else
+                     deleted = - cursor_pos;
+                 }
+               pos = 0;
              }
-           c = (-pos < preceding_text.Length
-                ? preceding_text[preceding_text.Length + pos] : -1);
+           if (pos < cursor_pos)
+             preedit_replace (pos, cursor_pos, null);
          }
-       else if (pos >= 0 && pos < preedit.Length)
-         c = preedit[pos];
        else
          {
-           pos -= preedit.Length;
-           if (pos >= following_text.Length)
+           if (pos > preedit.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;
+               if (DeleteSurroundingText != null)
+                 {
+                   callback_arg.Set (MSymbol.integer, pos - preedit.Length);
+                   if (DeleteSurroundingText (this, callback_arg))
+                     {
+                       if (callback_arg.IsInteger)
+                         deleted = callback_arg.Integer - cursor_pos;
+                       preceding_text.Del ();
+                     }
+                   else
+                     deleted = preedit.Length - cursor_pos;
+                 }
+               pos = preedit.Length;
              }
-           c = (pos < following_text.Length ? following_text[pos] : -1);
+           if (pos > cursor_pos)
+             preedit_replace (cursor_pos, pos, null);
          }
-       return 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;
+       if (deleted != 0)
+         changed |= ChangedStatus.Preedit | ChangedStatus.CursorPos;
+       return deleted;
       }
 
       internal void show ()
@@ -2605,57 +2601,62 @@ namespace M17N.Input
 
       internal void shift (State state)
       {
-       bool changed;
-
        if (state == null)
          {
-           if (state_list.Count > 1)
-             state_list.RemoveAt (state_list.Count - 1);
-           state = state_list[state_list.Count - 1];
-           changed = true;
+           if (prev_state == null)
+             return;
+           state = prev_state;
          }
-       else
-         {
-           changed = state != state_list[state_list.Count - 1];
-           if (changed)
-             state_list.Add (state);
-         }
-       if (state_list.Count == 1)
+
+       if (state == im.initial_state)
          {
            commit ();
-           reset ();
-         }
-       else
-         {
-           state_key_head = key_head;
-           state_pos = cursor_pos;
-           state_preedit = preedit.Dup ();
-           state_var_values = domain.SaveValues ();
-           if (changed)
+           keys.keyseq.RemoveRange (0, key_head);
+           key_head = 0;
+           if (state != this.state)
              {
-               status = state.title;
-               this.changed |= ChangedStatus.StateTitle;
+               domain.RestoreValues (state_initial_var_values);
                if (state.enter_actions != null)
-                 take_action (state.enter_actions);
+                 take_actions (state.enter_actions);
              }
+           prev_state = null;
+         }
+       else
+         {
+           if (state != this.state && state.enter_actions != null)
+             take_actions (state.enter_actions);
+           prev_state = this.state;
          }
+       save_state ();
+       if (this.state.title != state.title)
+         this.changed |= ChangedStatus.StateTitle;
+       this.state = state;
       }
 
       public Context (MInputMethod im)
       {
+       if (im.load_status != LoadStatus.Full
+           && ! im.Open ())
+         throw new Exception ("Openging " + im.tag + " failed");
        this.im = im;
        domain = new Xex.Domain (im.domain, this);
+       state_initial_var_values = domain.SaveValues ();
        reset ();
        active = true;
+       if (PreeditChanged != null)
+         {
+           callback_arg.Set (MSymbol.mtext, preedit);
+           PreeditChanged (this, callback_arg);
+         }
+       if (StatusChanged != null)
+         {
+           callback_arg.Set (MSymbol.mtext, status);
+           StatusChanged (this, callback_arg);
+         }
       }
 
       public ChangedStatus Changed { get { return changed; } }
 
-      public void AddCallback (MSymbol name, Callback callback)
-      {
-       callbacks[name] = callback;
-      }
-
       internal object GetCandidates (out int column)
       {
        column = 0;
@@ -2669,13 +2670,27 @@ namespace M17N.Input
        return candidates.Current;
       }
 
+      private void save_state ()
+      {
+       state_var_values = domain.SaveValues ();
+       state_preedit.Del ();
+       state_preedit.Ins (0, preedit);
+       state_key_head = key_head;
+       state_pos = cursor_pos;
+      }
+
       private void restore_state ()
       {
+       domain.RestoreValues (state_var_values);
+       preedit.Del ();
+       preedit.Ins (0, state_preedit);
+       key_head = state_key_head;
+       cursor_pos = state_pos;
       }
 
       private bool handle_key ()
       {
-       State state = state_list[state_list.Count - 1];
+       State current_state = state;
        Keymap sub = keymap.Lookup (keys, ref key_head);
 
        if (sub != keymap)
@@ -2684,7 +2699,7 @@ namespace M17N.Input
            if (keymap.map_actions != null)
              {
                restore_state ();
-               if (! take_action (keymap.map_actions))
+               if (! take_actions (keymap.map_actions))
                  return false;
              }
            else if (keymap.submaps != null)
@@ -2697,7 +2712,7 @@ namespace M17N.Input
              {
                if (keymap.branch_actions != null)
                  {
-                   if (! take_action (keymap.branch_actions))
+                   if (! take_actions (keymap.branch_actions))
                      return false;
                  }
                if (keymap != state.keymap)
@@ -2708,10 +2723,10 @@ namespace M17N.Input
          {
            if (keymap.branch_actions != null)
              {
-               if (! take_action (keymap.branch_actions))
+               if (! take_actions (keymap.branch_actions))
                  return false;
              }
-           if (state == state_list[state_list.Count - 1])
+           if (state == current_state)
              {
                if (state == im.initial_state
                    && key_head < keys.keyseq.Count)
@@ -2745,8 +2760,9 @@ namespace M17N.Input
 
       // Return value:
       //   true: All keys are handled and there's no text to commit.
-      //   false: Some key is unhandled or there's a text to commit.
-      //      The caller should use methods UnhandledKey and Produced.
+      //   false: Some key is left unhandled or there's a text to
+      //      commit.  The caller should refer to UnhandledKey and
+      //      Produced.
 
       public bool Filter (Key key)
       {
@@ -2778,6 +2794,25 @@ namespace M17N.Input
              break;
          }
        keys.keyseq.RemoveRange (0, key_head);
+
+       if ((changed & ChangedStatus.Preedit) != ChangedStatus.None
+           && PreeditChanged != null)
+         {
+           callback_arg.Set (MSymbol.mtext, preedit);
+           PreeditChanged (this, callback_arg);
+         }
+       if ((changed & ChangedStatus.StateTitle) != ChangedStatus.None
+           && StatusChanged != null)
+         {
+           callback_arg.Set (MSymbol.mtext, status);
+           StatusChanged (this, callback_arg);
+         }
+       if ((changed & ChangedStatus.Candidate) != ChangedStatus.None
+           && CandidateChanged != null)
+         {
+           CandidateChanged (this, callback_arg);
+         }
+
        return (! key_unhandled && produced.Length == 0);
       }
     }
index db38833..be619f6 100644 (file)
--- a/input.cs
+++ b/input.cs
@@ -14,35 +14,9 @@ public class Test
   {
     //M17n.debug = true;
     MDatabase.ApplicationDir = "/usr/local/share/m17n";
-
-#if false
-    MDatabase.Tag tag = new MDatabase.Tag ("input-method",
-                                          "t", "nil", "vi-base");
-    MDatabase mdb = MDatabase.Find (tag);
-    XmlNode node = mdb.Load ("map-alnum", "input-method", "map-list", "map");
-
-    Console.WriteLine (node.OuterXml);
-
-#elif true
     MInputMethod im = MInputMethod.Find ("vi", "telex");
+    MInputMethod.Context ic = new MInputMethod.Context (im);
+    ic.Filter (new MInputMethod.Key ('a'));
 
-    im.Open ();
-    Console.WriteLine (im);
-#else
-    MText desc, title;
-    Xex.Variable[] vars;
-    MInputMethod.Command[] cmds;
-    MInputMethod[] ims = MInputMethod.List ();
-    foreach (MInputMethod im in ims)
-      {
-
-       Console.Write ("(<{0}, {1}, {2}>", im.Language, im.Name, im.SubName);
-       if (im.Info (out desc, out title, out vars, out cmds))
-         Console.Write (" {0}, {1}, {2}, {3}", desc, title, vars, cmds);
-       if (! im.Open ())
-         Console.Write (" open fail");
-       Console.WriteLine (")");
-      }
-#endif
   }
 }