var supported = (document.all || document.getElementById);
var disabled = false;
var charmapid = 1;
var keymodeid = 2;
var linebreak = 0;
var theTyper = null;
reset = function(){}
telexingVietUC = initTyper;
function setTypingMode(mode) {
	keymodeid = mode;
	if (theTyper) theTyper.keymode= initKeys();
	if (!supported && !disabled) {
		alert("Xin loi, trinh duyet web cua ban khong cho phep dung VietTyping.\n");
		disabled = true;  
	}
}
initCharMap = function(){return new CVietUniCodeMap();}
initKeys = function(){

 switch(keymodeid){
		case 1:return new CTelexKeys();
		case 2:return new CVniKeys();
		default:return new CVniKeys();
	}
}
function initTyper(txtarea){
	txtarea.vietarea=true;
	txtarea.onkeyup=null;
	if(!supported)return;
	txtarea.onkeypress=vietTyping;
	txtarea.getCurrentWord=getCurrentWord;
	txtarea.replaceWord=replaceWord;
	txtarea.onkeydown=onKeyDown;
	txtarea.onmousedown=onMouseDown;
}
function onKeyDown(evt){
	var c=event?event.keyCode:evt.which?evt.which:0;
	if((c==10)||(c==13)){reset(1);linebreak=1;}
	else if((c<49)&&(c!=16)&&(c!=20)){linebreak=0;reset(c==32);}
	return true;
}
function onMouseDown(evt){reset(0);linebreak=0;return true;}
function vietTyping(evt){
	var c=event?event.keyCode:evt.which?evt.which:0;
	if(theTyper)theTyper.value=this.getCurrentWord();
	else theTyper=new CVietString(this.getCurrentWord());
	var changed=(c>32)&&theTyper.typing(c);
	if(changed)this.replaceWord(theTyper.value);
	return !changed;
}
function getCurrentWord(){
	if(!document.all)return this.value;
	var caret=this.document.selection.createRange();
	var backward=-17;
	do{
		var caret2=caret.duplicate();
		caret2.moveStart("character",backward++);
	}while(caret2.parentElement()!=this&&backward<0);
	this.curword=caret2.duplicate();
	return caret2.text;
}
function replaceWord(newword){
	if(!document.all){this.value=newword;return;}
	this.curword.text=newword;
	this.curword.collapse(false);
}
function CVietString(str){
	this.value=str;
	this.keymode=initKeys();
	this.charmap=initCharMap();
	this.ctrlchar='-';
	this.changed=0;
	this.typing=typing;
	this.Dau=Dau;
	this.AEOWD=AEOWD;
	this.findCharToChange=findCharToChange;
	return this;
}
function typing(ctrl){
	this.changed=0;
	this.ctrlchar=String.fromCharCode(ctrl);
	if(linebreak)linebreak=0;else this.keymode.getAction(this);
	return this.changed;
}
function AEOWD(type) {
	var lc=this.charmap.lastCharsOf(this.value);
	var telex=this.charmap.getAEOWD(lc[0],type);
	if(!(this.changed=telex[0]))return;
	this.value=this.value.replaceAt(this.value.length-lc[1],telex[1],lc[1]);
	if(!telex[2]){spellerror=1;this.value+=this.ctrlchar;}
}
function Dau(type){
	var info=this.findCharToChange(type);
	if(!info)return;
	var telex=this.charmap.getDau(info[0],type);
	if(!(this.changed=telex[0]))return;
	this.value=this.value.replaceAt(info[1],telex[1],info[2]);
	if(!telex[2]){spellerror=1;this.value+=this.ctrlchar;}
}
function findCharToChange(type){
	var lastchars=this.charmap.lastCharsOf(this.value,3);
	var i=0,c=lastchars[0][0];
	if(c=='\\')return [c,this.value.length-1,1];
	while(!this.charmap.isVowel(c)){
		if((c<'A')||(i>=2))return null;
		if(!(c=lastchars[++i][0]))return null;
	}
	c=lastchars[0][0].toLowerCase();
	var pc=lastchars[1][0].toLowerCase();
	var ppc=lastchars[2][0].toLowerCase();
	if(i==2&&type!=6){
		var tmp=pc+c;
		if((tmp!="ng")&&(tmp!="ch")&&(tmp!="nh"))return null;
		if(tmp=="ch"&&type!=1&&type!=3)return null;
	}else if(i==1&&type!=6){
		if((c>='v')||("bdfghjklqrs".indexOf(c)>=0))return null;
		else if("cpt".indexOf(c)>=0&&type!=1&&type!=3)return null; 
	}else if(this.charmap.isVowel(lastchars[1][0],0)&&("uyoia".indexOf(c)>=0)){
		if(!(((pc=='o')&&(c=='a'))||((pc=='u')&&(c=='y')))&&!(((ppc=='q')&&(pc=='u'))||((ppc=='g')&&(pc=='i'))))++i;
	}
	var pos=this.value.length;
	for(var j=0;j<=i;j++)pos-=lastchars[j][1];
	return [lastchars[i][0],pos,lastchars[i][1]];
}
function CVietCharMap(){
	this.vietchars=null;
	this.length=149;
	return this;
}
CVietCharMap.prototype.charAt=function(ind){
	var chrcode=this.vietchars[ind];
	return chrcode?String.fromCharCode(chrcode):null;
}
CVietCharMap.prototype.isVowel=function(chr,isnumber){
	var c=isnumber?String.fromcharCode(chr):chr;
	var ind=this.length-5;
	while((c!=this.charAt(ind))&&(ind>0))--ind;
	return ind;
}
CVietCharMap.prototype.getDau=function(vchr,type){
	if(vchr=='\\')return(type==3)?[1,'.',1]:(type==4)?[1,'?',1]:[0];
	var ind=this.isVowel(vchr);
	if(!ind)return[0];
	var accented=(ind<25)?0:1;
	var ind_i=(ind-1)%24+1;
	var charset=(type==6)?0:type;
	if((type==6)&&!accented)return [0];
	if(accented&(charset*24+ind_i==ind))charset=0;
	return [1,this.charAt(charset*24+ind_i),charset];
}
CVietCharMap.prototype.getAEOWD=function(vchr,type){
	var ind=1,len=this.length;
	if(type==15)while(this.charAt(len-ind)!=vchr){if(++ind>4)return [0];}
	else while((ind<25)&&(vchr!=this.charAt(ind))){ind++;}
	if(ind>=25)return [0];
	var map=[[7,7,7,8,8,8,9,10,11,15],[0,3,6,0,6,9,0,3,6,0],[1,4,7,2,8,10,1,4,7,1]];
	var vc=(type==15)?(ind-1)%2:(ind-1)%12;
	var i=-1,shift=0;
	while(shift==0&&++i<10){
		if(map[0][i]==type)if(map[1][i]==vc)shift=map[2][i]-vc;
		else if(map[2][i]==vc)shift=map[1][i]-vc;
	}
	if(shift==0)return [0];
	if(type==15){ind=len-(ind+shift);shift=-shift;}else ind+=shift;
	return [1,this.charAt(ind),(shift>0)];
}
CVietCharMap.prototype.lastCharsOf=function(str,num){
	if(!num)return [str.charAt(str.length-1),1];
	var vchars=new Array(num);
	for(var i=0;i<num;i++)vchars[i]=[str.charAt(str.length-i-1),1];
	return vchars;
}
String.prototype.replaceAt=function(i,newchr,clen){
	return this.substring(0,i)+newchr+this.substring(i+clen);
}

function CVietUniCodeMap(){var map=new CVietCharMap();
map.vietchars=new Array(
"UNICODE",
97,226,259,101,234,105,111,244,417,117,432,121,
65,194,258,69,202,73,79,212,416,85,431,89,
225,7845,7855,233,7871,237,243,7889,7899,250,7913,253,
193,7844,7854,201,7870,205,211,7888,7898,218,7912,221,
224,7847,7857,232,7873,236,242,7891,7901,249,7915,7923,
192,7846,7856,200,7872,204,210,7890,7900,217,7914,7922,
7841,7853,7863,7865,7879,7883,7885,7897,7907,7909,7921,7925,
7840,7852,7862,7864,7878,7882,7884,7896,7906,7908,7920,7924,
7843,7849,7859,7867,7875,7881,7887,7893,7903,7911,7917,7927,
7842,7848,7858,7866,7874,7880,7886,7892,7902,7910,7916,7926,
227,7851,7861,7869,7877,297,245,7895,7905,361,7919,7929,
195,7850,7860,7868,7876,296,213,7894,7904,360,7918,7928,
100,273,68,272);
return map;
}
function CTelexKeys(){
	var k=new CVietKeys();
	k.keys="sfjrxzaeowd";
	k.actions=[1,2,3,4,5,6,9,10,11,8,15];
	k.istelex=true;
	return k;
}
function CVniKeys(){
	var k=new CVietKeys();
	k.keys="0123456789";
	k.actions= [6,1,2,4,5,3,7,8,8,15];
	return k;
}
function CVietKeys(){
	this.getAction=function(typer){
		var ctrl=typer.ctrlchar.toLowerCase();
		var i=this.keys.indexOf(ctrl);
		if(i<0)return;
		var a=this.actions[i];
		if(a<=6)typer.Dau(a);else typer.AEOWD(a);
	}
	return this;
}
