/*
 ALee's Hangul Input Method on JavaScript

  Author: Ho-Seok Ee <alee@debian.org>
  Date: 2006-07-12
  Version: 0.1
  Usage: Use <script type="text/javascript" src="ahim.js"></script>
         to include this script and use <span id="imStatus">En</span>
         to enable status notification (not required).
 
 Copyright 2006 (C) Ho-Seok Ee <alee@debian.org>. All rights reserved.
 
  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License as
  published by the Free Software Foundation; either version 2 of
  the License, or (at your option) any later version.
  
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  The license can be found at http://www.gnu.org/licenses/gpl.txt.
 */

var imLang	= 'En';
var imQ		= new Array(0,0,0,0,0,0); /* cho=imQ[0]+imQ[1], jung=imQ[2]+imQ[3], jong=imQ[4]+imQ[5] */
var imChoJamo	= new Array(0,1,3,6,7,8,16,17,18,20,21,22,23,24,25,26,27,28,29);
var imJongJamo	= new Array(0,1,2,3,4,5,6,8,9,10,11,12,13,14,15,16,17,19,20,21,22,23,25,26,27,28,29);
var imDblJung	= new Array(9,1,1,9,2,2,9,21,3,14,5,1,14,6,2,14,21,3,19,21,1);
var imDblJong	= new Array(1,1,1,1,19,2,4,22,1,4,27,2,8,1,1,8,16,2,8,17,3,8,19,4,8,25,5,8,26,6,8,27,7,17,19,1,19,19,1);
var imH2KeyCode	= new Array(16,47,25,22,6,8,29,38,32,34,30,50,48,43,31,35,17,0,3,20,36,28,23,27,42,26); /*a~z*/
var imH3KeyCode	= new Array( /* 201~219 is cho, 301~321 is jung, 401~427 is jong, otherwise char code */
 /*!~*/ 402,183,422,414,413,8220,217,39,126,8221,43,44,41,46,309,216,427,420,417,313,318,303,308,320,314,52,208,44,62,46,33,409,
 /*A~*/ 407,63,424,411,405,410,304,48,55,49,50,51,34,45,56,57,426,415,406,412,54,403,425,418,53,423,40,58,60,61,59,42,
 /*a~*/ 421,314,306,321,307,301,319,203,207,212,201,213,219,210,215,218,419,302,404,305,204,309,408,401,206,416,37,92,47,8251);

function imIndexOf(array, code1, code2) {
	if (!code2) for (i=0; i<array.length; i++) if (code1 == array[i]) return i+1;
	if (code2) for (i=0; i<array.length; i+=3) if (code1 == array[i] && code2 == array[i+1]) return array[i+2];
	return 0;
}

function imInsertChar(field, mode, char) { // Insert char to cursor position
	if (char.length == 6) {
		if (!mode) mode = '0,0,0,0,0,0';
		if (char[0] && char[2]) char = 0xac00+(char[0]+char[1]-1)*588+(char[2]+char[3]-30)*28+char[4]+char[5];
		else char = 0x3131+(char[0]?imChoJamo[char[0]+char[1]-1]:char[2]?char[2]+char[3]:imJongJamo[char[4]-1]);
	}
	if (char) char = String.fromCharCode(char);
	else {
		if (imQ == '0,0,0,0,0,0') return true;
		else imQ = Array(0,0,0,0,0,0);
	}
	if (document.selection) {
		var selection = document.selection.createRange();
		var selectedtext = selection.text;
		if (selectedtext && document.selection.clear) document.selection.clear();
		if (mode == '0,0,0,0,0,0' || (char && selectedtext.length > 1)) selection.text = char;
		else selection.text = selectedtext + char;
		if (mode) { selection.moveStart('character', -char.length); selection.select(); }
	}
	else if (field) {
		var scroll = field.scrollTop, height = field.scrollHeight;
		var start = field.selectionStart, end = field.selectionEnd;
		if (mode != '0,0,0,0,0,0' && (!char || field.selectionEnd-field.selectionStart == 1)) start = end;
		field.value = field.value.substring(0, start) + char + field.value.substring(end, field.value.length);
		if (char && mode) field.setSelectionRange(start, start+char.length);
		else field.setSelectionRange(start+char.length, start+char.length);
		field.scrollTop = scroll - height + field.scrollHeight;
	}
}

function imComposeHangul2(field, code) { // for 2-bulsik
	if (code < 65 || (code-1)%32 > 25) { imInsertChar(field, '', ''); return true; } // The code is not Hangul
	else code = imH2KeyCode[code%32-1] + (code==79||code==80?2:imIndexOf(Array(69,81,82,84,87),code)?1:0);

	if (code < 30) { // The code is jaum
		if (imQ[5]) imQ[0] = -1;
		else if (imQ[2]) imQ[5] = imIndexOf(imDblJong, imQ[4], imIndexOf(imJongJamo, code));
		if (imQ[2] && (!imQ[0] || imQ[0] > 0 && (imQ[4] && imQ[5] || !imQ[4] && imIndexOf(imJongJamo, code)))) {
			if (!imQ[0]) imQ[0] = imIndexOf(imChoJamo, code);
			else if (!imQ[4]) imQ[4] = imIndexOf(imJongJamo, code);
			imInsertChar(field, '', imQ);
			if (imQ[5]) imQ[5] = imIndexOf(imChoJamo, code);
		}
		else if (!imQ[1] && !imQ[2] && imQ[0]==imIndexOf(imChoJamo, code) && imIndexOf(Array(1,4,8,10,13), imQ[0]))
			imInsertChar(field, '', imQ=Array(imIndexOf(imChoJamo,code),1,0,0,0,0));
		else imInsertChar(field, imQ, imQ=Array(imIndexOf(imChoJamo,code),0,0,0,0,0));
	}
	else { // The code is moum
		if (imQ[3] && !imQ[4]) imQ[2] = -1;
		else if (!imQ[4]) imQ[3] = imIndexOf(imDblJung, imQ[2]-29, code-29);
		if (imQ[0] && !imQ[2] || imQ[2] > 0 && imQ[3] && !imQ[4]) {
			if (!imQ[2]) imQ[2] = code;
			imInsertChar(field, '', imQ);
		}
		else if (imQ[0] && imQ[2] > 0 && imQ[4]) {
			if (!imQ[5]) { imQ[5] = imIndexOf(imChoJamo,imJongJamo[imQ[4]-1]); imQ[4] = 0; }
			imInsertChar(field, '', Array(imQ[0],imQ[1],imQ[2],imQ[3],imQ[4],0));
			imInsertChar(field, imQ, imQ=Array(imQ[5],0,code,0,0,0));
		}
		else imInsertChar(field, imQ, imQ=Array(0,0,code,0,0,0));
	}
	return false;
}

function imComposeHangul3(field, code) { // for 3-bulsik
	code = imH3KeyCode[code-33];
	if (code%512 < 200) imInsertChar(field, '', code); // The code is not Hangul

	else if (code < 300) { // The code is choseong
		if (!imQ[1] && !imQ[2] && imQ[0]==code-200 && imIndexOf(Array(1,4,8,10,13), imQ[0]))
			imInsertChar(field, '', imQ=Array(code-200,1,0,0,0,0));
		else imInsertChar(field, imQ, imQ=Array(code-200,0,0,0,0,0));
	}
	else if (code < 400) { // The code is jungseong
		if (imQ[3]) imQ[2] = -1;
		else imQ[3] = imIndexOf(imDblJung, imQ[2]-29, code-300);
		if (imQ[0] && !imQ[2] || imQ[2] > 0 && imQ[3] && !imQ[4]) {
			if (!imQ[2]) imQ[2] = code-300+29;
			imInsertChar(field, '', imQ);
		}
		else imInsertChar(field, imQ, imQ=Array(0,0,code-300+29,0,0,0));
	}
	else { // The code is jongseong
		if (imQ[5]) imQ[4] = -1;
		else imQ[5] = imIndexOf(imDblJong, imQ[4], code-400);
		if (imQ[0] && imQ[2] && (!imQ[4] || imQ[4] > 0 && imQ[5])) {
			if (!imQ[4]) imQ[4] = code-400;
			imInsertChar(field, '', imQ);
		}
		else imInsertChar(field, imQ, imQ=Array(0,0,0,0,code-400,0));
	}
	return false;
}

function imDeleteHangul(field) { // Handle backspace key
	if (imQ[1] || imQ[0] && imQ[2] || imQ[3]) {
		if (imQ[5]) imQ[5] = 0;
		else if (imQ[4]) imQ[4] = 0;
		else if (imQ[3]) imQ[3] = 0;
		else if (imQ[2]) imQ[2] = 0;
		else imQ[1] = 0;
		imInsertChar(field, '', imQ);
		return false;
	}
	else imQ = Array(0,0,0,0,0,0);
}

function imKeypressHandler(e) {
	if (e) {
		var field = e.target;
		var tagname = field.nodeName;
	}
	else {
		var e = window.event;
		var field = e.srcElement;
		var tagname = field.tagName;
	}
	var code = e.which||e.which==0?e.which:e.keyCode;
	if ((field.type == 'text' && tagname == 'INPUT') || tagname == 'TEXTAREA') {
		if (field.selectionEnd) if (field.selectionEnd-field.selectionStart != 1) imQ = Array(0,0,0,0,0,0);
		if (imLang != 'En' && e.keyCode == 8) return imDeleteHangul(field); // Backspace
		if (imLang != 'En' && code > 32 && code < 127 && !e.altKey && !e.ctrlKey) {
			if (code > 64 && code < 91 && !e.shiftKey) code += 32;
			if (code > 96 && code < 123 && e.shiftKey) code -= 32;
			if (imLang == 'H2') return imComposeHangul2(field, code);
			if (imLang == 'H3') return imComposeHangul3(field, code);
		}
		imInsertChar(field, '', '');
		if (e.keyCode == 27) field.blur(); // Esc
		if (code == 32 && (e.altKey || e.ctrlKey || e.shiftKey && imLang != 'H3')) { // Toggle
			if (!e.ctrlKey && imLang != 'H2') imLang = 'H2';
			else if (e.ctrlKey && imLang != 'H3') imLang = 'H3';
			else imLang = 'En';
			if (document.getElementById('imStatus')) document.getElementById('imStatus').innerHTML = imLang;
			return false;
		}
	}
}

function imKeydownHandler(e) { // for IE
	if (e) return true;
	var e = window.event;
	var tagname = e.srcElement.tagName;
	if (tagname == 'INPUT' || tagname == 'TEXTAREA') {
		if (document.selection) if (document.selection.createRange().text.length != 1) imQ = Array(0,0,0,0,0,0);
		if (e.keyCode == 8) return imDeleteHangul(''); // Backspace
		if (e.keyCode != 16 && e.keyCode < 49) imInsertChar('', '', '');
		if (e.keyCode == 27) e.srcElement.blur(); // Esc
	}
}

document.onkeypress = imKeypressHandler;
document.onkeydown = imKeydownHandler;

