// setting
var cha = {
	form  : 'charas',	// character-form id
	ori   : 'original',	// original-text element-name
	enc   : 'encoded',	// encoded-text element-name
	type  : 'type',	// encoding-type element-name
	alpha : 'alpha',	// except-alphabet element-name
	space : 'space',	// except-space element-name
	0 : 0
};


// encode
function chara_encode() {
	// form
	var form = form_object(cha['form']);
	if (!form) return false;

	// character-start element-object
	var ori = element_object(form, cha['ori']);
	if (!ori) return false;

	// character-end element-object
	var enc = element_object(form, cha['enc']);
	if (!enc) return false;

	// encoding-type element-object
	var type = element_value( element_object(form, cha['type']) );

	// except-alphabet element-object
	var alpha = element_value( element_object(form, cha['alpha']) );

	// except-space element-object
	var space = element_value( element_object(form, cha['space']) );

	// from original-text
	var text = ori.value;
	if (!text) return false;

	// encode
	var z = '';
	var leng = text.length;
	for (var i = 0; i < leng; i++) {
		var t = text.substr(i, 1);
		var c = t.charCodeAt(0);
		z +=
			(alpha && t.match(/[-_0-9A-Za-z]/)) ? t :	// alphabet
			(space && t.match(/[\ \t\r\n]/)) ? t :	// space
			(type == 'html10') ? '&#'  + c + ';' :	// html-10
			(type == 'html16') ? '&#x' + c.toString(16) + ';' :	// html-16
			(type == 'css')    ? '\\'  + c.toString(16) + ' ' :	// css
			(type == 'java')   ? '\\'	// javascript
				+ ( (c <= 0xf) ? 'x0' : (c <= 0xff) ? 'x' : (c <= 0xfff) ? 'u0' : 'u' )
				+ c.toString(16) :
			(type == 'url')    ? (	// url
				(c < 0x10) ? '%0' + c.toString(16) :
				(c < 0x80) ? '%' + c.toString(16) :
				(c < 0x800) ? 
					'%' + (c >> 6        | 0xc0).toString(16) + 
					'%' + (c      & 0x3f | 0x80).toString(16) :
				// (c >= 0x800)
					'%' + (c >> 12       | 0xe0).toString(16) + 
					'%' + (c >> 6 & 0x3f | 0x80).toString(16) +
					'%' + (c      & 0x3f | 0x80).toString(16)
			) : escape(t);
	}
		// %C0%80 (< 0x800)
			// 0100 1010 1010 =
				// (010 010 000000) | (000000 101 010) =>
					// %(00 01 0010 | 11 00 0000) + %(00 10 1010 | 10 00 0000) 
		// %E0%80%80 (>= 0x800)
			// 1000 1010 1010 1010 =
				// (0000 1000 0000 0000 0000) | (101 010 000000) | (000000 101 010) =>
					// %(0000 1000 | 1110 0000)
					//    + %(00 10 1010 | 10 00 0000) + %(00 10 1010 | 10 00 0000) 

	// to encoded-text
	enc.value = z;
}


// decode
function chara_decode() {
	// form
	var form = form_object(cha['form']);
	if (!form) return false;

	// character-start element-object
	var ori = element_object(form, cha['ori']);
	if (!ori) return false;

	// character-end element-object
	var enc = element_object(form, cha['enc']);
	if (!enc) return false;

	// encoding-type element-object
	var type = element_value( element_object(form, cha['type']) );

	// from decoded-text
	var text = enc.value;
	if (!text) return false;

	// reg
	var reg =
		(type == 'html10') ? '&#[0-9]+;' + '|.' :
		(type == 'html16') ? '&#x[0-9A-Fa-f]+;' + '|.' :
		(type == 'css')  ? '\\\\[0-9A-Fa-f]{1,6}\\ ?' + '|.' :
		(type == 'java') ? '\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f][0-9A-Fa-f]' + '|.' :
		(type == 'url')  ?
				'%[Ee][0-9A-Fa-f]%[89ABab][0-9A-Fa-f]%[89ABab][0-9A-Fa-f]' +
				'|%[CDcd][0-9A-Fa-f]%[89ABab][0-9A-Fa-f]' +
				'|%[0-7][0-9A-Fa-f]' + '|.' :
		'';
	if (!reg) { ori.value = unescape(text); return; }

	// characters
	var chrs = text.match( new RegExp(reg, 'g') );

	// decode
	var z = '';
	var leng = chrs.length;

	// !utf-8
	if (type != 'url') {
		for (var i = 0; i < leng; i++) {
			var t = chrs[i];
			z +=
				(t.length == 1) ? t : String.fromCharCode(
						parseInt(
							t.replace(/[^0-9A-Fa-f]/g, ''), (type == 'html10') ? 10 : 16
						)
				);
		}
	}
	// utf-8
	else {
		for (var i = 0; i < leng; i++) {
			var t = chrs[i];
			if (t.length == 1) {  z += t;  continue;  }
			var c = new Array();
			c[0] = parseInt(t.substr(1, 2), 16);
			c[1] = (t.length > 3) ? parseInt(t.substr(4, 2), 16) : null;
			c[2] = (t.length > 6) ? parseInt(t.substr(7, 2), 16) : null;

			z += String.fromCharCode(
				(c[0] < 0x80) ? c[0] :
				(c[0] < 0xe0) ? (c[0] ^ 0xc0) << 6 | (c[1] ^ 0x80) :
				( (c[0] ^ 0xe0) << 12 ) | ( (c[1] ^ 0x80) << 6 ) | (c[2] ^ 0x80)
			);
		}
		// %C0%80 (< 0x800)
			// da ^ c0 => 1a
				// 1101 1010 ^ 1100 0000 = 0001 1010
		// %E0%80%80 (>= 0x800)
			// ea ^ e0 => 0a
				// 1110 1010 ^ 1110 0000 = 0000 1010
	}

	// to original-text
	ori.value = z;
}




// tips
// get form-object
function form_object(id) {
	if (!id) return false;

	// from forms
	var df = document.forms;
	if (df) return df[ id ] || false;

	// from id
	var dei = document.getElementById( id );
	if (dei && dei.nodeType && dei.nodeName == 'FORM') return dei || false;

	// from name
	var tags = document.getElementsByTagName('FORM');
	var tags_leng = tags.length;
	for (var i = 0; i < tags_leng; i++) {
		if (tags[i].getAttribute('name') == id) return tags[i];
	}
	return false;
}


// get element-object
function element_object(df, name) {
	if (!df || !name || typeof(df) != 'object') return false;

	// from elements
	var de = df.elements;
	if (de) return de[ name ] || false;

	// from name
	var tags = df.getElementsByTagName('*');
	var tags_leng = tags.length;
	for (var i = 0; i < tags_leng; i++) {
		if (tags[i].getAttribute('name') == name &&
			(tags[i].type != 'radio' || tags[i].checked == true)
		) return tags[i] || false;
	}

	// from id
	var dei = document.getElementById( name );
	if (dei && dei.nodeType && dei.nodeType == 1) return dei || false;

	return false;
}


// get element-value
function element_value(obj) {
	if (!obj || typeof(obj) != 'object') return false;

	// select
	if (obj.nodeName == 'SELECT') {
		return (obj.options && obj.selectedIndex >= 0) ? 
				obj.options[ obj.selectedIndex ].value : false;
	}
	// radio
	else if (obj.length) {
		for (var i = 0; i < obj.length; i++) {
			if (obj[i].checked == true) return obj[i].value;
		}
		return false;
	}
	// checkbox
	else if (obj.type == 'checkbox') {
		return (obj.checked == true) ? obj.value : false;
	}
	// other
	else {
		return obj.value || false;
	}
}


