// Licensed Materials - Property of IBM
//
// 5724-D34   (Product: IBM HATS)
//
// (C) Copyright IBM Corp. 2002  All Rights Reserved


var SCREENORIENT = "Screen Orientation: ";
var TYPINGORIENT = "  Typing Orientation: ";
var AUTOPUSH = "  Autopush: ";
enableBIDI="true";
var AUTOFLDREV = "  AutoFldRev: ";
var autoFldrev = false;
var isFldreversed = false;
var isSession5250 = false;
var maxFieldLen;
var mouseIn = 2; 
var curPos = 1;
var selectionStart;
var autoPush = false;
var pushMode = false;
var mousePressed = false;
var rightPushBound = 0; 
var leftPushBound = 0;
var codePage = 37;
var layerGuess = false;
var swapChar = 0;
var hadnoFocus = true;
var isChkRTB = false;
var preventAltNumpad = false;

function TabIndexVIF() {
    hadnoFocus = false;

	var len =  hatsForm.elements.length;
	var curoffsetTop = -1;
	TA = new Array();
	var lineIndex = 0;
	for  ( var j = 0; j <= len-1; j++) { 
 		elementNext = hatsForm.elements[j];
		if (elementNext.tagName == "TEXTAREA") {
    		if ( (( elementNext.offsetTop - curoffsetTop)  > elementNext.offsetHeight) || ( curoffsetTop == -1) )  {
    			lineIndex++;
    			TA[lineIndex] = 1;
    			curoffsetTop = elementNext.offsetTop;
    		}			
    		else {
    			TA[lineIndex]++;	
    		}
		} 
		else 
            elementNext.tabIndex = 999;
	}

	lineIndex = 0;
	controlsOnLine = 0;
	previousTabIndex=0;
	for  ( var j = 0; j <= len-1; j++) {	
 		elementNext = hatsForm.elements[j];
		if (elementNext.tagName == "TEXTAREA") {
			if ( controlsOnLine == 0) {
			  	lineIndex++;
				controlsOnLine = TA[lineIndex];
			}
			elementNext.tabIndex = controlsOnLine + previousTabIndex; 		
			controlsOnLine--;
			if ( controlsOnLine == 0) previousTabIndex += TA[lineIndex];
		}	
	}
}		
 
document.body.oncopy = function(){ 
	var elementWithReordering = false;
	var reorderingRtl = false;
	
	if(((event.srcElement).outerHTML).indexOf("BDO dir=rtl") >= 0){
		elementWithReordering = true;
		reorderingRtl = true;		
	}
	else if(((event.srcElement).outerHTML).indexOf("BDO dir=ltr") >= 0){
		elementWithReordering = true;
		reorderingRtl = false;		
	}
	else if((event.srcElement).className == "CLASSTT"){
		var len =  document.styleSheets.length;        
		for  (var j = 0; j < len; j++){ 
	        elementNext = document.styleSheets[j];
	        if((elementNext.cssText).indexOf(".CLASSTT") >= 0){
				elementWithReordering = true;
				reorderingRtl = ((elementNext.cssText).indexOf("DIRECTION: rtl") >= 0);				
				break;	
	        }
		}		
	}
	
	if(elementWithReordering){
		window.event.returnValue = false;
	    var range = document.selection.createRange();
		var jr = new JSReorder();
		var text = range.text;
		var textToClipboard = "";
	
		if(reorderingRtl){
			var length = text.length;
			for(i = 0;i < length ;i++) {
				symbol = text.charAt(length - i - 1);
				symbol = doSymSwap(symbol);
				textToClipboard += symbol;
			}
						
			textToClipboard = jr.doReorder(textToClipboard);				
		}
		else	
			textToClipboard = jr.doReorder(text);

		window.clipboardData.setData("Text", textToClipboard);

	}
}

function reverseBeforeSubmit(hatsForm,intCommand){
	var temp,len,text;
	var isScreeRev = (intCommand == "reverse") ? true : false; 

    if(codePage == 420){
        if(hatsForm.LAYERGUESS != null)
            hatsForm.LAYERGUESS.value = (layerGuess) ? "true" : "false";
    }
	
   for  (var j = 0; j < hatsForm.elements.length; j++) {
	elementNext = hatsForm.elements[j];

	if(elementNext.tagName == "TEXTAREA") {									
		if(isScreeRev && ((elementNext.alt).indexOf("dirty") < 0)) {
			elementNext.disabled = true;
		}
		else {
			if((elementNext.alt).indexOf("dirty") >= 0)
				elementNext.disabled = false;

			if((elementNext.style.direction == "rtl") ^ (hatsForm.dir == "rtl")) {
				var text = elementNext.value;
				elementNext.value = "";
				for(i = text.length - 1;i >= 0;i--){
					symbol = text.charAt(i);
					if((codePage == 420) && isScreeRev)
						symbol = doSymSwap(symbol);
											
					elementNext.value += symbol;
				}
			}

			if((elementNext.style.textAlign == "right") ^ (hatsForm.dir == "rtl")) {
				if(elementNext.cols > (elementNext.value).length ){
					var len = elementNext.cols - (elementNext.value).length;
					var pad = "";
					for(i = 0;i < len;i++)
						pad += ' ';

					elementNext.value = pad + elementNext.value;
				}
			}

			if(elementNext.style.direction == "rtl") {
				var text = elementNext.value;
				elementNext.value = "";								
				for(i = 0;i < text.length;i++) {
					symbol = text.charAt(i);
					if(codePage != 420)
						symbol = doSymSwap(symbol);
						
					elementNext.value += symbol;
				}
			}
		}					
	}
    else if(elementNext.type == "password") {
		if ((elementNext.alt == "true") ||
            (((elementNext.alt).indexOf("num") >= 0) && (hatsForm.dir == "rtl")) )
		{
            var text = elementNext.value;
            elementNext.value = "";	
            for(i = text.length - 1;i >= 0;i--)
                elementNext.value += text.charAt(i);	
		}
    }
  }
}
 
function initVIF(codepage,ischkRTB,is5250) {
	codePage = codepage;
    isChkRTB = ischkRTB;
    if(!(document.all))
        alert("Emulation of Arabic/Hebrew host sessions works correctly only on Microsoft Explorer browser");

	if(codePage == 420){			
		if((document.all.lamalef != null) && (hatsForm.ARABICORIENTATION.value == "rtl"))
			document.all.lamalef.checked = true;
						
		if((hatsForm.LAYERGUESS != null) && (hatsForm.LAYERGUESS.value == "true"))
			layerGuess = true;				
	}
	
	for  (var j = 0; j < hatsForm.elements.length; j++) {
		elementNext = hatsForm.elements[j];

		if(((elementNext.tagName == "TEXTAREA") || (elementNext.type == "password")) && (elementNext.alt == null))
			elementNext.alt = "";	
	}
		
	isSession5250 = is5250;
	if(!is5250) {
		if (hatsForm.dir == "rtl"){
			processPasswordNumeric();
			if((hatsForm.AUTOPUSH.value).indexOf("autoreverse=off") >= 0) { 
				autoFldrev = false;
				processNumeric();
			}
			else
                autoFldrev = true;
		}			
		else {
			if((hatsForm.AUTOPUSH.value).indexOf("autoreverse=on") >= 0) {		 
				autoFldrev = true;
				processAutoFieldReverse(null);
			}
		}
	}

    if(((hatsForm.AUTOPUSH.value).indexOf("autopush") < 0) && is5250)
		autoPush = true;
    else
        autoPush = ((hatsForm.AUTOPUSH.value).indexOf("autopush=on") >= 0) ? true : false; 
}

function showStatusBar(obj) {
	temp_string = TYPINGORIENT;
	if(obj)
		temp_string += (obj.style.direction == "rtl") ? "<=" : "=>";

        temp_string += AUTOPUSH;
        temp_string += (autoPush) ? "on" : "off";

	if(!isSession5250){
		temp_string += AUTOFLDREV;	
		temp_string += (autoFldrev) ? "on" : "off";
	}
	if(codePage == 420){
	    temp_string += "  Numerals:";
	    temp_string += (layerGuess) ? " A" : " E";
	}
	
	statusBIDI = SCREENORIENT + ((hatsForm.dir == "rtl") ? "<=" : "=>") + temp_string;
	fieldType = ((obj.alt).indexOf("num") >= 0) ? " Num:   " : " Alpha: ";
	statusBIDI= fieldType + statusBIDI;
	window.status = statusE + statusBIDI;
}

function processCopy(){
	var range = document.selection.createRange();
	var jr = new JSReorder();
	var text = range.text;
	var textToClipboard = "";
	
	if((event.srcElement).style.direction == "rtl"){
		var len = text.length;
		for(i = 0;i < len;i++) { 
			symbol = text.charAt(len - i - 1);
			symbol = doSymSwap(symbol);
			textToClipboard += symbol;
		}
			
		textToClipboard = jr.doReorder(textToClipboard);				
	}
	else	
		textToClipboard = jr.doReorder(text);

	window.clipboardData.setData("Text", textToClipboard);
}

function copyText() {
	window.event.returnValue = false;
	processCopy(); 
}

function cutText() {
	if(pushMode) 
		leftPushBound -= Math.abs(selectionStart - curPos);
				
	curPos = Math.min(selectionStart,curPos);
	selectionStart = curPos;
	processCopy(); 

	if(((event.srcElement).alt).indexOf("dirty") < 0) 
		(event.srcElement).alt = (event.srcElement).alt + "dirty";
}

function pasteText() {
	window.event.returnValue = false;
	var range = document.selection.createRange();
	var clipboardText;
	var textToPaste = "";
	var jr = new JSReorder();
	clipboardText = window.clipboardData.getData("Text");
	var clipboardTextLen = clipboardText.length;
	var fieldText = (event.srcElement).innerText; 
	
	if((clipboardTextLen + fieldText.length - (range.text).length) >= maxFieldLen){
		clipboardText = clipboardText.substring(0,maxFieldLen - fieldText.length + (range.text).length);
		clipboardTextLen = clipboardText.length;
	}
		
	if((event.srcElement).style.direction == "rtl"){
	
		for(i = 0;i < clipboardTextLen;i++){
			symbol = clipboardText.charAt(clipboardTextLen - i - 1);
			symbol = doSymSwap(symbol);
			textToPaste += symbol;
		}
			
		textToPaste = jr.doReorder(textToPaste);									
	}
	else
		textToPaste = jr.doReorder(clipboardText);	
	
	range.text = textToPaste;
	
	if(pushMode)
		leftPushBound += clipboardTextLen - Math.abs(selectionStart - curPos);
		
	curPos = Math.min(selectionStart,curPos);
	selectionStart = curPos = curPos + clipboardTextLen;

	if(((event.srcElement).alt).indexOf("dirty") < 0) 
		(event.srcElement).alt = (event.srcElement).alt + "dirty";
}

function mouseDblClick(){
	selectionStart = ((event.srcElement).innerText).length;
	curPos = 0;
	mouseIn = 1; 
}

function mouseDown(obj){
	if(event.button == 2) {
		delta = document.body.clientWidth - obj.offsetLeft - obj.offsetWidth;
		document.all.hint.style.left = delta<0 ? obj.offsetLeft:obj.offsetLeft + obj.offsetWidth;
		document.all.hint.style.top = obj.offsetTop;		
		document.all.hint.style.visibility = "visible";
		return;
	}
	var text = obj.innerText;
	var len = text.length;
	var rightAlign = (obj.style.textAlign == "right");
	var mousePos = (rightAlign) ? obj.offsetWidth - window.event.x : window.event.x;

	mousePressed = true;
	
	var rng = document.body.createTextRange();
	rng.moveToElementText(obj);
	selectionStart = 0;
	
	rng.move("character",0);
 	while(selectionStart <= len) {		
		rng.moveEnd("character",1);
		if(rng.boundingWidth > mousePos)
			 break;
		selectionStart += 1;
	}
	if(rightAlign)
		selectionStart = len - selectionStart;
	
	if(obj.style.direction == "rtl")
		selectionStart = len - selectionStart;
		
	mouseIn = 1;		
}

function mouseUp(obj) {
	var text = obj.innerText;
	var len = text.length;
	var rightAlign = (obj.style.textAlign == "right"); 
	var mousePos = (rightAlign) ? obj.offsetWidth - window.event.x : window.event.x;

	document.all.hint.style.visibility = "hidden";

	mousePressed = false;

	var rng = document.body.createTextRange();
	rng.moveToElementText(obj);
	curPos = 0;

	rng.move("character",0);
	while(curPos <= len) {	
		rng.moveEnd("character",1);
		if(rng.boundingWidth > mousePos)
			 break;
		curPos += 1;
	}
	
	if(rightAlign)
		curPos = len - curPos;
	
	if(obj.style.direction == "rtl")
		curPos = len - curPos;
	
	if(pushMode & ((curPos > leftPushBound)|(curPos < rightPushBound)))
		toggleFieldOrient(true,false);			
}

function killFocus() {
	if(pushMode)
		toggleFieldOrient(false,false);
	
	pushMode = false;
	
	if (isFldreversed) 
		processFieldReverse(event.srcElement,false);				
}

function setFocus(obj,portlet_ID) {
	var text = obj.innerText;

	if(mouseIn != 1) { 
		selectionStart = curPos = 0;
		var rng = document.body.createTextRange();
		rng.moveToElementText(obj);
		rng.move("character",curPos);
		rng.select();
	}

	mouseIn = 0; 

	if(text.length == 0)
		obj.style.textAlign = (obj.style.direction == "ltr") ? "left" : "right";

	maxFieldLen = obj.cols;
	
	setFocusFieldIntoGlobal(obj,portlet_ID); //from lxgwfunctions.js

	showStatusBar(obj); 

	if (isChkRTB & hadnoFocus)
        TabIndexVIF();
}

function setFocusInput(obj,portlet_ID) {
	maxFieldLen = obj.cols;
	showStatusBar(obj); 
	
	setFocusFieldIntoGlobal(obj,portlet_ID); //from lxgwfunctions.js

	if (isChkRTB & hadnoFocus)
        TabIndexVIF();
}

function keyDownInput(obj) {
	var ieKey = event.keyCode;		
	if(window.event.shiftKey){
		if(window.event.altKey){ 
			layerGuess = !layerGuess;
            if(codePage==420) showStatusBar(obj); 
		}
	}	
}

function keyPressInput(obj) {
	var ieKey=event.keyCode;	
	if((ieKey > 47) & (ieKey < 58)){//Arabic, transform into Hindi			
		if((codePage == 420) & layerGuess) 
			ieKey = event.keyCode = ieKey + 1584;
	}
}

function mouseEnter() {
}

function mouseLeave() {
	document.all.hint.style.visibility = "hidden"; 
	
	if(mousePressed){
		obj = event.srcElement;
		if(event.x < 0)
			curPos = 0;
		else if(event.x > obj.offsetWidth)
			curPos = (obj.innerText).length;
			
		if(obj.style.direction == "rtl")
			curPos = (obj.innerText).length - curPos;			
	}
}

function swapBrackets(fieldDirection,swapped) {
	if(fieldDirection){
		if(swapChar == 219){
			if (codePage == 420)
				swapped = 62;
			else
				swapped = (window.event.shiftKey) ? 125 : 93;
		}
		else if(swapChar == 221){
			if (codePage == 420)
				swapped = 60;
			else
				swapped = (window.event.shiftKey) ? 123 : 91;
		}
		else if(swapChar == 48)
			swapped = 40;
		else if(swapChar == 57)
			swapped = 41;
		else if(swapChar == 188)
			swapped = 62;
		else if(swapChar == 190)
			swapped = 60;	
	}
	else {
		if(swapChar == 219){
			if (codePage == 420)
				swapped = 60;
			else
				swapped =  (window.event.shiftKey) ? 123 : 91;
		}
		else if(swapChar == 221) {
			if (codePage == 420)
				swapped = 62;
			else		
				swapped =  (window.event.shiftKey) ? 125 : 93;
		}
		else if(swapChar == 48)
			swapped = 41;
		else if(swapChar == 57)
			swapped = 40;
		else if(swapChar == 188)
			swapped = 60;
		else if(swapChar == 190)
			swapped = 62;	
	}
	swapChar = 0;
	return swapped;
}

function keyPress(obj) {
		if(event.returnValue == false) 
			return;

		if(preventAltNumpad){//prevent alt-numpad combinations
			event.returnValue = false;
			return;
		}

		curPos = Math.min(selectionStart,curPos) + 1;
		selectionStart = curPos;
		
		if(pushMode)
			leftPushBound += 1;

		charClass = fieldDirection = (obj.style.direction == "rtl");
		
		event.keyCode = swapBrackets(fieldDirection,event.keyCode);

		var ieKey=event.keyCode;
		
		if((ieKey > 47) & (ieKey < 58)){//Arabic, transform into Hindi			
			if((codePage == 420) & layerGuess) //d25618
				ieKey = event.keyCode = ieKey + 1584;
		}

		if(autoPush) {	
			if(((ieKey > 64) & (ieKey < 91)) || ((ieKey > 96) & (ieKey < 123)))
				layerGuess = charClass = false;  //English
			else if(ieKey > 1487)
				layerGuess = charClass = true;
			
			if(fieldDirection & ((ieKey > 47) & (ieKey < 58)) ) {
				if(!layerGuess | (obj.style.textAlign == "right"))		
					charClass = false;  //English (Numerals)					
			}
		
			if(fieldDirection != charClass){ //enter/leave push mode
				curPos = curPos - 1;
			 	toggleFieldOrient(true,curPos == leftPushBound);
			 	selectionStart = curPos = curPos + 1;
			}
		}
}

function keyUp(obj) {
	var ieKey = event.keyCode;
	var text = obj.innerText;	
	fieldDirection = (obj.style.direction == "ltr") ? 0 : 1;
	
	if (((ieKey == 37) & (fieldDirection == 0))|((ieKey == 39) & (fieldDirection == 1))) { // Left Arrow
		if(pushMode & (curPos < rightPushBound))
			toggleFieldOrient(true,false);	
	}
	else if (((ieKey == 39) & (fieldDirection == 0))|((ieKey == 37) & (fieldDirection == 1))) { // Right Arrow
		if(pushMode & (curPos > leftPushBound))
			toggleFieldOrient(true,false);
	}
	else if (ieKey == CODE_HOME) {
		processHome(obj);
	}
	else if (ieKey == CODE_END) {
		processEnd(obj);
	}
}

function keyDown(obj) {
	var ieKey = event.keyCode;
	var text = obj.innerText;
	
	if(ieKey == 18) //alt
		preventAltNumpad = true;	
	else if(!window.event.altKey)	
		preventAltNumpad = false;
	
	fieldDirection = (obj.style.direction == "ltr") ? 0 : 1;
	

	if(window.event.shiftKey && (ieKey == 48 || ieKey == 57))
		swapChar = ieKey;
	else if((ieKey == 219)||(ieKey == 221)) {
		if(codePage == 420) {
			if(window.event.shiftKey && layerGuess)
				swapChar = ieKey;					
		}
		else 	
			swapChar = ieKey;					
	}
	else if(window.event.shiftKey && (ieKey == 188 || ieKey == 190)) {		
		swapChar = (codePage == 420) ? 0 : ieKey;					
	}
				
	if(window.event.shiftKey){
		if(window.event.altKey){	
			layerGuess = !layerGuess;
			if(codePage==420) showStatusBar(obj);
		}
			
		processPush(ieKey);
	}
	if(window.event.altKey){ 
		if(ieKey == 111) {  //Toggle Autopush
			autoPush = !autoPush;
			autoreverse_value = (autoFldrev) ? "autoreverse=on" : "autoreverse=off";
 			hatsForm.AUTOPUSH.value = autoreverse_value + ((autoPush) ? "autopush=on" : "autopush=off");
			showStatusBar(obj);
		}
		else if(ieKey == 144) {  //Field reverse 
			processFieldReverse(obj,true);						
		}
		else if(((ieKey == 12) || (ieKey == 101)) & !isSession5250) {  //Toggle Auto field reverse 			
			autoFldrev = !autoFldrev;
				autopush_value = (autoPush) ? "autopush=on" : "autopush=off"; 
 				hatsForm.AUTOPUSH.value = ((autoFldrev) ? "autoreverse=on" : "autoreverse=off") + autopush_value;

			if(hatsForm.dir != "rtl")
				processAutoFieldReverse(obj);
			else {
				processNumeric();
				processPasswordNumeric();
			}

			showStatusBar(obj);							
			}
	}
	else if(((ieKey == 32)|(ieKey > 47)) & !window.event.altKey & !window.event.ctrlKey){ //regular character
		if(window.event.shiftKey & ((ieKey == 111) | (ieKey == 144))) //push on/off
				return;	
				
		if(ieKey == 144)
				return;	

		if(isOverWriteMode()==false) {
			if (text.length >= maxFieldLen) {
				event.returnValue = false;
				return;
			}
		}
		else {
			if (curPos >= maxFieldLen) {
				event.returnValue = false;
				return;
			}		
		}
			
		if((obj.alt).indexOf("dirty") < 0)
			obj.alt = obj.alt + "dirty";						
	}	
	else if(window.event.ctrlKey & (ieKey == CODE_A)) { //Ctrl+a - select all
		mouseDblClick();
	}	
	else if(ieKey == CODE_ENTER){ //enter
		if(hatsForm.KeyboardToggle.value == "0"){//bd3a
			event.returnValue = false;
			return;
		}		
		if(pushMode)
			toggleFieldOrient(false,false);
	}
	else if (ieKey == CODE_BACKSPACE) {
		processBackspace(obj);
	}
	else if (ieKey == CODE_DELETE) {	
		processDelete(obj);
	}
	else if ((ieKey == CODE_HOME)|(ieKey == CODE_END)) {
			event.returnValue = false; //disable, process it in KeyUp
	}
	else if (((ieKey == 37) & (fieldDirection == 0))|((ieKey == 39) & (fieldDirection == 1))) { // Left Arrow
		processLeftarrow(obj);
	}
	else if (((ieKey == 39) & (fieldDirection == 0))|((ieKey == 37) & (fieldDirection == 1))) { // Right Arrow
		processRightarrow(obj);
	}
	else if (ieKey == 33 || ieKey == 34 || ieKey == 38 || ieKey == 40) { //disable arrow and page up/down
		event.returnValue = false;
	}
	
}

function doSymSwap(symbol){
	switch(symbol)
	{
		case "(":
			symbol = ")";
			break;
		case ")":
			symbol = "(";
			break;
		case "{":
			symbol = "}";
			break;
		case "}":
			symbol = "{";
			break;
		case "[":
			symbol = "]";
			break;
		case "]":
			symbol = "[";
			break;					
		case "<": 
			symbol = ">";
			break;
		case ">":
			symbol = "<";
			break;								
	}
	return symbol;
}

function processHome(obj){
		if(pushMode)
			selectionStart = curPos = (obj.innerText).length;			
		else		
			selectionStart = curPos = 0;
						
		var rng = document.body.createTextRange();
		rng.moveToElementText(obj);
		rng.move("character",curPos);
		rng.select();

		if(pushMode & (curPos < rightPushBound))
			toggleFieldOrient(true,false);	
}

function processEnd(obj){
		if(pushMode)
			selectionStart = curPos = 0;
		else
			selectionStart = curPos =(obj.innerText).length;
			
		var rng = document.body.createTextRange();
		rng.moveToElementText(obj);
		rng.move("character",curPos);
		rng.select();			

		if(pushMode & (curPos > leftPushBound))
			toggleFieldOrient(true,false);
}

function toggleFieldOrient(setCursor,jumpFromPushSegment) {
		var obj = event.srcElement;
		
		obj.style.direction = (obj.style.direction == "rtl") ? "ltr" : "rtl";
		reverseText(obj); 
				
		if(setCursor) {
			var rng = document.body.createTextRange();	
			pushMode = !pushMode;		
					
			if(pushMode)
				leftPushBound = rightPushBound = selectionStart = curPos = len - curPos;
			else {
				if(jumpFromPushSegment)
					curPos = rightPushBound;
								
				selectionStart = curPos = len - curPos;			
			}
					
			rng.moveToElementText(event.srcElement);
			rng.move("character",curPos);							
			rng.select();
		}
					
		showStatusBar(obj); 
}

function processPush(ieKey){
		if(ieKey == 144) { //Push On
			if(!pushMode)
				toggleFieldOrient(true,true);

			event.returnValue = false;				
		}
		else if(ieKey == 111) { //Push Off
			if(pushMode)			
				toggleFieldOrient(true,true);

			event.returnValue = false;		
		}
}

function processPasswordNumeric(){
	var count =  hatsForm.elements.length;

	for  (var j = 0; j < count; j++){ 
		elementNext = hatsForm.elements[j];
		if((elementNext.type == "password") && ((elementNext.alt).indexOf("num") >= 0))	
			elementNext.dir = ((hatsForm.AUTOPUSH.value).indexOf("autoreverse=off") >= 0) ? "rtl" : "ltr";
	}
}
	
function processNumeric() {
	var count =  hatsForm.elements.length;

	for  (var j = 0; j < count; j++){ 
		elementNext = hatsForm.elements[j];
		if((elementNext.tagName == "TEXTAREA") && ((elementNext.alt).indexOf("num") >= 0)){
			reverseText(elementNext);
			if( ((elementNext.innerText).length == 0) || ((elementNext.innerText).length == elementNext.cols) )
				elementNext.style.textAlign = (elementNext.style.direction == "rtl") ? "left" : "right";
				
			elementNext.style.direction = (elementNext.style.direction == "rtl") ? "ltr" : "rtl";
		}
	}
}
	
function processAutoFieldReverse(obj) {
	var count =  hatsForm.elements.length;

	for  (var j = 0; j < count; j++){ 
		elementNext = hatsForm.elements[j];
		if((elementNext.tagName == "TEXTAREA") && ((elementNext.alt).indexOf("num") < 0)){
			reverseText(elementNext);	
			if( ((elementNext.innerText).length == 0) || ((elementNext.innerText).length == elementNext.cols) )
				elementNext.style.textAlign = (elementNext.style.direction == "rtl") ? "left" : "right";
				
			elementNext.style.direction = (elementNext.style.direction == "rtl") ? "ltr" : "rtl";				
		}
	}
	
	if(obj != null) {
		if ((obj.alt).indexOf("num") >= 0)
			return;
	
		var rng = document.body.createTextRange();
		rng.moveToElementText(obj);
		if((curPos != 0) || ((obj.innerText).length != obj.cols)) //bidi
			selectionStart = curPos = (obj.innerText).length - curPos;

		rng.move("character",curPos);							
		rng.select();
	}	
}

function reverseText(elementNext){
	text = elementNext.innerText;
	len = text.length;
	temp = "";
									 
	for(i = 0;i < len;i++)	{
		symbol = text.charAt(len - i - 1);
		symbol = doSymSwap(symbol);
		temp += symbol;
	}	 	  
	elementNext.innerText = temp;
}
	
function processFieldReverse(obj,setCursor){	
	isFldreversed = !isFldreversed;
	var len = (obj.innerText).length;
			
	if(len == 0) {
		obj.style.textAlign = (obj.style.direction == "rtl") ? "left" : "right";
		setCursor = false;
	}
	else if((curPos == 0) && (len == maxFieldLen)){
		obj.style.textAlign = (obj.style.direction == "rtl") ? "left" : "right";
		curPos = len - curPos;
	}
				
	toggleFieldOrient(false,false);
		
	if(setCursor) {
	var rng = document.body.createTextRange();
	rng.moveToElementText(obj);
	selectionStart = curPos = len - curPos;
	rng.move("character",curPos);							
	rng.select();
	}
}	

function processDelete(obj){
	if(pushMode){
		if(selectionStart == curPos)
			leftPushBound--;
		else
			leftPushBound -= Math.abs(selectionStart - curPos);
	}	
	curPos = Math.min(selectionStart,curPos);
	selectionStart = curPos;

	if((obj.alt).indexOf("dirty") < 0) 
		obj.alt = obj.alt + "dirty";
}

function processBackspace(obj){ 
		var range = document.selection.createRange();
		if((range.text).length == 0) {
			if(curPos > 0) {
				curPos--;
				if(pushMode) {
                    if(autoPush & (curPos == rightPushBound)) {
                        toggleFieldOrient(true,false);
                    }
					leftPushBound--;
                }
			}
			else {
				event.returnValue = false;
				return;
			}			
		}
		else {
			if(pushMode) 
				leftPushBound -= Math.abs(selectionStart - curPos);
								
			curPos = (selectionStart > curPos) ? curPos : selectionStart;			
		}			
		selectionStart = curPos;

		if((obj.alt).indexOf("dirty") < 0)
			obj.alt = obj.alt + "dirty";
	}

function processLeftarrow(obj){
	if(curPos > 0) {
		if (window.event.shiftKey) {//start selection
			if (selectionStart == curPos)
				selectionStart = curPos;
				curPos--;	
		}
		else {
			if(selectionStart != curPos)
				selectionStart = curPos = Math.min(selectionStart,curPos);
			else
				selectionStart = curPos = curPos - 1;								
		}
	}
	else
		event.returnValue = false;
}

function processRightarrow(obj){
	var text = obj.innerText;
	if(curPos < text.length){
		if (window.event.shiftKey) {//start selection
			if (selectionStart == curPos)
				selectionStart = curPos;
				curPos++;
		}
		else {
			if(selectionStart != curPos)
				selectionStart = curPos = Math.max(selectionStart,curPos);
			else
				selectionStart = curPos = curPos + 1;							
		}
	}
	else
		event.returnValue = false;	
}


function JSReorder()                   //Visual LTR -> Logical LTR only
{
this.INIT                   =  0
this.LATIN                  =  1
this.LOCAL                  =  2
this.NEUTRAL                =  3
this.LOCALNUMBER            =  4
this.LATINNUMBER            =  5
this.LATINNUMERICTERMINATOR =  6
this.NUMERICSEPARATOR       =  8
this.ENDOFLINE              =  9
this.CARRIAGERETURN         = 10
this.LINEFEED               = 11
this.SPACE                  = 12
this.ARABICDIGIT            = 13
this.SEGMENTSEPARATOR       = 14
this.BLOCKSEPARATOR         = 15
this.BIDISPECIAL            = 16

this.LATIN_STATE            =  0
this.LOCAL_STATE            =  1
this.LATIN_NUM_STATE        =  2
this.LOCAL_NUM_STATE        =  3
this.NEUTRAL_STATE          =  4
this.EOL_STATE              =  5

this.MASK_STATE             = 0x00FF
this.MASK_ACTION            = 0xFF00

this.ACTION                 = 0x4000
this.NL                     = 0x4100     //NEUTRALS TO LATIN
this.NR                     = 0x4200     //NEUTRALS TO LOCAL

this.LocalInvert            = 1
this.LocalNumInvert         = 2

var NL = this.NL
var NR = this.NR

this.StateTable = new Table(6,10)    
this.StateTable.initTable(
                    /*  I	L	R	N	.	D	.	.	E	.*/
                      
/* 0 LATIN_STATE     */ 0,	0,	1,	0,	-1,	2,	-1,	-1,	0,	5,
/* 1 LOCAL_STATE     */ 0,	0,	1,	4,	-1,	3,	-1,	-1,	4,	5,
/* 2 LATIN_NUM_STATE */ 0,	0,	1,	0,	-1,	2,	-1,	-1,	0,	5,
/* 3 LOCAL_NUM_STATE */ 0,	0,	1,	4,	-1,	3,	-1,	-1,	4,	5,
/* 4 NEUTRAL_STATE   */ NL|0,   NL|0,	NR|1,	4,	-1,	NR|3,	-1,	-1,	4,	NL|5,
/* 5 EOL_STATE	     */ 0,	0,	1,	0,	-1,	2,	-1,	-1,	0,	5
)	
this.getStateTable = getStateTable

this.StateToClass = new Array( this.LATIN, this.LOCAL, this.LATINNUMBER, this.LOCALNUMBER,
                               this.NEUTRAL, this.ENDOFLINE )

var I                       = this.INIT
var L                       = this.LATIN
var R                       = this.LOCAL
var D                       = this.LATINNUMBER
var X                       = this.LATINNUMERICTERMINATOR
var E                       = this.NUMERICSEPARATOR
var N                       = this.NEUTRAL
var S                       = this.SPACE
var C                       = this.CARRIAGERETURN
var F                       = this.LINEFEED
var A                       = this.ARABICDIGIT
var G                       = this.SEGMENTSEPARATOR
var B                       = this.BLOCKSEPARATOR
var H                       = this.BIDISPECIAL 

this.UnicodeTable = new Table(9,256)
this.UnicodeTable.initTable(
   /* Table 0: Unicode 00xx */
   /************************************************************************/
   /*     0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F    */
   /************************************************************************/
   /*0-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  I,  F,  N,  N,  C,  N,  N,
   /*1-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*2-*/ S,  N,  N,  X,  X,  X,  N,  N,  N,  N,  N,  N,  E,  N,  E,  E,
   /*3-*/ D,  D,  D,  D,  D,  D,  D,  D,  D,  D,  E,  N,  N,  N,  N,  N,
   /*4-*/ N,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*5-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  N,  N,  N,  N,  N,
   /*6-*/ N,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*7-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  N,  N,  N,  N,  N,
   /*8-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*9-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*A-*/ S,  N,  X,  X,  X,  X,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*B-*/ X,  X,  D,  D,  N,  N,  N,  N,  N,  D,  N,  N,  N,  N,  N,  N,
   /*C-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*D-*/ L,  L,  L,  L,  L,  L,  L,  N,  L,  L,  L,  L,  L,  L,  L,  L,
   /*E-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*F-*/ L,  L,  L,  L,  L,  L,  L,  N,  L,  L,  L,  L,  L,  L,  L,  L,
   
   /* Table 1: Unicode 05xx */
   /************************************************************************/
   /*     0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F    */
   /************************************************************************/
   /*0-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*1-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*2-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*3-*/ N,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*4-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*5-*/ L,  L,  L,  L,  L,  L,  L,  N,  N,  L,  L,  L,  L,  L,  L,  L,
   /*6-*/ N,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*7-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*8-*/ L,  L,  L,  L,  L,  L,  L,  L,  N,  L,  N,  N,  N,  N,  N,  N,
   /*9-*/ N,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*A-*/ R,  R,  N,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*B-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  N,  R,  R,  R,  R,  R,
   /*C-*/ R,  R,  R,  R,  R,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*D-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*E-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  N,  N,  N,  N,  N,
   /*F-*/ R,  R,  R,  R,  R,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   
   /* Table 2: Unicode 06xx */
   /************************************************************************/
   /*     0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F    */
   /************************************************************************/
   /*0-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  R,  N,  N,  N,
   /*1-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  R,  N,  N,  N,  N,
   /*2-*/ N,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*3-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  N,  N,  N,  N,  N,
   /*4-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*5-*/ R,  R,  R,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*6-*/ A,  A,  A,  A,  A,  A,  A,  A,  A,  A,  X,  A,  A,  R,  N,  N,
   /*7-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*8-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*9-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*A-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*B-*/ R,  R,  R,  R,  R,  R,  R,  R,  N,  N,  R,  R,  R,  R,  R,  N,
   /*C-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  N,
   /*D-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*E-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  N,  N,
   /*F-*/ D,  D,  D,  D,  D,  D,  D,  D,  D,  D,  N,  N,  N,  N,  N,  N,
   
   /* Table 3: Unicode 20xx */
   /************************************************************************/
   /*     0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F    */
   /************************************************************************/
   /*0-*/ S,  S,  S,  S,  S,  S,  S,  E,  S,  S,  S,  S,  N,  N,  L,  R,
   /*1-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*2-*/ N,  N,  N,  N,  N,  N,  N,  N,  B,  B,  H,  N,  N,  N,  H,  N,
   /*3-*/ X,  X,  X,  X,  X,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*4-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*5-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*6-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  H,  H,  H,  H,
   /*7-*/ D,  N,  N,  N,  D,  D,  D,  D,  D,  D,  X,  X,  N,  N,  N,  N,
   /*8-*/ D,  D,  D,  D,  D,  D,  D,  D,  D,  D,  X,  X,  N,  N,  N,  N,
   /*9-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*A-*/ X,  X,  X,  X,  X,  X,  X,  X,  X,  X,  X,  X,  N,  N,  N,  N,
   /*B-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*C-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*D-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*E-*/ L,  L,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*F-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   
   /* Table 4: Unicode 21xx */
   /************************************************************************/
   /*     0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F    */
   /************************************************************************/
   /*0-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*1-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*2-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*3-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*4-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*5-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*6-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*7-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*8-*/ L,  L,  L,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*9-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*A-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*B-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*C-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*D-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*E-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*F-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   
   /* Table 5: Unicode 30xx */
   /************************************************************************/
   /*     0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F    */
   /************************************************************************/
   /*0-*/ S,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*1-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*2-*/ N,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*3-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*4-*/ N,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*5-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*6-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*7-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*8-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*9-*/ L,  L,  L,  L,  L,  N,  N,  N,  N,  L,  L,  L,  L,  L,  L,  N,
   /*A-*/ N,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*B-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*C-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*D-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*E-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*F-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  N,
   
   /* Table 6: Unicode FBxx */
   /************************************************************************/
   /*     0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F    */
   /************************************************************************/
   /*0-*/ L,  L,  L,  L,  L,  L,  L,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*1-*/ N,  N,  N,  L,  L,  L,  L,  L,  N,  N,  N,  N,  N,  N,  R,  R,
   /*2-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*3-*/ R,  R,  R,  R,  R,  R,  R,  N,  R,  R,  R,  R,  R,  N,  R,  N,
   /*4-*/ R,  R,  N,  R,  R,  N,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*5-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*6-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*7-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*8-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*9-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*A-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*B-*/ R,  R,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*C-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*D-*/ N,  N,  N,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*E-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*F-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   
   /* Table 7: Unicode FExx */
   /************************************************************************/
   /*     0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F    */
   /************************************************************************/
   /*0-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*1-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*2-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*3-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*4-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*5-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*6-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*7-*/ R,  R,  R,  N,  R,  N,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*8-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*9-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*A-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*B-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*C-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*D-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*E-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,
   /*F-*/ R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  N,  N,  N,
   
   /* Table 8: Unicode FFxx */
   /************************************************************************/
   /*     0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F    */
   /************************************************************************/
   /*0-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*1-*/ D,  D,  D,  D,  D,  D,  D,  D,  D,  D,  N,  N,  N,  N,  N,  N,
   /*2-*/ N,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*3-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  N,  N,  N,  N,  N,
   /*4-*/ N,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*5-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  N,  N,  N,  N,  N,
   /*6-*/ N,  N,  N,  N,  N,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*7-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*8-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*9-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*A-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,
   /*B-*/ L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  L,  N,
   /*C-*/ N,  N,  L,  L,  L,  L,  L,  L,  N,  N,  L,  L,  L,  L,  L,  L,
   /*D-*/ N,  N,  L,  L,  L,  L,  L,  L,  N,  N,  L,  L,  L,  N,  N,  N,
   /*E-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,
   /*F-*/ N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N,  N
) 
this.getUnicodeTable = getUnicodeTable

this.stringAsClasses = new Array()
this.terminatorFlag = 0

this.doReorder = doReorder
this.stringToClass = stringToClass
this.applyClass = applyClass
this.getCharClass = getCharClass
this.getCharacterType = getCharacterType 
this.doAction = doAction
this.invertSegment = invertSegment
this.needInvert = needInvert
this.doSymSwap = doSymSwap
}

function getStateTable()
{
   return this.StateTable
}

function getUnicodeTable()
{
   return this.UnicodeTable
}

function getCharacterType(ch)
{
   var utab = this.getUnicodeTable().getArray()
   var str = new String(ch)
   var code = str.charCodeAt(0)
   var index = (code & 0xFF00) >> 8
   switch (index)
      {
         case 0x00: break
         case 0x05: index = 1 
                    break
         case 0x06: index = 2
                    break
         case 0x20: index = 3
                    break
         case 0x21: index = 4
                    break
         case 0x30: index = 5
                    break
         case 0xFB: index = 6
                    break
         case 0xFE: index = 7
                    break
         case 0xFF: index = 8
                    break
         default:   return(this.NEUTRAL)
      }
   return (utab[index][code & 0xFF])
}   

function doReorder(str)
{
   if (str == null || str.length < 2)
      return (str) 
   this.stringToClass(str)
   return (this.applyClass(str))   
}

function stringToClass(str)
{
   var stab = this.getStateTable().getArray()
   var prevState = 0
   var initialCharClass = this.LATIN
   var curState = stab[prevState][initialCharClass]
   var curCharClass
   var i
   
   for (i=0; i<str.length; i++)
       {
          prevState = curState
          curCharClass = this.getCharClass(str,i)             
          curState = stab[prevState][curCharClass]
          this.stringAsClasses[i] = this.StateToClass[curState & this.MASK_STATE] | this.terminatorFlag
          this.doAction(curState,i)                            
          curState &= this.MASK_STATE
       }
       
   for (i=0; i<str.length; i++)
       if ((this.stringAsClasses[i] & this.MASK_ACTION) == this.ACTION)
           this.stringAsClasses[i] &= this.MASK_STATE
}

function getCharClass(str,index)
{
   var prev = this.NEUTRAL
   var next = this.NEUTRAL
   var curr
   var result
   
   this.terminatorFlag = 0
   if (index > 0)
      prev = this.getCharacterType(str.charAt(index-1))
   curr = this.getCharacterType(str.charAt(index))
   
   switch (curr)
      {
         case this.BLOCKSEPARATOR:
         case this.SEGMENTSEPARATOR:
            result = this.LATIN
            break
         case this.ARABICDIGIT:
            result = this.LATINNUMBER
            break
         case this.LATINNUMERICTERMINATOR:
            if (index>0)
               prev = this.stringAsClasses[index-1]
            if (prev == this.LATINNUMBER || prev == this.LOCALNUMBER)
               result = this.LATINNUMBER
            else
               {
                  this.terminatorFlag = this.ACTION
                  result = this.NEUTRAL
               }
            break
         case this.NUMERICSEPARATOR:
            result = this.NEUTRAL
            if (prev == this.LATINNUMBER)
               {
                   if (index < str.length - 1)
                       next = this.getCharacterType(str.charAt(index+1))
                   switch (next)
                      {
                         case this.LATINNUMBER:
                             result = next
                             break
                         case this.LOCAL:
                         case this.NEUTRAL:
                             result = curr
                             break
                      }
                }      
            break
         case this.BIDISPECIAL:
         case this.SPACE:
            result = this.NEUTRAL
            break
         case this.CARRIAGERETURN:
         case this.LINEFEED:         
            result = this.ENDOFLINE
            break
         default:
            result = curr
      }
   return (result)                                                                    
}

function doAction(currState,index)
{
   var action = currState & this.MASK_ACTION
   var classFromAction 
   
   switch (action)
      {
         case this.NL:
         case this.NR:
            classFromAction = (action & this.MASK_ACTION & ~this.ACTION) >> 8
            while (index-- > 0)
               {
                  if ((this.stringAsClasses[index] & this.MASK_STATE) == this.NEUTRAL)
                     {
                        if ((this.stringAsClasses[index] & this.MASK_ACTION) &&
                            (this.stringAsClasses[index+1] == this.LOCALNUMBER ||
                             this.stringAsClasses[index+1] == this.LATINNUMBER))
                           this.stringAsClasses[index] = this.stringAsClasses[index+1]
                        else
                           this.stringAsClasses[index] = classFromAction
                     }
                  else
                     break
                }
             break                       
      }     
}

function applyClass(str)
{
   var array = new Array(str.length)
   var Str = new String("");
   var i
   for (i=0; i<str.length; i++)
       array[i] = str.charAt(i)
   this.invertSegment(array,this.LocalNumInvert)
   this.invertSegment(array,this.LocalInvert)
   for (i=0; i<array.length; i++)
       Str += array[i]
   return (Str)
}

function needInvert(invertType,index)
{
   switch (invertType)
      {
         case this.LocalInvert:
            return (this.stringAsClasses[index] == this.LOCAL ||
                    this.stringAsClasses[index] == this.LOCALNUMBER)
         case this.LocalNumInvert:
            return (this.stringAsClasses[index] == this.LOCALNUMBER)
         default:
            return (false)   
      }                
}
function invertSegment(s,invertType)
{   
   var start = 0
   var end
   var sum
   var tmp
   var i
          
   while (start < s.length)
      {
         if (this.needInvert(invertType,start))
            {
               end = start + 1
               while (end < s.length)
                  {
                     if (!this.needInvert(invertType,end))   
                        break
                     end++
                  }
               sum = end - 1 + start
               for (; start < sum - start; start++)
                   {
                      tmp = this.doSymSwap( s[start] )
                      s[start] = this.doSymSwap( s[sum-start] )
                      s[sum-start] = tmp
                   }
               start = end - 1
            }                       
         start++
      }      
}

// --------------------------------------------------------

function Table(nrows,ncols)
{
   var i = 0
   this.trows = nrows
   this.tcols = ncols          
   this.rows = new Array(nrows)
   for (i=0; i<nrows; i++)
       this.rows[i] = new Array(ncols)       
   this.initTable = initTable 
   this.getArray = getArray     
}

function getArray()
{
   return this.rows
}
   
function initTable()
{
   var i = 0
   var j = 0
   var k = 0
   var l = 0
   var m = Math.min(this.trows*this.tcols,initTable.arguments.length)
   for (k=0; k<m; k++,l++)
       {       
          if (l == this.tcols)
       	     {
       	     	i++
       	     	j=0
       	     	l=0
       	     }
       	   this.rows[i][j++] = this.initTable.arguments[k]        	  
       }
}	
	  

