// common functions
// copyright iBlocks 2002
// Julian George


// ibrowser() ====================================================================

//* OBJ DFN:ibrowser * what type of browser are we using?

function ibrowser(){ 
  this.ver=navigator.appVersion;
  this.agent=navigator.userAgent;
  this.dom=document.getElementById?1:0;
  this.opera5=this.agent.indexOf("Opera 5")>-1;
  this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0; 
  this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
  this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
  this.ie=this.ie4||this.ie5||this.ie6;
  this.mac=this.agent.indexOf("Mac")>-1;
  this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0; 
  this.ns4=(document.layers && !this.dom)?1:0;
  // supported browsers
  this.sp=(this.ie6||this.ie5||this.ie4||this.ns6||this.opera5);   
  this.platform = navigator.platform;
  return this;
}

browser = new ibrowser();


// getElementById() ===============================================================

// Finds objects on a pre-W3C Dom browser
function MM_findObj(n, d) 
{ 
	var p, i, x;  	 
	if ((p = n.indexOf("?"))>0 && parent.frames.length) 
	{
		d = parent.frames[n.substring(p+1)].document; 
		n = n.substring(0,p);
	}
	if (!(x=d[n]) && d.all) x = d.all[n]; 
	for (i=0; !x && i<d.forms.length; i++) x=d.forms[i][n];
	for (i=0; !x&&d.layers&&i<d.layers.length; i++) x=MM_findObj(n, d.layers[i].document); 
	return x;
}

// Finds objects on a page on a pre W3CDOM or W3CDOM browser
function getElementById(Id, d)
{
    if (!d) d=document;
	if (browser.ns6)
	{
		return d.getElementById(Id);										
	} else if (browser.ie) {	    		
		return eval('d.all["'+Id+'"]');
	} else {
		return MM_findObj(Id, d);
	}
}


//Document size object ********
function docSize(){ 
  this.x=0;this.x2=browser.ie && document.body.offsetWidth-20||innerWidth||0;
  this.y=0;this.y2=browser.ie && document.body.offsetHeight-5||innerHeight||0;
  if(!this.x2||!this.y2) return false;
  this.x50=this.x2/2;this.y50=this.y2/2;
  return this;
}

// FIFOStack() =========================================================================

// simple FIFO stack implementation
function FIFOStack(stackSize, ErrorMsg){

  this.addPointer = 0;
  this.takePointer = 0;
  this.theStack = new Array();
  this.stackSize = stackSize;
  this.overwrite = false;  
  this.ErrMsg = (ErrorMsg)?ErrorMsg:null;

  // initialise the stack with null elements
  this.clear();
  
}

FIFOStack.prototype.push = function(key, stackElement) { 
  var stackRtn;
  if (this.theStack[this.addPointer]==null || this.overwrite) {
   this.theStack[this.addPointer] = [key, stackElement];
   this.addPointer = (this.addPointer+1)%this.stackSize;
   stackRtn = true;
  } else {
   if (this.ErrMsg) alert(this.ErrMsg);
   stackRtn = false;   
  }
  return stackRtn;
}

FIFOStack.prototype.pop = function() { 
  if (this.theStack[this.takePointer]!=null) {
   stackElement = this.theStack[this.takePointer][1];
   this.theStack[this.takePointer] = null;
   this.takePointer = (this.takePointer+1)%this.stackSize;   
   return stackElement;
  } else {   
   return null;
  }
}

FIFOStack.prototype.peak = function(pointer) { 
   var thePointer = pointer?(pointer+this.takePointer)%this.stackSize:this.takePointer;
   if (this.theStack[thePointer])
     return this.theStack[thePointer][1];
   else 
     return null;
}

FIFOStack.prototype.clear = function() {           
  for(var i=0; i<this.stackSize; i++) this.theStack[i] = null;
}

FIFOStack.prototype.setOverwrite = function() {
  this.overwrite = true;
}

FIFOStack.prototype.freeSize = function() { 

  var freeCount = 0;

  if (this.overwrite) {
    freeCount = -1;
  } else if (this.theStack[this.addPointer]==null) {

   if ((this.takePointer)%this.stackSize<(this.addPointer+1)%this.stackSize) {
     freeCount = this.stackSize - (this.addPointer+1)%this.stackSize + (this.takePointer)%this.stackSize;
   } else {
     freeCount = this.stackSize + (this.addPointer+1)%this.stackSize - (this.takePointer)%this.stackSize;
   }
  } 

  return freeCount;
}

// searches the stack sequentially for keyed entries 
// [(element[0] of each entry) == (key)]
// from the point of last addition
// returns the stack element or null if not found

FIFOStack.prototype.search = function(key) {

  for(var i=(this.addPointer-1)%this.stackSize; i<this.addPointer+this.stackSize; i++){

    if(this.theStack[i%this.stackSize]){
      if (this.theStack[i%this.stackSize][0] == key){
	    return this.theStack[i%this.stackSize][1];
	  }
	}
  }
  return null;

}

// as above, searches the stack, but this time
// it pulls the element out of the stack,
// removing the null space. 
// WARNING: Not a quick function on larger statcks!
// returns pulled element
FIFOStack.prototype.pull = function(key){

  for(var i=(this.addPointer-1)%this.stackSize; i<this.addPointer+this.stackSize; i++){

   if(this.theStack[i%this.stackSize]){
	if (this.theStack[i%this.stackSize][0] == key){
	    var pulledElement = this.theStack[i%this.stackSize][1];
		if (this.takePointer>=i%this.stackSize){
          this.theStack = this.theStack.slice(0,i%this.stackSize).concat(this.theStack.slice(i%this.stackSize+1,this.takePointer), null, this.theStack.slice(this.takePointer));
		}else{
		  this.theStack = this.theStack.slice(0,this.takePointer).concat(null, this.theStack.slice(this.takePointer,i%this.stackSize), this.theStack.slice(i%this.stackSize+1));		  
          this.takePointer = (this.takePointer+1)%this.stackSize;
		}                
		return pulledElement;
	}
   }
  }
  return null;
}

// ibTimer() ==================================================================

function ibTimer(timeOut, timerName, exitFunc) {
  this.timerName = timerName;
  this.timeOut = timeOut;
  this.timer = 0;
  this.started = false;
  this.exitFunc = exitFunc;
}

ibTimer.prototype.start = function (){
  if (!this.started) {
    setTimeout(this.timerName+".iterate()", 10);
	this.started = true;
  }
}

ibTimer.prototype.reset = function (){
  this.started = false;
  this.timer = 0;
}

ibTimer.prototype.iterate = function (){
  if (this.started){    
	if (this.timer>this.timeOut) {
      eval(this.exitFunc);
	} else {
      this.timer+=10;	
      setTimeout(this.timerName+".iterate()", 10);
	}
  }
}

// =========================================================================

function addParameters(paramList, newParamsList) {

    var rtnParamList = new Array();
	
	// remove existing elements from param list
    for(var i=0; i<paramList.length; i++){

	  var containsParam = false;
	  for(var j=0; j<newParamsList.length; j++){
		  if(paramList[i][0] == newParamsList[j][0]) {
             containsParam = true;
		  }
	  }

      if (!containsParam) {
         rtnParamList = manualConcat(rtnParamList, [paramList[i]]);
	  }

	}

	// add the new element
    rtnParamList = manualConcat(rtnParamList, newParamsList);

	return rtnParamList;

}