// XLinterface/PHP/2.8.5

	window.xl_loaded = '2.8.5';

	var mouX = 0;
	var mouY = 0;
	var mouZ = 0;
	var anyO = false;

	document.onmousedown	= getmouseXY;
	window.onmousedown	= getmouseXY;

	function jsXLviewer(name, instance, sidkey, sidval, address, sitepath)
	{
		this.name	= name;
		this.instance	= instance;

		var imgname = this.name + "_" + this.instance;
		if (typeof(document.images[imgname]) == 'undefined')
		{
			alert("ERROR in HTML code: image " + imgname + " not found");
			return false;
		}

		this.img	= document.images[imgname];

		if (typeof(sitepath)== 'undefined')
		{
			alert("ERROR in PHP code: sitepath not passed");
			return false;
		}
		this.imgscript	= sitepath + 'xlimg.php';
		this.imgscript	+= '?' + sidkey + '=' + sidval + '&addr=' + address;

		this.command	= jsXL_command;
		this.update	= jsXL_update;
		this.thupdate	= jsXL_thumb_update;
		this.load	= jsXL_load;
		this.url	= jsXL_url;
		this.check	= jsXL_range_check;
		this.select	= jsXL_select;
		this.selected	= jsXL_selected;
		this.setzoom	= jsXL_setzoom;
		this.opaque	= jsXL_opacity;
		this.doGo	= jsXL_do;
		this.custom	= new Array;
		this.zslider	= false;
		this.opacity	= 100;
		this.thumbsize	= 0;		// Thumb size disregarded
		this.fndx	= -1;

		if (false == anyO)
		{
			anyO	= this;
			window.setInterval(jsXL_keepalive, 10 * 60000);
		}

		if (window.status)
			window.status	= 'XLimg JSapplet ' + this.name + ':' + this.instance + ' created.';
	}

	function getmouseXY(e)
	{
		// window.scrollX, window.scrollY,
		if (document.all)
		{
			// Internet Explorer
			mouX = event.clientX;
			mouY = event.clientY;
			if (self.document.compatMode)
			{
				if (document.getElementById)
				{
					mouX = event.x;
					mouY = event.y;
				}
				else
				{
					if (self.document.compatMode == 'CSS1Compat')
					{
						mouX	+= document.documentElement.scrollLeft;
						mouY	+= document.documentElement.scrollTop;
					}
					else
					{
						mouX	+= document.body.scrollLeft;
						mouY	+= document.body.scrollTop;
					}
				}
			}
			mouZ = (event.shiftKey ? 1:0) + (event.ctrlKey ? 2:0);
			if (self.document.disablerclick)
				if (2 == event.button)
					return false;
		}
		else
		{
			/* Mozilla */
			mouX = e.pageX;
			mouY = e.pageY;
			mouZ = (e.shiftKey ? 1:0) + (e.ctrlKey ? 2:0);
			if ((2 == e.which) || (3 == e.which))
				return false;
		}
		return true;
	}

	function jsXL_range_check()
	{
		var hw = Math.floor(this.width / 2);
		var hh = Math.floor(this.height / 2);
		if (this.zoom > this.zmax)
		{
			// alert("Zoom " + this.zoom + ", max is " + this.zmax);
			this.zoom = this.zmax;
		}
		if (this.zoom < this.maxzoom)
		{
			if (this.zoom != 0)
			{
				// alert("Zoom " + this.zoom + ", min is " + this.maxzoom);
				this.zoom = this.maxzoom;
			}
		}
		if (this.width * this.zoom > this.im_w)
			this.cur_x = Math.floor(this.im_w / 2);
		else
		{
			var zhw = hw * this.zoom;
			if (this.cur_x < zhw)
				this.cur_x = zhw;
			if (this.cur_x > this.im_w - zhw)
				this.cur_x = this.im_w - zhw;
		}
		if (this.height * this.zoom > this.im_h)
			this.cur_y = Math.floor(this.im_h / 2);
		else
		{
			var zhh = hh * this.zoom;
			if (this.cur_y < zhh)
				this.cur_y = zhh;
			if (this.cur_y > this.im_h - zhh)
				this.cur_y = this.im_h - zhh;
		}
	}

	function jsXL_resize (w, h)
	{
		this.width	= w;
		this.height	= h;
		this.check();
	}

	function jsXL_setzoom(z)
	{
		if (z)
		{
			this.zoom = Math.floor(200.0 / z);
			this.command('in');
			return;
		}
		var aspect	= Math.max(this.im_w / this.width, this.im_h / this.height);
		this.command('fit');
	}

	function jsXL_command(cmd)
	{
		var hw = Math.floor(this.width  / 2);
		var hh = Math.floor(this.height / 2);
		var px = 0;
		var py = 0;
		var cx = this.cur_x;
		var cy = this.cur_y;
		var cz = this.zoom ? this.zoom : 1;
		var fitting     = (0 == this.zoom);     // TRUE or FALSE
		var sk = false;

		// document.write("Error 25: " + cmd + "<br/>"); return;

		switch(cmd)
		{
			case 'in':
				this.zoom = cz / 2.0;
				break;
			case 'out':
				this.zoom = cz * 2.0;
				break;
			case 'left':
				px = -hw;
				break;
			case 'right':
				px = hw;
				break;
			case 'up':
				py = -hh;
				break;
			case 'down':
				py = hh;
				break;
			case 'ffirst':
				sk = this.select(0);
				break;
			case 'flast':
				sk = this.select(this.vSt_hash.length - 1);
				break;
			case 'fprev':
				if (this.fndx > 0)
					sk = this.select(this.fndx-1);
				break;
			case 'fnext':
				if (this.fndx < (this.vSt_hash.length -1))
					sk = this.select(this.fndx+1);
				break;
			case 'reset':
				this.cur_x = this.im_w / 2.0;
				this.cur_y = this.im_h / 2.0;
				this.zoom  = this.zmax;
				break;
			case 'fit':
				this.cur_x = this.im_w / 2.0;
				this.cur_y = this.im_h / 2.0;
				this.zoom  = 0;
				break;
			default:
				alert('unknown command: ' + cmd);
			break;
		}
		// Put back into place things
		if (sk)
		{
			cx	= this.cur_x;
			cy	= this.cur_y;
			cz	= this.zoom ? this.zoom : 1;
			fitting	= (0 == this.zoom);
		}
		// Now, if we're fitting, zoom must be handled specially. Unless unchanged.
		// NOTICE: "fitting" means this.zoom is zero *NOW*.

		if (0.5 == this.zoom)
		{
			// Actually we COULD halve imag size and rely on
			// browser's capabilities... not too honest to do
			window.status = 'cannot zoom more than that';
			this.zoom = 1;
		}

		if ((cz != this.zoom) && fitting)
		{
			// Now, this.zoom is either 0.5 (zoom in) or 2 (zoom out).
			// We can consider it as a factor.
			// We need the "virtual" zoom.

			var zx, zy, zt;
			zx	= this.im_w / this.width;
			zy	= this.im_h / this.height;
			if (zx < zy)
				zx = zy;
			// The math expression below is the "virtual" zoom.
			// We multiply it by the "virtual" factor obtained from commanding
			// a fake zoom of 1 (so 0.5 = zoom in, 2.0 = zoom out)
			for (zt = 1; zt/zx < 1; zt *= 2)
				;
			this.zoom *= zt;
			if (this.zoom != 0)
			{
				// We are COMING OUT of a fit
				this.cur_x = 0;
				this.cur_y = 0;
			}
		}
		this.cur_x += px * cz;
		this.cur_y += py * cz;
		this.check();

		if ((cx == this.cur_x) && (cy == this.cur_y))
			if (this.zoom != this.maxzoom)
				if (false == sk)
					if (cz == this.zoom)
						return;
		this.load(0);
		this.load(1);
		if (cz == this.zoom)
			return;
		if (this.zslider)
		{
			var i;
			var n = this.zform.abszoom.length;
			for (var i = 0; i < n; i++)
			{
				var radio = this.zform.abszoom[i];
				if (radio.value != "0")
					radio.checked = (this.zoom == (100/radio.value));
				else
					radio.checked = (this.zoom == radio.value);
			}
		}
	}

	function jsXL_update (px, py)
	{
		if (this.zoom)
		{
			this.cur_x += Math.floor((px - this.width /2)* this.zoom);
			this.cur_y += Math.floor((py - this.height/2)* this.zoom);
		}
		else
		{
			var zx, zy, zt;
			zx	= this.im_w / this.width;
			zy	= this.im_h / this.height;
			if (zx < zy)
				zx = zy;
			for (zt = 1; zt/zx < 1; zt *= 2)
				;
			this.zoom  = zt;
			this.cur_x = Math.floor(this.im_w * px / this.width);
			this.cur_y = Math.floor(this.im_h * py / this.height);
		}
	}

	// The thumbnail receives click at coordinates px, py
	function jsXL_thumb_update (px, py)
	{
		if (this.fixedt > 0)
		{
			this.cur_x = px * this.im_w / this.th_w;
			this.cur_y = py * this.im_h / this.th_h;
		}
		else
		{
			this.cur_x = px * this.thumb_zoom;
			this.cur_y = py * this.thumb_zoom;
		}
		this.check();
	}

	function jsXL_url(thidx)
	{
		var url	= this.imgscript;
		var amp = '&';
		var type;

		switch(thidx)
		{
			case 0:
				type	= 'image_f';
				break;
			case 1:
				type	= 'thumb';
				break;
			case 2:
			{
				// imgscript will read bgimages, set by XLinterfaceFn.
				type	= 'image_b';
				break;
			}
		}

		url += amp + 'type='	+ type;
		url += amp + 'name='	+ this.name + ':' + this.instance; 
		url += amp + 'n='	+ this.fndx;
		url += amp + 'x='	+ this.cur_x;
		url += amp + 'y='	+ this.cur_y;
		url += amp + 'w='	+ this.width;
		url += amp + 'h='	+ this.height;
		url += amp + 'z='	+ this.zoom;
		url += amp + 'b='	+ this.bg;
		url += amp + 'q='	+ this.im_q;
		url += amp + 'addr='	+ this.addr;
		url += amp + 'im_w='	+ this.im_w;
		url += amp + 'im_h='	+ this.im_h;
		url += amp + 'zmax='	+ this.zmax;

		if ('' != this.ip)	url += amp + 'ip=' + this.ip;
		if ('' != this.it)	url += amp + 'it=' + this.it;
		if ('' != this.ig)	url += amp + 'ig=' + this.ig;

		if (1 == thidx)
		{
			url += amp + 'tw=' + Math.floor(this.th_w);
			url += amp + 'th=' + Math.floor(this.th_h);
		}

		for (custKey in this.custom)
			url += amp + custKey + '=' + escape(this.custom[custKey]);

		return url;
	}

	function jsXL_keepalive()
	{
		anyO.load(1, true);
	}

	function jsXL_load(thidx, rac)
	{
		if (thidx > this.img.length)
			return;
		if (typeof(this.img[thidx]) == 'undefined')
			return;
		var trg = this.img[thidx];
		var url	= this.url(thidx);
		var cur	= false;

		if (trg.style)
			if (trg.style.cursor)
				cur = trg.style.cursor;
		if (cur != false)
			trg.style.cursor = 'wait';
		if (arguments.length > 1)
			if (true == rac)
				url += "&rac=" + Math.random();
		trg.src	= url;

		switch(thidx)
		{
			case 0:	// IMAG
				pid	= document.getElementById("parent_" + this.name + "_" + this.instance);
				pid.style.backgroundRepeat	= "no-repeat";
				if (0 == this.hasbg)
				{
					pid.style.backgroundImage	= ''; // "url(" + trg.src + ")";
					break;
				}
				this.opaque();
				pid.style.backgroundImage	= "url(" + this.url(2) + ")";
				break;
			case 1:	// THUMBNAIL
				if (0 != this.thumbscale)
				{
					/*
					trg.width	= this.thumb_w / this.thumbscale;
					trg.height	= this.thumb_h / this.thumbscale;
					*/
				}
				break;
		}
		if (cur != false)
			trg.style.cursor = cur;
	}

	function jsXL_do(obj, cmdNormal, cmdCtrl, cmdShift)
	{
		var cmd, imgX, imgY;

		imgX = mouX;
		imgY = mouY;
	
		if (!document.all)
		{
			imgX -= obj.offsetLeft;
			imgY -= obj.offsetTop;
		}
		else
		{
		}

		// alert(imgX + "," + imgY);

		switch(arguments.length)
		{
			case 1:	cmdNormal	= 'gotoxy';
			case 2:	cmdCtrl		= cmdNormal;
			case 3: cmdShift	= cmdCtrl;
			case 4:	break;
		}
		switch(mouZ)
		{
			case 0: cmd = cmdNormal;	break;
			case 1: cmd = cmdShift;		break;
			case 2: cmd = cmdCtrl;		break;
		}
		switch(cmd)
		{
			case 'in':
			case 'out':
				this.update(imgX, imgY);
				this.command(cmd);
				break;
			case 'gotoxy':
				this.thupdate(imgX, imgY);
				this.load(0);
				this.load(1);
				// TODO
				break;
			case 'mark':
				mark_function(this, imgX, imgY);
				break;
		}
		window.status = 'OK';
	}

	function jsXL_select(n)
	{
		var z;
		if (this.fndx == n)
			return true;

		if (this.fndx != -1)
		{
			this.vSt_hash[this.fndx]= this.xlimg
					+ ',' + this.zmax
					+ ',' + this.im_w + ',' + this.im_h
					+ ',' + this.th_w + ',' + this.th_h
					+ ',' + this.cur_x+ ',' + this.cur_y
					+ ',' + this.zoom;
			// alert('Saved ' + this.fndx + ' at zoom ' + this.zoom);
		}
		this.fndx	= n;

		var s = this.vSt_hash[this.fndx];
		var v = s.split(',');

		this.xlimg	= v[0];
		this.zmax	= Math.floor(v[1]);
		this.im_w	= Math.floor(v[2]);
		this.im_h	= Math.floor(v[3]);
		this.th_w	= Math.floor(v[4]);
		this.th_h	= Math.floor(v[5]);
		this.cur_x	= Math.floor(v[6]);
		this.cur_y	= Math.floor(v[7]);
		this.zoom	= Math.floor(v[8]);

		// alert('Loaded ' + this.fndx + ' at zoom ' + this.zoom);

		var selzoom = -1;

		for (z = 1; z < 1024; z*=2)
		{
			var chkzoom = document.getElementById("zoomspan" + z);
			if (null == chkzoom)
				continue;
			document.getElementById("zoomcheck" + z).checked = false;
			if (z > this.zmax)
			{
				// Disable
				chkzoom.disabled	= true; 
				chkzoom.readonly	= true;
				chkzoom.style.display	= 'none';
				continue;
			}
			// Enable
			chkzoom.disabled	= false; 
			chkzoom.readonly	= false;
			chkzoom.style.display	= 'block';
			if (z == this.zoom)
				selzoom = z;
		}
		if (selzoom != -1)
		{
			var chkzoom = document.getElementById("zoomcheck" + selzoom);
			chkzoom.checked	= true;
		}
		return true;
	}

	function jsXL_opacity()
	{
		var xlimg =  this.img[0];
		// CSS 3
		xlimg.style.opacity			= this.opacity / 100.0;
		// MSIE
		if (navigator.appName.indexOf("Microsoft")!=-1&&parseInt(navigator.appVersion)>=4)
			xlimg.filters.alpha.opacity	= this.opacity;
		// Mozilla
		if (navigator.appName.indexOf("Netscape")!=-1&&parseInt(navigator.appVersion)>=5)
			xlimg.style.MozOpacity		= this.opacity / 100.0;
		return true;
	}

	function jsXL_slider()
	{
		this.parentViewer.opacity	= this.getValue();
		this.parentViewer.opaque();
	}

	function jsXL_resizecb()
	{
		var sty	= this.parentViewer.img[0].style;
		var vwr	= this.parentViewer;
		var pct	= this.getValue() / 100.0;
		var pid	= document.getElementById("parent_" + vwr.name + "_" + vwr.instance);

		sty.width	= Math.floor(vwr.width * pct);
		sty.height	= Math.floor(vwr.height * pct);

		pid.style.width = Math.floor(vwr.width * pct);
		pid.style.height = Math.floor(vwr.height * pct); 
	}

	function jsXL_selected(property)
	{
		switch(property)
		{
			case 'name':
				return this.xlimg;
			default:
				return 'unknown';
		}
	}

