X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=MInputMethod.cs;h=3f80c2f3241ee319a385668fb76284f9c150e434;hb=3d9937566424ad30834dbf9090721ed8c95c47a5;hp=9e180d62720c86370f258162fe10ed90f847606b;hpb=15afd301194e834e8313cdd5fab4e86593e3b75b;p=m17n%2Fm17n-lib-cs.git diff --git a/MInputMethod.cs b/MInputMethod.cs index 9e180d6..3f80c2f 100644 --- a/MInputMethod.cs +++ b/MInputMethod.cs @@ -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"; @@ -75,6 +68,7 @@ namespace M17N.Input private static Xex.Symbol Qtitle = "title"; private static Xex.Symbol Qeq = "="; private static Xex.Symbol Qeqeq = "=="; + private static Xex.Symbol Qcandidates_group_size = "candidates-group-size"; private static Xex.Term Tnil = new Xex.Term ((Xex.Symbol) "nil"); private static Xex.Term Tcatch_tag = new Xex.Term ((Xex.Symbol) "@mimtag"); @@ -85,7 +79,7 @@ namespace M17N.Input internal static MInputMethod im_global = null; [FlagsAttribute] - private enum LoadStatus + protected enum LoadStatus { None = 0x00, Header = 0x01, @@ -99,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 @@ -804,13 +800,13 @@ namespace M17N.Input group = new object[column]; } - public Candidates (List list, int column) + public Candidates (Xex.Term[] candidates, int column) { - int nblocks = list.Count; + int nblocks = candidates.Length; blocks = new Block[nblocks]; for (int i = 0, start = 0; i < nblocks; i++) - start += (blocks[i] = new Block (index, list[i])).Count; + start += (blocks[i] = new Block (index, candidates[i])).Count; if (column > 0) group = new object[column]; } @@ -1103,7 +1099,7 @@ namespace M17N.Input if (branch_actions != null) foreach (Xex.Term term in branch_actions) mt.Cat (' ').Cat (term.ToString ()); - mt.Cat (')'); + mt.Cat (')'); } if (submaps != null) foreach (KeyValuePair kv in submaps) @@ -1120,7 +1116,6 @@ namespace M17N.Input KeySeq keyseq = new KeySeq (); describe (mt, keyseq); - mt.Cat (')'); return (string) mt; } } @@ -1144,6 +1139,8 @@ namespace M17N.Input XmlAttribute attr = node.Attributes[Qtitle]; if (attr != null) title = (MText) attr.Value; + else + title = im.title; keymap = new Keymap (); for (node = node.FirstChild; node != null; node = node.NextSibling) { @@ -1172,9 +1169,11 @@ namespace M17N.Input plist = plist.next; if (plist.IsMText) { - this.title = plist.Text; + title = plist.Text; plist = plist.next; } + else + title = im.title; keymap = new Keymap (); for (; ! plist.IsEmpty; plist = plist.next) { @@ -1213,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; @@ -1314,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 ()); } @@ -1378,7 +1377,7 @@ namespace M17N.Input private void add_default_state () { Xex.Symbol Qinit = "init"; - State state = new State (Qinit, null); + State state = new State (Qinit, title); foreach (KeyValuePairkv in maps) state.keymap.AddMap (kv.Value, null); states[Qinit] = initial_state = state; @@ -1765,6 +1764,8 @@ namespace M17N.Input { State state = new State (this, plist.Plist); states[state.name] = state; + if (initial_state == null) + initial_state = state; } } @@ -1775,6 +1776,8 @@ namespace M17N.Input { State state = new State (this, node); states[state.name] = state; + if (initial_state == null) + initial_state = state; } } @@ -2071,7 +2074,10 @@ namespace M17N.Input private static Xex.Term Finsert (Xex.Domain domain, Xex.Variable vari, Xex.Term[] args) { - ((Context) domain.context).insert (args[0]); + if (args[0].IsInt) + ((Context) domain.context).insert (args[0].Intval); + else + ((Context) domain.context).insert (args[0].Strval); return args[0]; } @@ -2079,7 +2085,11 @@ namespace M17N.Input Xex.Variable vari, Xex.Term[] args) { - ((Context) domain.context).insert_candidates (args[0]); + Context ic = (Context) domain.context; + Xex.Variable v = ic.domain.GetVar (Qcandidates_group_size, false); + int column = (v == null ? 0 : v.Value.Intval); + + ic.insert_candidates (new Candidates (args, column)); return args[0]; } @@ -2089,14 +2099,23 @@ 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, - Xex.Term[] args) + Xex.Term[] args) { - ((Context) domain.context).delete ((int) args[0].Intval); - return args[0]; + Context ic = (Context) domain.context; + int pos; + + if (args[0].IsInt) + pos = args[0].Intval; + else + { + Marker m = (Marker) args[0].Objval; + pos = m.Position (ic); + } + return new Xex.Term (ic.delete (pos)); } private static Xex.Term Fselect (Xex.Domain domain, Xex.Variable vari, @@ -2110,30 +2129,26 @@ namespace M17N.Input } private static Xex.Term Fshow (Xex.Domain domain, Xex.Variable vari, - Xex.Term[] args) + Xex.Term[] args) { ((Context) domain.context).show (); return Tnil; } private static Xex.Term Fhide (Xex.Domain domain, Xex.Variable vari, - Xex.Term[] args) + Xex.Term[] args) { ((Context) domain.context).hide (); return Tnil; } private static Xex.Term Fmove (Xex.Domain domain, Xex.Variable vari, - Xex.Term[] args) + Xex.Term[] args) { - if (args[0].IsInt) - ((Context) domain.context).move (args[0].Intval); - else - { - Marker m = (Marker) args[0].Objval; - Context ic = (Context) domain.context; - ((Context) domain.context).move (m.Position (ic)); - } + Context ic = (Context) domain.context; + int pos = (args[0].IsInt ? args[0].Intval + : ((Marker) args[0].Objval).Position (ic)); + ic.move (pos); return args[0]; } @@ -2219,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) { @@ -2259,39 +2275,35 @@ namespace M17N.Input public class Context { - internal static Xex.Symbol Qcandidates_group_size - = "candidates-group-size"; internal MInputMethod im; - private Dictionary callbacks - = new Dictionary (); - - private MText produced; + internal Xex.Domain domain; private bool active; + private MText status; - internal MText preedit; + private MText produced = new MText (); + internal MText preedit = new MText (); internal int cursor_pos; internal Dictionary marker_positions = new Dictionary (); + internal Candidates candidates; private int candidate_from, candidate_to; private bool candidate_show; public bool CandidateShow { get { return candidate_show; } } - private List state_list = new List (); - 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 (); @@ -2303,15 +2315,39 @@ namespace M17N.Input // 'key_unhandled' is true. private Key unhandled_key; - internal Xex.Domain domain; - internal ChangedStatus changed; - static MPlist callback_arg = new MPlist (); + internal void reset () + { + status = im.initial_state.title; + produced.Del (); + preedit.Del (); + + cursor_pos = 0; + marker_positions.Clear (); + candidates = null; + candidate_show = false; + + state = im.initial_state; + prev_state = null; + state_preedit.Del (); + state_key_head = 0; + state_var_values = state_initial_var_values; + state_pos = 0; + + 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); @@ -2320,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) @@ -2347,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)) @@ -2398,12 +2424,15 @@ namespace M17N.Input adjust_markers (from, to, mt); } - internal void insert (Xex.Term arg) + internal void insert (int c) { - if (arg.IsInt) - preedit_replace (cursor_pos, cursor_pos, arg.Intval); - else - preedit_replace (cursor_pos, cursor_pos, new MText (arg.Strval)); + preedit_replace (cursor_pos, cursor_pos, c); + changed |= ChangedStatus.Preedit | ChangedStatus.CursorPos; + } + + internal void insert (string str) + { + preedit_replace (cursor_pos, cursor_pos, (MText) str); changed |= ChangedStatus.Preedit | ChangedStatus.CursorPos; } @@ -2428,14 +2457,9 @@ namespace M17N.Input | CandidateAll); } - internal void insert_candidates (Xex.Term arg) + internal void insert_candidates (Candidates candidates) { - int column = 0; - Xex.Variable v = domain.GetVar (Qcandidates_group_size, false); - - if (v != null) - column = v.Value.Intval; - candidates = new Candidates (arg.Listval, column); + this.candidates = candidates; candidate_from = candidate_to = cursor_pos; update_candidate (); } @@ -2449,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 () @@ -2575,74 +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; - } - else - { - changed = state != state_list[state_list.Count - 1]; - if (changed) - state_list.Add (state); + if (prev_state == null) + return; + state = prev_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; - if (status == null) - status = im.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; } - } - - internal void reset () - { - preedit.Del (); - state_preedit.Del (); - produced.Del (); - marker_positions.Clear (); - cursor_pos = 0; - keys.keyseq.Clear (); - 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_pos = 0; + 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; @@ -2656,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) @@ -2671,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) @@ -2684,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) @@ -2695,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) @@ -2732,11 +2760,18 @@ 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) { + if (! active) + { + key_unhandled = true; + unhandled_key = key; + return false; + } if (key == Key.Reload) return true; changed = ChangedStatus.None; @@ -2759,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); } }