From 5721a65b2c018e6804bdac432fa9a242018ce45f Mon Sep 17 00:00:00 2001 From: handa Date: Tue, 6 Oct 2009 13:10:38 +0000 Subject: [PATCH] *** empty log message *** --- MInputMethod.cs | 477 ++++++++++++++++++++++++++++++++++++------------------- XmlExpr.cs | 10 +- 2 files changed, 320 insertions(+), 167 deletions(-) diff --git a/MInputMethod.cs b/MInputMethod.cs index b0736ea..f92e302 100644 --- a/MInputMethod.cs +++ b/MInputMethod.cs @@ -59,6 +59,14 @@ namespace M17N.Input private static MSymbol Mpushback = "pushback"; private static MSymbol Mkeyseq = "keyseq"; + private static MSymbol Mget_surrounding_text = "get-surrounding-text"; + private static MSymbol Mdel_surrounding_text = "del-surrounding-text"; + + private static MSymbol Mat_minus_zero = "@-0"; + + private static Xex.Symbol Nmap = "map"; + private static Xex.Symbol Nrule = "rule"; + private static Xex.Symbol Nkeyseq = "keyseq"; private static Xex.Symbol Nprogn = "progn"; private static Xex.Symbol Ninsert = "insert"; private static Xex.Symbol Ninsert_candidates = "insert-candidates"; @@ -127,6 +135,7 @@ namespace M17N.Input = new Dictionary (); private static uint keysym_base = 0x200000; private static uint char_mask = ~((uint) KeyModifier.All); + public static Key Reload; static Key () { @@ -149,6 +158,8 @@ namespace M17N.Input keymodifiers["altgr"] = KeyModifier.AltGr; keymodifiers["super"] = KeyModifier.Super; keymodifiers["hyper"] = KeyModifier.Hyper; + Reload = new Key (keysym_base); + keysyms["-reload"] = keysym_base++; } private static uint decode_keysym (MSymbol keysym) @@ -262,6 +273,20 @@ namespace M17N.Input get { return ((key & (uint) KeyModifier.All) != 0); } } + public static bool operator== (Key k1, Key k2) + { + return k1.key == k2.key; + } + + public static bool operator!= (Key k1, Key k2) + { + return k1.key != k2.key; + } + + public override bool Equals (object o) { return key == ((Key) o).key; } + + public override int GetHashCode () { return (int) key; } + public bool Match (Key k) { if (k.key == key) @@ -306,7 +331,7 @@ namespace M17N.Input } } - public class KeySeq : Xex.TermValue + internal class KeySeq : Xex.TermValue { public List keyseq = new List (); @@ -387,7 +412,7 @@ namespace M17N.Input { public MSymbol name; public MText description; - public List keys; + internal List keys; public Command (MPlist p) { @@ -494,20 +519,25 @@ namespace M17N.Input { private MSymbol name; - public Marker (MSymbol name) + private Marker (MSymbol name) { this.name = name; } public abstract int Position (Context ic); - public abstract void Mark (Context ic); - public abstract int CharAt (Context ic); + public virtual void Mark (Context ic) + { + throw new Exception ("Can't set predefined marker: " + name); + } + public virtual int CharAt (Context ic) + { + return ic.preedit[Position (ic)]; + } + public override Xex.TermValue Clone () { return this; } public static Xex.TermValue parser (Xex.Domain domain, XmlNode node) { - MSymbol name = node.InnerText; - - return Get ((Context) domain.context, name); + return Get ((MSymbol) node.InnerText); } public class Named : Marker @@ -516,20 +546,14 @@ namespace M17N.Input public override int Position (Context ic) { - int pos; - if (ic.markers.TryGetValue (name, out pos)) - return pos; - return 0; + MPlist p = ic.markers.Find (name); + return (p != null ? p.Integer : 0); + } public override void Mark (Context ic) { - ic.markers[name] = ic.cursor_pos; - } - - public override Xex.TermValue Clone () - { - return new Named (name, pos); + ic.markers.Put (name, ic.cursor_pos); } } @@ -566,23 +590,29 @@ namespace M17N.Input return name.Name[1] - '0'; } } - - public override void Mark (Context ic) - { - throw new Exception ("Can't set predefined marker: " + name); - } + } + + public class PredefinedAbsolute : Marker + { + private int pos; - public override Xex.TermValue Clone () + public PredefinedAbsolute (MSymbol name) : base (name) + { + if (! int.TryParse (name.Name.Substring (1), out pos)) + throw new Exception ("Invalid marker name: " + name); + } + + public override int Position (Context ic) { - return new Predefined (name); + return (pos < ic.preedit.Length ? pos : ic.preedit.Length); } } - public class PredefinedPlusMinus : Marker + public class PredefinedSurround : Marker { private int distance; - public PredefinedPlusMinus (MSymbol name): base (name) + public PredefinedSurround (MSymbol name) : base (name) { if (! int.TryParse (name.Name.Substring (2), out distance)) throw new Exception ("Invalid marker name: " + name); @@ -594,6 +624,16 @@ namespace M17N.Input { return ic.cursor_pos + distance; } + + public override int CharAt (Context ic) + { + int pos = ic.cursor_pos + distance; + if (pos < 0) + return ic.GetSurroundingChar (pos); + else if (pos >= ic.preedit.Length) + return ic.GetSurroundingChar (pos - ic.preedit.Length); + return ic.preedit[pos]; + } } static internal Dictionary predefined_markers; @@ -601,29 +641,26 @@ namespace M17N.Input static Marker () { predefined_markers = new Dictionary (); - MSymbol[] symlist = new MSymbol[] {"@<", "@>", "@-", "@+", "@[", "@]", - "@0", "@1", "@2", "@3", "@4", - "@5", "@6", "@7", "@8", "@9" }; + MSymbol[] symlist = new MSymbol[] {"@<", "@>", "@-", "@+", "@[", "@]" }; foreach (MSymbol s in symlist) predefined_markers[s] = new Predefined (s); } public static Marker Get (MSymbol name) { - Predefined pred; - - if (predefined_markers.TryGetValue (name, out pred)) - return pred; if (name.Name[0] == '@') { - int pos; - if (name.Name.Length >= 3 - && (name.Name[1] == '-' || name.Name[1] == '+') - && int.TryParse (name.Name.Substring (2), out pos) - && (pos > 0)) - return (predefined_markers[name] = new Predefined (name)); - else + Predefined pred; + if (predefined_markers.TryGetValue (name, out pred)) + return pred; + if (name.Name.Length == 1) throw new Exception ("Invalid marker name: " + name); + if (Char.IsDigit (name.Name[1])) + return new PredefinedAbsolute (name); + if (name.Name.Length == 2 || name == Mat_minus_zero + || ! (name.Name[1] == '-' || name.Name[1] == '+')) + throw new Exception ("Invalid marker name: " + name); + return new PredefinedSurround (name); } return new Named (name); } @@ -885,6 +922,30 @@ namespace M17N.Input internal class Selector : Xex.TermValue { + static new Dictionary selectors; + + static Selector () + { + selectors = new Dictionary (); + MSymbol[] symlist = new MSymbol[] { "@<", "@=", "@>", "@-", "@+", + "@[", "@]" }; + foreach (MSymbol s in symlist) + selectors[s] = new Selector (s); + selectors["@first"] = new Selector ('<'); + selectors["@current"] = new Selector ('='); + selectors["@last"] = new Selector ('>'); + selectors["@previous"] = new Selector ('-'); + selectors["@next"] = new Selector ('+'); + selectors["@previous-candidate-list"] = new Selector ('['); + selectors["@next-candidate-list"] = new Selector (']'); + } + + private char tag; + + private Selector (MSymbol sym) { tag = sym.Name[1]; } + + private Selector (char tag) { this.tag = tag; } + public static Xex.TermValue parser (Xex.Domain domain, XmlNode node) { return Get ((MSymbol) node.InnerText); @@ -892,11 +953,10 @@ namespace M17N.Input public static Xex.TermValue Get (MSymbol name) { - Predefined pred; - - if (! predefined_selectors.TryGetValue (name, out pred)) + Selector selector; + if (! selectors.TryGetValue (name, out selector)) throw new Exception ("Invalid selector name: " + name); - return pred; + return selector; } public override Xex.TermValue Clone () { return this; } @@ -914,44 +974,71 @@ namespace M17N.Input default: break; } } + } - static new Dictionary selectors; + internal class Map + { + public MSymbol name; + public List entries; - static Selector () + public Map (MSymbol name) { this.name = name; } + + public class Entry + { + public KeySeq keyseq; + public Xex.Term[] actions; + + public Entry (Xex.Domain domain, KeySeq keyseq, Xex.Term[] actions) { - selectors = new Dictionary (); - MSymbol[] symlist = new MSymbol[] { "@<", "@=", "@>", "@-", "@+", - "@[", "@]" }; - foreach (MSymbol s in symlist) - selectors[s] = new Selector (s); + this.keyseq = keyseq; + this.actions = actions; } + } } - internal class Map + internal class Branch { public MSymbol name; - public Dictionary submaps; - public Xex.Term actions; + public Keymap keymap; + public Xex.Term[] enter_actions, fallback_actions; + } - public void Add (KeySeq keys, int index, Xex.Term actions) - { - Map sub = null; + public class Keymap + { + public Dictionary keymaps; + public Xex.Term[] map_actions, branch_actions; - if (submaps == null) - submaps = new Dictionary (); - else - submaps.TryGetValue (keys.keyseq[index], out sub); - if (sub == null) + public void Add (KeySeq keys, int index, + Xex.Term[] map_actions, Xex.Term[] branch_actions) + { + Map sub = null; + + if (submaps == null) + submaps = new Dictionary (); + else + submaps.TryGetValue (keys.keyseq[index], out sub); + if (sub == null) + { + Key key = keys.keyseq[index]; + submaps[key] = sub = new Map (); + } + if (index + 1 < keys.keyseq.Count) + sub.Add (keys, index + 1, actions); + else + this.actions = actions; + } + } + + public void AddMap (Map map, Xex.Term[] actions) + { + foreach (Map.Entry entry in map.entries) { - Key key = keys.keyseq[index]; - submaps[key] = sub = new Map (); + Add (entry.keyseq, 0, entry.actions, actions) } - if (index + 1 < keys.keyseq.Count) - sub.Add (keys, index + 1, actions); - else - this.actions = actions; } + public void Add (KeySeq keys, int index, + Xex.Term[] map_actions, Xex.Term[] branch_actions) public Xex.Term Lookup (KeySeq keys, ref int index) { if (index < keys.keyseq.Count) @@ -997,18 +1084,18 @@ namespace M17N.Input internal class State { - public MSymbol name; + public Xex.Symbol name; public MText title; public MPlist branches = new MPlist (); - public State (MSymbol name) + public State (Xex.Symbol name) { this.name = name; } public override string ToString () { - MText mt = "(" + name.Name; + MText mt = "(" + name; if (title != null) mt.Cat (" \"" + title + "\""); @@ -1031,7 +1118,8 @@ namespace M17N.Input internal Xex.Symbol[] var_names; internal Dictionary plugins; internal Dictionary maps; - internal MPlist states; + internal Dictionary states; + internal State initial_state; static MInputMethod () { @@ -1182,10 +1270,19 @@ namespace M17N.Input return true; } + private void add_default_state () + { + Xex.Symbol Ninit = "init"; + State state = new State (Ninit); + foreach (KeyValuePairkv in maps) + state.branches.Add (kv.Key, null); + states[Ninit] = initial_state = state; + } + private void load (MPlist plist, bool full) { maps = new Dictionary (); - states = new MPlist (); + states = new Dictionary (); for (; ! plist.IsEmpty; plist = plist.next) if (plist.IsPlist) @@ -1230,14 +1327,8 @@ namespace M17N.Input commands = new Command[0]; if (! full) return; - if (states.IsEmpty) - { - State state = new State ((MSymbol) "init"); - plist = new MPlist (); - foreach (KeyValuePairkv in maps) - state.branches.Add (kv.Key, null); - states.Add (state.name, state); - } + if (states.Count == 0) + add_default_state (); } private void load (XmlNode node, bool full) @@ -1245,7 +1336,7 @@ namespace M17N.Input bool skip_header = load_status == LoadStatus.Header; maps = new Dictionary (); - states = new MPlist (); + states = new Dictionary (); if (node.NodeType == XmlNodeType.Document) node = node.FirstChild; @@ -1286,13 +1377,8 @@ namespace M17N.Input commands = new Command[0]; if (! full) return; - if (states.IsEmpty) - { - State state = new State ((MSymbol) "init"); - foreach (KeyValuePairkv in maps) - state.branches.Add (kv.Key, null); - states.Add (state.name, state); - } + if (states.Count == 0) + add_default_state (); } private static void transform (MPlist plist) @@ -1667,6 +1753,23 @@ namespace M17N.Input private void parse_maps (XmlNode node) { + for (node = node.FirstChild; node != null; node = node.NextSibling) + if (node.Name == Nmap) + { + MSymbol name = node.Attributes[0].Value; + Map map = new Map (name); + maps[name] = map; + for (XmlNode nd = node.FirstChild; nd != null; nd = nd.NextSibling) + if (nd.Name == Nrule) + { + XmlNode n = nd.FirstChild; + if (n.Name != Nkeyseq) + continue; + KeySeq keyseq = (KeySeq) KeySeq.parser (domain, n); + Xex.Term[] actions = Xex.ParseTerms (domain, n.NextSibling); + map.entries.Add (new Map.Entry (domain, keyseq, actions)); + } + } } private void parse_states (XmlNode node) @@ -1731,14 +1834,15 @@ namespace M17N.Input { if (target_name == MSymbol.nil) { - for (p = im.states; ! p.IsEmpty; p = p.next) - states.Add (p.key, p.val); + foreach (KeyValuePair kv in im.states) + states[kv.Key] = kv.Value; } else { - object state = im.states.Get (target_name); - if (state != null) - states.Add (target_name, state); + Xex.Symbol state_name = target_name.Name; + State state; + if (im.states.TryGetValue (state_name, out state)) + states[state_name] = state; } } } @@ -1883,7 +1987,6 @@ namespace M17N.Input return terms; } - private void parse_macros (MPlist plist) { for (MPlist pl = plist; ! pl.IsEmpty; pl = pl.next) @@ -1917,9 +2020,8 @@ namespace M17N.Input if (! pl.IsSymbol) continue; - Map map = new Map (); - map.name = pl.Symbol; - maps[map.name] = map; + Map map = new Map (pl.Symbol); + maps[pl.Symbol] = map; for (pl = pl.next; ! pl.IsEmpty; pl = pl.next) { if (! pl.IsPlist) @@ -1935,8 +2037,8 @@ namespace M17N.Input p = p.next; if (p.IsEmpty) continue; - map.Add (keys, 0, - new Xex.Term (domain, Nprogn, parse_actions (p))); + Xex.Term[] actions = parse_actions (p); + map.entries.Add (new Map.Entry (domain, keys, actions)); } } } @@ -1957,11 +2059,12 @@ namespace M17N.Input if (! pl.IsSymbol) continue; - State state = new State (pl.Symbol); + Xex.Symbol name = (Xex.Symbol) pl.Symbol.Name; + State state = new State (name); state.title = title; - if (states == null) - states = new MPlist (); - states.Add (state.name, state); + if (states.Count == 0) + initial_state = state; + states[name] = state; for (pl = pl.next; ! pl.IsEmpty; pl = pl.next) { if (! pl.IsPlist) @@ -2107,9 +2210,9 @@ namespace M17N.Input } private static Xex.Term Fshiftback (Xex.Domain domain, Xex.Variable vari, - Xex.Term[] args) + Xex.Term[] args) { - ((Context) domain.context).shift_back (); + ((Context) domain.context).shiftback (); return Tnil; } @@ -2123,7 +2226,7 @@ namespace M17N.Input Xex.Variable vari, Xex.Term[] args) { - return new Xex.Term (((Context) domain.context).surrounding_flag); + return new Xex.Term (((Context) domain.context).SurroundingFlag); } public override string ToString () @@ -2154,8 +2257,8 @@ namespace M17N.Input foreach (KeyValuePair kv in maps) str += " " + kv.Value; str += ") (states"; - foreach (MPlist p in states) - str += " " + p.val; + foreach (Xex.Symbol name in states.Keys) + str += " " + name; return str + "))"; } @@ -2163,13 +2266,16 @@ namespace M17N.Input { internal static Xex.Symbol Ncandidates_group_size = "candidates-group-size"; - public MInputMethod im; + private MInputMethod im; + private Dictionary callbacks + = new Dictionary (); + private MText produced; private bool active; private MText status; internal MText preedit; internal int cursor_pos; - internal Dictionary markers; + internal MPlist markers; internal Candidates candidates; private int candidate_from, candidate_to; private bool candidate_show; @@ -2203,17 +2309,48 @@ namespace M17N.Input internal ChangedStatus changed; - public ChangedStatus Changed { get { return changed; } } + static MPlist callback_arg = new MPlist (); - public Context (MInputMethod im) + private bool call_callback (MSymbol name, MPlist arg) { - this.im = im; - domain = new Xex.Domain (im.domain, this); - state_list = new List (); - state_list.Add ((State) im.states.val); - keys = new KeySeq (); + Callback callback; + if (! callbacks.TryGetValue (name, out callback)) + return false; + return callback (this, arg); } + private bool get_surrounding_text (int len) + { + if (len < 0 ? -len <= preceding_text.Length + : len <= following_text.Length) + return true; + callback_arg.Set (MSymbol.integer, len); + if (! call_callback (Mget_surrounding_text, callback_arg) + || ! callback_arg.IsMText) + return false; + if (len < 0) + { + preceding_text = callback_arg.Text; + return (-len <= preceding_text.Length); + } + following_text = callback_arg.Text; + 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)) + return 0; + if (pos < 0) + return preceding_text[preceding_text.Length + pos]; + return following_text[pos]; + } + private void adjust_markers (int from, int to, object inserted) { int ins = (inserted == null ? 0 @@ -2428,16 +2565,6 @@ namespace M17N.Input } } - internal void mark (MSymbol sym) - { - MPlist slot = markers.Find (sym); - - if (slot == null) - markers.Push (sym, cursor_pos); - else - slot.val = cursor_pos; - } - internal void pushback (int n) { if (n > 0) @@ -2488,28 +2615,9 @@ namespace M17N.Input changed |= ChangedStatus.Preedit; } - internal void shift (MSymbol sym) + private void new_state (bool changed) { - State state; - - if (sym == MSymbol.t) - { - state = state_list.Last (); - if (state_list.Count > 1) - state_list.RemoveAt (state_list.Count - 1); - } - else - { - state = (State) im.states.Get (sym); - if (state == null) - throw new Exception ("Unknown state: " + state.name); - } - if (state == null) - { - state = state_list.Last; - state_list.RemoveAt (state_list.Count -1); - } - if (state == (State) im.states.val) + if (state_list.Count == 1) { commit (); reset (); @@ -2519,14 +2627,14 @@ namespace M17N.Input state_key_head = key_head; state_pos = cursor_pos; state_preedit = preedit.Dup (); - if (state != state_list.Last ()) + state_var_values = domain.SaveValues (); + if (changed) { - state_list.Add (state); - state_var_values = domain.SaveValues (); + State state = state_list[state_list.Count - 1]; status = state.title; if (status == null) status = im.title; - changed |= ChangedStatus.StateTitle; + this.changed |= ChangedStatus.StateTitle; Xex on_entry = (Xex) state.branches.Get (MSymbol.t); if (on_entry != null) @@ -2535,6 +2643,26 @@ namespace M17N.Input } } + internal void shift (Xex.Symbol sym) + { + State state; + bool changed; + + if (! im.states.TryGetValue (sym, out state)) + throw new Exception ("Unknown state: " + sym); + changed = state != state_list[state_list.Count - 1]; + if (changed) + state_list.Add (state); + new_state (changed); + } + + internal void shiftback () + { + if (state_list.Count > 1) + state_list.RemoveAt (state_list.Count - 1); + new_state (true); + } + internal void reset () { preedit.Del (); @@ -2544,11 +2672,27 @@ namespace M17N.Input cursor_pos = 0; key_head = commit_key_head = 0; state_list.Clear (); - state_list.Add ((State) im.states.Val); + state_list.Add (im.initial_state); state_key_head = 0; state_pos = 0; } + public Context (MInputMethod im) + { + this.im = im; + domain = new Xex.Domain (im.domain, this); + state_list.Clear (); + state_list.Add (im.initial_state); + keys = new KeySeq (); + } + + public ChangedStatus Changed { get { return changed; } } + + public void AddCallback (MSymbol name, Callback callback) + { + callbacks[name] = callback; + } + internal object GetCandidates (out int column) { column = 0; @@ -2562,8 +2706,18 @@ namespace M17N.Input return candidates.Current; } - internal void HandleKey () + private bool handle_key () { + State state = state_list[state_list.Count - 1]; + for (MPlist *p = state.branches; ! p.IsEmpty; p = p.next) + { + int n = state_key_head; + Xex.Term term = ((Map) p.Val).Lookup (keys, ref n); + + + + } + } public bool Toggle () @@ -2584,7 +2738,6 @@ namespace M17N.Input return (produced.Length > 0); } - // 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. @@ -2592,7 +2745,7 @@ namespace M17N.Input public bool Filter (Key key) { - if (check_reload (key)) + if (key == Key.Reload) return true; changed = ChangedStatus.None; produced.Del (); @@ -2600,20 +2753,20 @@ namespace M17N.Input following_text.Del (); key_unhandled = false; - keys.Add (key); + keys.keyseq.Add (key); int count = 0; - while (key_head < keys.Length) + while (key_head < keys.keyseq.Count) { if (! handle_key ()) { - unhandled_key = keys[key_head++]; + unhandled_key = keys.keyseq[key_head++]; key_unhandled = true; break; } if (++count == 100) break; } - keys.RemoveRange (0, key_head); + keys.keyseq.RemoveRange (0, key_head); return (! key_unhandled && produced.Length == 0); } } diff --git a/XmlExpr.cs b/XmlExpr.cs index 60a2008..c609e1a 100644 --- a/XmlExpr.cs +++ b/XmlExpr.cs @@ -1880,7 +1880,7 @@ namespace System.Xml.Expression private Term[] terms; - private void parse_terms (Domain domain, XmlNode node) + public static Term[] ParseTerms (Domain domain, XmlNode node) { int nterms = 0; for (XmlNode n = node; n != null; n = n.NextSibling) @@ -1893,8 +1893,7 @@ namespace System.Xml.Expression else nterms++; } - - terms = new Term[nterms]; + Term[] terms = new Term[nterms]; int i = 0; for (XmlNode n = node; n != null; n = n.NextSibling) if (n.NodeType == XmlNodeType.Element) @@ -1904,11 +1903,12 @@ namespace System.Xml.Expression else if (n.Name != Ndefvar) terms[i++]= new Term (domain, n); } + return terms; } public Xexpression (Domain domain, XmlNode node) { - parse_terms (domain, node); + terms = ParseTerms (domain, node); } public Xexpression (Domain domain, string url) @@ -1927,7 +1927,7 @@ namespace System.Xml.Expression throw new Exception ("Node not found"); node = doc.ReadNode (reader); } - parse_terms (domain, node.FirstChild); + terms = ParseTerms (domain, node.FirstChild); } public Term Eval (Domain domain) -- 1.7.10.4