// This file contains code in connection with the WMI2 calculator

// Variables

var ifv = new String("..#");  // input field value unformatted
var ifv_bak = false;  // backup of input field value unformatted
var ifvs = new Array();  // input field value history array
var ifvprev = 0;  // index of previous input field value
var ifvlast = 0;  // index of last input field value
var buttons;  // array of 40, from ajax
var group;  // array of group, from ajax
var groupby;  // how many elements in a row in group, from ajax
var groupcount;  // how many elements altogether in group, from ajax
var grouplock = false;  // if true, no group-loader ajax call can be done
var grouplock2 = false; // if true, group-loader ajax calls have no effect
var timer;  // for displaying button group
var timer2;  // for destroying button group
var groupindisplay = -1;  // which of 40 for display/destroy group
var buttoncolor;  // colors of types of buttons array
var buttonbackground;  // background colors of types of buttons array
var introtext;  // this text comes from database when a new layout loads
var theinputispink = false;  // true if the formula couldn't be showed
var wmibear = false;  // true if wmi bear picture is on
var worksheetnew = 1;  // index of current entry on worksheet
var lastaction = "button"; // "button"/"key" hack to show long inputs
var prevaction = false; // variable in connection with maximaPress function
var prevbutton = false; // variable in connection with maximaPress function
var created = 0; // variable for the showLayout function
var befunloadmess = '';  // before window unload message
var freshsaved = false;

// Functions

// Counts the number of parameters of a maxima button from its changestring
function cntMaximaParams(changestring)
{
  var cs = changestring;
  var cs_l = cs.length;
  var cs_c = 0;

  if (cs.indexOf('[#]') != -1)
  {
    return 'list';
  }
  var cs_i = cs.indexOf('#');
  while (cs_i != -1)
  {
    cs_c++;
    if (cs_i+1 < cs_l) {
      cs_i = cs.indexOf('#',cs_i+1);
    } else {
      cs_i = -1;
    }
  }
  return cs_c;
}

// Counts the input parameters (','s which are not between [])
function cntCalcParams(ifield)
{
  var opening = 0;
  var commas = 0;
  var inputf = ifield;
  for (lv = 0; lv < inputf.length; lv++)
  {
    switch (inputf[lv])
    {
      case '[':
        opening++;
        break;
      case ']':
        if (opening > 0) {
          opening--;
        } else {
          return -1;
        }
        break;
      case ',':
        if (opening == 0) {
          commas++;
        }
        break;
      default:
        break;
    }
  }
  return commas+1;
}

// Returns true if a character is a digit
function isDigit(character)
{
  if ((character >= "0")&&(character <= "9")) 
  { 
    return true;
  } else { 
    return false;
  }
}

// Because of network communication, and formconv compatibility
// the value should be coded before sent to the server
function codeFormula(value)
{
  value = value.replace(".|",".0");
  value = value.replace("|","");
  value = value.replace(/aa/g,"aaa");
  value = value.replace(/\.\./g," aa ");
  value = value.replace(/bb/g,"bbb");
  if (value.indexOf("aa") == -1) {
    value = value.replace("#"," bb ");
  }
  value = value.replace(/#/g,"");
  value = escape(value);
  value = value.replace(/\+/g,"%2B");
  return value;
}

// A general function to escape a value for the network communication
function escapeValue(value)
{
  value = escape(value);
  value = value.replace(/\+/g,"%2B");
  return value;
}

// Some parts of the formula string should not be seen on the screen
function formatFormula(value)
{
  value = value.replace(".|",".0");
  value = value.replace("|","");
  value = value.replace(/\.\.#/g,"..");
  value = value.replace(/#$/,"");
  value = value.replace(/#/g,"_");
  return value;
}

// This function is called on the calculator erase button (ce)
function eraseInput()
{
  ifv = new String("..#");
  ifvprev = 0;
  ifvlast = 0;
  ifvs[ifvprev] = new String("..#");
  document.getElementById("theinput").value = formatFormula(ifv);
  lastaction = "button";
  var converted_value = codeFormula(ifv);
  ajaxRefreshImage("ui"+worksheetnew,converted_value,150,"true");
}

// This function starts a new entry on the worksheet
function newInput()
{
  ifv = new String("..#");
  ifvprev = 0;
  ifvlast = 0;
  ifvs[ifvprev] = new String("..#");
  document.getElementById("theinput").value = formatFormula(ifv);
  lastaction = "button";
  worksheetnew++;
  ajaxLoadNew(worksheetnew);
}

// This function refreshes the input formula (image) on the worksheet
function refreshInput()
{
  document.getElementById("theinput").value = formatFormula(ifv);
  lastaction = "button";
  var converted_value = codeFormula(ifv);
  ajaxRefreshImage("ui"+worksheetnew,converted_value,150,"true");
  document.getElementById("codiv"+worksheetnew).scrollIntoView(true);
  document.getElementById("uidivt"+worksheetnew).innerHTML = ifv;
  document.getElementById("theinput").focus();
}

// This runs when syntactically wrong button is pressed on the calculator
function wrongSyntax()
{
  var fres = function(restext) {
    alert(restext);
  }
  ajaxMessage("calc_wrongbutton",fres);
}

// This runs when a maxima button is pressed and produces an output formula
function maximaPress(operation,opbutton)
{
  prevaction = operation;
  prevbutton = opbutton;
  var converted_value = codeFormula(ifv);
  ajaxRefreshImage("ui"+worksheetnew,converted_value,150,"false");
  if (converted_value.indexOf("aa") == -1) {
    var conv_op = escapeValue(operation);
    ajaxLoadImage(worksheetnew,converted_value,150,conv_op,opbutton);
    document.getElementById("codiv"+worksheetnew).scrollIntoView(true);
    newInput();
    document.getElementById("theinput").focus();
  } else {
    wrongSyntax();
  }
}

// This funtion starts refreshing the input formula
function refreshInputStart()
{
  ifv = document.getElementById("theinput").value;
  ifvprev++;
  ifvs[ifvprev] = ifv;
  ifvlast = ifvprev;
  refreshInput();
}

// This function runs if an ENTER key is pressed on the calculator input field
function enterPress()
{
  if (prevaction == false)
  {
    if ((ongoingrefresh == false) && (theinputispink == false)) {
      var maxpar = cntMaximaParams('ev(#)');
      if ((maxpar == cntCalcParams(formatFormula(ifv))) || (maxpar == 'list')) {
        if (wmibear == true)
          document.getElementById("topleft").style.backgroundImage = "url(./image/tlbba.png)";
        maximaPress('ev(#)','ev');
      } else {
        if (maxpar == -1) {
          wrongSyntax();
        } else {
          var funcres = function(restext) {
            alertcont = restext.replace("[PAR]",maxpar);
            alert(alertcont);
          }
          ajaxMessage("calc_params",funcres);
        }
      }      
    }
  }
  else
  {
    if ((ongoingrefresh == false) && (theinputispink == false)) {
      var maxpar = cntMaximaParams(prevaction);
      if ((maxpar == cntCalcParams(formatFormula(ifv))) || (maxpar == 'list')) {
        if (wmibear == true)
          document.getElementById("topleft").style.backgroundImage = "url(./image/tlbba.png)";
        maximaPress(prevaction,prevbutton);
      } else {
        if (maxpar == -1) {
          wrongSyntax();
        } else {
          var funcres = function(restext) {
            alertcont = restext.replace("[PAR]",maxpar);
            alert(alertcont);
          }
          ajaxMessage("calc_params",funcres);
        }
      }
    }
  }
}

// This function makes the internally stored input field value capable of
// editing with the calculator
function ifvEnding()
{
  switch (ifv.charAt(ifv.length-1))
  {
    case '+': case '-': case '*': case '/': case '^':
      ifv = ifv+"..#";
      break;
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
      ifv = ifv+"|#";
      break;
    default:
      ifv = ifv+"#";
      break;
  }
}

// This function refreshes the input formula on the worksheet on a keypress
function refreshInputKey()
{
  var value = document.getElementById("theinput").value;
  value = value.replace(/\.\./g,"");
  value = value.replace(/_/g,"");
  ifv = value;
  if(lastaction == "button") {
    document.getElementById("theinput").value = formatFormula(ifv);
  }
  ifvEnding();
  ifvprev++;
  ifvs[ifvprev] = ifv;
  ifvlast = ifvprev;
  lastaction = "key";
  var converted_value = codeFormula(ifv);
  ajaxRefreshImage("ui"+worksheetnew,converted_value,150,"true");
  document.getElementById("codiv"+worksheetnew).scrollIntoView(true);
  document.getElementById("uidivt"+worksheetnew).innerHTML = ifv;
}

// This function is for creating a button in group div
function groupButton(id,button,label)
{
  var newbutton = document.createElement("a");
  newbutton.setAttribute("class","groupbutton");
  newbutton.setAttribute("className","groupbutton");
  if (groupcount > id) {
    if (group[id][5] != "") {
      newbutton.setAttribute("title",group[id][5]);
    }
  }
  var ds = function(event) {
    window.defaultStatus = '';
  }
  var nboc = function(event) {
    groupClick(id,button);
  }
  newbutton.onclick = nboc;
  var content = document.createElement("div");
  content.setAttribute("class","button");
  content.setAttribute("className","button");
  content.innerHTML = 
  "<font face='Arial, Verdana, sans-serif'>"+
  label
  +"</font>"
  ;
  content.style.cursor = "pointer";
  if (id < groupcount) {
    newbutton.style.color = buttoncolor[group[id][2]];
    newbutton.style.backgroundColor = buttonbackground[group[id][2]];
  } else {
    newbutton.style.color = "#00156c";
    newbutton.style.backgroundColor = "#00156c";
  }
  newbutton.appendChild(content);
  this.dom = newbutton;
}

// This function is for creating a visible button on the calculator
function calcButton(id)
{
  var newbutton = document.createElement("a");
  newbutton.setAttribute("id","btn"+id);
  newbutton.setAttribute("class","button");
  newbutton.setAttribute("className","button");
  if (buttons[id][5] != "") {
    newbutton.setAttribute("title",buttons[id][5]);
  }
  var ds = function(event) {
    window.defaultStatus = '';
  }
  newbutton.onmouseover = ds;
  newbutton.onmouseout = ds;
  var nboc = function(event) {
    buttonClick(id);
  }
  newbutton.onclick = nboc;
  var content1 = document.createElement("div");
  if (buttons[id][3] != "") {
    var content2 = document.createElement("div");
    content2.setAttribute("class","buttonimg");
    content2.setAttribute("className","buttonimg");
    var groupimg = document.createElement("img");
    groupimg.setAttribute("id","btnimg"+id);
    groupimg.setAttribute("name","btnimg"+id);
    groupimg.setAttribute("class","group");
    groupimg.setAttribute("className","group");
    groupimg.setAttribute("src","./image/groupsign.gif");
    groupimg.onmouseover = displayGroup;
    groupimg.onmouseout = hideGroup;
    content2.appendChild(groupimg);
    content2.style.cursor = "pointer";
    newbutton.appendChild(content2);
  }
  var content1 = document.createElement("div");    
  content1.setAttribute("class","button");
  content1.setAttribute("className","button");
  content1.innerHTML = 
  "<font face='Arial, Verdana, sans-serif'>"+
  buttons[id][4]
  +"</font>"
  ;
  content1.style.cursor = "pointer";
  newbutton.appendChild(content1);
  if (buttons[id][0] != "") {
    newbutton.style.color = buttoncolor[buttons[id][2]];
    newbutton.style.backgroundColor = buttonbackground[buttons[id][2]];
  } else {
    newbutton.style.color = "#00156c";
    newbutton.style.backgroundColor = "#00156c";
  }
  newbutton.style.cursor = "pointer";
  this.dom = newbutton;
}

// This function creates a layout HTML (the buttons variable describes it)
function createCalcHTML(indiv)
{
  var calcform = document.createElement("form");
  calcform.setAttribute("id","calcform");
  calcform.setAttribute("name","calcform");
  calcform.onsubmit = function(event) {
    return false;
  }
  var theinput = document.createElement("input");
  theinput.setAttribute("class","input");
  theinput.setAttribute("className","input");
  theinput.setAttribute("type","text");
  theinput.setAttribute("id","theinput");
  theinput.setAttribute("name","theinput");
  var tikp = function(ev) {
    ifv_bak = false;
    var eventobj = window.event ? window.event : ev;
    var unicode = eventobj.charCode ? eventobj.charCode : eventobj.keyCode;
    switch (unicode)
    {
      case 37:case 38:case 39:case 40:
        lastaction = "key";
        break;
      case 13:
        enterPress();
        break;
      default:
        refreshInputKey();
        break;
    }
  }
  theinput.onkeyup = tikp;
  var alertmy = function(ev) {
    ifv_bak = ifv;
    lastaction = "key";
    var valuex = this.value;
    valuex = valuex.replace(/\.\./g,"");
    valuex = valuex.replace(/_/g,"");
    if (valuex != this.value)
    {
      ifv = valuex;
      this.value = formatFormula(ifv);
      ifvEnding();
    }
  }
  theinput.onclick = alertmy;
  calcform.appendChild(theinput);
  var thetable = document.createElement("table");
  thetable.setAttribute("id","thetable");
  thetable.setAttribute("name","thetable");
  thetable.setAttribute("cellPadding","0px");
  thetable.setAttribute("cellSpacing","0px");
  thetable.insertRow(-1);
  thetable.rows[0].insertCell(-1);
  thetable.rows[0].cells[0].setAttribute("colSpan","5");
  thetable.rows[0].cells[0].appendChild(calcform);
  thetable.rows[0].cells[0].style.height = "30px";
  thetable.rows[0].cells[0].style.verticalAlign = "top";
  for (i = 0; i < 8; i++) {
    thetable.insertRow(-1);
    for (j = 0; j < 5; j++) {
      thetable.rows[i+1].insertCell(-1);      
      thetable.rows[i+1].cells[j].appendChild(
      new calcButton(i*5+j).dom);
    }
  }
  document.getElementById(indiv).appendChild(thetable);
  document.getElementById("theinput").value = formatFormula(ifv);
}

// This function shows a calculator layout (after it is loaded with images)
function showLayout()
{
  created++;
  if (created == 2) {
    document.getElementById("calcdiv").style.visibility = "visible";
    document.getElementById("theinput").focus();
  }
}

// This function changes the layout to 'layout'
function changeLayout(layout)
{
  hideLayout();
  ajaxLIPreload(layout);
  ajaxLoadLayout(layout);

  var ih = document.getElementById("uidivt"+worksheetnew).innerHTML;
  if ((ih == "..#") && (worksheetnew == 1))
  {
    var remv = document.getElementById("uidiv1");
    document.getElementById("workspace").removeChild(remv);
    remv = document.getElementById("codiv1");
    document.getElementById("workspace").removeChild(remv);
    ajaxLayoutMessage(layout);
    ajaxLoadNew(1);
    ajaxRefreshImage("ui1",codeFormula("..#"),150,"true");
  }
}

// This function loads a new calculator layout
function loadLayout(indiv)
{
  if (document.getElementById(indiv).hasChildNodes())
  {
    var thetablex = document.getElementById("thetable");
    var remn = document.getElementById(indiv).removeChild(thetablex);
  }
  createCalcHTML(indiv);
  showLayout();
}

// This function hides a calculator layout
function hideLayout()
{
  created = 0;
  document.getElementById("calcdiv").style.visibility = "hidden";
}

// Decides if a position in ifv is inside a vector or matrix, don't care with
// syntax errors: before position, more opening than closing []s
function inVector(position)
{
  var opening = 0;
  for (lv = 0; lv < position; lv++)
  {
    switch (ifv[lv])
    {
      case '[':
        opening++;
        break;
      case ']':
        if (opening > 0) {
          opening--;
        } else {
          return false;
        }
        break;
      default:
        break;
    }
  }
  if (opening > 0)
    return true;
  return false;
}

// This function controls the effects of clicks from the 40 visible buttons
// It identifies the button type and/or label, and does the effect
function buttonClick(id)
{
  clearTimeout(timer);
  if (ifv_bak != false) {
    ifv = ifv_bak;
    ifv_bak = false;
  }
  var concat = ifv.indexOf("#");
  var empty = ifv.indexOf("..");
  var cursorplace = ifv.indexOf("|");

  var val = document.getElementById("theinput").value;
  if ((concat == -1)&&(empty == -1)) {
    if (val.charAt(val.length-1) == "+" || val.charAt(val.length-1) == "*" ||
    val.charAt(val.length-1) == "-" || val.charAt(val.length-1) == "/" ||
    val.charAt(val.length-1) == "^") {
      ifv = document.getElementById("theinput").value+"..#";
      concat = ifv.indexOf("#");
      empty = ifv.indexOf("..");
    } else {
      ifv = document.getElementById("theinput").value+"#";
      concat = ifv.indexOf("#");
    }
  }

  var cv;
  switch (buttons[id][2])
  {
  case "maxima":
    break;
  case "gnuplot":
  case "complex":
    break;
  case "relation":
  case "special":
  case "control":
    switch (buttons[id][0])
    {
    case "ce":
      grouplock = false;
      grouplock2 = false;
      ongoingrefresh = false;
      nextrefresh = false;
      eraseInput();
      break;
    case "off":
      document.getElementById("calcdiv").style.display = "none";
      document.getElementById("menudiv").style.display = "block";
      break;
    case "back":
      if (ifvprev > 0) {
        ifvprev--;
      }
      ifv = ifvs[ifvprev];
      break;
    case "redo":
      if (ifvprev < ifvlast) {
        ifvprev++;
      }
      ifv = ifvs[ifvprev];
      break;
    case "solve":
      break;
    case "eval":
      break;
    case "cycle":
      break;
    case "]":
    case ")":
      if (cursorplace != -1) {
        ifv = ifv.replace("|#","");
        ifv = ifv.replace("|","");
      } else if (concat < ifv.length-1) {
        ifv = ifv.replace("#","");
      }
      break;
    case "(":
      if (empty != -1) {
        ifv = ifv.replace("..","(..#)");
      } else {
        wrongSyntax();
      }
      break;
    case "[":
      if (empty != -1) {
        ifv = ifv.replace("..","[..#]");
      } else {
        wrongSyntax();
      }
      break;
    case "(-)": 
      if (empty != -1) {
        ifv = ifv.replace("..","(-..)");
      } else {
        wrongSyntax();
      }
      break;
    case ".":
      if (cursorplace != -1) {
        cv = cursorplace-1;
        while (cv>=0) {
          if (!isDigit(ifv.charAt(cv))) break;
          --cv;
        }
        if (((cv < 0)||((ifv.charAt(cv) != ".")&&(ifv.charAt(cv) != "e")))
        &&(cursorplace-1>cv)) {
          ifv = ifv.replace("|",".|");
        } else {
          wrongSyntax();
        }
      } else {
        wrongSyntax();
      }
      break;
    case "EXP":
      ifv = ifv.replace("|",buttons[id][1]);
      break;
    case "%":
      ifv = ifv.replace("|",buttons[id][1]);
      break;
    case "equality":
      var commaind = ifv.lastIndexOf(",");
      var equalind = ifv.lastIndexOf("=");
      if ((concat == ifv.length-1)&&(empty == -1)&&(commaind >= equalind)) {
        ifv=ifv.replace("#","=..#");
      } else {
        wrongSyntax();
      }
      break;
    case ",":
      if ((concat == ifv.length-1)&&(empty == -1)) {
        ifv=ifv.replace("#",",..#");
      } else if (inVector(concat)&&(empty == -1)) {
        ifv=ifv.replace("#",",..#");
      } else {
        wrongSyntax();
      }
      break;
    default:
      if (buttons[id][3] == "layout") {
        layout = buttons[id][0];
        changeLayout(layout);
      } else if (buttons[id][3] == "lang") {
        ajaxSetLanguage(buttons[id][0]);
        changeLayout("default");
      }
      break;
    }
    break;
  case "digit":
    if (cursorplace != -1) {
      ifv = ifv.replace("|",buttons[id][1]);
    } else if (empty != -1) {
      ifv = ifv.replace("..",buttons[id][1]);
    } else {
      wrongSyntax();
    }
    break;
  case "fun1":
  case "fun2":
  case "var":
  case "const":
    if (empty != -1) {
      ifv = ifv.replace("..",buttons[id][1]);
    } else {
      wrongSyntax();
    }
    break;
  case "op1":
  case "op2":
    if ((concat != -1)&&((empty == -1)||(empty > concat))) {
      ifv = ifv.replace("#",buttons[id][1]);
    } else {
      wrongSyntax();
    }
    break;
  case "test":
  default:
    break;
  }

  if ((buttons[id][3] != "layout") && (buttons[id][3] != "lang")) {
    // Destroy cursor when digit typing ends
    if ((buttons[id][2] != "digit")&&(buttons[id][2] != "control")&&(buttons[id][0] != ".")&&(buttons[id][0] != "EXP")) {
      if (!(ongoingrefresh == true && buttons[id][2] == "maxima")) {
        if (ifv.charAt(cursorplace-1) == ".") ifv = ifv.replace("|","0");
        else ifv = ifv.replace("|","");
      }
    }
    if (buttons[id][2] == "gnuplot") {
      if (ongoingrefresh == false && theinputispink == false) {
        if (buttons[id][0] == "funpl") {
          if (document.getElementById("theinput").value != formatFormula(ifv)) {
            refreshInputStart();
          }
          if (wmibear == true)
            document.getElementById("topleft").style.backgroundImage = "url(./image/tlbba.png)";
          var converted_value = codeFormula(ifv);
          ajaxRefreshImage("ui"+worksheetnew,converted_value,150,"false");
          if (converted_value.indexOf("aa") == -1) {
            ajaxLoadPlot(worksheetnew,converted_value,-10,10,-10,10,'on','false');
            document.getElementById("codiv"+worksheetnew).scrollIntoView(true);
            newInput();
            document.getElementById("theinput").focus();
          } else {
            wrongSyntax();
          }
        } else if (buttons[id][0] == "pplot") {
          if (document.getElementById("theinput").value != formatFormula(ifv)) {
            refreshInputStart();
          }
          if (cntCalcParams(formatFormula(ifv)) == 2) {
            if (wmibear == true)
              document.getElementById("topleft").style.backgroundImage = "url(./image/tlbba.png)";
            var converted_value = codeFormula(ifv);
            ajaxRefreshImage("ui"+worksheetnew,converted_value,150,"false");
            if (converted_value.indexOf("aa") == -1) {
              ajaxLoadPlot(worksheetnew,converted_value,-10,10,-10,10,'on','true');
              document.getElementById("codiv"+worksheetnew).scrollIntoView(true);
              newInput();
              document.getElementById("theinput").focus();
            } else {
              wrongSyntax();
            }
          } else {
            if (buttons[id][6] != '') {
              alert(buttons[id][6]);
            } else {
              var funcres = function(restext) {
                alertcont = restext.replace("[PAR]",2);
                alert(alertcont);
              }
              ajaxMessage("calc_params",funcres);
            }
          }
        } else if (buttons[id][0] == "plot3") {
          if (document.getElementById("theinput").value != formatFormula(ifv)) {
            refreshInputStart();
          }
          if (wmibear == true)
            document.getElementById("topleft").style.backgroundImage = "url(./image/tlbba.png)";
          var converted_value = codeFormula(ifv);
          ajaxRefreshImage("ui"+worksheetnew,converted_value,150,"false");
          if (converted_value.indexOf("aa") == -1) {
            ajaxLoad3DPlot(worksheetnew,converted_value,-10,10,-10,10,'on','false',60,30);
            document.getElementById("codiv"+worksheetnew).scrollIntoView(true);
            newInput();
            document.getElementById("theinput").focus();
          } else {
            wrongSyntax();
          }
        }
      }
    } else if (buttons[id][2] == "complex") {
      if (ongoingrefresh == false && theinputispink == false) {
        if (buttons[id][0] == "cplot") {
          if (document.getElementById("theinput").value != formatFormula(ifv)) {
            refreshInputStart();
          }
          if (wmibear == true)
            document.getElementById("topleft").style.backgroundImage = "url(./image/tlbba.png)";
          var converted_value = codeFormula(ifv);
          ajaxRefreshImage("ui"+worksheetnew,converted_value,150,"false");
          if (converted_value.indexOf("aa") == -1) {
            ajaxLoadCPlot(worksheetnew,converted_value,-10,10,-10,10);
            document.getElementById("codiv"+worksheetnew).scrollIntoView(true);
            newInput();
            document.getElementById("theinput").focus();
          } else {
            wrongSyntax();
          }
        }
      }
    } else if (buttons[id][2] == "maxima") {
      if (ongoingrefresh == false && theinputispink == false) {
        var maxpar = cntMaximaParams(buttons[id][1]);
        if (maxpar == cntCalcParams(formatFormula(ifv)) || maxpar == 'list') {
          if (document.getElementById("theinput").value != formatFormula(ifv)) {
            refreshInputStart();
          }
          if (wmibear == true)
            document.getElementById("topleft").style.backgroundImage = "url(./image/tlbba.png)";
          maximaPress(buttons[id][1],buttons[id][0]);
        } else {
          if (maxpar == -1) {
            wrongSyntax();
          } else {
            if (buttons[id][6] != '') {
              alert(buttons[id][6]);
            } else {
              var funcres = function(restext) {
                alertcont = restext.replace("[PAR]",maxpar);
                alert(alertcont);
              }
              ajaxMessage("calc_params",funcres);
            }
          }
        }
      }
    } else if (buttons[id][0] == "back" || buttons[id][0] == "redo") {
      refreshInput();
    } else {
      if (wmibear == true)
        document.getElementById("topleft").style.backgroundImage = "url(./image/tlbbq.png)";
      ifvprev++;
      ifvs[ifvprev] = ifv;
      ifvlast = ifvprev;
      refreshInput();
    }
  }
}

// This function loads the button group of a visible button into a place
function loadGroup(button,cx,cy)
{
  var groupdiv = document.createElement("div");
  groupdiv.setAttribute("id","groupdiv");
  groupdiv.setAttribute("class","groupdiv");
  groupdiv.setAttribute("className","groupdiv");
  groupdiv.onmouseover = displayGroup;
  groupdiv.onmouseout = hideGroup;
  var grouptable = document.createElement("table");
  grouptable.setAttribute("id","grouptable");
  grouptable.setAttribute("name","grouptable");
  grouptable.setAttribute("cellPadding","0px");
  grouptable.setAttribute("cellSpacing","0px");
  var grouprow, groupcol, count;
  for (count = 0; count < groupcount; count++)
  {
    grouprow = Math.floor(count/groupby);
    groupcol = count%groupby;
    if (count%groupby == 0) grouptable.insertRow(-1);
    grouptable.rows[grouprow].insertCell(-1);
    grouptable.rows[grouprow].cells[groupcol].appendChild(
      new groupButton(count,button,group[count][4]).dom);
  }
  while (count%groupby!=0)
  {
    grouprow = Math.floor(count/groupby);
    groupcol = count%groupby;
    grouptable.rows[grouprow].insertCell(-1);
    grouptable.rows[grouprow].cells[groupcol].appendChild(
      new groupButton(count,button,group[groupcount][4]).dom);
    count++;
  }
  groupdiv.appendChild(grouptable);
  var gdwidth = groupby*56+8;
  var gdheight = Math.floor((groupcount+groupby-1)/groupby)*36+8;
  groupdiv.style.top = cy - gdheight;
  groupdiv.style.left = cx;
  document.body.appendChild(groupdiv);
  groupindisplay = button;
}

// This function destroys the div with the button group
function destroyGroup()
{
  var grpdiv = document.getElementById("groupdiv");
  document.body.removeChild(grpdiv);
  groupindisplay = -1;
}

// This function controls the effects of clicks from the group buttons
function groupClick(grp,btn)
{
  if (grp < groupcount) {
    buttons[btn] = group[grp];
    destroyGroup();
    document.getElementById("thetable").rows[Math.floor(btn/5)+1].cells[btn%5].removeChild(document.getElementById("btn"+btn));
    document.getElementById("thetable").rows[Math.floor(btn/5)+1].cells[btn%5].appendChild(new calcButton(btn).dom);
    buttonClick(btn);
  }
}

// This tells if a HTML element is an ancestor of an other in the DOM tree
function isIn(big,little)
{
  try {
    if (little == big)
      return true;
    while (little.parentNode) {
      little = little.parentNode;
      if (little == big) {
        return true;
      }
    }
    return false;
  } catch (ex) {
    return false;
  }
}

// This function is for the timing of the loading of the button group
function loadGroupL(button,cx,cy)
{
  if (grouplock == false) {
    grouplock = true;
    grouplock2 = false;
    ajaxLoadGroup(buttons[button][3],button,cx,cy);
  }
}

// This function issues displaying a button group
function displayGroup(event)
{
  var cx,cy,src;
  if (window.event) {
    cx = window.event.clientX - window.event.offsetX;
    cy = window.event.clientY - window.event.offsetY;
    src = window.event.srcElement;
  } else {
    cx = event.clientX - event.layerX;
    cy = event.clientY - event.layerY;
    src = event.target;
  }
  var groupdiv = document.getElementById("groupdiv");
  var button = new String(src.id);
  if (button.length > 6) button = button.substr(6);
  if (!((groupindisplay == button)||(isIn(groupdiv,src)))) {
    timer = setTimeout("loadGroupL("+button+","+cx+","+cy+")",1000);
  } else {
    clearTimeout(timer2);
  }
}

// This function issues destroying the div with a button group
function hideGroup(event)
{
  var ct, rt;
  if (window.event) {
    ct = this;
    rt = window.event.toElement;
  } else {
    ct = event.target;
    rt = event.relatedTarget;
  }
  var button = -1;
  if (ct.id != "")
    button = new String(ct.id).substr(6);

  var groupdiv = document.getElementById("groupdiv");
  if (groupindisplay == button) {
    if (!isIn(groupdiv,rt)) {
      timer2 = setTimeout("destroyGroup()",1000);
    }
  } else if (isIn(groupdiv,ct)) {
    if (!isIn(groupdiv,rt)) {
      var butt = -2;
      try {
        if (rt.id != "")
          butt = new String(rt.id).substr(6);
      } catch (ex) {
        butt = -2;
      }
      if (groupindisplay != butt) {
        timer2 = setTimeout("destroyGroup()",1000);
      }
    }
  } else {
    clearTimeout(timer);
    grouplock2 = true;
  }
}

// This can change the display of intro and WMI2 bear on some conditions
function setWmiBear(force,forceto,switching)
{
  var fromcookie;
  var bearcookie;
  if (switching == true) {
    forceto = !wmibear;
  }
  if (force == true) {
    fromcookie = false;
    bearcookie = true;
  } else {
    var start = document.cookie.indexOf("bear");
    if (start != -1) {
      start += 5;
      var end = document.cookie.indexOf(";",start);
      var cookiestring = document.cookie.substr(start,end-start);
      if (cookiestring == "true") {
        bearcookie = true;
        fromcookie = true;
      } else if (cookiestring == "false") {
        bearcookie = false;
        fromcookie = true;
      } else {
        fromcookie = false;
      }
    } else {
      fromcookie = false;
    }
  }
  var smallwindow;
  // if the height of the window is too small
  if (document.body.clientHeight <= 538)
    smallwindow = true;
  else
    smallwindow = false;
  if (((fromcookie && !bearcookie) || (!fromcookie && smallwindow)) &&
  forceto == null || forceto == false) {
    document.getElementById("topleft").style.background = "none";
    document.getElementById("topleft").style.height = "30px";
    document.getElementById("titletext").style.top = "10px";
    document.getElementById("wtop").style.display = "none";
    wmibear = false;
    if (!fromcookie) {
      var xdate = new Date();
      xdate.setTime(xdate.getTime()+30*24*3600*1000);
      document.cookie = "bear=false; expires="+xdate.toGMTString();
    }
  } else {
    document.getElementById("topleft").style.height = "200px";
    document.getElementById("topleft").style.backgroundImage = "url(./image/tlbbq.png)";
    document.getElementById("topleft").style.backgroundRepeat = "no-repeat";
    document.getElementById("topleft").style.backgroundPosition = "top left";
    document.getElementById("titletext").style.top = "180px";
    document.getElementById("wtop").style.display = "block";
    wmibear = true;
    if (!fromcookie) {
      var xdate = new Date();
      xdate.setTime(xdate.getTime()+30*24*3600*1000);
      document.cookie = "bear=true; expires="+xdate.toGMTString();
    }
  }
}

// gets the input formula from url query string, or ..#
function formulaFromQuery()
{
  var ls = location.search;
  var st = ls.indexOf("&input=");
  if (st == -1)
    st = ls.indexOf("?input=");
  if (st == -1)
    return "..#";
  var ed = ls.indexOf("&",st+7);
  if (ed == -1)
    return decodeURIComponent(ls.substring(st+7));
  return decodeURIComponent(ls.substring(st+7,ed));
}

// gets the input operation from url query string, or false
function operationFromQuery()
{
  var ls = location.search;
  var st = ls.indexOf("&button=");
  if (st == -1)
    st = ls.indexOf("?button=");
  if (st == -1)
    return false;
  var ed = ls.indexOf("&",st+8);
  if (ed == -1)
    return decodeURIComponent(ls.substring(st+8));
  return decodeURIComponent(ls.substring(st+8,ed));
}

// Loads WMI2 calculator at the first time
function loadFirst()
{
  setWmiBear(false,null,null);
  var formulamf = function(restext) {
    formulamessage = restext;
  }
  ajaxMessage("ws_formula",formulamf);
  ajaxMessage("ws_reallynew",function(rest) { ws_reallynewmess = rest; });
  ajaxButtonType();
  hideLayout();
  ajaxLIPreload("default");
  ajaxLoadLayout("default");
  ajaxLayoutMessage("default");
  ajaxLoadNew(1);
  ifv = formulaFromQuery();
  ifvs.push(ifv);
  var converted_value = codeFormula(ifv);
  ajaxRefreshImage("ui"+worksheetnew,converted_value,150,"true");
  if (ifv != "..#")
  {
    // wait other ajax calls
    var ifvprevious = ifv;
    ajaxPing(function(rt) {
      document.getElementById("uidivt1").innerHTML = ifvprevious;
    });
  }
  window.onbeforeunload = function(event) {
    if (((worksheetnew != 1) || (ifv != "..#")) && (freshsaved == false))
      event.returnValue = befunloadmess;
  }
  ajaxMessage("ws_exit", function(restext) { befunloadmess = restext; });

  var opop = operationFromQuery();
  if ((opop != false) && (ifv != "..#"))
  {
    switch (opop) {
      case "pplot":
        ajaxLoadPlot(worksheetnew,converted_value,-10,10,-10,10,'on','true');
        break;
      case "funpl":
        ajaxLoadPlot(worksheetnew,converted_value,-10,10,-10,10,'on','false');
        break;
      case "cplot":
        ajaxLoadCPlot(worksheetnew,converted_value,-10,10,-10,10);
        break;
      case "plot3":
        ajaxLoad3DPlot(worksheetnew,converted_value,-10,10,-10,10,'on','false',60,30);
        break;
      default:
        ajaxLoadImage(worksheetnew,converted_value,150,"server",opop);
        break;
    }
    ifv = new String("..#");
    ifvprev = 0;
    ifvlast = 0;
    ifvs[ifvprev] = new String("..#");
    lastaction = "button";
    worksheetnew++;
    ajaxLoadNew(2);
    document.getElementById("codiv"+worksheetnew).scrollIntoView(true);
    document.getElementById("theinput").focus();
    document.getElementById("theinput").value = formatFormula(ifv);
  }
}

// copies a former input formula back to the calculator
function toCalc(whichid) 
{
  var textformula = document.getElementById("uidivt"+whichid).innerHTML;
  if (ifv.indexOf("..") == -1) {
    ifv = textformula;
  } else {
    if (ifv.indexOf("..#") == -1) {
      ifv = ifv.replace("..",textformula);
    } else {
      ifv = ifv.replace("..#",textformula);
    }
  }
  ifv = ifv.replace("&gt;", ">");
  ifv = ifv.replace("&lt;", "<");
  ifvprev++;
  ifvs[ifvprev] = ifv;
  ifvlast = ifvprev;
  refreshInput();
  lastaction = "key";
}

// copies a former output formula back to the calculator
function toCalcRes(whichid)
{
  var textformula = document.getElementById("codivt"+whichid).innerHTML;
  if (ifv.indexOf("..") == -1) {
    ifv = textformula;
  } else {
    if (ifv.indexOf("..#") == -1) {
      ifv = ifv.replace("..",textformula);
    } else {
      ifv = ifv.replace("..#",textformula);
    }
  }
  ifv = ifv.replace("&gt;", ">");
  ifv = ifv.replace("&lt;", "<");
  ifvprev++;
  ifvs[ifvprev] = ifv;
  ifvlast = ifvprev;
  refreshInput();
  lastaction = "key";
}

