/*vietuni.js - V.1.618 - R.11.11.01 @QDJTGSLLA@P*Veni*Vidi*Vici*
* by Tran Anh Tuan [tuan@physik.hu-berlin.de]
* Copyright (c) 2001,2002 AVYS e.V.. All Rights Reserved.
*
* Originally published and documented at http://www.avys.de/
* You may use this code without fee on noncommercial web sites.
* You may NOT alter the code and then call it another name and/or resell it.
* The copyright notice must remain intact on srcipts.
*/

// interface for HTML:
//


var supported = (document.all || document.getElementById);
var disabled = false;
var charmapid = 1;
var keymodeid = 0;
var linebreak = 0;
var theTyper = null;

reset = function(){}
initTyper = telexingVietUC;

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();
case 3:return new CViqrKeys();
case 4:return new CAllKeys();
default:return new CVKOff();
}
}

function telexingVietUC(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;
txtarea.getValue= function(){ return this.value}
txtarea.setValue= function(txt){ this.value = txt}
if(!theTyper) theTyper = new CVietString("");
}

function getEvt(evt,external){
if (external) return external.event.keyCode;
if (typeof(evt)=='string') return evt.charCodeAt(0);
return document.all? event.keyCode:(evt && evt.which)? evt.which:0;
}

function onKeyDown(evt){
var c= getEvt(evt,this.win);
//***********************
if(this.id == "SP1234") 
{
if ((c==10) || (c==13)){return AdvSearch()}
}
//***********************
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= getEvt(evt,this.win);
theTyper.value= 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();
if (caret.text) return null;
var backward= -10;
do{
var caret2= caret.duplicate();
caret2.moveStart("character",backward);
outside= /[\x01-\x40]([^\x01-\x40]+)$/.exec(caret2.text);
if (outside) backward = -outside[1].length;
} while (outside && 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);
}
// end interface


// "class":CVietString
//
function CVietString(str){
this.value= str;
this.keymode= initKeys();
this.charmap= initCharMap();
this.ctrlchar= '-';
this.changed= 0;

this.typing= typing;
this.Compose= Compose;
this.Correct= Correct;
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);
this.Correct();
return this.changed;
}

function Compose(type){
if(!this.value) return;
var info= this.findCharToChange(type);
if (!info || !info[0]) return;
var telex;
if (info[0]=='\\') telex= [1,this.ctrlchar,1];
else if (type>6) telex= this.charmap.getAEOWD(info[0],type,info[3]);
else 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 Correct(){
if (this.charmap.maxchrlen || !document.all) return 0;
var tmp= this.value;
if ('nNcC'.indexOf(this.ctrlchar)>=0) tmp+= this.ctrlchar;
var er= /[^\x01-\x7f](hn|hc|gn)$/i.exec(tmp);
if (er){
this.value= tmp.substring(0,tmp.length-2)+er[1].charAt(1)+er[1].charAt(0);
this.changed= 1;
}
else if(!this.changed) return 0;
er= /\w([^\x01-\x7f])(\w*)([^\x01-\x7f])\S*$/.exec(this.value);
if (!er) return 0;
var i= this.charmap.isVowel(er[1]);
var ri= (i-1)%24 + 1,ci= (i-ri)/24;
var i2= this.charmap.isVowel(er[3]);
if (!ci || !i2) return 0;
var ri2= (i2-1)%24 + 1,ci2= (i2-ri2)/24;
var nc= this.charmap.charAt(ri)+ er[2]+ this.charmap.charAt(ci*24+ri2);
this.value= this.value.replace(new RegExp(er[1]+er[2]+er[3],'g'),nc);
}

function findCharToChange(type){
var lastchars= this.charmap.lastCharsOf(this.value,5);
var i= 0,c=lastchars[0][0],chr=0;
if (c=='\\') return [c,this.value.length-1,1];
if (type==15) while (!(chr=this.charmap.isVD(c))){
if ((c < 'A') || (i>=4) || !(c=lastchars[++i][0])) return null;
}
else while( "cghmnptCGHMNPT".indexOf(c)>=0){
if ((c < 'A') || (i>=2) || !(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==0 && type!=15){
if ( (chr=this.charmap.isVowel(lastchars[1][0]))
&& ("uyoia".indexOf(c)>=0) && !this.charmap.isUO(pc,c)
&& !((pc=='o' && c=='a') || (pc=='u' && c=='y'))
&& !((ppc=='q' && pc=='u') || (ppc=='g' && pc=='i')) ) ++i;
if (c=='a' && (type==9 || type==7)) i= 0;
}
c= lastchars[i][0];
if ((i==0 || chr==0) && type!=15) chr= this.charmap.isVowel(c);
if (!chr) return null;
var clen= lastchars[i][1],isuo=0;
if ((i>0) && (type==7 || type==8 || type==11)){
isuo=this.charmap.isUO(lastchars[i+1][0],c);
if (isuo){ chr=isuo;clen+=lastchars[++i][1];isuo=1}
}
var pos= this.value.length;
for (var j=0;j<= i;j++) pos -= lastchars[j][1];
return [chr,pos,clen,isuo];
}
// end CVietString


// character-map template
//
function CVietCharMap(){
this.vietchars = null;
this.length = 149;
this.chr_cache = new Array(20);
this.ind_cache = new Array(20);
this.cptr = 0;
this.caching= function(chr,ind){
this.chr_cache[this.cptr] = chr;
this.ind_cache[this.cptr++] = ind;
this.cptr %= 20;
}
return this;
}

CVietCharMap.prototype.charAt= function(ind){
var chrcode= this.vietchars[ind];
return chrcode ? String.fromCharCode(chrcode):null;
}

CVietCharMap.prototype.isVowel= function(chr){
var i= 0;
while ((i<20) && (chr != this.chr_cache[i])) ++i;
if (i<20) return this.ind_cache[i];

i = this.length-5;
while ((chr != this.charAt(i)) && i) --i;
this.caching(chr,i);
return i;
}

CVietCharMap.prototype.isVD= function (chr){
var ind= this.length-5;
while ((chr != this.charAt(ind)) && (ind < this.length)) ++ind;
return (ind<this.length)? ind:0;
}

CVietCharMap.prototype.isUO= function (c1,c2){
if (!c1 || !c2) return 0;
var ind1 = this.isVowel(c1);
var ci = (ind1-1)%12;
if ((ci!=9) && (ci!=10)) return 0;
var ind2 = this.isVowel(c2);
ci = (ind2-1)%12;
if ((ci!=6) && (ci!=7) && (ci!=8)) return 0;
return [ind1,ind2];
}

CVietCharMap.prototype.getDau= function (ind,type){
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];
var newind= charset*24 + ind_i;
if (newind == ind) newind= ind_i;
var chr= this.charAt(newind);
if (!chr) chr= this.lowerCaseOf(0,newind);
return [1,chr,newind>24 || type==6];
}

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]
];
CVietCharMap.prototype.getAEOWD= function(ind,type,isuo){
var c=0,i1=isuo? ind[0]:ind;
var vc1= (type==15)? (i1-1)%2:(i1-1)%12;
if (isuo){
var base= ind[1]-(ind[1]-1)%12;
if (type==7 || type==11) c= this.charAt(i1-vc1+9)+this.charAt(base+7);
else if (type==8) c= this.charAt(i1-vc1+10)+this.charAt(base+8);
return [c!=0,c,1];
}
var i= -1,shift= 0,del= 0;
while (shift==0 && ++i<map[0].length){
if (map[0][i]==type){
if(map[1][i]==vc1) shift= map[2][i]-vc1;
else if(map[2][i]==vc1) shift= map[1][i]-vc1;
}
}
if (shift==0){
if (type==7 && (vc1==2 || vc1==8)) shift=-1;
else if ((type==9 && vc1==2) || (type==11 && vc1==8)) shift=-1;
else if (type==8 && (vc1==1 || vc1==7)) shift=1;
del= 1;
} else del=(shift>0);
i1 += shift;
var chr= this.charAt(i1);
if (i1<145) this.caching(chr,i1);
if (!chr) chr= this.lowerCaseOf(0,i1);
return [shift!=0,chr,del];
}

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;
}
// end CVietCharMap prototype


String.prototype.replaceAt= function(i,newchr,clen){
return this.substring(0,i)+ newchr + this.substring(i+clen);
}

// output map:class CVietUniCodeMap
//
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;
}

// input methods:class C...Keys
function CVietKeys(){
this.getAction= function(typer){
var i= this.keys.indexOf(typer.ctrlchar.toLowerCase());
if(i>=0) typer.Compose(this.actions[i]);
}
return this;
}

function CVKOff(){
this.off = true;
this.getAction= function(){};
return this;
}

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 CViqrKeys(){
var k= new CVietKeys();
k.keys= "\xB4/'\u2019`.?~-^(*+d";
k.actions= [1,1,1,1,2,3,4,5,6,7,8,8,8,15];
return k;
}

function CAllKeys(){
var k= new CVietKeys();
k.keys= "sfjrxzaeowd0123456789\xB4/'`.?~-^(*+d";
k.actions= [1,2,3,4,5,6,9,10,11,8,15,6,1,2,4,5,3,7,8,8,15,1,1,1,2,3,4,5,6,7,8,8,8,15];
k.istelex= true;
return k;
}

// end vietuni.js

function createCookie(name,value,days){
if (days){
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = ";expires="+date.toGMTString();
}
else var expires = "";
document.cookie = name+"="+value+expires+";path=/";
}

function readCookie(name){
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++){
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}

function eraseCookie(name){
createCookie(name,"",-1);
}/*
Copyright 2005,4word systems
All rights reserved.

This software may not be reproduced or distributed in any form without the express 
written consent of 4word systems or it's designee.

Revision 1.1:20050729 Added underscore to list of valid characters
*/


function isValidEmail(email,required){
if (required==undefined){ // if not specified,assume it's required
required=true;
}
if (email==null){
if (required){
return false;
}
return true;
}
if (email.length==0){
if (required){
return false;
}
return true;
}
if (! allValidChars(email)){// check to make sure all characters are valid
return false;
}
if (email.indexOf("@") < 1){ //must contain @,and it must not be the first character
return false;
} else if (email.lastIndexOf(".") <= email.indexOf("@")){// last dot must be after the @
return false;
} else if (email.indexOf("@") == email.length){// @ must not be the last character
return false;
} else if (email.indexOf("..") >=0){ // two periods in a row is not valid
return false;
} else if (email.indexOf(".") == email.length){// . must not be the last character
return false;
}
return true;
}

function allValidChars(email){
var parsed = true;
var validchars = "abcdefghijklmnopqrstuvwxyz0123456789@.-_";
for (var i=0;i < email.length;i++){
var letter = email.charAt(i).toLowerCase();
if (validchars.indexOf(letter) != -1)
continue;
parsed = false;
break;
}
return parsed;
}
