+ // Delegaes
+ public delegate bool Callback (MInputContext 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 Callback GetSurroundingText;
+ public static Callback DeleteSurroundingText;
+
+ internal static Xex.Domain im_domain = new Xex.Domain (null);
+ private static MSymbol Minput_method = "input-method";
+ private static MSymbol Mdescription = "description";
+ private static MSymbol Mvariable = "variable";
+ private static MSymbol Mcommand = "command";
+ private static MSymbol Mmodule = "module";
+ private static MSymbol Mtitle = "title";
+ private static MSymbol Minclude = "include";
+ private static MSymbol Mmacro = "macro";
+ private static MSymbol Mmap = "map";
+ private static MSymbol Mmap_list = "map-list";
+ private static MSymbol Mstate = "state";
+ internal static MSymbol Mcandidates = "candidates";
+ private static MSymbol Minsert = "insert";
+ private static MSymbol Mdelete = "delete";
+ private static MSymbol Mmove = "move";
+ private static MSymbol Mmark = "mark";
+ private static MSymbol Mmarker = "marker";
+ private static MSymbol Mset = "set";
+ private static MSymbol Madd = "add";
+ private static MSymbol Msub = "sub";
+ private static MSymbol Mmul = "mul";
+ private static MSymbol Mdiv = "div";
+ private static MSymbol Mif = "if";
+ private static MSymbol Mcond = "cond";
+ private static MSymbol Mchar_at = "char-at";
+ private static MSymbol Msurrounding_text_p = "surrounding-text-p";
+ private static MSymbol Mpushback = "pushback";
+ private static MSymbol Mkeyseq = "keyseq";
+
+ private static Xex.Symbol Nprogn = "progn";
+ private static Xex.Term Tnil = new Xex.Term ((Xex.Symbol) "nil");
+ private static Xex.Term Tcatch_tag = new Xex.Term ((Xex.Symbol) "@mimtag");
+
+ private static Dictionary<MDatabase.Tag, MInputMethod> im_table
+ = new Dictionary<MDatabase.Tag, MInputMethod> ();
+
+ internal static MInputMethod im_global = null;
+
+ [FlagsAttribute]
+ private enum LoadStatus
+ {
+ None = 0x00,
+ Header = 0x01,
+ Body = 0x02,
+ Full = 0x03,
+ Error = 0x04,
+ };
+
+ [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<string, uint> keysyms
+ = new Dictionary<string, uint> ();
+ private static Dictionary<string, KeyModifier> keymodifiers
+ = new Dictionary<string, KeyModifier> ();
+ private static uint keysym_base = 0x200000;
+ private static uint char_mask = ~((uint) KeyModifier.All);
+
+ 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;
+ }
+
+ 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 (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 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 override string ToString ()
+ {
+ string str = Char.ToString ((char) key);
+ KeyModifier m = ((KeyModifier) key) & KeyModifier.All;
+
+ if (m != KeyModifier.None)
+ {
+ if ((m & KeyModifier.Shift) != KeyModifier.None)
+ str = "S-" + str;
+ if ((m & KeyModifier.Control) != KeyModifier.None)
+ str = "C-" + str;
+ if ((m & KeyModifier.Alt) != KeyModifier.None)
+ str = "A-" + str;
+ if ((m & KeyModifier.AltGr) != KeyModifier.None)
+ str = "G-" + str;
+ if ((m & KeyModifier.Super) != KeyModifier.None)
+ str = "s-" + str;
+ if ((m & KeyModifier.Hyper) != KeyModifier.None)
+ str = "H-" + str;
+ }
+ return str;
+ }
+ }
+
+ public class KeySeq : Xex.TermValue
+ {
+ public List<Key> keyseq = new List<Key> ();
+
+ 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]));
+ }
+
+ private static uint parse_integer (string str)
+ {
+ if (Char.IsDigit (str[0]))
+ {
+ if (str[0] == '0' && str.Length > 2 && str[1] == 'x')
+ {
+ uint i = 0;
+ for (int idx = 2; idx < str.Length; idx++)
+ {
+ uint c = str[idx];
+ if (c >= '0' && c <= '9')
+ i = i * 16 + (c - '0');
+ else if (c >= 'A' && c <= 'F')
+ i = i * 16 + 10 + (c - 'A');
+ else if (c >= 'a' && c <= 'f')
+ i = i * 16 + 10 + (c - 'a');
+ else
+ break;
+ }
+ return i;
+ }
+ return UInt32.Parse (str);
+ }
+ else if (str[0] == '?')
+ return str[1];
+ return 0;
+ }
+
+ public KeySeq (XmlNode node)
+ {
+ XmlAttributeCollection acol = node.Attributes;
+ XmlNode n;
+
+ if (acol != null && (n = acol["keys"]) != null)
+ {
+ foreach (char c in n.Value)
+ keyseq.Add (new Key ((uint) c));
+ }
+
+ for (node = node.FirstChild; node != null; node = node.NextSibling)
+ {
+ if (node.Name == "key-event")
+ keyseq.Add (new Key ((MSymbol) node.InnerText));
+ else
+ keyseq.Add (new Key (parse_integer (node.InnerText)));
+ }
+ }
+
+ public KeySeq (Xex.Term[] args)
+ {
+ foreach (Xex.Term term in args)
+ {
+ if (term.IsSymbol)
+ keyseq.Add (new Key ((MSymbol) ((string) term.Symval)));
+ else
+ keyseq.Add (new Key (term.Strval));
+ }
+ }
+
+ public override string ToString ()
+ {
+ string str;
+
+ foreach (Key key in keyseq)
+ if (key.HasModifier)
+ {
+ str = "(keyseq";
+ foreach (Key k in keyseq)
+ str += " " + k.ToString ();
+ return str + ")";
+ }
+ str = "\"";
+ foreach (Key key in keyseq)
+ str += key.ToString ();
+ return str + "\"";
+ }
+ }
+
+ public class Variable