--- /dev/null
+/*
+ Ajax IME: http://ajaxime.chasen.org/
+ Author: Taku Kudo <taku@chasen.org>
+
+ (C) Taku Kudo, all rights reserve rd.
+ Personal use only!
+*/
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//
+// Comment by kazawa
+// We cannot simply define getComputedStyle() in "if" block because it seems
+// like Safari overwrites functions during parsing the script i.e, before
+// execution (bug?). So we substitue it at run time instead.
+//
+// *** TESTED ONLY ON Firefox3 AND Safari3 ***
+//
+if (typeof(getComputedStyle) == 'undefined') {
+ function capitalize(prop) {
+ return prop.replace(/-(.)/g, function(m, m1) { return m1.toUpperCase(); })
+ }
+ function getComputedStyle(element, pseudo){
+ return {
+ currentStyle : element.currentStyle,
+ getPropertyValue : function(prop){
+ return this.currentStyle[capitalize(prop)];
+ },
+ setProperty : function(prop, value){
+ this.currentStyle[capitalize(prop)] = value;
+ }
+ }
+ }
+
+// getComputedStyle == __getComputedStyle;
+}
+
+function JSONRequest(url) {
+ this.url_ = url;
+ this.parent_ = document.getElementsByTagName('head').item(0);
+ this.obj_ = document.createElement('script');
+ this.obj_.setAttribute('type', 'text/javascript');
+ this.obj_.setAttribute('charset', 'utf-8');
+ this.obj_.setAttribute('src', this.url_);
+ this.parent_.appendChild(this.obj_);
+}
+
+JSONRequest.prototype.remove = function () {
+ this.parent_.removeChild(this.obj_);
+}
+
+function getEvent (evt) {
+ return (evt) ? evt : ((window.event) ? event : null);
+}
+
+function getKeyCode(event) {
+ var evt = getEvent(event);
+ return ((evt.which) ? evt.which : evt.keyCode);
+}
+
+function callWithDelay(func, delay) {
+ if (delay) setTimeout(func, 0);
+ else func();
+}
+
+function addEvent(obj, event, func) {
+ if (obj.addEventListener) {
+ obj.addEventListener(event, func, false);
+ } else if(obj.attachEvent){
+ obj.attachEvent('on' + event, func);
+ } else {
+ }
+}
+
+function copyFontStyle(elmOriginal, elmClone) {
+ var styleOriginal = getComputedStyle(elmOriginal,'');
+ var styleClone = getComputedStyle(elmClone,'');
+ elmClone.style["fontFamily"] = styleOriginal.getPropertyValue("font-family");
+ elmClone.style["fontSize"] = styleOriginal.getPropertyValue("font-size");
+ elmClone.style["fontWeight"] = styleOriginal.getPropertyValue('font-weight');
+ elmClone.style["fontVariant"] = styleOriginal.getPropertyValue('font-variant');
+}
+
+function cloneElement(elmOriginal, elmClone) {
+ var styleOriginal = getComputedStyle(elmOriginal,'');
+
+ var styleClone = getComputedStyle(elmClone,'');
+ elmClone.style.left = elmOriginal.offsetLeft + 'px';
+ elmClone.style.top = (elmOriginal.offsetTop + elmOriginal.offsetHeight + 30) + 'px';
+
+ elmClone.style["width"] = styleOriginal.getPropertyValue('width');
+ elmClone.style["height"] = styleOriginal.getPropertyValue('height');
+ elmClone.style["padding"] = styleOriginal.getPropertyValue('padding');
+ elmClone.style["paddingLeft"] = styleOriginal.getPropertyValue('padding-left');
+ elmClone.style["paddingRight"] = styleOriginal.getPropertyValue('padding-right');
+ elmClone.style["paddingTop"] = styleOriginal.getPropertyValue('padding-top');
+ elmClone.style["paddingBottom"] = styleOriginal.getPropertyValue('padding-bottom');
+ elmClone.style["borderStyle"] = styleOriginal.getPropertyValue('border-style');
+ elmClone.style["borderLeftStyle"] = styleOriginal.getPropertyValue('border-left-style');
+ elmClone.style["borderRightStyle"] = styleOriginal.getPropertyValue('border-right-style');
+ elmClone.style["borderTopStyle"] = styleOriginal.getPropertyValue('border-top-style');
+ elmClone.style["borderBottomStyle"] = styleOriginal.getPropertyValue('border-bottom-style');
+ elmClone.style["borderLeftWidth"] = styleOriginal.getPropertyValue('border-left-width');
+ elmClone.style["borderRightWidth"] = styleOriginal.getPropertyValue('border-right-width');
+ elmClone.style["borderTopWidth"] = styleOriginal.getPropertyValue('border-top-width');
+ elmClone.style["borderBottomWidth"] = styleOriginal.getPropertyValue('border-bottom-width');
+ elmClone.style["borderWidth"] = styleOriginal.getPropertyValue('border-width');
+ elmClone.style["fontFamily"] = styleOriginal.getPropertyValue('font-family');
+ elmClone.style["fontSize"] = styleOriginal.getPropertyValue('font-size');
+ elmClone.style["fontVariant"] = styleOriginal.getPropertyValue('font-variant');
+ elmClone.style["fontWeight"] = styleOriginal.getPropertyValue('font-weight');
+ elmClone.style["lineHeight"] = styleOriginal.getPropertyValue('line-height');
+ elmClone.style["letterSpacing"] = styleOriginal.getPropertyValue('letter-spacing');
+ elmClone.style["wordSpacing"] = styleOriginal.getPropertyValue('word-spacing');
+ elmClone.style.width = elmOriginal.offsetWidth;
+ elmClone.style.height = elmOriginal.offsetHeight;
+ elmClone.scrollLeft = elmOriginal.scrollLeft;
+ elmClone.scrollTop = elmOriginal.scrollTop;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+var ImeCGI_ = "http://api.chasen.org/ajaxime/";
+var ImeBackGroundColor_ = 'aliceblue';
+var ImeID_ = 0;
+var ImeCache_ = [];
+var ImeCurrentDocument_ = null;
+
+function AjaxIME(doc) {
+ var ImeJsonp_ = null;
+ var ImeJsonpLog_ = null;
+ var ImeDocument_ = doc;
+ var ImeMode_ = null;
+ var ImeResults_ = [];
+ var ImeTo_ = 0;
+ var ImeNumResults_ = 0;
+ var ImeLoaded_ = false;
+ var ImeCandidates_ = null;
+ var ImePreEdit_ = null;
+ var ImePreEditWidth_ = 0;
+ var ImeWindow_ = null;
+ var ImeTextArea_ = null;
+ var ImeTextAreaClone_ = null;
+ var ImeSelectedIndex_ = -1;
+ var ImeStartPos_ = 0;
+ var ImeEndPos_ = 0;
+
+ // initializer
+ {
+ if (ImeLoaded_) return;
+ ImeWindow_ = ImeDocument_.createElement('div');
+ ImePreEdit_ = ImeDocument_.createElement('input');
+ ImePreEdit_.setAttribute('type', 'text');
+ ImePreEdit_.setAttribute('autocomplete', 'off');
+ ImeCandidates_ = ImeDocument_.createElement('div');
+ ImeTextAreaClone_ = ImeDocument_.createElement('pre');
+ ImePreEdit_.__ImeUsed = ImeTextAreaClone_.__ImeUsed = true;
+ ImeWindow_.appendChild(ImePreEdit_);
+ ImeWindow_.appendChild(ImeCandidates_);
+ ImeDocument_.body.appendChild(ImeWindow_);
+
+ ImeWindow_.style.position = 'absolute';
+ ImeWindow_.style.margin = '0px';
+ ImeWindow_.style.padding = '0px';
+ ImeWindow_.style.textAlign = 'left';
+ ImePreEdit_.style.backgroundColor = ImeBackGroundColor_;
+ ImePreEdit_.style.borderWidth = '0px';
+ ImePreEdit_.style.textDecoration = 'underline';
+ ImePreEdit_.style.textUnderLineColor = 'red';
+ ImePreEdit_.style.textAlign = 'left';
+ ImeCandidates_.style.padding = '0px';
+ ImeCandidates_.style.borderColor = '#000';
+ ImeCandidates_.style.borderWidth = '1px';
+ ImeCandidates_.style.borderStyle = 'solid';
+ ImeCandidates_.style.styleFloat = 'left'; // IE
+ ImeCandidates_.style.cssFloat = 'left'; // Firefox
+ ImeCandidates_.style.textAlign = 'left';
+
+ ImeDocument_.ImeRequestCallback = ImeRequestCallback;
+ ImeDocument_.ImeChangeMode = ImeChangeMode;
+
+ addEvent(ImeDocument_, 'keydown', ImeDocumentKeyDown);
+ addEvent(ImePreEdit_, 'keydown', ImePreEditKeyDown);
+ addEvent(ImePreEdit_, 'keyup', ImePreEditKeyUp);
+
+ setInterval(ImeInitTextAreas, 500);
+ ImeLoaded_ = true;
+
+ ImeHide();
+ }
+
+ function ImeInitTextAreas() {
+ var inputs = ImeDocument_.getElementsByTagName('input');
+ for (var i = 0; i < inputs.length; ++i) {
+ if (inputs[i].type == 'text') ImeInitTextAreaEvent(inputs[i]);
+ }
+
+ var textareas = ImeDocument_.getElementsByTagName('textarea');
+ for (var i = 0; i < textareas.length; ++i) {
+ ImeInitTextAreaEvent(textareas[i]);
+ }
+ }
+
+ function ImeInitTextAreaEvent(textarea) {
+ if (!textarea.__ImeUsed && !textarea.__ImeRegistered) {
+ addEvent(textarea, 'keydown', ImeTextAreaKeyDown);
+ addEvent(textarea, 'click', ImeHide);
+ textarea.__ImeRegistered = true;
+ }
+ }
+
+ function ImeSetCaretPos(pos) {
+ if (ImeTextArea_.setSelectionRange) { // Mozilla
+ ImeTextArea_.setSelectionRange(pos, pos);
+ } else if (ImeDocument_.selection.createRange ){ // IE
+ var e = ImeTextArea_.createTextRange();
+ var tx = ImeTextArea_.value.substr(0, pos);
+ var pl = tx.split(/\n/);
+ e.collapse(true);
+ e.moveStart('character', pos - pl.length + 1);
+ e.collapse(false);
+ e.select();
+ }
+ ImeTextArea_.focus();
+ }
+
+ function ImeStoreCaretPos() {
+ var startpos = 0;
+ var endpos = 0;
+ if (ImeTextArea_.setSelectionRange) { // mozilla
+ startpos = ImeTextArea_.selectionStart;
+ endpos = ImeTextArea_.selectionEnd;
+ } else if (ImeDocument_.selection.createRange) { // IE
+ if (ImeTextArea_.type == 'textarea') {
+ ImeTextArea_.caretPos = ImeDocument_.selection.createRange().duplicate();
+ var sel = ImeDocument_.selection.createRange();
+ var r = ImeTextArea_.createTextRange();
+ var len = ImeTextArea_.value.length;
+ r.moveToPoint(sel.offsetLeft, sel.offsetTop);
+ r.moveEnd('textedit');
+ startpos = len - r.text.length
+ endpos = startpos + sel.text.length;
+ } else {
+ var r = ImeDocument_.selection.createRange();
+ var len = ImeTextArea_.value.length;
+ r.moveEnd('textedit');
+ startpos = len - r.text.length
+ endpos = startpos;
+ }
+ }
+ ImeStartPos_ = startpos;
+ ImeEndPos_ = endpos;
+ }
+
+ function ImeStoreWindowPos() {
+ var x = 0;
+ var y = 0;
+ var x2 = ImeDocument_.body.scrollTop;
+ var y2 = ImeDocument_.body.scrollLeft;
+
+ if (! ImeTextArea_.createTextRange || ImeTextArea_.type != 'textarea') {
+ for (var o = ImeTextArea_; o ; o = o.offsetParent) {
+ x2 += (o.offsetLeft - o.scrollLeft);
+ y2 += (o.offsetTop - o.scrollTop);
+ }
+ }
+
+ if (ImeTextArea_.selectionStart || ImeTextArea_.selectionStart == '0') { // Mozilla
+ cloneElement(ImeTextArea_, ImeTextAreaClone_);
+ ImeTextArea_.offsetParent.appendChild(ImeTextAreaClone_);
+ var value = ImeTextArea_.value.replace(/\r\n/g, '\n\r') + ' ';
+ var caretPos = ImeDocument_.createElement('span');
+ caretPos.innerHTML = '|';
+ ImeTextAreaClone_.innerHTML = '';
+ ImeTextAreaClone_.appendChild(ImeDocument_.createTextNode(value.substr(0,ImeStartPos_)));
+ ImeTextAreaClone_.appendChild(caretPos);
+ ImeTextAreaClone_.appendChild(ImeDocument_.createTextNode(value.substr(ImeStartPos_)));
+ y = y2 + (caretPos.offsetTop - ImeTextAreaClone_.offsetTop);
+ x = x2 + (caretPos.offsetLeft - ImeTextAreaClone_.offsetLeft);
+ ImeTextArea_.offsetParent.removeChild(ImeTextAreaClone_);
+ } else {
+ var caretPos = ImeDocument_.selection.createRange();
+ y = y2 + (caretPos.offsetTop + ImeDocument_.documentElement.scrollTop - 3); // why -3 ??
+ x = x2 + (caretPos.offsetLeft + ImeDocument_.documentElement.scrollLeft);
+ }
+
+ ImeWindow_.style.top = y + 'px';
+ ImeWindow_.style.left = x + 'px';
+ }
+
+ function ImeInsertText(text, delay) {
+ var func = function() { ImeSetCaretPos(ImeStartPos_ + text.length); }
+
+ if (ImeTextArea_.createTextRange && ImeTextArea_.caretPos) {
+ var caretPos = ImeTextArea_.caretPos;
+ caretPos.text = caretPos.text.charAt(caretPos.text.length - 1) == ' ' ?
+ text + ' ' : text;
+ callWithDelay(func, delay);
+ } else {
+ var tmpTop = ImeTextArea_.scrollTop;
+ var tmpLeft = ImeTextArea_.scrollLeft;
+ ImeTextArea_.value = ImeTextArea_.value.substring(0, ImeStartPos_) +
+ text + ImeTextArea_.value.substring(ImeEndPos_, ImeTextArea_.value.length);
+ callWithDelay(func, delay);
+ ImeTextArea_.scrollTop = tmpTop;
+ ImeTextArea_.scrollLeft = tmpLeft;
+ }
+ }
+
+ function ImeAdd(text, selected) {
+ if (text == '') return;
+
+ if (selected) ImeSelectedIndex_ = ImeNumResults_;
+
+ var n = ImeNumResults_;
+ ImeResults_[ImeNumResults_++] = text;
+
+ if (text.length > ImePreEditWidth_)
+ ImePreEditWidth_ = text.length;
+
+ var div = ImeDocument_.createElement('div');
+ div.style.width = '100%';
+ div.style.styleFloat = 'left';
+ div.style.cssFloat = 'left';
+ if (selected) {
+ div.style.backgroundColor = '#36c';
+ div.style.color = '#fff';
+ } else {
+ div.style.backgroundColor = '#fff';
+ div.style.color = '#000';
+ }
+
+ var txt = ImeDocument_.createTextNode(text);
+ var span = ImeDocument_.createElement('span');
+ span.appendChild(txt);
+ copyFontStyle(ImeTextArea_, span);
+ addEvent(div, 'click', function() {
+ ImeSelectedIndex_ = n; ImeSelect(true); ImeHide(); });
+ div.appendChild(span);
+ ImeCandidates_.appendChild(div);
+ }
+
+ function ImeHandleDown() {
+ if (ImeIsHidden()) return;
+ ++ImeSelectedIndex_;
+ if (ImeSelectedIndex_ == ImeNumResults_) ImeSelectedIndex_ = 0;
+ ImeHighlight();
+ }
+
+ function ImeHandleUp() {
+ if (ImeIsHidden()) return;
+ --ImeSelectedIndex_;
+ if (ImeSelectedIndex_ < 0) ImeSelectedIndex = ImeNumResults_ - 1;
+ ImeHighlight();
+ }
+
+ function ImeHighlight() {
+ var divs = ImeCandidates_.getElementsByTagName('div');
+ for (var i = 0; i < divs.length; ++i) {
+ if (i == ImeSelectedIndex_) {
+ ImePreEdit_.value = ImeResults_[i];
+ divs[i].style.backgroundColor = '#36c';
+ divs[i].style.color = '#fff';
+ } else {
+ divs[i].style.backgroundColor = '#fff';
+ divs[i].style.color = '#000';
+ }
+ }
+ }
+
+ function ImeNop() {
+ ImeInsertText('', false);
+ if (ImeRawInput_ != '')
+ ImeLog('cancel');
+ }
+
+ function ImeSelect(delay) {
+ var result = ImeResults_.length ? ImeResults_[ImeSelectedIndex_] : ImePreEdit_.value;
+ ImeInsertText(result, delay);
+ ImeLog(result);
+ }
+
+ function ImeIsHidden() {
+ return (ImeCandidates_.style.display == 'none');
+ }
+
+ function ImeHideCandidates() {
+ ImeCandidates_.style.display = 'none';
+ ImeCandidates_.innerHTML = '';
+ }
+
+ function ImeHide() {
+ ImeWindow_.style.display = 'none';
+ ImePreEdit_.style.display = 'none';
+ ImeHideCandidates();
+ ImeClear();
+ }
+
+ function ImeClear() {
+ ImeClearPreEdit();
+ ImeClearResults();
+ }
+
+ function ImeClearPreEdit() {
+ ImePreEdit_.value = '';
+ ImePreEditWidth_ = 0;
+ ImeRawInput_ = '';
+ ImeTo_ = "ime";
+ }
+
+ function ImeClearResults() {
+ ImeSelectedIndex_ = -1;
+ ImeNumResults_ = 0;
+ ImeResults_ = [];
+ }
+
+ function ImeShow() {
+ ImePreEdit_.style.display = 'block';
+ ImeWindow_.style.display = 'block';
+ }
+
+ function ImeShowPreEdit() {
+ ImeStoreCaretPos();
+ ImeStoreWindowPos();
+ ImeHide();
+ ImeShow();
+ ImePreEdit_.focus();
+ }
+
+ function ImeLog(result) {
+ if (ImeRawInput_ == '') ImeRawInput_ = result;
+ if (ImeSelectedIndex_ >= 1) ImeCache_[ImeRawInput_] = result;
+ var request = "action=log&query=" + encodeURI(ImeRawInput_) +
+ "&result=" + encodeURI(result) + "&sel=" + ImeSelectedIndex_ +
+ "&id=" + ImeID_;
+ ImeJsonpLog_ = new JSONRequest(ImeCGI_ + request);
+ ++ImeID_;
+ }
+
+ function ImeRequestCallback(result) {
+ try {
+ ImeClearResults();
+ var c = ImeCache_[ImeRawInput_];
+ if (c) {
+ ImeAdd(c, 1);
+ for (var i = 0; i < result.length; i++) {
+ if (result[i] != c) ImeAdd(result[i], 0);
+ }
+ } else {
+ for (var i = 0; i < result.length; i++) {
+ ImeAdd(result[i], i == 0 ? 1 : 0);
+ }
+ }
+ if (ImeResults_.length) ImePreEdit_.value = ImeResults_[0];
+ if (ImeRawInput_ == '') ImeRawInput_ = roma2hiragana(ImePreEdit_.value, false);
+ ImeCandidates_.style.display = 'block';
+ if (ImeJsonp_) ImeJsonp_.remove();
+ } catch (e) {}
+ }
+
+ function ImeShowCandidates() {
+ if (!ImeIsHidden()) return;
+ if (ImeRawInput_ == '') ImeRawInput_ = roma2hiragana(ImePreEdit_.value, false);
+ var request = "action=conv&to=" + ImeTo_ + "&query=" + encodeURI(ImeRawInput_) +
+ "&id=" + ImeID_;
+ ImeCurrentDocument_ = ImeDocument_;
+ ImeJsonp_ = new JSONRequest(ImeCGI_ + request);
+ }
+
+ function ImePreEditKeyDown(event) {
+ if (!ImeMode_) return false;
+
+ var evt = getEvent(event);
+ var key = getKeyCode(event);
+
+ ImePreEdit_.focus();
+ if (key == 0x20) { // space
+ ImeTo_ = "ime";
+ if (ImeIsHidden())
+ ImeShowCandidates();
+ else
+ ImeHandleDown();
+ } else if (key == 120) { // F9 katakana
+ ImeTo_ = "katakana";
+ ImeHideCandidates();
+ ImeShowCandidates();
+ } else if (key == 119) { // F9 roma
+ ImeTo_ = "alpha";
+ ImeHideCandidates();
+ ImeShowCandidates();
+ } else if (key == 40) { // down
+ ImeHandleDown();
+ } else if (key == 38) { // up
+ ImeHandleUp();
+ } else if (key == 13) { // return
+ ImeSelect(true);
+ ImeHide();
+ } else if (key == 27) { // esc, delete, bs
+ ImeNop();
+ ImeHide();
+ } else if (! ImeIsHidden()) { // next word
+ ImeSelect(false);
+ ImeStartPos_ += ImePreEdit_.value.length;
+ ImeSetCaretPos(ImeStartPos_);
+ ImeStoreWindowPos();
+ ImeStoreCaretPos();
+ ImeHideCandidates();
+ ImeClear();
+ ImePreEdit_.focus();
+ }
+
+ return false;
+ }
+
+ function ImePreEditKeyUp(event) {
+ if (ImePreEdit_.value.length == 0) {
+ ImeHide();
+ ImeNop();
+ return false;
+ }
+
+ ImePreEdit_.value = roma2hiragana(ImePreEdit_.value, true);
+
+ if (ImePreEdit_.value.length > ImePreEditWidth_)
+ ImePreEditWidth_ = ImePreEdit_.value.length;
+
+ var fontsize = parseFloat(getComputedStyle(ImeTextArea_, '').getPropertyValue('font-size'));
+
+ var length = (1.5 * fontsize * (ImePreEditWidth_ + 1)) + 'px';
+ ImePreEdit_.style.width = length;
+ ImeWindow_.style.width = length;
+ ImeCandidates_.style.width = length;
+
+ return true;
+ }
+
+ function ImeChangeMode() {
+ ImeMode_ = !ImeMode_;
+ ImeHide();
+
+ var inputs = ImeDocument_.getElementsByTagName('input');
+ for (var i = 0; i < inputs.length; ++i) {
+ if (!inputs[i].__ImeUsed && inputs[i].type == 'text') {
+ inputs[i].style.backgroundColor = ImeMode_ ? ImeBackGroundColor_ : 'white';
+ }
+ }
+
+ var textareas = ImeDocument_.getElementsByTagName('textarea');
+ for (var i = 0; i < textareas.length; ++i) {
+ if (!textareas[i].__ImeUsed)
+ textareas[i].style.backgroundColor = ImeMode_ ? ImeBackGroundColor_ : 'white';
+ }
+ }
+
+ function ImeDocumentKeyDown(event) {
+ var evt = getEvent(event);
+ var key = getKeyCode(event);
+ if ((key == 79 && evt.altKey) || ((key == 57 || key == 81) && evt.ctrlKey)) {
+ ImeChangeMode();
+ return false;
+ }
+ return true;
+ }
+
+ function ImeTextAreaKeyDown(event) {
+ var evt = getEvent(event);
+ var key = getKeyCode(event);
+
+ ImeTextArea_ = evt.target || evt.srcElement;
+
+ copyFontStyle(ImeTextArea_, ImePreEdit_);
+
+ if (ImeMode_) ImeHide();
+
+ // ignore Ctrl+C
+ if (evt.ctrlKey || evt.altKey) return true;
+
+ if (ImeMode_ && ImeIsHidden() &&
+ ((key >= 65 && key <= 90) ||
+ (key >= 48 && key <= 57) || (key >= 187 && key <= 222))) {
+
+ ImeShowPreEdit();
+ return false;
+ }
+
+ return true;
+ }
+}
+
+// roma 2 hiragana
+function roma2hiragana(str, delay) {
+ var result = [];
+ var text = str;
+ var rem = '';
+
+ if (delay) {
+ var l = str.length;
+ var last = str.substr(l - 1, 1);
+ var last2 = str.substr(l - 2, 2);
+ if (l > 1 && last2 == 'nn') {
+ text = str;
+ rem = '';
+ } else if (l > 1 && last2.match(/^[qwrtyplkjhgfdszxcvbmn]y$/)) {
+ text = str.substr(0, l - 2);
+ rem = last2;
+ } else if (l > 0 && last.match(/[qwrtyplkjhgfdszxcvbmn]/)) {
+ text = str.substr(0, l - 1);
+ rem = last;
+ }
+ }
+
+ for (var i = 0; i < text.length;) {
+ var o = text.charAt(i);
+ var c = o.charCodeAt(0);
+ var len = 0;
+ if ((c >= 97 && c <= 122) || (c >= 65 && c <= 90) || (c >= 44 && c <= 46))
+ len = 4;
+ while (len) {
+ var key = text.slice(i, i + len);
+ if (key in IMERoma2KatakanaTable_) {
+ var kana = IMERoma2KatakanaTable_[key];
+ if (typeof(kana) == 'string') {
+ result.push(kana);
+ i += len;
+ } else {
+ result.push(kana[0]);
+ i += (len - kana[1]);
+ }
+ break;
+ }
+ --len;
+ }
+
+ if (len == 0) {
+ result.push(o);
+ ++i;
+ }
+ }
+
+ return result.join("") + rem;
+}
+
+IMERoma2KatakanaTable_ = {'.':'。',',':'、','-':'ー','~':'〜','va':'う゛ぁ','vi':'う゛ぃ','vu':'う゛','ve':'う゛ぇ','vo':'う゛ぉ','vv': ['っ',1],'xx': ['っ',1],'kk': ['っ',1],'gg': ['っ',1],'ss': ['っ',1],'zz': ['っ',1],'jj': ['っ',1],'tt': ['っ',1],'dd': ['っ',1],'hh': ['っ',1],'ff': ['っ',1],'bb': ['っ',1],'pp': ['っ',1],'mm': ['っ',1],'yy': ['っ',1],'rr': ['っ',1],'ww': ['っ',1],'cc': ['っ',1],'kya':'きゃ','kyi':'きぃ','kyu':'きゅ','kye':'きぇ','kyo':'きょ','gya':'ぎゃ','gyi':'ぎぃ','gyu':'ぎゅ','gye':'ぎぇ','gyo':'ぎょ','sya':'しゃ','syi':'しぃ','syu':'しゅ','sye':'しぇ','syo':'しょ','sha':'しゃ','shi':'し','shu':'しゅ','she':'しぇ','sho':'しょ','zya':'じゃ','zyi':'じぃ','zyu':'じゅ','zye':'じぇ','zyo':'じょ','tya':'ちゃ','tyi':'ちぃ','tyu':'ちゅ','tye':'ちぇ','tyo':'ちょ','cha':'ちゃ','chi':'ち','chu':'ちゅ','che':'ちぇ','cho':'ちょ','dya':'ぢゃ','dyi':'ぢぃ','dyu':'ぢゅ','dye':'ぢぇ','dyo':'ぢょ','tha':'てゃ','thi':'てぃ','thu':'てゅ','the':'てぇ','tho':'てょ','dha':'でゃ','dhi':'でぃ','dhu':'でゅ','dhe':'でぇ','dho':'でょ','nya':'にゃ','nyi':'にぃ','nyu':'にゅ','nye':'にぇ','nyo':'にょ','jya':'じゃ','jyi':'じ','jyu':'じゅ','jye':'じぇ','jyo':'じょ','hya':'ひゃ','hyi':'ひぃ','hyu':'ひゅ','hye':'ひぇ','hyo':'ひょ','bya':'びゃ','byi':'びぃ','byu':'びゅ','bye':'びぇ','byo':'びょ','pya':'ぴゃ','pyi':'ぴぃ','pyu':'ぴゅ','pye':'ぴぇ','pyo':'ぴょ','fa':'ふぁ','fi':'ふぃ','fu':'ふ','fe':'ふぇ','fo':'ふぉ','mya':'みゃ','myi':'みぃ','myu':'みゅ','mye':'みぇ','myo':'みょ','rya':'りゃ','ryi':'りぃ','ryu':'りゅ','rye':'りぇ','ryo':'りょ','n\'':'ん','nn':'ん','n':'ん','a':'あ','i':'い','u':'う','e':'え','o':'お','xa':'ぁ','xi':'ぃ','xu':'ぅ','xe':'ぇ','xo':'ぉ','la':'ぁ','li':'ぃ','lu':'ぅ','le':'ぇ','lo':'ぉ','ka':'か','ki':'き','ku':'く','ke':'け','ko':'こ','ga':'が','gi':'ぎ','gu':'ぐ','ge':'げ','go':'ご','sa':'さ','si':'し','su':'す','se':'せ','so':'そ','za':'ざ','zi':'じ','zu':'ず','ze':'ぜ','zo':'ぞ','ja':'じゃ','ji':'じ','ju':'じゅ','je':'じぇ','jo':'じょ','ta':'た','ti':'ち','tu':'つ','tsu':'つ','te':'て','to':'と','da':'だ','di':'ぢ','du':'づ','de':'で','do':'ど','xtu':'っ','xtsu':'っ','na':'な','ni':'に','nu':'ぬ','ne':'ね','no':'の','ha':'は','hi':'ひ','hu':'ふ','fu':'ふ','he':'へ','ho':'ほ','ba':'ば','bi':'び','bu':'ぶ','be':'べ','bo':'ぼ','pa':'ぱ','pi':'ぴ','pu':'ぷ','pe':'ぺ','po':'ぽ','ma':'ま','mi':'み','mu':'む','me':'め','mo':'も','xya':'ゃ','ya':'や','xyu':'ゅ','yu':'ゆ','xyo':'ょ','yo':'よ','ra':'ら','ri':'り','ru':'る','re':'れ','ro':'ろ','xwa':'ゎ','wa':'わ','wi':'うぃ','we':'うぇ','wo':'を'};
+
+// global functions
+function ImeInit() {
+ function ImeInitRecursive(w) {
+ var frames = w.frames;
+ for (var i = 0; i < frames.length; ++i) {
+ AjaxIME(frames[i].document);
+ ImeInitRecursive(frames[i].window);
+ }
+ }
+ AjaxIME(document);
+ ImeInitRecursive(window);
+}
+
+function ImeChangeMode() {
+ function ImeChangeModeRecursive(w) {
+ var frames = w.frames;
+ for (var i = 0; i < frames.length; ++i) {
+ frames[i].document.ImeChangeMode();
+ ImeChangeModeRecursive(frames[i].window);
+ }
+ }
+ document.ImeChangeMode();
+ ImeChangeModeRecursive(window);
+}
+
+function ImeRequestCallback(result) {
+ ImeCurrentDocument_.ImeRequestCallback(result);
+}
+
+addEvent(window, 'load', ImeInit);
var Xex = {};
+Xex.Alist = function ()
+{
+ this.count = 0;
+}
+
+Xex.Alist.prototype.put = function (key, val)
+{
+ this.count++;
+ return (this[key] = val);
+}
+Xex.Alist.prototype.clone = function ()
+{
+ var alist = new Xex.Alist ();
+ for (key in this)
+ alist[key] = this[key];
+ return alist;
+}
+Xex.Alist.prototype.toString = function ()
+{
+ var str = 'alist:';
+ for (key in this)
+ str += '"' + key + '"';
+ return str;
+}
+
+// Xex.alist = new Xex.Alist ();
+// Xex.alist.put ('abc', "ABC");
+// alert (Xex.alist['abc']);
+
+Xex.Error = {
+ UnknownError: "unknown-error",
+ WrongArgument: "wrong-argument",
+ // Load time errors.
+ InvalidInteger: "invalid-integer",
+ TermTypeInvalid: "term-type-invalid",
+ FunctionConflict: "function-conflict",
+ VariableTypeConflict: "variable-type-conflict",
+ VariableRangeConflict: "variable-range-conflict",
+ VariableWrongRange: "variable-wrong-range",
+ VariableWrongValue: "variable-wrong-value",
+
+ UnknownFunction: "unknown-function",
+ MacroExpansionError: "macro-expansion-error",
+ NoVariableName: "no-variable-anme",
+
+ // Run time errors.
+ ArithmeticError: "arithmetic-error",
+ WrongType: "wrong-type",
+ IndexOutOfRange: "index-out-of-range",
+ ValueOutOfRange: "value-out-of-range",
+ NoLoopToBreak: "no-loop-to-break",
+ UncaughtThrow: "uncaught-throw"
+};
+
Xex.Variable = function (domain, name, val)
{
this.domain = domain;
this.name = name;
this.context = context;
this.depth = 0;
- this.termtypes = parent ? parent.termtypes.slice () : new Array ();
- this.functions = parent ? parent.functions.slice () : new Array ();
- this.variables = parent ? parent.variable.slice () : new Array ();
- var call_stack = new Array ();
- var bindings;
- var catch_stack = new Array ();
- var catch_count = 0;
-
- if (this.CallStackCount)
- return;
+ if (name != 'basic' && ! parent)
+ parent = Xex.BasicDomain
+ this.parent = parent;
+ this.termtypes = {};
+ this.functions = {};
+ this.variables = {};
+ if (parent)
+ {
+ var elt;
+ for (elt in parent.termtypes)
+ this.termtypes[elt] = parent.termtypes[elt];
+ for (elt in parent.functions)
+ this.functions[elt] = parent.functions[elt];
+ for (elt in parent.variables)
+ this.variables[elt] = parent.variables[elt];
+ }
- var proto = Xex.Domain.prototype;
+ this.call_stack = new Array ();
+ this.bindings = null;
+ this.catch_stack = new Array ();
+ this.catch_count = 0;
+ this.caught = false;
+};
- proto.CallStackCount = function () { return call_stack.length; }
- proto.CallStackPush = function (term) { call_stack.push (term); }
- proto.CallStackPop = function () { call_stack.pop (); }
- proto.Bind = function (vari, val)
+Xex.Domain.prototype = {
+ CallStackCount: function () { return this.call_stack.length; },
+ CallStackPush: function (term) { this.call_stack.push (term); },
+ CallStackPop: function () { this.call_stack.pop (); },
+ Bind: function (vari, val)
{
- bindings = Xex.Bind (bindings, vari, val);
- }
- proto.UnboundTo = function (boundary)
+ this.bindings = Xex.Bind (this.bindings, vari, val);
+ },
+ UnboundTo: function (boundary)
{
- if (bindings)
- bindings = bindings.UnboundTo (boundary);
- }
- proto.Catch = function (tag) { catch_stack.push (tag); catch_count++; }
- proto.Uncatch = function ()
+ if (this.bindings)
+ this.bindings = this.bindings.UnboundTo (boundary);
+ },
+ Catch: function (tag) { this.catch_stack.push (tag); this.catch_count++; },
+ Uncatch: function ()
{
- catch_stack.pop ();
- if (catch_count > catch_stack.length)
- catch_count--;
- }
- proto.Thrown = function ()
+ this.catch_stack.pop ();
+ if (this.catch_count > this.catch_stack.length)
+ this.catch_count--;
+ },
+ Thrown: function ()
{
- var i = catch_stack.length - catch_count;
- return (i > 0 ? i - 1 : false);
- }
- proto.ThrowReturn = function ()
+ if (this.catch_count < this.catch_stack.length)
+ {
+ this.caught = (this.catch_count == this.catch_stack.length - 1);
+ return true;
+ }
+ this.caught = false;
+ return false;
+ },
+ ThrowReturn: function ()
{
- for (var i = catch_stack.length - 1; i >= 0; i--)
+ for (var i = this.catch_stack.length - 1; i >= 0; i--)
{
- catch_count--;
- if (catch_stack[i] == Xex.CatchTag.Return)
+ this.catch_count--;
+ if (this.catch_stack[i] == Xex.CatchTag.Return)
break;
}
- }
- proto.ThrowBreak = function ()
+ },
+ ThrowBreak: function ()
{
- if (catch_stack[catch_stack.length - 1] != Xex.CatchTag.Break)
- throw new Xex.Error (Xex.Error.NoLoopToBreak,
+ if (this.catch_stack[this.catch_stack.length - 1] != Xex.CatchTag.Break)
+ throw new Xex.ErrTerm (Xex.Error.NoLoopToBreak,
"No surrounding loop to break");
- catch_count--;
- }
- proto.ThrowSymbol = function (tag)
+ this.catch_count--;
+ },
+ ThrowSymbol: function (tag)
{
- var i = catch_count;
- for (var j = catch_stack.length - 1; j >= 0; j--)
+ var i = this.catch_count;
+ for (var j = this.catch_stack.length - 1; j >= 0; j--)
{
i--;
- if (Xex.CatchTag.Matches (catch_stack[i], tag))
+ if (Xex.CatchTag.Matches (this.catch_stack[i], tag))
{
- catch_count = i;
+ this.catch_count = i;
return;
}
}
- throw new Xex.Error (Xex.Error.UncaughtThrow,
+ throw new Xex.ErrTerm (Xex.Error.UncaughtThrow,
"No corresponding catch: " + tag);
- }
- proto.DefType = function (obj)
+ },
+ DefType: function (obj)
{
var type = obj.type;
if (this.termtypes[type])
- throw new Xex.Error (Xex.Error.TermTypeInvalid,
+ throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid,
"Already defined: " + type);
if (this.functions[type])
- throw new Xex.Error (Xex.Error.TermTypeInvalid,
+ throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid,
"Already defined as a funciton or a macro: "
+ type);
this.termtypes[type] = obj.Parser;
- }
-
- proto.DefSubr = function (builtin, name, with_var, min_args, max_args)
+ },
+ DefSubr: function (builtin, name, with_var, min_args, max_args)
{
this.functions[name] = new Xex.Subrountine (builtin, name, with_var,
min_args, max_args);
- }
- proto.DefSpecial = function (builtin, name, with_var, min_args, max_args)
+ },
+ DefSpecial: function (builtin, name, with_var, min_args, max_args)
{
this.functions[name] = new Xex.SpecialForm (builtin, name, with_var,
min_args, max_args);
- }
- proto.Defun = function (name, min_args, max_args, args, body)
+ },
+ Defun: function (name, min_args, max_args, args, body)
{
- this.functions[name] = new Xex.Lambda (name, min_args, max_args,
- args, body);
- }
- proto.DefunByFunc = function (func) { this.functions[func.Name] = func; }
- proto.Defmacro = function (name, min_args, max_args, args, body)
+ this.functions[name] = new Xex.Lambda (name, min_args, max_args,
+ args, body);
+ },
+ DefunByFunc: function (func) { this.functions[func.Name] = func; },
+ Defmacro: function (name, min_args, max_args, args, body)
{
- this.functions[name] = new Xex.Macro (name, min_args, max_args, args, body);
- }
- proto.DefAlias = function (alias, fname)
+ this.functions[name] = new Xex.Macro (name, min_args, max_args,
+ args, body);
+ },
+ DefAlias: function (alias, fname)
{
var func = this.functions[fname];
if (this.termtypes[alias])
- throw new Xex.Error (Xex.Error.FunctionConflict,
+ throw new Xex.ErrTerm (Xex.Error.FunctionConflict,
"Already defined as a term type: " + alias);
if (this.functions[alias])
- throw new Xex.Error (Xex.Error.FunctionConflict,
+ throw new Xex.ErrTerm (Xex.Error.FunctionConflict,
"Already defined as a function: " + alias);
if (! func)
- throw new Xex.Error (Xex.Error.UnknownFunction, fname);
+ throw new Xex.ErrTerm (Xex.Error.UnknownFunction, fname);
this.functions[alias] = func;
- }
- proto.Defvar = function (name)
+ },
+ Defvar: function (name)
{
var vari = this.variables[name];
if (vari)
{
if (vari.Typed)
- throw new Xex.Error (Xex.Error.VariableTypeConflict,
+ throw new Xex.ErrTerm (Xex.Error.VariableTypeConflict,
"Not a non-typed variable: " + name);
}
else
this.variables[name] = vari;
}
return vari;
- }
- proto.GetFunc = function (name) { return this.functions[name]; }
- proto.CopyFunc = function (domain, name)
+ },
+ GetFunc: function (name)
+ {
+ var func = this.functions[name];
+ if (! func)
+ throw new Xex.ErrTerm (Xex.Error.UnknownFunction,
+ "Unknown function: " + this + ':' + name);
+ return func;
+ },
+ CopyFunc: function (domain, name)
{
var func = this.functions[name];
domain.DefunByFunc (func);
return true;
- }
- proto.CopyFuncAll = function (domain)
+ },
+ CopyFuncAll: function (domain)
{
- for (var i = this.functions.length - 1; i >= 0; i--)
- domain.DefunByFunc (this.functions[i]);
- }
- proto.GetVarCreate = function (name)
+ for (var elt in this.functions)
+ domain.DefunByFunc (this.functions[elt]);
+ },
+ GetVarCreate: function (name)
{
var vari = this.variables[name];
if (! vari)
- this.variables[name] = vari
- = new Xex.Variable (this, name, Xex.Zero);
+ vari = this.variables[name] = new Xex.Variable (this, name, Xex.Zero);
return vari;
- }
- proto.GetVar = function (name) { return this.variables[name]; }
- proto.SaveValues = function ()
+ },
+ GetVar: function (name) { return this.variables[name]; },
+ SaveValues: function ()
{
- values = new Array ()
- for (var i = this.variables.length - 1; i >= 0; i--)
- {
- var vari = this.variables[i];
- values[vari.Name] = vari.val.Clone ();
- }
+ values = {};
+ for (var elt in this.variables)
+ values[elt] = this.variables[elt].val.Clone ();
return values;
- }
- proto.RestoreValues = function (values)
+ },
+ RestoreValues: function (values)
{
var name;
for (name in values)
}
};
-Xex.Term = function () { }
+Xex.Term = function (type) { this.type = type; }
Xex.Term.prototype = {
- IsTrue: true,
+ IsTrue: function () { return true; },
Eval: function (domain) { return this.Clone (); },
+ Clone: function (domain) { return this; },
Equals: function (obj)
{
return (this.type == obj.type
return new Xex.Funcall.prototype.Parser (domain, node);
}
-Xex.Varref = function (vname)
+Xex.ParseTermList = function (domain, node)
{
- var vari;
+ for (var n = node; n; n = n.nextSibling)
+ if (n.nodeType == 1)
+ {
+ if (n.nodeName == 'defun' || n.nodeName == 'defmacro')
+ Xex.parse_defun_head (domain, n);
+ }
+ var terms = new Array ();
+ for (var n = node; n; n = n.nextSibling)
+ if (n.nodeType == 1)
+ {
+ if (n.nodeName == 'defun' || n.nodeName == 'defmacro')
+ Xex.parse_defun_body (domain, n);
+ else if (n.nodeName == 'defvar')
+ Xex.parse_defvar (domain, n);
+ else
+ terms.push (Xex.ParseTerm (domain, n));
+ }
+ return terms;
+}
+Xex.Varref = function (vname)
+{
this.val = vname;
- if (this.type)
- return;
- var proto = Xex.Varref.prototype;
+};
- proto.type = 'varref';
+(function () {
+ var proto = new Xex.Term ('varref');
proto.Clone = function () { return new Xex.Varref (this.val); }
proto.Eval = function (domain)
{
- if (! vari || vari.domain != domain)
- vari = domain.GetVarCreate (this.val);
- return vari.val;
+ if (! this.vari || this.vari.domain != domain)
+ this.vari = domain.GetVarCreate (this.val);
+ return this.vari.val;
}
proto.Parser = function (domain, node)
{
return new Xex.Varref (node.attributes['vname'].nodeValue);
}
-}
-Xex.Varref.prototype = new Xex.Term ();
+ Xex.Varref.prototype = proto;
+}) ();
var null_args = new Array ();
Xex.Funcall = function (func, vari, args)
{
this.func = func;
- if (! args)
- args = null_args;
this.vari = vari;
- this.args = args;
- if (this.type)
- return;
-
- var proto = Xex.Funcall.prototype;
+ this.args = args || null_args;
+};
- proto.type = 'funcall';
+(function () {
+ var proto = new Xex.Term ('funcall');
proto.Parser = function (domain, node)
{
var vari;
attr = node.attributes['vname'];
vari = attr != undefined ? domain.GetVarCreate (attr.nodeValue) : false;
- var args = new Array ();
- for (node = node.firstChild; node; node = node.nextSibling)
- if (node.nodeType == 1)
- args.push (Xex.ParseTerm (domain, node));
+ var args = Xex.ParseTermList (domain, node.firstChild);
return new Xex.Funcall (func, vari, args);
}
+ proto.New = function (domain, fname, vname, args)
+ {
+ var func = domain.GetFunc (fname);
+ var vari = vname ? domain.GetVarCreate (vname) : null;
+ var funcall = new Xex.Funcall (func, vari, args);
+ if (func instanceof Xex.Macro)
+ funcall = funcall.Eval (domain);
+ return funcall;
+ }
+
proto.Eval = function (domain)
{
return this.func.Call (domain, this.vari, this.args);
arglist += this.args[i].toString ();
return '<' + this.func.name + '>' + arglist + '</' + this.func.name + '>';
}
-}
-Xex.Funcall.prototype = new Xex.Term ();
+ Xex.Funcall.prototype = proto;
+}) ();
Xex.ErrTerm = function (ename, message, stack)
{
- if (this.type)
- return;
+ this.ename = ename;
+ this.message = message;
+ this.stack = stack;
+};
- var proto = Xex.ErrTerm.prototype;
+(function () {
+ var proto = new Xex.Term ('error');
- proto.type = 'error';
+ proto.IsError = true;
proto.Parser = function (domain, node)
{
return new Xex.ErrTerm (node.attributes['ename'].nodeValue,
- node.innerText, false);
+ node.innerText, false);
}
proto.CallStack = function () { return stack; }
proto.Equals = function (obj)
{
- return (obj.type == 'error'
+ return (obj.IsError
&& obj.ename == ename && obj.message == message
&& (obj.stack ? (stack && stack.length == obj.stack.length)
: ! stack));
proto.Matches = function (obj)
{
- return (obj.type == 'error' && obj.ename == ename);
+ return (obj.IsError && obj.ename == ename);
}
-}
-Xex.ErrTerm.prototype = new Xex.Term ();
+ proto.toString = function ()
+ {
+ return '<error ename="' + this.ename + '">' + this.message + '</error>';
+ }
-Xex.IntTerm = function (num)
-{
- this.val = num;
- this.IsTrue = num != 0;
- if (this.type)
- return;
- var proto = Xex.IntTerm.prototype;
- proto.type = 'integer';
+ Xex.ErrTerm.prototype = proto;
+}) ();
+
+Xex.IntTerm = function (num) { this.val = num; };
+(function () {
+ var proto = new Xex.Term ('integer');
+ proto.IsInt = true;
+ proto.IsTrue = function () { return this.val != 0; }
proto.Clone = function () { return new Xex.IntTerm (this.val); }
proto.Parser = function (domain, node)
{
+ var str = node.firstChild.nodeValue;
+
+ if (str.charAt (0) == '?' && str.length == 2)
+ return new Xex.IntTerm (str.charCodeAt (1));
return new Xex.IntTerm (parseInt (node.firstChild.nodeValue));
}
-}
-
-Xex.IntTerm.prototype = new Xex.Term ();
+ Xex.IntTerm.prototype = proto;
+}) ();
-Xex.StrTerm = function (str)
-{
- this.val = str;
- this.IsTrue = str && str.length > 0;
- if (this.type)
- return;
- var proto = Xex.StrTerm.prototype;
- proto.type = 'string';
+Xex.StrTerm = function (str) { this.val = str; };
+(function () {
+ var proto = new Xex.Term ('string');
+ proto.IsStr = true;
+ proto.IsTrue = function () { return this.val.length > 0; }
proto.Clone = function () { return new Xex.StrTerm (this.val); }
proto.Parser = function (domain, node)
{
return new Xex.StrTerm (node.firstChild.nodeValue);
}
-}
-
-Xex.StrTerm.prototype = new Xex.Term ();
-
-Xex.LstTerm = function (list)
-{
- this.val = list;
- this.IsTrue = list && list.length > 0;
- if (this.type)
- return;
+ Xex.StrTerm.prototype = proto;
+}) ();
- var proto = Xex.LstTerm.prototype;
+Xex.SymTerm = function (str) { this.val = str; };
+(function () {
+ var proto = new Xex.Term ('symbol');
+ proto.IsSymbol = true;
+ proto.IsTrue = function () { return this.val != 'nil'; }
+ proto.Clone = function () { return new Xex.SymTerm (this.val); }
+ proto.Parser = function (domain, node)
+ {
+ return new Xex.SymTerm (node.firstChild.nodeValue);
+ }
+ Xex.SymTerm.prototype = proto;
+}) ();
- proto.type = 'list';
-
- proto.Clone = function () { return new Xex.LstTerm (this.val.slice ()); }
+Xex.LstTerm = function (list) { this.val = list; };
+(function () {
+ var proto = new Xex.Term ('list');
+ proto.IsList = true;
+ proto.IsTrue = function () { return this.val.length > 0; }
+ proto.Clone = function () { return new Xex.LstTerm (this.val.slice (0)); }
proto.Equals = function (obj)
{
proto.Parser = function (domain, node)
{
- var list = new Array ();
-
- for (node = node.firstChild; node; node = node.nextSibling)
- if (node.nodeType == 1)
- list.push (Xex.ParseTerm (domain, node));
+ var list = Xex.ParseTermList (domain, node.firstChild);
return new Xex.LstTerm (list);
}
if (len == 0)
return '<list/>';
var str = '<list>';
- for (i = 0; i < len; i++)
+ for (var i = 0; i < len; i++)
str += this.val[i].toString ();
return str + '</list>';
}
-}
-
-Xex.LstTerm.prototype = new Xex.Term ();
+ Xex.LstTerm.prototype = proto;
+}) ();
(function () {
- var basic = new Xex.Domain ('basic');
+ var basic = new Xex.Domain ('basic', null, null);
function Fset (domain, vari, args)
{
return args[2].Eval (domain);
}
+ function eval_terms (domain, terms, idx)
+ {
+ var result = Xex.Zero;
+ domain.caught = false;
+ for (var i = idx; i < terms.length; i++)
+ {
+ result = terms[i].Eval (domain);
+ if (domain.Thrown ())
+ return result;
+ }
+ return result;
+ }
+
+ function Fcatch (domain, vari, args)
+ {
+ var caught = false;
+ var result;
+
+ if (args[0].IsError)
+ {
+ try {
+ result = eval_terms (domain, args, 1);
+ } catch (e) {
+ if (e instanceof Xex.ErrTerm)
+ {
+ if (! args[0].Matches (e))
+ throw e;
+ if (vari)
+ vari.SetValue (e);
+ return Xex.One;
+ }
+ }
+ }
+ else if (args[0].IsSymbol)
+ {
+ try {
+ domain.Catch (args[0].val);
+ result = eval_terms (domain, args, 1);
+ if (domain.caught)
+ {
+ if (vari != null)
+ vari.SetValue (result);
+ return Xex.One;
+ }
+ return Xex.Zero;
+ } finally {
+ domain.Uncatch ();
+ }
+ }
+ throw new Xex.ErrTerm (Xex.Error.WrongArgument,
+ "Not a symbol nor an error: " + args[0]);
+ }
+
+ function Fthrow (domain, vari, args)
+ {
+ if (args[0].IsSymbl)
+ {
+ domain.ThrowSymbol (args[0]);
+ return (args[args.length - 1]);
+ }
+ if (args[0].IsError)
+ {
+ throw args[0];
+ }
+ throw new Xex.ErrTerm (Xex.Error.WrongArgument,
+ "Not a symbol nor an error:" + args[0]);
+ }
+
+ Xex.BasicDomain = basic;
+
basic.DefSubr (Fset, "set", true, 1, 1);
basic.DefSubr (Fadd, "add", true, 1, -1);
+ basic.DefSubr (Fthrow, "throw", false, 1, 2);
+
basic.DefSpecial (Fand, "and", false, 1, -1);
basic.DefSpecial (For, "or", false, 1, -1);
basic.DefAlias ("=", "set");
basic.DefSpecial (Fprogn, "progn", false, 1, -1);
basic.DefSpecial (Fif, "if", false, 2, 3);
- basic.DefType (new Xex.Funcall ());
- basic.DefType (new Xex.Varref ());
- basic.DefType (new Xex.ErrTerm ());
- basic.DefType (new Xex.IntTerm ());
- basic.DefType (new Xex.StrTerm ());
- basic.DefType (new Xex.LstTerm ());
-
- Xex.Domain.basic = basic;
+ basic.DefSpecial (Fcatch, "catch", true, 2, -1);
+
+ basic.DefType (Xex.Funcall.prototype);
+ basic.DefType (Xex.Varref.prototype);
+ basic.DefType (Xex.ErrTerm.prototype);
+ basic.DefType (Xex.IntTerm.prototype);
+ basic.DefType (Xex.StrTerm.prototype);
+ basic.DefType (Xex.SymTerm.prototype);
+ basic.DefType (Xex.LstTerm.prototype);
+
}) ();
Xex.Zero = new Xex.IntTerm (0);
Xex.One = new Xex.IntTerm (1);
-var obj = new XMLHttpRequest ();
-obj.open ('GET', 'xex.xml', false);
-obj.send ('');
-var body = obj.responseXML.firstChild;
-var domain = Xex.Domain.basic;
-document.ATTR = body;
-alert (Xex.ParseTerm (domain, body).Eval (domain));
+Xex.Load = function (server, file)
+{
+ var obj = new XMLHttpRequest ();
+ var url = server ? server + '/' + file : file;
+ obj.open ('GET', url, false);
+ obj.overrideMimeType ('text/xml');
+ obj.send ('');
+ return obj.responseXML.firstChild;
+}
+
+var MIM = {
+ // URL of the input method server.
+ server: "http://www.m17n.org/common/mim-js",
+ // Boolean flag to tell if MIM is active or not.
+ enabled: true,
+ // Boolean flag to tell if MIM is running in debug mode or not.
+ debug: false,
+ // List of registered input methods.
+ im_list: {},
+ // Global input method data
+ im_global: null,
+ // Currently selected input method.
+ current: false,
+
+ // enum
+ LoadStatus: { NotLoaded:0, Loading:1, Loaded:2, Error:-1 },
+ ChangedStatus: {
+ None: 0x00,
+ StateTitle: 0x01,
+ PreeditText:0x02,
+ CursorPos: 0x04,
+ CandidateList:0x08,
+ CandidateIndex:0x10,
+ CandidateShow:0x20,
+ Preedit: 0x06, // PreeditText | CursorPos
+ Candidate: 0x38 // CandidateList | CandidateIndex | CandidateShow
+ },
+ KeyModifier: {
+ SL: 0x00400000,
+ SR: 0x00800000,
+ S: 0x00C00000,
+ CL: 0x01000000,
+ CR: 0x02000000,
+ C: 0x03000000,
+ AL: 0x04000000,
+ AR: 0x08000000,
+ A: 0x0C000000,
+ ML: 0x04000000,
+ MR: 0x08000000,
+ M: 0x0C000000,
+ G: 0x10000000,
+ s: 0x20000000,
+ H: 0x40000000,
+ High: 0x70000000,
+ All: 0x7FC00000
+ },
+ Error: {
+ ParseError: "parse-error"
+ }
+};
+
+(function () {
+ var keysyms = new Array ();
+ keysyms["bs"] = "backspace";
+ keysyms["lf"] = "linefeed";
+ keysyms["cr"] = keysyms["enter"] = "return";
+ keysyms["esc"] = "escape";
+ keysyms["spc"] = "space";
+ keysyms["del"] = "delete";
+
+ function decode_keysym (str) {
+ var parts = str.split ("-");
+ var len = parts.length, i;
+ var has_modifier = len > 1;
+
+ for (i = 0; i < len - 1; i++)
+ if (! MIM.KeyModifier.hasOwnProperty (parts[i]))
+ return false;
+ var key = parts[len - 1];
+ if (key.length > 1)
+ {
+ key = keysyms[key.toLowerCase ()];
+ if (key)
+ {
+ if (len > 1)
+ {
+ str = parts[0];
+ for (i = 1; i < len - 1; i++)
+ str += '-' + parts[i];
+ str += '-' + key;
+ }
+ else
+ str = key;
+ }
+ }
+ if (has_modifier)
+ {
+ parts = new Array ();
+ parts.push (str);
+ return parts;
+ }
+ return str;
+ }
+
+ MIM.Key = function (val)
+ {
+ this.key;
+ this.has_modifier = false;
+ if (typeof val == 'string' || val instanceof String)
+ {
+ this.key = decode_keysym (val);
+ if (! this.key)
+ throw new Xex.ErrTerm (MIM.Error.ParseError, "Invalid key: " + val);
+ if (this.key instanceof Array)
+ {
+ this.key = this.key[0];
+ this.has_modifier = true;
+ }
+ }
+ else if (typeof val == 'number' || val instanceof Number)
+ this.key = String.fromCharCode (val);
+ else
+ throw new Xex.ErrTerm (MIM.Error.ParseError, "Invalid key: " + val);
+ }
+
+ MIM.Key.prototype.toString = function () { return this.key; };
+}) ();
+
+(function () {
+ MIM.KeySeq = function (seq)
+ {
+ this.val = new Array ();
+ this.has_modifier = false;
+
+ if (seq)
+ {
+ if (seq.IsList)
+ {
+ 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')
+ 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;
+ }
+ }
+ else if (seq.IsStr)
+ {
+ var len = seq.val.length;
+ for (var i = 0; i < len; i++)
+ this.val.push (new MIM.Key (seq.val.charCodeAt (i)));
+ }
+ else
+ throw new Xex.ErrTerm (MIM.Error.ParseError, "Invalid key: " + seq);
+ }
+ }
+
+ var proto = new Xex.Term ('keyseq');
+ proto.Clone = function () { return this; }
+ proto.Parser = function (domain, node)
+ {
+ var seq = new Array ();
+ for (node = node.firstChild; node; node = node.nextSibling)
+ if (node.nodeType == 1)
+ {
+ var term = Xex.ParseTerm (domain, node);
+ return new MIM.KeySeq (term);
+ }
+ throw new Xex.ErrTerm (MIM.Error.ParseError, "Invalid keyseq");
+ }
+ proto.toString = function ()
+ {
+ var len = this.val.length;
+ if (len == 0)
+ return '<keyseq/>';
+ var first = true;
+ var str = '<keyseq>';
+ for (var i = 0; i < len; i++)
+ {
+ if (first)
+ first = false;
+ else if (this.has_modifier)
+ str += ' ';
+ str += this.val[i].toString ();
+ }
+ return str + '</keyseq>';
+ }
+
+ MIM.KeySeq.prototype = proto;
+}) ();
+
+(function () {
+ MIM.Marker = function () { }
+ MIM.Marker.prototype = new Xex.Term ('marker');
+ MIM.Marker.prototype.CharAt = function (ic)
+ {
+ var p = this.Position (ic);
+ if (p < 0)
+ return ic.GetSurroundingChar (p);
+ else if (pos >= ic.preedit.length)
+ return ic.GetSurroundingChar (p - ic.preedit.length);
+ 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];
+ return (p == undefined ? 0 : p);
+ }
+ MIM.NamedMarker.prototype.Mark = function (ic)
+ {
+ ic.marker_positions[this.val] = ic.cursor_pos;
+ }
+
+ MIM.PredefinedMarker = function (name) { this.val = name; }
+ MIM.PredefinedMarker.prototype = new MIM.Marker ();
+ MIM.PredefinedMarker.prototype.Position = function (ic)
+ {
+ if (typeof this.pos == 'number')
+ return this.pos;
+ return this.pos (ic);
+ }
+
+ var predefined = { }
+
+ function def_predefined (name, position)
+ {
+ predefined[name] = new MIM.PredefinedMarker (name);
+ predefined[name].pos = position;
+ }
+
+ def_predefined ('@<', 0);
+ def_predefined ('@>', function (ic) { return ic.preedit.length; });
+ def_predefined ('@-', function (ic) { return ic.cursor_pos - 1; });
+ def_predefined ('@+', function (ic) { return ic.cursor_pos + 1; });
+ def_predefined ('@[', function (ic) {
+ if (ic.cursor_pos > 0)
+ {
+ var pos = ic.cursor_pos;
+ return ic.preedit.FindProp ('candidates', pos - 1).from;
+ }
+ return 0;
+ });
+ def_predefined ('@]', function (ic) {
+ if (ic.cursor_pos < ic.preedit.length - 1)
+ {
+ var pos = ic.cursor_pos;
+ return ic.preedit.FindProp ('candidates', pos).to;
+ }
+ return ic.preedit.length;
+ });
+ for (var i = 0; i < 10; i++)
+ def_predefined ("@" + i, i);
+ predefined['@first'] = predefined['@<'];
+ predefined['@last'] = predefined['@>'];
+ predefined['@previous'] = predefined['@-'];
+ predefined['@next'] = predefined['@+'];
+ predefined['@previous-candidate-change'] = predefined['@['];
+ predefined['@next-candidate-change'] = predefined['@]'];
+
+ MIM.SurroundMarker = function (name)
+ {
+ this.val = name;
+ this.distance = parseInt (name.slice (2));
+ if (isNaN (this.distance))
+ throw new Xex.ErrTerm (MIM.Error.ParseError, "Invalid marker: " + name);
+ }
+ MIM.SurroundMarker.prototype = new MIM.Marker ();
+ MIM.SurroundMarker.prototype.Position = function (ic)
+ {
+ return ic.cursor_pos + this.distance;
+ }
+
+ MIM.Marker.prototype.Parser = function (domain, node)
+ {
+ var name = node.firstChild.nodeValue;
+ if (name.charAt (0) == '@')
+ {
+ var n = predefined[name];
+ if (n)
+ return n;
+ if (name.charAt (1) == '-')
+ return new MIM.SurroundMarker (name);
+ throw new Xex.ErrTerm (MIM.Error.ParseError,
+ "Invalid marker: " + name);
+ }
+ return new MIM.NamedMarker (name);
+ }
+}) ();
+
+MIM.Selector = function (name)
+{
+ this.val = name;
+}
+MIM.Selector.prototype = new Xex.Term ('selector');
+(function () {
+ var selectors = {};
+ selectors["@<"] = selectors["@first"] = new MIM.Selector ('@<');
+ selectors["@="] = selectors["@current"] = new MIM.Selector ('@=');
+ selectors["@>"] = selectors["@last"] = new MIM.Selector ('@>');
+ selectors["@-"] = selectors["@previous"] = new MIM.Selector ('@-');
+ selectors["@+"] = selectors["@next"] = new MIM.Selector ('@+');
+ selectors["@["] = selectors["@previous-candidate-change"]
+ = new MIM.Selector ('@[');
+ selectors["@]"] = selectors["@next-candidate-change"]
+ = new MIM.Selector ('@]');
+
+ MIM.Selector.prototype.Parser = function (domain, node)
+ {
+ var name = node.firstChild.nodeValue;
+ var s = selectors[name];
+ if (! s)
+ throw new Xex.ErrTerm (MIM.Error.ParseError,
+ "Invalid selector: " + name);
+ return s;
+ }
+}) ();
+
+MIM.Rule = function (keyseq, actions)
+{
+ this.keyseq = keyseq;
+ this.actions = actions;
+}
+MIM.Rule.prototype = new Xex.Term ('rule');
+MIM.Rule.prototype.Parser = function (domain, node)
+{
+ var n;
+ for (n = node.firstChild; n && n.nodeType != 1; n = n.nextSibling);
+ if (! n)
+ throw new Xex.ErrTerm (MIM.Error.ParseError, "invalid rule:" + node);
+ var keyseq = Xex.ParseTerm (domain, n);
+ if (keyseq.type != 'keyseq')
+ throw new Xex.ErrTerm (MIM.Error.ParseError, "invalid rule:" + node);
+ var actions = Xex.ParseTermList (domain, n.nextSibling);
+ return new MIM.Rule (keyseq, actions);
+}
+MIM.Rule.prototype.toString = function ()
+{
+ return '<rule/>';
+}
+
+MIM.Map = function (name)
+{
+ this.name = name;
+ this.rules = new Array ();
+};
+(function () {
+ var proto = new Xex.Term ('map');
+
+ proto.Parser = function (domain, node)
+ {
+ var name = node.attributes['mname'].nodeValue;
+ if (! name)
+ throw new Xex.ErrTerm (MIM.Error.ParseError, "invalid map");
+ var map = new MIM.Map (name);
+ for (var n = node.firstChild; n; n = n.nextSibling)
+ if (n.nodeType == 1)
+ map.rules.push (Xex.ParseTerm (domain, n));
+ return map;
+ }
+
+ proto.toString = function ()
+ {
+ var str = '<map mname="' + this.name + '">';
+ var len = this.rules.length;
+ for (i = 0; i < len; i++)
+ str += this.rules[i];
+ return str + '</map>';
+ }
+
+ MIM.Map.prototype = proto;
+}) ();
+
+Xex.CatchTag._mimtag = new Xex.SymTerm ('@mimtag');
+
+MIM.Action = function (domain, terms)
+{
+ var args = new Array ();
+ args.push (Xex.CatchTag_.mimtag);
+ for (var i = 0; i < terms.length; i++)
+ args.push (terms[i]);
+ this.action = Xex.Funcall.prototype.New (domain, 'catch', null, args);
+}
+
+MIM.Action.prototype.Run = function (domain)
+{
+ var result = this.action.Eval (domain);
+ if (result.type == 'error')
+ {
+ domain.context.Error = result.toString ();
+ return false;
+ }
+ return (result != Xex.CatchTag._mimtag);
+}
+
+MIM.Keymap = function ()
+{
+ this.submaps = null;
+ this.actions = null;
+};
+(function () {
+ var proto = {};
+
+ function add_rule (keymap, rule)
+ {
+ var keyseq = rule.keyseq;
+ var len = keyseq.val.length;
+
+ for (var i = 0; i < len; i++)
+ {
+ var key = keyseq.val[i];
+ var sub;
+
+ if (! keymap.submaps)
+ keymap.submaps = {};
+ else
+ sub = keymap.submaps[key.key];
+ if (! sub)
+ keymap.submaps[key.key] = sub = new MIM.Keymap ();
+ keymap = sub;
+ }
+ keymap.actions = rule.actions;
+ }
+
+ proto.Add = function (map)
+ {
+ var rules = map.rules;
+ var len = rules.length;
+
+ for (var i = 0; i < len; i++)
+ add_rule (this, rules[i]);
+ }
+ proto.Lookup = function (keys, index)
+ {
+ var sub;
+
+ if (index < keys.val.length && this.submaps
+ && (sub = this.submaps[keys.val[index].key]))
+ {
+ index++;
+ return sub.Lookup (keys, index);
+ }
+ return { map: this, index: index };
+ }
+
+ MIM.Keymap.prototype = proto;
+}) ();
+
+MIM.State = function (name)
+{
+ this.name = name;
+ this.keymap = new MIM.Keymap ();
+};
+(function () {
+ var proto = new Xex.Term ('state');
+
+ proto.Parser = function (domain, node)
+ {
+ var map_list = domain.map_list;
+ var name = node.attributes['sname'].nodeValue;
+ if (! name)
+ throw new Xex.ErrTerm (MIM.Error.ParseError, "invalid map");
+ var state = new MIM.State (name);
+ for (node = node.firstChild; node; node = node.nextSibling)
+ {
+ if (node.nodeType != 1)
+ continue;
+ if (node.nodeName == 'branch')
+ {
+ state.keymap.Add (map_list[node.attributes['mname'].nodeValue]);
+ state.keymap.actions = Xex.ParseTermList (domain, node.firstChild);
+ }
+ else if (node.nodeName == 'state-hook')
+ state.enter_actions = Xex.ParseTermList (domain, node.firstChild);
+ else if (node.nodeName == 'catch-all-branch')
+ state.fallback_actions = Xex.ParseTermList (domain, node.firstChild);
+ else if (node.nodeName == 'title')
+ state.title = node.firstChild.nodeValue;
+ }
+ return state;
+ }
+
+ proto.toString = function ()
+ {
+ return '<state sname="' + this.name + '">' + this.keymap + '</state>';
+ }
+
+ MIM.State.prototype = proto;
+}) ();
+
+MIM.im_domain = new Xex.Domain ('input-method', null, null);
+MIM.im_domain.DefType (MIM.KeySeq.prototype);
+MIM.im_domain.DefType (MIM.Marker.prototype);
+MIM.im_domain.DefType (MIM.Selector.prototype);
+MIM.im_domain.DefType (MIM.Rule.prototype);
+MIM.im_domain.DefType (MIM.Map.prototype);
+MIM.im_domain.DefType (MIM.State.prototype);
+
+(function () {
+ var im_domain = MIM.im_domain;
+
+ function Finsert (domain, vari, args)
+ {
+ domain.context.insert (args[0].val, null);
+ }
+
+ im_domain.DefSubr (Finsert, "insert", false, 1, 1);
+}) ();
+
+(function () {
+ var parsers = { };
+ parsers['description'] = function (node)
+ {
+ this.description = node.firstChild.nodeValue;
+ }
+ parsers['title'] = function (node)
+ {
+ this.title = node.firstChild.nodeValue;
+ }
+ parsers['map-list'] = function (node)
+ {
+ for (node = node.firstChild; node; node = node.nextSibling)
+ {
+ if (node.nodeType != 1 || node.nodeName != 'map')
+ continue;
+ var map = Xex.ParseTerm (this.domain, node);
+ this.map_list[map.name] = map;
+ }
+ }
+ parsers['state-list'] = function (node)
+ {
+ this.domain.map_list = this.map_list;
+ for (node = node.firstChild; node; node = node.nextSibling)
+ {
+ if (node.nodeType != 1 || node.nodeName != 'state')
+ continue;
+ var state = Xex.ParseTerm (this.domain, node);
+ if (! state.title)
+ state.title = this.title;
+ if (! this.initial_state)
+ this.initial_state = state;
+ this.state_list[state.name] = state;
+ }
+ delete this.domain.map_list;
+ }
+
+ MIM.IM = function (lang, name, extra_id, file)
+ {
+ this.lang = lang;
+ this.name = name;
+ this.extra_id = extra_id;
+ this.file = file;
+ this.load_status = MIM.LoadStatus.NotLoaded;
+ this.domain = new Xex.Domain (this.lang + '-' + this.name,
+ MIM.im_domain, null);
+ }
+
+ var proto = {
+ Load: function ()
+ {
+ var node = Xex.Load (null, this.file);
+ if (! node)
+ {
+ this.load_status = MIM.LoadStatus.Error;
+ return false;
+ }
+ this.map_list = {};
+ this.initial_state = null;
+ this.state_list = {};
+ for (node = node.firstChild; node; node = node.nextSibling)
+ {
+ if (node.nodeType != 1)
+ continue;
+ var name = node.nodeName;
+ var parser = parsers[name];
+ if (parser)
+ parser.call (this, node);
+ }
+ this.load_status = MIM.LoadStatus.Loaded;
+ return true;
+ }
+ }
+
+ MIM.IM.prototype = proto;
+
+ MIM.IC = function (im)
+ {
+ if (im.load_status == MIM.LoadStatus.NotLoaded)
+ im.Load ();
+ if (im.load_status != MIM.LoadStatus.Loaded)
+ alert ('im:' + im.name + ' error:' + im.load_status);
+ this.im = im;
+ this.domain = new Xex.Domain ('context', im.domain, this);
+ this.active = true;
+ this.reset ();
+ }
+
+ MIM.CandidateTable = function ()
+ {
+ this.table = new Array ();
+ }
+
+ MIM.CandidateTable.prototype.get = function (from)
+ {
+ for (var i = 0; i < this.table.length; i++)
+ {
+ var elt = this.table[i];
+ if (elt.from <= from && elt.to > from)
+ return elt.val;
+ }
+ }
+
+ MIM.CandidateTable.prototype.put = function (from, to, candidates)
+ {
+ 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)
+ {
+ elt.from = from;
+ elt.to = to;
+ elt.val = candidates;
+ return;
+ }
+ }
+ this.table.push ({ from: from, to: to, val: candidates });
+ }
+
+ MIM.CandidateTable.prototype.adjust = function (from, to, inserted)
+ {
+ var diff = inserted - (to - from);
+ for (var i = 0; i < this.table.length; i++)
+ {
+ var elt = this.table[i];
+ if (elt.from >= to)
+ {
+ elt.from += diff;
+ elt.to += diff;
+ }
+ }
+ }
+
+ MIM.CandidateTable.prototype.clear = function ()
+ {
+ this.table.length = 0;
+ }
+
+ function set_cursor (prefix, pos)
+ {
+ this.cursor_pos = pos;
+ if (pos > 0)
+ this.candidates = this.candidate_table.get (pos - 1);
+ else
+ this.candidates = null;
+ }
+
+ function save_state ()
+ {
+ this.state_var_values = this.domain.SaveValues ();
+ this.state_preedit = this.preedit;
+ this.state_key_head = this.key_head;
+ this.state_pos = this.cursor_pos;
+ }
+
+ function restore_state ()
+ {
+ this.domain.RestoreValues (this.state_var_values);
+ this.preedit = this.state_preedit;
+ set_cursor.call (this, "restore", this.state_pos);
+ }
+
+ function handle_key ()
+ {
+ var out = this.keymap.Lookup (this.keys, this.key_head);
+ var sub = out.map;
+
+ alert ('handling ' + this.keys.val[this.key_head]);
+ this.key_head = out.index;
+ if (sub != this.keymap)
+ {
+ restore_state.call (this);
+ this.keymap = sub;
+ alert ('submap found, taking map actions:' + sub.actions);
+ if (this.keymap.actions != null)
+ {
+ if (! this.take_actions (this.keymap.actions))
+ return false;
+ }
+ else if (this.keymap.submaps != null)
+ {
+ for (var i = this.state_key_head; i < this.key_head; i++)
+ this.preedit_replace (this.cursor_pos, this.cursor_pos,
+ this.keys.val[i].key, null);
+ }
+ if (this.keymap.submaps == null)
+ {
+ if (this.keymap.branch_actions != null)
+ {
+ if (! this.take_actions (this.keymap.branch_actions))
+ return false;
+ }
+ if (this.keymap != this.state.keymap)
+ this.shift (this.state);
+ }
+ }
+ else
+ {
+ var current_state = this.state;
+
+ if (this.keymap.branch_actions != null)
+ {
+ if (! this.take_actions (this.keymap.branch_actions))
+ return false;
+ }
+ if (this.state == current_state)
+ {
+ if (this.state == this.initial_state
+ && this.key_head < this.keys.val.length)
+ return false;
+ if (this.keymap != this.state.keymap)
+ this.shift (this.state);
+ else if (this.keymap.branch_actions == null)
+ this.shift (this.initial_state);
+ }
+ }
+ return true;
+ }
+
+ proto = {
+ init: function ()
+ {
+ this.produced = null;
+ this.preedit = '';
+ this.cursor_pos = 0;
+ this.marker_positions = {};
+ this.candidates = null;
+ this.candidate_show = false;
+ this.state = null;
+ this.prev_state = null;
+ this.initial_state = this.im.initial_state;
+ this.title = this.initial_state.title;
+ this.state_preedit = '';
+ this.state_key_head = 0;
+ this.state_var_values = {};
+ this.state_pos = 0;
+ this.keymap = null;
+ this.keys = new MIM.KeySeq ();
+ this.key_head = 0;
+ this.key_unhandled = false;
+ this.unhandled_key = null;
+ this.changed = MIM.ChangedStatus.None;
+ this.error_message = '';
+ this.title = this.initial_state.title;
+ this.produced = null;
+ this.preedit = '';
+ this.marker_positions = {};
+ this.candidate_table = new MIM.CandidateTable ();
+ this.candidates = null;
+ this.candidate_show = false;
+ },
+
+ reset: function ()
+ {
+ this.init ();
+ this.state_var_values = {};
+ this.shift (this.initial_state);
+ },
+
+ catch_args: new Array (Xex.CatchTag._mimtag, null),
+
+ take_actions: function (actions)
+ {
+ var func_progn = this.domain.GetFunc ('progn');
+ var func_catch = this.domain.GetFunc ('catch');
+ this.catch_args[1] = new Xex.Funcall (func_progn, null, actions);
+ var term = new Xex.Funcall (func_catch, null, this.catch_args);
+ term = term.Eval (this.domain);
+ return (! term.IsSymbol || term.val != '@mimtag');
+ },
+
+ GetSurroundingChar: function (pos)
+ {
+ if (pos < 0 ? this.caret_pos < - pos : this.target.value.length < pos)
+ return 0;
+ return this.target.value.charCodeAt (this.caret_pos + pos);
+ },
+
+ adjust_markers: function (from, to, inserted)
+ {
+ var diff = inserted - (to - from);
+
+ for (var m in this.marker_positions)
+ if (this.marker_positions[m] > from)
+ this.marker_positions[m] = (this.marker_positions[m] >= to
+ ? pos + diff : from);
+ if (this.cursor_pos >= to)
+ set_cursor.call (this, 'adjust', this.cursor_pos + diff);
+ else if (this.cursor_pos > from)
+ set_cursor.call (this, 'adjust', from)
+ },
+
+ preedit_replace: function (from, to, text, candidates)
+ {
+ this.preedit = (this.preedit.substring (0, from)
+ + text + this.preedit.substring (to));
+ this.adjust_markers (from, to, text.length);
+ this.candidate_table.adjust (from, to, text.length);
+ if (candidates)
+ this.candidate_table.put (from, from + text.length, candidates)
+ },
+
+ insert: function (text, candidates)
+ {
+ this.preedit_replace (this.cursor_pos, this.cursor_pos, text, candidates);
+ this.changed = MIM.ChangedStatus.Preedit | MIM.ChangedStatus.CursorPos;
+ },
+
+ del: function (pos)
+ {
+ if (pos < 0)
+ {
+ this.DelSurroundText (pos);
+ pos = 0;
+ }
+ else if (pos > this.preedit.length)
+ {
+ this.DelSurroundText (pos - this.preedit.length);
+ pos = this.preedit.length;
+ }
+ if (pos < this.cursor_pos)
+ this.preedit = (this.predit.substring (0, pos)
+ + this.preedit.substring (this.cursor_pos));
+ else
+ this.preedit = (this.preedit.substring (0, this.cursor_pos)
+ + this.predit.substring (pos));
+ },
+
+ show: function ()
+ {
+ this.candidate_show = true;
+ this.changed |= MIM.ChangedStatus.CandidateShow;
+ },
+
+ hide: function ()
+ {
+ this.candidate_show = false;
+ this.changed |= MIM.ChangedStatus.CandidateShow;
+ },
+
+ move: function (pos)
+ {
+ if (pos < 0)
+ pos = 0;
+ else if (pos > this.preedit.length)
+ pos = this.preedit.length;
+ if (pos != this.cursor_pos)
+ {
+ set_cursor.call (this, 'move', pos);
+ this.changed |= MIM.ChangedStatus.Preedit;
+ }
+ },
+
+ pushback: function (n)
+ {
+ if (n instanceof MIM.KeySeq)
+ {
+ if (this.key_head > 0)
+ this.key_head--;
+ if (this.key_head < this.keys.val.length)
+ this.keys.val.splice (this.key_head,
+ this.keys.val.length - this.key_head);
+ for (var i = 0; i < n.val.length; i++)
+ this.keys.val.push (n.val[i]);
+ return;
+ }
+ if (n > 0)
+ {
+ this.key_head -= n;
+ if (this.key_head < 0)
+ this.key_head = 0;
+ }
+ else if (n == 0)
+ this.key_head = 0;
+ else
+ {
+ this.key_head = - n;
+ if (this.key_head > this.keys.val.length)
+ this.key_head = this.keys.val.length;
+ }
+ },
+
+ pop: function ()
+ {
+ if (this.key_head < this.keys.val.length)
+ this.keys.val.splice (this.key_head, 1);
+ },
+
+ commit: function ()
+ {
+ if (this.preedit.length > 0)
+ {
+ this.candidate_table.clear ();
+ this.produced += this.preedit;
+ this.preedit_replace.call (this, 0, this.preedit.Length, '', null);
+ }
+ },
+
+ shift: function (state)
+ {
+ if (state == null)
+ {
+ if (this.prev_state == null)
+ return;
+ state = this.prev_state;
+ }
+
+ if (state == this.initial_state)
+ {
+ this.commit ();
+ this.keys.val.splice (0, this.key_head);
+ this.key_head = 0;
+ if (state != this.state)
+ {
+ this.domain.RestoreValues (this.state_initial_var_values);
+ if (state.enter_actions != null)
+ take_actions.call (state.enter_actions);
+ }
+ this.prev_state = null;
+ }
+ else
+ {
+ if (state != this.state && state.enter_actions != null)
+ take_actions.call (state.enter_actions);
+ this.prev_state = this.state;
+ }
+ save_state.call (this);
+ if (! this.state || this.state.title != state.title)
+ this.changed |= MIM.ChangedStatus.StateTitle;
+ this.state = state;
+ this.keymap = state.keymap;
+ },
+
+ Filter: function (key)
+ {
+ if (! this.active)
+ {
+ this.key_unhandled = true;
+ this.unhandled_key = key;
+ return false;
+ }
+ if (key.key == '_reload')
+ return true;
+ this.changed = MIM.ChangedStatus.None;
+ this.produced = '';
+ this.key_unhandled = false;
+ this.keys.val.push (key);
+ var count = 0;
+ while (this.key_head < this.keys.val.length)
+ {
+ if (! handle_key.call (this))
+ {
+ this.unhandled_key = this.keys.val[this.key_head++];
+ this.key_unhandled = true;
+ break;
+ }
+ if (++count == 10)
+ break;
+ }
+ this.keys.val.splice (0, this.key_head);
+ this.key_head = 0;
+ return (! this.key_unhandled && this.produced.length == 0);
+ }
+ }
+
+ MIM.IC.prototype = proto;
+
+ var node = Xex.Load (null, "imlist.xml");
+ for (node = node.firstChild; node; node = node.nextSibling)
+ if (node.nodeName == 'input-method')
+ {
+ var lang, name, extra_id, file;
+
+ for (var n = node.firstChild; n; n = n.nextSibling)
+ {
+ if (n.nodeName == 'language')
+ lang = n.firstChild.nodeValue;
+ else if (n.nodeName == 'name')
+ name = n.firstChild.nodeValue;
+ else if (n.nodeName == 'extra-id')
+ extra_id = n.firstChild.nodeValue;
+ else if (n.nodeName == 'filename')
+ file = n.firstChild.nodeValue;
+ }
+ if (! MIM.im_list[lang])
+ MIM.im_list[lang] = {};
+ MIM.im_list[lang][name] = new MIM.IM (lang, name, extra_id, file);
+ }
+ node = undefined;
+}) ();
+
+(function () {
+
+ MIMTEST = function (name) { this.nam = name; };
+
+ function testshow () { alert (this.nam); };
+
+ MIMTEST.prototype.show = function () { testshow.call (this); }
+ MIMTEST.prototype.cut = function (from, to) {
+ this.val.splice (from, to -from); return this.val; }
+
+ MIMTEST2 = function (name) { this.nam = name;
+ this.val = new Array (1,2,3,4,5);}
+
+ MIMTEST2.prototype = MIMTEST.prototype;
+
+ var x = new MIMTEST2 ('test2');
+}) ();
+
+MIM.test = function ()
+{
+ var im = MIM.im_list['t']['latn-post'];
+ var ic = new MIM.IC (im);
+
+ document.AIM = im;
+
+ ic.Filter (new MIM.Key ('a'));
+ ic.Filter (new MIM.Key ("'"));
+
+ if (true)
+ document.getElementById ('text').value = ic.preedit;
+ else {
+ try {
+ document.getElementById ('text').value
+ = Xex.ParseTerm (domain, body).Eval (domain).toString ();
+ } catch (e) {
+ if (e instanceof Xex.ErrTerm)
+ alert (e);
+ throw e;
+ }
+ }
+}