private static MSymbol Mat_minus_zero = "@-0";
- private static Xex.Symbol Nmap = "map";
- private static Xex.Symbol Nrule = "rule";
- private static Xex.Symbol Nkeyseq = "keyseq";
- private static Xex.Symbol Nprogn = "progn";
- private static Xex.Symbol Ninsert = "insert";
- private static Xex.Symbol Ninsert_candidates = "insert-candidates";
- private static Xex.Symbol Nchar_at = "char-at";
+ private static Xex.Symbol Qmap = "map";
+ private static Xex.Symbol Qrule = "rule";
+ private static Xex.Symbol Qkeyseq = "keyseq";
+ private static Xex.Symbol Qprogn = "progn";
+ private static Xex.Symbol Qinsert = "insert";
+ private static Xex.Symbol Qinsert_candidates = "insert-candidates";
+ private static Xex.Symbol Qchar_at = "char-at";
+ private static Xex.Symbol Qsname = "sname";
+ private static Xex.Symbol Qmname = "mname";
+ private static Xex.Symbol Qstate_hook = "state-hook";
+ private static Xex.Symbol Qcatch_all_branch = "catch-all-branch";
+ private static Xex.Symbol Qbranch = "branch";
+ private static Xex.Symbol Qstate = "state";
+ private static Xex.Symbol Qtitle = "title";
+
private static Xex.Term Tnil = new Xex.Term ((Xex.Symbol) "nil");
private static Xex.Term Tcatch_tag = new Xex.Term ((Xex.Symbol) "@mimtag");
&& ((m1 & KeyModifier.High) == (m2 & KeyModifier.High)));
}
+ public int ToChar ()
+ {
+ return key & 0x1FFFFF;
+ }
+
public override string ToString ()
{
string str = Char.ToString ((char) key);
selectors["@last"] = new Selector ('>');
selectors["@previous"] = new Selector ('-');
selectors["@next"] = new Selector ('+');
- selectors["@previous-candidate-list"] = new Selector ('[');
- selectors["@next-candidate-list"] = new Selector (']');
+ selectors["@previous-candidate-change"] = new Selector ('[');
+ selectors["@next-candidate-change"] = new Selector (']');
}
private char tag;
}
}
- internal class Branch
+ internal class Keymap
{
- public MSymbol name;
- public Keymap keymap;
- public Xex.Term[] enter_actions, fallback_actions;
- }
+ public Dictionary<Key, Keymap> submaps;
+ public Xex.Term[] map_actions, branch_actions;
- public class Keymap
- {
- public Dictionary<Key, Keymap> keymaps;
- public Xex.Term[] map_actions, branch_actions;
+ public Keymap () { }
- public void Add (KeySeq keys, int index,
- Xex.Term[] map_actions, Xex.Term[] branch_actions)
- {
- Map sub = null;
+ public void Add (KeySeq keys, int index,
+ Xex.Term[] map_actions, Xex.Term[] branch_actions)
+ {
+ if (index == keys.keyseq.Count)
+ {
+ this.map_actions = map_actions;
+ this.branch_actions = branch_actions;
+ }
+ else
+ {
+ Key key = keys.keyseq[index];
+ Keymap sub = null;
- if (submaps == null)
- submaps = new Dictionary<Key, Map> ();
- else
- submaps.TryGetValue (keys.keyseq[index], out sub);
- if (sub == null)
- {
- Key key = keys.keyseq[index];
- submaps[key] = sub = new Map ();
- }
- if (index + 1 < keys.keyseq.Count)
- sub.Add (keys, index + 1, actions);
- else
- this.actions = actions;
- }
+ if (submaps == null)
+ submaps = new Dictionary<Key, Keymap> ();
+ else
+ submaps.TryGetValue (key, out sub);
+ if (sub == null)
+ submaps[key] = sub = new Keymap ();
+ sub.Add (keys, index + 1, map_actions, branch_actions);
+ }
}
- public void AddMap (Map map, Xex.Term[] actions)
+ public void AddMap (Map map, Xex.Term[] branch_actions)
{
foreach (Map.Entry entry in map.entries)
- {
- Add (entry.keyseq, 0, entry.actions, actions)
- }
+ Add (entry.keyseq, 0, entry.actions, branch_actions);
}
- public void Add (KeySeq keys, int index,
- Xex.Term[] map_actions, Xex.Term[] branch_actions)
- public Xex.Term Lookup (KeySeq keys, ref int index)
+ public Keymap Lookup (KeySeq keys, ref int index)
{
- if (index < keys.keyseq.Count)
+ Keymap sub;
+
+ if (index < keys.keyseq.Count
+ && submaps != null
+ && submaps.TryGetValue (keys.keyseq[index], out sub))
{
- Map sub;
- if (submaps.TryGetValue (keys.keyseq[index], out sub))
- {
- index++;
- return sub.Lookup (keys, ref index);
- }
- return Tnil;
+ index++;
+ return sub.Lookup (keys, ref index);
}
- return actions;
+ return this;
}
private void describe (MText mt, KeySeq keyseq)
{
- if (keyseq.keyseq.Count > 0)
+ if (map_actions != null || branch_actions != null)
{
- mt.Cat (" (").Cat (keyseq.ToString ());
- mt.Cat (' ').Cat (actions.ToString ());
+ if (mt.Length > 0)
+ mt.Cat (" ");
+ mt.Cat ('(').Cat (keyseq.ToString ());
+ if (map_actions != null)
+ foreach (Xex.Term term in map_actions)
+ mt.Cat (' ').Cat (term.ToString ());
+ if (branch_actions != null)
+ foreach (Xex.Term term in branch_actions)
+ mt.Cat (' ').Cat (term.ToString ());
mt.Cat (')');
}
if (submaps != null)
- foreach (KeyValuePair<Key, Map> kv in submaps)
+ foreach (KeyValuePair<Key, Keymap> kv in submaps)
{
keyseq.keyseq.Add (kv.Key);
kv.Value.describe (mt, keyseq);
public override string ToString ()
{
- MText mt = "(" + name.Name;
+ MText mt = "";
KeySeq keyseq = new KeySeq ();
describe (mt, keyseq);
{
public Xex.Symbol name;
public MText title;
- public MPlist branches = new MPlist ();
+ public Xex.Term[] enter_actions, fallback_actions;
+ public Keymap keymap;
- public State (Xex.Symbol name)
+ public State (Xex.Symbol name, MText title)
{
this.name = name;
+ this.title = title;
+ }
+
+ public State (MInputMethod im, XmlNode node)
+ {
+ this.name = node.Attributes[Qsname].Value;
+ XmlAttribute attr = node.Attributes[Qtitle];
+ if (attr != null)
+ title = (MText) attr.Value;
+ keymap = new Keymap ();
+ for (node = node.FirstChild; node != null; node = node.NextSibling)
+ {
+ if (node.Name == Qstate_hook)
+ enter_actions = Xex.ParseTerms (im.domain, node.FirstChild);
+ else if (node.Name == Qcatch_all_branch)
+ fallback_actions = Xex.ParseTerms (im.domain, node.FirstChild);
+ else if (node.Name == Qbranch)
+ {
+ MSymbol mapname = node.Attributes[Qmname].Value;
+ Map map;
+ if (im.maps.TryGetValue (mapname, out map))
+ keymap.AddMap (map, Xex.ParseTerms (im.domain,
+ node.FirstChild));
+ else
+ throw new Exception ("Unknown map: " + mapname);
+ }
+ }
+ }
+
+ public State (MInputMethod im, MPlist plist)
+ {
+ if (! plist.IsSymbol)
+ throw new Exception ("Invalid state: " + plist);
+ this.name = plist.Symbol.Name;
+ plist = plist.next;
+ if (plist.IsMText)
+ {
+ this.title = plist.Text;
+ plist = plist.next;
+ }
+ keymap = new Keymap ();
+ for (; ! plist.IsEmpty; plist = plist.next)
+ {
+ if (! plist.IsPlist)
+ throw new Exception ("Invalid branch: " + plist);
+ MPlist p = plist.Plist;
+ if (! p.IsSymbol)
+ throw new Exception ("Invalid branch: " + p);
+ MSymbol mapname = p.Symbol;
+ if (mapname == MSymbol.t)
+ enter_actions = im.parse_actions (p.next);
+ else if (mapname == MSymbol.nil)
+ fallback_actions = im.parse_actions (p.next);
+ else
+ {
+ Map map;
+ if (im.maps.TryGetValue (mapname, out map))
+ keymap.AddMap (map, im.parse_actions (p.next));
+ else
+ throw new Exception ("Unknown map: " + mapname);
+ }
+ }
}
public override string ToString ()
if (title != null)
mt.Cat (" \"" + title + "\"");
- for (MPlist p = branches; ! p.IsEmpty; p = p.next)
- mt.Cat (" (" + p.Key + " " + (Xex) p.Val + ")");
+ mt += keymap.ToString ();
return (string) mt + ")";
}
}
private void add_default_state ()
{
- Xex.Symbol Ninit = "init";
- State state = new State (Ninit);
+ Xex.Symbol Qinit = "init";
+ State state = new State (Qinit, null);
foreach (KeyValuePair<MSymbol, Map>kv in maps)
- state.branches.Add (kv.Key, null);
- states[Ninit] = initial_state = state;
+ state.keymap.AddMap (kv.Value, null);
+ states[Qinit] = initial_state = state;
}
private void load (MPlist plist, bool full)
private void parse_maps (XmlNode node)
{
for (node = node.FirstChild; node != null; node = node.NextSibling)
- if (node.Name == Nmap)
+ 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 == Nrule)
+ if (nd.Name == Qrule)
{
XmlNode n = nd.FirstChild;
- if (n.Name != Nkeyseq)
+ if (n.Name != Qkeyseq)
continue;
KeySeq keyseq = (KeySeq) KeySeq.parser (domain, n);
Xex.Term[] actions = Xex.ParseTerms (domain, n.NextSibling);
}
}
+ private void parse_states (MPlist plist)
+ {
+ for (; ! plist.IsEmpty; plist = plist.next)
+ if (plist.IsPlist)
+ {
+ State state = new State (this, plist.Plist);
+ states[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;
+ }
}
private void parse_include (MPlist plist)
else
throw new Exception ("Invalid candidates: " + pl);
}
- return new Xex.Term (domain, Ninsert_candidates, args);
+ return new Xex.Term (domain, Qinsert_candidates, args);
}
else
throw new Exception ("Invalid arg to insert: " + plist);
args = new Xex.Term[1];
args[0] = arg;
- return new Xex.Term (domain, Ninsert, args);
+ return new Xex.Term (domain, Qinsert, args);
}
private Xex.Term parse_select (MPlist plist)
{
Xex.Term[] args = new Xex.Term[1];
args[0] = new Xex.Term (Marker.Get (name));
- return new Xex.Term (domain, Nchar_at, args);
+ return new Xex.Term (domain, Qchar_at, args);
}
private Xex.Term parse_action (MPlist plist)
}
}
- private void parse_states (MPlist plist)
- {
- for (; ! plist.IsEmpty; plist = plist.next)
- if (plist.IsPlist)
- {
- MPlist pl = plist.Plist;
- MText title = null;
-
- if (pl.IsMText)
- {
- title = pl.Text;
- pl = pl.next;
- }
- if (! pl.IsSymbol)
- continue;
-
- Xex.Symbol name = (Xex.Symbol) pl.Symbol.Name;
- State state = new State (name);
- state.title = title;
- if (states.Count == 0)
- initial_state = state;
- states[name] = state;
- for (pl = pl.next; ! pl.IsEmpty; pl = pl.next)
- {
- if (! pl.IsPlist)
- continue;
- MPlist p = pl.Plist;
- if (! p.IsSymbol)
- continue;
- MSymbol map_name = p.Symbol;
- p = p.next;
- Xex.Term term = new Xex.Term (domain, Nprogn, parse_actions (p));
- state.branches.Add (map_name, term);
- }
- }
- }
-
private static Xex.Term Finsert (Xex.Domain domain, Xex.Variable vari,
Xex.Term[] args)
{
public class Context
{
- internal static Xex.Symbol Ncandidates_group_size
+ internal static Xex.Symbol Qcandidates_group_size
= "candidates-group-size";
private MInputMethod im;
private Dictionary<MSymbol, Callback> callbacks
private int candidate_from, candidate_to;
private bool candidate_show;
- private List<State> state_list;
+ private List<State> state_list = new List<State> state_list ();
+ private Keymap keymap;
// Sequence of input keys.
- internal KeySeq keys;
+ internal KeySeq keys = new KeySeq ();
// Index into KEYS specifying the next key to handle.
internal int key_head;
internal void insert_candidates (Xex.Term arg)
{
int column = 0;
- Xex.Variable v = domain.GetVar (Ncandidates_group_size, false);
+ Xex.Variable v = domain.GetVar (Qcandidates_group_size, false);
if (v != null)
column = v.Value.Intval;
if (status == null)
status = im.title;
this.changed |= ChangedStatus.StateTitle;
- Xex on_entry
- = (Xex) state.branches.Get (MSymbol.t);
- if (on_entry != null)
+ if (state.enter_actions != null)
on_entry.Eval (domain);
}
}
produced.Del ();
markers.Clear ();
cursor_pos = 0;
+ keys.keyseq.Clear ();
key_head = commit_key_head = 0;
state_list.Clear ();
state_list.Add (im.initial_state);
- state_key_head = 0;
+ keymap = im.initial_state.keymap;
+ key_head = state_key_head = 0;
state_pos = 0;
}
{
this.im = im;
domain = new Xex.Domain (im.domain, this);
- state_list.Clear ();
- state_list.Add (im.initial_state);
- keys = new KeySeq ();
+ reset ();
}
public ChangedStatus Changed { get { return changed; } }
private bool handle_key ()
{
State state = state_list[state_list.Count - 1];
- for (MPlist *p = state.branches; ! p.IsEmpty; p = p.next)
+ Keymap sub = keymap.Lookup (keys, ref key_head);
+
+ if (sub != keymap)
{
- int n = state_key_head;
- Xex.Term term = ((Map) p.Val).Lookup (keys, ref n);
+ keymap = sub;
+ if (keymap->map_actions)
+ {
+ restore_state ();
+ if (! take_action (keymap->map_actions))
+ return false;
+ }
+ else if (keymap->submaps != null)
+ {
+ for (int i = state_key_head; i < n; i++)
+ preedit_replace (cursor_pos, cursor_pos,
+ keys.keyseq[i].ToChar ());
+ }
+ if (keymap->submaps == null)
+ {
+ if (keymap->branch_actions != null)
+ {
+ if (! take_action (keymap->branch_actions))
+ return false;
+ }
+ if (keymap != state->keymap)
+ shift (state->name);
+ }
+ }
+ else
+ {
+ if (keymap->branch_actions)
+ {
+ if (! take_action (keymap->branch_actions))
+ return false;
+ }
-
}
-
}
public bool Toggle ()
public override string ToString () { return name; }
}
- private static Symbol Nexpr = "expr";
-
- private static Symbol Nnull = "";
- private static Symbol Nfuncall = "funcall";
- private static Symbol Nvarref = "varref";
- private static Symbol Ninteger = "integer";
- private static Symbol Nstring = "string";
- private static Symbol Nsymbol = "symbol";
- private static Symbol Nlist = "list";
-
- private static Symbol Ndefun = "defun";
- private static Symbol Nfname = "fname";
- private static Symbol Nargs = "args";
- private static Symbol Nargs_unevalled = "args-unevalled";
- private static Symbol Nfixed = "fixed";
- private static Symbol Noptional = "optional";
- private static Symbol Nrest = "rest";
-
- private static Symbol Ndefvar = "defvar";
- private static Symbol Nvname = "vname";
- private static Symbol Ndescription = "description";
- private static Symbol Nrange = "range";
+ private static Symbol Qexpr = "expr";
+
+ private static Symbol Qnull = "";
+ private static Symbol Qfuncall = "funcall";
+ private static Symbol Qvarref = "varref";
+ private static Symbol Qinteger = "integer";
+ private static Symbol Qstring = "string";
+ private static Symbol Qsymbol = "symbol";
+ private static Symbol Qlist = "list";
+
+ private static Symbol Qdefun = "defun";
+ private static Symbol Qfname = "fname";
+ private static Symbol Qargs = "args";
+ private static Symbol Qargs_unevalled = "args-unevalled";
+ private static Symbol Qfixed = "fixed";
+ private static Symbol Qoptional = "optional";
+ private static Symbol Qrest = "rest";
+
+ private static Symbol Qdefvar = "defvar";
+ private static Symbol Qvname = "vname";
+ private static Symbol Qdescription = "description";
+ private static Symbol Qrange = "range";
public abstract class Function
{
int nfixed = 0;
int noptional = 0;
int nrest = 0;
- name = node.Attributes[Nfname].Value;
+ name = node.Attributes[Qfname].Value;
node = node.FirstChild;
if (node != null
- && (node.Name == Nargs || node.Name == Nargs_unevalled))
+ && (node.Name == Qargs || node.Name == Qargs_unevalled))
{
XmlNode n;
- args_evalled = node.Name == Nargs;
+ args_evalled = node.Name == Qargs;
for (n = node.FirstChild; n != null; n = n.NextSibling)
{
- if (n.Name == Nfixed)
+ if (n.Name == Qfixed)
nfixed++;
- else if (n.Name == Noptional)
+ else if (n.Name == Qoptional)
noptional++;
- else if (n.Name == Nrest)
+ else if (n.Name == Qrest)
nrest++;
else
throw new Exception ("Invalid argument type: " + n);
{
int i = 0;
for (i = 0; i < args.Length; i++, nfixed++)
- if (args[i] == Noptional || args[i] == Nrest)
+ if (args[i] == Qoptional || args[i] == Qrest)
break;
if (i < args.Length)
{
- if (args[i] == Noptional)
+ if (args[i] == Qoptional)
{
for (i++; i < args.Length; i++, noptional++)
- if (args[i] == Nrest)
+ if (args[i] == Qrest)
break;
if (i < args.Length)
nrest = 1;
this.args = new Variable[max_arg];
int j;
for (i = j = 0; j < this.args.Length; i++)
- if (args[i] != Noptional || args[i] != Nrest)
+ if (args[i] != Qoptional || args[i] != Qrest)
this.args[j++] = domain.Defvar (args[i]);
}
else
public void SetBody (Domain domain, XmlNode node)
{
for (node = node.FirstChild; node != null; node = node.NextSibling)
- if (node.Name != Ndescription
- && node.Name != Nargs
- && node.Name != Nargs_unevalled)
+ if (node.Name != Qdescription
+ && node.Name != Qargs
+ && node.Name != Qargs_unevalled)
break;
int nterms = 0;
for (XmlNode n = node; n != null; n = n.NextSibling)
public void Defun (XmlNode node, bool prototype)
{
- Symbol name = node.Attributes[Nfname].Value;
+ Symbol name = node.Attributes[Qfname].Value;
Function func;
if (prototype || ! functions.TryGetValue (name, out func))
Variable vari;
node = node.FirstChild;
- if (node != null && node.Name == Ndescription)
+ if (node != null && node.Name == Qdescription)
{
desc = node.InnerText;
node = node.NextSibling;
nranges = range_list.Count;
}
- if (type == Ninteger)
+ if (type == Qinteger)
{
int intval = parse_integer (val);
int[] range = null;
for (int i = 0; i < nranges; i++)
{
XmlNode n = range_list[i];
- if (n.Name == Nrange)
+ if (n.Name == Qrange)
{
range[i * 2]
= parse_integer (n.FirstChild.InnerText);
else
vari = new Variable.Int (name, desc, intval, range);
}
- else if (type == Nstring)
+ else if (type == Qstring)
{
string[] range = null;
if (range_list != null)
else
vari = new Variable.Str (name, desc, val, range);
}
- else if (type == Nsymbol)
+ else if (type == Qsymbol)
{
Symbol[] range = null;
if (range_list != null)
throw new Exception ("Invalid number of arguments to: "
+ fname + " " + nargs);
this.args = args;
- if (vname != Nnull)
+ if (vname != Qnull)
vari = domain.GetVar (vname, true);
}
internal static TermValue parser (Domain domain, XmlNode node)
{
Symbol fname = node.Name;
- Symbol vname = Nnull;
+ Symbol vname = Qnull;
XmlAttribute attr;
- if (fname == Nfuncall)
- fname = node.Attributes[Nfname].Value;
- attr = node.Attributes[Nvname];
+ if (fname == Qfuncall)
+ fname = node.Attributes[Qfname].Value;
+ attr = node.Attributes[Qvname];
if (attr != null)
vname = attr.Value;
{
Symbol name = node.Name;
- if (name == Ninteger)
+ if (name == Qinteger)
{
intval = parse_integer (node.InnerText);
objval = null;
else
{
intval = 0;
- if (name == Nsymbol)
+ if (name == Qsymbol)
objval = (Symbol) node.InnerText;
- else if (name == Nstring)
+ else if (name == Qstring)
objval = node.InnerText.Clone ();
- else if (name == Nvarref)
+ else if (name == Qvarref)
objval = domain.GetVar ((Symbol) node.Attributes[0].Value, true);
- else if (name == Nlist)
+ else if (name == Qlist)
{
List<Term> list = new List<Term> ();
for (node = node.FirstChild; node != null;
static private Term Zero = new Term (0);
static private Term One = new Term (1);
- static private Term TermInt = new Term (Ninteger);
- static private Term TermStr = new Term (Nstring);
- static private Term TermSymbol = new Term (Nsymbol);
- static private Term TermList = new Term (Nlist);
+ static private Term TermInt = new Term (Qinteger);
+ static private Term TermStr = new Term (Qstring);
+ static private Term TermSymbol = new Term (Qsymbol);
+ static private Term TermList = new Term (Qlist);
static private Term TermTerm = new Term ((Symbol) "term");
internal static int parse_integer (string str)
for (XmlNode n = node; n != null; n = n.NextSibling)
if (n.NodeType == XmlNodeType.Element)
{
- if (n.Name == Ndefun)
+ if (n.Name == Qdefun)
domain.Defun (n, true);
- else if (n.Name == Ndefvar)
+ else if (n.Name == Qdefvar)
domain.Defvar (n);
else
nterms++;
for (XmlNode n = node; n != null; n = n.NextSibling)
if (n.NodeType == XmlNodeType.Element)
{
- if (n.Name == Ndefun)
+ if (n.Name == Qdefun)
domain.Defun (n, false);
- else if (n.Name != Ndefvar)
+ else if (n.Name != Qdefvar)
terms[i++]= new Term (domain, n);
}
return terms;
reader.Read ();
} while (reader.NodeType != XmlNodeType.None
&& (reader.NodeType != XmlNodeType.Element
- || reader.Name != Nexpr));
+ || reader.Name != Qexpr));
if (reader.NodeType == XmlNodeType.None)
throw new Exception ("Node <expr> not found");
node = doc.ReadNode (reader);