/**

	Título..: VeryTinyAJAX 0.5, Wrapper JavaScript simple a funciones XMLHTTP para AJAX
  Licencia: GPL (http://www.gnu.org/licenses/gpl.txt)
	Autores.: Pablo Rodríguez Rey (mr.xkr -en- inertinc -punto- org)
	          http://mr.xkr.inertinc.org/
            Javier Gil Motos (cucaracha -en- inertinc -punto- org)
            http://cucaracha.inertinc.org/

	Agradecimientos a Cucaracha, por darme interés en el desarrollo de webs usando
	AJAX y proveerme del ejemplo básico con el que está desarrollada esta librería.
	También a Binny V A (binnyva -en- hotmail -punto- com
	http://www.geocities.com/binnyva) por la función adump.

*/


// declarar el objeto XML-HTTP global
var http;

// constante de versión de protocolo de transacción
var httpTP="VeryTinyAJAX/tp1:";

// constantes para httpRequest
var hGET=0;
var hPOST=1;

// funciones auxiliares generales
function gid(id) { return(document.getElementById(id)); }

// parsear cadena para ser enviada por GET/POST
function gescape(torg) {
	var d=""+torg;
	try { var d=d.replace(/\"/gi,"%22"); } catch(e) {}
	try { var d=d.replace(/\\/gi,"%5C"); } catch(e) {}
	try { var d=d.replace(/\?/gi,"%3F"); } catch(e) {}
	try { var d=d.replace(/&/gi,"%26"); } catch(e) {}
	try { var d=d.replace(/\+/gi,"%2B"); } catch(e) {}
	try { var d=d.replace(/ /gi,"+"); } catch(e) {}
	return(d);
}

// información de versión
function httpVersion() { return("VeryTinyAJAX/0.4b"); }

// crea el objeto XML-HTTP
function httpObject() {
	var xmlhttp;
	// comprobar que el navegador soporta XMLHttpRequest
	try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); }
	catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
	catch (e) { try { xmlhttp = new XMLHttpRequest(); }
	catch (e) { xmlhttp = false; } } }
	return(xmlhttp);
}

// estado de la petición
function httpState() {
	try { return(http.readyState); }
	catch (e) { return(5); }
}

// cadena de estado de la petición
function httpStateString() {
	try { var rs=http.readyState; }
	catch (e) { var rs=5; }
	switch (rs) {
	case 0: return("Uninitialized")
	case 1: return("Loading");
	case 2: return("Loaded");
	case 3: return("Interactive");
	case 4: return("Complete");
	case 5: return("Server Crashed");
	}
}

// Indicar si se ha completado la operación
function httpComplete() {
	if (http.readyState==4) return(true);
	else return(false);
}

// Devolver los datos recibidos
function httpData() {
	return(http.responseText);
}

// Devolver los datos recibidos en formato documento XML
function httpXML() {
	return(http.responseXML);
}

// Devolver el estado del servidor
// Si se detecta error, el servidor no estará disponible
function httpStatus() {
	try { return(http.status); }
	catch(e) { return(0); }
}

// Comprobar que la respuesta del servidor es la 200 (HTTP OK)
function httpError() {
	if (http.readyState==4) {
		try { var ok=(http.status!=200); }
		catch(e) { return(true); }
		return(ok);
	}
}

// Muestra un mensaje de error dependiendo del tipo de error encontrado
function httpErrorShow() {
	if (httpError()) {
		if (httpStatus()) alert("Se ha encontrado el error "+httpStatus()+" en el servidor.");
		else alert("El servidor no responde a la petición!\nPruebe dentro de unos instantes.");
	}
}

// Realizar un envío de datos http
function httpSend(method, url, data, eventfunction) {
	var sdata=(data?data:"");
	var async=(eventfunction?true:false);
	http=httpObject();
	switch (method) {
	case hGET: http.open("GET",url+"?"+sdata,async); sdata=null; break;
	case hPOST: http.open("POST",url,async); break;
	default: return(false);
	}
	if (async) http.onreadystatechange=eventfunction;
	http.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=ISO-8859-1"');
	http.send(sdata);
	return(true);
}

// Devuelve todos los campos y datos
// de un formulario en forma campo1=dato1&campo2=dato2&...
function httpFormFields(formObject) {
	var fields="";
	for (i=0;i<formObject.length;i++) {
		if (!formObject[i].name) continue;
		if (formObject[i].type=="radio" && !formObject[i].checked) continue;
		fields+=(i>0?"&":"")+formObject[i].name+"="+gescape(httpGetObjectValue(formObject[i]));
	}
	return(fields);
}

// Habilitar o deshabilitar la posibilidad de introducción
// o modificación de datos de un formulario completo.
function httpFormFieldsEnabled(formObject,isEnabled) {
	for (x=0;x<formObject.length;x++) {
		try { formObject[x].disabled=!isEnabled; }
		catch(e) {}
	}
}

// Devuelve todos los campos y datos de un lista de identificadores
// tipo id1,id2,id3 en forma id1=dato1&id2=dato2&...
function httpGetFields(fieldNames) {
	var fn=fieldNames.split(",");
	var fields="";
	var formObject;
	for (i=0;i<fn.length;i++) {
		formObject=gid(fn[i]);
		if (!formObject) continue;
		if (formObject.type=="radio" && !formObject.checked) continue;
		fields+=(i>0?"&":"")+fn[i]+"="+gescape(httpGetObjectValue(formObject));
	}
	return(fields);
}

// Devuelve un valor de un campo
function httpGetObjectValue(formObject) {
	switch (formObject.type) {
	case "checkbox": return(formObject.checked?"1":"0");
	case "radio": case "button": case "select-one": case "text": case "textarea": default: return(formObject.value);
	}
}

// devuelve un objeto con las variables creadas con la función aput
function aget(fullData) {
	var d=(fullData==null?httpData():fullData);
	var o=new Object();
	var n=0;
	var p0,p1,p2,isa;
	var debug=false;
	// comprobar si usa una transacción
	if (d.substring(0,httpTP.length)!=httpTP) debug=true;
	else d=d.substring(httpTP.length);
	// leer datos
	while (true) {
		try {
			p0=d.indexOf("="); if (!p0) break;
			p1=d.indexOf("("); if (!p1) break;
			p2=d.indexOf(")"); if (!p2) break;
			isa=d.substring(p2+1,p2+2); if (!isa) break;
			isa=(isa=="$"?true:false);
			name=d.substring(0,p1); if (!name) { alert("aget warning: bad output"+"\n\n"+httpData()); break; }
			plength=parseInt(d.substring(p1+1,p2));
			data=d.substring(p0+1,p0+plength+1);
			if (!isa) eval("o."+name+"=data;");
			else eval("o."+name+"="+data+";");
			d=d.substring(p0+plength+2);
		} catch(e) {
			if (debug) alert("aget error: "+e+"\n\n"+httpData());
			return(false);
		}
	}
	return(o);
}

// mensaje de error en aget predefinido
function agetErrorShow() {
	alert("Error en procesamiento. Salida devuelta:\n\n"+httpData());
}

// Función auxiliar para crear cadenas PHP sin caracteres de control
function aescape(torg) {
	var d=""+torg;
	try { var d=d.replace(/\\/gi,"\\\\"); } catch(e) {}
	try { var d=d.replace(/\"/gi,"\\\""); } catch(e) {}
	try { var d=d.replace(/\'/gi,"\\'"); } catch(e) {}
	try { var d=d.replace(/\n/gi,"\\n"); } catch(e) {}
	try { var d=d.replace(/\t/gi,"\\t"); } catch(e) {}
	try { var d=d.replace(/\f/gi,"\\f"); } catch(e) {}
	try { var d=d.replace(/\r/gi,"\\r"); } catch(e) {}
	return(d);
}

// Devuelve un cadena con el objeto serializado a PHP
// ATENCIÓN: Debe ser saneado por la función verifyArray(cadena)
//           para evitar inyecciones de código a PHP.
function aput(data,level,human_readable) {
	var i,j,k,n=(level?level:0),r="",s="";
	if (human_readable) { s="\n"; for (i=0;i<n;i++) s+="\t"; }
	if (data==null) return("null");
	if (typeof data=="object") {
		if (data.constructor.toString().indexOf("Array")!=-1) {
			j=0;
			r+=s+"Array(";
			for (i in data) {
				if (typeof data[i]!="function") {
					if (j) r+=s+","; j++;
					r+=aput(data[i],n+1,human_readable);
				}
			}
			r+=s+")";
		} else {
			k=0;
			for (i in data) {
				k++;
				if (k>1) {
					r+=s+'Array(';
					break;
				}
			}
			j=0;
			for (i in data) {
				if (typeof data[i]!="function") {
					if (j) r+=","; j++;
					r+=s+'"'+i+'"=>'+aput(data[i]);
				}
			}
			if (k>1) r+=s+')';
		}
	} else {
		r+=(typeof data=="number"?data:'"'+aescape(data)+'"');
	}
	return(r);
}

// volcar el árbol de una variable JavaScript
function adump(arr,level) {
	var dumped_text="";
	if (!level) level=0;

	// the padding given at the beginning of the line
	var level_padding="";
	for (var j=0;j<level;j++) level_padding+="\t";

	if (typeof(arr)=='object') { // Array/Hashes/Objects
		for (var item in arr) {
			var value=arr[item];
			if (typeof(value)=='object') { // if it is an array
				var size=0; for (var none in value) size++;
				dumped_text+=level_padding+'["' + item + '"] ('+size+') =>\n';
				dumped_text+=adump(value,level+1);
			} else {
				dumped_text+=level_padding+'["' + item + '"] => '+typeof(value)+'("' + value + '")\n';
			}
		}
	} else { // Strings/Chars/Numbers etc.
		dumped_text="("+typeof(arr)+") "+arr;
	}
	return dumped_text;
}
// pequeñas macros para reducir código
function gid(id) {
	try {
		return(document.getElementById(id));
	} catch(e) {
		return(false);
	}
}
function gidget(id) { return(gid(id).innerHTML); }
function gidset(id,html) { gid(id).innerHTML=html; }
function gidval(id,data) { if (data!=null) gid(id).value=data; else return(gid(id).value); }
function giddel(id) { var d=gid(id); d.parentNode.removeChild(d); }
function gmove(id_org,id_dst) { gid(id_dst).innerHTML=gid(id_org).innerHTML; gid(id_org).innerHTML=""; }
function show(id) { gid(id).style.display="block"; }
function hide(id) { gid(id).style.display="none"; }
function view(id) { gid(id).style.visibility="visible"; }
function hidden(id) { gid(id).style.visibility="hidden"; }
function isshow(id) { return(gid(id).style.display=="block"?true:false); }
function isvisible(id) { return(gid(id).style.display!="none"?true:false); }
function isfunction(cfunction) { return((typeof cfunction)=='function'?true:false); }
function gettop(id) { var o=gid(id); var p=0; do { p+=o.offsetTop; } while (o=o.offsetParent); return(p); }
function getleft(id) { var o=gid(id); var p=0; do { p+=o.offsetLeft; } while (o=o.offsetParent); return(p); }

// propiedades del documento y ventana
function ietruebody() { return((document.compatMode && document.compatMode!="BackCompat")?document.documentElement:document.body); }
function scrollLeft() { return(ietruebody().scrollLeft); }
function scrollTop() { return(ietruebody().scrollTop); }
function windowWidth() { return(window.innerWidth?window.innerWidth:document.documentElement.clientWidth); }
function windowHeight() { return(window.innerHeight?window.innerHeight:document.documentElement.clientHeight); }
function documentWidth() { return(document.all?ietruebody().clientWidth:document.body.clientWidth); }
function documentHeight() { return(document.all?ietruebody().clientHeight:document.body.clientHeight); }

// almacenar cookie
function setCookie(name,value,days) {
	var expires="";
	if (days) {
		var date=new Date();
		date.setTime(date.getTime()+(days*86400000));
		expires="; expires="+date.toGMTString();
	}
	document.cookie=name+"="+value+expires+"; path=/";
}

// obtener cookie
function getCookie(name) {
	var nameEQ=name+"=";
	var ca=document.cookie.split(';');
	for (i=0;i<ca.length;i++) {
		var c=ca[i];
		while (c.charAt(0)==' ') c=c.substring(1,c.length);
		if (c.indexOf(nameEQ)==0) return(c.substring(nameEQ.length,c.length));
	}
	return("");
}

// borrar cookie
function delCookie(name) {
	setCookie(name,"",-1);
}

// es internet explorer?
function isie() {
	var ag="ua: "+navigator.userAgent;
	if (ag.indexOf("MSIE")>0) return(true);
	else return(false);
}

// es mozilla firefox?
function ismoz() {
	var ag="ua: "+navigator.userAgent;
	if (ag.indexOf("Firefox")>0) return(true);
	else return(false);
}

// Parche al único fallo del FireFox que siguen sin solucionar
// al cambiar el tamaño de un table con height especificado,
// este no se autoredimensiona al disminuir su contenido.
// este problema suele aparecer al desarrollar aplicaciones AJAX.
function fffix(id) {
	gid(id).height="99%";
	setTimeout('gid("'+id+'").height="100%";',1);
}

// ancho sin los márgenes
function crossInnerWidth(element) {
	try {
		if (window.getComputedStyle(element,"")) {
			return(element.clientWidth-parseInt(window.getComputedStyle(element,"").getPropertyValue("padding-left"))-parseInt(window.getComputedStyle(element,"").getPropertyValue("padding-right")));
		}
	} catch(e) {
		return(element.clientWidth-parseInt(element.currentStyle.paddingLeft)-parseInt(element.currentStyle.paddingRight));
	}
}

// alto sin los márgenes
function crossInnerHeight(element) {
	try {
		if (window.getComputedStyle(element,"")) {
			return(element.clientHeight-parseInt(window.getComputedStyle(element,"").getPropertyValue("padding-top"))-parseInt(window.getComputedStyle(element,"").getPropertyValue("padding-bottom")));
		}
	} catch(e) {
		return(element.clientHeight-parseInt(element.currentStyle.paddingTop)-parseInt(element.currentStyle.paddingBottom));
	}
}

// ancho del scroll vertical
function scrollWidth() {

	// thanks to Alexandre Gomes (Portugal) http://www.alexandre-gomes.com/?p=115
	var inner=document.createElement('p');
	inner.style.width='100%';
	inner.style.height='200px';

	var outer=document.createElement('div');
	outer.style.position='absolute';
	outer.style.top='0px';
	outer.style.left='0px';
	outer.style.visibility='hidden';
	outer.style.width='200px';
	outer.style.height='150px';
	outer.style.overflow='hidden';

	outer.appendChild(inner);
	document.body.appendChild(outer);

	var w1=inner.offsetWidth;
	outer.style.overflow='scroll';
	var w2=inner.offsetWidth;
	if (w1==w2) w2=outer.clientWidth;

	document.body.removeChild(outer);
	return(w1-w2);
}

// buscar y ejecutar tags <script> embebidos
function getrunjs(data) {
	runjs(getjs(data));
}

// buscar tags <script> embebidos
function getjs(data) {
	scode="";
	while (true) {
		ss=data.toLowerCase().indexOf("<script>"); if (ss<0) break;
		es=data.toLowerCase().indexOf("<\/script>",ss+2); if (es<0) break;
		scode=scode+data.substring(ss+8,es);
		data=data.substring(0,ss)+data.substring(es+9);
	}
	return(scode);
}

// ejecutar cadena de javascript (mucho mejor que eval)
function runjs(data) {
	if (!data) return;
	var escode=document.createElement("script");
	escode.setAttribute("type","text/javascript");
	escode.text=data;
	document.getElementsByTagName("body").item(0).appendChild(escode);
}
var calertid=0;

function hideSelects(hidden) {
	if (!isie()) return;
	selects=document.getElementsByTagName("select");
	for (i=0;i<selects.length;i++)
		selects[i].style.visibility=(hidden?"hidden":"visible");
}

function wbox() {

	this.createDIV=function() {
		var w=40,h=20;
		var d=document.createElement("div");
		calertid++;
		d.id="ca"+calertid;
		d.className="alert";
		d.style.display="none";
		d.style.position="absolute";
		d.style.zIndex=500;
		d.style.width=w+"px";
		d.style.height=h+"px";
		document.body.appendChild(d);
		return(d.id);
	}

	this.id=this.createDIV();
	this.d=gid(this.id);
	this.widthSet=false;
	this.heightSet=false;

	this.center=function() {
		this.d.style.left=Math.floor(scrollLeft()+(windowWidth()-parseInt(this.d.style.width))/2)+"px";
		this.d.style.top=Math.floor(scrollTop()+(windowHeight()-parseInt(this.d.style.height))/2)+"px";
	}

	this.width=function(w) {
		this.widthSet=true;
		this.d.style.width=w+"px";
		this.center();
	}

	this.height=function(h) {
		this.heightSet=true;
		this.d.style.height=h+"px";
		this.center();
	}

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

	this.get=function(){
		return(this.d.innerHTML);
	}

	this.set=function(html){
		this.d.innerHTML=html;
	}

	this.show=function(){
		if (!this.widthSet) this.width(300);
		if (!this.heightSet) this.width(180);
		this.center();
		this.d.style.display="block";
		hideSelects(true);
	}

	this.hide=function(){
		this.d.style.display="none";
		hideSelects(false);
	}

	this.del=function() {
		wboxdel(this.id);
	}

}

function wboxdel(id) {
	hideSelects(false);
	if (gid(id)) giddel(id);
}

function walert(html,w,h) {
	var win=new wbox();
	if (w) win.width(w);
	if (h) win.height(h);
	win.set
		("<table width='100%' height='100%'>"
		+"<tr height='99%'><td valign=top>"+html+"</td></tr>"
		+"<tr height='1%'><td align=right><input class=cmd type=button value='Cerrar' onClick='javascript:wboxdel(\""+win.id+"\")' /></td></tr>"
		+"</table>");
	win.show();
}window.onload=function(){ try { init(); } catch(e) {} }
window.onunload=function(){ try { unload(); } catch(e) {} }
/*
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for more info.
 */

/*
 * Configurable variables. You may need to tweak these to be compatible with
 * the server-side, but the defaults work in most cases.
 */
var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

/*
 * These are the functions you'll usually want to call
 * They take string arguments and return either hex or base-64 encoded strings
 */
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }

/*
 * Perform a simple self-test to see if the VM is working
 */
function md5_vm_test()
{
  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
}

/*
 * Calculate the MD5 of an array of little-endian words, and a bit length
 */
function core_md5(x, len)
{
  /* append padding */
  x[len >> 5] |= 0x80 << ((len) % 32);
  x[(((len + 64) >>> 9) << 4) + 14] = len;

  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;

  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;

    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);

    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

    a = safe_add(a, olda);
    b = safe_add(b, oldb);
    c = safe_add(c, oldc);
    d = safe_add(d, oldd);
  }
  return Array(a, b, c, d);

}

/*
 * These functions implement the four basic operations the algorithm uses.
 */
function md5_cmn(q, a, b, x, s, t)
{
  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}

/*
 * Calculate the HMAC-MD5, of a key and some data
 */
function core_hmac_md5(key, data)
{
  var bkey = str2binl(key);
  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);

  var ipad = Array(16), opad = Array(16);
  for(var i = 0; i < 16; i++)
  {
    ipad[i] = bkey[i] ^ 0x36363636;
    opad[i] = bkey[i] ^ 0x5C5C5C5C;
  }

  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
  return core_md5(opad.concat(hash), 512 + 128);
}

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
function safe_add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}

/*
 * Bitwise rotate a 32-bit number to the left.
 */
function bit_rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

/*
 * Convert a string to an array of little-endian words
 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
 */
function str2binl(str)
{
  var bin = Array();
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < str.length * chrsz; i += chrsz)
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
  return bin;
}

/*
 * Convert an array of little-endian words to a string
 */
function binl2str(bin)
{
  var str = "";
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < bin.length * 32; i += chrsz)
    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
  return str;
}

/*
 * Convert an array of little-endian words to a hex string.
 */
function binl2hex(binarray)
{
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i++)
  {
    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
  }
  return str;
}

/*
 * Convert an array of little-endian words to a base-64 string
 */
function binl2b64(binarray)
{
  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i += 3)
  {
    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
    for(var j = 0; j < 4; j++)
    {
      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
    }
  }
  return str;
}
/**
 * SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
 *
 * SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */
if(typeof deconcept=="undefined"){var deconcept=new Object();}if(typeof deconcept.util=="undefined"){deconcept.util=new Object();}if(typeof deconcept.SWFObjectUtil=="undefined"){deconcept.SWFObjectUtil=new Object();}deconcept.SWFObject=function(_1,id,w,h,_5,c,_7,_8,_9,_a){if(!document.getElementById){return;}this.DETECT_KEY=_a?_a:"detectflash";this.skipDetect=deconcept.util.getRequestParameter(this.DETECT_KEY);this.params=new Object();this.variables=new Object();this.attributes=new Array();if(_1){this.setAttribute("swf",_1);}if(id){this.setAttribute("id",id);}if(w){this.setAttribute("width",w);}if(h){this.setAttribute("height",h);}if(_5){this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));}this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion();if(!window.opera&&document.all&&this.installedVer.major>7){deconcept.SWFObject.doPrepUnload=true;}if(c){this.addParam("bgcolor",c);}var q=_7?_7:"high";this.addParam("quality",q);this.setAttribute("useExpressInstall",false);this.setAttribute("doExpressInstall",false);var _c=(_8)?_8:window.location;this.setAttribute("xiRedirectUrl",_c);this.setAttribute("redirectUrl","");if(_9){this.setAttribute("redirectUrl",_9);}};deconcept.SWFObject.prototype={useExpressInstall:function(_d){this.xiSWFPath=!_d?"expressinstall.swf":_d;this.setAttribute("useExpressInstall",true);},setAttribute:function(_e,_f){this.attributes[_e]=_f;},getAttribute:function(_10){return this.attributes[_10];},addParam:function(_11,_12){this.params[_11]=_12;},getParams:function(){return this.params;},addVariable:function(_13,_14){this.variables[_13]=_14;},getVariable:function(_15){return this.variables[_15];},getVariables:function(){return this.variables;},getVariablePairs:function(){var _16=new Array();var key;var _18=this.getVariables();for(key in _18){_16[_16.length]=key+"="+_18[key];}return _16;},getSWFHTML:function(){var _19="";if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","PlugIn");this.setAttribute("swf",this.xiSWFPath);}_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\"";_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";var _1a=this.getParams();for(var key in _1a){_19+=[key]+"=\""+_1a[key]+"\" ";}var _1c=this.getVariablePairs().join("&");if(_1c.length>0){_19+="flashvars=\""+_1c+"\"";}_19+="/>";}else{if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","ActiveX");this.setAttribute("swf",this.xiSWFPath);}_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\">";_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";var _1d=this.getParams();for(var key in _1d){_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";}var _1f=this.getVariablePairs().join("&");if(_1f.length>0){_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";}_19+="</object>";}return _19;},write:function(_20){if(this.getAttribute("useExpressInstall")){var _21=new deconcept.PlayerVersion([6,0,65]);if(this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version"))){this.setAttribute("doExpressInstall",true);this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));document.title=document.title.slice(0,47)+" - Flash Player Installation";this.addVariable("MMdoctitle",document.title);}}if(this.skipDetect||this.getAttribute("doExpressInstall")||this.installedVer.versionIsValid(this.getAttribute("version"))){var n=(typeof _20=="string")?document.getElementById(_20):_20;n.innerHTML=this.getSWFHTML();return true;}else{if(this.getAttribute("redirectUrl")!=""){document.location.replace(this.getAttribute("redirectUrl"));}}return false;}};deconcept.SWFObjectUtil.getPlayerVersion=function(){var _23=new deconcept.PlayerVersion([0,0,0]);if(navigator.plugins&&navigator.mimeTypes.length){var x=navigator.plugins["Shockwave Flash"];if(x&&x.description){_23=new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));}}else{if(navigator.userAgent&&navigator.userAgent.indexOf("Windows CE")>=0){var axo=1;var _26=3;while(axo){try{_26++;axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_26);_23=new deconcept.PlayerVersion([_26,0,0]);}catch(e){axo=null;}}}else{try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");_23=new deconcept.PlayerVersion([6,0,21]);axo.AllowScriptAccess="always";}catch(e){if(_23.major==6){return _23;}}try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(e){}}if(axo!=null){_23=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));}}}return _23;};deconcept.PlayerVersion=function(_29){this.major=_29[0]!=null?parseInt(_29[0]):0;this.minor=_29[1]!=null?parseInt(_29[1]):0;this.rev=_29[2]!=null?parseInt(_29[2]):0;};deconcept.PlayerVersion.prototype.versionIsValid=function(fv){if(this.major<fv.major){return false;}if(this.major>fv.major){return true;}if(this.minor<fv.minor){return false;}if(this.minor>fv.minor){return true;}if(this.rev<fv.rev){return false;}return true;};deconcept.util={getRequestParameter:function(_2b){var q=document.location.search||document.location.hash;if(_2b==null){return q;}if(q){var _2d=q.substring(1).split("&");for(var i=0;i<_2d.length;i++){if(_2d[i].substring(0,_2d[i].indexOf("="))==_2b){return _2d[i].substring((_2d[i].indexOf("=")+1));}}}return "";}};deconcept.SWFObjectUtil.cleanupSWFs=function(){var _2f=document.getElementsByTagName("OBJECT");for(var i=_2f.length-1;i>=0;i--){_2f[i].style.display="none";for(var x in _2f[i]){if(typeof _2f[i][x]=="function"){_2f[i][x]=function(){};}}}};if(deconcept.SWFObject.doPrepUnload){if(!deconcept.unloadSet){deconcept.SWFObjectUtil.prepUnload=function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};window.attachEvent("onunload",deconcept.SWFObjectUtil.cleanupSWFs);};window.attachEvent("onbeforeunload",deconcept.SWFObjectUtil.prepUnload);deconcept.unloadSet=true;}}if(!document.getElementById&&document.all){document.getElementById=function(id){return document.all[id];};}var getQueryParamValue=deconcept.util.getRequestParameter;var FlashObject=deconcept.SWFObject;var SWFObject=deconcept.SWFObject;/*
	Título..: xwin - mr.xkr's JavaScript Windows, implementación de ventanas DHTML
	Licencia: GPL (http://www.gnu.org/licenses/gpl.txt)
	Autor...: Pablo Rodríguez Rey (mr -en- xkr -punto- es)
	          http://mr.xkr.es/
	Usa libremente esta librería bajo los términos de la licencia GPL, pero por favor,
	deja la autoría intacta, es lo único que te pido, sólo son 397 bytes de carga ;-)
*/

// rutas por defecto
var xwinImagePath="images/";
var xwinImageMin="xwin_bmin.gif";
var xwinImageMax="xwin_bmax.gif";
var xwinImageRestore="xwin_bres.gif";
var xwinImageClose="xwin_bclose.gif";
var xwinImageGenIcon="xwin_igen.gif";
var xwinImageTrans="xwin_trans.gif";

// opciones por defecto
var xwinBorderSize=4;
var xwinBorderResize=10;
var xwinShadowSizeLeft=5;
var xwinShadowSizeTop=9;
var xwinMoveMinSize=4;
var xwinMinWidth=150;
var xwinMinHeight=24;

// variables de las ventanas
var xwin=new Array();
var xwinMax=0;

// estado de las ventanas
var xwinActive=0;
var xwinActiveAction=0;
var xwinForeground=0;
var xwinIsTitle=false;
var xwinIsMain=false;
var xwinMoving=false;
var xwinResizing=false;
var xwinMaximized=false;
var xwinMoveMinSizeReached=false;
var xwinAlphaShadow=false;
var xwinNoSelect=false;

// posiciones iniciales en movimientos/redimensionamiento
var xwinStartL;
var xwinStartT;
var xwinStartX;
var xwinStartY;
var xwinStartW;
var xwinStartH;
var xwinLastScrollX;
var xwinLastScrollY;
var xwinCreateL=0;
var xwinCreateT=0;
var xwinZIndex=100;

// constantes de redimensionamiento
var xwinRESLEFT=1;
var xwinRESRIGHT=2;
var xwinRESTOP=3;
var xwinRESBOTTOM=4;
var xwinRESTOPLEFT=5;
var xwinRESTOPRIGHT=6;
var xwinRESBOTTOMLEFT=7;
var xwinRESBOTTOMRIGHT=8;

// constantes de títulos
var xwinTMINIMIZE="Minimizar";
var xwinTRESTORE="Restaurar";
var xwinTMAXIMIZE="Maximizar";
var xwinTCLOSE="Cerrar";

// caché de imágenes
var xwinImageCache=false;


// traer una ventana al frente
function xwinFocus(wid) {
	xwinForeground=wid;
	for (i=1;i<=xwinMax;i++) {
		if (xwin[i] && i!=wid) {
			if (xwin[i].xwinMain.className!="xwinmain xwinmaindisabled") xwin[i].xwinMain.className="xwinmain xwinmaindisabled";
			if (xwin[i].xwinTitle.className!="xwintitle xwintitledisabled") xwin[i].xwinTitle.className="xwintitle xwintitledisabled";
			if (xwin[i].onblur) eval(xwin[i].onblur);
		}
	}
	if (!xwin[wid]) return;
	xwin[wid].xwin.style.zIndex=++xwinZIndex;
	xwin[wid].xwinShadow.style.zIndex=++xwinZIndex;
	xwin[wid].xwinMain.style.zIndex=++xwinZIndex;
	if (!xwin[wid].disabled) {
		xwin[wid].xwinMain.className="xwinmain";
		xwin[wid].xwinTitle.className="xwintitle";
		xwinActive=wid;
	}
	for (i=1;i<=xwinMax;i++) {
		if (xwin[i]) {
			if (xwin[i].ontop) {
				xwin[i].xwin.style.zIndex=++xwinZIndex;
				xwin[i].xwinShadow.style.zIndex=++xwinZIndex;
				xwin[i].xwinMain.style.zIndex=++xwinZIndex;
			}
		}
	}
}

// comprobar si el ratón se encuentra en los bordes
// y actuar en caso de estar en un borde de cambio de tamaño
function xwinMouseMoveCheck(e) {
	var x,y,wid=xwinActive;
	if (!wid) return;
	if (!xwin[wid] || xwinResizing || xwinMoving) return;
	if (xwin[wid].xwinMaximized || xwin[wid].xwinMinimized || xwin[wid].disabled) return;
	if (!e) e=window.event;

	xwinResizeAction=0;

	if (e.clientX>=parseInt(xwin[wid].xwinMain.style.left)
		&& e.clientX<=(parseInt(xwin[wid].xwinMain.style.left)+parseInt(xwin[wid].xwinMain.style.width))
		&& e.clientY>=parseInt(xwin[wid].xwinMain.style.top)
		&& e.clientY<=(parseInt(xwin[wid].xwinMain.style.top)+parseInt(xwin[wid].xwinMain.style.height))
		) {
		if (!xwin[wid].noresize) {

		  var sx=ietruebody().scrollLeft;
			var sy=ietruebody().scrollTop;

			x1=(e.clientX-parseInt(xwin[wid].xwinMain.style.left))-sx;
			x2=-(e.clientX-parseInt(xwin[wid].xwinMain.style.left)-parseInt(xwin[wid].xwinMain.style.width))+1-sx;
			y1=(e.clientY-parseInt(xwin[wid].xwinMain.style.top))-sy;
			y2=-(e.clientY-parseInt(xwin[wid].xwinMain.style.top)-parseInt(xwin[wid].xwinMain.style.height))+1-sy;

			if (x1>=0 && x1<=xwinBorderSize) xwinResizeAction=xwinRESLEFT;
			if (x2>=0 && x2<=xwinBorderSize) xwinResizeAction=xwinRESRIGHT;
			if (y1>=0 && y1<=xwinBorderSize) xwinResizeAction=xwinRESTOP;
			if (y2>=0 && y2<=xwinBorderSize) xwinResizeAction=xwinRESBOTTOM;

			if (x1>=0 && x1<=xwinBorderResize && y1>=0 && y1<=xwinBorderResize) xwinResizeAction=xwinRESTOPLEFT;
			if (x2>=0 && x2<=xwinBorderResize && y1>=0 && y1<=xwinBorderResize) xwinResizeAction=xwinRESTOPRIGHT;
			if (x1>=0 && x1<=xwinBorderResize && y2>=0 && y2<=xwinBorderResize) xwinResizeAction=xwinRESBOTTOMLEFT;
			if (x2>=0 && x2<=xwinBorderResize && y2>=0 && y2<=xwinBorderResize) xwinResizeAction=xwinRESBOTTOMRIGHT;

			if (xwinResizeAction) {
				switch (xwinResizeAction) {
				case xwinRESTOPLEFT: xwin[wid].xwinTitle.style.cursor="NW-resize"; break;
				case xwinRESTOPRIGHT: xwin[wid].xwinTitle.style.cursor="NE-resize"; break;
				case xwinRESBOTTOMRIGHT: xwin[wid].xwinMain.style.cursor="NW-resize"; break;
				case xwinRESBOTTOMLEFT: xwin[wid].xwinMain.style.cursor="NE-resize"; break;
				case xwinRESLEFT: xwin[wid].xwinMain.style.cursor="E-resize"; break;
				case xwinRESRIGHT: xwin[wid].xwinMain.style.cursor="E-resize"; break;
				case xwinRESTOP: xwin[wid].xwinTitle.style.cursor="N-resize";	break;
				case xwinRESBOTTOM: xwin[wid].xwinMain.style.cursor="N-resize";	break;
				}
				return(false);
			}
		}
	}
	
	xwin[wid].xwinMain.style.cursor="default";
	xwin[wid].xwinTitle.style.cursor="default";
	
}

// hacer click con el ratón... ¿mover? ¿redimensionar?
function xwinMouseDown(e) {
	var wid=xwinActive;

	// comprobar si se ha especificado al sistema
	// que no se permita la selección de texto temporalmente
	if (xwinNoSelect) {
		xwinNoSelect=false;
		return(false);
	}

	// comprobar si hay una ventana seleccionada
	if (!wid) return;
	if (!xwin[wid] || xwinResizing) return;
	if (xwin[wid].disabled || xwin[wid].xwinMaximized) return;
	if (!e) e=window.event;

	xwinStartX=e.clientX;
	xwinStartY=e.clientY;
	xwinStartL=(parseInt(xwin[wid].xwinMain.style.left)!=NaN?parseInt(xwin[wid].xwinMain.style.left):0);
	xwinStartT=(parseInt(xwin[wid].xwinMain.style.top)!=NaN?parseInt(xwin[wid].xwinMain.style.top):0);

	// comprobar si se está moviendo la ventana
	if (xwinIsTitle && !xwinResizeAction && !xwin[wid].nomobile) {
		xwinActiveAction=wid;
		xwinMoving=true;
		xwinMoveMinSizeReached=false;
		return(false);
	}

	// comprobar si se está cambiando el tamaño
	if ((xwinIsMain || xwinIsTitle) && xwinResizeAction) {
		xwinActiveAction=wid;
		xwinStartW=xwin[wid].xwinMain.offsetWidth;
		xwinStartH=xwin[wid].xwinMain.offsetHeight;
		xwinResizing=true;
		return(false);	
	}

	// comprobar si está dentro de una ventana
	if (!xwinIsMain && !xwinIsTitle) {
		xwinFocus(0);
	}

}

// desplazar el ratón... ¿moviendo? ¿redimensionando?
function xwinMouseMove(e) {
	var wid=xwinActiveAction;
	if (!e) e=window.event;

	// si se está moviendo la ventana
	if (xwinMoving) {
		var x=(e.clientX-xwinStartX);
		var y=(e.clientY-xwinStartY);
		if (xwinMoveMinSizeReached || x>xwinMoveMinSize || y>xwinMoveMinSize || x<-xwinMoveMinSize || y<-xwinMoveMinSize) {
			xwinMoveMinSizeReached=true;
			var newL=(xwinStartL+x),newT=(xwinStartT+y);
			xwin[wid].xwinMain.style.left=newL;
			xwin[wid].xwinMain.style.top=(newT>0?newT:0);
			xwinUpdate(wid);
			xwinMouseMoveCheck(e);
		}
		return(false);
	}

	// si cambiando el tamaño
	if (xwinResizing) {
		var newT=0;
		var minL=0,minT=0;
		var newW=0,newH=0;
		switch (xwinResizeAction) {
		case xwinRESTOPLEFT:
			newL=xwinStartL+(e.clientX-xwinStartX);
			newW=xwinStartW-(e.clientX-xwinStartX);
			newT=xwinStartT+(e.clientY-xwinStartY);
			newH=xwinStartH-(e.clientY-xwinStartY);
			break;
		case xwinRESTOPRIGHT:
			newW=xwinStartW+(e.clientX-xwinStartX);
			newT=xwinStartT+(e.clientY-xwinStartY);
			newH=xwinStartH-(e.clientY-xwinStartY);
			break;
		case xwinRESBOTTOMLEFT:
			newL=xwinStartL+(e.clientX-xwinStartX);
			newW=xwinStartW-(e.clientX-xwinStartX);
			newH=xwinStartH+(e.clientY-xwinStartY);
			break;
		case xwinRESBOTTOMRIGHT:
			newW=xwinStartW+(e.clientX-xwinStartX);
			newH=xwinStartH+(e.clientY-xwinStartY);
			break;
		case xwinRESLEFT:
			newL=xwinStartL+(e.clientX-xwinStartX);
			newW=xwinStartW-(e.clientX-xwinStartX);
			break;
		case xwinRESRIGHT:
			newW=xwinStartW+(e.clientX-xwinStartX);
			break;
		case xwinRESTOP:
			newT=xwinStartT+(e.clientY-xwinStartY);
			newH=xwinStartH-(e.clientY-xwinStartY);
			break;
		case xwinRESBOTTOM:
			newH=xwinStartH+(e.clientY-xwinStartY);
			break;
		}
		
		// hacer efectivas las nuevas posiciones
		if (newL) xwin[wid].xwinMain.style.left=newL;
		if (newT) xwin[wid].xwinMain.style.top=(newT>minT?newT:minT);
		if (newW) {
			if (newW<xwinMinWidth) newW=xwinMinWidth;
			if (xwin[wid].minwidth && newW<xwin[wid].minwidth) newW=xwin[wid].minwidth;
			if (xwin[wid].maxwidth && newW>xwin[wid].maxwidth) newW=xwin[wid].maxwidth;
			xwin[wid].xwinMain.style.width=newW;
		}
		if (newH) {
			if (newH<xwinMinHeight) newH=xwinMinHeight;
			if (xwin[wid].minheight && newH<xwin[wid].minheight) newH=xwin[wid].minheight;
			if (xwin[wid].maxheight && newH>xwin[wid].maxheight) newH=xwin[wid].maxheight;
			xwin[wid].xwinMain.style.height=newH;
		}
		
		// actualizar las capas
		xwinUpdate(wid);
		return(false);
	}

}

// se ha soltado el ratón
function xwinMouseUp(e) {
	xwinActiveAction=0;
	xwinMoving=false;
	xwinResizing=false;
	xwinResizeAction=0;
}

// F4 cierra la ventana activa
function xwinOnKeyDown(e) {
	if (!e) e=window.event;
	if (e.keyCode==115) xwinClose(xwinForeground);
}

// actualizar las posiciones y tamaños de una ventana
function xwinUpdate(wid) {
	var xwinMainWidth=parseInt(xwin[wid].xwinMain.style.width);
	var xwinMainHeight=parseInt(xwin[wid].xwinMain.style.height);

	// barra de título
	xwin[wid].xwinCaption.style.width=xwinMainWidth-xwin[wid].xwinButtons.offsetWidth-(isie()?2:0);

	// sombra
	if (!xwin[wid].xwinMaximized) {
		xwin[wid].xwinShadow.style.left=parseInt(xwin[wid].xwinMain.style.left)+xwinShadowSizeLeft;
		xwin[wid].xwinShadow.style.top=parseInt(xwin[wid].xwinMain.style.top)+xwinShadowSizeTop;
		xwin[wid].xwinShadow.style.width=xwinMainWidth;
		xwin[wid].xwinShadow.style.height=xwinMainHeight;
	} else {
		xwin[wid].xwinShadow.style.visibility="hidden";
	}

	// contenido
	if (!xwin[wid].xwinMaximized && !xwin[wid].xwinMinimized) {
		var bodyW=(xwinMainWidth-xwinBorderSize*2);
		var bodyH=(xwinMainHeight-xwin[wid].xwinTitle.offsetHeight-xwinBorderSize*2);
		xwin[wid].xwinBody.style.left  =xwinBorderSize;
		xwin[wid].xwinBody.style.top   =xwinBorderSize;
		xwin[wid].xwinBody.style.width =(bodyW>1?bodyW:1);
		xwin[wid].xwinBody.style.height=(bodyH>1?bodyH:1);
		xwin[wid].xwinShadow.style.visibility="visible";
	} else {
		var bodyW=(xwinMainWidth);
		var bodyH=(xwinMainHeight-xwin[wid].xwinTitle.offsetHeight-xwinBorderSize);
		xwin[wid].xwinBody.style.left  =0;
		xwin[wid].xwinBody.style.top   =xwinBorderSize;
		xwin[wid].xwinBody.style.width =(bodyW>1?bodyW:1);
		xwin[wid].xwinBody.style.height=(bodyH>1?bodyH:1);
		xwin[wid].xwinShadow.style.visibility="hidden";
	}
	if (bodyW<=1 || bodyH<=1) xwin[wid].xwinBody.style.visibility="hidden";
	else xwin[wid].xwinBody.style.visibility="visible";
	if (xwin[wid].disabled) {
		xwin[wid].xwinDisable.style.left  =xwin[wid].xwinBody.style.left;
		xwin[wid].xwinDisable.style.top   =xwin[wid].xwinBody.style.top;
		xwin[wid].xwinDisable.style.width =xwin[wid].xwinBody.style.width;
		xwin[wid].xwinDisable.style.height=xwin[wid].xwinBody.style.height;
		xwin[wid].xwinDisable.style.visibility="visible";
	} else {
		if (xwin[wid].xwinDisable.style.visibility!="hidden") xwin[wid].xwinDisable.style.visibility="hidden";
	}
}

// evento que mueve todas las ventanas si se desplaza la página
function xwinScroll() {

	// nueva posición
	var scrX=ietruebody().scrollLeft;
	var scrY=ietruebody().scrollTop;

	// mover todas las ventanas afectadas
	for (wid=1;wid<=xwinMax;wid++) {
		if (gid('xwin'+wid)) {
			xwin[wid].xwinMain.style.left=parseInt(xwin[wid].xwinMain.style.left)+(scrX-xwinLastScrollX);
			xwin[wid].xwinMain.style.top=parseInt(xwin[wid].xwinMain.style.top)+(scrY-xwinLastScrollY);
			xwinUpdate(wid);
		}
	}

	// actualizar y restaurar variables
	xwinLastScrollX=scrX;
	xwinLastScrollY=scrY;

}

// comprobar cada 1ms en IE si se ha producido un desplazamiento
function xwinIEscrollTimer() {
	if (ietruebody().scrollLeft!=xwinLastScrollX || ietruebody().scrollTop!=xwinLastScrollY) xwinScroll();
	setTimeout("xwinIEscrollTimer()",1);
}

// cerrar una ventana y destruir el objeto asociado
function xwinClose(wid) {
	xwin[wid].xwin.parentNode.removeChild(xwin[wid].xwin);
	xwin[wid]=false;
	xwinIsTitle=false;
	xwinIsMain=false;
}

// definir el HTML del contenedor de la ventana
function xwinSetBody(wid,html) {
	gid('xwin'+wid+'body').innerHTML=html;
}

// minimizar una ventana
function xwinMin(wid) {
	var l,t,w,h;
	var xw=xwin[wid].xwin;
	
	// comprobar si está minimizada o no
	if (!xwin[wid].xwinMinimized) {
		xwin[wid].xwinMinimized=true;
		if (!xwin[wid].xwinMaximized) {
			xwin[wid].oldpos={
				"left":xwin[wid].xwinMain.style.left,
				"top":xwin[wid].xwinMain.style.top,
				"width":xwin[wid].xwinMain.style.width,
				"height":xwin[wid].xwinMain.style.height
				};
		}
	  l=xwin[wid].xwinMain.style.left;
		t=xwin[wid].xwinMain.style.top;
	  w=xwinMinWidth;
	  h=xwin[wid].xwinTitle.offsetHeight+xwinBorderSize;
		if (gid('xwin'+wid+'bmaxi')) gid('xwin'+wid+'bmaxi').src=xwinImagePath+xwinImageRestore;
		if (gid('xwin'+wid+'bmaxa')) gid('xwin'+wid+'bmaxa').title=xwinTRESTORE;
		if (gid('xwin'+wid+'bmina')) gid('xwin'+wid+'bmina').style.display="none";
		eval("xwin["+wid+"].xwinCaption.ondblclick=function(){xwinMin("+wid+");}");
	} else {
		xwin[wid].xwinMinimized=false;
		if (gid('xwin'+wid+'bmina')) gid('xwin'+wid+'bmina').style.display="inline";
		if (!xwin[wid].xwinMaximized) {
			l=xwin[wid].oldpos.left;
			t=xwin[wid].oldpos.top;
			w=xwin[wid].oldpos.width;
			h=xwin[wid].oldpos.height;
			if (gid('xwin'+wid+'bmaxi')) gid('xwin'+wid+'bmaxi').src=xwinImagePath+xwinImageMax;
			if (gid('xwin'+wid+'bmaxa')) gid('xwin'+wid+'bmaxa').title=xwinTMAXIMIZE;
		} else {
			xwin[wid].xwinMaxFromMin=true;
			xwinRestore(wid);
		}
		eval("xwin["+wid+"].xwinCaption.ondblclick=function(){xwinRestore("+wid+");}");
	}
	
	// aplicar valores de posición y tamaño si procede
	if (!xwin[wid].xwinMaxFromMin) {
		xwin[wid].xwinMain.style.left=l;
		xwin[wid].xwinMain.style.top=t;
		xwin[wid].xwinMain.style.width=w;
		xwin[wid].xwinMain.style.height=h;
		xwinUpdate(wid);
	} else {
		xwin[wid].xwinMaxFromMin=false;
	}
}

// maximizar o restaurar el tamaño de una ventana
function xwinRestore(wid) {
	var l,t,w,h;
	var xw=xwin[wid].xwin;
	
	// si está minimizada, tratar por xwinMin
	if (xwin[wid].xwinMinimized) {
		xwinMin(wid);
		return;
	}
	
	// no se puede maximizar ni restaurar, no hay botón
	if (!gid('xwin'+wid+'bmaxi')) return
	
	// comprobar si está maximizada o no
	if (!xwin[wid].xwinMaximized || xwin[wid].xwinMaxFromMin) {
		xwin[wid].xwinMaximized=true;
		if (!xwin[wid].xwinMaxFromMin) {
			xwin[wid].oldpos={
				"left":xwin[wid].xwinMain.style.left,
				"top":xwin[wid].xwinMain.style.top,
				"width":xwin[wid].xwinMain.style.width,
				"height":xwin[wid].xwinMain.style.height
				};
		}
	  var l=ietruebody().scrollLeft; xwinLastScrollX=l;
		var t=ietruebody().scrollTop; xwinLastScrollY=t;
	  var w=(document.all?ietruebody().clientWidth:document.body.clientWidth);
	  var h=(document.all?ietruebody().clientHeight:document.body.clientHeight);
		gid('xwin'+wid+'bmaxi').src=xwinImagePath+xwinImageRestore;
		gid('xwin'+wid+'bmaxa').title=xwinTRESTORE;
	} else {
		xwin[wid].xwinMaximized=false;
		l=xwin[wid].oldpos.left;
		t=xwin[wid].oldpos.top;
		w=xwin[wid].oldpos.width;
		h=xwin[wid].oldpos.height;
		gid('xwin'+wid+'bmaxi').src=xwinImagePath+xwinImageMax;
		gid('xwin'+wid+'bmaxa').title=xwinTMAXIMIZE;
	}
	
	// aplicar valores de posición y tamaño
	xwin[wid].xwinMain.style.left=l;
	xwin[wid].xwinMain.style.top=t;
	xwin[wid].xwinMain.style.width=w;
	xwin[wid].xwinMain.style.height=h;
	xwinUpdate(wid);
}

// poner mezcla alpha a las sombras de las ventanas
function xwinSetAlphaShadow(wid) {
	xwinAlphaShadow=true;
	for (i=(wid?wid:1);i<=(wid?wid:xwinMax);i++) {
		if (xwin[i].xwin) {
			if (isie()) xwin[i].xwinShadow.style.filter="alpha(opacity=50);";
			else xwin[i].xwinShadow.style.opacity=0.5;
		}
	}
}

// quitar mezcla alpha a las sombras de las ventanas
function xwinUnSetAlphaShadow() {
	xwinAlphaShadow=false;
	for (i=1;i<=xwinMax;i++) {
		if (xwin[i].xwin) {
			if (isie()) xwin[i].xwinShadow.style.filter="";
			else xwin[i].xwinShadow.style.opacity=1;
		}
	}
}

// poner sombras a las ventanas a unas distancias definidas por left y top
// si son 0 y 0 respectiamente se quitan las sombras
function xwinSetShadows(left,top) {
	xwinShadowSizeLeft=left;
	xwinShadowSizeTop=top;
	xwinAlphaShadow=false;
	for (i=1;i<=xwinMax;i++) {
		if (xwin[i].xwin) {
			xwinUpdate(i);
			xwin[i].xwinShadow.style.visibility=(xwinShadowSizeLeft||xwinShadowSizeTop?"visible":"hidden");
		}
	}
}

// poner una ventana siempre encima de las otras
function xwinSetOntop(wid) {
	xwin[wid].ontop=true;
	xwinFocus(xwinForeground);
}

// quitar una ventana de estar siempre encima de las otras
function xwinUnSetOntop(wid) {
	xwin[wid].ontop=false;
	xwinFocus(xwinForeground);
}

// habilitar redimensionaiento de una ventana
function xwinResize(wid) {
	xwin[wid].noresize=false;
}

// deshabilitar redimensionaiento de una ventana
function xwinNoResize(wid) {
	xwin[wid].noresize=true;
}

// habilitar el desplazamiento de una ventana
function xwinMobile(wid) {
	xwin[wid].nomobile=false;
}

// deshabilitar el desplazamiento de una ventana
function xwinNoMobile(wid) {
	xwin[wid].nomobile=true;
}

// mover una ventana y cambiar su tamaño si se especificase
// (todos los parámetros son opcionales excepto la ventana)
function xwinMove(wid,left,top,width,height) {
	xwinLeft(wid,left,true);
	xwinTop(wid,top,true);
	xwinWidth(wid,width,true);
	xwinHeight(wid,height,true);
	xwinUpdate(wid);
}

// cambiar el tamaño de una ventana
function xwinGeometry(wid,width,height) {
	xwinWidth(wid,width,true);
	xwinHeight(wid,height,true);
	xwinUpdate(wid);
}

// cambiar la posición horizontal de una ventana
function xwinLeft(wid,left,noupdate) {
	if (left!=undefined) xwin[wid].xwinMain.style.left=left;
	if (!noupdate) xwinUpdate(wid);
}

// cambiar la posición vertical de una ventana
function xwinTop(wid,top,noupdate) {
	if (top!=undefined) xwin[wid].xwinMain.style.top=top;
	if (!noupdate) xwinUpdate(wid);
}

// cambiar el ancho de una ventana
function xwinWidth(wid,width,noupdate) {
	if (width!=undefined) xwin[wid].xwinMain.style.width=width;
	if (!noupdate) xwinUpdate(wid);
}

// cambiar el alto de una ventana
function xwinHeight(wid,height,noupdate) {
	if (height!=undefined) xwin[wid].xwinMain.style.height=height;
	if (!noupdate) xwinUpdate(wid);
}

// deshabilitar una ventana
function xwinEnable(wid) {
	xwin[wid].disabled=false;
	xwinUpdate(wid);
}

// deshabilitar una ventana
function xwinDisable(wid) {
	xwin[wid].disabled=true;
	xwinUpdate(wid);
}

// crear una nueva ventana
function xwinNew(p) {

	// comprobar si hay caché de imágenes, y en caso contrario inicializar
	if (!xwinImageCache) xwinInit();

	// crear nueva ventana y objetos asociados
	for (wid=1;wid<=xwinMax;wid++) {
		if (!gid('xwin'+wid)) break;
	}
	if (wid>xwinMax) xwinMax=wid;
	else {
		// purgar contador si hay ventanas destruidas
		for (i=xwinMax;i>wid;i--) {
			if (gid('xwin'+i)) break;
		}
		xwinMax=i;
	}
	
	// crear un objeto y copiar los parámetros en el objeto (si se especifican)
	xwin[wid]=new Object();
	if (p) xwin[wid]=p;
	
	if (p.noresize) {
		if (p.nomax==undefined) p.nomax=true;
	}

	// contenido de la ventana
	var w="";
	w+="<div id=xwin"+wid+"shadow class=xwinshadow></div>"
		+"<div id=xwin"+wid+"main class=xwinmain>"
			+"<div id=xwin"+wid+"title class=xwintitle onMouseDown='javascript:return(false);'><table><tr>"
				+"<td><div class=xwincaption><div id=xwin"+wid+"caption onDblClick='javascript:if(!xwin["+wid+"].disabled)xwinRestore("+wid+");' title='"+(p.caption?p.caption:"")+"'"+(isie()?" style='text-overflow: ellipsis;'":"")+">"
					+(p.icon==undefined?"&nbsp; ":"<a href='javascript:void(0)' onDblClick='javascript:if(!xwin["+wid+"].disabled)xwinClose("+wid+");'><img src='"+(p.icon!=""?p.icon:xwinImagePath+xwinImageGenIcon)+"' alt='' width=16 height=16 /></a> ")
					+(p.caption?p.caption:"&nbsp;")+"</div></div></td>"
				+"<td id=xwin"+wid+"buttons class=xwinbuttons>"
					+(p.nomin?"":"<a id=xwin"+wid+"bmina href='javascript:if(!xwin["+wid+"].disabled)xwinMin("+wid+");' title='"+xwinTMINIMIZE+"'><img id=xwin"+wid+"bmini src='"+xwinImagePath+xwinImageMin+"' width=16 height=16 alt='_' /></a>")
					+(p.nomax?"":"<a id=xwin"+wid+"bmaxa href='javascript:if(!xwin["+wid+"].disabled)xwinRestore("+wid+");' title='"+xwinTMAXIMIZE+"'><img id=xwin"+wid+"bmaxi src='"+xwinImagePath+xwinImageMax+"' width=16 height=16 alt='[]' /></a>")
					+(p.noclose?"":"<a id=xwin"+wid+"bclosea href='javascript:if(!xwin["+wid+"].disabled)"+(p.onclose?p.onclose:"xwinClose("+wid+");")+"' title='"+xwinTCLOSE+"'><img id=xwin"+wid+"bclosei src='"+xwinImagePath+xwinImageClose+"' width=16 height=16 alt='X' /></a>")
				+"</td>"
			+"</tr></table></div>"
			+"<div class=xwindisable><div id=xwin"+wid+"disable style=\"background-image:url('"+xwinImagePath+xwinImageTrans+"');\"></div></div>"
			+"<div id=xwin"+wid+"body class=xwinbody></div>"
		+"</div>";

	// crear ventana en el documento
	var win=document.createElement("div");
	win.setAttribute("id","xwin"+wid);
	win.setAttribute("class","xwin");
	win.innerHTML=w;
	document.getElementsByTagName("body")[0].appendChild(win);

	// definir las referencias y variables de esta ventana
	xwin[wid].xwin=gid('xwin'+wid);
	xwin[wid].xwinMain=gid('xwin'+wid+'main');
	xwin[wid].xwinShadow=gid('xwin'+wid+'shadow');
	xwin[wid].xwinCaption=gid('xwin'+wid+'caption');
	xwin[wid].xwinTitle=gid('xwin'+wid+'title');
	xwin[wid].xwinBody=gid('xwin'+wid+'body');
	xwin[wid].xwinDisable=gid('xwin'+wid+'disable');
	xwin[wid].xwinButtons=gid('xwin'+wid+'buttons');
	xwin[wid].xwinMinimized=false;
	xwin[wid].xwinMaximized=false;

	// definir eventos de la ventana
	eval("xwin["+wid+"].xwinTitle.onmouseover=function(){xwinIsTitle=true;xwinActive="+wid+";}");
	eval("xwin["+wid+"].xwinTitle.onmouseout=function(){xwinIsTitle=false;}");
	eval("xwin["+wid+"].xwinMain.onmouseover=function(){xwinIsMain=true;xwinActive="+wid+";}");
	eval("xwin["+wid+"].xwinMain.onmouseout=function(){xwinIsMain=false;}");
	eval("xwin["+wid+"].xwinMain.onmousedown=function(){if(!xwin["+wid+"].disabled && xwinForeground!="+wid+")xwinFocus("+wid+");}");
	eval("xwin["+wid+"].xwinMain.onmousemove=xwinMouseMoveCheck;");
	eval("xwin["+wid+"].xwinTitle.onmousemove=xwinMouseMoveCheck;");

  var scrX=ietruebody().scrollLeft; xwinLastScrollX=0;
	var scrY=ietruebody().scrollTop; xwinLastScrollY=0;
  var maxW=(document.all?ietruebody().clientWidth:document.body.clientWidth);
  var maxH=(document.all?ietruebody().clientHeight:document.body.clientHeight);

	// tamaño y posición inicial
	xwin[wid].xwinMain.style.width =(p.width ?p.width :xwin[wid].xwinMain.offsetWidth);
	xwin[wid].xwinMain.style.height=(p.height?p.height:xwin[wid].xwinMain.offsetHeight);

	// tamaño y posición iniciales
	xwin[wid].xwinMain.style.left=(p.left?p.left:xwinCreateL=(xwinCreateL+24)%200)+scrX;
	xwin[wid].xwinMain.style.top =(p.top ?p.top :xwinCreateT=(xwinCreateT+24)%200)+scrY;
	if (p.center) {
		if (!p.left) xwin[wid].xwinMain.style.left=((maxW-xwin[wid].xwinMain.offsetWidth)/2+scrX);
		if (!p.top) xwin[wid].xwinMain.style.top =((maxH-xwin[wid].xwinMain.offsetHeight)/2+scrY);
	}
	
	// actualizar tamaños de la ventana
	xwinUpdate(wid);

	// si hay contenido, cambiar
	if (p.body) xwinSetBody(wid,p.body);

	// mostrar ventana y su sombra (si procede)
	if (xwinShadowSizeLeft || xwinShadowSizeTop) {
		xwin[wid].xwinShadow.style.visibility="visible";
		if (xwinAlphaShadow) xwinSetAlphaShadow(wid);
	}
	xwin[wid].xwinMain.style.visibility="visible";

	// traer al frente
	xwinFocus(wid);

	// comprobar si se inicia maximizada
	if (p.maximized) xwinRestore(wid);

	// actualizar todo
	xwinUpdateAll();

	// devolver el identificador de ventana
	return(wid);

}

// limpieza de todas las ventanas y variables
function xwinClean() {
	
	// cerrar todas las ventanas abiertas
	for (i=1;i<=xwinMax;i++) {
		if (xwin[i].xwin) xwinClose(i);
	}
	
	// limpiar variables
	xwin=new Array();
	xwinMax=0;
	xwinCreateL=0;
	xwinCreateT=0;
	xwinZIndex=100;
	xwinImageCache=new Array();

}

// inicialización de las ventanas
// no es necesario llamar a esta función, pero cuanto antes se llame a la misma,
// antes estarán disponibles las imágenes para los botones de las ventanas
function xwinInit() {

	// limpiar variables
	xwinClean();
	
	// precarga de todas las imágenes
	var imageList=Array(xwinImageGenIcon,xwinImageMin,xwinImageMax,xwinImageRestore,xwinImageClose);
	xwinImageCache=new Array();
	for (i=0;i<imageList.length;i++) {
		xwinImageCache[i]=new Image();
		xwinImageCache[i].src=xwinImagePath+imageList[i];
	}

	// activar timer para Internet Explorer que no tiene el evento onscroll
	if (isie()) xwinIEscrollTimer();

	// primera inicialización
	xwinUpdateAll();

}

// inicialización de las variables y eventos
function xwinUpdateAll() {

	// inicializar variables
	xwinIsTitle=false;
	xwinIsMain=false;
	xwinMoving=false;
	xwinResizing=false;
	xwinMaximized=false;
	xwinMoveMinSizeReached=false;

	// declarar los eventos	necesarios
	document.onmouseup=xwinMouseUp;
	document.onmousedown=xwinMouseDown;
	document.onmousemove=xwinMouseMove;
	document.onscroll=xwinScroll;
	document.onkeydown=xwinOnKeyDown;

}