X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=xex.js;h=ffcfc70f584377edce80a224a56535808c1dfb0d;hb=b80d723bac900d147bed053b5bf432fc70a0991c;hp=38068d5929f82d5cd6aa44f80ce69e819d4e1315;hpb=b65c29fb4cfe14addb2e496f2917bed497f042c2;p=m17n%2Fm17n-lib-js.git diff --git a/xex.js b/xex.js index 38068d5..ffcfc70 100644 --- a/xex.js +++ b/xex.js @@ -6,11 +6,16 @@ var Xex = { { if (! Xex.LogNode) return; - var str = ''; - if (indent != undefined) - for (var i = 0; i < indent; i++) - str += ' '; - Xex.LogNode.value = str + arg + "\n" + Xex.LogNode.value; + if (! arg) + Xex.LogNode.value = ''; + else + { + var str = ''; + if (indent != undefined) + for (var i = 0; i <= indent; i++) + str += ' '; + Xex.LogNode.value = str + arg + "\n" + Xex.LogNode.value; + } } }; @@ -660,7 +665,7 @@ Xex.Funcall = function (func, vari, args) var func = domain.GetFunc (fname); var vari; attr = node.attributes['vname']; - vari = attr != undefined ? domain.GetVarCreate (attr.nodeValue) : false; + vari = attr != undefined ? domain.GetVarCreate (attr.nodeValue) : null; var args = Xex.Term.Parse (domain, node.firstElement (), null); return new Xex.Funcall (func, vari, args); } @@ -711,8 +716,12 @@ Xex.Funcall = function (func, vari, args) str += ' vname="' + this.vari.name + '"'; if (len == 0) return str + '/>'; - for (var i = 0; i < len; i++) - arglist += '.'; //this.args[i].toString (); + if (this.func instanceof Xex.Subrountine) + for (var i = 0; i < len; i++) + arglist += this.args[i].toString (); + else + for (var i = 0; i < len; i++) + arglist += '.'; return str + '>' + arglist + ''; } @@ -794,7 +803,7 @@ Xex.StrTerm = function (str) { this.val = str; }; proto.Clone = function () { return new Xex.StrTerm (this.val); } proto.Parser = function (domain, node) { - return new Xex.StrTerm (node.firstChild.nodeValue); + return new Xex.StrTerm (node.firstChild ? node.firstChild.nodeValue : ''); } Xex.StrTerm.prototype = proto; }) (); @@ -862,6 +871,11 @@ Xex.LstTerm = function (list) { this.val = list; }; return args[0]; } + function Fnot (domain, vari, args) + { + return (args[0].IsTrue () ? Xex.Zero : Xex.One); + } + function maybe_set_intvar (vari, n) { var term = new Xex.IntTerm (n); @@ -939,6 +953,39 @@ Xex.LstTerm = function (list) { this.val = list; }; return maybe_set_intvar (vari, n); } + function Flogand (domain, vari, args) + { + var n, i; + if (vari == null) + { + Xex.Log ("logand arg args[0]" + args[0]); + n = args[0].Intval () + i = 1; + } + else + { + Xex.Log ("logand arg var " + vari); + n = vari.val.Intval (); + i = 0; + } + while (n > 0 && i < args.length) + { + Xex.Log ("logand arg " + args[i]); + n &= args[i++].val; + } + return maybe_set_intvar (vari, n); + } + + function Flsh (domain, vari, args) + { + return maybe_set_intvar (vari, args[0].Intval () << args[1].Intval ()); + } + + function Frsh (domain, vari, args) + { + return maybe_set_intvar (vari, args[0].Intval () >> args[1].Intval ()); + } + function Fand (domain, vari, args) { var len = args.length; @@ -975,13 +1022,18 @@ Xex.LstTerm = function (list) { this.val = list; }; return Xex.One; } + function Fnoteq (domain, vari, args) + { + return (Feq (domain, vari, args) == Xex.One ? Xex.Zero : Xex.One); + } + function Flt (domain, vari, args) { - var n = args[0].Intval; + var n = args[0].Intval (); for (var i = 1; i < args.length; i++) { - var n1 = args[i].Intval; + var n1 = args[i].Intval (); if (n >= n1) return Xex.Zero; n = n1; @@ -991,10 +1043,10 @@ Xex.LstTerm = function (list) { this.val = list; }; function Fle (domain, vari, args) { - var n = args[0].Intval; + var n = args[0].Intval (); for (var i = 1; i < args.length; i++) { - var n1 = args[i].Intval; + var n1 = args[i].Intval (); if (n > n1) return Xex.Zero; n = n1; @@ -1004,10 +1056,10 @@ Xex.LstTerm = function (list) { this.val = list; }; function Fgt (domain, vari, args) { - var n = args[0].Intval; + var n = args[0].Intval (); for (var i = 1; i < args.length; i++) { - var n1 = args[i].Intval; + var n1 = args[i].Intval (); if (n <= n1) return Xex.Zero; n = n1; @@ -1017,10 +1069,10 @@ Xex.LstTerm = function (list) { this.val = list; }; function Fge (domain, vari, args) { - var n = args[0].Intval; + var n = args[0].Intval (); for (var i = 1; i < args.Length; i++) { - var n1 = args[i].Intval; + var n1 = args[i].Intval (); if (n < n1) return Xex.Zero; n = n1; @@ -1149,8 +1201,8 @@ Xex.LstTerm = function (list) { this.val = list; }; basic.DefSubr (Fset, "set", true, 1, 1); basic.DefAlias ("=", "set"); - //basic.DefSubr (Fnot, "not", false, 1, 1); - //basic.DefAlias ("!", "not"); + basic.DefSubr (Fnot, "not", false, 1, 1); + basic.DefAlias ("!", "not"); basic.DefSubr (Fadd, "add", true, 1, -1); basic.DefSubr (Fmul, "mul", true, 1, -1); basic.DefAlias ("*", "mul"); @@ -1162,16 +1214,16 @@ Xex.LstTerm = function (list) { this.val = list; }; basic.DefAlias ("%", "mod"); basic.DefSubr (Flogior, "logior", true, 1, -1); basic.DefAlias ('|', "logior"); - //basic.DefSubr (Flogand, "logand", true, 1, -1); - //basic.DefAlias ("&", "logand"); - //basic.DefSubr (Flsh, "lsh", true, 1, 2); - //basic.DefAlias ("<<", "lsh"); - //basic.DefSubr (Frsh, "rsh", true, 1, 2); - //basic.DefAlias (">>", "rsh"); + basic.DefSubr (Flogand, "logand", true, 1, -1); + basic.DefAlias ("&", "logand"); + basic.DefSubr (Flsh, "lsh", true, 1, 2); + basic.DefAlias ("<<", "lsh"); + basic.DefSubr (Frsh, "rsh", true, 1, 2); + basic.DefAlias (">>", "rsh"); basic.DefSubr (Feq, "eq", false, 2, -1); basic.DefAlias ("==", "eq"); - //basic.DefSubr (Fnoteq, "noteq", false, 2, 2); - //basic.DefAlias ("!=", "noteq"); + basic.DefSubr (Fnoteq, "noteq", false, 2, 2); + basic.DefAlias ("!=", "noteq"); basic.DefSubr (Flt, "lt", false, 2, -1); basic.DefAlias ("<", "lt"); basic.DefSubr (Fle, "le", false, 2, -1); @@ -1296,6 +1348,8 @@ var MIM = { keysyms["del"] = "delete"; function decode_keysym (str) { + if (str.length == 1) + return str; var parts = str.split ("-"); var len = parts.length, i; var has_modifier = len > 1; @@ -1333,7 +1387,9 @@ var MIM = { { this.key; this.has_modifier = false; - if (typeof val == 'string' || val instanceof String) + if (val instanceof Xex.Term) + this.key = val.val; + else if (typeof val == 'string' || val instanceof String) { this.key = decode_keysym (val); if (! this.key) @@ -1366,12 +1422,14 @@ var MIM = { var len = seq.val.length; for (var i = 0; i < len; i++) { - var v = seq.val[i]; - if (v.type != 'string' && v.type != 'integer' - && v.type != 'symbol') + var v = seq.val[i], key; + if (v.type == 'symbol' || v.type == 'string') + key = new MIM.Key (v); + else if (v.type == 'integer') + key = new MIM.Key (v.val); + else throw new Xex.ErrTerm (MIM.Error.ParseError, "Invalid key: " + v); - var key = new MIM.Key (v.val); this.val.push (key); if (key.has_modifier) this.has_modifier = true; @@ -1433,19 +1491,11 @@ var MIM = { return ic.preedit.charCodeAt (p); } - MIM.NamedMarker = function (name) { this.val = name; } - MIM.NamedMarker.prototype = new MIM.Marker (); - MIM.NamedMarker.prototype.Position = function (ic) - { - var p = ic.marker_positions[this.val]; - if (p == undefined) - Xex.Log ('no position of ' + this.val); - return (p == undefined ? 0 : p); - } - MIM.NamedMarker.prototype.Mark = function (ic) - { - ic.marker_positions[this.val] = ic.cursor_pos; - } + MIM.FloatingMarker = function (name) { this.val = name; }; + var proto = new MIM.Marker (); + MIM.FloatingMarker.prototype = proto; + proto.Position = function (ic) { return ic.marker_positions[this.val]; }; + proto.Mark = function (ic) { ic.marker_positions[this.val] = ic.cursor_pos; }; MIM.PredefinedMarker = function (name) { this.val = name; } MIM.PredefinedMarker.prototype = new MIM.Marker (); @@ -1525,12 +1575,12 @@ var MIM = { var n = predefined[name]; if (n) return n; - if (name.charAt (1) == '-') + if (name.charAt (1) == '-' || name.charAt (1) == '+') return new MIM.SurroundMarker (name); throw new Xex.ErrTerm (MIM.Error.ParseError, "Invalid marker: " + name); } - return new MIM.NamedMarker (name); + return new MIM.FloatingMarker (name);; } }) (); @@ -1986,7 +2036,7 @@ MIM.im_domain.DefType (MIM.State.prototype); { var ic = domain.context; var gsize = domain.variables['candidates_group_size']; - var candidates = new MIM.Candidates (args, gsize ? gsize.Intval : 0); + var candidates = new MIM.Candidates (args, gsize ? gsize.Intval () : 0); ic.ins (candidates.Current (), candidates); return args[0]; } @@ -1994,7 +2044,7 @@ MIM.im_domain.DefType (MIM.State.prototype); function Fdelete (domain, vari, args) { var ic = domain.context; - var pos = args[0].IsInt ? args[0].Intval : args[0].Position (ic); + var pos = args[0].IsInt ? args[0].Intval () : args[0].Position (ic); return new Xex.IntTerm (ic.del (pos)); } @@ -2010,10 +2060,24 @@ MIM.im_domain.DefType (MIM.State.prototype); ic.rep (old_text, new_text, can); } else - Xex.Log ('no candidates'); + Xex.Log ('no candidates at ' + ic.cursor_pos + ' of ' + ic.candidate_table.table.length); return args[0]; } + function Fshow (domain, vari, args) + { + domain.context.candidate_show = true; + domain.context.changed |= MIM.ChangedStatus.CandidateShow; + return Xex.nil; + } + + function Fhide (domain, vari, args) + { + domain.context.candidate_show = false; + domain.context.changed |= MIM.ChangedStatus.CandidateShow; + return Xex.nil; + } + function Fchar_at (domain, vari, args) { return new Xex.IntTerm (args[0].CharAt (domain.context)); @@ -2042,6 +2106,14 @@ MIM.im_domain.DefType (MIM.State.prototype); return args[0]; } + function Fpop (domain, vari, args) + { + var ic = domain.context; + if (ic.key_head < ic.keys.val.length) + ic.keys.val.splice (ic.keys_head, 1); + return Xex.nil; + } + function Fundo (domain, vari, args) { var ic = domain.context; @@ -2077,6 +2149,17 @@ MIM.im_domain.DefType (MIM.State.prototype); return args[0]; } + function Fshiftback (domain, vari, args) + { + domain.context.shift (null); + return Xex.nil; + } + + function Fkey_count (domain, vari, args) + { + return new Xex.IntTerm (domain.context.key_head); + } + function Fsurrounding_flag (domain, vari, args) { return new Xex.IntTerm (-1); @@ -2086,19 +2169,19 @@ MIM.im_domain.DefType (MIM.State.prototype); 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-candidates", false, 0, 0); - //im_domain.DefSubr (Fhide, "hide-candidates", 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 (Fpop, "pop", false, 0, 0); + im_domain.DefSubr (Fpop, "pop", false, 0, 0); im_domain.DefSubr (Fundo, "undo", false, 0, 1); im_domain.DefSubr (Fcommit, "commit", false, 0, 0); im_domain.DefSubr (Funhandle, "unhandle", false, 0, 0); im_domain.DefSubr (Fshift, "shift", false, 1, 1); - //im_domain.DefSubr (Fshiftback, "shiftback", false, 0, 0); + 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, 0, 0); + im_domain.DefSubr (Fkey_count, "key-count", false, 0, 0); im_domain.DefSubr (Fsurrounding_flag, "surrounding-text-flag", false, 0, 0); }) (); @@ -2286,7 +2369,7 @@ MIM.im_domain.DefType (MIM.State.prototype); this.state = null; this.initial_state = this.im.initial_state; this.keys = new MIM.KeySeq (); - this.marker_positions = {}; + this.marker_positions = new Array (); this.candidate_table = new MIM.CandidateTable (); this.reset (); } @@ -2296,12 +2379,12 @@ MIM.im_domain.DefType (MIM.State.prototype); this.table = new Array (); } - MIM.CandidateTable.prototype.get = function (from) + MIM.CandidateTable.prototype.get = function (pos) { for (var i = 0; i < this.table.length; i++) { var elt = this.table[i]; - if (elt.from <= from && elt.to > from) + if (elt.from < pos && pos <= elt.to) return elt.val; } } @@ -2311,8 +2394,7 @@ MIM.im_domain.DefType (MIM.State.prototype); for (var i = 0; i < this.table.length; i++) { var elt = this.table[i]; - if (elt.from >= from && elt.from < to - || elt.to >= from && elt.to < to) + if (elt.from < to && elt.to > from) { elt.from = from; elt.to = to; @@ -2326,6 +2408,8 @@ MIM.im_domain.DefType (MIM.State.prototype); MIM.CandidateTable.prototype.adjust = function (from, to, inserted) { var diff = inserted - (to - from); + if (diff == 0) + return; for (var i = 0; i < this.table.length; i++) { var elt = this.table[i]; @@ -2347,18 +2431,15 @@ MIM.im_domain.DefType (MIM.State.prototype); ic.candidate_table.clear (); ic.candidates = null; ic.changed |= (MIM.ChangedStatus.Preedit | MIM.ChangedStatus.CursorPos - | ChangedStatus.CandidateList - | ChangedStatus.CandidateIndex - | ChangedStatus.CandidateShow); + | MIM.ChangedStatus.CandidateList + | MIM.ChangedStatus.CandidateIndex + | MIM.ChangedStatus.CandidateShow); } function set_cursor (prefix, pos) { this.cursor_pos = pos; - if (pos > 0) - this.candidates = this.candidate_table.get (pos - 1); - else - this.candidates = null; + this.candidates = this.candidate_table.get (pos); } function save_state () @@ -2452,8 +2533,8 @@ MIM.im_domain.DefType (MIM.State.prototype); proto = { reset: function () { + Xex.Log ('reseting ' + this.im.lang); this.cursor_pos = 0; - this.candidates = null; this.candidate_show = false; this.prev_state = null; this.title = this.initial_state.title; @@ -2542,21 +2623,15 @@ MIM.im_domain.DefType (MIM.State.prototype); { var diff = inserted - (to - from); - for (var m in this.marker_positions) + for (var name in this.marker_positions) { - var pos = this.marker_positions[m]; + var pos = this.marker_positions[name]; if (pos > from) { if (pos >= to) - { - this.marker_positions[m] = pos + diff; - Xex.Log ('Marker ' + m + ' = ' + this.marker_positions[m]); - } + this.marker_positions[name] += diff; else if (pos > from) - { - this.marker_positions[m] = from; - Xex.Log ('Marker ' + m + ' = ' + this.marker_positions[m]); - } + this.marker_positions[name] = from; } } if (this.cursor_pos >= to) @@ -2831,22 +2906,64 @@ MIM.im_domain.DefType (MIM.State.prototype); keys[0x90] = "numlock"; keys[0xF0] = "capslock"; + var keyids = {}; + keyids['U+0008'] = 'backspace'; + keyids['U+0009'] = 'tab'; + keyids['U+0018'] = 'cancel'; + keyids['U+001B'] = 'escape'; + keyids['U+0020'] = 'space'; + keyids['U+007F'] = 'delete'; + + var modifiers = {} + modifiers.Shift = 1; + modifiers.Control = 1; + modifiers.Alt = 1; + modifiers.AltGraph = 1; + modifiers.Meta = 1 + MIM.decode_key_event = function (event) { - var key = ((event.type == 'keydown' || event.keyCode) ? event.keyCode + var key = event.keyIdentifier; + + if (key) // keydown event of Chrome + { + if (modifiers[key]) + return false; + var mod = ''; + if (event.ctrlKey) mod += 'C-'; + if (event.metaKey) mod += 'M-'; + if (event.altKey) mod += 'A-'; + var keysym = keyids[key]; + if (keysym) + key = keysym; + else if (key.match(/^U\+([0-9A-Z]+)$/)) + { + if (mod.length == 0) + return false; + key = String.fromCharCode (parseInt (RegExp.$1, 16)); + } + else + key = key.toLowerCase (); + if (event.shiftKey) mod += 'S-'; + return new MIM.Key (mod + key); + } + else + { + key = ((event.type == 'keydown' || event.keyCode) ? event.keyCode : event.charCode ? event.charCode : false); - if (! key) - return false; - if (event.type == 'keydown') - { - key = keys[key]; if (! key) return false; - if (event.shiftKey) key = "S-" + key ; + if (event.type == 'keydown') + { + key = keys[key]; + if (! key) + return false; + if (event.shiftKey) key = "S-" + key ; + } + else + key = String.fromCharCode (key); } - else - key = String.fromCharCode (key); if (event.altKey) key = "A-" + key ; if (event.ctrlKey) key = "C-" + key ; return new MIM.Key (key); @@ -2877,10 +2994,10 @@ MIM.debug_print = function (event, ic) if (! MIM.debug_nodes) { MIM.debug_nodes = new Array (); - MIM.debug_nodes['keydown'] = document.getElementById ('keydown'); - MIM.debug_nodes['keypress'] = document.getElementById ('keypress'); MIM.debug_nodes['status0'] = document.getElementById ('status0'); MIM.debug_nodes['status1'] = document.getElementById ('status1'); + MIM.debug_nodes['keydown'] = document.getElementById ('keydown'); + MIM.debug_nodes['keypress'] = document.getElementById ('keypress'); MIM.debug_nodes['keymap0'] = document.getElementById ('keymap0'); MIM.debug_nodes['keymap1'] = document.getElementById ('keymap1'); MIM.debug_nodes['preedit0'] = document.getElementById ('preedit0'); @@ -2888,11 +3005,11 @@ MIM.debug_print = function (event, ic) } var target = event.target; var code = event.keyCode; - var ch = event.type == 'keydown' ? 0 : event.charCode; + var ch = event.type == 'keypress' ? event.charCode : 0; var key = MIM.decode_key_event (event); var index; - MIM.debug_nodes[event.type].innerHTML = "" + code + "/" + ch + " : " + key; + MIM.debug_nodes[event.type].innerHTML = "" + code + "/" + ch + ":" + key + '/' + event.keyIdentifier; index = (event.type == 'keydown' ? '0' : '1'); if (ic) MIM.debug_nodes['status' + index].innerHTML = ic.im.load_status; @@ -3003,6 +3120,19 @@ MIM.keydown = function (event) } MIM.debug_print (event, ic); ic.key = MIM.decode_key_event (event); + if (ic.key) + { + Xex.Log ("filtering " + ic.key); + try { + var result = ic.Filter (ic.key); + } catch (e) { + Xex.Log ('Error;' + e); + throw (e); + } + MIM.update (target, ic); + if (! ic.key_unhandled) + event.preventDefault (); + } }; MIM.keypress = function (event) @@ -3028,76 +3158,280 @@ MIM.keypress = function (event) } Xex.Log ("filtering " + ic.key); - var result = ic.Filter (ic.key); + try { + var result = ic.Filter (ic.key); + } catch (e) { + Xex.Log ('Error;' + e); + throw (e); + } MIM.update (target, ic); if (! ic.key_unhandled) event.preventDefault (); + } catch (e) { + Xex.Log ("error:" + e); + event.preventDefault (); } finally { MIM.debug_print (event, ic); } return; }; -MIM.select_im = function (event) -{ - var target = event.target.parentNode; - while (target.tagName != "SELECT") - target = target.parentNode; - var idx = 0; - var im = false; - for (var lang in MIM.imlist) - for (var name in MIM.imlist[lang]) - if (idx++ == target.selectedIndex) - { - im = MIM.imlist[lang][name]; - break; - } - document.getElementsByTagName ('body')[0].removeChild (target); - target.target.focus (); - if (im && im != MIM.current) - { - MIM.current = im; - Xex.Log ('select IM: ' + im.name); - } -}; +(function () { + var lang_category = { + European: { + cs: { name: 'Czech' }, + da: { name: 'Danish' }, + el: { name: 'Greek' }, + en: { name: 'English' }, + eo: { name: 'Esperanto' }, + fr: { name: 'French' }, + grc: { name: 'ClassicGreek' }, + hr: { name: 'Croatian' }, + hy: { name: 'Armenian' }, + ka: { name: 'Georgian' }, + kk: { name: 'Kazakh' }, + ru: { name: 'Russian' }, + sk: { name: 'Slovak' }, + sr: { name: 'Serbian' }, + sv: { name: 'Swedish' }, + vi: { name: 'Vietnamese' }, + yi: { name: 'Yiddish' } }, + MiddleEast: { + ar: { name: 'Arabic' }, + dv: { name: 'Divehi' }, + fa: { name: 'Persian' }, + he: { name: 'Hebrew' }, + kk: { name: 'Kazakh' }, + ps: { name: 'Pushto' }, + ug: { name: 'Uighur' }, + yi: { name: 'Yiddish' } }, + SouthAsia: { + as: { name: 'Assamese' }, + bn: { name: 'Bengali' }, + bo: { name: 'Tibetan' }, + gu: { name: 'Gujarati' }, + hi: { name: 'Hindi' }, + kn: { name: 'Kannada' }, + ks: { name: 'Kashmiri' }, + ml: { name: 'Malayalam' }, + mr: { name: 'Marathi' }, + ne: { name: 'Nepali' }, + or: { name: 'Oriya' }, + pa: { name: 'Panjabi' }, + sa: { name: 'Sanskirit' }, + sd: { name: 'Sindhi' }, + si: { name: 'Sinhalese' }, + ta: { name: 'Tamil' }, + te: { name: 'Telugu' }, + ur: { name: 'Urdu' } }, + SouthEastAsia: { + cmc: { name: 'Cham' }, + km: { name: 'Khmer'}, + lo: { name: 'Lao' }, + my: { name: 'Burmese' }, + tai: { name: 'Tai Viet' }, + th: { name: 'Thai' }, + vi: { name: 'Vietanamese' } }, + EastAsia: { + ii: { name: 'Yii' }, + ja: { name: 'Japanese' }, + ko: { name: 'Korean' }, + zh: { name: 'Chinese' } }, + Other: { + am: { name: 'Amharic' }, + ath: { name: 'Carrier' }, + bla: { name: 'Blackfoot' }, + cr: { name: 'Cree' }, + eo: { name: 'Esperanto' }, + iu: { name: 'Inuktitut' }, + nsk: { name: 'Naskapi' }, + oj: { name: 'Ojibwe' }, + t: { name: 'Generic' } } + }; + + function categorize_im () + { + var cat, lang, list, name; + for (lang in MIM.imlist) + { + list = null; + for (cat in lang_category) + if (lang_category[cat][lang]) + { + list = lang_category[cat][lang].list; + if (! list) + list = lang_category[cat][lang].list = {}; + break; + } + if (list) + for (name in MIM.imlist[lang]) + list[name] = MIM.imlist[lang][name]; + else + for (name in MIM.imlist[lang]) + Xex.Log ('no category ' + lang + '-' + name); + } + } -MIM.destroy_menu = function (event) -{ - if (event.target.tagName == "SELECT") - document.getElementsByTagName ('body')[0].removeChild (event.target); -}; + var destroy_timer; + var last_target; -MIM.select_menu = function (event) -{ - var target = event.target; + function destroy () + { + clearTimeout (destroy_timer); + destroy_timer = null; + var target = document.getElementById ('mim-menu'); + if (target) + { + for (; last_target && last_target.menu_level; + last_target = last_target.parentLi) + last_target.style.backgroundColor = 'white'; + var nodes = target.getElementsByTagName ('ul'); + for (var i = 0; i < nodes.length; i++) + nodes[i].style.visibility = 'hidden'; + document.getElementsByTagName ('body')[0].removeChild (target); + } + } - if (! ((target.type == "text" || target.type == "textarea") - && event.which == 1 && event.ctrlKey)) - return; + function destroy_menu () { + if (! destroy_timer) + destroy_timer = setTimeout (destroy, 1000); + } - var sel = document.createElement ('select'); - sel.onclick = MIM.select_im; - sel.onmouseout = MIM.destroy_menu; - sel.style.position='absolute'; - sel.style.left = (event.clientX - 10) + "px"; - sel.style.top = (event.clientY - 10) + "px"; - sel.target = target; - var idx = 0; - for (var lang in MIM.imlist) - for (var name in MIM.imlist[lang]) - { - var option = document.createElement ('option'); - var imname = lang + "-" + name; - option.appendChild (document.createTextNode (imname)); - option.value = imname; - sel.appendChild (option); - if (MIM.imlist[lang][name] == MIM.current) - sel.selectedIndex = idx; - idx++; - } - sel.size = idx; - document.getElementsByTagName ('body')[0].appendChild (sel); -}; + function show_submenu (event) + { + if (destroy_timer) + { + clearTimeout (destroy_timer); + destroy_timer = null; + } + var target = event.target; + if (! target.menu_level) + return; + if (last_target && target.parentLi != last_target) + { + last_target.style.backgroundColor = 'white'; + if (target.menu_level < last_target.menu_level) + { + last_target = last_target.parentLi; + last_target.style.backgroundColor = 'white'; + } + var uls = last_target.getElementsByTagName ('ul'); + for (var i = 0; i < uls.length; i++) + uls[i].style.visibility = 'hidden'; + } + last_target = target; + target.style.backgroundColor = 'yellow'; + if (target.menu_level < 3) + { + target.lastChild.style.visibility = 'visible'; + target.lastChild.style.left = target.clientWidth + 'px'; + } + event.preventDefault (); + } + + function select_im (event) + { + var target = event.target; + if (target.im) + { + MIM.current = target.im; + destroy (); + } + event.preventDefault (); + } + + function create_ul (visibility) + { + var ul = document.createElement ('ul'); + ul.style.position = 'absolute'; + ul.style.margin = '0px'; + ul.style.padding = '0px'; + ul.style.border = '1px solid gray'; + ul.style.borderBottom = 'none'; + ul.style.top = '-1px'; + ul.style.backgroundColor = 'white'; + ul.style.visibility = visibility; + return ul; + } + + function create_li (level, text) + { + var li = document.createElement ('li'); + li.style.position = 'relative'; + li.style.margin = '0px'; + li.style.padding = '1px'; + li.style.borderBottom = '1px solid gray'; + li.style.top = '0px'; + li.style.listStyle = 'none'; + li.menu_level = level; + li.appendChild (document.createTextNode (text)); + return li; + } + + var menu; + + function create_menu (event) + { + var target = event.target; + + if (! ((target.type == "text" || target.type == "textarea") + && event.which == 1 && event.ctrlKey)) + return; + if (! menu) + { + categorize_im (); + menu = create_ul ('visible'); + menu.style.fontFamily = 'sans-serif'; + menu.style.fontWeight = 'bold'; + menu.id = 'mim-menu'; + menu.onclick = select_im; + menu.onmouseover = show_submenu; + menu.onmouseout = destroy_menu; + for (var catname in lang_category) + { + var cat = lang_category[catname]; + var li = create_li (1, catname); + var sub = create_ul ('hidden'); + for (var langname in cat) + { + var lang = cat[langname]; + if (! lang.list) + continue; + var sub_li = create_li (2, lang.name); + sub_li.parentLi = li; + var subsub = create_ul ('hidden'); + for (var name in lang.list) + { + var im = lang.list[name]; + var subsub_li = create_li (3, im.name); + subsub_li.parentLi = sub_li; + subsub_li.im = im; + subsub.appendChild (subsub_li); + } + sub_li.appendChild (subsub); + sub.appendChild (sub_li); + } + li.appendChild (sub); + menu.appendChild (li); + } + document.mimmenu = menu; + lang_category = null; + } + menu.style.left = (event.clientX - 10) + "px"; + menu.style.top = (event.clientY - 10) + "px"; + document.getElementsByTagName ('body')[0].appendChild (menu); + }; + + MIM.init = function () + { + MIM.add_event_listener (window, 'keydown', MIM.keydown); + MIM.add_event_listener (window, 'keypress', MIM.keypress); + MIM.add_event_listener (window, 'mousedown', create_menu); + if (window.location == 'http://localhost/mim/index.html') + MIM.server = 'http://localhost/mim'; + MIM.current = MIM.imlist['vi']['telex']; + }; +}) (); MIM.test = function () { @@ -3122,19 +3456,10 @@ MIM.test = function () } -MIM.init = function () -{ - MIM.add_event_listener (window, 'keydown', MIM.keydown); - MIM.add_event_listener (window, 'keypress', MIM.keypress); - MIM.add_event_listener (window, 'mousedown', MIM.select_menu); - if (window.location == 'http://localhost/mim/index.html') - MIM.server = 'http://localhost/mim'; - MIM.current = MIM.imlist['vi']['telex']; -}; - MIM.init_debug = function () { MIM.debug = true; Xex.LogNode = document.getElementById ('log'); + Xex.Log (null); MIM.init (); };