X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=MInputMethod.cs;h=0670f99e4937d595a11ecbc6f67df4d60584f6ae;hb=refs%2Fheads%2Fmaster;hp=96181356093e166bca1120cf7fe733926ab353e0;hpb=d514dc2573b9efceca395594cefa93c6446f961d;p=m17n%2Fm17n-lib-cs.git diff --git a/MInputMethod.cs b/MInputMethod.cs index 9618135..0670f99 100644 --- a/MInputMethod.cs +++ b/MInputMethod.cs @@ -138,10 +138,11 @@ namespace M17N.Input = new Dictionary (); private static uint keysym_base = 0x200000; private static uint char_mask = ~((uint) KeyModifier.All); - public static Key Reload; + public static readonly Key Reload; static Key () { + keysyms["null"] = 0x00; keysyms["bs"] = keysyms["backspace"] = 0x08; keysyms["tab"] = 0x09; keysyms["lf"] = keysyms["linefeed"] = 0x10; @@ -161,8 +162,7 @@ namespace M17N.Input keymodifiers["altgr"] = KeyModifier.AltGr; keymodifiers["super"] = KeyModifier.Super; keymodifiers["hyper"] = KeyModifier.Hyper; - Reload = new Key (keysym_base); - keysyms["-reload"] = keysym_base++; + Reload = new Key ((MSymbol) "-reload"); } private static uint decode_keysym (MSymbol keysym) @@ -312,7 +312,7 @@ namespace M17N.Input public int ToChar () { - return (int) (key & 0x1FFFFF); + return (key & 0x3FFFFF) <= 0x1FFFFF ? (int) (key & 0x1FFFFF) : -1; } public override string ToString () @@ -321,7 +321,7 @@ namespace M17N.Input MText mt = null; if (c < 0x20) foreach (KeyValuePair kv in keysyms) - if ((uint) c == kv.Value) + if ((key & 0x3FFFFF) == kv.Value) { mt = kv.Key; break; @@ -352,6 +352,9 @@ namespace M17N.Input internal class KeySeq : Xex.TermValue { + private static Xex.Symbol name = "keyseq"; + public static Xex.Symbol Name { get { return name; } } + public List keyseq = new List (); public override Xex.TermValue Clone () @@ -393,7 +396,7 @@ namespace M17N.Input if (list[i].IsInt) keyseq.Add (new Key (list[i].Intval)); else if (list[i].IsStr) - keyseq.Add (new Key (list[i].Strval)); + keyseq.Add (new Key (list[i].Strval.ToString ())); else if (list[i].IsSymbol) keyseq.Add (new Key ((string) list[i].Symval)); else @@ -401,13 +404,33 @@ namespace M17N.Input } } - public static Xex.TermValue parser (Xex.Domain domain, XmlNode node) + public static Xex.TermValue Parser (Xex.Domain domain, XmlNode node) { - Xex.Term term = new Xex.Term (domain, node.FirstChild).Eval (domain); - return (term.IsStr ? new KeySeq ((MText) term.Strval) + Xex.Term term = Xex.Parse (domain, node.FirstChild); + term = Xex.Eval (domain, term); + return (term.IsStr ? new KeySeq ((MText) term.Strval.ToString ()) : new KeySeq (term.Listval)); } + public override bool Equals (object obj) + { + KeySeq ks = obj as KeySeq; + if (ks == null || ks.keyseq.Count != keyseq.Count) + return false; + for (int i = 0; i < keyseq.Count; i++) + if (keyseq[i] != ks.keyseq[i]) + return false; + return true; + } + + public override int GetHashCode () + { + int code = 0; + for (int i = 0; i < keyseq.Count; i++) + code ^= keyseq[i].GetHashCode (); + return code; + } + public override string ToString () { MText mt; @@ -468,7 +491,7 @@ namespace M17N.Input if (node.Name == "description") description = parse_description (node); else if (node.Name == "keyseq") - keys.Add ((KeySeq) KeySeq.parser (null, node)); + keys.Add ((KeySeq) KeySeq.Parser (null, node)); } } @@ -519,7 +542,7 @@ namespace M17N.Input object[] parameters = new object[2]; public PluginMethod (Plugin plugin, string name) - : base ((Xex.Symbol) name, 0, -1) + : base ((Xex.Symbol) name, false, 0, -1) { this.plugin = plugin; } @@ -530,8 +553,8 @@ namespace M17N.Input args = (Xex.Term[]) args.Clone (); for (int i = 0; i < args.Length; i++) { - args[i] = args[i].Eval (domain); - if (domain.Thrown) + args[i] = Xex.Eval (domain, args[i]); + if (domain.Thrown ()) return args[i]; } if (method_info == null) @@ -544,18 +567,21 @@ namespace M17N.Input internal abstract class Marker : Xex.TermValue { - private MSymbol name; + private static Xex.Symbol name = "marker"; + public static Xex.Symbol Name { get { return name; } } - private Marker (MSymbol name) + private MSymbol mname; + + private Marker (MSymbol mname) { - this.name = name; + this.mname = mname; } public abstract int Position (Context ic); public virtual void Mark (Context ic) { - throw new Exception ("Can't set predefined marker: " + name); + throw new Exception ("Can't set predefined marker: " + mname); } public virtual int CharAt (Context ic) { @@ -567,27 +593,36 @@ namespace M17N.Input public override string ToString () { - return "" + name.Name + ""; + return "" + mname + ""; } - public static Xex.TermValue parser (Xex.Domain domain, XmlNode node) + public static Xex.TermValue Parser (Xex.Domain domain, XmlNode node) { return Get ((MSymbol) node.InnerText); } + + public override bool Equals (object obj) + { + Marker m = obj as Marker; + return (m != null && m.mname == mname); + } + + public override int GetHashCode () { return mname.GetHashCode (); } + public class Named : Marker { - public Named (MSymbol name) : base (name) { } + public Named (MSymbol mname) : base (mname) { } public override int Position (Context ic) { - MPlist p = ic.marker_positions.Find (name); + MPlist p = ic.marker_positions.Find (mname); return (p == null ? 0 : p.Integer); } public override void Mark (Context ic) { - ic.marker_positions.Put (name, ic.cursor_pos); + ic.marker_positions.Put (mname, ic.cursor_pos); } } @@ -632,10 +667,10 @@ namespace M17N.Input { private int pos; - public PredefinedAbsolute (MSymbol name) : base (name) + public PredefinedAbsolute (MSymbol mname) : base (mname) { - if (! int.TryParse (((string) name).Substring (1), out pos)) - throw new Exception ("Invalid marker name: " + name); + if (! int.TryParse (((string) mname).Substring (1), out pos)) + throw new Exception ("Invalid marker name: " + mname); } public override int Position (Context ic) @@ -648,10 +683,10 @@ namespace M17N.Input { private int distance; - public PredefinedSurround (MSymbol name) : base (name) + public PredefinedSurround (MSymbol mname) : base (mname) { - if (! int.TryParse (((string) name).Substring (2), out distance)) - throw new Exception ("Invalid marker name: " + name); + if (! int.TryParse (((string) name).Substring (1), out distance)) + throw new Exception ("Invalid marker name: " + mname); if (distance > 0) distance--; } @@ -687,24 +722,24 @@ namespace M17N.Input = new Predefined (']'); } - public static Marker Get (MSymbol name) + public static Marker Get (MSymbol mname) { - string str = name.Name; + string str = mname.Name; if (str[0] == '@') { Predefined pred; - if (predefineds.TryGetValue (name, out pred)) + if (predefineds.TryGetValue (mname, out pred)) return pred; if (str.Length == 1) - throw new Exception ("Invalid marker name: " + name); + throw new Exception ("Invalid marker name: " + mname); if (Char.IsDigit (str[1])) - return new PredefinedAbsolute (name); - if (str.Length == 2 || name == Mat_minus_zero + return new PredefinedAbsolute (mname); + if (str.Length == 2 || mname == Mat_minus_zero || ! (str[1] == '-' || str[1] == '+')) - throw new Exception ("Invalid marker name: " + name); - return new PredefinedSurround (name); + throw new Exception ("Invalid marker name: " + mname); + return new PredefinedSurround (mname); } - return new Named (name); + return new Named (mname); } } @@ -719,13 +754,13 @@ namespace M17N.Input { Index = index; if (term.IsStr) - Data = (MText) term.Strval; + Data = (MText) term.Strval.ToString (); else { MPlist plist = new MPlist (); MPlist p = plist; foreach (Xex.Term t in term.Listval) - p = p.Add (MSymbol.mtext, (MText) t.Strval); + p = p.Add (MSymbol.mtext, (MText) t.Strval.ToString ()); Data = plist; } } @@ -992,19 +1027,22 @@ namespace M17N.Input internal class Selector : Xex.TermValue { - static new Dictionary selectors; + private static Xex.Symbol name = "selector"; + public static Xex.Symbol Name { get { return name; } } + + static Dictionary selectors; static Selector () { selectors = new Dictionary (); - selectors ["@<"] = selectors["@first"] = new Selector ('<'); - selectors ["@="] = selectors["@current"] = new Selector ('='); - selectors ["@>"] = selectors["@last"] = new Selector ('>'); - selectors ["@-"] = selectors["@previous"] = new Selector ('-'); - selectors ["@+"] = selectors["@next"] = new Selector ('+'); - selectors ["@["] = selectors["@previous-candidate-change"] + selectors["@<"] = selectors["@first"] = new Selector ('<'); + selectors["@="] = selectors["@current"] = new Selector ('='); + selectors["@>"] = selectors["@last"] = new Selector ('>'); + selectors["@-"] = selectors["@previous"] = new Selector ('-'); + selectors["@+"] = selectors["@next"] = new Selector ('+'); + selectors["@["] = selectors["@previous-candidate-change"] = new Selector ('['); - selectors ["@]"] = selectors["@next-candidate-change"] + selectors["@]"] = selectors["@next-candidate-change"] = new Selector (']'); } @@ -1014,7 +1052,7 @@ namespace M17N.Input private Selector (char tag) { this.tag = tag; } - public static Xex.TermValue parser (Xex.Domain domain, XmlNode node) + public static Xex.TermValue Parser (Xex.Domain domain, XmlNode node) { return Get ((MSymbol) node.InnerText); } @@ -1026,6 +1064,19 @@ namespace M17N.Input throw new Exception ("Invalid selector name: " + name); return selector; } + + public override bool Equals (object obj) + { + Selector s = obj as Selector; + return (s != null && s.tag == tag); + } + + public override int GetHashCode () { return (int) tag; } + + public override string ToString () + { + return "@" + tag + ""; + } } internal class Map @@ -1056,6 +1107,31 @@ namespace M17N.Input } } + protected class Action + { + private Xex.Term action; + + public Action (Xex.Domain domain, Xex.Term[] terms) + { + Xex.Term[] args = new Xex.Term[terms.Length]; + args[0] = Tcatch_tag; + for (int i = 0; i < terms.Length; i++) + args[i + 1] = terms[i]; + action = new Xex.Term (domain, Qcatch, args); + } + + public bool Run (Xex.Domain domain) + { + Xex.Term result = Xex.Eval (domain, action); + if (result.IsError) + { + ((Context) domain.context).Error = result.ToString (); + return false; + } + return (result != Tcatch_tag); + } + } + internal class Keymap { public Dictionary submaps; @@ -1165,16 +1241,16 @@ namespace M17N.Input for (node = node.FirstChild; node != null; node = node.NextSibling) { if (node.Name == Qstate_hook) - enter_actions = Xex.ParseTerms (im.domain, node.FirstChild); + enter_actions = Xex.Parse (im.domain, node.FirstChild, null); else if (node.Name == Qcatch_all_branch) - fallback_actions = Xex.ParseTerms (im.domain, node.FirstChild); + fallback_actions = Xex.Parse (im.domain, node.FirstChild, null); else if (node.Name == Qbranch) { MSymbol mapname = node.Attributes[Qmname].Value; Map map; if (im.maps.TryGetValue (mapname, out map)) - keymap.AddMap (map, Xex.ParseTerms (im.domain, - node.FirstChild)); + keymap.AddMap (map, Xex.Parse (im.domain, node.FirstChild, + null)); else throw new Exception ("Unknown map: " + mapname); } @@ -1246,9 +1322,9 @@ namespace M17N.Input static MInputMethod () { - im_domain.DefTerm ("keyseq", KeySeq.parser); - im_domain.DefTerm ("marker", Marker.parser); - im_domain.DefTerm ("selector", Selector.parser); + im_domain.DefType (typeof (KeySeq)); + im_domain.DefType (typeof (Marker)); + im_domain.DefType (typeof (Selector)); im_domain.DefSubr (Finsert, "insert", false, 1, 1); im_domain.DefSubr (Finsert_candidates, "insert-candidates", false, 1, -1); @@ -1312,7 +1388,7 @@ namespace M17N.Input variables = new Xex.Variable[var_names.Length]; int i = 0; foreach (Xex.Symbol name in var_names) - variables[i++] = domain.GetVar (name, false); + variables[i++] = domain.GetVar (name); } commands = this.commands; return true; @@ -1543,7 +1619,7 @@ namespace M17N.Input if (! im_global.Open ()) throw new Exception ("Failed to load global"); } - return im_global.domain.GetVar (name, false); + return im_global.domain.GetVar (name); } private void parse_variables (MPlist plist) @@ -1651,7 +1727,7 @@ namespace M17N.Input Xex.Variable vari = get_global_var (name); if (vari != null) domain.Defvar (vari); - domain.Defvar (node_list[i]); + Xex.Parse (domain, node_list[i]); var_names[i] = name; } } @@ -1739,17 +1815,13 @@ namespace M17N.Input private void parse_macros (XmlNode node) { for (XmlNode nn = node.FirstChild; nn != null; nn = nn.NextSibling) - if (nn.NodeType == XmlNodeType.Element) - { - if (nn.Name == Xex.Qdefun) - domain.Defun (nn, true); - else if (nn.Name == Qxi_include) + if (nn.NodeType == XmlNodeType.Element && nn.Name == Qxi_include) + { parse_include (nn); - } - for (XmlNode nn = node.FirstChild; nn != null; nn = nn.NextSibling) - if (nn.NodeType == XmlNodeType.Element - && nn.Name == Xex.Qdefun) - domain.Defun (nn, false); + nn = nn.PreviousSibling; + node.RemoveChild (nn.NextSibling); + } + Xex.Parse (domain, node.FirstChild, null); } private void parse_maps (XmlNode node) @@ -1768,8 +1840,9 @@ namespace M17N.Input XmlNode n = nd.FirstChild; if (n.Name != Qkeyseq) continue; - KeySeq keyseq = (KeySeq) KeySeq.parser (domain, n); - Xex.Term[] actions = Xex.ParseTerms (domain, n.NextSibling); + KeySeq keyseq = (KeySeq) KeySeq.Parser (domain, n); + n = n.NextSibling; + Xex.Term[] actions = Xex.Parse (domain, n, null); map.entries.Add (new Map.Entry (domain, keyseq, actions)); } } @@ -2065,17 +2138,16 @@ namespace M17N.Input MPlist p = pl.Plist; if (! p.IsSymbol) continue; - domain.Defun ((Xex.Symbol) p.Symbol.Name, null, null, true); + domain.Defun ((Xex.Symbol) p.Symbol.Name, 0, 0, null, null); } for (MPlist pl = plist; ! pl.IsEmpty; pl = pl.next) if (pl.IsPlist) { MPlist p = pl.Plist; - if (! p.IsSymbol) continue; - domain.Defun ((Xex.Symbol) p.Symbol.Name, null, - parse_actions (p.next, false), false); + domain.Defun ((Xex.Symbol) p.Symbol.Name, 0, 0, null, + parse_actions (p.next, false)); } } @@ -2116,7 +2188,8 @@ namespace M17N.Input if (args[0].IsInt) ((Context) domain.context).insert (args[0].Intval, null); else - ((Context) domain.context).insert ((MText) args[0].Strval, null); + ((Context) domain.context).insert ((MText) args[0].Strval.ToString (), + null); return args[0]; } @@ -2125,8 +2198,8 @@ namespace M17N.Input Xex.Term[] args) { Context ic = (Context) domain.context; - Xex.Variable v = ic.domain.GetVar (Qcandidates_group_size, false); - int column = (v == null ? 0 : v.Value.Intval); + Xex.Variable v = ic.domain.GetVar (Qcandidates_group_size); + int column = v == null ? 0 : v.Value.Intval; Candidates candidates = new Candidates (args, column); object candidate = candidates.Current; @@ -2228,7 +2301,7 @@ namespace M17N.Input if (args[0].IsInt) ic.pushback (args[0].Intval); else if (args[0].IsStr) - ic.pushback (new KeySeq (args[0].Strval)); + ic.pushback (new KeySeq (args[0].Strval.ToString ())); else ic.pushback ((KeySeq) args[0].Objval); return args[0]; @@ -2260,9 +2333,7 @@ namespace M17N.Input Xex.Term[] args) { ((Context) domain.context).commit (); - args = new Xex.Term[2]; - args[0] = args[1] = Tcatch_tag; - return Xex.Fthrow (domain, vari, args); + return Xex.Fthrow (domain, vari, new Xex.Term[1] { Tcatch_tag }); } private static Xex.Term Fshift (Xex.Domain domain, Xex.Variable vari, @@ -2379,6 +2450,12 @@ namespace M17N.Input internal ChangedStatus changed; + private string error_message; + public string Error { + get { return error_message; } + set { error_message = value; } + } + private void set_cursor (string prefix, int pos) { cursor_pos = pos; @@ -2419,7 +2496,7 @@ namespace M17N.Input catch_args[0] = Tcatch_tag; catch_args[1]= new Xex.Term (domain, Qprogn, actions); Xex.Term term = new Xex.Term (domain, Qcatch, catch_args); - term = term.Eval (domain); + term = Xex.Eval (domain, term); return (! term.IsSymbol || term.Symval != Tcatch_tag.Symval); } @@ -2519,6 +2596,7 @@ namespace M17N.Input { if (DelSurroundingText != null) { + Console.WriteLine ("deleting the prev {0} chars", - pos); callback_arg.Set (MSymbol.integer, pos); if (DelSurroundingText (this, callback_arg)) { @@ -2540,6 +2618,8 @@ namespace M17N.Input { if (DelSurroundingText != null) { + Console.WriteLine ("deleting the next {0} chars", + pos - preedit.Length); callback_arg.Set (MSymbol.integer, pos - preedit.Length); if (DelSurroundingText (this, callback_arg)) { @@ -2630,9 +2710,12 @@ namespace M17N.Input internal void commit () { - Candidates.Detach (this); - produced.Cat (preedit); - preedit_replace (0, preedit.Length, null, null); + if (preedit.Length > 0) + { + Candidates.Detach (this); + produced.Cat (preedit); + preedit_replace (0, preedit.Length, null, null); + } } internal void shift (State state) @@ -2674,7 +2757,7 @@ namespace M17N.Input { if (im.load_status != LoadStatus.Full && ! im.Open ()) - throw new Exception ("Openging " + im.tag + " failed"); + throw new Exception ("Opening " + im.tag + " failed"); this.im = im; domain = new Xex.Domain ("context", im.domain, this); initial_state = (State) im.states.Val; @@ -2727,8 +2810,7 @@ namespace M17N.Input private bool handle_key () { - Console.WriteLine ("{0}:key='{1}'", state.name, - new MText (keys.keyseq[key_head].ToChar ())); + Console.WriteLine ("{0}:key='{1}'", state.name, keys.keyseq[key_head]); Keymap sub = keymap.Lookup (keys, ref key_head); if (sub != keymap) @@ -2852,6 +2934,34 @@ namespace M17N.Input } return (! key_unhandled && produced.Length == 0); } + + public bool Filter () + { + changed = ChangedStatus.None; + produced.Del (); + preceding_text.Del (); + following_text.Del (); + + commit (); + 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 (produced.Length == 0); + } } public class Session @@ -2882,6 +2992,7 @@ namespace M17N.Input private bool del_surrounding_text (Context ic, MPlist args) { int pos = this.pos + args.Integer; + Console.WriteLine ("del-surround: {0}-{1}", this.pos, pos); if (pos < this.pos) { mt.Del (pos, this.pos); @@ -2892,25 +3003,37 @@ namespace M17N.Input return true; } - public bool HandleKey (Key key) + public bool HandleKey (ref Key key) { - bool result = ic.Filter (key); - - if (! result) + if (! ic.Filter (key)) { MText produced = ic.Produced; mt.Ins (pos, produced); pos += produced.Length; - if (ic.UnhandledKey (out key)) + Key unhandled; + if (ic.UnhandledKey (out unhandled)) { - mt.Ins (pos, key.ToChar ()); - pos++; + key = unhandled; + return false; } } + return true; + } + + public bool Close () + { + bool result = ic.Filter (); + if (! result) + { + mt.Ins (pos, ic.Produced); + pos += ic.Produced.Length; + } + ic = null; + mt = null; return result; } - public int CurrentPos { get { return pos; } } + public int CurrentPos { get { return pos; } set { pos = value; } } public MText Preedit { get { return ic.Preedit; } } } }