// @(#) $Id: util.js,v 1.5 2005/11/17 19:14:25 tom Exp $

/**
* @package lib5
* @subpackage util
* @version @(#) $Id: util.js,v 1.5 2005/11/17 19:14:25 tom Exp $
*/



function WOpen(name,url,w,h,s,r)
{
	return(window.open(url,name,"toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars="+s+",resizable="+r+",fullscreen=no,channelmode=no,width="+w+",height="+h));
}


//---------------------------------------------------------------------
//-----------UTIL------------------------------------------------------


function Util()
{
}
	Util.dec2HexHalf=function dec2HexHalf(b)
	{
		var s="0123456789abcdef";
		if(b>=0 && b<16)
			return(s.charAt(b));
		return("0");
	}
	Util.dec2Hex=function dec2Hex(d,len)
	{
		var res="";
		do {
			var b=(d&0xf);
			d>>=4;
			res=Util.dec2HexHalf(b)+res;
		} while(d!=0);
		if(len!=null)
			for(var i=res.length;i<len;i++)
				res="0"+res;
		return(res);
	}


	Util.rgb2Color=function rgb2Color(r,g,b)
	{
		var res="#";
		res+=Util.dec2Hex(r,2)+Util.dec2Hex(g,2)+Util.dec2Hex(b,2);
		return(res);
	}
// End of Util


//---------------------------------------------------------------------
//-----------LISTS-----------------------------------------------------


function ListElement(o)
{
	var self=new Object();
	self.data=o;
	self.prev=null;
	self.next=null;
	self.name=null;

	self.set=function set(o)
	{
		self.data=o;
	}

	self.get=function get()
	{
		return(self.data);
	}

	return(self);
}




function ListIterator(list)
{
	var self=new Object();
	self.list=list;
	self.lpointer=0;

	self.next=function next()
	{
		if(self.lpointer<self.list.length)
			return(self.list.item(self.lpointer++));
		return(null);
	}

	self.hasNext=function hasNext()
	{
		if(self.lpointer<self.list.length)
			return(true);
		return(false);
	}

	self.remove=function remove()
	{
		if(self.lpointer>0)
			self.list.remove(--self.lpointer);
	}

	return(self);
}




function List()
{
	var self=new Object();
	self.head=null;
	self.tail=null;
	self.length=0;

	self.add=function add(o)
	{
		var elem=new ListElement(o);
		if(self.head==null || self.tail==null)
		{
			self.head=elem;
			self.tail=elem;
		}
		else
		{
			elem.prev=self.tail;
			self.tail.next=elem;
			self.tail=elem;
		}
		self.length++;
		return(elem);
	}

	self.insert=function insert(n,newNode)
	{
		var o=self.getNode(n);
		if(o!=null)
			return(self.insertBeforeObject(o,newNode));
	}

	self.insertBeforeObject=function insertBeforeObject(node,newNode)
	{
		var elem=new ListElement(newNode);
		if(node.prev!=null)
			node.prev.next=elem;
		elem.prev=node.prev;
		elem.next=o;
		node.prev=elem;
		self.length++;
		if(self.head==node)
			self.head=elem;
		return(elem);
	}

	self.remove=function remove(n)
	{
		var o=self.getNode(n);
		if(o!=null)
		{
			if(self.head==o)
				self.head=o.next;
			if(self.tail==o)
				self.tail=o.prev;
			if(o.prev!=null)
				o.prev.next=o.next;
			if(o.next!=null)
				o.next.prev=o.prev;
			self.length--;
			return(o);
		}
		return(null);
	}

	self.removeNode=function removeNode(node)
	{
		var o=self.head;
		while(o!=null)
		{
			if(o==node)
				break;
			o=o.next;
		}
		if(o!=null)
		{
			if(self.head==o)
				self.head=o.next;
			if(self.tail==o)
				self.tail=o.prev;
			if(o.prev!=null)
				o.prev.next=o.next;
			if(o.next!=null)
				o.next.prev=o.prev;
			self.length--;
			return(o);
		}
		return(null);
	}

	self.getNode=function getNode(n)
	{
		if(n>=0 && n<self.length)
		{
			var o=self.head;
			while(n--)
				o=o.next;
			return(o);
		}
		return(null);
	}

	self.item=function item(n)
	{
		var o=self.getNode(n);
		if(o!=null)
			return(o.get());
		return(null);
	}

	self.contains=function contains(obj)
	{
		var o=self.head;
		while(o!=null)
		{
			if(o.data==obj)
				return(true);
			o=o.next;
		}
		return(false);
	}

	self.getNodeWithData=function getNodeWithData(obj)
	{
		var o=self.head;
		while(o!=null)
		{
			if(o.data==obj)
				return(o);
			o=o.next;
		}
		return(null);
	}

	self.getIterator=function getIterator()
	{
		return(new ListIterator(self));
	}

	self.toArray=function toArray()
	{
		var a=new Array();
		for(var i=0;i<self.length;i++)
			a[i]=self.item(i);
		return(a);
	}

	self.toString=function toString()
	{
		var res="List [";
		for(var i=0;i<self.length;i++)
		{
			if(i>0)
				res+=",";
			res+=self.item(i);
		}
		res+="]";
		return(res);
	}

	return(self);
}




function HashList()
{
	var self=new List();

	self.parent_add=self.add;
	self.add=function add(name,o)
	{
		self.parent_add(o).name=name;
	}

	self.get=function get(name)
	{
		var i, o;
		for(i=0;i<self.length;i++)
		{
			o=self.getNode(i);
			if(o!=null && o.name==name)
				return(o.get());
		}
		return(null);
	}

	self.getKey=function getKey(n)
	{
		if(n>=0 && n<self.length)
		{
			var o=self.head;
			while(n--)
				o=o.next;
			return(o.name);
		}
		return(null);
	}

	self.toString=function toString()
	{
		var res="List [";
		var o;
		for(var i=0;i<self.length;i++)
		{
			if(i>0)
				res+=",";
			o=self.getNode(i);
			res+=o.name+"="+o.data
		}
		res+="]";
		return(res);
	}

	return(self);
}




function Stack()
{
	var self=new List();

	self.push=function push(o)
	{
		self.add(o);
	}

	self.pop=function pop()
	{
		if(self.length==0)
			return(null);
		var o=self.item(self.length-1);
		self.remove(self.length-1);
		return(o);
	}

	self.peek=function peek()
	{
		if(self.length==0)
			return(null);
		return(self.item(self.length-1));
	}

	return(self);
}



//---------------------------------------------------------------------
//-----------TREE------------------------------------------------------

function TreeElement(o)
{
	var self=new Object();
	self.data=o;
	self.parentNode=null;
	self.firstChild=null;
	self.lastChild=null;
	self.nextNode=null;
	self.prevNode=null;

	self.set=function set(o)
	{
		self.data=o;
	}

	self.get=function get()
	{
		return(self.data);
	}

	self.getDepth=function getDepth()
	{
		var n=0;
		var o=self;
		while(o!=o.parentNode)
		{
			o=o.parentNode;
			n++;
		}
		return(n);
	}

	self.appendChild=function appendChild(newNode)
	{
		if(newNode==null)
			return(null);
		if(self.lastChild!=null)
		{
			self.lastChild.nextNode=newNode;
			newNode.prevNode=self.lastChild;
		}
		else
			self.firstChild=newNode;
		self.lastChild=newNode;
		newNode.parentNode=self;
		return(newNode);
	}

	self.prependChild=function prependChild(newNode)
	{
		if(newNode==null)
			return(null);
		if(self.firstChild!=null)
		{
			self.firstChild.prevNode=newNode;
			newNode.nextNode=self.firstChild;
		}
		else
			self.lastChild=newNode;
		self.firstChild=newNode;
		newNode.parentNode=self;
		return(newNode);
	}

	self.insertAfter=function insertAfter(newNode)
	{
		if(newNode==null)
			return(null);
		if(self==self.parentNode)
			return(null);
		newNode.parentNode=self.parentNode;
		newNode.prevNode=self;
		newNode.nextNode=self.nextNode;
		if(self.nextNode!=null)
			self.nextNode.prevNode=newNode;
		else
			self.parentNode.lastChild=newNode;
		self.nextNode=newNode;
		return(newNode);
	}

	self.insertBefore=function insertBefore(newNode)
	{
		if(newNode==null)
			return(null);
		if(self==self.parentNode)
			return(null);
		newNode.parentNode=self.parentNode;
		newNode.nextNode=self;
		newNode.prevNode=self.prevNode;
		if(self.prevNode!=null)
			self.prevNode.nextNode=newNode;
		else
			self.parentNode.firstChild=newNode;
		self.prevNode=newNode;
		return(newNode);
	}

	self.removeNode=function removeChild(oldNode)
	{
		if(oldNode==null)
			return(null);
		if(oldNode.prevNode==null)
			oldNode.parentNode.firstChild=oldNode.nextNode;
		if(oldNode.nextNode==null)
			oldNode.parentNode.lastChild=oldNode.prevNode;

		if(oldNode.prevNode!=null)
			oldNode.prevNode.nextNode=oldNode.nextNode;
		if(oldNode.nextNode!=null)
			oldNode.nextNode.prevNode=oldNode.prevNode;

		oldNode.parentNode=oldNode.prevNode=oldNode.nextNode=null;
		return(oldNode);
	}

	self.hasChildNodes=function hasChildNodes()
	{
		return(self.firstChild!=null);
	}


	return(self);
}




function Tree()
{
	var self=new Object();
	self.rootNode=null;

	self.setRootNode=function setRootNode(newNode)
	{
		self.rootNode=newNode;
		self.rootNode.parentNode=self.rootNode;
		return(self.rootNode);
	}

	self.getRootNode=function getRootNode()
	{
		return(self.rootNode);
	}

	return(self);
}




function TreeLeafIterator(parentNode)
{
	var self=new Object();
	if(parentNode!=null)
		self.node=parentNode.firstChild;
	else
		self.node=null;

	self.next=function next()
	{
		if(self.node==null)
			return(null);
		var o=self.node;
		self.node=self.node.nextNode;
		return(o);
	}

	self.hasNext=function hasNext()
	{
		if(self.node==null)
			return(false);
		return(self.node.nextNode!=null);
	}

	return(self);
}




//---------------------------------------------------------------------
//---------------------------------------------------------------------

function log()
{
	var o=document.getElementById("log");
	if(o==null)
		o=document.body;
	if(o!=null)
	{
		var s="";
		var i;
		for(i=0;i<arguments.length;i++)
		{
			if(i>0)
				s+=",";
			s+=arguments[i];
		}
		o.appendChild(document.createTextNode(s+" "));
	}
}


var dumpList,dumpParentList=new Stack();


function js_dump_function(o)
{
	var w=WOpen(null,"dump_function",400,300,"yes","yes");
	var res="";
	res+="<pre>";
	res+=o;
	res+="</pre>";
	w.document.open();
	w.document.write(res);
	w.document.close();
}


function js_dump(obj)
{
var e,s,name,res="";
var s="";

	res+="<html><body style=\"font-family:helvetica,arial;font-size:10pt\">";

	dumpList=new HashList();

	if(dumpParentList.peek()!=null)
		res+="<span style=\"cursor:pointer;color:white;background-color:green\" onClick=\"opener.dumpParentList.pop();opener.js_dump(opener.dumpParentList.pop())\">&nbsp;&lt;&lt;&nbsp;</span><br><br>";
	dumpParentList.push(obj);

	try {
		s=obj.toString();
	} catch(e) {
		s=obj;
	}
	res+="<b>Dump of "+s+"</b><br><br>\n";
	try {
		for(name in obj)
		{
			if(name=="dumpList" || name=="dumpParentList")
				continue;
			try {
				o=obj[name];
				dumpList.add(name,o);
				res+="<span style=\"cursor:pointer;color:blue\" onClick=\"opener.js_dump(opener.dumpList.get('"+name+"'))\">"+name+"</span>";
				res+=" <font color='green'>["+typeof(o)+"]</font>";
				if(typeof(o)=="function")
					res+=" <font color='brown'><span style=\"cursor:pointer\" onClick=\"opener.js_dump_function(opener.dumpList.get('"+name+"'))\">function ...</span></font>";
				else
					res+=" <font color='brown'>"+o+"</font>";
			} catch(e) {
				res+="<font color='red'>"+name+" ("+e+")</font>";
			}
		res+="<br>\n";
		}
	} catch(e) {}

	res+="</body></html>";
	w=WOpen("dump","",400,600,"yes","yes");
	w.document.open();
	w.document.write(res);
	w.document.close();
}




function _js_dump_r(obj,level)
{
var e,s,i,name,ident="",res="";

//	if(level>5)
//		return(res);

	if(level!=null)
		for(i=0;i<level;i++)
			ident+="+--";
	if(dumpList.contains(obj))
		return(ident+"**RECURSION**<br>");
	dumpList.add(obj);

	try {
		s=obj.toString();
	} catch(e) {
		s=obj;
	}

	try {
		for(name in obj)
		{
			if(name=="dumpList" || name=="dumpParentList")
				continue;
			try {
				o=obj[name];
//				if(typeof(o)!="object")
//					continue;
				res+=ident+name+" <font color=\"green\">"+s+"</font>";
				if(typeof(o)=="function")
					res+=" <font color='brown'>function</font>";
				else
					res+=" <font color='brown'>"+o+"</font>";
				res+="<br>";
				if(typeof(o)=="object")
					res+=_js_dump_r(o,level+1);
			} catch(e) {
				res+=ident+"<font color=\"red\">"+name+"</font><br>";
			}
		}
	} catch(e) {}
	return(res);
}


function js_dump_r(obj)
{
var e,name,res="";
var s="";

	dumpList=new List();
	res+="<html><body style=\"font-family:helvetica,arial;font-size:10pt\">";

	try {
		s=obj.toString();
	} catch(e) {
		s=obj;
	}
	res+="<b>Dump of "+s+"</b><br><br>\n";

	res+=_js_dump_r(obj,0);

	res+="</body></html>";
	w=WOpen("dump","",400,600,"yes","yes");
	w.document.open();
	w.document.write(res);
	w.document.close();
}

