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<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);
- 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<string, uint> 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<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]));
- }
-
- public KeySeq (List<Xex.Term> 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<KeySeq> keys;
-
- public Command (MPlist p)
- {
- name = p.Symbol;
- p = p.Next;
- description = parse_description (p);
- if (description == null)
- description = "No description";
- keys = new List<KeySeq> ();
- 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<KeySeq> ();
- 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 "<marker>" + name.Name + "</marker>";
- }
-
- 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<MSymbol,Predefined> predefined_markers;
-
- static Marker ()
- {
- predefined_markers = new Dictionary<MSymbol, Predefined> ();
- 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<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);
+ 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<string, uint> 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<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]));
+ }
+
+ public KeySeq (List<Xex.Term> 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<KeySeq> keys;
+
+ public Command (MPlist p)
+ {
+ name = p.Symbol;
+ p = p.Next;
+ description = parse_description (p);
+ if (description == null)
+ description = "No description";
+ keys = new List<KeySeq> ();
+ 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<KeySeq> ();
+ 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 "<marker>" + name.Name + "</marker>";
+ }
+
+ 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<MSymbol,Predefined> predefined_markers;
+
+ static Marker ()
+ {
+ predefined_markers = new Dictionary<MSymbol, Predefined> ();
+ 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.
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];
}
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];
}
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];
}
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; } }
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)
{
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)
pos = 0;
}
if (pos < cursor_pos)
- preedit_replace (pos, cursor_pos, null);
+ preedit_replace (pos, cursor_pos, null, null);
}
else
{
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;
internal void commit ()
{
produced.Cat (preedit);
- preedit_replace (0, preedit.Length, null);
+ preedit_replace (0, preedit.Length, null, null);
changed |= ChangedStatus.Preedit;
}
{
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)
{