this.actions = actions;
}
- public Xex.Term Lookup (KeySeq keys, int index)
+ public Xex.Term Lookup (KeySeq keys, ref index)
{
- Map sub;
-
- if (index + 1 == keys.keyseq.Count)
- return actions;
- if (submaps.TryGetValue (keys.keyseq[index], out sub))
- return sub.Lookup (keys, index + 1);
- return Tnil;
+ if (index < keys.keyseq.Count)
+ {
+ Map sub;
+ if (submaps.TryGetValue (keys.keyseq[index], out sub))
+ {
+ index++;
+ return sub.Lookup (keys, ref index);
+ }
+ return Tnil;
+ }
+ return actions;
}
private void describe (MText mt, KeySeq keyseq)
if (! plist.IsPlist)
throw new Exception ("Invalid cond args: " + plist);
MPlist p = plist.Plist;
- List<Xex.Term> arg = new List<Xex.Term> (parse_action (p));
+ List<Xex.Term> arg = new List<Xex.Term> (parse_actions (p));
args[i] = new Xex.Term (arg);
}
return new Xex.Term (domain, (Xex.Symbol) Mcond.Name, args);
}
- private Xex.Term[] parse_action (MPlist plist)
+ private Xex.Term parse_integer (MPlist plist)
{
- Xex.Term[] terms = new Xex.Term[plist.Count];
+ if (plist.IsSymbol)
+ {
+ Xex.Variable vari = domain.GetVar (Xex.Name (plist.Symbol.Name),
+ true);
+ Xex.Term[] args = Xex.Term[1];
+ args[0] = new Xex.Term (vari);
+ terms[i] = new Xex.Term (domain, Ninsert, args);
+ }
+ else if (plist.IsMText)
+ {
+ Xex.Term[] args = Xex.Term[1];
+ args[0] = new Xex.Term ((string) plist.Text);
+ terms[i] = new Xex.Term (domain, Ninsert, args);
+ }
+ else if (plist.IsInteger)
+ {
+ Xex.Term[] args = Xex.Term[1];
+ args[0] = new Xex.Term (plist.Integer);
+ terms[i] = new Xex.Term (domain, Ninsert, args);
+ }
+ }
- for (int i = 0; ! plist.IsEmpty; i++, plist = plist.next)
+ private Xex.Term parse_action (MPlist plist)
+ {
+ if (plist.IsPlist)
{
- if (plist.IsSymbol)
- terms[i] = new Xex.Term ((Xex.Symbol) plist.Symbol.Name);
- else if (plist.IsMText)
- terms[i] = new Xex.Term ((string) plist.Text);
- else if (plist.IsInteger)
- terms[i] = new Xex.Term (plist.Integer);
- else if (plist.IsPlist)
+ MPlist p = plist.Plist;
+
+ if (p.IsMText || p.IsPlist)
+ return parse_integer (p);
+ if (! p.IsSymbol)
+ throw new Exception ("Invalid action: " + p);
+ MSymbol name = p.Symbol;
+ p = p.next;
+ if (name == Mcond)
+ return parse_cond (p);
+ else if (name == Mset || name == Madd || name == Msub
+ || name == Mmul || name == Mdiv)
{
- MPlist p = plist.Plist;
if (! p.IsSymbol)
throw new Exception ("Invalid action: " + p);
- MSymbol name = p.Symbol;
- p = p.next;
- if (name == Mcond)
- terms[i] = parse_cond (p);
- else if (name == Mset || name == Madd || name == Msub
- || name == Mmul || name == Mdiv)
- {
- if (! p.IsSymbol)
- throw new Exception ("Invalid action: " + p);
- Xex.Symbol varname = p.Symbol.Name;
- terms[i] = new Xex.Term (domain, (Xex.Symbol) name.Name,
- varname, parse_action (p.next));
- }
- else
- terms[i] = new Xex.Term (domain, (Xex.Symbol) name.Name,
- parse_action (p));
+ Xex.Symbol varname = p.Symbol.Name;
+ return new Xex.Term (domain, (Xex.Symbol) name.Name,
+ varname, parse_actions (p.next));
}
else
- throw new Exception ("Invalid action: " + plist);
+ return new Xex.Term (domain, (Xex.Symbol) name.Name,
+ parse_actions (p));
}
+ else if (plist.MText || plist.Integer || plist.IsSymbol)
+ retunr parse_insert (plist);
+ else
+ throw new Exception ("Invalid action: " + plist);
+ }
+
+ private Xex.Term[] parse_actions (MPlist plist)
+ {
+ Xex.Term[] terms = new Xex.Term[plist.Count];
+
+ for (int i = 0; ! plist.IsEmpty; i++, plist = plist.next)
+ terms[i] = parse_action (plist);
return terms;
}
continue;
transform (p.next);
domain.Defun ((Xex.Symbol) p.Symbol.Name, false, null,
- parse_action (p.next), false);
+ parse_actions (p.next), false);
}
}
if (p.IsEmpty)
continue;
map.Add (keys, 0,
- new Xex.Term (domain, Nprogn, parse_action (p)));
+ new Xex.Term (domain, Nprogn, parse_actions (p)));
}
}
}
continue;
MSymbol map_name = p.Symbol;
p = p.next;
- Xex.Term term = new Xex.Term (domain, Nprogn, parse_action (p));
+ Xex.Term term = new Xex.Term (domain, Nprogn, parse_actions (p));
state.branches.Add (map_name, term);
}
}
private int candidate_from, candidate_to;
private bool candidate_show;
- private Stack<State> state_stack;
+ private List<State> state_list;
+
+ // Sequence of input keys.
internal KeySeq keys;
+
+ // Index into KEYS specifying the next key to handle.
internal int key_head;
+
+
private int state_key_head;
private object state_var_values;
private int commit_key_head;
internal MPlist markers = new MPlist ();
internal MText preceding_text = new MText ();
internal MText following_text = new MText ();
+
+ // Set to false before calling the method 'handle_key', and set
+ // to true when some key is unhandled.
private bool key_unhandled;
+ // The unhandled key. It has the meaning only when
+ // 'key_unhandled' is true.
+ private Key unhandled_key;
+
internal Xex.Domain domain;
internal ChangedStatus changed;
{
this.im = im;
domain = new Xex.Domain (im.domain, this);
- state_stack = new Stack<State> ();
- state_stack.Push ((State) im.states.val);
+ state_list = new List<State> ();
+ state_list.Add ((State) im.states.val);
keys = new KeySeq ();
}
if (sym == MSymbol.t)
{
- if (state_stack.Count > 1)
- state = state_stack.Pop ();
- else
- state = state_stack.Peek ();
+ state = state_list.Last ();
+ if (state_list.Count > 1)
+ state_list.RemoveAt (state_list.Count - 1)
}
else
{
throw new Exception ("Unknown state: " + state.name);
}
if (state == null)
- state = state_stack.Pop ();
+ {
+ state = state_list.Last;
+ state_list.RemoveAt (state_list.Count -1);
+ }
if (state == (State) im.states.val)
{
commit ();
state_key_head = key_head;
state_pos = cursor_pos;
state_preedit = preedit.Dup ();
- if (state != state_stack.Peek ())
+ if (state != state_list.Last ())
{
- state_stack.Push (state);
+ state_list.Add (state);
state_var_values = domain.SaveValues ();
status = state.title;
if (status == null)
markers.Clear ();
cursor_pos = 0;
key_head = commit_key_head = 0;
- state_stack.Clear ();
- state_stack.Push ((State) im.states.Val);
+ state_list.Clear ();
+ state_list.Add ((State) im.states.Val);
state_key_head = 0;
state_pos = 0;
}
active = ! active;
return active;
}
+
+ public bool UnhandledKey (out const Key key)
+ {
+ key = unhandled_key;
+ return key_unhandled;
+ }
+
+ public bool Produced (out const MText mt)
+ {
+ mt = produced;
+ return (produced.Length > 0);
+ }
+
+
+ // Return value:
+ // true: All keys are handled and there's no text to commit.
+ // false: Some key is unhandled or there's a text to commit.
+ // The caller should use methods UnhandledKey and Produced.
+
+ public bool Filter (Key key)
+ {
+ if (check_reload (key))
+ return true;
+ changed = ChangedStatus.None;
+ produced.Del ();
+ preceding_text.Del ();
+ following_text.Del ();
+
+ key_unhandled = false;
+ keys.Add (key);
+ int count = 0;
+ while (key_head < keys.Length)
+ {
+ if (! handle_key ())
+ {
+ unhandled_key = keys[key_head++];
+ key_unhandled = true;
+ break;
+ }
+ if (++count == 100)
+ break;
+ }
+ keys.RemoveRange (0, key_head);
+ return (! key_unhandled && produced.Length == 0);
+ }
}
}
}