
/// ******
/// QQQQQQ
# A spell checker Module....


# SPELL_CONST.id_prefix
var SPELL_CONST = {
    unused: "spell", id_prefix: "misspell-", instance_list: { }, suggest_max: 5,
    pg_not_found: "404 Not Found",
    squiggle: "mark", unmark : "unmark", reg_exp: null, max_check: 51200
};

# *** Initialisation and instance handling
function Spell(scid, win)	// WAS cI
{
    this.scid = scid;
    this.the_win = win;
    this.the_doc = win.document;
    this.the_body = win.document.body;
    this.modified = false;
    this.unique = 0;
    this.N = true;
    this.xx_init = false;
    this.xx_unique = 0;
    this.F = [];		// Language related stuff
    SPELL_CONST.instance_list[this.scid] = this;
}
Spell.prototype.attach = function(win)	// was gE
{
    this.the_win = win;
    this.the_doc = win.document;
    this.the_body = win.document.body;
};
Spell.prototype.detach = function(reset)			
{
    this.the_body = null;
    this.the_doc = null;
    this.the_win = null;
    if (reset) {
        SPELL_CONST.instance_list[this.scid] = null;
    }
};
Spell.getInstance = function(id)			// was B
{
    if (SPELL_CONST.instance_list[id]) {
        return SPELL_CONST.instance_list[id];
    } else {
        return null;
    }
};

# *** Actually highlight the misspelled words in the document
Spell.prototype.highlightWords = function()				//was fq
{
    var results = this.response; 	// was T =...

//	If anything mis-spelled	
    if (results != null && results.length) {

        var results_length = results.length;

        var keep = { };
        var start_tag = '<SPAN id="_mid" class="' + SPELL_CONST.squiggle + '" >';
		var end_tag = '</SPAN>';		// Pe == Primary string table...

        var old_html = this.html_on1line_clean();
#        old_html=old_html.substring(old_html.indexOf("The"));
        var new_html = "";
        var upto = 0;
        var report_bug = "";
        var done_some = false;

// 		Walk for each word		
        for (var i = 0; i < results_length; ++i) {
            var offset = parseInt(results[i]["offset"]);
            var word = results[i]["word"];

            if (this.lookup_in_arrLang(word)) {
                continue;
            }
            new_html += old_html.substring(upto, offset);
            var rword = old_html.substring(offset, offset + word.length);

            if (word == rword) {
                new_html += start_tag.replace("_mid", SPELL_CONST.id_prefix + i);
                new_html += rword + end_tag;
                if (!done_some) {
                    done_some = true;
                }
            } else {
                new_html += rword;
                if(!report_bug)report_bug += word + '/' + rword;
            }
            upto = offset + word.length;
            keep[word] = results[i];
        }

        if (report_bug) {
			set_status('$$st_spell_unsync$$ (expected/found='+report_bug+')',"info")            
        }
        this.unique = results_length;
        new_html += old_html.substr(upto, old_html.length);

        this.Q = keep;
        
        var cursor = isIE ? this.getCursorIE() : null;		//Ca.A ==> isIE

        if (isMozilla) {									//Ca.B ==> isMozilla
            xdoc.designMode = "Off";
        }
        this.the_body.innerHTML = new_html;
        this.modified = true;

        if (isMozilla) {									//Ca.B ==> isMozilla
            xdoc.designMode = "on";
            this.setCursorMoz();
        } else {
            this.setCursorIE(cursor);						// else IE??
        }

        if (!done_some) {
            alert("$$st_spell_none$$");// Pe.jk);									// There are no spelling errors!!
        }
    }
};
Spell.prototype.isModified = function() { return this.modified; };

# *** Deal with cursor and selections etc...

Spell.prototype.getCursorIE = function()
{
    var E = this.the_doc.selection.createRange();
    var D = E.getClientRects ? E.getClientRects() : null;

    if (D && D.length > 0) {
        var F = { };
        F.x = E.offsetLeft;
        F.y = E.offsetTop;
        return F;
    }
    return null;
};
Spell.prototype.setCursorIE = function(F)
{
    if (F == null) {
        return;
    }

    try {
        var E = this.the_body.createTextRange();
        E.collapse(true);
        E.moveToPoint(F.x, F.y);
        E.select();
    } catch (D) { }
};
Spell.prototype.markCursorMozilla = function()
{

	try {
        var H = this.the_win.getSelection();
        var J = H.rangeCount > 0 ? H.getRangeAt(0) : null;
        var K = J ? J.commonAncestorContainer : null;
        var G = null;

        if (K) {
            G = K.nodeType == 3 ? K.parentNode : K;
        }

        if (G) {
#            J.setStart(J.startContainer, 0);
            var L = this.the_win.document.createElement("span");
            L.id = SPELL_CONST.id_prefix + "cursor";
            L.className = SPELL_CONST.unmark;
            J.insertNode(L);
#			insert_within_textnode(L,J,J.startOffset);
        }
    } catch (I) {
        eK.A("Problem marking cursor position before spellcheck");
    }
};
function insert_within_textnode(span,text_node,at)
{
	// create new span node with content
#	var span = this.the_win.document.createElement("span");
#	span.appendChild(this.the_win.document.createTextNode('ipsum'));

	// Split the text node into two and add new span
	text_node.insertBefore(span, text_node.splitText(at));
}
Spell.prototype.setCursorMoz = function()
{
 	var el_cursor = this.the_doc.getElementById(SPELL_CONST.id_prefix + "cursor");

    if (el_cursor) {
        var sel = this.the_win.getSelection();
        var range = sel.rangeCount > 0 ? sel.getRangeAt(0) : null;

        if (range) {
            var range2 = range.cloneRange();
            sel.removeAllRanges();
        } else {
            range2 = this.the_win.document.createRange();
        }
        range2.selectNode(el_cursor);	// 
        range2.collapse(false);			// Collapse to end!! 
        sel.addRange(range2);
    }
};

# *** Get and set the actual html 

Spell.prototype.html_on1line = function()
{
    var B = this.the_body.innerHTML;
    B = B.replace(/[\r\n]/g, " ");
    return B;
};
Spell.prototype.html_on1line_clean = function()
{
    var root = this.the_body.cloneNode(true);
    els=root.getElementsByTagName('span');
    for(var i=els.length-1;i>=0;i--)
		if(class_contains(els[i],'mark'))
		    this.applyCorrection(els[i],true);
	var txt= oddball_cleanup(root.innerHTML);

	txt = txt.replace(/[\r\n]/g, " ");

	root=null;
    return txt;
};
Spell.prototype.getTextToCheck = function()
{
//    this.correctAll(true, null, true);

    if (isMozilla) {
        this.markCursorMozilla();
    }
    var txt = this.html_on1line_clean();

// 	Cannot be done clientside if txt is used to save drafts
//    if (txt && txt.length > SPELL_CONST.max_check) {
//        txt = txt.substring(0, SPELL_CONST.max_check);
//    }
    this.S = false;
#	Cannot do this as it does bad things sending messages that contain percentage signs 
#	try without and see if we encounter problems with the spelling checker??
#   txt = txt.replace(/%/g, "%25");
    return txt;
};


# *** Actually apply corrections

Spell.prototype.correctAll = function(flag1, txt, flag2)
{
    flag1 == (!flag1) ? false : flag1;
    var words = this.getWords(txt, flag2);

    for (var J = words.length - 1; J >= 0; J--) {
        var G = words[J].id;

        if (G && G.indexOf(SPELL_CONST.id_prefix) != -1) {
            this.applyCorrection(words[J], flag1);
        }
    }
};
Spell.prototype.applyCorrection = function(el, flag, correct_word)
{
    el = el ? el : this.current_node;

    if (el != null) {
        if (isIE) {
            if (correct_word) {
                el.innerText = correct_word;
            }

            if (flag) {
                if (el.spellMenu) {
                    el.spellMenu = null;
                }
                el.removeNode(false);
            } else {
                el.className = SPELL_CONST.unmark;
            }
        } else {
            if (correct_word) {
                el.textContent = correct_word;
            }
            el.className = SPELL_CONST.unmark;

            if (flag && !correct_word) {
                this.correctSpecalCase(el);
            }
        }
    }
};
Spell.prototype.correctSpecalCase = function(G)
{
    var F = G.parentNode;
    var E = G;

    for (var H = G.childNodes.length - 1; H >= 0; H--) {
        E = F.insertBefore(G.childNodes[H], E);
    }

    if (F.spellMenu) {
        F.spellMenu = null;
    }
    F.removeChild(G);
    F.normalize();
};

// Get all words (spans) matching first param
Spell.prototype.getWords = function(txt, L)		//was g5
{
    var Q = [];
    var M = [];
    var O = this.the_doc.getElementsByTagName("SPAN");

    if (O) {
        if (!O.length) {
            M[0] = O;
        } else {
            M = O;
        }
        var U2 = M.length;
        var S = 0;

        if (txt) {
            txt = txt.toUpperCase();
        }

        for (var N = 0; N < U2; N++) {
            if (txt) {
                var T = isIE ? M[N].innerText : M[N].textContent;

                if (T.toUpperCase() != txt) {
                    continue;
                }
            }
            var R = M[N].id;

            if (R && R.indexOf(SPELL_CONST.id_prefix) != -1) {
                var V = M[N].className;

                if (L || V != SPELL_CONST.unmark) {
                    Q[S++] = M[N];
                }
            }
        }
    }
    return Q;
};
Spell.prototype.spellCorrectHandler = function(e)
{
    var F = this.current_node;

    if (!(e && e.srcElement)) {
        return;
    }
    var D = e.srcElement.innerHTML;

    if (e.srcElement.tagName == "LI") {
        D = e.srcElement.childNodes[0].innerHTML;
    }

    if (F != null && e != null) {
        this.doCorrection(F, true, D);
    }
};
Spell.prototype.spellIgnoreHandler = function(e) { this.applyCorrection(null, isIE); };
Spell.prototype.gD = function() { };
Spell.prototype.spellIgnoreAllHandler = function(e)
{
    var word = isIE ? this.current_node.innerText : this.current_node.textContent;
    this.correctAll(false, word);
};
Spell.prototype.ajaxResultApply = function(txt)		// was g4
{
	this.response=txt;	// Object really
	return;

    this.response = [];
    var gG = false;
    var gF = null;

    if (!txt || txt.indexOf(SPELL_CONST.pg_not_found) >= 0) {
        gG = "404";
    } else {
        var gI = "var mwc = " + txt + ";";

        try {
            eval(gI);
            gF = mwc;

            if (gF.length == 0) {
                return "222";
            }
        } catch (gJ) {
            gG = "501";
            gF = null;
        }
    }
    this.response = gF ? gF : [];
    return gG;
};
Spell.prototype.showElementsMenu = function(el, E)		// was fw
{
    var id = el ? el.id : null;
    if (id && id.indexOf(SPELL_CONST.id_prefix) != -1 && el.className == SPELL_CONST.squiggle) {
        var same_node = this.current_node && (id == this.current_node.id);
        this.N = same_node ? !this.N : true;
        this.current_node = el;
        
        // QQQ
        this.showMenu(el)
		return true
        
        Component.load(Pe.Ug, EE(this, this.showMenu, el, E));
        return true;
    } else {
        this.current_node = null;
        dj.A();
    }
    return false;
};
Spell.prototype.keyEvent = function(E)
{
    // Hide stuff menu related??
    dj.A();			

    if (this.specialKeys(E)) {
        return;
    }

    if (E.keyCode != KeyCodes.Escape) {
        this.S = true;
    }

    if (this.xx_init) {
        this.xx_UnInitAndCall();		// Some form of global function etc to be calling
    }

    if (!this.modified) {
        return;
    }
    var el = this.bothRangeFn(E);
    var id = el ? el.id : null;

    if (id && id.indexOf(SPELL_CONST.id_prefix) != -1) {
        if (el.className == SPELL_CONST.squiggle) {
            this.applyCorrection(el);
        } else {
            if (E.keyCode == KeyCodes.Space || E.keyCode == KeyCodes.Escape) {
                this.modified = false;
                this.correctAll(false);
            }
        }
    } else {
        if (E.keyCode != KeyCodes.Enter) {
            this.modified = false;
            this.correctAll(false);
        }
    }
};
Spell.prototype.ft = function(B) { };
Spell.prototype.specialKeys = function(B)
{
    if ((B.keyCode >= KeyCodes.PageUp && B.keyCode <= KeyCodes.Insert)
        || (B.altKey || B.ctrlKey || B.keyCode == KeyCodes.Shift || B.metaKey)
            || (B.keyCode == KeyCodes.Caps || B.keyCode == KeyCodes.Tab)
            || (B.keyCode == 144 || B.keyCode == 145 || B.keyCode == 19) || (B.keyCode >= 112 && B.keyCode <= 135)
            || (B.keyCode >= 91 && B.keyCode <= 93) || (B.keyCode >= 164 && B.keyCode <= 165)) {
        return true;
    }
    return false;
};
Spell.prototype.bothRangeFn = function(W)
{
    var O = null;
    var M = false;

    if (isIE) {
        var N = this.the_doc.selection.createRange();
        var X = N.text;

        if (N && N.parentElement()) {
            O = N.parentElement();
        }
        var P = N ? (N.text.length > 1) : false;
        var T = O ? O.id : null;
        var Q = T && T.indexOf(SPELL_CONST.id_prefix) != -1;
        var R = this.ieRangeFn1(N, Q, P);

        if (R) {
            O = R;
        }
        var S = this.ieRangeFn2(N, Q, P, W);

        if (S) {
            O = S;
        }
        this.ieRangeFn3(N, Q, P, O);
    } else {
        var U2 = this.the_win.getSelection();
        var N = U2.rangeCount > 0 ? U2.getRangeAt(0) : null;
        var V = N ? N.commonAncestorContainer : null;

        if (V) {
            O = V.nodeType == 3 ? V.parentNode : V;
        }
        var P = N ? (N.toString().length > 1) : false;
        var T = O ? O.id : null;
        var Q = T && T.indexOf(SPELL_CONST.id_prefix) != -1;
        var R = this.mozRangeFn1(N, Q, P, U2);

        if (R) {
            O = R;
        }
        var S = this.mozRangeFn2(N, Q, P, U2);

        if (S) {
            O = S;
        }
    }
    return O;
};
Spell.prototype.ieRangeFn3 = function(J, H, I, L)
{
    if (H) {
        if (J.text == L.innerText) {
            var G = J.text.charAt(J.text.length - 1) != " ";

            if (G) {
                J.moveEnd("character", -1);
                J.collapse(true);
                this.the_doc.selection.empty();
                var K = this.the_win.document.createElement("span");
                K.innerText = " ";
                oElement = L.insertAdjacentElement("afterEnd", K);
                J.moveToElementText(L);
                J.select();
            }
        }
    }
};
Spell.prototype.ieRangeFn1 = function(L, J, K)
{
    if (!J && K) {
        var N = L.htmlText;

        if (!SPELL_CONST.reg_exp) {
            SPELL_CONST.reg_exp = new RegExp("^<span ([^>]*?class=" + SPELL_CONST.squiggle + "[^>]*[ ]+id=" + SPELL_CONST.id_prefix + "[0-9]+[^>]*?>)(.*)(</span>) $",
                "ig");
        }
        var I = SPELL_CONST.reg_exp;
        var H = N.search(I);

        if (H != -1) {
            L.moveEnd("character", -1);

            if (L && L.parentElement()) {
                var M = L.parentElement();
                L.collapse(true);
                this.the_doc.selection.empty();
                L.moveToElementText(M);
                L.select();
                return M;
            }
        }
    }
    return null;
};
Spell.prototype.ieRangeFn2 = function(K, L, M, J)
{
    if (!L && !M) {
        var O = K.duplicate();
        O.move("character", 1);

        if (O && O.parentElement()) {
            var N = O.parentElement();

            if (N && N.id && N.id.indexOf(SPELL_CONST.id_prefix) != -1) {
                if (J.keyCode == 46/*KeyCodes.Delete*/) {
                    return N;
                }
                var P = this.the_win.document.createElement("span");
                P.id = SPELL_CONST.id_prefix + (this.unique++);
                P.className = SPELL_CONST.unmark;
                P.innerText = " ";
                var I = N.parentNode;
                I.insertBefore(P, N);
                O.moveToElementText(P);
                O.select();
                return N;
            }
        }
    }
    return null;
};
Spell.prototype.mozRangeFn1 = function(X, O, b, a)
{
    if (b && !O) {
        var T = null;
        var W = X.cloneContents();
        var U2 = this.the_win.document.createElement("span");
        U2.appendChild(W);
        var Y = U2.innerHTML;

        if (!SPELL_CONST.reg_exp) {
            SPELL_CONST.reg_exp = new RegExp('^<span ([^>]*?id="' + SPELL_CONST.id_prefix + '[0-9]+"[^>]*[ ]+class="' + SPELL_CONST.squiggle
                + '"[^>]*?>)(.*)(</span>) $',
                "ig");
        }
        var V = SPELL_CONST.reg_exp;
        var Z = Y.search(V);

        if (Z != -1) {
            var S = X.cloneRange();
            var P = this.the_win.document.createElement("span");
            P.id = SPELL_CONST.id_prefix + (this.unique++);
            P.className = SPELL_CONST.squiggle;
            a.removeAllRanges();
            S.insertNode(P);
            S.selectNodeContents(P);
            S.collapse(false);
            a.addRange(S);
            T = P;

            if (P.parentNode.className == SPELL_CONST.squiggle) {
                var R = P.parentNode;
                R.removeChild(P);
                S.selectNodeContents(R);
                T = R;
            } else {
                if (P) {
                    var R = P.parentNode;
                    var Q = P.nextSibling;

                    if (Q && Q.textContent == "") {
                        Q = Q.nextSibling;
                    }

                    if (Q && (Q.className == SPELL_CONST.squiggle)) {
                        R.removeChild(Q);
                    }
                }
            }
        }
        return T;
    }
    return null;
};
Spell.prototype.mozRangeFn2 = function(L, U2, V, N)
{
    if (!U2 && !V) {
        var Q = N.anchorNode;
        var S = N.focusNode;
        var P = Q ? Q.previousSibling : null;
        var O = Q ? Q.nextSibling : null;
        var R = N.focusOffset;
        var T = N.anchorOffset;

        if (P && P.id && P.id.indexOf(SPELL_CONST.id_prefix) != -1 && R == 0) {
            var M = this.the_win.document.createRange();
            M.selectNodeContents(P);
            M.collapse(false);
            N.removeAllRanges();
            N.addRange(M);
            return P;
        }

        if (O && O.id && O.id.indexOf(SPELL_CONST.id_prefix) != -1 && R == S.textContent.length) {
            var M = this.the_win.document.createRange();
            M.selectNodeContents(O);
            M.collapse(true);
            N.removeAllRanges();
            N.addRange(M);
            return O;
        }
    }
    return null;
};

function create_element_with_textnode_(J, G, H)
{
	H = H || this.E;
	H=document;
	
	var I = H.createElement(J);
	var F = H.createTextNode(G || "");
	I.appendChild(F);
	return I;
}
function create_element_with_textnode(J, G, H)
{
	H = H || this.E;
	H=document;	
	var I = H.createElement(J);
	I.innerHTML=G;
	return I;
}

function fancy_DOM_Call()
{
#	return xdoc;
	return document;
}


# Menu handling
Spell.prototype.createSpellMenu = function()
{
#    var menu = fancy_DOM_Call().createElement('div');
#    menu.setAttribute("id", "spellCheckMenu");
#    menu.setAttribute("className", "spellmenu");
#	menu.innerHTML="QWERTY";
#	document.body.appendChild(menu);
#	return menu;
	

#	var el= new_anchor('div','Foobar');
#	el.className="spellmenu";
#	return el
	var el=dge('spellCheckMenu');
	if (el) remove_node(el);

    var arr = this.getMenuArray();
    var lab = arr.labels;
    var cmd = arr.commands;
    var menu = fancy_DOM_Call().createElement('div');

    menu.id='spellCheckMenu';
#    menu.setAttribute("id", "spellCheckMenu");
#    menu.setAttribute("className", "spellmenu");
#    menu.setAttribute("className", "xmenu");
	class_add(menu,"xmenu");
	shadofy(menu);
	ignore_one_hide=true;

    for (var i = 0; i < lab.length; i++) {
        var el;

        if (lab[i].indexOf("---") == -1) {
#            el = create_element_with_textnode("item", lab[i]);
            el = create_element_with_textnode("a", lab[i]);
            el.setAttribute("cmd", cmd[i]);
#            el.setAttribute("id", "_test_" + cmd[i] + "_" + i);
        } else {
            el = create_element_with_textnode('a','---');
        }
        menu.appendChild(el);
    }
	menu.onmouseup=spell_menu_click;
	menu.onmouseout=function(e){if(!e) e=window.event; menu_action_mouseout(e,menu.id)}; 
	menu.onmouseover=function(e){if(!e) e=window.event; menu_action_mouseover(e,menu.id)};	
	document.body.appendChild(menu);
	xmenu_register_jshover(menu);
#	menu.onmousemove=function(e){dbg("*** MOVE target="+target(e).tagName)}
#	xx_menu=menu;	
	return menu;	
//    var O = fk.A(menu);		// Create or return existing menu proxy object
//    var R = function() { dj.D("spellCheckMenu"); };
//    fk.B(O, function(A) { A.on("hideEvent", R); });
//    return O;
};
#var xx_menu;

Spell.prototype.showMenu = function(el, D)
{
 	if (!el || el.className != SPELL_CONST.squiggle) {
        return;
    }
    var mnu;
//    var mnu = el.spellMenu;
//    if (mnu == null) {
        mnu = this.createSpellMenu();
        el.spellMenu = mnu;
        mnu.el=el;
        //xdoc.offsetParent=sw.active.field_eframe;
#		menu_position(el,mnu,{yoffset:5},sw.active.field_eframe);

		do_menu_show2(mnu,el,{yoffset:doc_scroll_height(this.the_win,this.the_doc)-5}); 
		//this.positionMenu(el, mnu, D);
#        mnu_show(mnu);
//    } else {
//        el.spellMenu = null;
//        mnu.hide();
//    }
};
function mnu_show(el)
{
	el.style.visibility='visible';
}
Spell.prototype.positionMenu = function(el, mnu, flag)
{
    var x = 0, y = 0;
    var outer_el = this.the_win.frameElement.parentElement;
    var scroll = null;

    while (outer_el && outer_el.id.indexOf("ViewComp_") != 0) {
        if (outer_el.id.indexOf("compAreaT") != 0) {
            x += outer_el.offsetLeft;
            y += outer_el.offsetTop;
        }

        if (outer_el.id.indexOf("compAreaC") == 0) {
            scroll = outer_el;
        }
        outer_el = outer_el.parentElement;
    }

    if (outer_el) {
        x += outer_el.offsetLeft;
        y += outer_el.offsetTop;
    }
    var x2 = this.the_win.frameElement.offsetLeft;
    var y2 = this.the_win.frameElement.offsetTop;
    var x3 = el.offsetLeft;
    var y3 = el.offsetTop;

    if (scroll) {
        y3 -= scroll.scrollTop;
        x3 -= scroll.scrollLeft;
    } else {
        y3 -= this.the_body.scrollTop;
        x3 -= this.the_body.scrollLeft;
    }
    var X = x + x2 + x3 + (el.offsetWidth / 2) + 1;
    var Y = y + y2 + y3 + (el.offsetHeight) + 3;
    
    mnu.style.left=px(X);
    mnu.style.top=px(Y);
#    mnu.cfg.setProperty("xy", [X,Y]);
};

# *** Result data format dependant
Spell.prototype.getMenuArray = function()
{
    var L = "---------";
    var N = [];
    var O = [];
    var K = isIE ? this.current_node.innerText : this.current_node.textContent;
    var I = [];

    if (this.response && this.Q[K]) {
        I = this.Q[K]["suggestions"];
    }
    var J = I.length < SPELL_CONST.suggest_max ? I.length : SPELL_CONST.suggest_max;

    if (J == 0) {
        N[0] = "<i>$$st_spell_no_sugg$$</i>";
        O[0] = "spell_menu_unknown";
    }

    for (var P = 0; P < J; P++) {
        N[P] = I[P];
        O[P] = "spell_menu_correct";
    }

#    if (N.length >= 2) {
	N[N.length] = L;
	O[O.length] = L;

	N[N.length] = "<i>$$st_spell_learn$$</i>";
	O[O.length] = "spell_menu_learn";

	N[N.length] = "<i>$$st_spell_ignore$$</i>";
	O[O.length] = "spell_menu_ignore";
#    }

//    if (N.length > 2) {
//        N[N.length] = "Ignore All";
//        O[O.length] = "compose_ext:spell_ignore_all";
//    }
    var M = {
        labels: N,
        commands: O
    };

    return M;
};


# *** Utility, Debug & Misc functions

Spell.prototype.lookup_in_arrLang = function(D)		// was .c
{
    if (this.F.length == 0) {
        return false;
    }
    D = D.toUpperCase();
    var C = Lang.arrays.indexOf(this.F, D);
    return C != -1;
};
Spell.prototype.g8 = function(B)
{
    if (this.F.length == 0) {
        this.F = B;
    } else {
        this.F = this.F.concat(B);
    }
};
Spell.prototype.xx_DoInit = function()
{
    this.F = [];
    this.xx_init = true;
    this.xx_unique++;
};
Spell.prototype.xx_UnInit = function() { this.xx_init = false; };
Spell.prototype.xx_InitDone = function() { return this.xx_init; };
Spell.prototype.xx_UniqueUpto = function() { return this.xx_unique; };
Spell.prototype.xx_UniqueIdOk = function(B) { return this.xx_unique == B && !this.S; };
Spell.prototype.xx_UnInitAndCall  = function()
{
    this.xx_init = false;

    if (typeof Yv == Pe.Jh) {
        Yv(this);
    }
};


