//    gamabhana phonetic Library: Client side javascript library to attach phonetics to
//    editable html tags facilitating direct input capabilitiy.
//    Copyright (C) 2006  Omkar Milind Joshi.
//
//    This library is free software; you can redistribute it and/or
//    modify it under the terms of the GNU Lesser General Public
//    License as published by the Free Software Foundation; either
//    version 2.1 of the License, or (at your option) any later version.
//
//    This library is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//    Lesser General Public License for more details.
//
//    You should have received a copy of the GNU Lesser General Public
//    License along with this library; if not, write to the Free Software
//    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
//    Contact : josh9383@gmail.com or call : 9869l84O6O 

var __GgvActiveWritePane; //active text area
var __GgvKEY__ = '';  //This variable stores each keystrokes
var __GgvOldLength =0; //This stores length of parsed tupple

// unicode shifts for different indic scripts

var __GgaShift = new Array(5);
var __GgaPhoneticMap=GgaDevBaseMap;

__GgaShift['__devanagari__']=0;
__GgaShift['__bengoli__']=128;
__GgaShift['__gurumukhi__']=256;
__GgaShift['__gujarati__']=384;
__GgaShift['__kannada__']=896;

var GgvLocationType;
var GgvAfterNode=null;
var GgvTextNode=null;
var GgvBeforeNode=null;
var GgvInsertNode=null;
var GgvNewNode = null;
var GgvThisContainer;
var GgvOldNode;
var GgvSelection;
var GgvRange;
var Ggves=false;
var GgvPosition=0;
var GgvText=null;

var GgvIE=false;
var GgvMozilla=false;

var __GgvLanguageShift=0;
var __GgvLanguage='__roman__';



function GfResetGvars()
{
Ggves=false;
GgvNewNode=null;
GgvText=null;
GgvAfterNode=null;
GgvTextNode=null;
GgvBeforeNode=null;
GgvInsertNode=null;
GgvNewNode = null;
GgvOldNode=null;
GgvPosition=0;
__GgvKEY__ = '';
__GgvOldLength =0;
}


//set language


function GfSetLanguage(GivLanguage)
{
        if(GivLanguage=='')
                return false;

        if(__GgaShift[GivLanguage])
        {
                __GgvLanguageShift=__GgaShift[GivLanguage];
                __GgvLanguage = GivLanguage;
                GgvNewNode=null;
                GgvOldNode=null;
                GgvBeforeNode=null;
                GgvAfterNode=null;
                Ggves=false;
                GgvText=null;
        }

        if(GivLanguage=='__roman__')
        {
                __GgvLanguageShift=0;
                __GgvLanguage=GivLanguage;
                GgvNewNode=null;
                GgvOldNode=null;
                GgvBeforeNode=null;
                GgvAfterNode=null;
                Ggves=false;
                GgvText=null;
        }

        if(!__GgaShift[GivLanguage])
        {
                __GgvLanguageShift=0;
                __GgvLanguage=GivLanguage;
                GgvNewNode=null;
                GgvOldNode=null;
                GgvBeforeNode=null;
                GgvAfterNode=null;
                Ggves=false;
                GgvText=null;

        }



        if(
                __GgvLanguage == '__devanagari__' ||
                __GgvLanguage == '__bengoli__' || 
                __GgvLanguage == '__gurumukhi__' ||
                __GgvLanguage =='__gujarati__'||
                __GgvLanguage =='__kannada__'
        )
        {
                __GgaPhoneticMap = GgaDevBaseMap;
        }
        return true;
}

// decide whether to apply shift on retrieved unicode string

function GfShiftRequired(GlvUnicodeValue)
{

if 
(
GlvUnicodeValue == '\u007E' ||
GlvUnicodeValue =='\u0060'||
GlvUnicodeValue =='\u0021'||
GlvUnicodeValue =='\u0040'||
GlvUnicodeValue =='\u0023'||
GlvUnicodeValue =='\u0024'||
GlvUnicodeValue =='\u0025'||
GlvUnicodeValue =='\u005E'||
GlvUnicodeValue =='\u0026'||
GlvUnicodeValue =='\u002A'||
GlvUnicodeValue =='\u0028'||
GlvUnicodeValue =='\u0029'||
GlvUnicodeValue =='\u002D'||
GlvUnicodeValue =='\u003D'||
GlvUnicodeValue =='\u005F'||
GlvUnicodeValue =='\u002B'||
GlvUnicodeValue =='\u005B'||
GlvUnicodeValue =='\u005D'||
GlvUnicodeValue =='\u007B'||
GlvUnicodeValue =='\u007D'||
GlvUnicodeValue =='\u003B'||
GlvUnicodeValue =='\u0027'||
GlvUnicodeValue =='\u003A'||
GlvUnicodeValue =='\u0022'||
GlvUnicodeValue =='\u002C'||
GlvUnicodeValue =='\u002F'||
GlvUnicodeValue =='\u003C'||
GlvUnicodeValue =='\u003E'||
GlvUnicodeValue =='\u003F'||
GlvUnicodeValue =='\u005C'||
GlvUnicodeValue =='\u007C')
        return false;
else 
        return true;
}


// Yes ! thats it! you have to attach phonetics to editable html tag by id 

function GfAttachPhoneticsToEditableId(GivId)
{

  var Glfmyfunc=new Function("e","__GgvActiveWritePane = '"+GivId+"';GfKeyboardListener(e);");
 if(document.all)
 {
        GgvIE=true;
        document.getElementById(GivId).onfocus=function(){__GgvActiveWritePane=GivId;GfResetGvars()};
        document.getElementById(GivId).onblur=function(){GfResetGvars()};
        if(document.getElementById(GivId).contentWindow)
                document.getElementById(GivId).contentWindow.document.onkeypress= Glfmyfunc;
        else
                document.getElementById(GivId).onkeypress= Glfmyfunc;
  }
 else
 {
        GgvMozilla=true;
        if(document.getElementById(GivId).contentWindow)
        {
                document.getElementById(GivId).contentWindow.document.addEventListener("onfocus", function(){__GgvActiveWritePane=GivId;GfResetGvars();}, true);
                var Glfmyfunc2=new Function("e","__GgvActiveWritePane = '"+GivId+"';GfResetGvars();");
                var Glfmyfunc3=new Function("e","GfResetGvars();");
                document.getElementById(GivId).contentWindow.document.addEventListener("onclick", Glfmyfunc2, true);
                document.getElementById(GivId).contentWindow.document.addEventListener("onblur", Glfmyfunc3,  true);
        }
        else
        {
                document.getElementById(GivId).onfocus=function(){__GgvActiveWritePane=GivId;GfResetGvars();};
                document.getElementById(GivId).onclick=function(){__GgvActiveWritePane=GivId;GfResetGvars();};
                document.getElementById(GivId).onblur=function(){GfResetGvars();};
        }

        try
        {
                if(document.getElementById(GivId).contentWindow)
                        document.getElementById(GivId).contentWindow.document.addEventListener("keypress", Glfmyfunc, true);
                else
                {
                        document.getElementById(GivId).onkeypress= GfKeyboardListener;
                }

        }
        catch (e)
        {
                alert("Error preloading content.");
        }
 }

}


// gamabhana keyboardlistener 


function GfKeyboardListener(GivEvent)
{

if(__GgvLanguage!='__roman__')
{
        var GlvState = (typeof document.getElementById(__GgvActiveWritePane).contentWindow == "undefined")?false:true;
        if(GlvState==true && GgvMozilla)
        {
                        if (!GivEvent.ctrlKey)
                        {
         
                                var __GlvKeyStroke = GivEvent.which;

                                if(
                                        __GlvKeyStroke == 0 || __GlvKeyStroke==8 || __GlvKeyStroke==13 || __GlvKeyStroke==9 ||
                                        __GlvKeyStroke== 32 || __GlvKeyStroke == 33 || __GlvKeyStroke == 34 || __GlvKeyStroke == 35 || __GlvKeyStroke == 36 || __GlvKeyStroke==37 || __GlvKeyStroke==38 || __GlvKeyStroke==39 || __GlvKeyStroke==40 ||
                                        __GlvKeyStroke==45 || __GlvKeyStroke == 46 ||
                                        __GlvKeyStroke==60 || __GlvKeyStroke==62
                                )

                                {       Ggves=false;
                                        __GgvKEY__='';
                                        GgvOldNode=false;
                                        GgvNewNode=false;
                                        GgvAfterNode=false;
                                        return;
                                }
                                else
                                {
                                        GfparsePhonetic(__GgvActiveWritePane,GivEvent.charCode);
                                        GivEvent.preventDefault();
                                        return false;
                                }
                        }
                return;
         }
        else 
        {
                var GlvThisEvent;
                if(GgvIE && document.getElementById(__GgvActiveWritePane).contentWindow)
                        GlvThisEvent=document.getElementById(__GgvActiveWritePane).contentWindow.event;
                else
                        GlvThisEvent=(window.event) ? window.event : GivEvent ; //document.getElementById(__GgvActiveWritePane).event;


                if (!GlvThisEvent.ctrlKey)
                {

                        var __GlvKeyStroke ;
                        if(GlvThisEvent.keyCode ==0)
                                __GlvKeyStroke = GlvThisEvent.charCode;
                        else
                                __GlvKeyStroke = GlvThisEvent.keyCode;

                        if(GgvIE)
                                GlvThisEvent.returnValue=GfparsePhonetic(__GgvActiveWritePane,__GlvKeyStroke);
                        else
                        {
                                if( 
                                        __GlvKeyStroke == 0 || __GlvKeyStroke==8 || __GlvKeyStroke==13 || __GlvKeyStroke==9 ||
                                        __GlvKeyStroke== 32 || __GlvKeyStroke == 33 || __GlvKeyStroke == 34 || __GlvKeyStroke == 35 || __GlvKeyStroke == 36 || __GlvKeyStroke==37 || __GlvKeyStroke==38 || __GlvKeyStroke==39 || __GlvKeyStroke==40 ||
                                        __GlvKeyStroke==45 || __GlvKeyStroke == 46 ||
                                        __GlvKeyStroke==60 || __GlvKeyStroke==62
                                )

                                {
                                        __GgvKEY__ = " ";
                                        __GgvOldLength = 1;
                                        return __GlvKeyStroke;
                                }
                                GfparsePhonetic(__GgvActiveWritePane,__GlvKeyStroke);
                                //GlvThisEvent.preventDefault();
                        }
                        return false;
                }
        }
}
return;
}




// gamabhana phonetic parser



function GfparsePhonetic(GivId,GivCode)
{

        var GlvChar = String.fromCharCode(GivCode); // get the character equivalent to this keycode
        if(GivCode==8 || GivCode==32 || GivCode==0)
        {
                // if space or backspace is pressed we have to clear the key. otherwise there will be some malformed conjunctions
                //alert(GivCode);
                Ggves=false;
                GgvNewNode = null;
                conj=false;
                __GgvKEY__ = " ";
                __GgvOldLength = 1;
                //window.status = __GgvKEY__;
                return ;
        }

        lastkey = __GgvKEY__;
        __GgvKEY__ += "" + GlvChar;      //append the current character pressed to the key
        //alert(__GgvKEY__);
        //if(!document.all) alert(__GgvKEY__+' '+GlvChar);

        GlvParsedTupple = GfparsePhonetickey(__GgvKEY__); // get the combined equivalent
        parsed___GgvKEY__ = GfparsePhonetickey(GlvChar); // get the single equivalent

        if((GlvParsedTupple == "" && parsed___GgvKEY__ !="")) //that means it has no joint equivalent
        {
                //alert('1');
                // there is no joint equivalent - so show the single equivalent. 
                GlvParsedTupple = parsed___GgvKEY__;
                if (GlvParsedTupple=="")
                {
                        // there is no available equivalent 
                        __GgvKEY__ ="";
                        GgvNewNode = null;
                        //window.status = __GgvKEY__;
                        return;
                }
                else
                {
                        // found one equivalent
                        __GgvKEY__ = GlvChar;
                        //alert('insertAtCursor '+GlvParsedTupple);
                        //insertAtCursor(GivId,GlvParsedTupple);
                        //alert(-1);
                        GfSpecialInsert(GivId,GlvParsedTupple,-1);
                        __GgvOldLength = GlvParsedTupple.length;
                        //window.status = __GgvKEY__;
                        return false;
                }
        }
        else if(GlvParsedTupple!="")//joint equivalent found 
        {
                // we have found some joint equivalent process it
                //alert(__GgvOldLength);
                //alert('insertJointAtCursor '+GlvParsedTupple);
                //insertJointAtCursor(GivId,GlvParsedTupple, __GgvOldLength);
                //alert(1);
                GfSpecialInsert(GivId,GlvParsedTupple, __GgvOldLength);
                __GgvOldLength = GlvParsedTupple.length;
                //window.status = __GgvKEY__;
                return false;
        }

}

// gamabhana phonetic parser keylevel function

    function GfparsePhonetickey(GivCode)
    {
        //this function just returns a phonetic equivalent for a given keystroke or tupple
        //just read the array - if found then return the eq.
        //otherwise return a null value

        if (!__GgaPhoneticMap[GivCode])  
        {
                        //alert('no match');
                        return ""; //return a null value
        }
        else
        {
                var GlvUnicodeX = __GgaPhoneticMap[GivCode].toString();
                var GlvLocalShift = 0;
                if(GfShiftRequired(GlvUnicodeX))
                        GlvLocalShift=__GgvLanguageShift;

                var GlvReturnCode;
                GlvReturnCode="";
                // process returned unicode(s) and apply proper shift

                for ( i = 0; i < GlvUnicodeX.length;i++)
                                GlvReturnCode = GlvReturnCode.toString()+String.fromCharCode((GlvUnicodeX.charCodeAt(i)+GlvLocalShift));
                return (GlvReturnCode);
        }

}

// gamabhana editor interface : internal routine for rich text editing in mozilla

function GfInsertPhoneticNodeMozilla(GivId,GivString,GivConjunction)
{
        GgvNewNode=document.createTextNode(GivString);
        if(!Ggves)
        {
                GgvOldNode=null;
                GgvNewNode=null;
                //alert('new es');

                // es : false : editing will begin as new word or line

                Ggves=true;
                GgvSelection = document.getElementById(GivId).contentWindow.getSelection();

                //get the first range of the selection

                if(typeof GgvSelection!="undefined")
                        GgvRange=GgvSelection.getRangeAt(0);
                else
                        GgvRange= document.getElementById(GivId).contentWindow.document.createRange();


                GgvThisContainer=GgvRange.startContainer;
                GgvPosition=GgvRange.startOffset;
                GgvLocationType=GgvThisContainer.nodeType;

                if(GgvLocationType!=3)
                        GgvAfterNode=GgvThisContainer.childNodes[GgvPosition];
                else
                {
                        GgvTextNode = GgvThisContainer;
                        GgvThisContainer = GgvTextNode.parentNode;
                        GgvText = GgvTextNode.nodeValue;
                }

                GgvNewNode=document.createTextNode(GivString);
                var GlvTextBefore="";

                if(GgvPosition >0 && GgvText!=null)
                        GlvTextBefore = GgvText.substr(0,GgvPosition);

                var GlvTextAfter="";
                if(GgvText!=null)
                        GlvTextAfter = GgvText.substr(GgvPosition);

                GgvBeforeNode = document.createTextNode(GlvTextBefore);

                if(!(GgvLocationType!=3))
                        GgvAfterNode = document.createTextNode(GlvTextAfter);
         }
  
        if (GivConjunction && GgvOldNode!=null && GgvNewNode!=null)
        {
                GgvThisContainer.removeChild(GgvOldNode);
                GgvThisContainer.insertBefore(GgvNewNode, GgvAfterNode);
                GgvOldNode=GgvNewNode;
        }
  
        if(!GivConjunction && GgvOldNode!=null && GgvNewNode!=null)
        {
                //alert('non conjugate to GgvOldNode: '+GgvOldNode.nodeValue);
                GgvThisContainer.insertBefore(GgvNewNode, GgvAfterNode);
                GgvOldNode=GgvNewNode;     

        }

        if(GgvOldNode==null && GgvNewNode!=null)
        {
                GgvOldNode=GgvNewNode;
                if(GgvLocationType!=3)
                        GgvThisContainer.insertBefore(GgvNewNode,GgvAfterNode);
                else
                {
                        GgvThisContainer.insertBefore(GgvAfterNode,GgvTextNode);
                        GgvThisContainer.insertBefore(GgvNewNode,GgvAfterNode);
                        GgvThisContainer.insertBefore(GgvBeforeNode,GgvNewNode);

                        if(GgvText!=null)
                                GgvThisContainer.removeChild(GgvTextNode);
                }
        }

        if(GgvLocationType!=3)
        {
                var GlvDevlen = GivString.length;
                GgvRange.setEnd(GgvNewNode,GlvDevlen);
                GgvRange.setStart(GgvNewNode,GlvDevlen);
        }
        else
        {
                GgvRange.setStart(GgvAfterNode,0);
                GgvRange.setEnd(GgvAfterNode,0);
        }
}


// gamabhana editor interface :internal routine for rich text,plain text editing in IE


function GfInsertPhoneticNodeIE(GivId,GivString,GivLength)
{
                var GlvElement = document.getElementById(GivId);

                if(GivLength==-1)
                {
                        if (GlvElement.document.selection)
                        {
                                GlvElement.focus();
                                GgvSelection = GlvElement.document.selection.createRange();
                                GgvSelection.text = GivString;
                                GgvSelection.collapse(true);
                                GgvSelection.select();
                        }
                }
                else
                {
                        if (GlvElement.document.selection) 
                        {
                                GlvElement.focus();
                                var GlvPane = GlvElement.document;

                                GgvRange = GlvPane.selection.createRange();

                                if(!GlvElement.value)
                                        var GlvLength= GlvPane.body.innerHTML.length;
                                else
                                        var GlvLength = GlvElement.value.length;

                                if (GlvLength >= GivLength)
                                {  
                                        GgvRange.moveStart('character', -1*(GivLength));   
                                        //sel.moveEnd('character',-1*(len-1));
                                }


                                GgvRange.text = GivString;
                                GgvRange.collapse(true);
                                GgvRange.select();
                         }
                }
}


// gamabhana editor interface function


function GfSpecialInsert(GivId,GivString,GivLength)
{
        if(GgvIE)
                GfInsertPhoneticNodeIE(GivId,GivString,GivLength);
        if(GgvMozilla)
        {
                if(typeof document.getElementById(GivId).contentWindow == "undefined" )
                        return GfInsertPhoneticTextMozilla(GivId,GivString,GivLength);
                else
                {
                        if(GivLength==-1)
                                GfInsertPhoneticNodeMozilla(GivId,GivString,false);
                        else
                                GfInsertPhoneticNodeMozilla(GivId,GivString,true);
                }
        }
}


// gamabhana editor interface :internal routine for plain text editing in Mozilla

function GfInsertPhoneticTextMozilla(GivId,GivString,GivLength)
{

        var GlvElement = document.getElementById(GivId);
        var GlvDiff = 0;
        if (GivLength != -1)
                GlvDiff = GivLength;

        if (GlvElement.selectionStart || GlvElement.selectionStart == 0)
        {

                var startPos = GlvElement.selectionStart-GlvDiff;
                var endPos = GlvElement.selectionEnd;
                var scrollTop = GlvElement.scrollTop;
                startPos = (startPos == -1 ? GlvElement.value.length : startPos );
                GlvElement.value = GlvElement.value.substring(0, startPos)+ GivString+ GlvElement.value.substring(endPos, GlvElement.value.length);
                GlvElement.focus();
                GlvElement.selectionStart = startPos + GivString.length;
                GlvElement.selectionEnd = startPos + GivString.length;
                GlvElement.scrollTop = scrollTop;
        }
        else
        {
                var scrollTop = GlvElement.scrollTop;
                GlvElement.value += GivString;
                GlvElement.focus();
                GlvElement.scrollTop = scrollTop;
        }
        return;
}
