/********************************************************************************
  JavaScript Virtual Keyboard

  Copyright (C) 2006 Dmitry Khudorozhkov (mailto:kh_dmitry2001@mail.ru)

  This software is provided "as-is", without any express or implied warranty. In
  no event will the author be held liable for any damages arising from the use
  of this software.

  Permission is granted to anyone to use this software for any purpose, including
  commercial applications, and to alter it and redistribute it freely, subject to
  the following restrictions:

  1. The origin of this software must not be misrepresented; you must not claim
     that you wrote the original software. If you use this software in a product,
     an acknowledgment in the product documentation would be appreciated but is
     not required.

  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.

  3. This notice may not be removed or altered from any source distribution.

********************************************************************************/

var kbArray = new Array();

var agent = navigator.userAgent.toLowerCase();
var msie = (agent.indexOf("msie") != -1) && !window.opera;

function setup_event(elem, eventType, handler)
{
  if(elem.attachEvent)
  {
    elem.attachEvent("on" + eventType, handler);
  }
  else if(elem.addEventListener)
  {
    elem.addEventListener(eventType, handler, false);
  }
}

function detach_event(elem, eventType, handler)
{
  if(elem.detachEvent)
  {
    elem.detachEvent("on" + eventType, handler);
  }
  else if(elem.removeEventListener)
  {
    elem.removeEventListener(eventType, handler, false);
  }
}

function get_event_source(e)
{
  var event = e ? e : window.event;
  return event.srcElement ? event.srcElement : event.target;
}

// Many thanks to Peter-Paul Koch (www.quirksmode.org) for the following 2 functions.
function findPosX(obj)
{
  var curleft = 0;
  if(obj.offsetParent)
  {
    while(obj.offsetParent)
    {
      curleft += obj.offsetLeft;
      obj = obj.offsetParent;
    }
  }
  else if(obj.x)
    curleft += obj.x;

  return curleft;
}

function findPosY(obj)
{
  var curtop = 0;
  if(obj.offsetParent)
  {
    while(obj.offsetParent)
    {
      curtop += obj.offsetTop;
      obj = obj.offsetParent;
    }
  }
  else if(obj.y)
    curtop += obj.y;

  return curtop;
}

function findOffX(obj)
{ return (obj && obj.main) ? parseFloat(obj.main.offsetLeft) : 0; }

function findOffY(obj)
{ return (obj && obj.main) ? parseFloat(obj.main.offsetTop) : 0; }

function findOffW(obj)
{ return (obj && obj.main) ? parseFloat(obj.main.offsetWidth) : 0; }

function findOffH(obj)
{ return (obj && obj.main) ? parseFloat(obj.main.offsetHeight) : 0; }

function setup_style(obj, top, left, width, height, position, border_color, text_align, line_height, font_size, font_weight, padding_left, padding_right, font_color, back_color)
{
  if(top) obj.style.top = top;
  if(left) obj.style.left = left;
  if(width) obj.style.width = width;
  if(height) obj.style.height = height;
  if(position) obj.style.position = position;
  if(border_color) obj.style.border = "1px solid " + border_color;
  if(back_color) obj.style.backgroundColor = back_color;

  if(line_height) obj.style.lineHeight = line_height;
  if(text_align) obj.style.textAlign = text_align;
  if(padding_left) obj.style.paddingLeft = padding_left;
  if(padding_right) obj.style.paddingRight = padding_right;

  obj.style.fontWeight = (font_weight ? font_weight : "bold");
  if(font_size) obj.style.fontSize = font_size;
  if(msie) obj.UNSELECTABLE = "on";
}

function setup_key(top, left, width, height, border_color, text_align, line_height, font_size, font_weight, padding_left, padding_right, font_color, back_color)
{
  var key = document.createElement("DIV");
  setup_style(key, top, left, width, height, "absolute");

  var key_sub = document.createElement("DIV");
  key.appendChild(key_sub);

  setup_style(key_sub,"","","",line_height,"relative",border_color,text_align,line_height,font_size,font_weight,padding_left,padding_right,font_color,back_color);

  var retObj = new Object();
  retObj.main = key;
  retObj.sub = key_sub;

  return retObj;
}

function ShowVKeyboard(container_id, callback_proc, shownhide_on_change, font_size, font_color, dead_color, back_color, border_color, inactive_border_color, lang_sel_brd_color, lang_sel_item_color)
{
  var ct = document.getElementById(container_id);
  var vkboard = kbArray[container_id];

  if(vkboard)
  {
    var changed = false;

    if((vkboard.Callback != callback_proc) && (String(callback_proc).length > 0))
    {
      vkboard.Callback = callback_proc;
      changed = true;
    }

    if(!changed || (changed && shownhide_on_change))
    {
      ct.style.display = (ct.style.display == "none" ? "block" : "none");

      var menu = document.getElementById(container_id + "___lang_menu");
      if(menu)
        ct.removeChild(menu);
    }
  }
  else
  {
    var fs = font_size ? font_size : "14px";
    var fc = font_color ? font_color : "#000";
    var bkc = back_color ? back_color : "#FFF";
    var bc = border_color ? border_color : "#777";
    var ibc = inactive_border_color ? inactive_border_color : "#CCC";
    var lsc = lang_sel_brd_color ? lang_sel_brd_color : "#F77";
    var lic = lang_sel_item_color ? lang_sel_item_color : "#DDD";

    // vkboard creation:
    vkboard = new Object;

    vkboard.Callback = callback_proc;
    vkboard.Caps = false;
    vkboard.Shift = false;
    vkboard.AltGr = false;
    vkboard.DeadAction = null;
    vkboard.CurrentLayout = "Us";

    vkboard.fontsize = fs;
    vkboard.fontcolor = fc;
    vkboard.backcolor = bkc;
    vkboard.bordercolor = bc;
    vkboard.inactivebc = ibc;
    vkboard.lsc = lsc;
    vkboard.lic = lic;

    vkboard.keys = new Array(), vkboard.ctrl = new Array();

    kbArray[container_id] = vkboard;

    var mag = parseFloat(fs) / 14.0, cell = 25.0 * mag, dcell = 2 * cell;
    var cp = String(cell) + "px", lh = String(Math.floor(cell - 2.0)) + "px";

    var initY = findPosY(ct), initX = findPosX(ct);

    var kb = document.createElement("DIV");
    ct.appendChild(kb);

    ct.style.display = "block";
    ct.style.position = "absolute";
    ct.style.top = initY + "px", ct.style.left = initX +"px";

    kb.style.position = "relative";
    kb.style.top = "0px", kb.style.left = "0px";
    kb.style.border = "1px solid " + bc;

    var kb_main = document.createElement("DIV");
    kb.appendChild(kb_main);

    kb_main.style.position = "relative";
    kb_main.style.width = "1px";
    kb_main.style.cursor = "default";
    kb_main.style.backgroundColor = bkc;

    var prevX = 0, prevY = 1, prevW = 0, prevH = 0;

    // Convinience var-strings:
    var c = "center", n = "normal", r = "right", l = "left", e = "&nbsp;";

    // Number row:

    var key;
    for(var i = 0; i < 13; i++)
    {
      key = setup_key("1px", (prevX + prevW + 1) + "px", cp, cp, bc, c, lh, fs);
      key.sub.id = container_id + "___key" + String(i);
      kb_main.appendChild(key.main);

      prevX = findOffX(key), prevW = findOffW(key), vkboard.keys[i] = key.sub;
    }

    prevY = findOffY(key), prevH = findOffH(key);

    var kb_kbp = setup_key("1px", (prevX + prevW + 1) + "px", (2.96 * cell) + "px", cp, bc, r, lh, fs, n, "", "4px");
    kb_kbp.sub.innerHTML = "BackSpace";
    kb_kbp.sub.id = container_id + "___kbp";
    kb_main.appendChild(kb_kbp.main);
    vkboard.ctrl["backsp"] = kb_kbp.sub;

    // Top row:

    var kb_tab = setup_key((prevY + prevH + 1) + "px", "1px", (1.48 * cell + 1) + "px", cp, bc, l, lh, fs, n, "4px");
    kb_tab.sub.innerHTML = "Tab";
    kb_tab.sub.id = container_id + "___tab";
    kb_main.appendChild(kb_tab.main);
    vkboard.ctrl["tab"] = kb_tab.sub;

    prevX = findOffX(kb_tab), prevW = findOffW(kb_tab), prevY = findOffY(kb_tab);

    for(; i < 26; i++)
    {
      key = setup_key(prevY + "px", (prevX + prevW + 1) + "px", cp, cell + "px", bc, c, lh, fs);
      key.sub.id = container_id + "___key" + String(i);
      kb_main.appendChild(key.main);

      prevX = findOffX(key), prevW = findOffW(key), vkboard.keys[i] = key.sub;
    }

    prevH = findOffH(key);
    var kbpH = findOffX(kb_kbp) + findOffW(kb_kbp);

    var kb_enter_top = setup_key(prevY + "px", (prevX + prevW + 1) + "px", String(kbpH - prevX - prevW - 1) + "px", (1.08 * cell) + "px", bc, c, cp, fs);
    kb_enter_top.sub.style.borderBottomColor = bkc;
    kb_enter_top.sub.innerHTML = e;
    kb_enter_top.sub.subst = "Enter";      // Special expando
    kb_enter_top.sub.id = container_id + "___enter_top";
    kb_main.appendChild(kb_enter_top.main);
    vkboard.ctrl["et"] = kb_enter_top.sub;

    // Home row:

    var kb_caps = setup_key((prevY + prevH + 1) + "px", "1px", dcell + "px", cp, bc, l, lh, fs, n, "4px");
    kb_caps.sub.innerHTML = "Caps";
    kb_caps.sub.id = container_id + "___caps";
    kb_main.appendChild(kb_caps.main);
    vkboard.ctrl["caps"] = kb_caps.sub;

    prevX = findOffX(kb_caps), prevW = findOffW(kb_caps), prevY = findOffY(kb_caps);

    for(; i < 38; i++)
    {
      key = setup_key(prevY + "px", (prevX + prevW + 1) + "px", cp, cp, bc, c, lh, fs);
      key.sub.id = container_id + "___key" + String(i);
      kb_main.appendChild(key.main);

      prevX = findOffX(key), prevW = findOffW(key), vkboard.keys[i] = key.sub;
    }

    prevY = findOffY(key), prevH = findOffH(key);

    var kb_enter_l = setup_key(prevY + "px", (prevX + prevW + 1) + "px", (0.54 * cell) + "px", cp, bc, r, lh, fs, n, "", "4px");
    kb_enter_l.sub.style.borderRightColor = bkc;
    kb_enter_l.sub.innerHTML = e;
    kb_enter_l.sub.subst = "Enter";
    kb_enter_l.sub.id = container_id + "___enter_l";
    kb_main.appendChild(kb_enter_l.main);
    vkboard.ctrl["el"] = kb_enter_l.sub;

    prevX = findOffX(kb_enter_l), prevW = findOffW(kb_enter_l);

    var kb_enter = setup_key(prevY + "px", (prevX + prevW) + "px", String(findOffX(kb_enter_top) + findOffW(kb_enter_top) - prevX - prevW) + "px", cp, bc, r, lh, fs, n, "", "4px");
    kb_enter.sub.style.borderTopColor = bkc;
    kb_enter.sub.style.borderLeftColor = bkc;
    kb_enter.sub.innerHTML = "Enter";
    kb_enter.sub.id = container_id + "___enter";
    kb_main.appendChild(kb_enter.main);
    vkboard.ctrl["e"] = kb_enter.sub;

    // Bottom row:

    var kb_shift = setup_key((prevY + prevH + 1) + "px", "1px", (2.52 * cell) + "px", cp, bc, l, lh, fs, n, "4px");
    kb_shift.sub.innerHTML = "Shift";
    kb_shift.sub.id = container_id + "___shift";
    kb_main.appendChild(kb_shift.main);
    vkboard.ctrl["sh"] = kb_shift.sub;

    prevX = findOffX(kb_shift), prevW = findOffW(kb_shift), prevY = findOffY(kb_shift);

    for(; i < 48; i++)
    {
      key = setup_key(prevY + "px", (prevX + prevW + 1) + "px", cp, cp, bc, c, lh, fs);
      key.sub.id = container_id + "___key" + String(i);
      kb_main.appendChild(key.main);

      prevX = findOffX(key), prevW = findOffW(key), vkboard.keys[i] = key.sub;
    }

    prevY = findOffY(key), prevH = findOffH(key);

    var kb_shift_r = setup_key(prevY + "px", (prevX + prevW + 1) + "px", String(findOffX(kb_kbp) + findOffW(kb_kbp) - prevX - prevW - 1) + "px", cp, bc, r, lh, fs, n, "", "4px");
    kb_shift_r.sub.innerHTML = "Shift";
    kb_shift_r.sub.id = container_id + "___shift_r";
    kb_main.appendChild(kb_shift_r.main);
    vkboard.ctrl["sr"] = kb_shift_r.sub;

    // Language selector:
    var vcell = String(1.32 * cell) + "px";

    var kb_lang = setup_key((prevY + prevH + 1) + "px", "1px", vcell, cp, lsc, l, lh, fs, n, "4px");
    kb_lang.sub.id = container_id + "___lang";
    vkboard.ctrl["lang"] = kb_lang.sub;
    kb_main.appendChild(kb_lang.main);

    prevY = findOffY(kb_lang);

    var kb_res_2 = setup_key(prevY + "px", (findOffX(kb_lang) + findOffW(kb_lang) + 1) + "px", vcell, cp, ibc, c, lh, fs);
    kb_res_2.sub.innerHTML = e;
    kb_main.appendChild(kb_res_2.main);

    var kb_res_3 = setup_key(prevY + "px", (findOffX(kb_res_2) + findOffW(kb_res_2) + 1) + "px", vcell, cp, ibc, c, lh, fs);
    kb_res_3.sub.innerHTML = e;
    kb_main.appendChild(kb_res_3.main);

    var kb_space = setup_key(prevY + "px", (findOffX(kb_res_3) + findOffW(kb_res_3) + 1) + "px", (6.28 * cell) + "px", cp, bc, c, lh, fs);
    kb_space.sub.id = container_id + "___space";
    setup_event(kb_space.sub, 'mousedown', generic_callback_proc);
    vkboard.ctrl["space"] = kb_space.sub;
    kb_main.appendChild(kb_space.main);

    var kb_alt_gr = setup_key(prevY + "px", (findOffX(kb_space) + findOffW(kb_space) + 1) + "px", vcell, cp, bc, c, lh, parseFloat(fs) * 0.786, n);
    kb_alt_gr.sub.innerHTML = "AltGr";
    kb_alt_gr.sub.id = container_id + "___alt_gr";
    vkboard.ctrl["altgr"] = kb_alt_gr.sub;
    kb_main.appendChild(kb_alt_gr.main);

    var kb_res_5 = setup_key(prevY + "px", (findOffX(kb_alt_gr) + findOffW(kb_alt_gr) + 1) + "px", vcell, cp, ibc, c, lh, fs);
    kb_res_5.sub.innerHTML = e;
    kb_main.appendChild(kb_res_5.main);

    var kb_res_6 = setup_key(prevY + "px", (findOffX(kb_res_5) + findOffW(kb_res_5) + 1) + "px", vcell, cp, ibc, c, lh, fs);
    kb_res_6.sub.innerHTML = e;
    kb_main.appendChild(kb_res_6.main);

    kb_main.style.height = (prevY + prevH + 1) + "px";

    // Numeric keypad:

    var edge = (kbpH + cell + 1) + "px";

    var kb_pad_eur = setup_key("1px", edge, cp, cp, bc, c, lh, fs);
    kb_pad_eur.sub.innerHTML = "&#x20AC;";
    kb_pad_eur.sub.id = container_id + "___pad_eur";
    vkboard.ctrl["padeur"] = kb_pad_eur.sub;
    kb_main.appendChild(kb_pad_eur.main);

    var edge_1 = (findOffX(kb_pad_eur) + findOffW(kb_pad_eur) + 1) + "px";

    var kb_pad_slash = setup_key("1px", edge_1, cp, cp, bc, c, lh, fs);
    kb_pad_slash.sub.innerHTML = "/";
    kb_pad_slash.sub.id = container_id + "___pad_slash";
    vkboard.ctrl["padsl"] = kb_pad_slash.sub;
    kb_main.appendChild(kb_pad_slash.main);

    var edge_2 = (findOffX(kb_pad_slash) + findOffW(kb_pad_slash) + 1) + "px";

    var kb_pad_star = setup_key("1px", edge_2, cp, cp, bc, c, lh, fs);
    kb_pad_star.sub.innerHTML = "*";
    kb_pad_star.sub.id = container_id + "___pad_star";
    vkboard.ctrl["padst"] = kb_pad_star.sub;
    kb_main.appendChild(kb_pad_star.main);

    var edge_3 = (findOffX(kb_pad_star) + findOffW(kb_pad_star) + 1) + "px";

    var kb_pad_minus = setup_key("1px", edge_3, cp, cp, bc, c, lh, fs);
    kb_pad_minus.sub.innerHTML = "-";
    kb_pad_minus.sub.id = container_id + "___pad_minus";
    vkboard.ctrl["padmin"] = kb_pad_minus.sub;
    kb_main.appendChild(kb_pad_minus.main);

    kb.style.width = kb_main.style.width = String(findOffX(kb_pad_minus) + findOffW(kb_pad_minus) + 1) + "px";

    var edge_Y = (findOffY(kb_pad_eur) + findOffH(kb_pad_eur) + 1) + "px";

    var kb_pad_7 = setup_key(edge_Y, edge, cp, cp, bc, c, lh, fs);
    kb_pad_7.sub.innerHTML = "7";
    kb_pad_7.sub.id = container_id + "___pad_7";
    vkboard.ctrl["pad7"] = kb_pad_7.sub;
    kb_main.appendChild(kb_pad_7.main);

    var kb_pad_8 = setup_key(edge_Y, edge_1, cp, cp, bc, c, lh, fs);
    kb_pad_8.sub.innerHTML = "8";
    kb_pad_8.sub.id = container_id + "___pad_8";
    vkboard.ctrl["pad8"] = kb_pad_8.sub;
    kb_main.appendChild(kb_pad_8.main);

    var kb_pad_9 = setup_key(edge_Y, edge_2, cp, cp, bc, c, lh, fs);
    kb_pad_9.sub.innerHTML = "9";
    kb_pad_9.sub.id = container_id + "___pad_9";
    vkboard.ctrl["pad9"] = kb_pad_9.sub;
    kb_main.appendChild(kb_pad_9.main);

    var kb_pad_plus = setup_key(edge_Y, edge_3, cp, (dcell + 1) + "px", bc, c, (dcell - 1) + "px", fs);
    kb_pad_plus.sub.innerHTML = "+";
    kb_pad_plus.sub.id = container_id + "___pad_plus";
    vkboard.ctrl["padpl"] = kb_pad_plus.sub;
    kb_main.appendChild(kb_pad_plus.main);

    edge_Y = (findOffY(kb_pad_7) + findOffH(kb_pad_7) + 1) + "px";

    var kb_pad_4 = setup_key(edge_Y, edge, cp, cp, bc, c, lh, fs);
    kb_pad_4.sub.innerHTML = "4";
    kb_pad_4.sub.id = container_id + "___pad_4";
    vkboard.ctrl["pad4"] = kb_pad_4.sub;
    kb_main.appendChild(kb_pad_4.main);

    var kb_pad_5 = setup_key(edge_Y, edge_1, cp, cp, bc, c, lh, fs);
    kb_pad_5.sub.innerHTML = "5";
    kb_pad_5.sub.id = container_id + "___pad_5";
    vkboard.ctrl["pad5"] = kb_pad_5.sub;
    kb_main.appendChild(kb_pad_5.main);

    var kb_pad_6 = setup_key(edge_Y, edge_2, cp, cp, bc, c, lh, fs);
    kb_pad_6.sub.innerHTML = "6";
    kb_pad_6.sub.id = container_id + "___pad_6";
    vkboard.ctrl["pad6"] = kb_pad_6.sub;
    kb_main.appendChild(kb_pad_6.main);

    edge_Y = (findOffY(kb_pad_4) + findOffH(kb_pad_4) + 1) + "px";

    var kb_pad_1 = setup_key(edge_Y, edge, cp, cp, bc, c, lh, fs);
    kb_pad_1.sub.innerHTML = "1";
    kb_pad_1.sub.id = container_id + "___pad_1";
    vkboard.ctrl["pad1"] = kb_pad_1.sub;
    kb_main.appendChild(kb_pad_1.main);

    var kb_pad_2 = setup_key(edge_Y, edge_1, cp, cp, bc, c, lh, fs);
    kb_pad_2.sub.innerHTML = "2";
    kb_pad_2.sub.id = container_id + "___pad_2";
    vkboard.ctrl["pad2"] = kb_pad_2.sub;
    kb_main.appendChild(kb_pad_2.main);

    var kb_pad_3 = setup_key(edge_Y, edge_2, cp, cp, bc, c, lh, fs);
    kb_pad_3.sub.innerHTML = "3";
    kb_pad_3.sub.id = container_id + "___pad_3";
    vkboard.ctrl["pad3"] = kb_pad_3.sub;
    kb_main.appendChild(kb_pad_3.main);

    var kb_pad_enter = setup_key(edge_Y, edge_3, cp, (dcell + 1) + "px", bc, c, (dcell - 1) + "px", parseFloat(fs) * 0.643, n);
    kb_pad_enter.sub.innerHTML = "Enter";
    kb_pad_enter.sub.id = container_id + "___pad_enter";
    vkboard.ctrl["pade"] = kb_pad_enter.sub;
    kb_main.appendChild(kb_pad_enter.main);

    edge_Y = (findOffY(kb_pad_1) + findOffH(kb_pad_1) + 1) + "px";

    var kb_pad_0 = setup_key(edge_Y, edge, (dcell + 1) + "px", cp, bc, l, lh, fs, "bold", "7px");
    kb_pad_0.sub.innerHTML = "0";
    kb_pad_0.sub.id = container_id + "___pad_0";
    vkboard.ctrl["pad0"] = kb_pad_0.sub;
    kb_main.appendChild(kb_pad_0.main);

    var kb_pad_period = setup_key(edge_Y, edge_2, cp, cp, bc, c, lh, fs);
    kb_pad_period.sub.innerHTML = ".";
    kb_pad_period.sub.id = container_id + "___pad_period";
    vkboard.ctrl["padp"] = kb_pad_period.sub;
    kb_main.appendChild(kb_pad_period.main);

    refresh_layout(container_id);
  }
}

function set_key_state(key, onoff, textcolor, bordercolor, backcolor)
{
  if(key && key.style)
  {
    if(backcolor) key.style.backgroundColor = backcolor;
    if(bordercolor) key.style.borderColor = bordercolor;
    if(textcolor) key.style.color = textcolor;
  }

  detach_event(key, 'mousedown', generic_callback_proc);
  if(onoff)
    setup_event(key, 'mousedown', generic_callback_proc);
}

function refresh_layout(container_id)
{
  var vkboard = kbArray[container_id];
  var fc = vkboard.fontcolor;
  var bkc = vkboard.backcolor, bc = vkboard.bordercolor;
  var ibc = vkboard.inactivebc, lic = vkboard.lic;

  var layout_name = vkboard.CurrentLayout;
  var arr_type = vkboard.AltGr ? (vkboard.Shift ? "alt_gr_shift" : "alt_gr") : (vkboard.Shift ? "shift" : (vkboard.Caps ? "caps" : "normal"));

  var nkeys = vkboard.keys.length;

  eval("var caps_arr = typeof(" + layout_name + "_caps) != 'undefined'");
  if(caps_arr)
    eval("caps_arr = " + layout_name + "_caps.length == " + String(nkeys));

  eval("var shift_arr = typeof(" + layout_name + "_shift) != 'undefined'");
  if(shift_arr)
    eval("shift_arr = " + layout_name + "_shift.length == " + String(nkeys));

  eval("var alt_gr_arr = typeof(" + layout_name + "_alt_gr) != 'undefined'");
  if(alt_gr_arr)
    eval("alt_gr_arr = " + layout_name + "_alt_gr.length == " + String(nkeys));

  eval("var alt_gr_shift_arr = alt_gr_arr && typeof(" + layout_name + "_alt_gr_shift) != 'undefined'");
  if(alt_gr_shift_arr)
    eval("alt_gr_shift_arr = " + layout_name + "_alt_gr_shift.length == " + String(nkeys));

  var caps = vkboard.ctrl["caps"], shift = vkboard.ctrl["sh"], shift_r = vkboard.ctrl["sr"];
  var alt_gr = vkboard.ctrl["altgr"], space = vkboard.ctrl["space"], lang = vkboard.ctrl["lang"];
  var enter_t = vkboard.ctrl["et"], enter_l = vkboard.ctrl["el"], enter_c = vkboard.ctrl["e"];

  if(shift_arr)
  {
    set_key_state(shift, true, fc, bc, vkboard.Shift ? lic : bkc);
    set_key_state(shift_r, true, fc, bc, vkboard.Shift ? lic : bkc);
  }
  else
  {
    set_key_state(shift, false, ibc, ibc, bkc);
    set_key_state(shift_r, false, ibc, ibc, bkc);

    if(arr_type == "shift")
    {
      arr_type = "normal";
      vkboard.Shift = false;
    }
  }

  if(alt_gr_arr)
  {
    set_key_state(alt_gr, true, fc, bc, vkboard.AltGr ? lic : bkc);

    if((arr_type == "alt_gr") || (arr_type == "alt_gr_shift"))
    {
      if(alt_gr_shift_arr)
      {
        set_key_state(shift, true, fc, bc, "");
        set_key_state(shift_r, true, fc, bc, "");
      }
      else
      {
        set_key_state(shift, false, ibc, ibc, bkc);
        set_key_state(shift_r, false, ibc, ibc, bkc);

        arr_type = "alt_gr";
        vkboard.Shift = false;
      }
    }
  }
  else
  {
    set_key_state(alt_gr, false, ibc, ibc, bkc);

    if(arr_type == "alt_gr")
    {
      arr_type = "normal";
      vkboard.AltGr = false;
    }
    else if(arr_type == "alt_gr_shift")
    {
      arr_type = "normal";
      vkboard.AltGr = false, vkboard.Shift = false;

      shift.style.backgroundColor = bkc, shift_r.style.backgroundColor = bkc;
    }
  }

  if(caps_arr && (arr_type != "alt_gr") && (arr_type != "alt_gr_shift"))
  {
    set_key_state(caps, true, fc, bc, vkboard.Caps ? lic : bkc);
  }
  else
  {
    set_key_state(caps, false, ibc, ibc, bkc);

    vkboard.Caps = false;
    if(arr_type == "caps") arr_type = "normal";
  }

  var DeadValue = "";

  for(var i = 0; i < nkeys; i++)
  {
    var ndx = "[" + String(i) + "]";

    eval("var key_val = " + layout_name + "_" + arr_type + ndx);
    var key = vkboard.keys[i];

    if(vkboard.Shift && vkboard.Caps)
    {
      eval("var key_nrm = " + layout_name + "_normal" + ndx);
      eval("var key_cps = " + layout_name + "_caps" + ndx);
      eval("var key_shf = " + layout_name + "_shift" + ndx);

      if((key_cps == key_shf) && (key_nrm != key_cps))
        key_val = key_nrm;
    }

    if(String(typeof(key_val)).toLowerCase() == "object")
    {
      key.innerHTML = key_val[0], key.dead = key_val[1];

      if(vkboard.DeadAction == key_val[1]) DeadValue = key_val[0];

      set_key_state(key, true, "#F00", bc, (DeadValue == key_val[0] ? lic : bkc));
    }
    else
    {
      key.dead = null;

      var block = false;
      if((key_val != "") && vkboard.DeadAction)
      {
        eval("for(var j = 0; j < " + vkboard.DeadAction + ".length; j++) { if(" + vkboard.DeadAction + "[j][0] == key_val) { key_val = " + vkboard.DeadAction + "[j][1]; break; }}");

        eval("if(j == " + vkboard.DeadAction + ".length) block = true");
      }

      if(key_val != "")
      {
        key.innerHTML = key_val;

        if(block)
          set_key_state(key, false, ibc, ibc, bkc);
        else
          set_key_state(key, true, fc, bc, bkc);
      }
      else
      {
        key.innerHTML = "&nbsp;";
        set_key_state(key, false, ibc, ibc, bkc);
      }
    }
  }

  for(var k in vkboard.ctrl)
  {
    var key = vkboard.ctrl[k];
    switch(key)
    {
      case caps: case shift: case shift_r: case alt_gr:
        break;

      case space:
        space.innerHTML = vkboard.DeadAction ? DeadValue : "&#x00A0;";
        break;

      case lang:
        detach_event(key, 'mousedown', handle_lang_choice_menu);

        if(vkboard.DeadAction)
          set_key_state(key, false, ibc, ibc, bkc);
        else
        {
          set_key_state(key, false, fc, vkboard.lsc, bkc);
          setup_event(key, 'mousedown', handle_lang_choice_menu);
        }
        break;

      default:
        if(vkboard.DeadAction)
          set_key_state(key, false, ibc, ibc, "");
        else
          set_key_state(key, true, fc, bc, "");

        switch(key)
        {
          case enter_t: key.style.borderBottomColor = bkc; break;
          case enter_l: key.style.borderRightColor = bkc; break;
          case enter_c: key.style.borderTopColor = key.style.borderLeftColor = bkc; break;
        }
    }
  }

  lang.innerHTML = layout_name;
}

function handle_lang_choice_menu(event)
{
  var in_el = get_event_source(event);
  var container_id = in_el.id.substring(0, in_el.id.indexOf("___"));

  var ct = document.getElementById(container_id);
  var menu = document.getElementById(container_id + "___lang_menu");

  if(menu)
    ct.removeChild(menu);
  else
  {
    var vkboard = kbArray[container_id];
    var fs = vkboard.fontsize, fc = vkboard.fontcolor;
    var bkc = vkboard.backcolor, bc = vkboard.bordercolor;
    var ibc = vkboard.inactivebc, lic = vkboard.lic;

    var mag = parseFloat(fs) / 14.0, cell = 25.0 * mag, w = 102 * mag;

    menu = document.createElement("DIV");
    menu.id = container_id + "___lang_menu";
    menu.style.display = "block";
    menu.style.position = "relative";
    menu.style.top = "1px";
    menu.style.left = "0px";
    menu.style.width = String(w) + "px";
    menu.style.border = "1px solid " + bc;
    ct.appendChild(menu);

    var menu_main = document.createElement("DIV");
    menu_main.style.position = "relative";
    menu_main.style.width = String(w) + "px";
    menu_main.style.height = String(avail_langs.length * (cell + mag) + 1) + "px";
    menu_main.style.cursor = "default";
    menu.appendChild(menu_main);

    for(var j = 0; j < avail_langs.length; j++)
    {
      var item = setup_key(String((cell + mag) * j + 1) + "px", "1px", String(w - 2 * mag) + "px", cell + "px", ibc, "left", (cell - 2) + "px", fs, "normal", "4px", "", fc, bkc);
      menu_main.appendChild(item.main);

      item.sub.id = container_id + "___lang_" + String(j);
      item.sub.innerHTML = avail_langs[j][1];

      setup_event(item.sub, 'mousedown', handle_lang_choice_item);
      setup_event(item.sub, 'mouseover', new Function("event", "get_event_source(event).style.backgroundColor = '" + lic + "'"));
      setup_event(item.sub, 'mouseout', new Function("event", "get_event_source(event).style.backgroundColor = '" + bkc + "'"));
    }
  }
}

function handle_lang_choice_item(event)
{
  var in_el = get_event_source(event);

  var ndx = in_el.id.indexOf("___lang_");
  var lng = in_el.id.substring(ndx + 8, in_el.id.length);
  var container_id = in_el.id.substring(0, ndx);

  kbArray[container_id].CurrentLayout = avail_langs[lng][0];
  refresh_layout(container_id);

  document.getElementById(container_id).removeChild(document.getElementById(container_id + "___lang_menu"));
}

function generic_callback_proc(event)
{
  var in_el = get_event_source(event);
  var container_id = in_el.id.substring(0, in_el.id.indexOf("___"));

  var vkboard = kbArray[container_id];
  var val = in_el.subst ? in_el.subst : in_el.innerHTML;

  if((val != "Caps") && (val != "Shift") && (val != "AltGr") && (in_el.dead || vkboard.DeadAction))
  {
    if(vkboard.DeadAction)
    {
      if(in_el.dead) val = "";

      vkboard.DeadAction = null;
      refresh_layout(container_id);
    }
    else
    {
      vkboard.DeadAction = in_el.dead;
      refresh_layout(container_id);
      return;
    }
  }

  switch(val)
  {
    case "Caps": case "Shift": case "AltGr":
    {
      eval("vkboard." + val + " = !vkboard." + val);
      refresh_layout(container_id);
      return;
    }

    case "Tab": val = "   "; break;
    case "&lt;": val = "<"; break;
    case "&gt;": val = ">"; break;
    case "&amp;": val = "&"; break;
    case "&nbsp;": val = " "; break;
    case "&quot;": val = "\""; break;
    default:
      vkboard.AltGr = false, vkboard.Shift = false;
      refresh_layout(container_id);
      break;
  }

  if(val && vkboard.Callback)
    eval(vkboard.Callback + (val == "\"" ? "('" + val + "')" : (val == "\\" ? "(\"\\\\\")" : "(\"" + val + "\")")));
}

// Layout info:

var avail_langs = new Array(Array("Us", "English (US)"), Array("Ca", "Canadian"),
                            Array("Ru", "Russian"), Array("De", "German"),
                            Array("Fr", "French"), Array("Es", "Spanish"),
                            Array("It", "Italian"), Array("Cz", "Czech"),
                            Array("El", "Greek"), Array("He", "Hebrew"));
// Us International:

var Us_normal = new Array(Array("&#x0060;", "Grave"), "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x002D;", "&#x003D;",
                          "&#x0071;", "&#x0077;", "&#x0065;", "&#x0072;", "&#x0074;", "&#x0079;", "&#x0075;", "&#x0069;", "&#x006F;", "&#x0070;", "&#x005B;", "&#x005D;", "&#x005C;",
                          "&#x0061;", "&#x0073;", "&#x0064;", "&#x0066;", "&#x0067;", "&#x0068;", "&#x006A;", "&#x006B;", "&#x006C;", "&#x003B;", "&#x0027;", "",
                          "&#x007A;", "&#x0078;", "&#x0063;", "&#x0076;", "&#x0062;", "&#x006E;", "&#x006D;", "&#x002C;", "&#x002E;", "&#x002F;");

var Us_caps = new Array(Array("&#x0060;", "Grave"), "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x002D;", "&#x003D;",
                        "&#x0051;", "&#x0057;", "&#x0045;", "&#x0052;", "&#x0054;", "&#x0059;", "&#x0055;", "&#x0049;", "&#x004F;", "&#x0050;", "&#x005B;", "&#x005D;", "&#x005C;",
                        "&#x0041;", "&#x0053;", "&#x0044;", "&#x0046;", "&#x0047;", "&#x0048;", "&#x004A;", "&#x004B;", "&#x004C;", "&#x003B;", "&#x0027;", "",
                        "&#x005A;", "&#x0058;", "&#x0043;", "&#x0056;", "&#x0042;", "&#x004E;", "&#x004D;", "&#x002C;", "&#x002E;", "&#x002F;");

var Us_shift = new Array(Array("&#x007E;", "Tilde"), "&#x0021;", "&#x0040;", "&#x0023;", "&#x0024;", "&#x0025;", Array("&#x005E;", "Circumflex"), "&#x0026;", "&#x002A;", "&#x0028;", "&#x0029;", "&#x005F;", "&#x002B;",
                         "&#x0051;", "&#x0057;", "&#x0045;", "&#x0052;", "&#x0054;", "&#x0059;", "&#x0055;", "&#x0049;", "&#x004F;", "&#x0050;", "&#x007B;", "&#x007D;", "&#x007C;",
                         "&#x0041;", "&#x0053;", "&#x0044;", "&#x0046;", "&#x0047;", "&#x0048;", "&#x004A;", "&#x004B;", "&#x004C;", "&#x003A;", "&#x0022;", "",
                         "&#x005A;", "&#x0058;", "&#x0043;", "&#x0056;", "&#x0042;", "&#x004E;", "&#x004D;", "&#x003C;", "&#x003E;", "&#x003F;");

var Us_alt_gr = new Array("", "&#x00A1;", "&#x00B2;", "&#x00B3;", "&#x00A4;", "&#x20AC;", "&#x00BC;", "&#x00BD;", "&#x00BE;", "&#x0091;", "&#x0092;", "&#x00A5;", "&#x00D7;",
                          "&#x00E4;", "&#x00E5;", "&#x00E9;", "&#x00AE;", "&#x00FE;", "&#x00FC;", "&#x00FA;", "&#x00ED;", "&#x00F3;", "&#x00F6;", "&#x00AB;", "&#x00BB;",
                          "&#x00AC;", "&#x00E1;", "&#x00DF;", "&#x0111;", "", "", "", "", "", "&#x00F8;", "&#x00B6;", Array("&#x00B4;", "Acute"), "", "&#x00E6;", "", "&#x00A9;", "", "",
                          "&#x00F1;", "&#x00B5;", "&#x00E7;", "", "&#x00BF;");

var Us_alt_gr_shift = new Array("", "&#x00B9;", "", "", "&#x00A3;", "", "", "", "", "", "", "", "&#x00F7;", "&#x00C4;", "&#x00C5;", "&#x00C9;", "", "&#x00DE;", "&#x00DC;",
                                "&#x00DA;", "&#x00CD;", "&#x00D3;", "&#x00D6;", "", "", "&#x00A6;", "&#x00C1;", "&#x00A7;", "&#x0110;", "", "", "", "", "", "&#x00D8;",
                                "&#x00B0;", Array("&#x00A8;", "Umlaut"), "", "&#x00C6;", "", "&#x00A2;", "", "", "&#x00D1;", "", "&#x00C7;", "", "");

// Canadian (multilingual standard):

var Ca_normal = new Array("&#x002F;", "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x002D;", "&#x003D;",
                          "&#x0071;", "&#x0077;", "&#x0065;", "&#x0072;", "&#x0074;", "&#x0079;", "&#x0075;", "&#x0069;", "&#x006F;", "&#x0070;", Array("&#x005E;", "Circumflex"), "&#x00E7;", "&#x00F9;",
                          "&#x0061;", "&#x0073;", "&#x0064;", "&#x0066;", "&#x0067;", "&#x0068;", "&#x006A;", "&#x006B;", "&#x006C;", "&#x003B;", "&#x00E8;", "&#x00E0;",
                          "&#x007A;", "&#x0078;", "&#x0063;", "&#x0076;", "&#x0062;", "&#x006E;", "&#x006D;", "&#x002C;", "&#x002E;", "&#x00E9;");

var Ca_caps = new Array("&#x002F;", "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x002D;", "&#x003D;",
                        "&#x0051;", "&#x0057;", "&#x0045;", "&#x0052;", "&#x0054;", "&#x0059;", "&#x0055;", "&#x0049;", "&#x004F;", "&#x0050;", Array("&#x005E;", "Circumflex"), "&#x00C7;", "&#x00D9;",
                        "&#x0041;", "&#x0053;", "&#x0044;", "&#x0046;", "&#x0047;", "&#x0048;", "&#x004A;", "&#x004B;", "&#x004C;", "&#x003B;", "&#x00C8;", "&#x00C0;",
                        "&#x005A;", "&#x0058;", "&#x0043;", "&#x0056;", "&#x0042;", "&#x004E;", "&#x004D;", "&#x002C;", "&#x002E;", "&#x00C9;");

var Ca_shift = new Array("&#x005C;", "&#x0021;", "&#x0040;", "&#x0023;", "&#x0024;", "&#x0025;", "&#x003F;", "&#x0026;", "&#x002A;", "&#x0028;", "&#x0029;", "&#x005F;", "&#x002B;",
                         "&#x0051;", "&#x0057;", "&#x0045;", "&#x0052;", "&#x0054;", "&#x0059;", "&#x0055;", "&#x0049;", "&#x004F;", "&#x0050;", Array("&#x00A8;", "Umlaut"), "&#x00C7;", "&#x00D9;",
                         "&#x0041;", "&#x0053;", "&#x0044;", "&#x0046;", "&#x0047;", "&#x0048;", "&#x004A;", "&#x004B;", "&#x004C;", "&#x003A;", "&#x00C8;", "&#x00C0;",
                         "&#x005A;", "&#x0058;", "&#x0043;", "&#x0056;", "&#x0042;", "&#x004E;", "&#x004D;", "&#x0027;", "&#x0022;", "&#x00C9;");

var Ca_alt_gr = new Array("&#x007C;", "", "", "", "", "", "", "&#x007B;", "&#x007D;", "&#x005B;", "&#x005D;", "", "&#x00AC;", "", "", "", "", "", "", "", "", "", "", Array("&#x0060;", "Grave"),
                          Array("&#x007E;", "Tilde"), "", "", "", "", "", "", "", "", "", "", "&#x00B0;", "", "", "&#x00AB;", "&#x00BB;", "", "", "", "", "", "&#x003C;", "&#x003E;", "");

// Russian:

var Ru_normal = new Array("&#x0451;", "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x002D;", "&#x003D;",
                          "&#x0439;", "&#x0446;", "&#x0443;", "&#x043A;", "&#x0435;", "&#x043D;", "&#x0433;", "&#x0448;", "&#x0449;", "&#x0437;", "&#x0445;", "&#x044A;", "&#x005C;",
                          "&#x0444;", "&#x044B;", "&#x0432;", "&#x0430;", "&#x043F;", "&#x0440;", "&#x043E;", "&#x043B;", "&#x0434;", "&#x0436;", "&#x044D;", "",
                          "&#x044F;", "&#x0447;", "&#x0441;", "&#x043C;", "&#x0438;", "&#x0442;", "&#x044C;", "&#x0431;", "&#x044E;", "&#x002E;");

var Ru_caps = new Array("&#x0401;", "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x002D;", "&#x003D;",
                        "&#x0419;", "&#x0426;", "&#x0423;", "&#x041A;", "&#x0415;", "&#x041D;", "&#x0413;", "&#x0428;", "&#x0429;", "&#x0417;", "&#x0425;", "&#x042A;", "&#x005C;",
                        "&#x0424;", "&#x042B;", "&#x0412;", "&#x0410;", "&#x041F;", "&#x0420;", "&#x041E;", "&#x041B;", "&#x0414;", "&#x0416;", "&#x042D;", "",
                        "&#x042F;", "&#x0427;", "&#x0421;", "&#x041C;", "&#x0418;", "&#x0422;", "&#x042C;", "&#x0411;", "&#x042E;", "&#x002E;");

var Ru_shift = new Array("&#x0401;", "&#x0021;", "&#x0022;", "&#x2116;", "&#x003B;", "&#x0025;", "&#x003A;", "&#x003F;", "&#x002A;", "&#x0028;", "&#x0029;", "&#x005F;", "&#x002B;",
                         "&#x0419;", "&#x0426;", "&#x0423;", "&#x041A;", "&#x0415;", "&#x041D;", "&#x0413;", "&#x0428;", "&#x0429;", "&#x0417;", "&#x0425;", "&#x042A;", "&#x002F;",
                         "&#x0424;", "&#x042B;", "&#x0412;", "&#x0410;", "&#x041F;", "&#x0420;", "&#x041E;", "&#x041B;", "&#x0414;", "&#x0416;", "&#x042D;", "",
                         "&#x042F;", "&#x0427;", "&#x0421;", "&#x041C;", "&#x0418;", "&#x0422;", "&#x042C;", "&#x0411;", "&#x042E;", "&#x002C;");

// German:

var De_normal = new Array(Array("&#x005E;", "Circumflex"), "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x00DF;", Array("&#x00B4;", "Acute"),
                          "&#x0071;", "&#x0077;", "&#x0065;", "&#x0072;", "&#x0074;", "&#x007A;", "&#x0075;", "&#x0069;", "&#x006F;", "&#x0070;", "&#x00FC;", "&#x002B;", "&#x003C;",
                          "&#x0061;", "&#x0073;", "&#x0064;", "&#x0066;", "&#x0067;", "&#x0068;", "&#x006A;", "&#x006B;", "&#x006C;", "&#x00F6;", "&#x00E4;", "&#x0023;",
                          "&#x0079;", "&#x0078;", "&#x0063;", "&#x0076;", "&#x0062;", "&#x006E;", "&#x006D;", "&#x002C;", "&#x002E;", "&#x002D;");

var De_caps = new Array(Array("&#x005E;", "Circumflex"), "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x00DF;", Array("&#x00B4;", "Acute"),
                        "&#x0051;", "&#x0057;", "&#x0045;", "&#x0052;", "&#x0054;", "&#x005A;", "&#x0055;", "&#x0049;", "&#x004F;", "&#x0050;", "&#x00DC;", "&#x002B;", "&#x003C;",
                        "&#x0041;", "&#x0053;", "&#x0044;", "&#x0046;", "&#x0047;", "&#x0048;", "&#x004A;", "&#x004B;", "&#x004C;", "&#x00D6;", "&#x00C4;", "&#x0023;",
                        "&#x0059;", "&#x0058;", "&#x0043;", "&#x0056;", "&#x0042;", "&#x004E;", "&#x004D;", "&#x002C;", "&#x002E;", "&#x002D;");

var De_shift = new Array("&#x00BA;", "&#x0021;", "&#x0022;", "&#x00A7;", "&#x0024;", "&#x0025;", "&#x0026;", "&#x002F;", "&#x0028;", "&#x0029;", "&#x003D;", "&#x003F;", Array("&#x0060;", "Grave"),
                         "&#x0051;", "&#x0057;", "&#x0045;", "&#x0052;", "&#x0054;", "&#x005A;", "&#x0055;", "&#x0049;", "&#x004F;", "&#x0050;", "&#x00DC;", "&#x002A;", "&#x003E;",
                         "&#x0041;", "&#x0053;", "&#x0044;", "&#x0046;", "&#x0047;", "&#x0048;", "&#x004A;", "&#x004B;", "&#x004C;", "&#x00D6;", "&#x00C4;", "&#x0027;",
                         "&#x0059;", "&#x0058;", "&#x0043;", "&#x0056;", "&#x0042;", "&#x004E;", "&#x004D;", "&#x003B;", "&#x003A;", "&#x005F;");

var De_alt_gr = new Array("", "", "&#x00B2;", "&#x00B3;", "", "", "", "&#x007B;", "&#x005B;", "&#x005D;", "&#x007D;", "&#x005C;", "", "&#x0040;", "", "&#x20AC;", "", "", "", "", "",
                          "", "", "", Array("&#x007E;", "Tilde"), "&#x007C;", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "&#x00B5;", "", "", "");

// French:

var Fr_normal = new Array("&#x00B2;", "&#x0026;", "&#x00E9;", "&#x0022;", "&#x0027;", "&#x0028;", "&#x007C;", "&#x00E8;", "&#x005F;", "&#x00E7;", "&#x00E0;", "&#x0029;", "&#x003D;",
                          "&#x0061;", "&#x007A;", "&#x0065;", "&#x0072;", "&#x0074;", "&#x0079;", "&#x0075;", "&#x0069;", "&#x006F;", "&#x0070;", Array("&#x005E;", "Circumflex"), "&#x0024;", "&#x003C;",
                          "&#x0071;", "&#x0073;", "&#x0064;", "&#x0066;", "&#x0067;", "&#x0068;", "&#x006A;", "&#x006B;", "&#x006C;", "&#x006D;", "&#x00F9;", "&#x002A;",
                          "&#x0077;", "&#x0078;", "&#x0063;", "&#x0076;", "&#x0062;", "&#x006E;", "&#x002C;", "&#x003B;", "&#x003A;", "&#x0021;");

var Fr_caps = new Array("&#x00B2;", "&#x0026;", "&#x00C9;", "&#x0022;", "&#x0027;", "&#x0028;", "&#x007C;", "&#x00C8;", "&#x005F;", "&#x00C7;", "&#x00C0;", "&#x0029;", "&#x003D;",
                        "&#x0041;", "&#x005A;", "&#x0045;", "&#x0052;", "&#x0054;", "&#x0059;", "&#x0055;", "&#x0049;", "&#x004F;", "&#x0050;", Array("&#x005E;", "Circumflex"), "&#x0024;", "&#x003C;",
                        "&#x0051;", "&#x0053;", "&#x0044;", "&#x0046;", "&#x0047;", "&#x0048;", "&#x004A;", "&#x004B;", "&#x004C;", "&#x004D;", "&#x00D9;", "&#x002A;",
                        "&#x0057;", "&#x0058;", "&#x0043;", "&#x0056;", "&#x0042;", "&#x004E;", "&#x002C;", "&#x003B;", "&#x003A;", "&#x0021;");

var Fr_shift = new Array("", "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x00BA;", "&#x002B;",
                         "&#x0041;", "&#x005A;", "&#x0045;", "&#x0052;", "&#x0054;", "&#x0059;", "&#x0055;", "&#x0049;", "&#x004F;", "&#x0050;", Array("&#x00A8;", "Umlaut"), "&#x00A3;", "&#x003E;",
                         "&#x0051;", "&#x0053;", "&#x0044;", "&#x0046;", "&#x0047;", "&#x0048;", "&#x004A;", "&#x004B;", "&#x004C;", "&#x004D;", "&#x0025;", "&#x00B5;",
                         "&#x0057;", "&#x0058;", "&#x0043;", "&#x0056;", "&#x0042;", "&#x004E;", "&#x003F;", "&#x005F;", "&#x002F;", "&#x00A7;");

var Fr_alt_gr = new Array("", "", "", "&#x0023;", "&#x007B;", "&#x005B;", "&#x007C;", "", "&#x005C;", "&#x005E;", "&#x0040;", "&#x005D;", "&#x007D;", "", "", "", "", "", "", "", "",
                          "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "");

// Spanish:

var Es_normal = new Array("&#x00BA;", "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x0092;", "&#x00A1;",
                          "&#x0071;", "&#x0077;", "&#x0065;", "&#x0072;", "&#x0074;", "&#x0079;", "&#x0075;", "&#x0069;", "&#x006F;", "&#x0070;", Array("&#x0060;", "Grave"), "&#x002B;", "&#x003C;",
                          "&#x0061;", "&#x0073;", "&#x0064;", "&#x0066;", "&#x0067;", "&#x0068;", "&#x006A;", "&#x006B;", "&#x006C;", "&#x00F1;", Array("&#x00B4;", "Acute"), "&#x00E7;",
                          "&#x007A;", "&#x0078;", "&#x0063;", "&#x0076;", "&#x0062;", "&#x006E;", "&#x006D;", "&#x002C;", "&#x002E;", "&#x002D;");

var Es_caps = new Array("&#x00BA;", "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x0092;", "&#x00A1;",
                        "&#x0051;", "&#x0057;", "&#x0045;", "&#x0052;", "&#x0054;", "&#x0059;", "&#x0055;", "&#x0049;", "&#x004F;", "&#x0050;", Array("&#x0060;", "Grave"), "&#x002B;", "&#x003C;",
                        "&#x0041;", "&#x0053;", "&#x0044;", "&#x0046;", "&#x0047;", "&#x0048;", "&#x004A;", "&#x004B;", "&#x004C;", "&#x00D1;", Array("&#x00B4;", "Acute"), "&#x00C7;",
                        "&#x005A;", "&#x0058;", "&#x0043;", "&#x0056;", "&#x0042;", "&#x004E;", "&#x004D;", "&#x002C;", "&#x002E;", "&#x002D;");

var Es_shift = new Array("&#x00AA;", "&#x0021;", "&#x0022;", "&#x0027;", "&#x0024;", "&#x0025;", "&#x0026;", "&#x002F;", "&#x0028;", "&#x0029;", "&#x003D;", "&#x003F;", "&#x00BF;",
                         "&#x0051;", "&#x0057;", "&#x0045;", "&#x0052;", "&#x0054;", "&#x0059;", "&#x0055;", "&#x0049;", "&#x004F;", "&#x0050;", Array("&#x005E;", "Circumflex"), "&#x002A;", "&#x003E;",
                         "&#x0041;", "&#x0053;", "&#x0044;", "&#x0046;", "&#x0047;", "&#x0048;", "&#x004A;", "&#x004B;", "&#x004C;", "&#x00D1;", Array("&#x00A8;", "Umlaut"), "&#x00C7;",
                         "&#x005A;", "&#x0058;", "&#x0043;", "&#x0056;", "&#x0042;", "&#x004E;", "&#x004D;", "&#x003B;", "&#x003A;", "&#x005F;");

var Es_alt_gr = new Array("&#x005C;", "&#x007C;", "&#x0040;", "&#x0023;", "", "", "&#x00AC;", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "&#x005B;",
                          "&#x005D;", "", "", "", "", "", "", "", "", "", "", "", "&#x007B;", "&#x007D;", "", "", "", "", "", "", "", "", "", "");

// Italian:

var It_normal = new Array("&#x005C;", "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x0092;", "&#x00EC;",
                          "&#x0071;", "&#x0077;", "&#x0065;", "&#x0072;", "&#x0074;", "&#x0079;", "&#x0075;", "&#x0069;", "&#x006F;", "&#x0070;", "&#x00E8;", "&#x002B;", "&#x003C;",
                          "&#x0061;", "&#x0073;", "&#x0064;", "&#x0066;", "&#x0067;", "&#x0068;", "&#x006A;", "&#x006B;", "&#x006C;", "&#x00F2;", "&#x00E0;", "&#x00F9;",
                          "&#x007A;", "&#x0078;", "&#x0063;", "&#x0076;", "&#x0062;", "&#x006E;", "&#x006D;", "&#x002C;", "&#x002E;", "&#x002D;");

var It_caps = new Array("&#x005C;", "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x0092;", "&#x00EC;",
                        "&#x0051;", "&#x0057;", "&#x0045;", "&#x0052;", "&#x0054;", "&#x0059;", "&#x0055;", "&#x0049;", "&#x004F;", "&#x0050;", "&#x00C8;", "&#x002B;", "&#x003C;",
                        "&#x0041;", "&#x0053;", "&#x0044;", "&#x0046;", "&#x0047;", "&#x0048;", "&#x004A;", "&#x004B;", "&#x004C;", "&#x00D2;", "&#x00C0;", "&#x00D9;",
                        "&#x005A;", "&#x0058;", "&#x0043;", "&#x0056;", "&#x0042;", "&#x004E;", "&#x004D;", "&#x002C;", "&#x002E;", "&#x002D;");

var It_shift = new Array("&#x007C;", "&#x0021;", "&#x0022;", "&#x00A3;", "&#x0024;", "&#x0025;", "&#x0026;", "&#x002F;", "&#x0028;", "&#x0029;", "&#x003D;", "&#x003F;", "&#x005E;",
                         "&#x0051;", "&#x0057;", "&#x0045;", "&#x0052;", "&#x0054;", "&#x0059;", "&#x0055;", "&#x0049;", "&#x004F;", "&#x0050;", "&#x00E9;", "&#x002A;", "&#x003C;",
                         "&#x0041;", "&#x0053;", "&#x0044;", "&#x0046;", "&#x0047;", "&#x0048;", "&#x004A;", "&#x004B;", "&#x004C;", "&#x00E7;", "&#x00B0;", "&#x00A7;",
                         "&#x005A;", "&#x0058;", "&#x0043;", "&#x0056;", "&#x0042;", "&#x004E;", "&#x004D;", "&#x003B;", "&#x003A;", "&#x005F;");

var It_alt_gr = new Array("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "&#x005B;", "&#x005D;",
                          "", "", "", "", "", "", "", "", "", "", "&#x0040;", "&#x0023;", "", "", "", "", "", "", "", "", "", "", "");

var It_alt_gr_shift = new Array("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "&#x007B;",
                                "&#x007D;", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "");

// Czech:

var Cz_normal = new Array("&#x003B;", "&#x002B;", "&#x011B;", "&#x0161;", "&#x010D;", "&#x0159;", "&#x017E;", "&#x00FD;", "&#x00E1;", "&#x00ED;", "&#x00E9;", "&#x003D;", Array("&#x00B4;", "Acute"),
                          "&#x0071;", "&#x0077;", "&#x0065;", "&#x0072;", "&#x0074;", "&#x0079;", "&#x0075;", "&#x0069;", "&#x006F;", "&#x0070;", "&#x00FA;", "&#x0029;", "&#x005C;",
                          "&#x0061;", "&#x0073;", "&#x0064;", "&#x0066;", "&#x0067;", "&#x0068;", "&#x006A;", "&#x006B;", "&#x006C;", "&#x016F;", "&#x00A7;", Array("&#x00A8;", "Umlaut"),
                          "&#x007A;", "&#x0078;", "&#x0063;", "&#x0076;", "&#x0062;", "&#x006E;", "&#x006D;", "&#x002C;", "&#x002E;", "&#x002D;");

var Cz_caps = new Array("&#x003B;", "&#x002B;", "&#x011A;", "&#x0160;", "&#x010C;", "&#x0158;", "&#x017D;", "&#x00DD;", "&#x00C1;", "&#x00CD;", "&#x00C9;", "&#x003D;", "&#x02CA;",
                        "&#x0051;", "&#x0057;", "&#x0045;", "&#x0052;", "&#x0054;", "&#x0059;", "&#x0055;", "&#x0049;", "&#x004F;", "&#x0050;", "&#x00DA;", "&#x0029;", "&#x005C;",
                        "&#x0041;", "&#x0053;", "&#x0044;", "&#x0046;", "&#x0047;", "&#x0048;", "&#x004A;", "&#x004B;", "&#x004C;", "&#x016E;", "&#x00A7;", Array("&#x00A8;", "Umlaut"),
                        "&#x005A;", "&#x0058;", "&#x0043;", "&#x0056;", "&#x0042;", "&#x004E;", "&#x004D;", "&#x002C;", "&#x002E;", "&#x002D;");

var Cz_shift = new Array(Array("&#x00BA;", "Ring"), "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x0025;", Array("&#x02C7;", "Caron"),
                         "&#x0051;", "&#x0057;", "&#x0045;", "&#x0052;", "&#x0054;", "&#x0059;", "&#x0055;", "&#x0049;", "&#x004F;", "&#x0050;", "&#x002F;", "&#x0028;", "&#x007C;",
                         "&#x0041;", "&#x0053;", "&#x0044;", "&#x0046;", "&#x0047;", "&#x0048;", "&#x004A;", "&#x004B;", "&#x004C;", "&#x0022;", "&#x0021;", "&#x0027;",
                         "&#x005A;", "&#x0058;", "&#x0043;", "&#x0056;", "&#x0042;", "&#x004E;", "&#x004D;", "&#x003F;", "&#x003A;", "&#x005F;");

var Cz_alt_gr = new Array(Array("&#x0060;", "Grave"), "&#x0021;", "&#x0040;", "&#x0023;", "&#x0024;", "&#x0025;", "&#x005E;", "&#x0026;", "&#x002A;", "&#x0028;", "&#x0029;", "&#x002D;", "&#x003D;",
                          "", "", "&#x20AC;", "", "", "", "", "", "", "", "&#x005B;", "&#x005D;", "&#x00DF;", "", "", "", "", "", "", "", "", "", "&#x003B;", "&#x00A4;", "&#x005C;",
                          "", "", "", "", "", "", "", "&#x003C;", "&#x003E;", "&#x002F;");

var Cz_alt_gr_shift = new Array(Array("&#x007E;", "Tilde"), "", "", "", "", "", "", "", "", "", "", "&#x005F;", "&#x002B;", "", "", "&#x20AC;", "", "", "", "", "", "", "", "&#x007B;", "&#x007D;",
                                Array("&#x00A8;", "Umlaut"), "", "", "", "", "", "", "", "", "", "&#x003A;", Array("&#x005E;", "Circumflex"), "&#x007C;", "", "", "", "", "", "", "", "&#x00D7;", "&#x00F7;", "&#x003F;");

// Greek:

var El_normal = new Array("&#x0091;", "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x002D;", "&#x003D;",
                          "&#x003B;", "&#x03C2;", "&#x03B5;", "&#x03C1;", "&#x03C4;", "&#x03C5;", "&#x03B8;", "&#x03B9;", "&#x03BF;", "&#x03C0;", "&#x005B;", "&#x005D;", "&#x003C;",
                          "&#x03B1;", "&#x03C3;", "&#x03B4;", "&#x03C6;", "&#x03B3;", "&#x03B7;", "&#x03BE;", "&#x03BA;", "&#x03BB;", "&#x0092;", "&#x00B4;", "&#x005C;",
                          "&#x03B6;", "&#x03C7;", "&#x03C8;", "&#x03C9;", "&#x03B2;", "&#x03BD;", "&#x03BC;", "&#x002C;", "&#x002E;", "&#x002F;");

var El_caps = new Array("&#x0091;", "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x002D;", "&#x003D;",
                        "&#x003B;", "&#x03C2;", "&#x0395;", "&#x03A1;", "&#x03A4;", "&#x03A5;", "&#x0398;", "&#x0399;", "&#x039F;", "&#x03A0;", "&#x005B;", "&#x005D;", "&#x003C;",
                        "&#x0391;", "&#x03A3;", "&#x0394;", "&#x03A6;", "&#x0393;", "&#x0397;", "&#x039E;", "&#x039A;", "&#x039B;", "&#x0092;", "&#x00B4;", "&#x005C;",
                        "&#x0396;", "&#x03A7;", "&#x03A8;", "&#x03A9;", "&#x0392;", "&#x039D;", "&#x039C;", "&#x002C;", "&#x002E;", "&#x002F;");

var El_shift = new Array("&#x007E;", "&#x0021;", "&#x0040;", "&#x0023;", "&#x0024;", "&#x0025;", "&#x005E;", "&#x0026;", "&#x002A;", "&#x0028;", "&#x0029;", "&#x005F;", "&#x002B;",
                         "&#x003A;", "&#x02C6;", "&#x0395;", "&#x03A1;", "&#x03A4;", "&#x03A5;", "&#x0398;", "&#x0399;", "&#x039F;", "&#x03A0;", "&#x007B;", "&#x007D;", "&#x003E;",
                         "&#x0391;", "&#x03A3;", "&#x0394;", "&#x03A6;", "&#x0393;", "&#x0397;", "&#x039E;", "&#x039A;", "&#x039B;", "&#x00A8;", "&#x0022;", "&#x007C;",
                         "&#x0396;", "&#x03A7;", "&#x03A8;", "&#x03A9;", "&#x0392;", "&#x039D;", "&#x039C;", "&#x003C;", "&#x003E;", "&#x003F;");

var El_alt_gr = new Array("", "", "&#x00B2;", "&#x00B3;", "&#x00A3;", "&#x00A7;", "&#x00B6;", "", "&#x00A4;", "&#x00A6;", "&#x00B0;", "&#x00B1;", "&#x00BD;", "", "", "", "", "",
                          "", "", "", "", "", "&#x00AB;", "&#x00BB;", "", "", "", "", "", "", "", "", "", "", "&#x02C6;", "", "&#x00AC;", "", "", "", "", "", "", "", "", "", "");

// Hebrew:

var He_normal = new Array("&#x003B;", "&#x0031;", "&#x0032;", "&#x0033;", "&#x0034;", "&#x0035;", "&#x0036;", "&#x0037;", "&#x0038;", "&#x0039;", "&#x0030;", "&#x002D;", "&#x003D;",
                          "&#x002F;", "&#x0027;", "&#x05E7;", "&#x05E8;", "&#x05D0;", "&#x05D8;", "&#x05D5;", "&#x05DF;", "&#x05DD;", "&#x05E4;", "&#x005D;", "&#x005B;", "&#x005C;",
                          "&#x05E9;", "&#x05D3;", "&#x05D2;", "&#x05DB;", "&#x05E2;", "&#x05D9;", "&#x05D7;", "&#x05DC;", "&#x05DA;", "&#x05E3;", "&#x002C;", "&#x005C;",
                          "&#x05D6;", "&#x05E1;", "&#x05D1;", "&#x05D4;", "&#x05E0;", "&#x05DE;", "&#x05E6;", "&#x05EA;", "&#x05E5;", "&#x002E;");

var He_shift = new Array("&#x007E;", "&#x0021;", "&#x0040;", "&#x0023;", "&#x0024;", "&#x0025;", "&#x005E;", "&#x0026;", "&#x002A;", "&#x0029;", "&#x0028;", "&#x005F;", "&#x002B;",
                         "&#x002F;", "&#x0027;", "&#x05E7;", "&#x05E8;", "&#x05D0;", "&#x05D8;", "&#x05D5;", "&#x05DF;", "&#x05DD;", "&#x05E4;", "&#x007D;", "&#x007B;", "&#x007C;",
                         "&#x05E9;", "&#x05D3;", "&#x05D2;", "&#x05DB;", "&#x05E2;", "&#x05D9;", "&#x05D7;", "&#x05DC;", "&#x05DA;", "&#x003A;", "&#x0022;", "&#x007C;",
                         "&#x05D6;", "&#x05E1;", "&#x05D1;", "&#x05D4;", "&#x05E0;", "&#x05DE;", "&#x05E6;", "&#x003C;", "&#x003E;", "&#x003F;");

var He_alt_gr = new Array("", "", "", "", "", "", "", "", "", "", "", "&#x05BE;", "", "", "", "", "", "", "", "&#x05F0;", "", "", "", "",
                          "", "", "", "", "", "", "", "&#x05F2;", "&#x05F1;", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "");

// Diacritic arrays:

var Acute = new Array(Array("&#x0061;", "&#x00E1;"), Array("&#x0065;", "&#x00E9;"), Array("&#x0069;", "&#x00ED;"), Array("&#x006F;", "&#x00F3;"),
                      Array("&#x0075;", "&#x00FA;"), Array("&#x0079;", "&#x00FD;"), Array("&#x0041;", "&#x00C1;"), Array("&#x0045;", "&#x00C9;"),
                      Array("&#x0049;", "&#x00CD;"), Array("&#x004F;", "&#x00D3;"), Array("&#x0055;", "&#x00DA;"), Array("&#x0059;", "&#x00DD;"),
                      Array("&#x0063;", "&#x0107;"), Array("&#x0043;", "&#x0106;"), Array("&#x006C;", "&#x013A;"), Array("&#x004C;", "&#x0139;"),
                      Array("&#x006E;", "&#x0144;"), Array("&#x004E;", "&#x0143;"), Array("&#x0072;", "&#x0155;"), Array("&#x0052;", "&#x0154;"),
                      Array("&#x0073;", "&#x015B;"), Array("&#x0053;", "&#x015A;"), Array("&#x007A;", "&#x017A;"), Array("&#x005A;", "&#x0179;"));

var Caron = new Array(Array("&#x0063;", "&#x010D;"), Array("&#x0043;", "&#x010C;"), Array("&#x0064;", "&#x010F;"), Array("&#x0044;", "&#x010E;"),
                      Array("&#x0065;", "&#x011B;"), Array("&#x0045;", "&#x011A;"), Array("&#x006E;", "&#x0148;"), Array("&#x004E;", "&#x0147;"),
                      Array("&#x0072;", "&#x0159;"), Array("&#x0052;", "&#x0158;"), Array("&#x0073;", "&#x0161;"), Array("&#x0053;", "&#x0160;"),
                      Array("&#x0074;", "&#x0165;"), Array("&#x0054;", "&#x0164;"), Array("&#x007A;", "&#x017E;"), Array("&#x005A;", "&#x017D;"),
                      Array("&#x006C;", "&#x013E;"), Array("&#x004C;", "&#x013D;"));

var Cedilla = new Array(Array("&#x0063;", "&#x00E7;"), Array("&#x0043;", "&#x00C7;"), Array("&#x0067;", "&#x0123;"), Array("&#x0047;", "&#x0122;"),
                        Array("&#x006B;", "&#x0137;"), Array("&#x004B;", "&#x0136;"), Array("&#x006C;", "&#x013C;"), Array("&#x004C;", "&#x013B;"),
                        Array("&#x006E;", "&#x0146;"), Array("&#x004E;", "&#x0145;"), Array("&#x0072;", "&#x0157;"), Array("&#x0052;", "&#x0156;"),
                        Array("&#x0073;", "&#x015F;"), Array("&#x0053;", "&#x015E;"), Array("&#x0074;", "&#x0163;"), Array("&#x0054;", "&#x0162;"));

var Circumflex = new Array(Array("&#x0061;", "&#x00E2;"), Array("&#x0041;", "&#x00C2;"), Array("&#x0065;", "&#x00EA;"), Array("&#x0045;", "&#x00CA;"),
                           Array("&#x0069;", "&#x00EE;"), Array("&#x0049;", "&#x00CE;"), Array("&#x006F;", "&#x00F4;"), Array("&#x004F;", "&#x00D4;"),
                           Array("&#x0063;", "&#x0109;"), Array("&#x0043;", "&#x0108;"), Array("&#x0067;", "&#x011D;"), Array("&#x0047;", "&#x011C;"),
                           Array("&#x0068;", "&#x0125;"), Array("&#x0048;", "&#x0124;"), Array("&#x006A;", "&#x0135;"), Array("&#x004A;", "&#x0134;"),
                           Array("&#x0073;", "&#x015D;"), Array("&#x0053;", "&#x015C;"), Array("&#x0075;", "&#x00FB;"), Array("&#x0055;", "&#x00DB;"),
                           Array("&#x0077;", "&#x0175;"), Array("&#x0057;", "&#x0174;"), Array("&#x0079;", "&#x0177;"), Array("&#x0059;", "&#x0176;"));

var Grave = new Array(Array("&#x0061;", "&#x00E0;"), Array("&#x0065;", "&#x00E8;"), Array("&#x0069;", "&#x00EC;"), Array("&#x006F;", "&#x00F2;"), Array("&#x0075;", "&#x00F9;"),
                      Array("&#x0041;", "&#x00C0;"), Array("&#x0045;", "&#x00C8;"), Array("&#x0049;", "&#x00CC;"), Array("&#x004F;", "&#x00D2;"), Array("&#x0055;", "&#x00D9;"));

var Ring = new Array(Array("&#x0061;", "&#x00E5;"), Array("&#x0041;", "&#x00C5;"), Array("&#x0075;", "&#x016F;"), Array("&#x0055;", "&#x016E;"));

var Tilde = new Array(Array("&#x0061;", "&#x00E3;"), Array("&#x006F;", "&#x00F5;"), Array("&#x006E;", "&#x00F1;"), Array("&#x0041;", "&#x00C3;"), Array("&#x004F;", "&#x00D5;"),
                      Array("&#x0069;", "&#x0129;"), Array("&#x0049;", "&#x0128;"), Array("&#x0075;", "&#x0169;"), Array("&#x0055;", "&#x0168;"), Array("&#x004E;", "&#x00D1;"));

var Umlaut = new Array(Array("&#x0061;", "&#x00E4;"), Array("&#x0065;", "&#x00EB;"), Array("&#x0069;", "&#x00EF;"), Array("&#x006F;", "&#x00F6;"), Array("&#x0075;", "&#x00FC;"),
                       Array("&#x0079;", "&#x00FF;"), Array("&#x0041;", "&#x00C4;"), Array("&#x0045;", "&#x00CB;"), Array("&#x0049;", "&#x00CF;"), Array("&#x004F;", "&#x00D6;"), 
                       Array("&#x0055;", "&#x00DC;"), Array("&#x0059;", "&#x0178;"));