private static MSymbol Mvariable = "variable";
private static MSymbol Mcommand = "command";
private static MSymbol Mmodule = "module";
- private static MSymbol Mmodule_list = "module-list";
private static MSymbol Mtitle = "title";
private static MSymbol Minclude = "include";
private static MSymbol Mmacro = "macro";
- private static MSymbol Mmacro_list = "macro-list";
private static MSymbol Mmap = "map";
private static MSymbol Mmap_list = "map-list";
private static MSymbol Mstate = "state";
- private static MSymbol Mstate_list = "state-list";
internal static MSymbol Mcandidates = "candidates";
private static MSymbol Minsert = "insert";
private static MSymbol Mdelete = "delete";
internal static MInputMethod im_global = null;
- // Sub classes
- private class Exception : System.Exception
- {
- bool error;
-
- public Exception (string msg) : base (msg)
- {
- error = true;
- }
-
- public Exception (string fmt, params object[] args)
- : base (String.Format (fmt, args))
- {
- error = true;
- }
-
- public Exception (string msg, bool error) : base (msg)
- {
- this.error = error;
- }
- }
-
[FlagsAttribute]
private enum LoadStatus
{
List<MDatabase> list = MDatabase.List (tag);
M17n.DebugPrint ("Found {0} input methods\n", list.Count);
foreach (MDatabase mdb in list)
- {
- im_table[mdb.tag] = new MInputMethod (mdb.tag);
- }
- tag = new MDatabase.Tag (Minput_method, MSymbol.t, MSymbol.nil, "global");
- im_global = im_table[tag];
+ im_table[mdb.tag] = new MInputMethod (mdb.tag);
}
// Constructor
}
}
+ 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");
+ im_global = im_table[tag];
+ if (! im_global.Open ())
+ throw new Exception ("Failed to load global");
+ }
+ return im_global.domain.GetVar (name, false);
+ }
+
private void parse_variables (MPlist plist)
{
var_names = new Xex.Symbol[plist.Count];
var_names[i] = name;
p = p.next;
string desc = (string) parse_description (p);
- Xex.Variable vari
- = im_global != null ? im_global.domain.GetVar (name, false) : null;
+ Xex.Variable vari = get_global_var (name);
if (vari != null)
domain.Defvar (vari);
if (desc != null)
for (int i = 0; i < node_list.Count; i++)
{
Xex.Symbol name = node_list[i].Attributes[0].Value;
- Xex.Variable vari = im_global.domain.GetVar (name, false);
-
+ Xex.Variable vari = get_global_var (name);
if (vari != null)
domain.Defvar (vari);
else
private MText produced;
private bool active;
private MText status;
- private bool status_changed;
internal MText preedit;
- private bool preedit_changed;
internal int cursor_pos;
- private bool cursor_pos_changed;
private Candidates candidates;
private MPlist candidate_group;
private int candidate_index;
private int candidate_from, candidate_to;
private bool candidate_show;
- private bool candidate_changed;
private Stack<MInputMethod.State> states;
internal MInputMethod.KeySeq keys;
internal Xex.Domain domain;
+ [FlagsAttribute]
+ public enum ChangedStatus
+ {
+ None = 0x00,
+ StateTitle = 0x01,
+ Preedit = 0x02,
+ CursorPos = 0x04,
+ CandidateList = 0x08,
+ CandidateIndex = 0x10,
+ CandidateShow = 0x20,
+ }
+
+ private static ChangedStatus CandidateAll = (ChangedStatus.CandidateList
+ | ChangedStatus.CandidateIndex
+ | ChangedStatus.CandidateShow);
+ private ChangedStatus changed;
+
+ public ChangedStatus Changed { get { return changed; } }
+
public MInputContext (MInputMethod im)
{
this.im = im;
preedit_replace (cursor_pos, cursor_pos, arg.Intval);
else
preedit_replace (cursor_pos, cursor_pos, new MText (arg.Strval));
- preedit_changed = true;
- cursor_pos_changed = true;
+ changed |= ChangedStatus.Preedit | ChangedStatus.CursorPos;
}
private class Candidates
{
ic.preedit.PopProp (0, ic.preedit.Length, MInputMethod.Mcandidates);
ic.candidates = null;
- ic.preedit_changed = true;
- ic.cursor_pos_changed = true;
- ic.candidate_changed = true;
+ ic.changed |= (ChangedStatus.Preedit | ChangedStatus.CursorPos
+ | CandidateAll);
}
// Fill the array "group" by candidates stating from INDEX.
preedit.PushProp (candidate_from, candidate_to,
MInputMethod.Mcandidates, this);
cursor_pos = candidate_from;
- preedit_changed = true;
- cursor_pos_changed = true;
- candidate_changed = true;
+ changed |= (ChangedStatus.Preedit | ChangedStatus.CursorPos
+ | CandidateAll);
}
internal void insert_candidates (Xex.Term arg)
preedit_replace (pos, cursor_pos, null);
else
preedit_replace (cursor_pos, pos, null);
- preedit_changed = true;
- cursor_pos_changed = true;
+ changed |= ChangedStatus.Preedit | ChangedStatus.CursorPos;
}
internal void show ()
{
candidate_show = true;
- candidate_changed = true;
+ changed |= ChangedStatus.CandidateShow;
}
internal void hide ()
{
candidate_show = false;
- candidate_changed = true;
+ changed |= ChangedStatus.CandidateShow;
}
internal void move (int pos)
if (pos != cursor_pos)
{
cursor_pos = pos;
- preedit_changed = true;
+ changed |= ChangedStatus.Preedit;
}
}
{
produced.Cat (preedit);
preedit.Del ();
- preedit_changed = true;
+ changed |= ChangedStatus.Preedit;
}
internal void shift (MSymbol sym)
status = state.title;
if (status == null)
status = im.title;
- status_changed = true;
+ changed |= ChangedStatus.StateTitle;
Xex on_entry
= (Xex) state.branches.Get (MSymbol.t);
if (on_entry != null)
internal void HandleKey ()
{
- MInputMethod.State state = states.Peek ();
+ }
-
+ public bool Toggle ()
+ {
+ active = ! active;
+ return active;
}
}
}
--- /dev/null
+INPUT-METHOD =
+ '<input-method>'
+ TAGS
+ DESCRIPTION ?
+ TITLE ?
+ VARLIST ?
+ CMDLIST ?
+ MODULELIST ?
+ MACROLIST ?
+ MAPLIST ?
+ STATELIST ?
+ '</input-method>'
+
+VARLIST = '<variable-list>' DEFVAR * '</variable-list>'
+CMDLIST = '<command-list>' COMMAND * '</command-list>'
+MODULELIST = '<module-list>' MODULE * '</module-list>'
+MACROLIST = '<macro-list>' DEFUN * '</macro-list>'
+MAPLIST = '<map-list>' MAP * '</map-list>'
+STATELIST = '<state-list>' STATE * '</state-list>'
+
+MODULE = '<module>' DEFUN-NAME + '</module>'
+DEFUN-NAME = '<defun fname=">' FNAME '"/>'
+
+MAP = '<map id="' MAPNAME '">' RULE * '</map>'
+
+RULE = '<rule>' [ KEYSEQ | COMMAND-REF ] FUNCALL * '</rule>'
+
+STATE = '<state id="' STATENAME '">' BRANCH * '</state>'
+
+BRANCH = ...
+
+TERM += MIM-TERM
+PREDEFINED += MIM-PREDEFEIND
+
+MIM-TERM = KEYSEQ MARKER
+
+KEYSEQ = '<keyseq>' [ INTTERM | STRTERM | SYMTERM ] + '</keyseq>'
+KEYSEQTERM = KEYSEQ | VAR (value is KEYSEQ) | FUNCALL (return KEYSEQ)
+
+MARKER = '<marker>' SYMTERM '</marker>'
+MARKERTERM = MARKER | VAR (value is MARKER) | FUNCALL (return MARKER)
+
+
+MIM-PREDEFINED = MARK MOVE PUSHBACK ...
+
+MOVE = '<move>' [ MARKERTERM | INTTERM ] '</move>'
+MARK = '<mark>' MARKERTERM '</mark>'
+PUSHBACK = '<pushback>' [ KEYSEQTERM | INTTERM ] '</pushback>'
+...
FUNCALL =
'<funcall fname="' FNAME '">' TERM * '</funcall>'
- | '<' PREDEFINED '>' TERM * '</' PREDEFINED '>'
- | '<' PREDEFINED 'vname="' VNAME '">' TERM * '</' PREDEFINED '>'
+ | PREDEFINED
PREDEFINED =
- 'set'
- | 'and' | 'or' | 'not'
- | 'lt' | 'le' | 'eq' | 'ge' | 'gt' | 'noteq'
- | 'add' | 'sub' | 'mul' | 'div' | 'mod'
- | 'logand' | 'logior' | 'logxor' | 'lsh'
- | 'append' | 'concat' | 'length' | 'nth' | 'copy' | 'ins' | 'del'
- | 'progn' | 'if' | 'when' | 'cond'
- | 'loop' | 'while' | 'foreach' | 'break' | 'return'
- | 'quote' | 'eval' | 'type'
+ SET
+ | AND | OR | NOT
+ | LT | LE | EQ | GE | GT | NOTEQ
+ | ADD | SUB | MUL | DIV | MOD
+ | LOGAND | LOGIOR | LOGXOR | LSH
+ | APPEND | CONCAT | LENGTH | NTH | COPY | INS | DEL
+ | PROGN | IF | WHEN | COND
+ | LOOP | WHILE | FOREACH | BREAK | RETURN
+ | QUOTE | EVAL | TYPE
;; TERM has a value, and is evaluated to a TERM as below.
;; INT has an integer value, and is evaluated to itself .
INTTERM = INT | VAR (value is INT) | FUNCALL (return INT)
STRTERM = STR | VAR (value is STR) | FUNCALL (return STR)
+SYMTERM = SYMBOL | VAR (value is SYMBOL) | FUNCALL (return SYMBOL)
LISTTERM = LIST | VAR (value is LIST) | FUNCALL (return LIST)
ANYTERM = TERM
;; Here after, when an argument is TERM, it is given to a function
;; without being evaluted. Otherwise, an evaluated term is given.
-'<set vname="' VNAME '">' ANYTERM '</set>'
-'<add>' INTTERM + '</add>'
-'<add vname="' VNAME '">' INTTERM + '</add>'
-'<sub>' INTTERM + '</sub>'
-'<sub vname="' VNAME '">' INTTERM + '</sub>'
-'<mul>' INTTERM + '</mul>'
-'<mul vname="' VNAME '">' INTTERM + '</mul>'
-'<div>' INTTERM + '</div>'
-'<div vname="' VNAME '">' INTTERM + '</div>'
-'<mod>' INTTERM INTTERM '</mod>'
-'<mod vname="' VNAME '">' INTTERM '</div>'
-'<logand> INTTERM + '</logand>'
-'<logand vname="' VNAME '">' INTTERM + '</logand>'
-'<logior> INTTERM + '</logior>'
-'<logior> vname="' VNAME '">' INTTERM + '</logior>'
-'<logxor> INTTERM + '</logxor>'
-'<logxor> vname="' VNAME '">' INTTERM + '</logxor>'
-'<lsh>' INTTERM INTTERM '</lsh>'
-'<lsh vname="' VNAME '">' INTTERM '</mul>'
-'<lt>' INTTERM INTTERM '</lt>'
-'<le>' INTTERM INTTERM '</le>'
-'<eq>' INTTERM INTTERM '</eq>'
-'<noteq>' INTTERM INTTERM '</noteq>'
-'<ge>' INTTERM INTTERM '</ge>'
-'<gt>' INTTERM INTTERM '</gt>'
-'<append>' ANYTERM + '</append>'
-'<concat>' [ INTTERM | STRTERM | LISTTERM ] + '</concat>'
-'<length>' [ STRTERM | LISTTERM ] '</length>'
-'<nth>' INTTERM [ STRTERM | LISTTERM ] '</nth>'
-'<copy>' LISTTERM '</nth>'
-'<ins vname="' VNAME '">' INTTERM [ STRTERM | LISTTERM ] '</ins>'
-'<del vname="' VNAME '">' INTTERM INTTERM '</ins>'
-'<and>' TERM + '</and>'
-'<or>' TERM + '</or>'
-'<not>' TERM '</not>'
-'<progn>' TERM * '</progn>'
-'<if>' TERM TERM TERM ? '</if>'
-'<when>' TERM TERM * '</when>'
-'<cond>' LIST + '</cond>'
-'<loop>' TERM + '</loop>'
-'<while>' TERM + '</while>'
-'<foreach vname="' VNAME '">' TERM + '</foreach>'
-'<break>' ANYTERM ? '</break>'
-'<return>' ANYTERM ? '</return>'
-'<quote>' TERM '</quote>'
-'<eval>' TERM '</eval>'
-'<type>' ANYTERM '</type>'
+SET = '<set vname="' VNAME '">' ANYTERM '</set>'
+ADD = '<add>' INTTERM + '</add>'
+ | '<add vname="' VNAME '">' INTTERM + '</add>'
+SUB = '<sub>' INTTERM + '</sub>'
+ | '<sub vname="' VNAME '">' INTTERM + '</sub>'
+MUL = '<mul>' INTTERM + '</mul>'
+ | '<mul vname="' VNAME '">' INTTERM + '</mul>'
+DIB = '<div>' INTTERM + '</div>'
+ | '<div vname="' VNAME '">' INTTERM + '</div>'
+MOD = '<mod>' INTTERM INTTERM '</mod>'
+ | '<mod vname="' VNAME '">' INTTERM '</div>'
+LOGAND = '<logand> INTTERM + '</logand>'
+ | '<logand vname="' VNAME '">' INTTERM + '</logand>'
+LOGIOR = '<logior> INTTERM + '</logior>'
+ | '<logior> vname="' VNAME '">' INTTERM + '</logior>'
+LOGXOR = '<logxor> INTTERM + '</logxor>'
+ | '<logxor> vname="' VNAME '">' INTTERM + '</logxor>'
+LSH = '<lsh>' INTTERM INTTERM '</lsh>'
+ | '<lsh vname="' VNAME '">' INTTERM '</mul>'
+LT = '<lt>' INTTERM INTTERM '</lt>'
+LE = '<le>' INTTERM INTTERM '</le>'
+EQ = '<eq>' INTTERM INTTERM '</eq>'
+NOTEQ = '<noteq>' INTTERM INTTERM '</noteq>'
+GE = '<ge>' INTTERM INTTERM '</ge>'
+GT ='<gt>' INTTERM INTTERM '</gt>'
+APPEND = '<append>' ANYTERM + '</append>'
+CONCAT = '<concat>' [ INTTERM | STRTERM | LISTTERM ] + '</concat>'
+LENGTH = '<length>' [ STRTERM | LISTTERM ] '</length>'
+NTH = '<nth>' INTTERM [ STRTERM | LISTTERM ] '</nth>'
+COPY = '<copy>' LISTTERM '</nth>'
+INS = '<ins vname="' VNAME '">' INTTERM [ STRTERM | LISTTERM ] '</ins>'
+DEL = '<del vname="' VNAME '">' INTTERM INTTERM '</ins>'
+AND = '<and>' TERM + '</and>'
+OR = '<or>' TERM + '</or>'
+NOT = '<not>' TERM '</not>'
+PROGN = '<progn>' TERM * '</progn>'
+IF = '<if>' TERM TERM TERM ? '</if>'
+WHEN = '<when>' TERM TERM * '</when>'
+COND = '<cond>' LIST + '</cond>'
+LOOP = '<loop>' TERM + '</loop>'
+WHILE = '<while>' TERM + '</while>'
+FOREACH = '<foreach vname="' VNAME '">' TERM + '</foreach>'
+BREAK = '<break>' ANYTERM ? '</break>'
+RETURN = '<return>' ANYTERM ? '</return>'
+QUOTE = '<quote>' TERM '</quote>'
+EVAL = '<eval>' TERM '</eval>'
+TYPE = '<type>' ANYTERM '</type>'