From: handa Date: Thu, 15 Oct 2009 12:54:19 +0000 (+0000) Subject: *** empty log message *** X-Git-Url: http://git.chise.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2a6d904273f074ce782a4fdcbc42dc1aaa579923;p=m17n%2Fm17n-lib-cs.git *** empty log message *** --- diff --git a/MInputMethod.cs b/MInputMethod.cs index c2da081..f2fe910 100644 --- a/MInputMethod.cs +++ b/MInputMethod.cs @@ -106,720 +106,721 @@ namespace M17N.Input private static ChangedStatus CandidateAll = (ChangedStatus.CandidateList | ChangedStatus.CandidateIndex | ChangedStatus.CandidateShow); - [FlagsAttribute] - public enum KeyModifier - { - None = 0x00000000, - Shift_L = 0x00400000, - Shift_R = 0x00800000, - Shift = 0x00C00000, - Control_L = 0x01000000, - Control_R = 0x02000000, - Control = 0x03000000, - Alt_L = 0x04000000, - Alt_R = 0x08000000, - Alt = 0x0C000000, - AltGr = 0x10000000, - Super = 0x20000000, - Hyper = 0x40000000, - High = 0x70000000, - All = 0x7FC00000, - }; - - public struct Key - { - internal uint key; - - private static Dictionary keysyms - = new Dictionary (); - private static Dictionary keymodifiers - = new Dictionary (); - private static uint keysym_base = 0x200000; - private static uint char_mask = ~((uint) KeyModifier.All); - public static Key Reload; - - static Key () - { - keysyms["bs"] = keysyms["backspace"] = 0x08; - keysyms["tab"] = 0x09; - keysyms["lf"] = keysyms["linefeed"] = 0x10; - keysyms["cr"] = keysyms["return"] = keysyms["enter"] = 0x13; - keysyms["esc"] = keysyms["escape"] = 0x1B; - keysyms["spc"] = keysyms["space"] = 0x20; - keysyms["del"] = keysyms["delete"] = 0x7F; - keymodifiers["shift-l"] = KeyModifier.Shift_L; - keymodifiers["shift-r"] = KeyModifier.Shift_R; - keymodifiers["shift"] = KeyModifier.Shift; - keymodifiers["control-l"] = KeyModifier.Control_L; - keymodifiers["control-r"] = KeyModifier.Control_R; - keymodifiers["control"] = KeyModifier.Control; - keymodifiers["alt-l"] = KeyModifier.Alt_L; - keymodifiers["alt-r"] = KeyModifier.Alt_R; - keymodifiers["alt"] = KeyModifier.Alt; - 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) - { - uint key; - string name = keysym.Name; - - if (name.Length == 1) - return name[0]; - name = name.ToLower (); - if (! keysyms.TryGetValue (name, out key)) - keysyms[name] = key = keysym_base++; - return key; - } - - private static uint combine_modifiers (uint c, KeyModifier modifiers) - { - if (c < 0x7F && c != 0x20) - { - if ((modifiers & KeyModifier.Shift) != KeyModifier.None - && Char.IsLower ((char) c)) - { - modifiers &= ~KeyModifier.Shift; - c = Char.ToUpper ((char) c); - } - if ((modifiers & KeyModifier.Control) != KeyModifier.None) - { - modifiers &= ~KeyModifier.Control; - c &= 0x1F; - } - } - return c | (uint) modifiers; - } - - public Key (uint c) { key = c; } - public Key (int c) { key = (uint) c; } - - public Key (uint c, KeyModifier modifiers) - { - key = combine_modifiers (c, modifiers); - } - - public Key (MSymbol keysym, KeyModifier modifiers) - { - key = combine_modifiers (decode_keysym (keysym), modifiers); - } - - public Key (MSymbol keysym) - { - string str = keysym.Name; - int len = str.Length; - int i; - KeyModifier modifiers = KeyModifier.None; - - for (i = 0; i + 2 < len && str[i + 1] == '-'; i += 2) - { - if (str[i] == 'S') - modifiers |= KeyModifier.Shift; - else if (str[i] == 'C') - modifiers |= KeyModifier.Control; - else if (str[i] == 'A') - modifiers |= KeyModifier.Alt; - else if (str[i] == 'G') - modifiers |= KeyModifier.AltGr; - else if (str[i] == 's') - modifiers |= KeyModifier.Super; - else if (str[i] == 'H') - modifiers |= KeyModifier.Hyper; - } - if (i + 1 == len) - key = combine_modifiers (str[i], modifiers); - else - key = combine_modifiers (decode_keysym (keysym), modifiers); - } - - public Key (MPlist plist) - { - KeyModifier modifiers = KeyModifier.None; - MPlist p; - - for (p = plist; ! p.IsEmpty; p = p.next) - { - if (p.IsInteger) - { - if (! p.next.IsEmpty) - throw new Exception ("Invalid Key: " + plist); - break; - } - else if (! p.IsSymbol) - throw new Exception ("Invalid Key: " + plist); - else - { - string name = p.Symbol.Name.ToLower (); - KeyModifier m; - - if (! keymodifiers.TryGetValue (name, out m)) - break; - modifiers |= m; - } - } - if (p.IsEmpty || ! p.next.IsEmpty) - throw new Exception ("Invalid Key: " + plist); - if (p.IsInteger) - key = combine_modifiers ((uint) p.Integer, modifiers); - else - key = combine_modifiers (decode_keysym (p.Symbol), modifiers); - } - - public bool HasModifier - { - 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) - return true; - if ((k.key & char_mask) != (key & char_mask)) - return false; - KeyModifier m1 = ((KeyModifier) key) & KeyModifier.All; - KeyModifier m2 = ((KeyModifier) k.key) & KeyModifier.All; - return (((m1 & KeyModifier.Shift) == (m2 & KeyModifier.Shift) - || ((m1 & KeyModifier.Shift) == KeyModifier.Shift - && (m2 & KeyModifier.Shift) != KeyModifier.None)) - && ((m1 & KeyModifier.Control) == (m2 & KeyModifier.Control) - || ((m1 & KeyModifier.Control) == KeyModifier.Control - && (m2 & KeyModifier.Control) != KeyModifier.None)) - && ((m1 & KeyModifier.Alt) == (m2 & KeyModifier.Alt) - || ((m1 & KeyModifier.Alt) == KeyModifier.Alt - && (m2 & KeyModifier.Alt) != KeyModifier.None)) - && ((m1 & KeyModifier.High) == (m2 & KeyModifier.High))); - } - - public int ToChar () - { - return (int) (key & 0x1FFFFF); - } - - public override string ToString () - { - int c = ToChar (); - MText mt = null; - if (c < 0x20) - foreach (KeyValuePair kv in keysyms) - if ((uint) c == kv.Value) - { - mt = kv.Key; - break; - } - if (mt == null) - mt = new MText (c); - - KeyModifier m = ((KeyModifier) key) & KeyModifier.All; - - if (m != KeyModifier.None) - { - if ((m & KeyModifier.Shift) != KeyModifier.None) - mt.Ins (0, "S-"); - if ((m & KeyModifier.Control) != KeyModifier.None) - mt.Ins (0, "C-"); - if ((m & KeyModifier.Alt) != KeyModifier.None) - mt.Ins (0, "A-"); - if ((m & KeyModifier.AltGr) != KeyModifier.None) - mt.Ins (0, "G-"); - if ((m & KeyModifier.Super) != KeyModifier.None) - mt.Ins (0, "s-"); - if ((m & KeyModifier.Hyper) != KeyModifier.None) - mt.Ins (0, "H-"); - } - return (string) mt; - } - } - - internal class KeySeq : Xex.TermValue - { - public List keyseq = new List (); - - public override Xex.TermValue Clone () - { - KeySeq ks = new KeySeq (); - ks.keyseq.InsertRange (0, keyseq); - return ks; - } - - public KeySeq () { } - - public KeySeq (MPlist plist) - { - foreach (MPlist p in plist) - { - if (p.IsSymbol) - keyseq.Add (new Key (p.Symbol)); - else if (p.IsInteger) - keyseq.Add (new Key ((char) p.Integer)); - else if (p.IsPlist) - keyseq.Add (new Key (p.Plist)); - else - throw new Exception ("Invalid Key Sequence: " + plist); - } - } - - public KeySeq (MText mt) : base () - { - for (int i = 0; i < mt.Length; i++) - keyseq.Add (new Key ((uint) mt[i])); - } - - public KeySeq (List list) - { - int len = list.Count; - - for (int i = 0; i < len; i++) - { - if (list[i].IsInt) - keyseq.Add (new Key (list[i].Intval)); - else if (list[i].IsStr) - keyseq.Add (new Key (list[i].Strval)); - else if (list[i].IsSymbol) - keyseq.Add (new Key ((string) list[i].Symval)); - else - throw new Exception ("Invalid key: " + list[i]); - } - } - - 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) - : new KeySeq (term.Listval)); - } - - public override string ToString () - { - MText mt; - foreach (Key key in keyseq) - if (key.HasModifier || key.ToChar () < 0x20) - { - mt = "("; - foreach (Key k in keyseq) - { - if (mt.Length > 1) - mt.Cat (' '); - mt.Cat (k.ToString ()); - } - return (string) mt.Cat (")"); - } - mt = "\""; - foreach (Key k in keyseq) - { - int c = k.ToChar (); - - if (c == '\\' || c == '"') - mt.Cat ('\\'); - mt.Cat (c); - } - return (string) mt.Cat ("\""); - } - } - - public class Command - { - public MSymbol name; - public MText description; - internal List keys; - - public Command (MPlist p) - { - name = p.Symbol; - p = p.Next; - description = parse_description (p); - if (description == null) - description = "No description"; - keys = new List (); - for (p = p.next; ! p.IsEmpty; p = p.next) - { - if (p.IsMText) - keys.Add (new KeySeq (p.Text)); - else if (p.IsPlist) - keys.Add (new KeySeq (p.Plist)); - } - } - - public Command (XmlNode node) - { - name = node.Attributes[0].Value; - keys = new List (); - for (node = node.FirstChild; node != null; node = node.NextSibling) - { - if (node.Name == "description") - description = parse_description (node); - else if (node.Name == "keyseq") - keys.Add ((KeySeq) KeySeq.parser (null, node)); - } - } - - public override string ToString () - { - string str = "(" + name + " \"" + (string) description; - foreach (KeySeq keyseq in keys) - str += " " + keyseq; - return str + ")"; - } - } - - internal class Plugin - { - private string name; - private Assembly assembly; - private Type plugin_type; - - public Plugin (string name) - { - this.name = name; - } - - public MethodInfo GetMethod (Xex.Symbol name) - { - if (assembly == null) - { - assembly = Assembly.LoadFrom (name + ".dll"); - plugin_type = assembly.GetType ("M17n.MInputMethod.Plugin"); - } - - MethodInfo info = plugin_type.GetMethod ((string) name); - if (info == null) - throw new Exception ("Invalid plugin method: " + name); - return info; - } - - public override string ToString () - { - return String.Format ("(module {0}", name); - } - } - - internal class PluginMethod : Xex.Function - { - private Plugin plugin; - private MethodInfo method_info; - object[] parameters = new object[2]; - - public PluginMethod (Plugin plugin, string name) - : base ((Xex.Symbol) name, 0, -1) - { - this.plugin = plugin; - } - - public override Xex.Term Call (Xex.Domain domain, Xex.Variable vari, - Xex.Term[] args) - { - args = (Xex.Term[]) args.Clone (); - for (int i = 0; i < args.Length; i++) - { - args[i] = args[i].Eval (domain); - if (domain.Thrown) - return args[i]; - } - if (method_info == null) - method_info = plugin.GetMethod (name); - parameters[0] = domain.context; - parameters[1] = args; - return (Xex.Term) method_info.Invoke (null, parameters); - } - } - - internal abstract class Marker : Xex.TermValue - { - private MSymbol name; - - private Marker (MSymbol name) - { - this.name = name; - } - - public abstract int Position (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 string ToString () - { - return "" + name.Name + ""; - } - - public static Xex.TermValue parser (Xex.Domain domain, XmlNode node) - { - return Get ((MSymbol) node.InnerText); - } - - public class Named : Marker - { - public Named (MSymbol name) : base (name) { } - - public override int Position (Context ic) - { - MPlist p = ic.marker_positions.Find (name); - return (p == null ? 0 : p.Integer); - } - - public override void Mark (Context ic) - { - ic.marker_positions.Put (name, ic.cursor_pos); - } - } - - public class Predefined : Marker - { - char tag; - - public Predefined (MSymbol name) : base (name) - { - tag = ((string) name)[1]; - } - - public override int Position (Context ic) - { - switch (tag) { - case '<': return 0; - case '>': return ic.preedit.Length; - case '-': return ic.cursor_pos - 1; - case '+': return ic.cursor_pos + 1; - case '[': - if (ic.cursor_pos > 0) - { - int pos = ic.cursor_pos; - int to; - ic.preedit.FindProp (Mcandidates, pos - 1, out pos, out to); - return pos; - } - return 0; - case ']': - if (ic.cursor_pos < ic.preedit.Length - 1) - { - int pos = ic.cursor_pos; - int from; - ic.preedit.FindProp (Mcandidates, pos, out from, out pos); - return pos; - } - return ic.preedit.Length; - default: - return tag - '0'; - } - } - } - - public class PredefinedAbsolute : Marker - { - private int pos; - - public PredefinedAbsolute (MSymbol name) : base (name) - { - if (! int.TryParse (((string) name).Substring (1), out pos)) - throw new Exception ("Invalid marker name: " + name); - } - - public override int Position (Context ic) - { - return (pos < ic.preedit.Length ? pos : ic.preedit.Length); - } - } - - public class PredefinedSurround : Marker - { - private int distance; - - public PredefinedSurround (MSymbol name) : base (name) - { - if (! int.TryParse (((string) name).Substring (2), out distance)) - throw new Exception ("Invalid marker name: " + name); - if (distance > 0) - distance--; - } - - public override int Position (Context ic) - { - 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; - - static Marker () - { - predefined_markers = new Dictionary (); - MSymbol[] symlist = new MSymbol[] {"@<", "@>", "@-", "@+", "@[", "@]" }; - foreach (MSymbol s in symlist) - predefined_markers[s] = new Predefined (s); - } - - public static Marker Get (MSymbol name) - { - string str = name.Name; - if (str[0] == '@') - { - Predefined pred; - if (predefined_markers.TryGetValue (name, out pred)) - return pred; - if (str.Length == 1) - throw new Exception ("Invalid marker name: " + name); - if (Char.IsDigit (str[1])) - return new PredefinedAbsolute (name); - if (str.Length == 2 || name == Mat_minus_zero - || ! (str[1] == '-' || str[1] == '+')) - throw new Exception ("Invalid marker name: " + name); - return new PredefinedSurround (name); - } - return new Named (name); - } - } - - internal class Candidates - { - private class Block - { - public int Index; - public object Data; - - public Block (int index, Xex.Term term) - { - Index = index; - if (term.IsStr) - Data = (MText) term.Strval; - else - { - MPlist plist = new MPlist (); - MPlist p = plist; - foreach (Xex.Term t in term.Listval) - p = p.Add (MSymbol.mtext, (MText) t.Strval); - Data = plist; - } - } - public Block (int index, MPlist plist) - { - Index = index; - if (plist.IsMText) - Data = plist.Text; - else if (plist.IsPlist) - Data = plist.Plist; - else - throw new Exception ("Invalid candidate: " + plist); - } - - public int Count - { - get { return (Data is MText - ? ((MText) Data).Length - : ((MPlist) Data).Count); } - } - - public object this[int i] - { - get { - if (Data is MText) return ((MText) Data)[i]; - return ((MPlist) Data)[i]; - } - } - } - - private Block[] blocks; - private int row = 0; - private int index = 0; - public object[] group; - - private bool IsFixed { get { return group != null; } } - private int Total { - get { - Block last = blocks[blocks.Length - 1]; - return last.Index + last.Count; } - } - - public int Column { - get { return (IsFixed ? index % group.Length - : index - blocks[row].Index); } - } - - public object Group { - get { return (IsFixed ? group : blocks[row].Data); } - } - - public int GroupLength - { - get { - if (IsFixed) - { - int nitems = group.Length; - int start = index - (index % nitems); - int total = Total; - return (start + nitems <= total ? nitems : total - start); - } - return blocks[row].Count; - } - } - - public object Current { - get { - return (IsFixed ? group[index % group.Length] - : blocks[row][index - blocks[row].Index]); - } - } - - public Candidates (MPlist list, int column) - { - int nblocks = list.Count; - - blocks = new Block[nblocks]; - for (int i = 0, start = 0; i < nblocks; i++, list = list.next) - start += (blocks[i] = new Block (index, list)).Count; - if (column > 0) - group = new object[column]; - } - - public Candidates (Xex.Term[] candidates, int column) - { - int nblocks = candidates.Length; - - blocks = new Block[nblocks]; - for (int i = 0, start = 0; i < nblocks; i++) - start += (blocks[i] = new Block (index, candidates[i])).Count; - if (column > 0) - group = new object[column]; - } - - public static void Detach (Context ic) - { - ic.preedit.PopProp (0, ic.preedit.Length, Mcandidates); - ic.candidates = null; - ic.changed |= (ChangedStatus.Preedit | ChangedStatus.CursorPos - | CandidateAll); + [FlagsAttribute] + public enum KeyModifier + { + None = 0x00000000, + Shift_L = 0x00400000, + Shift_R = 0x00800000, + Shift = 0x00C00000, + Control_L = 0x01000000, + Control_R = 0x02000000, + Control = 0x03000000, + Alt_L = 0x04000000, + Alt_R = 0x08000000, + Alt = 0x0C000000, + AltGr = 0x10000000, + Super = 0x20000000, + Hyper = 0x40000000, + High = 0x70000000, + All = 0x7FC00000, + }; + + public struct Key + { + internal uint key; + + private static Dictionary keysyms + = new Dictionary (); + private static Dictionary keymodifiers + = new Dictionary (); + private static uint keysym_base = 0x200000; + private static uint char_mask = ~((uint) KeyModifier.All); + public static Key Reload; + + static Key () + { + keysyms["bs"] = keysyms["backspace"] = 0x08; + keysyms["tab"] = 0x09; + keysyms["lf"] = keysyms["linefeed"] = 0x10; + keysyms["cr"] = keysyms["return"] = keysyms["enter"] = 0x13; + keysyms["esc"] = keysyms["escape"] = 0x1B; + keysyms["spc"] = keysyms["space"] = 0x20; + keysyms["del"] = keysyms["delete"] = 0x7F; + keymodifiers["shift-l"] = KeyModifier.Shift_L; + keymodifiers["shift-r"] = KeyModifier.Shift_R; + keymodifiers["shift"] = KeyModifier.Shift; + keymodifiers["control-l"] = KeyModifier.Control_L; + keymodifiers["control-r"] = KeyModifier.Control_R; + keymodifiers["control"] = KeyModifier.Control; + keymodifiers["alt-l"] = KeyModifier.Alt_L; + keymodifiers["alt-r"] = KeyModifier.Alt_R; + keymodifiers["alt"] = KeyModifier.Alt; + 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) + { + uint key; + string name = keysym.Name; + + if (name.Length == 1) + return name[0]; + name = name.ToLower (); + if (! keysyms.TryGetValue (name, out key)) + keysyms[name] = key = keysym_base++; + return key; + } + + private static uint combine_modifiers (uint c, KeyModifier modifiers) + { + if (c < 0x7F && c != 0x20) + { + if ((modifiers & KeyModifier.Shift) != KeyModifier.None + && Char.IsLower ((char) c)) + { + modifiers &= ~KeyModifier.Shift; + c = Char.ToUpper ((char) c); + } + if ((modifiers & KeyModifier.Control) != KeyModifier.None) + { + modifiers &= ~KeyModifier.Control; + c &= 0x1F; + } + } + return c | (uint) modifiers; + } + + public Key (uint c) { key = c; } + public Key (int c) { key = (uint) c; } + + public Key (uint c, KeyModifier modifiers) + { + key = combine_modifiers (c, modifiers); + } + + public Key (MSymbol keysym, KeyModifier modifiers) + { + key = combine_modifiers (decode_keysym (keysym), modifiers); + } + + public Key (MSymbol keysym) + { + string str = keysym.Name; + int len = str.Length; + int i; + KeyModifier modifiers = KeyModifier.None; + + for (i = 0; i + 2 < len && str[i + 1] == '-'; i += 2) + { + if (str[i] == 'S') + modifiers |= KeyModifier.Shift; + else if (str[i] == 'C') + modifiers |= KeyModifier.Control; + else if (str[i] == 'A') + modifiers |= KeyModifier.Alt; + else if (str[i] == 'G') + modifiers |= KeyModifier.AltGr; + else if (str[i] == 's') + modifiers |= KeyModifier.Super; + else if (str[i] == 'H') + modifiers |= KeyModifier.Hyper; + } + if (i + 1 == len) + key = combine_modifiers (str[i], modifiers); + else + key = combine_modifiers (decode_keysym (keysym), modifiers); + } + + public Key (MPlist plist) + { + KeyModifier modifiers = KeyModifier.None; + MPlist p; + + for (p = plist; ! p.IsEmpty; p = p.next) + { + if (p.IsInteger) + { + if (! p.next.IsEmpty) + throw new Exception ("Invalid Key: " + plist); + break; + } + else if (! p.IsSymbol) + throw new Exception ("Invalid Key: " + plist); + else + { + string name = p.Symbol.Name.ToLower (); + KeyModifier m; + + if (! keymodifiers.TryGetValue (name, out m)) + break; + modifiers |= m; + } + } + if (p.IsEmpty || ! p.next.IsEmpty) + throw new Exception ("Invalid Key: " + plist); + if (p.IsInteger) + key = combine_modifiers ((uint) p.Integer, modifiers); + else + key = combine_modifiers (decode_keysym (p.Symbol), modifiers); + } + + public bool HasModifier + { + 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) + return true; + if ((k.key & char_mask) != (key & char_mask)) + return false; + KeyModifier m1 = ((KeyModifier) key) & KeyModifier.All; + KeyModifier m2 = ((KeyModifier) k.key) & KeyModifier.All; + return (((m1 & KeyModifier.Shift) == (m2 & KeyModifier.Shift) + || ((m1 & KeyModifier.Shift) == KeyModifier.Shift + && (m2 & KeyModifier.Shift) != KeyModifier.None)) + && ((m1 & KeyModifier.Control) == (m2 & KeyModifier.Control) + || ((m1 & KeyModifier.Control) == KeyModifier.Control + && (m2 & KeyModifier.Control) != KeyModifier.None)) + && ((m1 & KeyModifier.Alt) == (m2 & KeyModifier.Alt) + || ((m1 & KeyModifier.Alt) == KeyModifier.Alt + && (m2 & KeyModifier.Alt) != KeyModifier.None)) + && ((m1 & KeyModifier.High) == (m2 & KeyModifier.High))); + } + + public int ToChar () + { + return (int) (key & 0x1FFFFF); + } + + public override string ToString () + { + int c = ToChar (); + MText mt = null; + if (c < 0x20) + foreach (KeyValuePair kv in keysyms) + if ((uint) c == kv.Value) + { + mt = kv.Key; + break; + } + if (mt == null) + mt = new MText (c); + + KeyModifier m = ((KeyModifier) key) & KeyModifier.All; + + if (m != KeyModifier.None) + { + if ((m & KeyModifier.Shift) != KeyModifier.None) + mt.Ins (0, "S-"); + if ((m & KeyModifier.Control) != KeyModifier.None) + mt.Ins (0, "C-"); + if ((m & KeyModifier.Alt) != KeyModifier.None) + mt.Ins (0, "A-"); + if ((m & KeyModifier.AltGr) != KeyModifier.None) + mt.Ins (0, "G-"); + if ((m & KeyModifier.Super) != KeyModifier.None) + mt.Ins (0, "s-"); + if ((m & KeyModifier.Hyper) != KeyModifier.None) + mt.Ins (0, "H-"); + } + return (string) mt; + } + } + + internal class KeySeq : Xex.TermValue + { + public List keyseq = new List (); + + public override Xex.TermValue Clone () + { + KeySeq ks = new KeySeq (); + ks.keyseq.InsertRange (0, keyseq); + return ks; + } + + public KeySeq () { } + + public KeySeq (MPlist plist) + { + foreach (MPlist p in plist) + { + if (p.IsSymbol) + keyseq.Add (new Key (p.Symbol)); + else if (p.IsInteger) + keyseq.Add (new Key ((char) p.Integer)); + else if (p.IsPlist) + keyseq.Add (new Key (p.Plist)); + else + throw new Exception ("Invalid Key Sequence: " + plist); + } + } + + public KeySeq (MText mt) : base () + { + for (int i = 0; i < mt.Length; i++) + keyseq.Add (new Key ((uint) mt[i])); + } + + public KeySeq (List list) + { + int len = list.Count; + + for (int i = 0; i < len; i++) + { + if (list[i].IsInt) + keyseq.Add (new Key (list[i].Intval)); + else if (list[i].IsStr) + keyseq.Add (new Key (list[i].Strval)); + else if (list[i].IsSymbol) + keyseq.Add (new Key ((string) list[i].Symval)); + else + throw new Exception ("Invalid key: " + list[i]); + } + } + + 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) + : new KeySeq (term.Listval)); + } + + public override string ToString () + { + MText mt; + foreach (Key key in keyseq) + if (key.HasModifier || key.ToChar () < 0x20) + { + mt = "("; + foreach (Key k in keyseq) + { + if (mt.Length > 1) + mt.Cat (' '); + mt.Cat (k.ToString ()); + } + return (string) mt.Cat (")"); + } + mt = "\""; + foreach (Key k in keyseq) + { + int c = k.ToChar (); + + if (c == '\\' || c == '"') + mt.Cat ('\\'); + mt.Cat (c); + } + return (string) mt.Cat ("\""); + } + } + + public class Command + { + public MSymbol name; + public MText description; + internal List keys; + + public Command (MPlist p) + { + name = p.Symbol; + p = p.Next; + description = parse_description (p); + if (description == null) + description = "No description"; + keys = new List (); + for (p = p.next; ! p.IsEmpty; p = p.next) + { + if (p.IsMText) + keys.Add (new KeySeq (p.Text)); + else if (p.IsPlist) + keys.Add (new KeySeq (p.Plist)); + } + } + + public Command (XmlNode node) + { + name = node.Attributes[0].Value; + keys = new List (); + for (node = node.FirstChild; node != null; node = node.NextSibling) + { + if (node.Name == "description") + description = parse_description (node); + else if (node.Name == "keyseq") + keys.Add ((KeySeq) KeySeq.parser (null, node)); + } + } + + public override string ToString () + { + string str = "(" + name + " \"" + (string) description; + foreach (KeySeq keyseq in keys) + str += " " + keyseq; + return str + ")"; + } + } + + internal class Plugin + { + private string name; + private Assembly assembly; + private Type plugin_type; + + public Plugin (string name) + { + this.name = name; + } + + public MethodInfo GetMethod (Xex.Symbol name) + { + if (assembly == null) + { + assembly = Assembly.LoadFrom (name + ".dll"); + plugin_type = assembly.GetType ("M17n.MInputMethod.Plugin"); + } + + MethodInfo info = plugin_type.GetMethod ((string) name); + if (info == null) + throw new Exception ("Invalid plugin method: " + name); + return info; + } + + public override string ToString () + { + return String.Format ("(module {0}", name); + } + } + + internal class PluginMethod : Xex.Function + { + private Plugin plugin; + private MethodInfo method_info; + object[] parameters = new object[2]; + + public PluginMethod (Plugin plugin, string name) + : base ((Xex.Symbol) name, 0, -1) + { + this.plugin = plugin; + } + + public override Xex.Term Call (Xex.Domain domain, Xex.Variable vari, + Xex.Term[] args) + { + args = (Xex.Term[]) args.Clone (); + for (int i = 0; i < args.Length; i++) + { + args[i] = args[i].Eval (domain); + if (domain.Thrown) + return args[i]; + } + if (method_info == null) + method_info = plugin.GetMethod (name); + parameters[0] = domain.context; + parameters[1] = args; + return (Xex.Term) method_info.Invoke (null, parameters); + } + } + + internal abstract class Marker : Xex.TermValue + { + private MSymbol name; + + private Marker (MSymbol name) + { + this.name = name; + } + + public abstract int Position (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 string ToString () + { + return "" + name.Name + ""; + } + + public static Xex.TermValue parser (Xex.Domain domain, XmlNode node) + { + return Get ((MSymbol) node.InnerText); + } + + public class Named : Marker + { + public Named (MSymbol name) : base (name) { } + + public override int Position (Context ic) + { + MPlist p = ic.marker_positions.Find (name); + return (p == null ? 0 : p.Integer); + } + + public override void Mark (Context ic) + { + ic.marker_positions.Put (name, ic.cursor_pos); + } + } + + public class Predefined : Marker + { + char tag; + + public Predefined (MSymbol name) : base (name) + { + tag = ((string) name)[1]; + } + + public override int Position (Context ic) + { + switch (tag) { + case '<': return 0; + case '>': return ic.preedit.Length; + case '-': return ic.cursor_pos - 1; + case '+': return ic.cursor_pos + 1; + case '[': + if (ic.cursor_pos > 0) + { + int pos = ic.cursor_pos; + int to; + ic.preedit.FindProp (Mcandidates, pos - 1, out pos, out to); + return pos; + } + return 0; + case ']': + if (ic.cursor_pos < ic.preedit.Length - 1) + { + int pos = ic.cursor_pos; + int from; + ic.preedit.FindProp (Mcandidates, pos, out from, out pos); + return pos; + } + return ic.preedit.Length; + default: + return tag - '0'; + } + } + } + + public class PredefinedAbsolute : Marker + { + private int pos; + + public PredefinedAbsolute (MSymbol name) : base (name) + { + if (! int.TryParse (((string) name).Substring (1), out pos)) + throw new Exception ("Invalid marker name: " + name); + } + + public override int Position (Context ic) + { + return (pos < ic.preedit.Length ? pos : ic.preedit.Length); + } + } + + public class PredefinedSurround : Marker + { + private int distance; + + public PredefinedSurround (MSymbol name) : base (name) + { + if (! int.TryParse (((string) name).Substring (2), out distance)) + throw new Exception ("Invalid marker name: " + name); + if (distance > 0) + distance--; + } + + public override int Position (Context ic) + { + 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; + + static Marker () + { + predefined_markers = new Dictionary (); + MSymbol[] symlist = new MSymbol[] {"@<", "@>", "@-", "@+", "@[", "@]" }; + foreach (MSymbol s in symlist) + predefined_markers[s] = new Predefined (s); + } + + public static Marker Get (MSymbol name) + { + string str = name.Name; + if (str[0] == '@') + { + Predefined pred; + if (predefined_markers.TryGetValue (name, out pred)) + return pred; + if (str.Length == 1) + throw new Exception ("Invalid marker name: " + name); + if (Char.IsDigit (str[1])) + return new PredefinedAbsolute (name); + if (str.Length == 2 || name == Mat_minus_zero + || ! (str[1] == '-' || str[1] == '+')) + throw new Exception ("Invalid marker name: " + name); + return new PredefinedSurround (name); + } + return new Named (name); + } + } + + internal class Candidates + { + private class Block + { + public int Index; + public object Data; + + public Block (int index, Xex.Term term) + { + Index = index; + if (term.IsStr) + Data = (MText) term.Strval; + else + { + MPlist plist = new MPlist (); + MPlist p = plist; + foreach (Xex.Term t in term.Listval) + p = p.Add (MSymbol.mtext, (MText) t.Strval); + Data = plist; + } + } + + public Block (int index, MPlist plist) + { + Index = index; + if (plist.IsMText) + Data = plist.Text; + else if (plist.IsPlist) + Data = plist.Plist; + else + throw new Exception ("Invalid candidate: " + plist); + } + + public int Count + { + get { return (Data is MText + ? ((MText) Data).Length + : ((MPlist) Data).Count); } + } + + public object this[int i] + { + get { + if (Data is MText) return ((MText) Data)[i]; + return ((MPlist) Data)[i]; + } + } + } + + private Block[] blocks; + private int row = 0; + private int index = 0; + public object[] group; + + private bool IsFixed { get { return group != null; } } + private int Total { + get { + Block last = blocks[blocks.Length - 1]; + return last.Index + last.Count; } + } + + public int Column { + get { return (IsFixed ? index % group.Length + : index - blocks[row].Index); } + } + + public object Group { + get { return (IsFixed ? group : blocks[row].Data); } + } + + public int GroupLength + { + get { + if (IsFixed) + { + int nitems = group.Length; + int start = index - (index % nitems); + int total = Total; + return (start + nitems <= total ? nitems : total - start); + } + return blocks[row].Count; + } + } + + public object Current { + get { + return (IsFixed ? group[index % group.Length] + : blocks[row][index - blocks[row].Index]); + } + } + + public Candidates (MPlist list, int column) + { + int nblocks = list.Count; + + blocks = new Block[nblocks]; + for (int i = 0, start = 0; i < nblocks; i++, list = list.next) + start += (blocks[i] = new Block (index, list)).Count; + if (column > 0) + group = new object[column]; + } + + public Candidates (Xex.Term[] candidates, int column) + { + int nblocks = candidates.Length; + + blocks = new Block[nblocks]; + for (int i = 0, start = 0; i < nblocks; i++) + start += (blocks[i] = new Block (index, candidates[i])).Count; + if (column > 0) + group = new object[column]; + } + + public static void Detach (Context ic) + { + ic.preedit.PopProp (0, ic.preedit.Length, Mcandidates); + ic.candidates = null; + ic.changed |= (ChangedStatus.Preedit | ChangedStatus.CursorPos + | CandidateAll); } // Fill the array "group" by candidates stating from START. @@ -2091,9 +2092,9 @@ namespace M17N.Input Xex.Term[] args) { if (args[0].IsInt) - ((Context) domain.context).insert (args[0].Intval); + ((Context) domain.context).insert (args[0].Intval, null); else - ((Context) domain.context).insert (args[0].Strval); + ((Context) domain.context).insert ((MText) args[0].Strval, null); return args[0]; } @@ -2104,8 +2105,13 @@ namespace M17N.Input Context ic = (Context) domain.context; Xex.Variable v = ic.domain.GetVar (Qcandidates_group_size, false); int column = (v == null ? 0 : v.Value.Intval); + Candidates candidates = new Candidates (args, column); + object candidate = candidates.Current; - ic.insert_candidates (new Candidates (args, column)); + if (candidate is MText) + ic.insert ((MText) candidate, candidates); + else + ic.insert ((int) candidate, candidates); return args[0]; } @@ -2137,14 +2143,25 @@ namespace M17N.Input private static Xex.Term Fselect (Xex.Domain domain, Xex.Variable vari, Xex.Term[] args) { - Candidates can = ((Context) domain.context).candidates; + Context ic = (Context) domain.context; + Candidates can = ic.candidates; if (can != null) { + object candidate = can.Current; + + if (candidate is MText) + ic.delete (ic.cursor_pos - ((MText) candidate).Length); + else + ic.delete (ic.cursor_pos - 1); if (args[0].IsInt) - can.Select (args[0].Intval); + candidate = can.Select (args[0].Intval); else - ((Selector) args[0].Objval).Select (can); + candidate = ((Selector) args[0].Objval).Select (can); + if (candidate is MText) + ic.insert ((MTtext) candidate, can); + else + ic.insert ((int) candidate, can); } return args[0]; } @@ -2307,7 +2324,6 @@ namespace M17N.Input internal MPlist marker_positions = new MPlist (); internal Candidates candidates; - private int candidate_from, candidate_to; private bool candidate_show; public bool CandidateShow { get { return candidate_show; } } @@ -2411,12 +2427,9 @@ namespace M17N.Input return following_text[pos]; } - private void adjust_markers (int from, int to, object inserted) + private void adjust_markers (int from, int to, int inserted) { - int ins = (inserted == null ? 0 - : inserted is int ? 1 - : ((MText) inserted).Length); - int diff = ins - (to - from); + int diff = inserted - (to - from); for (MPlist p = marker_positions; ! p.IsEmpty; p = p.next) { @@ -2430,64 +2443,45 @@ namespace M17N.Input set_cursor ("adjust", from); } - private void preedit_replace (int from, int to, int c) + private void preedit_replace (int from, int to, int c, + Candidates candidates) { preedit.Del (from, to); preedit.Ins (from, c); - adjust_markers (from, to, c); + if (candidates != null) + { + preedit.PushProp (cursor_pos - 1, cursor_pos, + Mcandidates, candidates); + changed |= (ChangedStatus.Preedit | ChangedStatus.CursorPos + | CandidateAll); + } + adjust_markers (from, to, 1); } - private void preedit_replace (int from, int to, MText mt) + private void preedit_replace (int from, int to, MText mt, + Candidates candidates) { preedit[from, to] = mt; - adjust_markers (from, to, mt); - } - - internal void insert (int c) - { - 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; - } - - private void update_candidate (Candidates candidates) - { - object candidate = candidates.Current; - - if (candidate is MText) - { - preedit_replace (candidate_from, candidate_to, (MText) candidate); - candidate_to = candidate_from + ((MText) candidate).Length; - } - else + if (candidates != null) { - preedit_replace (candidate_from, candidate_to, (int) candidate); - candidate_to = candidate_from + 1; + preedit.PushProp (cursor_pos - mt.Length, cursor_pos, + Mcandidates, candidates); + changed |= (ChangedStatus.Preedit | ChangedStatus.CursorPos + | CandidateAll); } - set_cursor ("update-candidate", candidate_to); - changed |= (ChangedStatus.Preedit | ChangedStatus.CursorPos - | CandidateAll); + adjust_markers (from, to, mt.Length); } - internal void insert_candidates (Candidates candidates) + internal void insert (int c, Candidates candidates) { - this.candidates = candidates; - candidate_from = candidate_to = cursor_pos; - update_candidate (candidates); + preedit_replace (cursor_pos, cursor_pos, c, candidates); + changed |= ChangedStatus.Preedit | ChangedStatus.CursorPos; } - internal void select (int n) + internal void insert (MText mt, Candidates candidates) { - if (candidates != null) - { - candidates.Select (n); - update_candidate (null); - } + preedit_replace (cursor_pos, cursor_pos, mt, candidates); + changed |= ChangedStatus.Preedit | ChangedStatus.CursorPos; } internal int delete (int pos) @@ -2513,7 +2507,7 @@ namespace M17N.Input pos = 0; } if (pos < cursor_pos) - preedit_replace (pos, cursor_pos, null); + preedit_replace (pos, cursor_pos, null, null); } else { @@ -2534,7 +2528,7 @@ namespace M17N.Input pos = preedit.Length; } if (pos > cursor_pos) - preedit_replace (cursor_pos, pos, null); + preedit_replace (cursor_pos, pos, null, null); } if (deleted != 0) changed |= ChangedStatus.Preedit | ChangedStatus.CursorPos; @@ -2612,7 +2606,7 @@ namespace M17N.Input internal void commit () { produced.Cat (preedit); - preedit_replace (0, preedit.Length, null); + preedit_replace (0, preedit.Length, null, null); changed |= ChangedStatus.Preedit; } @@ -2725,7 +2719,7 @@ namespace M17N.Input { for (int i = state_key_head; i < key_head; i++) preedit_replace (cursor_pos, cursor_pos, - keys.keyseq[i].ToChar ()); + keys.keyseq[i].ToChar (), null); } if (keymap.submaps == null) {