
// Refresh the 'framemenu' frame, which is usually the left-bottom frame.
function refreshFramemenu() {
  if( parent ){
    var menu = parent.frames["framemenu"];
    if( menu ) menu.location.href = menu.location.href;
  }
}

function linker()
{
  if(document.all && document.all.item)
  { // MSIE
    var i,l=document.links
    for(i=0;i<l.length;i++)
   {
    l[i].onfocus=function(){this.blur()}
    }
  }
}


// Remember the path of the current liable object.
// The path is stored in the parent (frameset) to be somewhat persistent.
// Old path is preserved if both the 'structure' and the 'repository' parameters are empty.
function setLiableObjectPath( structure, repository ) {
  if( ! parent ) return;
  if( 0 != structure.length ){
    if( parent.liableObjectStructurePath == null ) return;
    parent.liableObjectStructurePath = structure;
  }
  if( 0 != repository.length ){
    if( parent.liableObjectRepositoryPath == null ) return;
    parent.liableObjectRepositoryPath = repository;
  }
}
// Return a Repository path remembered using the 'setLiableObjectPath' function.
// Empty string is returned if the 'liable object path' is not available.
function getLiableObjectRepositoryPath() {
  if( ! parent ) return "";
  if( parent.liableObjectRepositoryPath == null ){
    alert( "parent.liableObjectRepositoryPath is not declared" ); return "";
  }
  return parent.liableObjectRepositoryPath;
}
// Return a Structure path remembered using the 'setLiableObjectPath' function.
// Empty string is returned if the 'liable object path' is not available.
function getLiableObjectStructurePath() {
  if( ! parent ) return "";
  if( parent.liableObjectStructurePath == null ){
    alert( "parent.liableObjectStructurePath is not declared" ); return "";
  }
  return parent.liableObjectStructurePath;
}

// This function returns the index of the cursor location in
// the value of the input text element.
// It is important to make sure that the sWeirdString variable contains
// a set of characters that will not be encountered normally in your text.
function getCursorPos( textElement ) {
  
  // Mozilla have "selectionStart" property.
  
  try{
    if( textElement.selectionStart || textElement.selectionStart == '0' )
      return textElement.selectionStart;
  }catch( ignored ){}
  
  // The rest is for the MSIE.
  
  var objRange;
  if( document.selection && ( objRange = document.selection.createRange() ) ){
    // save off the current value to restore it later,
    var sOldText = textElement.value;
    
    // create a range object and save off it's text
    var sOldRange = objRange.text;
    // Ignore the text when multiple characters are selected.
    if( sOldRange.length > 0 ) return 0;
    
    // set this string to a small string that will not normally be  encountered
    var sWeirdString = '~@^+{-o-}+^@~';
    
    // insert the weirdstring where the cursor is at
    objRange.text = sOldRange + sWeirdString;
    objRange.moveStart('character', (0 - sOldRange.length - sWeirdString.length));
    
    // save off the new string with the weirdstring in it
    var sNewText = textElement.value;
    
    // set the actual text value back to how it was
    objRange.text = sOldRange;
    
    // look through the new string we saved off and find the location of
    // the weirdstring that was inserted and return that value
    var i = sNewText.indexOf( sWeirdString );
    if( -1 != i ) return i;
  }
  
  return 0;
}

// Take the absolute position in the text element
// and return the corresponding "row" and "col" offsets.
// @return an Object with "row" and "col" fields.
function posToRow( text, pos ){
  var res = new Object();
  res.row = 1;
  res.col = 1;
  
  if( pos < 1 ) return res;
  
  var n = 0;
  var lines = 1;
  var lastLinePos = 0;
  var skipNext = ' ';

  var nextR = text.indexOf( '\r' ); if( -1 == nextR ) nextR = text.length;
  var nextN = text.indexOf( '\n' ); if( -1 == nextN ) nextN = text.length;
  
  while( n < pos ){
    if( nextR < n ){ nextR = text.indexOf( '\r', n ); if( -1 == nextR ) nextR = text.length; }
    if( nextN < n ){ nextN = text.indexOf( '\n', n ); if( -1 == nextN ) nextN = text.length; }
    
    n = nextR < nextN ? nextR : nextN;
    ++n;
    if( nextN == nextR + 1 ) ++n;
    
    if( n > pos ) break;
    
    ++lines;
    lastLinePos = n;
  }
  res.row = lines;
  res.col = pos - lastLinePos + 1;
  return res;
}

// Indent Velocity text to made its structure obvious.
function indentVm( text ){
  if( text.length < 1 ) return text;
  
  var buf = "";
  
  var n = 0;
  var nextR = text.indexOf( '\r' ); if( -1 == nextR ) nextR = text.length;
  var nextN = text.indexOf( '\n' ); if( -1 == nextN ) nextN = text.length;
  
  var tab = 0;
  var openers = new Array();
  openers.unshift( new RegExp( "#" + "if[ \\t]*\\(", "g" ) );
  openers.unshift( new RegExp( "#" + "macro[ \\t]*\\(", "g" ) );
  openers.unshift( new RegExp( "#" + "foreach[ \\t]*\\(", "g" ) );
  openers.unshift( new RegExp( "#" + "else\\b", "g" ) );
  openers.unshift( new RegExp( "#" + "elseif[ \\t]*\\(", "g" ) );
  var closers = new Array();
  closers.unshift( new RegExp( "#" + "end\\b", "g" ) );
  closers.unshift( new RegExp( "#" + "else\\b", "g" ) );
  closers.unshift( new RegExp( "#" + "elseif[ \\t]*\\(", "g" ) );
  var openersLen = openers.length;
  var closersLen = closers.length;
  var textLen = text.length;
  while( n < textLen ){
    var prevN = n;
    if( nextR < n ){ nextR = text.indexOf( '\r', n ); if( -1 == nextR ) nextR = textLen; }
    if( nextN < n ){ nextN = text.indexOf( '\n', n ); if( -1 == nextN ) nextN = textLen; }
    
    n = nextR < nextN ? nextR : nextN;
    ++n;
    if( nextN == nextR + 1 ) ++n;
    
    var line = text.substring( prevN, n );
    var cut = 0;
    while( cut < line.length && ( line.charAt( cut ) == ' ' || line.charAt( cut ) == '\t' ) ) ++cut;
    line = line.substring( cut, line.length );
    
    var closed = 0;
    for( var i = 0; i < closersLen; ++i ) closed += countVmEnt( line, closers[ i ] );
    var opened = 0;
    for( var i = 0; i < openersLen; ++i ) opened += countVmEnt( line, openers[ i ] );
    var controlOffset = 0
    if( closed > opened ) controlOffset = opened - closed;
    else if( line.indexOf( "#" + "else" ) == 0 ) controlOffset = -1;
    
    var spacing = ( tab + controlOffset ) * 2;
    if( spacing < cut ){
      if( line.length == 0 ) spacing = cut;
      if( line.length >= 2 && ( line.charAt(0) != '#' || line.charAt(1) == '#' ) ) spacing = cut;
    }
    for( var i = 0; i < spacing; ++i ) line = " " + line;
    buf += line;
    
    tab -= closed;
    tab += opened;
  }
  return buf;
}
// A helper function used in indentVm.
function countVmEnt( line, pattern ){
  var comment = line.indexOf( "#" + "#" );
  if( -1 != comment ) line = line.substring( 0, comment );
  
  var counter = 0;
  while( null != pattern.exec( line ) ) ++ counter;
  return counter;
}


var curtab = 1;
			function tabClick(tab)
			{
				document.getElementById("tab" + curtab).className = "tab";
				document.getElementById("div" + curtab).className = "hide";
				curtab = tab;
				document.getElementById("tab" + curtab).className = "tab-selected";
				document.getElementById("div" + curtab).className = "show";
			}
			function init()
			{
				document.getElementById("tab" + curtab).className = "tab-selected";
				document.getElementById("div" + curtab).className = "show";
			}
