// $Revision: 4908 $

// user input field

/*Common functions*/

function GetNumberOfWordsToFinishString(numOfLine, text)
{
  var line = 0, i = 0, numOfWords = 0;
  
  for(; line < numOfLine + 1  &&  i < text.length; i++)
  {
    if(text.charAt(i) == '\n')
    {
      line++;
      numOfWords++;
    }
    if(text.charAt(i) == ' ')  numOfWords++;
  }
  return numOfWords;
}

function EmptySpan(letter)
{
  var style1 = "display: block; height: 1px; overflow: hidden; font-size: 1px; margin: 0 1px";
  var style2 = "padding: 0px 2px; margin: 0; font-weight: bold; height: 100%; font-family: Courier New; font-size: 12pt;";

  var letter_ = letter;
  
  if(letter_ == " ")  letter_ = "&nbsp;";

  var res = "<b style='" + style1 + "'></b>" +
		  "<div style='" + style2 + "'>" + letter_ +
		  "</div>" +
		  "<b style='" + style1 + "'></b>";  
  
  return res;
}

function GetWordBeginStrIndex(src, wordInd)
{
  var wI, i;
  for(wI = 0, i = 0; wI < wordInd && i < src.length; i++)
  {
    if(src.charAt(i) == " " || src.charAt(i) == "\n")  wI++;
  }

  return i;
}

function IsWordLastAtString(s, ind)
{
  var i;
  for(i = GetWordBeginStrIndex(s, ind); i < s.length; i++)
  {
    if(s.charAt(i) == ' ')  
    {
      return false;
    }
    if(s.charAt(i) == '\n')
    {
      return true;
    }
  }
}

function GetNumOfWords(str)
{
  var numOfWords = 0;
  for(i = 0; i < str.length; i++)
  {
    if(str.charAt(i) == " "  ||  str.charAt(i) == "\n") numOfWords++;
  }
  if(str.charAt(i-1) != "\n"  &&  str.charAt(i-1) != " "  &&  i == str.length)  numOfWords++; 
  return numOfWords;
}

function TInputField(id, strLength, numOfLines, numOfLinesBeforeCurrentLine)
{
  this.Id = id;
  this.LetterId = 'Letter';
  this.StrLength = strLength;
  this.NumOfLines = numOfLines;
  this.NumOfLinesBeforeCurrentLine = numOfLinesBeforeCurrentLine;
  
  this.Text = String("");
  this.InnerHTML = String("");
  
  this.Index = 0;
  
  this.SetText = SetText;
  this.SetCaret = SetCaret;
  this.Render = Render;
  this.PlaceHere = PlaceHere;
  this.SetLastChar = SetLastChar;
//  this.RenderMarkChar = RenderMarkChar;
  this.SetBkRedCurrentChar = SetBkRedCurrentChar;
  this.SetBkGreenCurrentChar = SetBkGreenCurrentChar;
  
  this.LetterSpan = LetterSpan;
  
  this.EmptyField = new TEmptyField("Text", "#f6f6f6");
  this.GetEmptyField = GetEmptyField;
  this.LastChar = -1;
  this.MarkError = false;
  this.BkCurrentCharColor = 'green';
  this.CurrentCharColor = 'white';
  
  this.GetStringId = GetStringId;
  this.GetLetterSpanId = GetLetterSpanId;
  
  this.SetCharColorBkColor = SetCharColorBkColor;
  this.SetCharBkColor = SetCharBkColor;
  this.SetCharColor = SetCharColor;
  
  this.GetIndex = GetIndex;
  this.GetCurLine = GetCurLine;
  
  this.StepForward = StepForward;
  this.GoToBegOfLine = GoToBegOfLine;
  this.SetError = SetError;
  this.ResetError = ResetError;
  this.GoToBeg = GoToBeg;
  
  this.CurLine = 0;
  this.PrevLine = 0;
  this.NumOfLinesAtText = 0; // num of lines at exercise
  this.WholeTextNumOfLines = 0;
  
  this.ShowElement = ShowElement;
  
  this.BWordsMode = false;
  
  this.GetCurLine = function()
  {
    return this.CurLine;
  }
  this.GetNumOfLinesAtText = function()
  {
    return this.WholeTextNumOfLines;
  }
  
  this.SetWordsMode = function(bMode)
  {
    this.BWordsMode = bMode;
  }
  
  this.GetWordNum = function(num)
  {
    var obj = document.getElementById(this.GetLetterSpanId(num));
    if(obj == undefined)
      return;
    
    return document.getElementById(this.GetLetterSpanId(num)).innerHTML;
  }
  
function PlaceHere()
{
  return BeginSpan('id', this.Id) + EndSpan();
}  
    
function GetEmptyField()
{
  return this.EmptyField;
} 

function GetLetterSpanId(i)
{
  return this.Id + this.LetterId + String(i);
}

function SetText(text)
{
  var obj = document.getElementById(this.Id);
  
  this.Text = text;
  
  for(i = 0; i < this.Text.length; i++)
  {
    this.InnerHTML += this.LetterSpan(i, this.Text.charAt(i));
  }
}

function GetText()
{
  return this.Text; 
}

function SetError()
{
  this.SetCharBkColor(this.Index, '#AB0000');
}

function ResetError()
{
  this.SetCharBkColor(this.Index, '');
}

this.RestoreCursor = function()
{
  this.SetCharColorBkColor(this.Index, "white", "green");
}

function SetLastChar(lastChar)
{
  this.LastChar = lastChar;
}

function SetBkRedCurrentChar()
{
  this.BkCurrentCharColor = 'red';
}

function SetBkGreenCurrentChar()
{
  this.BkCurrentCharColor = 'green';
}

function ShowElement(i, bShow)
{
  var obj = document.getElementById(this.GetStringId(i));
  if(bShow)  obj.style.display = "";
  else  obj.style.display = "none";
}

function SetCaret(index, bIsBackward)
{
  // change here the manner of vision...
  if(index == 0)  
  {
    this.CurLine = 0;
	  this.Index = 0;
    if(bIsBackward == true)  this.Render();
  }
  else
  if(index > 0)
  {
    if(this.BWordsMode == false)
    {
      if(this.Text.charAt(index - 1) == '\n'  &&  bIsBackward != true)  
      {
        this.CurLine++;
      }
    }
    else
    {
      if(index == GetNumberOfWordsToFinishString(this.CurLine, this.Text))
      {
        this.CurLine++;
      }
    }
  }
  
  if(this.CurLine != this.PrevLine  &&  this.CurLine > this.NumOfLinesBeforeCurrentLine  &&  
      this.CurLine < this.NumOfLinesAtText - 1  &&  bIsBackward != true)  
  { 
    this.ShowElement(this.CurLine - this.NumOfLinesBeforeCurrentLine - 1, false);
    this.ShowElement(this.CurLine + 1, true);
  }    
  
  var color = "";
  
  if(bIsBackward == undefined  ||  bIsBackward == false)  color = "green";
  
  this.SetCharColorBkColor(this.Index, color, "");
  this.SetCharColorBkColor(index, "white", "green");
  
  this.Index = index;
  
  this.PrevLine = this.CurLine;
}

function GetIndex()
{
  return this.Index;
}

function StepForward()
{
  /*if(this.GetIndex() < this.Text.length - 1)  */this.SetCaret(this.GetIndex() + 1);
}

function GoToBeg()
{
  this.SetCaret(0, true);
}

function GoToBegOfLine()
{
  var i = this.GetIndex();
  if(this.Text.charAt(i) == '\n')
    i--;
  
  for(; i > 0  &&  this.Text.charAt(i) != '\n'; i--)
  {
    this.SetCharColor(i, "")
    this.SetCharBkColor(i, "");    
  }
  
  if(this.Text.charAt(i) == '\n')  i++;
  
  this.SetCaret(i, true);
}

function SetCharColorBkColor(i, color, bkColor)
{
  /*var style1 = "display: block; height: 1px; overflow: hidden; " + 
                    "font-size: 1px; margin: 0 1px; background-color: " + bkColor;
  var style2 = "padding: 0 2px; margin: 0; background-color: " + bkColor + 
                      "; font-weight: bold;  text-align: left; color: " + color + "; vertical-align: top;";*/
                      
  var obj1 = document.getElementById(this.GetLetterSpanId(i) + "El1"); 
  var obj2 = document.getElementById(this.GetLetterSpanId(i));
  var obj3 = document.getElementById(this.GetLetterSpanId(i) + "El2");  
  
  obj1.style.background  = bkColor;
  obj2.style.color = color;
  obj2.style.background = bkColor;
  obj3.style.background  = bkColor;                           
}

function LetterSpan(i, letter, bGreen)
{               
  //var addColorStr = "";
  //if(bGreen == true)  addColorStr += " color: green;";

  /*var style1 = "display: block; height: 1px; overflow: hidden; " + 
                    "font-size: 1px; margin: 0 1px";
  var style2 = "padding: 0px 2px; margin: 0;" +
                      " font-weight: bold; height: 100%; font-family: Courier New; font-size: 12pt;" + addColorStr;*/ // + " text-align: center; vertical-align: center;"

  //var letter_ = letter;
  
  if(letter == " ")  letter = "&nbsp;";

  if(bGreen == false)
    return  "<b id='" + this.GetLetterSpanId(i) + "El1' class='Input1Class1'></b><div id='" + 
      this.GetLetterSpanId(i) + 
      "' class='Input2ColorNone'>" + letter +
		  "</div><b id='" + this.GetLetterSpanId(i) + "El2" + "' class='Input1Class1'></b>";
	else
	 return  "<b id='" + this.GetLetterSpanId(i) + "El1' class='Input1Class1'></b><div id='" + 
      this.GetLetterSpanId(i) + 
      "' class='Input2ColorGreen'>" + letter +
		  "</div><b id='" + this.GetLetterSpanId(i) + "El2" + "' class='Input1Class1'></b>";

}

function SetCharBkColor(i, color)
{

  this.Style1 = "display: block; height: 1px; overflow: hidden; " + 
                    "font-size:1px; margin: 0 1px; background-color: " + this.BkColor;
  this.Style2 = "padding: 0 2px; margin: 0; background-color: " + this.BkColor + 
                      "; font-weight: bold;  text-align: left; color: " + this.Color + "; vertical-align: top;";

  document.getElementById(this.GetLetterSpanId(i)).style.background = color;
  return;
}

function SetCharColor(i, color)
{
  document.getElementById(this.GetLetterSpanId(i)).style.color = color;
}

function GetCurLine(curPos)
{
  return this.CurLine;
}

function GetStringId(numOfString)
{
  return "InputFieldString" + String(numOfString);
}

this.GetNumOfWords = function()
{
  return this.NumOfWords;
}

this.GetWord = function(index, str)
{
  var i;
  var index_ = 0;
  
  for(i = 0; i < str.length; i++)
  {
    if(index == index_)
    {
      var strRet = "";
      for(;str.charAt(i) != " " && str.charAt(i) != "\n"; i++)
        strRet += str.charAt(i);
      return strRet;
    }
    
    if(str.charAt(i) == " "  ||  str.charAt(i) == "\n")  index_++;
  }
}

this.GetWordLength = function(begIndex, text)
{
  var i, len = 0;
  for(i = begIndex; text.charAt(i) != " "  &&  text.charAt(i) != "\n"  &&
          i < text.length; i++)
            len++;
  return len;
}

/*function TInterval()
{
  alert("test");
}*/

function Render() // new (without color/bkcolor of text )
{
  var obj = document.getElementById(this.Id);
  
//  setInterval("TInterval()", 300);
  
  var exStr = "";
  
  var curLine = 0;
    
  var text = this.Text;
  if(this.LastChar != -1)  text = this.Text.substring(0, this.LastChar);
  
  curLine = this.GetCurLine();
 
// теперь надо решить с какой строки начинать отображение 
  var beginningLine = curLine - this.NumOfLinesBeforeCurrentLine;
  if(beginningLine < 0) beginningLine = 0; 
 
  var i = 0;
  for(var k = 0; k < beginningLine; i++)
  {
    if(text.charAt(i) == '\n') k++;
  }
  endLine = beginningLine + this.NumOfLines;
  
  var cntWord;
  
  if(this.BWordsMode == false)
  {
    for(i = 0, k = 0; i < text.length; i++)
    {
      if(k >= beginningLine && k < endLine)  exStr += "<table id='" + this.GetStringId(k) + "' cellspacing='0' cellpadding='0' border='0'><tr>";
      else  exStr += "<table id='" + this.GetStringId(k) + "' cellspacing='0' cellpadding='0' border='0' style='display: none'><tr>";
          
      for(var j = 0; j < this.StrLength && i < text.length  &&  text.charAt(i) != '\n'; j++, i++)
      {
        exStr += "<td>";
        var bGreen = false;
        if(this.Index > i)  bGreen = true;    
        
        // params: this.BWordsMode
        
        exStr += this.LetterSpan(i, text.charAt(i), bGreen);
        
        exStr += "</td>";
      }
    
      if(text.charAt(i) == '\n')
      {
        exStr += "<td>";
        exStr += this.LetterSpan(i, '&nbsp;');
        exStr += "</td>";   
        k++;
        //i++;
      }    
      exStr += "</tr></table>";
    }
  }
  else
  {      
   // var bBeginStr = true;
   var NumOfWord = 0;
   for(i = 0, k = 0; i < text.length; i++)
   {
      if(k >= beginningLine && k < endLine)  exStr += "<table cellspacing='0' cellpadding='0' border='0'><tr id='" + this.GetStringId(k) + "'>";
      else  exStr += "<table cellspacing='0' cellpadding='0' border='0'><tr id='" + this.GetStringId(k) + "' style='display: none'>";
          
      for(var j = 0; j < this.StrLength && i < text.length; j++, i++)
      {
      
        if(text.charAt(i) == ' ' || text.charAt(i) == '\n')
        {      
          exStr += "<td>";
          var bGreen = false;
          if(this.Index > NumOfWord)  bGreen = true;    
          exStr += this.LetterSpan(NumOfWord, this.GetWord(NumOfWord, text), bGreen);
          //alert(this.LetterSpan(NumOfWord, this.GetWord(NumOfWord, text), bGreen));
          exStr += "</td>";
          NumOfWord++;
        }
        if(text.charAt(i) == '\n')  break;
      }
    
      if(text.charAt(i) == '\n')
      {
        exStr += "<td>";
        exStr += /*this.LetterSpan(i, '&nbsp;&nbsp;')*/EmptySpan('&nbsp;');
        //alert(this.LetterSpan(i, '&nbsp;&nbsp;'));
        exStr += "</td>";   
        k++;
        //i++;
      }    
      exStr += "</tr></table>";
    }
    
    this.NumOfWords = NumOfWord;
  }
  
  this.WholeTextNumOfLines = k;
  
  for(; k < this.NumOfLines; k++) // fill empty strings
  {
    exStr += "<table cellspacing='0' cellpadding='0' border='0'><tr><td>&nbsp;</td></tr></table>";
  }
  
  this.NumOfLinesAtText = k; // Init NumOfLines
  //exStr += "</tr></td></table>";
  obj.innerHTML = this.EmptyField.HTMLPreInputField(this.Id) + exStr + this.EmptyField.HTMLPostInputField();
}
  
}  

///////

function TCiteField(id)
{
  this.Id = id;
  this.FieldId = id + 'Field';
  this.SetCite = SetCite;
  this.Update = Update;
  this.Render = Render;
  this.PlaceHere = PlaceHere;
  this.RenderError = RenderError;
  this.EmptyField = new TEmptyField("Cite", "#FFFFFF");
  this.GetEmptyField = GetEmptyField;
  
  this.Cite = "";
  this.ErrorText = "";
  this.Author = "";
  this.AuthorInfo = "";
  
  this.Hide = function()
  {
    var obj = document.getElementById(this.Id);
    obj.style.visibility = "hidden";
  }
  
  this.Show = function()
  {
    var obj = document.getElementById(this.Id);
    obj.style.visibility = "visible";
  }
  
function PlaceHere()
{
  return BeginSpan('id', this.Id) + EndSpan();
} 
  
function GetEmptyField()
{
  return this.EmptyField;
} 

this.Init = function()
{

 //if(this.BInited == false)
  //{
  //}
  this.OText = document.getElementById(this.CiteId);
  this.OCiteCornerTopLeft = document.getElementById("IDCiteCornerTopLeft");
  this.OCiteTop = document.getElementById("IDCiteTop");
  this.OCiteCornerTopRight = document.getElementById("IDCiteCornerTopRight");
  this.OCiteLeft = document.getElementById("IDCiteLeft");
  this.OCiteRight = document.getElementById("IDCiteRight");
  this.OCiteSpeech = document.getElementById("IDCiteSpeech");
  this.OCiteRight2 = document.getElementById("IDCiteRight2");
  this.OCiteLeft2 = document.getElementById("IDCiteLeft2");
  this.OCiteRight3 = document.getElementById("IDCiteRight3");
  this.OCiteRight3 = document.getElementById("IDCiteRight3");
  this.OCiteCornerBottomLeft = document.getElementById("IDCiteCornerBottomLeft");
  this.OCiteBottom = document.getElementById("IDCiteBottom");
  this.OCiteCornerBottomRight = document.getElementById("IDCiteCornerBottomRight");
  this.OCiteSpeechFiller = document.getElementById("IDCiteSpeechFiller");
} 

this.BInited = false;

this.SetBorder = function(pre)
{  

//  alert("SetBorder("+pre);
  if(pre == "exBlack")
    this.OText.style.color = "black";
  else
    this.OText.style.color = "red";
  
  this.OCiteTop.className = pre + "CiteBkTop";
  this.OCiteCornerTopLeft.className = pre + "CiteCornerTopLeft";
  this.OCiteTop.className = pre + "CiteBkTop";
  this.OCiteCornerTopRight.className = pre + "CiteCornerTopRight";
  this.OCiteLeft.className = pre + "CiteBkLeft";
  this.OCiteRight.className = pre + "CiteBkRight";
  this.OCiteSpeech.className = pre + "CiteSpeechBk";
  this.OCiteRight2.className = pre + "CiteBkRight";
  this.OCiteLeft2.className = pre + "CiteBkLeft";
  this.OCiteRight3.className = pre + "CiteBkRight";
  this.OCiteCornerBottomLeft.className = pre + "CiteCornerBottomLeft";
  this.OCiteBottom.className = pre + "CiteBkBottom";
  this.OCiteCornerBottomRight.className = pre + "CiteCornerBottomRight";
  this.OCiteSpeechFiller.className = pre + "CiteFiller";
}

this.SetBlack = function()
{
//  alert("SetBlack");
  this.SetBorder("exBlack");
}

this.SetError = function()
{
//  alert("SetError");
  this.SetBorder("exError");
}

this.MergeInt = 0;


function citeFieldMerge(obj)
{
   if(CiteField.MergePh)
   {
      CiteField.SetBlack();
   }
   else
   {
      CiteField.SetError();
   }
   CiteField.MergePh = !CiteField.MergePh;
}

this.BeginMerge = function()
{
  this.MergeInt = setInterval(function(){citeFieldMerge(this);}, 300);
  this.MergeF0 = this.SetBlack;
  this.MergeF1 = this.SetError; 
  this.MergePh = false;
}
this.StopMerge = function()
{
  clearInterval(this.MergeInt);
}

function SetCite(cite, author, authorInfo)
{
  this.Store(this.Cite, this.Author, this.AuthorInfo);
  this.Cite = cite;
  if(author != undefined)
  {
    this.Author = author.replace(/,/, ",<br>");
  }
  else
    this.Author = "";
  if(authorInfo != undefined)
  {
    this.AuthorInfo = authorInfo;
  }
  else this.AuthorInfo = "";
}

this.TPrev = function()
{
  this.Cite = "not inited";
  this.Author = "not inited";
  this.AuthInfo = "not inited";
}
this.Prev = new this.TPrev();

this.Store = function(cite, auth, authInfo)
{
  this.Prev.Cite = cite;
  this.Prev.Author = auth;
  this.Prev.AuthInfo = authInfo;  
}

this.Restore = function()
{
  this.Cite = this.Prev.Cite;
  this.Author = this.Prev.Author;
  this.AuthorInfo = this.Prev.AuthInfo;
}


function Update()
{
//  var objCite = document.getElementById(this.CiteId);
  
  var objAuthor = document.getElementById(this.AuthorId);
  
  this.Init();
  
//  objCite.innerHTML = "<div style='color: #000000; font-size: 12pt; font-weight: bold; font-family: Tahoma; line-height: 1.2'>" + this.Cite + "</div>";
//  objAuthor.innerHTML = "<div style='color: #000000; font-size: 9pt; font-family: Arial; font-style:italic; line-height: 1.1'>" + this.Author + "<br>" + this.AuthorInfo + "</div>";
}

this.SetErrorText = function(val)
{
  this.Store(this.Cite, this.Author, this.AuthorInfo);
  this.ErrorText = val;
}

this.UpdateErrorText = function()
{
//  var objCite = document.getElementById(this.CiteId);
//  var objAuthor = document.getElementById(this.AuthorId);
  
  var boldness = 400;
  
  if(window.navigator.appName == "Opera")  boldness = 600;
  
//  objCite.innerHTML = "<center><span style='font-size: 14pt; font-family: Arial; line-height: 125%;'>" + this.ErrorText + "</span></center>";
//  objAuthor.innerHTML = "";
}

this.SetWarning = function()
{
  
}

this.GetCiteField = function(bError)
{
  var class_ = undefined;
  var vertAlign = "top";
  if(bError == true)
  {
    class_ = "ErrorCite";
    vertAlign = "middle";
  }
  return  BeginSpan('id',this.FieldId) + this.EmptyField.HTMLPreCiteField(class_) +
  "<table cellpadding=4 border=0 width='100%' height='90px'><tr><td valign='" + vertAlign + "'>" + 
  BeginSpan("id", this.CiteId) + EndSpan() +
  "</td></tr><tr valign='bottom' align='right'><td>" + 
  BeginSpan("id", this.AuthorId) + EndSpan() +
  "</td></tr></table>" + 
    this.EmptyField.HTMLPostCiteField(class_) + EndSpan();
}

function Render()
{
  var obj = document.getElementById(this.Id);

  this.CiteId = this.Id + "Cite";
  this.AuthorId = this.Id + "Author";

  obj.innerHTML = this.GetCiteField(false);   
  
//  TableBuilder.ResetT();
  
  //alert(BeginP('align', 'right') + "" + EndP());
}

function RenderError()
{
  var obj = document.getElementById(this.Id);
  obj.innerHTML = this.GetCiteField(true);
  this.Update();
  
  this.UpdateErrorText();
}

this.SetBlackBorder = function()
{
// rename all the classes
  
}

}


////////////
  
function TEmptyField(style, bk, height)
{
  this.Style = style;
  this.HTMLPreInputField = HTMLPreInputField;
  this.HTMLPreInputField2 = HTMLPreInputField2;
  this.HTMLPostInputField = HTMLPostInputField;
  this.HTMLPostInputField2 = HTMLPostInputField2;
  this.Bk = bk;
  this.Height = height;
  
  
  this.RowHeight = 0;
  this.RowWidth = 0;
  this.SetRowHeight = SetRowHeight;
  this.GetRowHeight = GetRowHeight;
  this.SetRowWidth = SetRowWidth;
  this.GetRowWidth = GetRowWidth;
  
function SetRowHeight(val)
{
  this.RowHeight = val;
}

function GetRowHeight()
{
  return this.RowHeight;
}

function SetRowWidth(val)
{
  this.RowWidth = val;
}

function GetRowWidth()
{
  return this.RowWidth;
}
    
function HTMLPreInputField(id)
{
  var strHeight = "";
  if(this.Height != 0 && this.Height != undefined)  strHeight = " height=\'" + String(this.Height) + "\'";
  var res = "<table border=0 id='" + id + "Table' border=0 cellspacing=0 cellpadding=0 width='600' class=\'ex" + this.Style + "Table\'>" +
  "<tr height='4px'>" +
  "<td class='ex" + this.Style + "CornerTopLeft' width='4px'>" + 
  "</td>" +
  "<td height='4px' class='ex" + this.Style + "BkTop'>" +
  "</td>" +
  "<td width='4px' height='4px' class='ex" + this.Style + "CornerTopRight'>" +
  "</td>" +  
  "</tr>" +
  "<tr" +
  ">" +
  "<td width='4px' class='ex" + this.Style + "BkLeft'>" +
  "</td>" +
  "<td  valign='middle'>" +
  "<table border=0 cellspacing=0 cellpadding=7 width=100% align='center' bgcolor=\'" + this.Bk + "\'>" +
  "<tr>" +
  "<td valign='middle'>" +
  "<span class='exercise" + this.Style + "'>";
  return res;
}

function HTMLPostInputField()
{
  return "</span>" +
  "</td>" +
  "</tr>" +
  "</table>" +
  "</td>" +
  "<td width='4px' class='ex" + this.Style + "BkRight'>" +
  "</td>" + 
  "</tr>" +
  "<tr height='4px'>" +
  "<td width='4px' height='4px' class='ex" + this.Style + "CornerBottomLeft'>" +
  "</td>" +
  "<td  height='4px' class='ex" + this.Style + "BkBottom'>" +
  "</td>" +
  "<td width='4px'  height='4px' class='ex" + this.Style + "CornerBottomRight'>" +
  "</td>" +  
  "</tr>" +  
  "</table>";
}

function HTMLPreInputField2(id)
{
  var strHeight = "";
  if(this.Height != 0 && this.Height != undefined)  strHeight = " height=\'" + String(this.Height) + "\'";
  var res = "<table id='" + id + "Table' border=0 cellspacing=0 cellpadding=0 width='600' class=\'ex" + this.Style + "Table\'>" +
  "<tr height='4px'>" +
  "<td class='ex" + this.Style + "CornerTopLeft' width='4px'>" + 
  "</td>" +
  "<td height='4px' class='ex" + this.Style + "BkTop'>" +
  "</td>" +
  "<td width='4px' height='4px' class='ex" + this.Style + "CornerTopRight'>" +
  "</td>" +  
  "</tr>" +
  "<tr" +
  ">" +
  "<td width='4px' class='ex" + this.Style + "BkLeft'>" +
  "</td>" +
  "<td  valign='middle'>" +
  "<table border=0 cellspacing=0 cellpadding=5 width=100% align='center' bgcolor=\'" + this.Bk + "\'>" +
  "<tr>" +
  "<td valign='middle'>" +
  "<span class='exercise" + this.Style + "'>";
  //alert("HTMLPreInputField2: test");
  return res;
}  

function HTMLPostInputField2()
{
  return "</span>" +
  "</td>" +
  "</tr>" +
  "</table>" +
  "</td>" +
  "<td width='4px' class='ex" + this.Style + "BkRight'>" +
  "</td>" + 
  "</tr>" +
  "<tr height='4px'>" +
  "<td width='4px' height='4px' class='ex" + this.Style + "CornerBottomLeft'>" +
  "</td>" +
  "<td  height='4px' class='ex" + this.Style + "BkBottom'>" +
  "</td>" +
  "<td width='4px'  height='4px' class='ex" + this.Style + "CornerBottomRight'>" +
  "</td>" +  
  "</tr>" +  
  "</table>";
}

this.HTMLPreCiteField = function(class_)
{
if(class_ == undefined)  class_ = "Cite";

return "<TABLE class='ex" + class_ + "Table' WIDTH=100% BORDER='0' CELLPADDING=0 CELLSPACING=0>" +
"	<TR VALIGN=TOP height='4px'>" +
"		<TD WIDTH='19px'>" +
"		</TD>" +
"		<TD id='IDCiteCornerTopLeft' class='ex" + class_ + "CornerTopLeft' width='4px'>" +
"		</TD>" +
"		<TD id='IDCiteTop' class='ex" + class_ + "BkTop'>" +
"		</TD>" +
"		<TD id='IDCiteCornerTopRight' class='ex" + class_ + "CornerTopRight' width='4px'>" +
"		</TD>" +
"	</TR>" +
"	<TR VALIGN=TOP height='35px'>" +
"		<TD width='4px'><font size='2pt' face='Times New Roman'>&nbsp;</font>" +
"		</TD>" +
"		<TD id='IDCiteLeft' class='ex" + class_ + "BkLeft' WIDTH='4px'>" +
"		</TD>" +
"		<TD ROWSPAN=3>";
}

this.HTMLPostCiteField = function(class_)
{
  if(class_ == undefined)  class_ = "Cite";

  /*var speechHeight = 19;
  if(window.navigator.appName == "Microsoft Internet Explorer")
    speechHeight = 19;*/    

return "</TD>" +
"		<TD id='IDCiteRight' class='ex" + class_ + "BkRight' WIDTH='4px'>" +
"		</TD>" +
"	</TR>" +
"	<TR VALIGN=TOP style='height: 19px'>" +
"		<TD id='IDCiteSpeech' style='height: 19px' class='ex" + class_ + "SpeechBk' WIDTH='19px'>" +
"		</TD>" +
"		<TD id='IDCiteSpeechFiller' WIDTH='4px' class='exCiteSpeechFiller'" +
"		</TD>" +
"		<TD id='IDCiteRight2' class='ex" + class_ + "BkRight' WIDTH='4px'>" +
"		</TD>" +
"	</TR>" +
"	<TR VALIGN=TOP height='35px'>" +
"		<TD WIDTH='19px'><font size='2pt' face='Times New Roman'>&nbsp;</font>" +
"   </TD>" +
"		<TD id='IDCiteLeft2'  class='ex" + class_ + "BkLeft' WIDTH='4px'>" +
"		</TD>" +
"		<TD id='IDCiteRight3' WIDTH='4px' class='ex" + class_ + "BkRight' >" +
"		</TD>" +
"	</TR>" +
"	<TR VALIGN=TOP height='4px'>" +
"		<TD WIDTH='19px'>" +
"		</TD>" +
"		<TD id='IDCiteCornerBottomLeft' class='ex" + class_ + "CornerBottomLeft' WIDTH='4px'>" +
"		</TD>" +
"		<TD id='IDCiteBottom' class='ex" + class_ + "BkBottom'>" +
"		</TD>" +
"		<TD id='IDCiteCornerBottomRight' class='ex" + class_ + "CornerBottomRight' WIDTH='4px'>" +
"		</TD>" +
"	</TR>" +
"</TABLE>";
}


this.HTMLPreResultMessageField = function()
{
  var strHeight = "";
  if(this.Height != 0 && this.Height != undefined)  strHeight = " height=\'" + String(this.Height) + "\'";
  var res = "<table width='100%' border=0 cellspacing=0 cellpadding=0 class='exResultMessageTable'>" +
  "<tr height='4px'>" +
  "<td id='IDTdResultMessageCornerTopLeft' class='exResultMessageCornerTopLeft' width='4px'>" + 
  "</td>" +
  "<td id='IDTdResultMessageBkTop' height='4px' class='exResultMessageBkTop'>" +
  "</td>" +
  "<td id='IDTdResultMessageCornerTopRight' width='4px' height='4px' class='exResultMessageCornerTopRight'>" +
  "</td>" +  
  "</tr>" +
  "<tr" +
  ">" +
  "<td id='IDTdResultMessageBkLeft' width='4px' class='exResultMessageBkLeft'>" +
  "</td>" +
  "<td valign='middle'>" +
  "<table border=0 cellspacing=0 cellpadding=7 width=100% align='center' bgcolor=\'" + this.Bk + "\'>" +
  "<tr>" +
  "<td valign='middle'>";
  return res;
}

this.HTMLPostResultMessageField = function()
{
  return "</td>" +
  "</tr>" +
  "</table>" +
  "</td>" +
  "<td id='IDTdResultMessageBkRight' width='4px' class='exResultMessageBkRight'>" +
  "</td>" + 
  "</tr>" +
  "<tr height='4px'>" +
  "<td id='IDTdResultMessageCornerBottomLeft' width='4px' height='4px' class='exResultMessageCornerBottomLeft'>" +
  "</td>" +
  "<td id='IDTdResultMessageBkBottom' height='4px' class='exResultMessageBkBottom'>" +
  "</td>" +
  "<td id='IDTdResultMessageCornerBottomRight' width='4px'  height='4px' class='exResultMessageCornerBottomRight'>" +
  "</td>" +  
  "</tr>" +  
  "</table>";
}

}

///////

function TInputField2(id, strLength, numOfLines, numOfLinesBeforeCurrentLine)
{
  this.Id = id;
  this.LetterId = 'Letter';
  this.StrLength = strLength;
  this.NumOfLines = numOfLines;
  this.NumOfLinesBeforeCurrentLine = numOfLinesBeforeCurrentLine;
  
  this.Text = String("");
  this.InnerHTML = String("");
  
  this.Index = 0;
  
  this.SetText = SetText;
  this.SetCaret = SetCaret;
  this.Render = Render;
  this.SetLastChar = SetLastChar;
//  this.RenderMarkChar = RenderMarkChar;
  this.SetBkRedCurrentChar = SetBkRedCurrentChar;
  this.SetBkGreenCurrentChar = SetBkGreenCurrentChar;
  
  this.LetterSpan = LetterSpan;
  
  this.EmptyField = new TEmptyField("Text", "#f6f6f6");
  this.GetEmptyField = GetEmptyField;
  this.LastChar = -1;
  this.MarkError = false;
  this.BkCurrentCharColor = 'green';
  this.CurrentCharColor = 'white';
  
  this.GetLetterSpanId = GetLetterSpanId;
  
  this.SetCharBkColor = SetCharBkColor;
  this.SetCharColor = SetCharColor;
  
  this.GetIndex = GetIndex;
  
  this.GetCurLine = GetCurLine;
  this.GetStringId = GetStringId;
  
  this.StepForward = StepForward;
  this.SetError = SetError;
  this.GoToBegOfLine = GoToBegOfLine;
  this.SetChar = SetChar;
  this.AppendLastChar = AppendLastChar;
  this.GoToBeg = GoToBeg; 
  this.ClearAfterError = ClearAfterError;
  this.PlaceHere = PlaceHere;
  
  this.SetSpanVisible = SetSpanVisible;
  this.SetSpanInvisible = SetSpanInvisible;

  this.NumOfLinesAtText = 0; // num of lines at exercise  
  
  this.CurLine = 0;
  this.ShowElement = ShowElement;
  
  this.BWordsMode = false;
  this.CurNumOfWord = 0; // actually number of active span
  this.NumOfWords = 0;
  this.EnteredText = "";
  
  this.WordSymbolIndex = 0;
  
  this.bUseFragmentLength = false;
  
  this.SetUseFragmentLength = function(bVal)
  {
    this.bUseFragmentLength = bVal;
  }
  
  this.AddToEnteredText = function(ch)
  {
    this.EnteredText += ch;
  }
  
this.SetWordsMode = function(bMode)
{
  this.BWordsMode = bMode;
  this.CurNumOfWord = 0;
}

this.GetCurNumOfWord = function()
{
  return this.CurNumOfWord;
}

this.NextWord = function()
{
  this.CurNumOfWord++;
}

this.ClearCurWord = function()
{
  this.CurWord = "";
  this.WordSymbolIndex = 0;
}
this.GetCurWord = function()
{
  return this.CurWord;
}

this.AddToCurWord = function(strWord)
{
  var obj = document.getElementById(this.GetLetterSpanId(this.CurNumOfWord));
  var s = obj.innerHTML;
  s += strWord;
  this.CurWord = s;
  obj.innerHTML = s;
  this.WordSymbolIndex++;
}

this.GetWordSymbolIndex = function()
{
  return this.WordSymbolIndex;
}

this.GetWordNum = function(num)
{
  var obj = document.getElementById(this.GetLetterSpanId(num));
  if(obj == undefined)
  {
    alert("Can't get word number " + num);
    return;
  }
  
  return document.getElementById(this.GetLetterSpanId(num)).innerHTML;
}

function PlaceHere()
{
  return BeginSpan('id', this.Id) + EndSpan();
}   
  
function GetEmptyField()
{
  return this.EmptyField;
} 

function GetLetterSpanId(i)
{
  return this.Id + this.LetterId + String(i);
}

function LetterSpan(i, letter, bGreen, bVisible)
{
  /*var style1 = "display: block; height: 1px; overflow: hidden; " + 
                    "font-size: 1px; margin: 0 1px";
  var style2;                  
  if(bVisible == true)
    style2 = "padding: 0px 2px; margin: 0;" +
                      " font-weight: bold; height: 100%; font-family: Courier New; font-size: 12pt";
  else
    style2 = "visibility: hidden; padding: 0px 2px; margin: 0;" +
                      " font-weight: bold; height: 100%; font-family: Courier New; font-size: 12pt";*/

  var letter_ = letter;
  
  if(letter_ == " ")  letter_ = "&nbsp;";

  if(bVisible)
    return "<b class='Input2Class1'></b><div id='" + this.GetLetterSpanId(i) + "' class='Input2Class2Visible'>" + letter_ +
		  "</div><b class='Input2Class1'></b>"; 
	else
	  return "<b class='Input2Class1'></b><div id='" + this.GetLetterSpanId(i) + "' class='Input2Class2Invisible'>" + letter_ +
		  "</div><b class='Input2Class1'></b>"; 
}

this.WordModeWordSpan = function(word)
{
  /*var style1 = "display: block; height: 1px; overflow: hidden; " + 
                    "font-size: 1px; margin: 0 1px";
  var style2 = "padding: 0px 2px; margin: 0;" +
                      " font-weight: bold; height: 100%; font-family: Courier New; font-size: 12pt";*/// + " text-align: center; vertical-align: center;"
  
  if(word == " ")  word = "&nbsp;";

  return "<b class='Input2Class1'></b><div class='Input2Class2Visible'>" + word_ +
		  "</div><b style='Input2Class1'></b>"; 
}

this.WordModeLetterSpan = function(i, letter)
{
  var letter_ = letter;
  var style = "visibility: hidden;";
  if(letter_ == " ")  letter_ = "&nbsp;";  
  return "<span id='" + this.GetLetterSpanId(i) + "' style='" + style + "'>" + letter_ + "</span>";
}

function SetText(text)
{
  var obj = document.getElementById(this.Id);
  
  this.Text = text;
  
  this.WordSymbolIndex = 0; // for word mode
  
  for(i = 0; i < this.Text.length; i++)
  {
    this.InnerHTML += this.LetterSpan(i, this.Text.charAt(i));
  }
  
}

function GetText()
{
  return this.Text;
}

function SetError(errorCh)
{
  this.AppendLastChar(errorCh);
  this.SetCharColor(this.Index, '#AB0000');
}

this.SetBkRed = function(index)
{
  document.getElementById(this.GetLetterSpanId(index)).style.background = "#AB0000";
}
this.ClearBk = function(index)
{
  document.getElementById(this.GetLetterSpanId(index)).style.background = "";
}

this.TrimLastChar = function()
{
  this.ClearBk(this.Index);
  document.getElementById(this.GetLetterSpanId(this.Index)).style.visibility = "hidden";  
  this.SetCharColor(this.Index, ''); // clear after error //  
  this.SetChar(this.Index, this.Text.charAt(this.Index));
}

function AppendLastChar(ch)
{
  var ch_ = ch;
  if(ch_ == '\r') ch_ = "&#182;";
  if(ch_ == ' ')
  {
    document.getElementById(this.GetLetterSpanId(this.Index)).innerHTML = '&nbsp;';
    document.getElementById(this.GetLetterSpanId(this.Index)).style.visibility = "visible";
    this.SetBkRed(this.Index);
  }
  else
  {
    document.getElementById(this.GetLetterSpanId(this.Index)).innerHTML = ch_;
    document.getElementById(this.GetLetterSpanId(this.Index)).style.visibility = "visible";
  }
}

function SetLastChar(lastChar)
{
  this.LastChar = lastChar;
}

function SetBkRedCurrentChar()
{
  this.BkCurrentCharColor = 'red';
}

function SetBkGreenCurrentChar()
{
  this.BkCurrentCharColor = 'green';
}

function ShowElement(i, bShow)
{
  var obj = document.getElementById(this.GetStringId(i));
  if(bShow)  obj.style.display = "";
  else  obj.style.display = "none";
}

function SetCaret(index, bIsBackward)
{   
  this.Index = index;
}

function GoToBeg()
{
  this.SetCaret(0, true);
/*Next actions are for word mode*/
  this.CurLine = 0;
  this.CurNumOfWord = 0;
/**/
  this.Render();
}

function GetIndex()
{
  return this.Index;
}

function SetSpanVisible(index)
{ 
  document.getElementById(this.GetLetterSpanId(index)).style.visibility = "visible";
}

function SetSpanInvisible(index)
{
  document.getElementById(this.GetLetterSpanId(index)).style.visibility = "hidden";
}

function StepForward()
{
  
  var newIndex;
  
  if(this.bUseFragmentLength == false)
    newIndex = this.GetIndex() + 1;
  else
    newIndex = this.GetIndex() + TextFragmentsData.GetLengthAddFrag(CaretPos);
/*Very bad, context depending...*/    

  
  if(newIndex == 0)  
  {
    this.CurLine = 0;
    if(bIsBackward == true)  this.Render();
  }
  else
  if(newIndex > 0)
  {
    if(this.BWordsMode == false)
    {
      if(this.Text.charAt(newIndex - 1) == '\n')  this.CurLine++;
    }
    else
    {
      if(IsWordLastAtString(this.Text, this.GetIndex()))  this.CurLine++;
    }
  }
  
  if(this.CurLine != this.PrevLine  &&  this.CurLine > this.NumOfLinesBeforeCurrentLine  &&  
      this.CurLine < this.NumOfLinesAtText - 1)  
  {
    this.ShowElement(this.CurLine - this.NumOfLinesBeforeCurrentLine - 1, false);
    this.ShowElement(this.CurLine + 1, true);
  }   
    
  for(var i = this.Index; i < newIndex; i++)  
    this.SetSpanVisible(i);
  
  this.Index = newIndex;
}

function SetChar(i, ch)
{
  if(ch != " ") document.getElementById(this.GetLetterSpanId(i)).innerHTML = ch;
  else  document.getElementById(this.GetLetterSpanId(i)).innerHTML = "&nbsp;";
}

function ClearAfterError()
{
 this.ClearBk(this.Index); // if error char is " "
 this.SetCharColor(this.Index, ''); // clear after error //  
 this.SetChar(this.Index, this.Text.charAt(this.Index));
}

function GoToBegOfLine()
{
  var i = this.GetIndex();
  if(this.Text.charAt(i) == '\n')
    i--;
  
  this.ClearAfterError();
  
  for(; i > 0  &&  this.Text.charAt(i) != '\n'; i--)
  {
    this.SetSpanInvisible(i);   
  }
  
//  alert("GoToBegOfLine():i=" + i);
  
  if(this.Text.charAt(i) == '\n')  i++;
  else  this.SetSpanInvisible(i);
  
  this.SetCaret(i);
}

function SetCharBkColor(i, color)
{
  document.getElementById(this.GetLetterSpanId(i)).style.background = color;
}

function SetCharColor(i, color)
{
  document.getElementById(this.GetLetterSpanId(i)).style.color = color;
}

function GetCurLine(curPos)
{
  return this.CurLine;
}

function GetStringId(numOfString)
{
  return "InputField2String" + String(numOfString);
}

function Render() // new (without color/bkcolor of text )
{
  var obj = document.getElementById(this.Id);
  
  var exStr = "";
  
  var curLine = 0;
    
  var text = this.Text;
  if(this.LastChar != -1)  text = this.Text.substring(0, this.LastChar);
  
  var curLine = this.GetCurLine();
 
// теперь надо решить с какой строки начинать отображение 
  var beginningLine = curLine - this.NumOfLinesBeforeCurrentLine;
  if(beginningLine < 0) beginningLine = 0; 
 
  var i = 0;
  for(var k = 0; k < beginningLine; i++)
  {
    if(text.charAt(i) == '\n') k++;
  }
  
  endLine = beginningLine + this.NumOfLines;
  
  if(this.BWordsMode == false)
  {
    for(i = 0, k = 0; i < text.length;)
    {
      
      if(k >= beginningLine && k < endLine)  exStr += "<table id='" + this.GetStringId(k) + "' cellspacing='0' cellpadding='0' border='0'><tr>";
      else  exStr += "<table id='" + this.GetStringId(k) + "' cellspacing='0' cellpadding='0' border='0' style='display: none'><tr>";

      for(var j = 0; j < this.StrLength && i < text.length  &&  text.charAt(i) != '\n'; j++, i++)
      {
        exStr += "<td>";
        exStr += this.LetterSpan(i, text.charAt(i));
        exStr += "</td>";
      }
    
      if(text.charAt(i) == '\n')
      {
        exStr += "<td>";
        exStr += this.LetterSpan(i, '&nbsp;');   
        exStr += "</td>";
        k++;
        i++;
      }    
      exStr += "</tr></table>";
    }
  }
  else
  {
    var NumOfWord = 0;
    for(i = 0, k = 0; i < text.length; i++)
    {
      if(k >= beginningLine && k < endLine)  exStr += "<table cellspacing='0' cellpadding='0' border='0'><tr id='" + this.GetStringId(k) + "'>";
      else  exStr += "<table cellspacing='0' cellpadding='0' border='0'><tr id='" + this.GetStringId(k) + "' style='display: none'>";
          
      for(var j = 0; j < this.StrLength && i < text.length; j++, i++)
      {
        if(text.charAt(i) == ' ' || text.charAt(i) == '\n')
        {      
          exStr += "<td>";
          var bGreen = false;
          if(this.Index > NumOfWord)  bGreen = true;    
          exStr += this.LetterSpan(NumOfWord, "", bGreen, true); // we should fill this words later
          exStr += "</td>";
          NumOfWord++;
        }
        if(text.charAt(i) == '\n')  break;
      }
    
      if(text.charAt(i) == '\n')
      {
        exStr += "<td>";
        exStr += /*this.LetterSpan(i, '&nbsp;&nbsp;')*/EmptySpan('&nbsp;');
        exStr += "</td>";   
        k++;
        //i++;
      }    
      exStr += "</tr></table>";
    }    
        
  }
  
  for(; k < this.NumOfLines; k++) // fill empty strings
  {
    exStr += "<table cellspacing='0' cellpadding='0' border='0'><tr><td>&nbsp;</td></tr></table>";
  }  
  
  this.NumOfLinesAtText = k; // Init NumOfLines
  //exStr += "</table>";
  obj.innerHTML = this.EmptyField.HTMLPreInputField(this.Id) + exStr + this.EmptyField.HTMLPostInputField();  
}
  
} 
///////

function TRoundField(id, color, bkColor)
{
  this.Value = "";
  this.Id = id;
  this.BkColor = bkColor;
  this.Color = color;
  
  this.Style1 = "display: block; height: 1px; overflow: hidden; " + 
                    "font-size:1px; margin: 0 1px; background-color: " + this.BkColor;
  this.Style2 = "padding: 0 2px; margin: 0; background-color: " + this.BkColor + 
                      "; font-weight: bold;  text-family: Arial; text-size: 11px; text-align: left; color: " + this.Color + "; vertical-align: top;";
  
  this.StrPre = "";
  this.StrPost = "";
  
  this.SetStrPre = function(val)
  {
    this.StrPre = "<td>" + "<span style='font-family: Arial; font-size: 8pt'>" + val + "</span>" + "</td>";
  }
  
  this.SetStrPost = function(val)
  {
    this.StrPost = "<td>" + "<span style='font-family: Arial; font-size: 8pt'>" + val + "</span>" + "</td>";
  }
  
  this.Place = function()
  {
    var res = "<table><tr>" + this.StrPre +
		  "<td>" +
		  "<b style='" + this.Style1 + "'></b>" +
		  "<div id='" + this.Id + "' style='" + this.Style2 + "'>" +
		  "</div>" +
		  "<b style='" + this.Style1 + "'></b>" +
		  "</td>" + this.StrPost + "</tr></table>";
//    alert(res);
    return res;
  }
  
  this.Update = function(val)
  {
//    document.getElementById(this.Id).innerHTML = val;
  }
  
  this.Show = function()
  {
    var obj = document.getElementById(this.Id);
    obj.style.visibility = "visible"; 
  }
  
  this.Hide = function()
  {
    var obj = document.getElementById(this.Id);
    obj.style.visibility = "hidden";  
  }
}         


/*function TProgressRoundField(id, color, bkColor1, bkColor2)
{
  this.Value = "";
  this.Id = id;
  this.IdEntered = this.Id + "Entered";
  this.IdTotal = this.Id + "Total";
  this.BkColor1 = bkColor1;
  this.BkColor2 = bkColor2;
  this.Color = color;
  
  this.Style1 = "display: block; height: 1px; overflow: hidden; " + 
                    "font-size:1px; margin: 0 1px; background-color: " + this.BkColor1;
  this.Style2 = "padding: 0 2px; margin: 0; background-color: " + this.BkColor1 + 
                      "; font-weight: bold;  text-family: Arial; text-size: 11px; text-align: left; color: " + this.Color + "; vertical-align: top;";
  this.Style3 = "display: block; height: 1px; overflow: hidden; " + 
                    "font-size:1px; margin: 0 1px; background-color: " + this.BkColor2;
  this.Style4 = "padding: 0 2px; margin: 0; background-color: " + this.BkColor2 + 
                      "; font-weight: bold;  text-family: Arial; text-size: 11px; text-align: left; color: " + this.Color + "; vertical-align: top;";                      
  
  this.StrPre = "";
  this.StrPost = "";
  
  this.Place = function()
  {
    var res = "<center><table><tr>" +
		  "<td>" +
		  "<b style='" + this.Style1 + "'></b>" +
		  "<div id='" + this.IdEntered + "' style='" + this.Style2 + "'>" +
		  "</div>" +
		  "<b style='" + this.Style1 + "'></b>" +
		  "</span></td>" +
		  "<td><span style='font-family: Arial; font-size: 10pt'><b>/</b></span></td>" + 
      "<td>" +
		  "<b style='" + this.Style3 + "'></b>" +
		  "<div id='" + this.IdTotal + "' style='" + this.Style4 + "'>" +
		  "</div>" +
		  "<b style='" + this.Style3 + "'></b>" +
		  "</td>" +
      "</tr></table></center>";
//    alert(res);
    return res;
  }
  
  this.Update = function(valEntered, valTotal)
  {
    document.getElementById(this.IdEntered).innerHTML = valEntered;
    document.getElementById(this.IdTotal).innerHTML = valTotal;
  }
  
  this.Show = function()
  {
    var obj = document.getElementById(this.Id);
    obj.style.visibility = "visible"; 
  }
  
  this.Hide = function()
  {
    var obj = document.getElementById(this.Id);
    obj.style.visibility = "hidden";  
  }
}      */


function TTimeRoundField(id, color, bkColor)
{
  this.Value = "";
  this.Id = id;
  this.IdMin = this.Id + "Min";
  this.IdSec = this.Id + "Sec";
  this.BkColor = bkColor;
  this.Color = color;
  
  this.Style1 = "display: block; height: 1px; overflow: hidden; " + 
                    "font-size:1px; margin: 0 1px; background-color: " + this.BkColor;
  this.Style2 = "padding: 0 2px; margin: 0; background-color: " + this.BkColor + 
                      "; font-weight: bold; text-family: Arial; text-size: 11px; text-align: left; color: " + this.Color + "; vertical-align: top;";
  
  this.StrPre = "";
  this.StrPost = "";
  
  this.Place = Place;
  this.Update = Update;
  
  
  function Place()
  {
    var res = "<table><tr>" +
		  "<td>" +
		  "<b style='" + this.Style1 + "'></b>" +
		  "<div id='" + this.IdMin + "' style='" + this.Style2 + "'>" +
		  "</div>" +
		  "<b style='" + this.Style1 + "'></b>" +
		  "</span></td>" +
		  "<td><span style='font-family: Arial; font-size: 8pt'>&nbsp;минут</span></td>" + 
      "<td>" +
		  "<b style='" + this.Style1 + "'></b>" +
		  "<div id='" + this.IdSec + "' style='" + this.Style2 + "'>" +
		  "</div>" +
		  "<b style='" + this.Style1 + "'></b>" +
		  "</td><td><span style='font-family: Arial; font-size: 8pt'>&nbsp;секунд</span></td>" +
      "</tr></table>";
    
    return res;
  }
  
  function Update(min, sec)
  {
    document.getElementById(this.IdMin).innerHTML = min;
    document.getElementById(this.IdSec).innerHTML = sec;
  }
}

TTextFragmentsData = function()
{
  this.BlockingPositions = new Array();
  this.LengthAddFrag = new Array();
  this.SetBlockingWords = function(text)
  {
    var nOfWord = 0;
    this.BlockingPositions.splice(0, this.BlockingPositions.length); // clear an array
    
    for(var i = 0; i < text.length; i++)
    {
      switch(text.charAt(i))
      {
      case ' ': case '\n':
        for(var j = i-1; text.charAt(j) != ' '  &&  text.charAt(j) != '\n'  &&
                text.charAt(j) != '«'  &&  j > 0; j--);
        if(text.charAt(j) != '«')  this.BlockingPositions.push(nOfWord);
        nOfWord++;
        break;
      case '«':
        //this.BlockingPositions.push(nOfWord);
        break;
      default:
        ;
      }
    }
  }
  
  this.IsWordBlocked = function(nOfWord)
  {
    for(var i = 0; i < this.BlockingPositions.length; i++)
    {
      if(this.BlockingPositions[i] == nOfWord)  return true;
    }
    return false;
  }
  
  this.GetFragmentWordNum = function(src, num)
  {
    var wNum = -1;
    var sRet = "";
    for(var i = 0; i < src.length; i++)
    {
      if(src.charAt(i) == "«")  wNum++;
      if(wNum == num)
      {
        for(var k = i+1; k < src.length  &&  src.charAt(k) != '»'; k++)
          sRet += src.charAt(k);
        return sRet;
      }
    }
  }
  
  this.ReplaceFragText = function(text, text2)
  {
    var sRet = "";
    var wNum = -1;
    
    for(var i = 0; i < text.length; i++)
    {
      if(text.charAt(i) == '«')
      {
        wNum++;
        var frag = this.GetFragmentWordNum(text2, wNum);
        
        if(frag == undefined) continue;
        //alert("frag="+frag);
          
        this.LengthAddFrag.push(frag.length);
          
        sRet += frag;
        for(var j = i+1; j < text.length  &&  text.charAt(j) != '»'; j++);
        i = j;
        continue;
      }
      sRet += text.charAt(i);
      this.LengthAddFrag.push(1);
    }
    
    return sRet;
  }
  
  this.GetLengthAddFrag = function(num)
  {
    if(num < this.LengthAddFrag.length)
      return this.LengthAddFrag[num];
    else
      alert("[!] GetLengthAddFrag: " + "Array range error");
  }
}

var TextFragmentsData = new TTextFragmentsData();



function flashInputOnBlur()
{
//  alert("focus");
}

function flashInputMouseIn()
{
//  FlashInput.SetMouseIn(true);
}

function flashInputMouseOut()
{
//  FlashInput.SetMouseIn(false);
}

/*function InputFields_DoFSCommand()
{
  alert("test");
}*/
    
function flashErrorLoaded()
{  
  if(isIe6()) return;             
//  FlashError.IndErrorLimit( ErrorObj.GetNumOfMistakes() > ErrorObj.GetMaxNumOfMistakes() );
}    
    
function TFlashError()
{

  this.CallMethod = 0;
  if(document.flashError)  this.CallMethod = 1;
  this.Call = function(p, arg)
  {
    try
    {
      if(window.document["flashError"]) 
      {
        window.document["flashError"].SetVariable(p, arg);
      }
      else
      {
        document.flashError.SetVariable(p, arg);
      }
    }
    catch(e)
    {
// warn about problem to access to FlashInput   
    }
  }
  
  this.IndErrorLimit = function(bVal)
  {
    this.Call("listener.isError", String(bVal));
  }
  
  this.Place = function()
  {
    return "<OBJECT codebase='' ID='flashError'><PARAM NAME='allowScriptAccess' VALUE='" + Environment.getScriptAccess() + "' />" +
	       "<PARAM NAME='movie' VALUE='" + Environment.getResourceDirectory() + "flash/onlineError.swf'>" +
	       "<EMBED WIDTH='911' HEIGHT='240' play='true' swliveconnect='true' name='flashError' src='" + Environment.getResourceDirectory() + "flash/onlineError.swf' quality='high' bgcolor='#FFFFFF' allowScriptAccess='" + Environment.getScriptAccess() + "' TYPE='application/x-shockwave-flash'></EMBED></OBJECT>";  
  }
  
  this.ID = "flashErrorSpan";
  this.Reset = function()
  {
//    alert(this.ID);
     document.getElementById(this.ID).innerHTML = this.Place();
     //alert();
  };
}

var exerciseIniter = {
		  Init: function()
		  {
		      this.Activate();
		      this.InitLanguage();
//		      FlashInput.SetLayout(KeyboardInfo.Layout);                  
		      SetCurKeyboardKey(); 	  
		  }
};

function TFlashKeyboard()
{
  this.Call = function(p, arg)
  {
    try
    {
      if(this.CallMethod == 0) 
      {
        window.document["flashKeyboard"].SetVariable(p, arg);
      }
      else
      {
        document.flashKeyboard.SetVariable(p, arg);
      }
      
      //alert("Caller: "+this.Call.caller.toString());
      //alert("FlashKeyboard.SetVariable(" + p + ", " + arg + ")");
    }
    catch(e)
    {
// warn about problem to access to FlashInput  
    }
  }
  
  this.bParamsLoaded = false;
  
  this.GetParamsLoaded = function()
  {
	return this.bParamsLoaded;  
  };
  
  this.SetParamsLoaded = function(b)
  {
	this.bParamsLoaded = b;  
  };
  
  this.SetLanguage = function(lang)
  {
    this.Call("listener.language", lang);    
  }
  this.SetLayout = function(layout)
  {
    this.Call("listener.layout", layout);    
  }
  this.SetLayoutChanged = function()
  {
    this.Call("listener.layoutChanged", "");
  }
  this.BBackspMode = false;
  this.BBackspSet = false;
  this.PreBkspKey = "";
  this.SetBkspMode = function(bVal)
  {
    this.BBackspMode = bVal;
    this.BBackspSet = !bVal;
    if(this.BBackspMode) 
      this.SetKey("backspace");
    else
      this.SetKey(this.PreBkspKey);
  }
  this.SetKey = function(key)
  {
    if(this.BBackspMode)
    {
      if(this.BBackspSet) return;
      this.Call("listener.key", "backspace");
      this.BBackspSet = true;
    }
    else
    {
      this.Call("listener.key", key);
      this.PreBkspKey = key;
    }      
  }
  this.SetParams = function(sXml)
  {
    this.Call("listener.params", sXml);
  }
  
  this.Activate = function()
  {
            var params = "layout=" + KeyboardInfo.Layout + "&next_key=" + String(KeyboardInfo.bNextKey) + "&show_chars=" + String(KeyboardInfo.bShowChars) + "&colored=" + String(KeyboardInfo.bColored);
            this.SetParams(params);
  }
  
  this.InitLanguage = function()
  {
    try
    {
      this.SetLanguage(commonInfo.Language);
    }
    catch(e)
    {
// init failed because the component has not loaded    
    }
  }
}

function TFlashInput()
{
  this.ID = "FlashInput";
  this.CallMethod = 0;
  
  this.BMouseIn = false;
  this.BLowResolution = false;

  this.dx = 600;
  this.dy = 224;
  
  this.SetLowResolution = function(bVal)
  {
    if(bVal)
      this.Call("listener.resolution", "low");
    else
      this.Call("listener.resolution", "high");
  }
  
  this.SetHighXYRatio = function(bVal)
  {
    if(bVal)
      this.Call("listener.XYRatio", "high");
    else
      this.Call("listener.XYRatio", "low");
  }
  
  this.SetMouseIn = function(bVal)
  {
    this.BMouseIn = bVal;
  }
  
  this.OnFlashLoaded = function()
  {
    /*if(this.BLowResolution)
    {
      this.SetYToStretch(this.dy);
    }*/
  }
  
  this.BFlashLoaded = false;
  
  this.IsFlashLoaded = function()
  {
    return this.BFlashLoaded;
  }
  
  this.SetFlashLoaded = function(bVal)
  {
    this.BFlashLoaded = bVal;
  }
  
  if(document.flashKeyboard)  this.CallMethod = 1;
  
  this.PlaceHere = function()
  {
	
    if(window.navigator.appName == "Microsoft Internet Explorer")
    {        
//      alert("this.ID="+this.ID);
      return "<span id='ID"+this.ID+"'><OBJECT codebase='' ID='IDFlashInput'><PARAM NAME='allowScriptAccess' VALUE='" + Environment.getScriptAccess() + "' />"+
        "<PARAM NAME='movie' VALUE='" + Environment.getResourceDirectory() + "flash/InputFields.swf'>" +
        "<EMBED WIDTH='" + this.dx + "' HEIGHT='" + this.dy + "' play='true' swliveconnect='true' name='FlashInput' src='" + Environment.getResourceDirectory() + "flash/InputFields.swf' quality='high' bgcolor='#FFFFFF' allowScriptAccess='" + Environment.getScriptAccess() + "' TYPE='application/x-shockwave-flash'></EMBED>"+
        "</OBJECT></span>";
    }
    return "<span id='ID"+this.ID+"'></span>";
  }
  
  this.Reset = function()
  {	
    document.getElementById("ID"+this.ID).innerHTML = "<OBJECT codebase='' ID='IDFlashInput'><PARAM NAME='allowScriptAccess' VALUE='" + Environment.getScriptAccess() + "' /><PARAM NAME='movie' VALUE='" + Environment.getResourceDirectory() + "flash/InputFields.swf'><EMBED style='display: block' WIDTH='" + this.dx + "' HEIGHT='" + this.dy + "' play='true' swliveconnect='true' name='FlashInput' src='" + Environment.getResourceDirectory() + "flash/InputFields.swf' quality='high' bgcolor='#FFFFFF' allowScriptAccess='" + Environment.getScriptAccess() + "' TYPE='application/x-shockwave-flash'></EMBED></OBJECT>";  
  }
  
  this.Clear = function()
  {
//	alert("FlashInput.Clear()");  
    document.getElementById("ID"+this.ID).innerHTML = "";
  }
  
  this.Focus = function()
  {
    document.getElementById(this.ID).focus();    
  }
  
  this.Call = function(p, arg)
  { 
    try
    {
      if(this.CallMethod == 0) 
      {
//        window.document["FlashInput"].SetVariable(p, arg);
      }
      else
      {
//        document.FlashInput.SetVariable(p, arg);
      }
    }
    catch(e)
    {
// warn about problem to access to FlashInput
    }
  }
  
  this.SetText = function(text)
  {  
    this.Call("listener.text", text);
  }
  this.SetText1 = function(text)
  {
//	alert("FlashImput.SetText1="+text);
    this.Call("listener.text1", text);
  }
  this.SetText2 = function(text)
  {
    this.Call("listener.text2", text); 
  }
  this.SetRegime = function(text)
  {
    this.Call("listener.regime", text); 
  }
  this.SetMode = function(text)
  {
    this.Call("listener.mode", text);
  }
  this.Error = function(ch)
  {
    this.Call("listener.error", ch);
  }
  this.FastError = function(ch)
  {
    this.Call("listener.fastError", ch);
  }
  this.StepForward = function()
  {
    this.Call("listener.action", "StepForward");
  }
  this.BegLine = function()
  {
    //this.Call("listener.action", "BeginExercise");
    this.Call("listener.action", "BeginLine");
  }
  this.BegExercise = function()
  {
    this.Call("listener.action", "BeginExercise");
  }
  this.SetModeNormal = function()
  {
     this.Call("listener.action", "SetModeNormal");
  }
  this.SetModeBottomFragments = function()
  {
     this.Call("listener.action", "SetModeBottomFragments");
  }
  this.ShowTypeHere = function()
  {
    this.Call("listener.action", "SetTypeHere");
  }  
  this.ResetContent = function() // use it for ie6 instead of Reset()
  {
    this.Call("listener.action", "Reset");
  }
  this.SetOperationSystem = function(opSystem)
  {
    this.Call("listener.operationSystem", opSystem);
  }
  this.BCanType = true;
  this.SetCanType = function(bCanType)
  {
//    alert("SetOperationSystem");
    if(bCanType == false) this.Call("listener.canType", "false");
    else
        this.Call("listener.canType", "true");
    
    this.BCanType = bCanType;
  }
  this.SetLayout = function(layout)
  {
      this.Call("listener.layout", layout);
  }
  this.GenerateOnloadMessage = function()
  {
      this.Call("listener.spec", "onloadMessage");
  }
  
  this.InitOS = function()
  {
    try
    {
      if(commonInfo.Language == "4") // 4 - English
        this.SetOperationSystem("Windows"); // do not recode chars
      else                
      if(IsWindows())
      {
	     this.SetOperationSystem("Windows"); // do not recode chars
      }
      else
      {
  	   this.SetOperationSystem("Other (not Windows)"); // recode chars
      }
    }
    catch(e) { }
  }
}

function TPhotoInfo()
{
  this.IsHint = function(numEx, typEx, nErrors)
  {
    switch(typEx)
    {
      case 1: case 6:
      if(nErrors == 0)
        return true;
      return false;
      default:;
    }
    return false;
  }
  this.GetNumOfPic = function(numEx, typEx, nErrors)
  {
     switch(typEx)
    {
      case 1: case 6:
      if(nErrors == 0) 
      {
        return parseInt(numEx);    
      }
      else 
      {
        return parseInt(numEx) + 100;
      }
      default:
        return 201;
    } 
  }
}

var PhotoInfo = new TPhotoInfo();

function TResultImg(id, path, ext)
{
  this.ID = id;
  this.Path = path;
  this.Ext = ext;
  this.GetNumOfPic = function(numEx, typEx, nErrors)
  {
      return PhotoInfo.GetNumOfPic(numEx, typEx, nErrors);
  }
  
  this.Update = function(numEx, typEx, nErrors)
  {
    var sPic = this.Path +
      String( this.GetNumOfPic(numEx, typEx, nErrors) ) + this.Ext;
    document.getElementById(this.ID).src = sPic; 
  }
  
}


String.prototype.SelectLinks = function()
{
  var mess = this;
  
  var mess2 = mess.match(/(http:\/\/|https:\/\/|http:\/\/www\.|www\.)([0-9a-zA-Z]+(\.|\/)){1,16}[a-zA-Z]+(\/)?(\?[0-9a-zA-Z]+=[%0-9a-zA-Z]+)?\S+/g);
  
  if(mess2 != null)
  for(var i = 0; i < mess2.length; i++)
  {
    mess3 = mess.replace(mess2[i], "<a href='" + mess2[i] + "'>"+mess2[i]+"</a>");
    mess = mess3;      
  }
  return mess;
}
