// Dependências: (nenhuma).
//
// Funções de utilidade geral.

var KLangVar = "__lang__"	// *
var nullf = function(){}	// A função nula.
window.doc = document, window.wnd = window
var isIE = doc.all, uqnum


if (!top.formDispatchHook) {
	uqnum = 0					// Destina-se a produzir sempre um nº único. Uso: ++uqnum.
	top.formDispatchHook = 0	// Ao despachar uma 'form' deve-se chamar este 'hook'.
}

// Faz a derivação da classe 'derived' a partir de 'base'. Isto deve acontecer antes de se definir 'Derived'. A partir da utilização
// desta função, a variável 'proto' fica a apontar para o protótipo da classe derivada. Adicionalmente, cada instância de 'derived' 
// terá definida a variável 'base' que apontará para a classe base.
var proto = null
function derive (derived, base) {	derived.prototype = proto = new base ()	}

// Despacha o formulário 'frm', executando antes a rotinas de validação respectiva.
function dispatch (frm, optNoClearParams, optAction) {
	frm.substr && (frm = elmnx (frm))
	var wm = (wnd.timeMsg && wnd.timeMsg (frm)) || new WebMsg (frm)
	if (runHook (top.formDispatchHook, frm) == false) return false
	if (runHook (frm.onsubmit, frm) == false) return false

	if (!optNoClearParams) {
		var s = wm.frm.action
		if (!s)
			wm.frm.action = optAction || doc.location.pathname
		else {
			var i = s.lastIndexOf ("?")
			if (i >= 0) wm.frm.action = s.substr (0, i)
		}
	}

	wm.send ()
	return true
}

// Retorna 'true' se 'frm' referir ficheiros a carregar.
function hasFilesToUpl (frm) {
	var els = frm.getElementsByTagName ("input")

	for (var i = 0; i < els.length; ++i) {
		var el = els [i]
		if (el.type && el.type.toLowerCase () == "file" && !el.noFile)
			if (el.value != "") return true
	}
	return false
}

// Navega para 'url'. Esta função destina-se a substituír os links directos, pois permite outra flexibilidade, através de 'hooks'.
// NOTA: Requere WebMsg.js;
function nav (url) {
	var wm = new WebMsg ()

//	if (runHook (top.formDispatchHook, wm.frm) == -1) return

	wm.send (url)
}

// Quando chamada em resposta a um evento, retorna 'true' se se tiver premido "enter".
function checkForEnter (ev) {
	ev || (ev = wnd.event)
	return ev.keyCode == 13 && !ev.shiftKey && !ev.ctrlKey && !ev.altKey
}

// Quando chamada em resposta a um evento, retorna 'true' se se tiver premido "escape".
function checkForEsc (ev) {
	ev || (ev = wnd.event)
	return ev.keyCode == 27 && !ev.shiftKey && !ev.ctrlKey && !ev.altKey
}

// Cria e retorna um objecto 'XMLHttpRequest' de forma compatível com IE e Mozilla.
createXHttpReq = isIE ? function () {
	try {	return new ActiveXObject("MSXML2.XMLHTTP")	} catch(x) {}
	try {	return new ActiveXObject("Microsoft.XMLHTTP")	} catch (x) {}
	throw new Error (-1, "Impossível criar XMLHTTP!")
}
: 
function () {	new XMLHttpRequest	}			// Mozilla.

// Espera 'msecs' mili-segundos.
// NOTA: Evitar o uso desta função em detrimento de 'setTimeout'.
function delay (msecs) {
	var d = new Date
	while (1) {
		var mill = new Date
		var diff = mill - d
		if (diff > msecs)
			break
	}
}

// Retorna 'hook' com 'func' acoplado. Quando 'hook' for chamado será executado todo o seu código actual mais 'func'.
//
// NOTA: Se alguma função retornar 'false' cancela-se o 'hook'.
function mkHook (h, func) {
	var node = new Object
	if (!h || !h._hfirst) {
		var f = h
		h = function (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) {	h._rhf (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)	}
		h._rhf = _runHook
		// Guardar a função em 'h'.
		if (f) {
			h._hfirst = h._hlast = new Object
			h._hfirst.f = h.f = f
		}
		else h._hfirst = node
	}
	// Adicionar 'func' ao final da lista.
	h._hlast && (h._hlast.hnext = node)
	h._hlast = node
	node.f = func

	return h
}

// Elimina a função 'f' do "hook" 'h'.
// RETORNO: 'h'.
function rmFromHook (h, f) {
	if (!h) return null
	var n = h._hfirst, prevn
	f.f && (f = f.f)
	while (n) {
		if (n.f == f) {
			var e = n.hnext
			e || (h._hlast = prevn)
			prevn ? prevn.hnext = e : h._hfirst = e
			return h._hfirst ? h : null
		}
		prevn = n
		n = n.hnext
	}
	return h
}

// Corre 'hook' e retorna o resultado da última função. Se for 'false', houve cancelamento.
function runHook (hook, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) {	return !hook ? true : hook (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)	}

// Executa todas as funções de 'h'.
function _runHook (h, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) {
	var res, n = h._hfirst
	while (n) {
		if ((res = n.f (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)) == false)
			return false
		n = n.hnext
	}
	return res
}

// Retorna 'html' com os caractéres HTML especiais representados como entidades.
function htmlEncode (html) {
	return html.replace (/</g, "&lt;").replace (/>/g, "&gt;").replace (/\"/g, "&quot;").replace (/&/g, "&amp;")
}

// Retorna o objecto __associado__ a 'ev'. Para saber o objecto que disparou o evento verifique 'wnd.event.el'.
function getEvObj (ev) {
	var el = ev.el, obj
	// Encontrar o objecto.
	var origel = el
	while (!(obj = el._obj))
		if (!(el = el.parentNode)) return false

	return origel._obj = obj
}

// Limpa 'to' e retorna um novo agendamento.
function setTO (to, f, msecs) {
	clearTimeout (to)
	return wnd.setTimeout (f, msecs)
}
