using M17N.Core;
using M17N.Input;
-using Xex = System.Xml.Expression.Xexpression;
+using Xex = System.Xml.Xexpression;
namespace M17N.Input
{
// Delegaes
public delegate bool Callback (Context ic, MPlist args);
- // Class members
- public static event Callback PreeditChanged;
- public static event Callback StatusChanged;
- public static event Callback CandidateChanged;
- public static Callback GetSurroundingText;
- public static Callback DeleteSurroundingText;
-
internal static Xex.Domain im_domain
= new Xex.Domain ("input-method", null);
private static MSymbol Minput_method = "input-method";
private static MSymbol Mstate = "state";
internal static MSymbol Mcandidates = "candidates";
private static MSymbol Mat_minus_zero = "@-0";
+ private static MSymbol Matat = "@@";
+ private static Xex.Symbol Qxi_include = "xi:include";
private static Xex.Symbol Qmap = "map";
private static Xex.Symbol Qrule = "rule";
private static Xex.Symbol Qkeyseq = "keyseq";
private static Xex.Symbol Qtitle = "title";
private static Xex.Symbol Qeq = "=";
private static Xex.Symbol Qeqeq = "==";
+ private static Xex.Symbol Qhide = "hide";
+ private static Xex.Symbol Qhide_candidates = "hide-candidates";
+ private static Xex.Symbol Qshow = "show";
+ private static Xex.Symbol Qshow_candidates = "show-candidates";
+ private static Xex.Symbol Qkey_count = "key-count";
+ private static Xex.Symbol Qsurrounding_text_flag = "surrounding-text-flag";
private static Xex.Symbol Qcandidates_group_size = "candidates-group-size";
private static Xex.Term Tnil = new Xex.Term ((Xex.Symbol) "nil");
= new Dictionary<string, KeyModifier> ();
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;
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)
public int ToChar ()
{
- return (int) (key & 0x1FFFFF);
+ return (key & 0x3FFFFF) <= 0x1FFFFF ? (int) (key & 0x1FFFFF) : -1;
}
public override string ToString ()
MText mt = null;
if (c < 0x20)
foreach (KeyValuePair<string, uint> kv in keysyms)
- if ((uint) c == kv.Value)
+ if ((key & 0x3FFFFF) == kv.Value)
{
mt = kv.Key;
break;
internal class KeySeq : Xex.TermValue
{
+ private static Xex.Symbol name = "keyseq";
+ public static Xex.Symbol Name { get { return name; } }
+
public List<Key> keyseq = new List<Key> ();
public override Xex.TermValue Clone ()
}
}
- 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)
: 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;
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));
}
}
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)
{
- return ic.preedit[Position (ic)];
+ int pos = Position (ic);
+
+ return ((pos >= 0 && pos < ic.preedit.Length) ? ic.preedit[pos]
+ : -1);
}
public override string ToString ()
{
- return "<marker>" + name.Name + "</marker>";
+ return "<marker>" + mname + "</marker>";
}
- 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);
}
}
{
char tag;
- public Predefined (MSymbol name) : base (name)
- {
- tag = ((string) name)[1];
- }
+ public Predefined (char tag) : base ("@" + tag) { this.tag = tag; }
public override int Position (Context ic)
{
{
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)
{
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--;
}
}
}
- static internal Dictionary<MSymbol,Predefined> predefined_markers;
+ static internal Dictionary<MSymbol,Predefined> predefineds;
static Marker ()
- {
- predefined_markers = new Dictionary<MSymbol, Predefined> ();
- MSymbol[] symlist = new MSymbol[] {"@<", "@>", "@-", "@+", "@[", "@]" };
- foreach (MSymbol s in symlist)
- predefined_markers[s] = new Predefined (s);
- }
+ {
+ predefineds = new Dictionary<MSymbol, Predefined> ();
+ predefineds ["@<"] = predefineds["@first"] = new Predefined ('<');
+ predefineds ["@>"] = predefineds["@last"] = new Predefined ('>');
+ predefineds ["@-"] = predefineds["@previous"] = new Predefined ('-');
+ predefineds ["@+"] = predefineds["@next"] = new Predefined ('+');
+ predefineds ["@["] = predefineds["@previous-candidate-change"]
+ = new Predefined ('[');
+ predefineds ["@]"] = predefineds["@next-candidate-change"]
+ = 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 (predefined_markers.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);
}
}
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];
+ {
+ group = new object[column];
+ fill_group (0);
+ }
}
public Candidates (Xex.Term[] candidates, int column)
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];
+ {
+ group = new object[column];
+ fill_group (0);
+ }
}
public static void Detach (Context ic)
ic.candidates = null;
ic.changed |= (ChangedStatus.Preedit | ChangedStatus.CursorPos
| CandidateAll);
- }
+ }
- // Fill the array "group" by candidates stating from START.
- // START must be a multiple of "column". Return the number of
- // valid candidates in "group".
+ // Fill the array "group" by candidates stating from START.
+ // START must be a multiple of "column". Return the number of
+ // valid candidates in "group".
- private int fill_group (int start)
- {
- int nitems = group.Length;
- int r = row;
- Block b = blocks[r];
+ private int fill_group (int start)
+ {
+ int nitems = group.Length;
+ int r = row;
+ Block b = blocks[r];
- if (start < b.Index)
- while (start < b.Index)
- b = blocks[--r];
- else
- while (start >= b.Index + b.Count)
- b = blocks[++r];
- row = r;
+ if (start < b.Index)
+ while (start < b.Index)
+ b = blocks[--r];
+ else
+ while (start >= b.Index + b.Count)
+ b = blocks[++r];
+ row = r;
- int count = b.Count;
- start -= b.Index;
- for (int i = 0; i < nitems; i++, start++)
- {
- if (start >= count)
- {
- r++;
- if (r == blocks.Length)
- return i;
- b = blocks[r];
- count = b.Count;
- start = 0;
- }
- group[i] = b[start];
- }
- return nitems;
- }
+ int count = b.Count;
+ start -= b.Index;
+ for (int i = 0; i < nitems; i++, start++)
+ {
+ if (start >= count)
+ {
+ r++;
+ if (r == blocks.Length)
+ return i;
+ b = blocks[r];
+ count = b.Count;
+ start = 0;
+ }
+ group[i] = b[start];
+ }
+ return nitems;
+ }
- // Update "row" to what contains the first candidate of
- // the previous candidate-group, update "current_index", and
- // update "group" if necessary. Return the previous
- // candidate-group. Set NITEMS to the number of valid
- // candidates contained in that group.
+ // Update "row" to what contains the first candidate of
+ // the previous candidate-group, update "current_index", and
+ // update "group" if necessary. Return the previous
+ // candidate-group. Set NITEMS to the number of valid
+ // candidates contained in that group.
- public int PrevGroup ()
- {
- int nitems;
- int col = Column;
+ public int PrevGroup ()
+ {
+ int nitems;
+ int col = Column;
- if (IsFixed)
- {
- nitems = group.Length;
- if ((index -= col + nitems) < 0)
- index = (Total / nitems) * nitems;
- nitems = fill_group (index);
- }
- else
- {
- row = row > 0 ? row-- : blocks.Length - 1;
- nitems = blocks[row].Count;
- index = blocks[row].Index;
- }
- index += col < nitems ? col : nitems - 1;
- return nitems;
- }
+ if (IsFixed)
+ {
+ nitems = group.Length;
+ if ((index -= col + nitems) < 0)
+ index = (Total / nitems) * nitems;
+ nitems = fill_group (index);
+ }
+ else
+ {
+ row = row > 0 ? row-- : blocks.Length - 1;
+ nitems = blocks[row].Count;
+ index = blocks[row].Index;
+ }
+ index += col < nitems ? col : nitems - 1;
+ return nitems;
+ }
- public int NextGroup ()
- {
- int nitems;
- int col = Column;
+ public int NextGroup ()
+ {
+ int nitems;
+ int col = Column;
- if (IsFixed)
- {
- nitems = group.Length;
- if ((index += nitems - col) >= Total)
- index = 0;
- nitems = fill_group (index);
- }
- else
- {
- row = row < blocks.Length - 1 ? row + 1 : 0;
- nitems = blocks[row].Count;
- index = blocks[row].Count;
- }
- index += col < nitems ? col : nitems - 1;
- return nitems;
- }
+ if (IsFixed)
+ {
+ nitems = group.Length;
+ if ((index += nitems - col) >= Total)
+ index = 0;
+ nitems = fill_group (index);
+ }
+ else
+ {
+ row = row < blocks.Length - 1 ? row + 1 : 0;
+ nitems = blocks[row].Count;
+ index = blocks[row].Count;
+ }
+ index += col < nitems ? col : nitems - 1;
+ return nitems;
+ }
- public void Prev ()
- {
- int col = Column;
+ public void Prev ()
+ {
+ int col = Column;
- if (col == 0)
- {
- int nitems = PrevGroup ();
- index += col < nitems - 1 ? col : nitems - 1;
- }
- else
- index--;
- }
+ if (col == 0)
+ {
+ int nitems = PrevGroup ();
+ index += col < nitems - 1 ? col : nitems - 1;
+ }
+ else
+ index--;
+ }
- public void Next ()
- {
- int col = Column;
- int nitems = GroupLength;
+ public void Next ()
+ {
+ int col = Column;
+ int nitems = GroupLength;
- if (col == nitems - 1)
- {
- nitems = NextGroup ();
- index -= Column;
- }
- else
- index++;
- }
+ if (col == nitems - 1)
+ {
+ nitems = NextGroup ();
+ index -= Column;
+ }
+ else
+ index++;
+ }
- public void First ()
- {
- index -= Column;
- }
+ public void First ()
+ {
+ index -= Column;
+ }
- public void Last ()
- {
- index += GroupLength - (Column + 1);
- }
+ public void Last ()
+ {
+ index += GroupLength - (Column + 1);
+ }
- public object Select (int col)
- {
- int maxcol = GroupLength - 1;
- if (col > maxcol)
- col = maxcol;
- index = index - Column + col;
- return Current;
- }
+ public object Select (int col)
+ {
+ int maxcol = GroupLength - 1;
+ if (col > maxcol)
+ col = maxcol;
+ index = index - Column + col;
+ return Current;
+ }
- public object Select (Selector selector)
- {
- switch (selector.Tag)
- {
- case '<': First (); break;
- case '>': Last (); break;
- case '-': Prev (); break;
- case '+': Next (); break;
- case '[': PrevGroup (); break;
- case ']': NextGroup (); break;
- default: break;
- }
- return Current;
- }
+ public object Select (Selector selector)
+ {
+ switch (selector.Tag)
+ {
+ case '<': First (); break;
+ case '>': Last (); break;
+ case '-': Prev (); break;
+ case '+': Next (); break;
+ case '[': PrevGroup (); break;
+ case ']': NextGroup (); break;
+ default: break;
+ }
+ return Current;
+ }
- public override string ToString ()
- {
- return (String.Format ("<candidates row={0} col={1}>", row, index)
- + Group
- + "</candidates>");
- }
- }
+ public override string ToString ()
+ {
+ return (String.Format ("<candidates row={0} col={1}>", row, index)
+ + Group
+ + "</candidates>");
+ }
+ }
internal class Selector : Xex.TermValue
{
+ private static Xex.Symbol name = "selector";
+ public static Xex.Symbol Name { get { return name; } }
+
static new Dictionary<MSymbol, Selector> selectors;
static Selector ()
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);
}
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 "<selector>@" + tag + "</selector>";
+ }
}
internal class Map
}
}
+ 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 = action.Eval (domain);
+ if (result.IsError)
+ {
+ ((Context) domain.context).Error = result.ToString ();
+ return false;
+ }
+ return (result != Tcatch_tag);
+ }
+ }
+
internal class Keymap
{
public Dictionary<Key, Keymap> submaps;
internal class State
{
- public Xex.Symbol name;
+ public MSymbol name;
public MText title;
public Xex.Term[] enter_actions, fallback_actions;
public Keymap keymap = new Keymap ();
- public State (Xex.Symbol name, MText title)
+ public State (MSymbol name, MText title)
{
this.name = name;
this.title = title;
{
if (! plist.IsSymbol)
throw new Exception ("Invalid state: " + plist);
- this.name = plist.Symbol.Name;
+ this.name = plist.Symbol;
plist = plist.next;
if (plist.IsMText)
{
internal Xex.Symbol[] var_names;
internal Dictionary<MSymbol, Plugin> plugins;
internal Dictionary<MSymbol, Map> maps;
- internal Dictionary<Xex.Symbol, State> states;
- internal State initial_state;
+ internal MPlist states;
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);
im_domain.DefSubr (Fdelete, "delete", false, 1, 1);
im_domain.DefSubr (Fselect, "select", false, 1, 1);
- im_domain.DefSubr (Fshow, "show", false, 0, 0);
- im_domain.DefSubr (Fhide, "hide", false, 0, 0);
+ im_domain.DefSubr (Fshow, "show-candidates", false, 0, 0);
+ im_domain.DefSubr (Fhide, "hide-candidates", false, 0, 0);
im_domain.DefSubr (Fmove, "move", false, 1, 1);
im_domain.DefSubr (Fmark, "mark", false, 1, 1);
im_domain.DefSubr (Fpushback, "pushback", false, 1, 1);
im_domain.DefSubr (Fshift, "shift", false, 1, 1);
im_domain.DefSubr (Fshiftback, "shiftback", false, 0, 0);
im_domain.DefSubr (Fchar_at, "char-at", false, 1, 1);
- im_domain.DefSubr (Fkey_count, "key-count", false, 1, 1);
+ im_domain.DefSubr (Fkey_count, "key-count", false, 0, 0);
im_domain.DefSubr (Fsurrounding_flag, "surrounding-text-flag",
false, 0, 0);
mdb = MDatabase.Find (tag);
if (mdb == null)
return false;
- mdb.name_table = Xex.Symbol.Table;
try {
- MSymbol format = mdb.Format;
-
- if (format == MSymbol.plist)
- load ((MPlist) mdb.Load (Mmap), false);
+ if (mdb.Format == MSymbol.plist)
+ load (mdb.Load (Mmap), false);
else
{
- XmlDocument doc = (XmlDocument) mdb.Load (Mmap_list);
+ XmlDocument doc = new XmlDocument (Xex.Symbol.NameTable);
+ if (! mdb.Load (doc, Mmap_list))
+ throw new Exception ("Load error" + mdb.tag);
load (doc.DocumentElement, false);
}
} catch (Exception e) {
mdb = MDatabase.Find (tag);
if (mdb == null)
return false;
- mdb.name_table = Xex.Symbol.Table;
try {
- object obj = mdb.Load ();
- if (obj is MPlist)
- load ((MPlist) obj, true);
+ if (mdb.Format == MSymbol.plist)
+ load (mdb.Load (), true);
else
- load ((XmlDocument) obj, true);
+ {
+ XmlDocument doc = new XmlDocument (Xex.Symbol.NameTable);
+ if (! mdb.Load (doc))
+ throw new Exception ("Load error" + mdb.tag);
+ load (doc.DocumentElement, true);
+ }
} catch (Exception e) {
Console.WriteLine (e);
load_status = LoadStatus.Error;
private void add_default_state ()
{
- Xex.Symbol Qinit = "init";
+ MSymbol Qinit = "init";
State state = new State (Qinit, title);
foreach (KeyValuePair<MSymbol, Map>kv in maps)
state.keymap.AddMap (kv.Value, null);
- states[Qinit] = initial_state = state;
+ states.Add (Qinit, state);
}
private void load (MPlist plist, bool full)
{
maps = new Dictionary<MSymbol, Map> ();
- states = new Dictionary<Xex.Symbol, State> ();
+ states = new MPlist ();
for (; ! plist.IsEmpty; plist = plist.next)
if (plist.IsPlist)
commands = new Command[0];
if (! full)
return;
- if (states.Count == 0)
+ if (states.IsEmpty)
add_default_state ();
}
bool skip_header = load_status == LoadStatus.Header;
maps = new Dictionary<MSymbol, Map> ();
- states = new Dictionary<Xex.Symbol, State> ();
+ states = new MPlist ();
if (node.NodeType == XmlNodeType.Document)
node = node.FirstChild;
else if (node.Name == "command-list")
parse_commands (node);
}
- else if (full)
+ if (full)
{
if (node.Name == "module-list")
parse_plugins (node);
commands = new Command[0];
if (! full)
return;
- if (states.Count == 0)
+ if (states.IsEmpty)
add_default_state ();
}
return node.InnerText;
}
- private void new_variable (Xex.Symbol name, string desc, int val,
- MPlist pl, Xex.Variable vari)
- {
- int[] range;
-
- if (pl.IsEmpty)
- range = null;
- else
- {
- int nrange = pl.Count;
- range = new int[nrange * 2];
- for (int i = 0; i < nrange; i++)
- {
- if (pl.IsPlist)
- {
- MPlist p = pl.Plist;
-
- if (! p.IsInteger || ! p.next.IsInteger)
- throw new Exception ("Invalid range: " + p);
- range[i * 2] = p.Integer;
- range[i * 2 + 1] = p.next.Integer;
- }
- else if (pl.IsInteger)
- range[i * 2] = range[i * 2 + 1] = pl.Integer;
- else
- throw new Exception ("Invalid range: " + pl);
- }
- }
- if (vari == null)
- domain.Defvar (new Xex.Variable.Int (domain, name, desc, val, range));
- else
- {
- Xex.Term term = new Xex.Term (val);
- vari.Value = term;
- vari.DefaultValue = term;
- vari.Range = range;
- }
- }
-
- private void new_variable (Xex.Symbol name, string desc, MText val,
- MPlist pl, Xex.Variable vari)
- {
- string[] range;
-
- if (pl.IsEmpty)
- range = null;
- else
- {
- range = new string[pl.Count * 2];
- for (int i = 0; i < range.Length; i++)
- {
- if (pl.IsMText)
- range[i] = (string) pl.Text;
- else
- throw new Exception ("Invalid range: " + pl);
- }
- }
- if (vari == null)
- domain.Defvar (new Xex.Variable.Str (domain, name, desc, (string) val, range));
- else
- {
- Xex.Term term = new Xex.Term ((string) val);
- vari.Value = term;
- vari.DefaultValue = term;
- vari.Range = range;
- }
- }
-
- private void new_variable (Xex.Symbol name, string desc, MSymbol val,
- MPlist pl, Xex.Variable vari)
- {
- Xex.Symbol[] range;
- Xex.Symbol sym = val.Name;
-
- if (pl.IsEmpty)
- range = null;
- else
- {
- range = new Xex.Symbol[pl.Count * 2];
- for (int i = 0; i < range.Length; i++)
- {
- if (pl.IsSymbol)
- range[i] = pl.Symbol.Name;
- else
- throw new Exception ("Invalid range: " + pl);
- }
- }
- if (vari == null)
- domain.Defvar (new Xex.Variable.Sym (domain, name, desc, sym, range));
- else
- {
- Xex.Term term = new Xex.Term (sym);
- vari.Value = term;
- vari.DefaultValue = term;
- vari.Range = range;
- }
- }
-
private Xex.Variable get_global_var (Xex.Symbol name)
{
if (im_global == null || this != im_global)
{
- tag = new MDatabase.Tag (Minput_method, MSymbol.t, MSymbol.nil,
- "global");
+ MDatabase.Tag tag =
+ new MDatabase.Tag (Minput_method, MSymbol.t, MSymbol.nil, "global");
im_global = im_table[tag];
if (! im_global.Open ())
throw new Exception ("Failed to load global");
Xex.Symbol name = (Xex.Symbol) p.Symbol.Name;
var_names[i] = name;
p = p.next;
- string desc = (string) parse_description (p);
+ MText mt = parse_description (p);
+ string desc = mt == null ? null : (string) mt;
+ if (! p.IsEmpty)
+ p = p.next;
Xex.Variable vari = get_global_var (name);
if (vari != null)
domain.Defvar (vari);
- if (desc != null)
- p = p.next;
- if (! p.IsEmpty)
+ if (p.IsInteger)
{
- if (p.IsInteger)
- new_variable (name, desc, p.Integer, p.next, vari);
- else if (p.IsMText)
- new_variable (name, desc, p.Text, p.next, vari);
- else if (p.IsSymbol)
- new_variable (name, desc, p.Symbol, p.next, vari);
+ int n = p.Integer;
+ int[] range = null;
+
+ p = p.Next;
+ if (! p.IsEmpty)
+ {
+ int nrange = p.Count;
+ range = new int[nrange * 2];
+ for (int j = 0; j < nrange; j++)
+ {
+ if (p.IsPlist)
+ {
+ MPlist p0 = p.Plist;
+
+ if (! p0.IsInteger || ! p0.next.IsInteger)
+ throw new Exception ("Invalid range: " + p0);
+ range[j * 2] = p0.Integer;
+ range[j * 2 + 1] = p0.next.Integer;
+ }
+ else if (p.IsInteger)
+ range[j * 2] = range[j * 2 + 1] = p.Integer;
+ else
+ throw new Exception ("Invalid range: " + p);
+ }
+ }
+ domain.DefvarInt (name, n, desc, range);
+ }
+ else if (p.IsMText)
+ {
+ string str = (string) p.Text;
+ string[] range = null;
+
+ p = p.next;
+ if (! p.IsEmpty)
+ {
+ range = new string[p.Count];
+ for (int j = 0; j < range.Length; j++)
+ {
+ if (p.IsMText)
+ range[j] = (string) p.Text;
+ else
+ throw new Exception ("Invalid range: " + p);
+ }
+ }
+ domain.DefvarStr (name, str, desc, range);
+ }
+ else if (p.IsSymbol)
+ {
+ Xex.Symbol sym = p.Symbol.Name;
+ Xex.Symbol[] range;
+
+ p = p.next;
+ if (p.IsEmpty)
+ range = null;
else
- throw new Exception ("Invalid variable type: " + p.val);
+ {
+ range = new Xex.Symbol[p.Count];
+ for (int j = 0; j < range.Length; j++)
+ {
+ if (p.IsSymbol)
+ range[j] = p.Symbol.Name;
+ else
+ throw new Exception ("Invalid range: " + p);
+ }
+ }
+ domain.DefvarSym (name, sym, desc, range);
}
+ else if (! p.IsEmpty)
+ throw new Exception ("Invalid variable type: " + p.val);
}
}
}
}
+ private void parse_include (XmlNode node)
+ {
+ XmlNode n;
+ MSymbol language, name, subname;
+ MSymbol part, section;
+ node = node.FirstChild;
+ n = node.FirstChild;
+ language = n.InnerText;
+ n = n.NextSibling;
+ name = n.InnerText;
+ n = n.NextSibling;
+ if (n != null)
+ subname = n.InnerText;
+ else
+ subname = MSymbol.nil;
+ node = node.NextSibling;
+ part = node.InnerText;
+ node = node.NextSibling;
+ if (node != null)
+ section = node.InnerText;
+ else
+ section = MSymbol.nil;
+ include_part (language, name, subname, part, section);
+ }
+
private void parse_macros (XmlNode node)
{
for (XmlNode nn = node.FirstChild; nn != null; nn = nn.NextSibling)
if (nn.NodeType == XmlNodeType.Element)
- domain.Defun (nn, true);
+ {
+ if (nn.Name == Xex.Qdefun)
+ domain.Defun (nn, true);
+ else if (nn.Name == Qxi_include)
+ parse_include (nn);
+ }
for (XmlNode nn = node.FirstChild; nn != null; nn = nn.NextSibling)
- if (nn.NodeType == XmlNodeType.Element)
+ if (nn.NodeType == XmlNodeType.Element
+ && nn.Name == Xex.Qdefun)
domain.Defun (nn, false);
}
private void parse_maps (XmlNode node)
{
for (node = node.FirstChild; node != null; node = node.NextSibling)
- if (node.Name == Qmap)
- {
- MSymbol name = node.Attributes[0].Value;
- Map map = new Map (name);
- maps[name] = map;
- for (XmlNode nd = node.FirstChild; nd != null; nd = nd.NextSibling)
- if (nd.Name == Qrule)
- {
- XmlNode n = nd.FirstChild;
- if (n.Name != Qkeyseq)
- continue;
- KeySeq keyseq = (KeySeq) KeySeq.parser (domain, n);
- Xex.Term[] actions = Xex.ParseTerms (domain, n.NextSibling);
- map.entries.Add (new Map.Entry (domain, keyseq, actions));
- }
- }
+ {
+ if (node.Name == Qmap)
+ {
+ MSymbol name = node.Attributes[0].Value;
+ Map map = new Map (name);
+ maps[name] = map;
+ for (XmlNode nd = node.FirstChild; nd != null;
+ nd = nd.NextSibling)
+ if (nd.Name == Qrule)
+ {
+ XmlNode n = nd.FirstChild;
+ if (n.Name != Qkeyseq)
+ continue;
+ KeySeq keyseq = (KeySeq) KeySeq.Parser (domain, n);
+ Xex.Term[] actions = Xex.ParseTerms (domain, n.NextSibling);
+ map.entries.Add (new Map.Entry (domain, keyseq, actions));
+ }
+ }
+ else if (node.Name == Qxi_include)
+ parse_include (node);
+ }
}
private void parse_states (MPlist plist)
if (plist.IsPlist)
{
State state = new State (this, plist.Plist);
- states[state.name] = state;
- if (initial_state == null)
- initial_state = state;
+ states.Add (state.name, state);
}
}
private void parse_states (XmlNode node)
{
for (node = node.FirstChild; node != null; node = node.NextSibling)
- if (node.Name == Qstate)
- {
- State state = new State (this, node);
- states[state.name] = state;
- if (initial_state == null)
- initial_state = state;
- }
- }
-
- private void parse_include (MPlist plist)
- {
- if (! plist.IsPlist)
- return;
- MPlist p = plist.Plist;
- MSymbol language, name, subname;
- language = p.Symbol;
- p = p.next;
- if (! p.IsSymbol)
- name = subname = MSymbol.nil;
- else
{
- name = p.Symbol;
- p = p.next;
- if (! p.IsSymbol)
- subname = MSymbol.nil;
- else
- subname = p.Symbol;
+ if (node.Name == Qstate)
+ {
+ State state = new State (this, node);
+ states.Add (state.name, state);
+ }
+ else if (node.Name == Qxi_include)
+ parse_include (node);
}
+ }
+ private void include_part (MSymbol language, MSymbol name, MSymbol subname,
+ MSymbol part, MSymbol section)
+ {
MInputMethod im = MInputMethod.Find (language, name, subname);
if (im == null)
return;
if (! im.Open ())
return;
- plist = plist.next;
- if (! plist.IsSymbol)
- return;
- MSymbol target_type = plist.Symbol;
- plist = plist.next;
- MSymbol target_name = MSymbol.nil;
- if (plist.IsSymbol)
- target_name = plist.Symbol;
- if (target_type == Mmacro)
+ if (part == Mmacro)
{
- if (target_name == MSymbol.nil)
+ if (section == MSymbol.nil)
im.domain.CopyFunc (domain);
else
- im.domain.CopyFunc (domain, (Xex.Symbol) target_name.Name);
+ im.domain.CopyFunc (domain, (Xex.Symbol) section.Name);
}
- else if (target_type == Mmap)
+ else if (part == Mmap)
{
- if (target_name == MSymbol.nil)
+ if (section == MSymbol.nil)
{
foreach (KeyValuePair<MSymbol, Map> kv in im.maps)
maps[kv.Key] = kv.Value;
else
{
Map map;
- if (im.maps.TryGetValue (target_name, out map))
- maps[target_name] = map;
+ if (im.maps.TryGetValue (section, out map))
+ maps[section] = map;
}
}
- else if (target_type == Mstate)
+ else if (part == Mstate)
{
- if (target_name == MSymbol.nil)
+ if (section == MSymbol.nil)
{
- foreach (KeyValuePair<Xex.Symbol, State> kv in im.states)
- states[kv.Key] = kv.Value;
+ for (MPlist p = im.states; ! p.IsEmpty; p = p.next)
+ states.Add (p.Key, p.Val);
}
else
{
- Xex.Symbol state_name = target_name.Name;
- State state;
- if (im.states.TryGetValue (state_name, out state))
- states[state_name] = state;
+ MSymbol state_name = (string) section.Name;
+ State state = (State) im.states.Get (state_name);
+ if (state != null)
+ states.Add (state.name, state);
}
}
}
+ private void parse_include (MPlist plist)
+ {
+ if (! plist.IsPlist)
+ return;
+ MPlist p = plist.Plist;
+ MSymbol language, name, subname;
+ language = p.Symbol;
+ p = p.next;
+ if (! p.IsSymbol)
+ name = subname = MSymbol.nil;
+ else
+ {
+ name = p.Symbol;
+ p = p.next;
+ if (! p.IsSymbol)
+ subname = MSymbol.nil;
+ else
+ subname = p.Symbol;
+ }
+ plist = plist.next;
+ if (! plist.IsSymbol)
+ return;
+ MSymbol part = plist.Symbol;
+ plist = plist.next;
+ MSymbol section = MSymbol.nil;
+ if (plist.IsSymbol)
+ section = plist.Symbol;
+ include_part (language, name, subname, part, section);
+ }
+
private Xex.Term parse_cond (MPlist plist)
{
Xex.Term[] args = new Xex.Term[plist.Count];
return parse_funcall_with_marker (p, name);
if (name == Qshift)
return parse_shift (p);
- if (((string) name)[0] == '@')
- return parse_char_at (sym);
if (name == Qset || name == Qadd || name == Qsub
|| name == Qmul || name == Qdiv)
{
{
if (name == Qeq)
name = Qeqeq;
+ else if (name == Qhide)
+ name = Qhide_candidates;
+ else if (name == Qshow)
+ name = Qshow_candidates;
if (p.IsEmpty)
return new Xex.Term (domain, name, null);
else
}
else if (plist.IsSymbol)
{
+ if (plist.Symbol == Matat)
+ return new Xex.Term (domain, Qkey_count, null);
+ if (plist.Symbol == Mat_minus_zero)
+ return new Xex.Term (domain, Qsurrounding_text_flag, null);
if (plist.Symbol.Name[0] == '@')
return parse_char_at (plist.Symbol);
return new Xex.Term (domain, (Xex.Symbol) plist.Symbol.Name);
if (pl.IsPlist)
{
MPlist p = pl.Plist;
-
if (! p.IsSymbol)
continue;
domain.Defun ((Xex.Symbol) p.Symbol.Name, null, null, true);
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,
Xex.Term[] args)
{
Context ic = (Context) domain.context;
- State state;
- if (ic.im.states.TryGetValue (args[0].Symval, out state))
- ((Context) domain.context).shift (state);
- else
- throw new Exception ("Unknown state: " + args[0].Symval);
+ MSymbol state_name = (string) args[0].Symval;
+ State state = (State) ic.im.states.Get (state_name);
+ if (state == null)
+ throw new Exception ("Unknown state: " + state_name);
+ ((Context) domain.context).shift (state);
return args[0];
}
Xex.Variable vari,
Xex.Term[] args)
{
- return new Xex.Term (GetSurroundingText == null ? 0 : 1);
+ return new Xex.Term (((Context) domain.context).GetSurroundingText == null
+ ? -2 : -1);
}
public override string ToString ()
foreach (KeyValuePair<MSymbol, Map> kv in maps)
str += " " + kv.Value;
str += ") (states";
- foreach (KeyValuePair<Xex.Symbol, State> kv in states)
- {
- str += " (" + kv.Key + " " + kv.Value.keymap + ")";
- }
+ for (MPlist p = states; ! p.IsEmpty; p = p.next)
+ str += " (" + p.Key + " " + ((State) p.Val).keymap + ")";
return str + "))";
}
internal Xex.Domain domain;
private bool active;
+ public Callback PreeditChanged;
+ public Callback StatusChanged;
+ public Callback CandidateChanged;
+ public Callback GetSurroundingText;
+ public Callback DelSurroundingText;
+
private MText status;
private MText produced = new MText ();
internal MText preedit = new MText ();
private bool candidate_show;
public bool CandidateShow { get { return candidate_show; } }
- private State state, prev_state;
+ private State initial_state, state, prev_state;
private MText state_preedit = new MText ();
private int state_key_head;
private object state_var_values, state_initial_var_values;
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;
internal void reset ()
{
- status = im.initial_state.title;
+ status = initial_state.title;
produced.Del ();
preedit.Del ();
state_preedit.Del ();
state_var_values = state_initial_var_values;
state_pos = 0;
- shift (im.initial_state);
+ shift (initial_state);
preceding_text.Del ();
following_text.Del ();
{
if (pos < 0)
{
- if (DeleteSurroundingText != null)
+ if (DelSurroundingText != null)
{
+ Console.WriteLine ("deleting the prev {0} chars", - pos);
callback_arg.Set (MSymbol.integer, pos);
- if (DeleteSurroundingText (this, callback_arg))
+ if (DelSurroundingText (this, callback_arg))
{
if (callback_arg.IsInteger)
deleted = callback_arg.Integer - cursor_pos;
{
if (pos > preedit.Length)
{
- if (DeleteSurroundingText != null)
+ if (DelSurroundingText != null)
{
+ Console.WriteLine ("deleting the next {0} chars",
+ pos - preedit.Length);
callback_arg.Set (MSymbol.integer, pos - preedit.Length);
- if (DeleteSurroundingText (this, callback_arg))
+ if (DelSurroundingText (this, callback_arg))
{
if (callback_arg.IsInteger)
deleted = callback_arg.Integer - cursor_pos;
internal void commit ()
{
- produced.Cat (preedit);
- preedit_replace (0, preedit.Length, null, null);
- changed |= ChangedStatus.Preedit;
+ if (preedit.Length > 0)
+ {
+ Candidates.Detach (this);
+ produced.Cat (preedit);
+ preedit_replace (0, preedit.Length, null, null);
+ }
}
internal void shift (State state)
state = prev_state;
}
- if (state == im.initial_state)
+ if (state == initial_state)
{
commit ();
keys.keyseq.RemoveRange (0, key_head);
throw new Exception ("Openging " + im.tag + " failed");
this.im = im;
domain = new Xex.Domain ("context", im.domain, this);
+ initial_state = (State) im.states.Val;
state_initial_var_values = domain.SaveValues ();
reset ();
active = true;
private bool handle_key ()
{
- Console.Write ("\nHandle ({0}[{1}]) in {2}",
- keys, key_head, state.name);
-
+ Console.WriteLine ("{0}:key='{1}'", state.name, keys.keyseq[key_head]);
Keymap sub = keymap.Lookup (keys, ref key_head);
if (sub != keymap)
}
if (state == current_state)
{
- if (state == im.initial_state
+ if (state == initial_state
&& key_head < keys.keyseq.Count)
return false;
if (keymap != state.keymap)
shift (state);
else if (keymap.branch_actions == null)
- shift (im.initial_state);
+ shift (initial_state);
}
}
return true;
{
CandidateChanged (this, callback_arg);
}
+ return (! key_unhandled && produced.Length == 0);
+ }
- Console.Write ("\nPreedit(\"{0}\"/{1}), Produced({2})",
- preedit, cursor_pos, produced);
+ public bool Filter ()
+ {
+ changed = ChangedStatus.None;
+ produced.Del ();
+ preceding_text.Del ();
+ following_text.Del ();
- return (! key_unhandled && produced.Length == 0);
+ 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
+ {
+ Context ic;
+ MText mt;
+ int pos;
+
+ public Session (MInputMethod im, MText mt, int pos)
+ {
+ ic = new Context (im);
+ this.mt = mt;
+ this.pos = pos;
+ ic.GetSurroundingText = get_surrounding_text;
+ ic.DelSurroundingText = del_surrounding_text;
+ }
+
+ private bool get_surrounding_text (Context ic, MPlist args)
+ {
+ int len = args.Integer;
+ if (len < 0)
+ args.Set (MSymbol.mtext, mt[0, pos]);
+ else
+ args.Set (MSymbol.mtext, mt[pos, mt.Length]);
+ return true;
+ }
+
+ 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);
+ this.pos = pos;
+ }
+ else
+ mt.Del (this.pos, pos);
+ return true;
+ }
+
+ public bool HandleKey (ref Key key)
+ {
+ if (! ic.Filter (key))
+ {
+ MText produced = ic.Produced;
+ mt.Ins (pos, produced);
+ pos += produced.Length;
+ Key unhandled;
+ if (ic.UnhandledKey (out unhandled))
+ {
+ 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; } set { pos = value; } }
+ public MText Preedit { get { return ic.Preedit; } }
}
}
}