/*
 *  Kirylaca project
 *  v1.1
 *  www.zedlik.com
 *  copyright (c) zedlik 2006
 *  http://www.zedlik.com/pragramy/kirylaca/
 *
 *
 *  Note! IE6 ignores javascript line
 *  following by a cyrillic // commentary.
 */

var charset = "latin";

var deadKeyATableLatin = new Array();
var deadKeyBTableLatin = new Array();

var pCyrillicMap = new Array();
var pCyrillicSoftMap = new Array();
var pDigraphMap = new Array();

var deadKeyAPressed = false;
var deadKeyBPressed = false;


// auxillary characters
deadKeyATableLatin["`"] = "``";
deadKeyATableLatin[" "] = "`";
deadKeyATableLatin["~"] = "";
deadKeyBTableLatin["~"] = "~~";
deadKeyBTableLatin[" "] = "~";
deadKeyBTableLatin["`"] = "";

// subject characters

// lacin
// dead `
// lacinka
deadKeyATableLatin["c"] = String.fromCharCode(0x0107);
deadKeyATableLatin["C"] = String.fromCharCode(0x0106);
deadKeyATableLatin["n"] = String.fromCharCode(0x0144);
deadKeyATableLatin["N"] = String.fromCharCode(0x0143);
deadKeyATableLatin["s"] = String.fromCharCode(0x015B);
deadKeyATableLatin["S"] = String.fromCharCode(0x015A);
deadKeyATableLatin["z"] = String.fromCharCode(0x017A);
deadKeyATableLatin["Z"] = String.fromCharCode(0x0179);

//useful stuff
deadKeyATableLatin["a"] = String.fromCharCode(0x00E1);
deadKeyATableLatin["A"] = String.fromCharCode(0x00C1);
deadKeyATableLatin["e"] = String.fromCharCode(0x00E9);
deadKeyATableLatin["E"] = String.fromCharCode(0x00C9);
deadKeyATableLatin["i"] = String.fromCharCode(0x00ED);
deadKeyATableLatin["I"] = String.fromCharCode(0x00CD);
// deadKeyATableLatin["l"] = String.fromCharCode(0x013E);
// deadKeyATableLatin["L"] = String.fromCharCode(0x013D);
deadKeyATableLatin["o"] = String.fromCharCode(0x00F3);
deadKeyATableLatin["O"] = String.fromCharCode(0x00D3);
deadKeyATableLatin["u"] = String.fromCharCode(0x00FA);
deadKeyATableLatin["U"] = String.fromCharCode(0x00DA);
deadKeyATableLatin["y"] = String.fromCharCode(0x00FD);
deadKeyATableLatin["Y"] = String.fromCharCode(0x00DD);
deadKeyATableLatin[","] = String.fromCharCode(0x00AB); // &laquo;
deadKeyATableLatin["."] = String.fromCharCode(0x00BB); // &raquo;
deadKeyATableLatin["<"] = String.fromCharCode(0x201E); // double low-9 quotation mark
deadKeyATableLatin[">"] = String.fromCharCode(0x201C); // left fouble quotation mark
deadKeyATableLatin["-"] = String.fromCharCode(0x2014); // mdash

// [cyrillic]
deadKeyATableLatin["'"] = String.fromCharCode(0x044C); // soft sign
deadKeyATableLatin["\""] = String.fromCharCode(0x042C); // capital soft sign

// dead ~
// lacinka
deadKeyBTableLatin["c"] = String.fromCharCode(0x010D);
deadKeyBTableLatin["C"] = String.fromCharCode(0x010C);
deadKeyBTableLatin["l"] = String.fromCharCode(0x0142);
deadKeyBTableLatin["L"] = String.fromCharCode(0x0141);
deadKeyBTableLatin["s"] = String.fromCharCode(0x0161);
deadKeyBTableLatin["S"] = String.fromCharCode(0x0160);
deadKeyBTableLatin["u"] = String.fromCharCode(0x016D);
deadKeyBTableLatin["U"] = String.fromCharCode(0x016C);
deadKeyBTableLatin["z"] = String.fromCharCode(0x017E);
deadKeyBTableLatin["Z"] = String.fromCharCode(0x017D);

// useful stuff
deadKeyBTableLatin["x"] = String.fromCharCode(0x017C); // dotted z
deadKeyBTableLatin["X"] = String.fromCharCode(0x017B); // dotted Z
deadKeyBTableLatin["a"] = String.fromCharCode(0x0105); // an
deadKeyBTableLatin["A"] = String.fromCharCode(0x0104); // An
deadKeyBTableLatin["e"] = String.fromCharCode(0x0119); // en
deadKeyBTableLatin["E"] = String.fromCharCode(0x0118); // En
deadKeyBTableLatin["-"] = String.fromCharCode(0x2013); // ndash


pCyrillicMap["a"] = String.fromCharCode(0x0430);
pCyrillicMap["A"] = String.fromCharCode(0x0410);
pCyrillicMap["b"] = String.fromCharCode(0x0431);
pCyrillicMap["B"] = String.fromCharCode(0x0411);
pCyrillicMap["c"] = String.fromCharCode(0x0446);
pCyrillicMap["C"] = String.fromCharCode(0x0426);
pCyrillicMap[String.fromCharCode(0x0107)] = String.fromCharCode(0x0446) + String.fromCharCode(0x044C); // c'
pCyrillicMap[String.fromCharCode(0x0106)] = String.fromCharCode(0x0426) + String.fromCharCode(0x044C); // Ñ'
pCyrillicMap[String.fromCharCode(0x010D)] = String.fromCharCode(0x0447); // c^
pCyrillicMap[String.fromCharCode(0x010C)] = String.fromCharCode(0x0427); // Ñ^
pCyrillicMap["d"] = String.fromCharCode(0x0434);
pCyrillicMap["D"] = String.fromCharCode(0x0414);
pCyrillicMap["e"] = String.fromCharCode(0x044D);
pCyrillicMap["E"] = String.fromCharCode(0x042D);
pCyrillicMap["f"] = String.fromCharCode(0x0444);
pCyrillicMap["F"] = String.fromCharCode(0x0424);
pCyrillicMap["g"] = String.fromCharCode(0x0491);
pCyrillicMap["G"] = String.fromCharCode(0x0490);
pCyrillicMap["h"] = String.fromCharCode(0x0433);
pCyrillicMap["H"] = String.fromCharCode(0x0413);
pCyrillicMap["i"] = String.fromCharCode(0x0456);
pCyrillicMap["I"] = String.fromCharCode(0x0406);
pCyrillicMap["j"] = String.fromCharCode(0x0439);
pCyrillicMap["J"] = String.fromCharCode(0x0419);
pCyrillicMap["k"] = String.fromCharCode(0x043A);
pCyrillicMap["K"] = String.fromCharCode(0x041A);
pCyrillicMap["l"] = String.fromCharCode(0x043B) + String.fromCharCode(0x044C);
pCyrillicMap["L"] = String.fromCharCode(0x041B) + String.fromCharCode(0x044C);
pCyrillicMap[String.fromCharCode(0x0142)] = String.fromCharCode(0x043B);
pCyrillicMap[String.fromCharCode(0x0141)] = String.fromCharCode(0x041B);
pCyrillicMap["m"] = String.fromCharCode(0x043C);
pCyrillicMap["M"] = String.fromCharCode(0x041C);
pCyrillicMap["n"] = String.fromCharCode(0x043D);
pCyrillicMap["N"] = String.fromCharCode(0x041D);
pCyrillicMap[String.fromCharCode(0x0144)] = String.fromCharCode(0x043D) + String.fromCharCode(0x044C);
pCyrillicMap[String.fromCharCode(0x0143)] = String.fromCharCode(0x041D) + String.fromCharCode(0x044C);
pCyrillicMap["o"] = String.fromCharCode(0x043E);
pCyrillicMap["O"] = String.fromCharCode(0x041E);
pCyrillicMap["p"] = String.fromCharCode(0x043F);
pCyrillicMap["P"] = String.fromCharCode(0x041F);
pCyrillicMap["r"] = String.fromCharCode(0x0440);
pCyrillicMap["R"] = String.fromCharCode(0x0420);
pCyrillicMap["s"] = String.fromCharCode(0x0441);
pCyrillicMap["S"] = String.fromCharCode(0x0421);
pCyrillicMap[String.fromCharCode(0x015B)] = String.fromCharCode(0x0441) + String.fromCharCode(0x044C); // s'
pCyrillicMap[String.fromCharCode(0x015A)] = String.fromCharCode(0x0421) + String.fromCharCode(0x044C); // S'
pCyrillicMap[String.fromCharCode(0x0161)] = String.fromCharCode(0x0448); // s^
pCyrillicMap[String.fromCharCode(0x0160)] = String.fromCharCode(0x0428); // S^
pCyrillicMap["t"] = String.fromCharCode(0x0442);
pCyrillicMap["T"] = String.fromCharCode(0x0422);
pCyrillicMap["u"] = String.fromCharCode(0x0443);
pCyrillicMap["U"] = String.fromCharCode(0x0423);
pCyrillicMap[String.fromCharCode(0x016D)] = String.fromCharCode(0x045E); // u~
pCyrillicMap[String.fromCharCode(0x016C)] = String.fromCharCode(0x040E); // U~
pCyrillicMap["v"] = String.fromCharCode(0x0432);
pCyrillicMap["V"] = String.fromCharCode(0x0412);
pCyrillicMap["y"] = String.fromCharCode(0x044B);
pCyrillicMap["Y"] = String.fromCharCode(0x042B);
pCyrillicMap["z"] = String.fromCharCode(0x0437);
pCyrillicMap["Z"] = String.fromCharCode(0x0417);
pCyrillicMap[String.fromCharCode(0x017A)] = String.fromCharCode(0x0437) + String.fromCharCode(0x044C); // z'
pCyrillicMap[String.fromCharCode(0x0179)] = String.fromCharCode(0x0417) + String.fromCharCode(0x044C); // Z'
pCyrillicMap[String.fromCharCode(0x017E)] = String.fromCharCode(0x0436); // z^
pCyrillicMap[String.fromCharCode(0x017D)] = String.fromCharCode(0x0416); // Z^


pCyrillicSoftMap["a"] = String.fromCharCode(0x044F); // ja
pCyrillicSoftMap["A"] = String.fromCharCode(0x042F); // Ja
pCyrillicSoftMap["e"] = String.fromCharCode(0x0435); // je
pCyrillicSoftMap["E"] = String.fromCharCode(0x0415); // Je
pCyrillicSoftMap["o"] = String.fromCharCode(0x0451); // jo
pCyrillicSoftMap["O"] = String.fromCharCode(0x0401); // Jo
pCyrillicSoftMap["u"] = String.fromCharCode(0x044E); // ju
pCyrillicSoftMap["U"] = String.fromCharCode(0x042E); // Ju
pCyrillicSoftMap["i"] = String.fromCharCode(0x0456); // i
pCyrillicSoftMap["I"] = String.fromCharCode(0x0406); // I

pDigraphMap["h"] = new Array(String.fromCharCode(0x0446), String.fromCharCode(0x0445)); // c, ch
pDigraphMap["H"] = new Array(String.fromCharCode(0x0426), String.fromCharCode(0x0425)); // C, Ch


function addTextToCurrentPosition_LatinSelection(s, el)
{
    var tb = el;
    var pretext = tb.value.substring(0, tb.selectionStart);
    var posttext = tb.value.substr(tb.selectionEnd);
    var fh = pretext + s;
    tb.value = fh + posttext;
    tb.setSelectionRange(fh.length, fh.length);

    return false;
}

function addTextToCurrentPosition_LatinRange(s, el)
{
    var range;
    range = document.selection.createRange();
    range.text = "";
    range.collapse();

    range = document.selection.createRange();
    range.select();
    range.text = s;
    range.collapse();

    return false;
}

function isJotedCapital(c)
{
        switch (c)
    {
            case String.fromCharCode(0x0419): // J
          return true;
    }
    return false;
}

function isJotedLower(c)
{
        switch (c)
    {
            case String.fromCharCode(0x0439): // j
          return true;
    }
    return false;
}


function isSoftCapital(c)
{
        switch (c)
    {
            case String.fromCharCode(0x042C): // capital soft sign
            case String.fromCharCode(0x0406): // I
          return true;
    }
    return isJotedCapital(c);
}

function isSoftLower(c)
{
        switch (c)
    {
            case String.fromCharCode(0x044C): // soft sign
            case String.fromCharCode(0x0456): // i
          return true;
    }
    return isJotedLower(c);
}


function isJoted(c)
{
        return isJotedCapital(c) || isJotedLower(c);
}

function isSoft(c)
{
        return isSoftCapital(c) || isSoftLower(c);
}


function isDigraphCapital(c)
{
        switch (c)
    {
            case String.fromCharCode(0x0426): // C
                  return true;
    }
    return false;
}

function isHard(c)
{
        switch (c)
    {
            case String.fromCharCode(0x0431): // b
            case String.fromCharCode(0x0411): // B
            case String.fromCharCode(0x0432): // v
            case String.fromCharCode(0x0412): // V
            case String.fromCharCode(0x0433): // h
            case String.fromCharCode(0x0413): // H
            case String.fromCharCode(0x0491): // g
            case String.fromCharCode(0x0490): // G
            case String.fromCharCode(0x0434): // d
            case String.fromCharCode(0x0414): // D
            case String.fromCharCode(0x0436): // z^
            case String.fromCharCode(0x0416): // Z^
            case String.fromCharCode(0x0437): // z
            case String.fromCharCode(0x0417): // Z
            case String.fromCharCode(0x043A): // k
            case String.fromCharCode(0x041A): // K
            case String.fromCharCode(0x043B): // l/
            case String.fromCharCode(0x041B): // L/
            case String.fromCharCode(0x043C): // m
            case String.fromCharCode(0x041C): // M
            case String.fromCharCode(0x043D): // n
            case String.fromCharCode(0x041D): // N
            case String.fromCharCode(0x043F): // p
            case String.fromCharCode(0x041F): // P
            case String.fromCharCode(0x0440): // r
            case String.fromCharCode(0x0420): // R
            case String.fromCharCode(0x0441): // s
            case String.fromCharCode(0x0421): // S
            case String.fromCharCode(0x0442): // t
            case String.fromCharCode(0x0422): // T
            case String.fromCharCode(0x0444): // f
            case String.fromCharCode(0x0424): // F
            case String.fromCharCode(0x0445): // ch
            case String.fromCharCode(0x0425): // Ch
            case String.fromCharCode(0x0446): // c
            case String.fromCharCode(0x0426): // C
            case String.fromCharCode(0x0447): // c^
            case String.fromCharCode(0x0427): // C^
            case String.fromCharCode(0x0448): // s^
            case String.fromCharCode(0x0428): // S^
          return true;
    }
    return false;
}


function mapCyrillicChar(s)
{
        var rc;
           if (pCyrillicMap[s])
               rc = pCyrillicMap[s];
    else
               rc = s;
    return rc;
}


function addCyrillicChar(pretext, s)
{
    if (pCyrillicSoftMap[s])
    {
            var l = pretext.length;
            if (l > 0)
            {
                    // var prechar = pretext[l - 1];
                    var prechar = pretext.substr(l - 1, 1);
            if (isSoft(prechar))
            {
                    if (isSoftCapital(prechar))
                {
                        s = s.toUpperCase();
                }
                              rc = pCyrillicSoftMap[s];
                if (isJoted(prechar))
                {
                    if (l > 1)
                    {
                        // var pprechar = pretext[l - 2];
                                            var pprechar = pretext.substr(l - 2, 1);
                        if (isHard(pprechar))
                        {
                            rc = "'" + rc;
                        }
                    }
                }
                pretext = pretext.substring(0, l - 1);
            }
            else
            {
                              rc = pCyrillicMap[s];
            }
            }
        else
        {
                      rc = pCyrillicMap[s];
        }
    }
    else
    {
            if (pDigraphMap[s])
            {
                      var l = pretext.length;
                    if (l > 0)
                    {
                            // var prechar = pretext[l - 1];
                            var prechar = pretext.substr(l - 1, 1);
                if (isDigraphCapital(prechar))
                {
                        s = s.toUpperCase();
                }
                if (prechar == pDigraphMap[s][0])
                {
                        pretext = pretext.substring(0, l - 1);
                        rc = pDigraphMap[s][1];
                }
                else
                {
                                 rc = mapCyrillicChar(s);
                }
            }
            else
            {
                        rc = mapCyrillicChar(s);
            }
            }
            else
            {
                rc = mapCyrillicChar(s);
            }
    }
    return pretext + rc;
}


function addTextToCurrentPosition_CyrillicSelection(s, el)
{
    var tb = el;
    var pretext = tb.value.substring(0, tb.selectionStart);
    var posttext = tb.value.substr(tb.selectionEnd);
    var fh = addCyrillicChar(pretext, s);
    tb.value = fh + posttext;
    tb.setSelectionRange(fh.length, fh.length);

    return false;
}

function addTextToCurrentPosition_CyrillicRange(s, el)
{
    var range;
        range = document.selection.createRange()
    range.text = "";
        range.collapse();

        range = document.selection.createRange();
        range.select();
        range.text = "_";
        range.moveStart("word", -2);
        var pretext = range.text.substring(0, range.text.length - 1);
        range.text = '';
        range.collapse();

    var fh = addCyrillicChar(pretext, s);
        range = document.selection.createRange();
    range.select();
    range.text = "";
        range.collapse();
    range.text = "";
        range.collapse();
        range.text = fh;
        range.collapse();

    return false;
}


var addTextToCurrentPosition_Latin = 0;
var addTextToCurrentPosition_Cyrillic = 0;

function addTextToCurrentPosition(s, el)
{
        var r;
    if (charset == "latin")
    {
            r = addTextToCurrentPosition_Latin(s, el);
    }
    else
    {
            // r = addTextToCurrentPosition_Cyrillic(" ", el);
            r = addTextToCurrentPosition_Cyrillic(s, el);
    }
    setFocus(el);
    return r;
}


function setFunctions(which)
{
    if (!addTextToCurrentPosition_Latin)
    {
        addTextToCurrentPosition_Latin = which ?
          addTextToCurrentPosition_LatinSelection : addTextToCurrentPosition_LatinRange;
    }

    if (!addTextToCurrentPosition_Cyrillic)
    {
        addTextToCurrentPosition_Cyrillic = which ?
          addTextToCurrentPosition_CyrillicSelection : addTextToCurrentPosition_CyrillicRange;
    }
}

function onKeyPressHandler(e, el, label)
{
    var key = window.event ? e.keyCode : e.which;
    var keychar = String.fromCharCode(key);

    var result = true;

    setFunctions(e.which);

    if (key >= 32 && !e.ctrlKey && !e.altKey && !(e.which == 0))
    {
            if (charset == "cyrillic" && !deadKeyAPressed && !deadKeyBPressed)
            {
            if (pCyrillicMap[keychar])
            {
                    addTextToCurrentPosition(keychar, el);
                result = false;
            }
            }

        if (deadKeyAPressed)
        {
            if (deadKeyATableLatin[keychar])
            {
                addTextToCurrentPosition(deadKeyATableLatin[keychar], el);
                result = false;
            }
            else
            {
                addTextToCurrentPosition("`", el);
                    if (pCyrillicMap[keychar])
                    {
                            addTextToCurrentPosition(keychar, el);
                        result = false;
                    }
            }
            if (keychar != "`")
                deadKeyAPressed = false;
        }

        if (deadKeyBPressed)
        {
            if (deadKeyBTableLatin[keychar])
            {
                addTextToCurrentPosition(deadKeyBTableLatin[keychar], el);
                result = false;
            }
            else
            {
                addTextToCurrentPosition("~", el);
            }
            if (keychar != "~")
                deadKeyBPressed = false;
        }

        switch (keychar)
        {
            case "`":
                deadKeyAPressed = !deadKeyAPressed;
                result = false;
                break;
            case "~":
                deadKeyBPressed = !deadKeyBPressed;
                result = false;
                break;
        }
    }
    else
    {
                   result = true;
    }
    setFocus(el);
    return result;
}

function changeCharset(el, label)
{
    if (charset == "latin")
            charset = "cyrillic";
    else
            charset = "latin";
    setCharset(el, label); // *
    setFocus(el);
          return false;
}

function selectAll(el)
{
        setFocus(el);
        el.select();
    return false;
}

function setFocus(el)
{
        el.focus();
        return false;
}

// ***

function keyDownHandler(e, el, label)
{
    var keyCode = e.keyCode;
    switch (keyCode)
    {
            case 27: // Esc
                        changeCharset(el, label);
            if (e.which == null)
                                e.returnValue = false;
                else
                    e.preventDefault();
                break;

            case 8: // Backspace
                if (deadKeyAPressed || deadKeyBPressed)
            {
                    deadKeyAPressed = false;
                deadKeyBPressed = false;
                    if (e.which == null)
                                        e.returnValue = false;
                        else
                {
                        // add a fictive char :)
                    var selectedText = "";
                    var selectionStart = el.selectionStart;
                    var selectionEnd = el.selectionEnd;

                    if (selectionStart < selectionEnd)
                    {
                              selectedText = el.value.substring(selectionStart, selectionEnd);
                            addTextToCurrentPosition(selectedText, el);
                    }

                    addTextToCurrentPosition(" ", el);
                            // e.preventDefault();
                }
            }
            break;

    }
    // setFocus(el);
    return false;
}


function setCharset(el, label)
{
    // var kLabel = "KIRYLICA";
    var kLabel = "&#x041A;&#x0406;&#x0420;&#x042B;&#x041B;&#x0406;&#x0426;&#x0410;";
//    var kLabel = "&#x041A;&#x0406;&#x0420;&#x042B;&#x041B;&#x0406;&#x0426;&#x0410;";
    var lLabel = "&#321;ACINKA";
//    var lLabel = "&#322;acinka";

//    var kLabel = "EN";
//    var lLabel = "&#321;A";

    if (label)
    {
            if (label.innerHTML != null)
        {
                    if (charset == "latin")
                                  label.innerHTML = lLabel;
                    else
                                  label.innerHTML = kLabel;
        }
            else if (label.value != null)
        {
                    if (charset == "latin")
                                  label.value = lLabel;
                    else
                                  label.value = kLabel;
        }
    }

        setFocus(el);
          return false;
}

// * real-time resize routines

  var resizeHandlerSet = false;
  var startPointY;
  var startHeight;
  var minHeight = 180;
  var selectHandler;

  function setResizeHandler(e, element, stub)
  {
    resizeHandlerSet = true;
    startPointY = e.clientY;
    startHeight = parseInt(element.style.height);

    stub.style.visibility = "visible";
    // stub.style.width = "90%";
    // stub.style.height = "90%";
    selectHandler = document.onselectstart;
    element.style.cursor = "s-resize";
    document.onselectstart = new Function ("return false"); // IE
  }

  function unsetResizeHandler(e, element, stub)
  {
    if (resizeHandlerSet)
    {
      resizeHandlerSet = false;

      stub.style.visibility = "hidden";
      document.onselectstart = selectHandler;
      element.style.cursor = "text";
    }
  }

  function resizeHandler(e, element)
  {
    if (resizeHandlerSet)
    {
      var currentHeight = parseInt(element.style.height);
      var recalculatedHeight = startHeight + e.clientY - startPointY;
      if (recalculatedHeight >= minHeight)
      {
        element.style.height = recalculatedHeight;
      }
    }
  }