Object.extend = function(destination, source) {
	var properties = [];
	
	for (var property in source) properties.push(property);
	
	if (source.toString.valueOf() != Object.toString.valueOf()) properties.push("toString");
	if (String(source.valueOf) != String(Object.valueOf)) properties.push("valueOf");
	
	for (var i = 0; i < properties.length; i++) {
		var property = properties[i];
		var propDestination = destination[property];
		var propSource = source[property];
		
		if (propDestination instanceof Function && propSource instanceof Function && propDestination.valueOf() != propSource.valueOf()) {
			propSource = (function(oldMethod, newMethod) {
				var method = function() {
					var previous = this.base;
					
					this.base = oldMethod;
					
					var result = newMethod.apply(this, arguments);
					
					this.base = previous;
					return result;
				};
				method.valueOf = function() {
					return newMethod;
				};
				method.toString = function() {
					return String(newMethod);
				};
				return method;
			})(propDestination, propSource);
		}
		destination[property] = propSource;
	}
	
	return destination;
}

Object.extend(Object, {
	K: function(value) {
		return value;
	},
	
	keys: function(object) {
		var keys = [];
		
		for (var property in object) keys.push(property);
		
		return keys;
	},
	
	values: function(object) {
		var values = [];
		
		for (var property in object)values.push(object[property]);
		
		return values;
	},
	
	inspect: function(object) {
		if (object === undefined) return 'undefined';
		if (object === null) return 'null';
		
		return (object.inspect ? object.inspect() : object.toString ? object.toString(): "[Object]");
	}
});

Object.extend(String.prototype, {
	first: function(length) {
		return this.substr(0, length);
	},
	
	last: function(length) {
		return this.substr(this.length - length);
	},
	
	padLeft: function(totalLength, paddingChar) {
		var s = this;
		
		paddingChar = paddingChar || " ";
		
		while (s.length < totalLength) s = paddingChar + s;
		
		return s;
	},
	
	padRight: function(totalLength, paddingChar) {
		var s = this;
		
		paddingChar = paddingChar || " ";
		
		while (s.length < totalLength) s += paddingChar;
		
		return s;
	},
	
	startsWith: function(value) {
		if (this.length < value.length) return false;
		
		return (this.first(value.length) === value);
	},
	
	endsWith: function(value) {
		if (this.length < value.length) return false;
		
		return (this.last(value.length) === value);
	},
	
	trimLeft: function(trimChar) {
		var s = this;
		
		trimChar = trimChar || " ";
		
		while (s.charAt(0) === trimChar) s = s.substr(1);

		return s;
	},
	
	trimRight: function(trimChar) {
		var s = this;
		
		trimChar = trimChar || " ";
		
		while (s.charAt(s.length - 1) === trimChar) s = s.substr(0, s.length - 1);

		return s;
	},
	
	trim: function(trimChar) {
		return this.trimRight(trimChar).trimLeft(trimChar);
	},
	
	toCharArray: function() {
		return this.split("");
	},
	
	reverse: function() {
		return this.split("").reverse().join("");
	},
	
	removeHTML: function() {
		with (document.createElement("p")) {
			innerHTML = this;
			return innerText;
		}
	},
	
	format: function() {
		var a = arguments;
		
		return this.replace(/\{(\d)\}/g, function ($1, $2) {
			return a[$2];
		} );
	},
	
	capitalizePhrase: function() {
		return this.replace(/^\s*.|[\.\?\!]\s*./g, function ($1) {
			return $1.toUpperCase();
		} );
	},
	
	capitalizeWords: function() {
		return this.replace(/^.|[\.\?\!\s]+./g, function ($1) {
			return $1.toUpperCase();
		} );
	},
	
	times: function(count) {
		var result = "";
		
		for (var i = 0; i < count; i++) result += this;
		
		return result;
	},
	
	contains: function(value) {
		return (this.indexOf(value) != -1);
	},
	
	insert: function(index, value) {
		return this.substring(0, index) + value + this.substring(index);
	},
	
	replace: function(oldElement, newElement) {
		if (oldElement instanceof Array) {
			var result = this;
			
			for (var i = 0; i < oldElement.length; i++) result = result.replace(oldElement[i], newElement[i]);
			
			return result;
		}
		else
			return this.base(oldElement, newElement);
	},
	
	toString: function(format) {
		if (format)
			return this.format(format);
		else
			return this.base();
	},
	
	compare: function(value) {
		return (this < value ? -1 : this > value ? 1 : 0);
	},
	
	inspect: function() {
		return "'" + this.replace(/'/g, "\\\'") + "'";
	}
});

Object.extend(Date.prototype, {
	format: function(format) {
		if (!this.valueOf()) return "";
	    
		var d = this;
		
		return format.replace(/(dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|HH|H|hh|h|mm|m|ss|s|nnnn|nn|n|tt|t|\'[^\']*\')/g, function($1) {
			switch ($1) {
				case "dddd":
					return Localization.weekDayNames[d.getDay()];
				case "ddd":
					return Localization.weekDayNames[d.getDay()].first(3);
				case "dd":
					return d.getDate().zeroFill(2);
				case "d":
					return d.getDate();
				case "MMMM":
					return Localization.monthNames[d.getMonth()];
				case "MMM":
					return Localization.monthNames[d.getMonth()].first(3);
				case "MM":
					return (d.getMonth() + 1).zeroFill(2);
				case "M":
					return (d.getMonth() + 1);
				case "yyyy":
					return d.getFullYear();
				case "yy":
					return d.getFullYear().zeroFill(2).last(2);
				case "y":
					return parseInt(d.getFullYear().last(2));
				case "HH":
					return d.getHours().zeroFill(2);
				case "H":
					return d.getHours();
				case "hh":
					return ((h = d.getHours() % 12) ? h : 12).zeroFill(2);
				case "h":
					return ((h = d.getHours() % 12) ? h : 12);
				case "mm":
					return d.getMinutes().zeroFill(2);
				case "m":
					return d.getMinutes();
				case "ss":
					return d.getSeconds().zeroFill(2);
				case "s":
					return d.getSeconds();
				case "nnnn":
					return d.getMilliseconds().zeroFill(4);
				case "nn":
					return d.getMilliseconds().zeroFill(2);
				case "n":
					return d.getMilliseconds();
				case "tt":
					return d.getHours() < 12 ? "am" : "pm";
				case "t":
					return d.getHours() < 12 ? "a" : "p";
				default:
					return $1.substr(1, $1.length - 2);
			}
		});
	},
	
	getDateOnly: function() {
		if (!this.valueOf()) return new Date();
		
		return new Date(this.getFullYear(), this.getMonth(), this.getDate());
	},
	
	toShortDateString: function() {
		if (!this.valueOf()) return new Date();
		
		return this.format(Localization.shortDateFormat);
	},
	
	toLongDateString: function() {
		if (!this.valueOf()) return new Date();
		
		return this.format(Localization.longDateFormat);
	},
	
	toShortTimeString: function() {
		if (!this.valueOf()) return new Date();
		
		return this.format(Localization.shortTimeFormat);
	},
	
	toLongTimeString: function() {
		if (!this.valueOf()) return new Date();
		
		return this.format(Localization.longTimeFormat);
	},
	
	addYears: function(value) {
		if (!this.valueOf()) return new Date();
		
		var dt = new Date(this);
		dt.setFullYear(dt.getFullYear() + value);
		
		return dt;
	},
	
	addMonths: function(value) {
		if (!this.valueOf()) return new Date();
		
		var dt = new Date(this);
		dt.setMonth(dt.getMonth() + value);
		
		return dt;
	},
	
	addDays: function(value) {
		if (!this.valueOf()) return new Date();
		
		var dt = new Date(this);
		dt.setDate(dt.getDate() + value);
		
		return dt;
	},
	
	addHours: function(value) {
		if (!this.valueOf()) return new Date();
		
		var dt = new Date(this);
		dt.setHours(dt.getHours() + value);
		
		return dt;
	},
	
	addMinutes: function(value) {
		if (!this.valueOf()) return new Date();
		
		var dt = new Date(this);
		dt.setMinutes(dt.getMinutes() + value);
		
		return dt;
	},
	
	addSeconds: function(value) {
		if (!this.valueOf()) return new Date();
		
		var dt = new Date(this);
		dt.setSeconds(dt.getSeconds() + value);
		
		return dt;
	},
	
	addMilliseconds: function(value) {
		if (!this.valueOf()) return new Date();
		
		var dt = new Date(this);
		dt.setMilliseconds(dt.getMilliseconds() + value);
		
		return dt;
	},
	
	firstDateInMonth: function () {
		if (!this.valueOf()) return new Date();
		
		return new Date(this.getFullYear(), this.getMonth(), 1);
	},
	
	lastDateInMonth: function() {
		if (!this.valueOf()) return new Date();
		
		return new Date(this.getFullYear(), this.getMonth() + 1, 0);
	},
	
	daysInMonth: function() {
		if (!this.valueOf()) return 0;
		
		return this.lastDateInMonth().getDate();
	},
	
	firstDateInYear: function () {
		if (!this.valueOf()) return new Date();
		
		return new Date(this.getFullYear(), 0, 1);
	},
	
	lastDateInYear: function() {
		if (!this.valueOf()) return new Date();
		
		return new Date(this.getFullYear(), 11, 31);
	},
	
	daysInYear: function() {
		if (!this.valueOf()) return 0;
		
		var dtFirstDateInYear = this.firstDateInYear();
		
		return dtFirstDateInYear.addYears(1).subtract(dtFirstDateInYear).days();
	},
	
	isLeapYear: function() {
		return (this.daysInYear() == 366);
	},
	
	subtract: function(value) {
		if (value instanceof TimeSpan) {
			if (!this.valueOf()) return new Date();
			
			return new Date(this - value);
		}
		else {
			if (!this.valueOf()) return new TimeSpan(0);
			
			return new TimeSpan(this - value);
		}
	},
	
	add: function(value) {
		if (!this.valueOf()) return new Date();
		
		return new Date(this.valueOf() + value);
	},
	
	toString: function(format) {
		if (format)
			return this.format(format);
		else
			return this.base();
	},
	
	compare: function(value) {
		return (this < value ? -1 : this > value ? 1 : 0);
	},
	
	inspect: function() {
		return "#" + this.toString() + "#";
	}
});

Object.extend(Number.prototype, {
	zeroFill: function(totalLength) {
		if (!this.valueOf()) return "0".times(totalLength);
		
		return this.toString().padLeft(totalLength, "0");
	},
	
	format: function(format) {
		var n = this.toString().split(".");
		var ds, dgs;
		
		if (format.toLowerCase() == "c") {
			format = Localization.currencyFormat;
			ds = Localization.currencyDecimalSimbol;
			dgs = Localization.currencyDigitGroupingSymbol;
		}
		else {
			if (format.toLowerCase() == "n") format = Localization.numberFormat;
			ds = Localization.numberDecimalSimbol;
			dgs = Localization.numberDigitGroupingSymbol;
		}
		
		var f = format.split(".");
		var r = innerFormat(n[0], f[0], false);
		
		//if (n[1] && f[1]) r += ds + innerFormat(n[1].reverse(), f[1].reverse(), true).reverse();
		
		if (f[1]) r += ds + innerFormat((n.length == 1 ? "" : n[1].reverse()), f[1].reverse(), true).reverse();
		
		return r;
		
		function innerFormat(number, format, dropRemain)
		{
			var n = number.toCharArray();
			var f = format.toCharArray();
			var r = "", r0 = "";
			
			for (var i = format.indexOf("0"); i < format.length; i++) if (f[i] == "#") f[i] = "0";
			
			while (f.length > 0) {
				var f0 = f.pop();
				switch (f0) {
					case "0":
						r += r0;
						r0 = "";
						if (n.length > 0)
							r += n.pop();
						else
							r += "0";
						break;
					case "#":
						if (n.length > 0)
							r += n.pop();
						else
							r0 += "0";
						break;
					case "\"":
						while(1) {
							f0 = f.pop();
							if (f0 == "\"") break;
							r += f0;
						}
						break;
					case ",":
						if (n.length > 0)
							r += dgs;
						else
							r0 += dgs;
						break;
					default:
						r += f0;
				}
			}
			if (!dropRemain) while (n.length > 0) r += n.pop();
			
			return r.reverse();
		}
	},
	
	toString: function(format) {
		if (format)
			return this.format(format);
		else
			return this.base();
	},
	
	compare: function(value) {
		return (this < value ? -1 : this > value ? 1 : 0);
	},
	
	inspect: function() {
		return this.toString();
	}
});

Object.extend(Array.prototype, {
	first: function() {
		return this[0];
	},
	
	last: function() {
		return this[this.length - 1];
	},
	
	each: function(iterator, index, length) {
		for (var i = (index || 0); i < (length || this.length); i++) iterator(this[i], i);
	},
	
	indexOf: function(value, index) {
		for (var i = (index || 0); i < this.length; i++) if (this[i] === value) return i;
	},
	
	lastIndexOf: function(value, index) {
		for (var i = (index || this.length - 1); i >= 0; i--) if (this[i] === value) return i;
	},
	
	find: function(iterator, index) {
		for (var i = (index || 0); i < this.length; i++) if (iterator(this[i], i)) return this[i];
	},
	
	findAll: function(iterator) {
		var results = [];
		
		this.each(function(value, index) {
			if (iterator(value, index)) results.push(value);
		});
		
		return results;
	},
	
	sortBy: function(iterator) {
		return this.collect(function(item, index) {
			return {value: item, criteria: iterator(item, index)};
		}).sort(function (left, right) {
			var a = left.criteria, b = right.criteria;
			
			return (a < b ? -1 : a > b ? 1 : 0);
		}).collect(function(value, index) {
			return value.value;
		});
    },
    
	maxBy: function(iterator) {
		var result, val;
		
		this.each(function(value, index) {
			var val0 = (iterator || Object.K)(value, index);
			
			if (val === undefined || val0 >= val) {
				val = val0;
				result = value;
			}
		});
		
		return result;
	},
	
	minBy: function(iterator) {
		var result, val;
		
		this.each(function(value, index) {
			var val0 = (iterator || Object.K)(value, index);
			
			if (val === undefined || val0 <= val) {
				val = val0;
				result = value;
			}
		});
		
		return result;
	},
	
	collect: function(iterator) {
		var results = [];
		
		this.each(function(value, index) {
			results.push((iterator || Object.K)(value, index));
		});
		
		return results;
	},
	
	inspect: function() {
		return '[' + this.collect(Object.inspect).join(', ') + ']';
	}
});

function TimeSpan(value)
{
	this.milliseconds = value;
	
	this.days = function() {
		return Math.floor(this.totalDays());
	}
	this.hours = function() {
		return Math.floor(this.totalHours());
	}
	this.minutes = function() {
		return Math.floor(this.totalMinutes());
	}
	this.seconds = function() {
		return Math.floor(this.totalSeconds());
	}
	this.totalDays = function() {
		return this.milliseconds / 86400000;
	}
	this.totalHours = function() {
		return this.milliseconds / 3600000;
	}
	this.totalMinutes = function() {
		return this.milliseconds / 60000;
	}
	this.totalSeconds = function() {
		return this.milliseconds / 1000;
	}
	
	this.toString = function() {
		var dtBuffer = new Date(this.milliseconds);
		
		return this.days() + "d" + dtBuffer.format("HH:MM:ss.nnnn");
	}
	
	this.valueOf = function() {
		return this.milliseconds;
	}
	
	this.compare = function(value) {
		return (this.milliseconds < value ? -1 : this.milliseconds > value ? 1 : 0);
	}
	
	this.inspect = function() {
		return "%" + this.toString() + "%";
	}
}

function Version(version)
{
	var sPart = version.split(".");
	
	this.major = parseInt(sPart[0], 10);
	if (sPart.length > 1)
		this.minor = parseInt(sPart[1], 10);
	else
		this.minor = 0;
	if (sPart.length > 2)
		this.revision = parseInt(sPart[2], 10);
	else
		this.revision = 0;
	
	this.isNewer = function(version) {
		if (typeof version == "string") version = new Version(version);
		
		return (this.major > version.major || (this.major == version.major && (this.minor > version.minor || (this.minor == version.minor && this.revision > version.revision))));
	}
	
	this.toString = function() {
		return this.major + "." + this.minor + "." + this.revision;
	}
	
	this.compare = function(value) {
		return (this.major.compare(value.major) != 0 ? this.major.compare(value.major) : (this.minor.compare(value.minor) != 0 ? this.minor.compare(value.minor) : this.revision.compare(value.revision)));
	}
	
	this.inspect = function() {
		return this.toString();
	}
}

var Localization = {
	set: function(localization) {
		if (typeof localization == "string") {
			if (localization.length == 5)
				localization = eval("Localization." + localization);
			else {
				for (var l in Localization) {
					if (l.toString().startsWith(localization + "_")) {
						localization = eval("Localization." + l);
						break;
					}
				}
			}
		}
		
		this.numberDecimalSimbol = localization.numberDecimalSimbol;
		this.numberDigitGroupingSymbol = localization.numberDigitGroupingSymbol 
		this.numberFormat = localization.numberFormat;
		this.currencyDecimalSimbol = localization.currencyDecimalSimbol;
		this.currencyDigitGroupingSymbol = localization.currencyDigitGroupingSymbol;
		this.currencyFormat = localization.currencyFormat;
		this.shortTimeFormat = localization.shortTimeFormat;
		this.longTimeFormat = localization.longTimeFormat;
		this.shortDateFormat = localization.shortDateFormat;
		this.longDateFormat = localization.longDateFormat;
		this.monthNames = localization.monthNames;
		this.weekDayNames = localization.weekDayNames;
	}
}
Localization.en_us = {
	numberDecimalSimbol: ".",
	numberDigitGroupingSymbol: ",",
	numberFormat: "###,###,###,##0.00",
	currencyDecimalSimbol: ".",
	currencyDigitGroupingSymbol: ",",
	currencyFormat: "$###,###,###,##0.00",
	shortTimeFormat: "h:mm tt",
	longTimeFormat: "h:mm:ss tt",
	shortDateFormat: "M/d/yyyy",
	longDateFormat: "dddd, MMMM dd, yyyy",
	monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
	weekDayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
}
Localization.pt_pt = {
	numberDecimalSimbol: ",",
	numberDigitGroupingSymbol: ".",
	numberFormat: "###,###,###,##0.00",
	currencyDecimalSimbol: ",",
	currencyDigitGroupingSymbol: ".",
	currencyFormat: "###,###,###,##0.00 €",
	shortTimeFormat: "HH:mm",
	longTimeFormat: "HH:mm:ss",
	shortDateFormat: "dd-MM-yyyy",
	longDateFormat: "dddd, d' de 'MMMM' de 'yyyy",
	monthNames: ["Janeiro", "Fevereiro", "Mar\xE7o", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
	weekDayNames: ["Domingo", "Segunda", "Ter\xE7a", "Quarta", "Quinta", "Sexta", "S\xE1bado"]
}
Localization.nl_nl = {
    numberDecimalSimbol: ",",
    numberDigitGroupingSymbol: ".",
    numberFormat: "###,###,###,##0.00",
    currencyDecimalSimbol: ",",
    currencyDigitGroupingSymbol: ".", 
    currencyFormat: "€ ###,###,###,##0.00",
    shortTimeFormat: "H:mm",
    longTimeFormat: "H:mm:ss",
    shortDateFormat: "d-M-yyyy",
    longDateFormat: "dddd d MMMM yyyy", 
    monthNames: ["Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"], 
    weekDayNames: ["Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag"]
}
Localization.nl_be = {
    numberDecimalSimbol: ",", 
    numberDigitGroupingSymbol: ".",
    numberFormat: "###,###,###,##0.00",
    currencyDecimalSimbol: ",",
    currencyDigitGroupingSymbol: ".",
    currencyFormat: "###,###,###,##0.00 €", 
    shortTimeFormat: "H:mm",
    longTimeFormat: "H:mm:ss",
    shortDateFormat: "d/MM/yyyy",
    longDateFormat: "dddd d MMMM yyyy",
    monthNames: ["Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"], 
    weekDayNames: ["Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag"]
}
Localization.set("en_us");

function $get() {
	var elements = new Array();
	
	for (var i = 0; i < arguments.length; i++) {
		var element = arguments[i];
		
		if (typeof element == "string") {
			element = document.getElementById(element);
			
			var j = 0;
			
			while (!element && j < document.forms.length) {
				element = document.forms[j].elements[arguments[i]];
				j++;
			}
		}
		
		if (arguments.length == 1) return element;
		
		elements.push(element);
	}
	return elements;
}

function $addHandler(element, eventName, handler) {
	element = $get(element);
	
	if (element.attachEvent)
		element.attachEvent("on" + eventName, handler);
	else if (element.addEventListener) {
		element.addEventListener(eventName, handler, false);
	}
}

var Try = {
	these: function() {
		for (var i = 0; i < arguments.length; i++) {
			try {
				return arguments[i]();
			}
			catch (e) {}
		}
	}
}

function ServerXMLHTTP() {
	return Try.these(
		function() {return new ActiveXObject("Msxml2.ServerXMLHTTP.6.0")},
		function() {return new ActiveXObject("Msxml2.ServerXMLHTTP.5.0")},
		function() {return new ActiveXObject("Msxml2.ServerXMLHTTP.4.0")},
		function() {return new ActiveXObject("Msxml2.ServerXMLHTTP")}
	);
}







var Matepsoft = {
	XGrid: {
		initialize: function(obj) {
			var cGrid = $get(obj);
			var hfScrollPos = $get(obj + "_scroll");
			
			if (hfScrollPos.value != "") {
				var iPosition = hfScrollPos.value.split("x");
				
				cGrid.scrollTop = parseInt(iPosition[0]);
				cGrid.scrollLeft = parseInt(iPosition[1]);
			}
			
			if (cGrid.nodeName != "TABLE") cGrid = cGrid.firstChild;
			if (!cGrid) return;
			
			for (var i = 0; i < cGrid.rows.length; i++) {
				var tr = cGrid.rows[i];
				
				if (tr.className == "dl_i" || tr.className == "dl_i2" || (tr.className == "dl_b" && tr.onclick != undefined)) {
					if (window.attachEvent) {
						tr.onmouseover = rowMouseOver;
						tr.onmouseout = rowMouseOut;
					}
					else {
						$addHandler(tr, "mouseover", rowMouseOver);
						$addHandler(tr, "mouseout", rowMouseOut);
					}
				}
				
				for (var j = 0; j < tr.cells.length; j++) {
					var td = tr.cells[j];
					
					if (window.attachEvent && tr.className == "dl_h" && td.innerText != "") {
						td.onmousedown = columnMouseDown;
						td.onmousemove = columnMouseMove;
						td.onmouseup = columnMouseUp;
					}
					
					if (td.title == "") td.title = (td.innerText != " " && td.innerText != "\xFC" ? td.innerText : "");
					
					var o = td.firstChild;
					if (o && o.className == "checkbox") {
						$addHandler(o.firstChild, "click", function(event) {
							if (!event.ctrlKey) return;
							
							var chk = (window.attachEvent ? event.srcElement : event.target);
							var td = chk.parentNode.parentNode;
							var x = td.cellIndex;
							
							for (var i = 0; i <= 1; i++) {
								var y = td.parentNode.rowIndex;
								var yy = i * 2 - 1;
								
								do {
									y += yy;
									
									var tr2 = cGrid.rows[y];
									if (!tr2 || tr2.cells.length < x) break;
									
									var td2 = tr2.cells[x];
									if (!td2) break;
									
									var inp = td2.firstChild.firstChild;
									if (!inp || inp.type != "checkbox" || inp.disabled) break;
									
									inp.checked = chk.checked;
								} while (1);
							}
							
						} );
						o.firstChild.title = "Fa\xE7a Ctrl + Click para seleccionar todas as linhas do grupo";
					}
				}
			}
			
			function rowMouseOver() {
				if (this.className == "dl_i")
					this.className = "dlh_i";
				else if (this.className == "dl_i2")
					this.className = "dlh_i2";
			}
			
			function rowMouseOut() {
				if (this.className == "dlh_i")
					this.className = "dl_i";
				else if (this.className == "dlh_i2")
					this.className = "dl_i2";
			}
			
			var _x;
			var _resizing = 0;
			var _lastheader = null;
			
			function columnMouseDown() {
				if (_lastheader == null) return;
				
				_lastheader.setCapture();
				_x = event.screenX;
				_resizing = 1;
			}
			
			function columnMouseMove() {
				if (_resizing != 0) return;
				
				var newheader = (event.offsetX > this.offsetWidth-10 ? this : null);
				
				if (_lastheader != newheader) {
					if (_lastheader != null) {
						_lastheader.style.cursor = "";
						_lastheader.title = _lastheader.innerText;
					}
					_lastheader = newheader;
					
					if (_lastheader != null) {
						_lastheader.style.cursor = "col-resize";
						_lastheader.title = "Redimensionar coluna '" + _lastheader.innerText + "'";
					}
				}
			}
			
			function columnMouseUp() {
				if (_lastheader == null) return;
				
				var list = _lastheader.parentNode.parentNode.parentNode;
				var columns = list.firstChild;
				
				var xx = event.screenX - _x + parseInt(columns.childNodes[_lastheader.cellIndex].width);
				columns.childNodes[_lastheader.cellIndex].width = (xx < 20 ? 20 : xx);
				
				_lastheader.releaseCapture();
				_resizing = 0;
			}
		}
	},
	
	XRichTextbox: {
		initialize: function (obj) {
			var cEditor = $get(obj + "_cEditor");
			var txtHtmlView = cEditor.contentWindow;
			var txtHtmlSource = $get(obj + "_txtHtml");
			
			var ddlParagraph = $get(obj + "_ddlParagraph");
			var ddlFontName = $get(obj + "_ddlFontName");
			var ddlFontSize = $get(obj + "_ddlFontSize");
			var ddlColor = $get(obj + "_ddlColor");
			
			var chkViewMode = $get(obj + "_chkViewMode");
			
			$addHandler(cEditor, "load", function() {
				if (chkViewMode) $addHandler(chkViewMode, "click", function() { Matepsoft.XRichTextbox.viewMode(obj, chkViewMode.checked) } );
				
				$addHandler(txtHtmlView.document, "keyup", function() { Matepsoft.XRichTextbox.updateHtmlSource(obj) } );
				$addHandler(txtHtmlView.document, "mouseup", function() { Matepsoft.XRichTextbox.updateHtmlSource(obj) } );
				$addHandler(txtHtmlView.document.body, "paste", function() { Matepsoft.XRichTextbox.updateHtmlSource(obj) } );
				$addHandler(txtHtmlSource, "change", function() { Matepsoft.XRichTextbox.updateHtmlView(obj) } );
				
				$addHandler(ddlParagraph, "change", function() { if (ddlParagraph.selectedIndex == 0) return; Matepsoft.XRichTextbox.execCommand(obj, "formatblock", ddlParagraph.value); ddlParagraph.selectedIndex = 0 } );
				$addHandler(ddlFontName, "change", function() { if (ddlFontName.selectedIndex == 0) return; Matepsoft.XRichTextbox.execCommand(obj, "fontname", ddlFontName.value); ddlFontName.selectedIndex = 0 } );
				$addHandler(ddlFontSize, "change", function() { if (ddlFontSize.selectedIndex == 0) return; Matepsoft.XRichTextbox.execCommand(obj, "fontsize", ddlFontSize.value); ddlFontSize.selectedIndex = 0 } );
				$addHandler(ddlColor, "change", function() { if (ddlColor.selectedIndex == 0) return; Matepsoft.XRichTextbox.execCommand(obj, "forecolor", ddlColor.value); ddlColor.selectedIndex = 0 } );
				
				$addHandler(obj + "_xbBold", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "bold", null) } );
				$addHandler(obj + "_xbItalic", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "italic", null) } );
				$addHandler(obj + "_xbUnderline", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "underline", null) } );
				$addHandler(obj + "_xbStrike", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "strikethrough", null) } );
				
				$addHandler(obj + "_xbSuperscript", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "superscript", null) } );
				$addHandler(obj + "_xbSubscript", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "subscript", null) } );
				$addHandler(obj + "_xbClearFormat", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "removeformat", null) } );
				
				$addHandler(obj + "_xbAlignLeft", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "justifyleft", null) } );
				$addHandler(obj + "_xbAlignCenter", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "justifycenter", null) } );
				$addHandler(obj + "_xbAlignRight", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "justifyright", null) } );
				$addHandler(obj + "_xbAlignJustify", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "justifyfull", null) } );
				
				$addHandler(obj + "_xbBulletList", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "insertunorderedlist", null) } );
				$addHandler(obj + "_xbNumberList", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "insertorderedlist", null) } );
				$addHandler(obj + "_xbIndent", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "indent", null) } );
				$addHandler(obj + "_xbOutdent", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "outdent", null) } );
				
				$addHandler(obj + "_xbLink", "click", function() { var sLink = prompt("Introduza o endereco", ""); if (sLink != "") Matepsoft.XRichTextbox.execCommand(obj, "createlink", sLink) } );
				$addHandler(obj + "_xbLinkRemove", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "unlink", null) } );
				$addHandler(obj + "_xbRule", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "inserthorizontalrule", null) } );
				
				$addHandler(obj + "_xbCut", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "cut", null) } );
				$addHandler(obj + "_xbCopy", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "copy", null) } );
				$addHandler(obj + "_xbPaste", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "paste", null) } );
				$addHandler(obj + "_xbUndo", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "undo", null) } );
				$addHandler(obj + "_xbRedo", "click", function() { Matepsoft.XRichTextbox.execCommand(obj, "redo", null) } );
				
				if (chkViewMode)
					Matepsoft.XRichTextbox.viewMode(obj, chkViewMode.checked);
				else
					Matepsoft.XRichTextbox.viewMode(obj, false);

				txtHtmlView.document.body.innerHTML = txtHtmlSource.value;
				
				if (window.attachEvent)
					txtHtmlView.document.body.contentEditable = true;
				else
					txtHtmlView.document.designMode = "on";
			} );
		},
		
		viewMode: function(obj, viewSource) {
			$get(obj + "_trToolbar").style.display = (viewSource ? "none" : "");
			$get(obj + "_trView").style.display = (viewSource ? "none" : "");
			$get(obj + "_trHtml").style.display = (viewSource ? "" : "none");
			$get(obj + "_trViewMode").style.display = "";
			
			if (viewSource)
				$get(obj + "_txtHtml").focus(); 
			else
				$get(obj + "_cEditor").contentWindow.focus();
		},
		
		execCommand: function(obj, command, parameter) {
			if (parameter == undefined) parameter = null;
			
			$get(obj + "_cEditor").contentWindow.document.execCommand(command, false, parameter);
			
			Matepsoft.XRichTextbox.updateHtmlSource(obj);
		},
		
		updateHtmlSource: function(obj) {
			$get(obj + "_txtHtml").value = $get(obj + "_cEditor").contentWindow.document.body.innerHTML;
		},
		
		updateHtmlView: function(obj) {
			$get(obj + "_cEditor").contentWindow.document.body.innerHTML = $get(obj + "_txtHtml").value;
		}
	},
	
	XObject: {
		initialize: function (html) {
			document.write(html);
		}
	}
}