1// #############################################################################
2
3var Korean={
4Jamo: {
5// bits: 1: vowel, 2:
6'\u3131':[14,44032,1], //g
7'\u3132':[6,44620,2], //gg
8'\u3133':[4,-1,3], //gs
9'\u3134':[14,45208,4], //n
10'\u3135':[4,-1,5], //nj
11'\u3136':[4,-1,6], //nh
12'\u3137':[6,45796,7], //d
13'\u3138':[2,46384,0], //dd
14'\u3139':[14,46972,8], //r
15'\u313a':[4,-1,9], //lg
16'\u313b':[4,-1,10], //lm
17'\u313c':[4,-1,11], //lb
18'\u313d':[4,-1,12], //ls
19'\u313e':[4,-1,13], //lt
20'\u313f':[4,-1,14], //lp
21'\u3140':[4,-1,15], //lh
22'\u3141':[6,47560,16], //m
23'\u3142':[14,48148,17], //b
24'\u3143':[2,48736,0], //bb
25'\u3144':[4,-1,18], //bs
26'\u3145':[14,49324,19], //s
27'\u3146':[6,49912,20], //ss
28'\u3147':[6,50500,21], //ng
29'\u3148':[6,51088,22], //j
30'\u3149':[2,51676,0], //jj
31'\u314a':[6,52264,23], //ch
32'\u314b':[6,52852,24], //k
33'\u314c':[6,53440,25], //t
34'\u314d':[6,54028,26], //p
35'\u314e':[6,54616,27], //h
36'\u314f':[1,0,0], //a
37'\u3150':[1,28,0], //ae
38'\u3151':[1,56,0], //ya
39'\u3152':[1,84,0], //yae
40'\u3153':[1,112,0], //eo
41'\u3154':[1,140,0], //e
42'\u3155':[1,168,0], //yeo
43'\u3156':[1,196,0], //ye
44'\u3157':[1,224,0], //o
45'\u315b':[1,336,0], //yo
46'\u315c':[1,364,0], //u
47'\u3160':[1,476,0], //yu ?
48'\u3161':[1,504,0], //eu
49'\u3163':[1,560,0] //i
50},
51VV2V:[0,0,0,0,0,0,0,0,0,224,224,224,0,0,364,364,364,0,0,504,0],
52V2VV:[0,0,0,0,0,0,0,0,{'\u314f':252,'\u3150':280,'\u3163':308},0,0,0,0,{'\u3153':392,'\u3154':420,'\u3163':448},0,0,0,0, {'\u3163':532},0,0],
53CV2C: ['\u3131','\u3132','\u3134','\u3137','\u3138','\u3139','\u3141','\u3142','\u3143','\u3145','\u3146','\u3147','\u3148','\u3149','\u314a','\u314b','\u314c','\u314d','\u314e'],
54C2CC: {'\u3131':'\u3132','\u3137':'\u3138','\u3142':'\u3143','\u3145':'\u3146','\u3148':'\u3149'},
55CC2C: {'\u3132':'\u3131','\u3138':'\u3137','\u3143':'\u3142','\u3146':'\u3145','\u3149':'\u3148'},
56PP2P:[0,0,1,1,0,4,4,0,0,8,8,8,8,8,8,8,0,0,17,0,19,0,0,0,0,0,0,0],
57PP2PC:[0,
58[0,44032],//g
59[0,44620],//gg
60[1,49324],//gs
61[0,45208],//n
62[4,51088],//nj
63[4,54616],//nh
64[0,45796],//d
65[0,46972],//r
66[8,44032],//lg
67[8,47560],//lm
68[8,48148],//lb
69[8,49324],//ls
70[8,53440],//lt
71[8,54028],//lp
72[8,54616],//lh
73[0,47560],//m
74[0,48148],//b
75[17,49324],// bs
76[0,49324],//s
77[0,49912],//ss
78[0,50500],//ng
79[0,51088],//j
80[0,52264],//ch
81[0,52852],//k
82[0,53440],//t
83[0,54028],//p
84[0,54616]//h
85],
86
87P2PP:[0,{'\u3131':2, '\u3145':3}, //g
880,0,{'\u3148':5, '\u314e':6}, //n
890,0,0,{'\u3131':9, '\u3141':10, '\u3142':11, '\u3145':12, '\u314c':13, '\u314d':14, '\u314e':15}, //r
900,0,0,0,0,0,0, // l*
910,{'\u3145':18}, //b
920, {'\u3145':20}, //s
930,0,0,0,0,0,0,0],
94
95Ru2Kor:{'-':'-',
96'\u0430': '\u314f',	'\u0410': '\u314f',//a
97'\u0431': '\u3142',	'\u0411': '\u3143',	//b, PP
98'\u0432': '\u3157',	'\u0412': '\u3157',	//v
99'\u0433': '\u3131',	'\u0413': '\u3132',	//g,G
100'\u0434': '\u3137',	'\u0414': '\u3138',	//d,TT
101'\u0435': '\u3154',	'\u0415': '\u3154',	//e
102'\u0451': '\u315b',	'\u0401': '\u3155',	//yo, Yo
103'\u0436': '\u3148',	'\u0416': '\u3148',	//zh
104'\u0437': '\u3148',	'\u0417': '\u3148',	//z
105'\u0438': '\u3163',	'\u0418': '\u3163',	//i
106'\u0439': '\u3163',	'\u0419': '\u3163',	//y
107'\u043a': '\u3131',	'\u041a': '\u3132',	//k, K
108'\u043b': '\u3139',	'\u041b': '\u3139',	//l
109'\u043c': '\u3141',	'\u041c': '\u3141',	//m
110'\u043d': '\u3134',	'\u041d': '\u3147',	//n, N=ng
111'\u043e': '\u3157',	'\u041e': '\u3153',	//o, O
112'\u043f': '\u3142',	'\u041f': '\u3143',	//p, PP
113'\u0440': '\u3139',	'\u0420': '\u3139',	//r
114'\u0441': '\u3145',	'\u0421': '\u3146',	//s, SS
115'\u0442': '\u3137',	'\u0422': '\u3138',	//t, TT
116'\u0443': '\u315c',	'\u0423': '\u315c',	//u
117'\u0444': '\u314d',	'\u0424': '\u314d',	//f
118'\u0445': '\u314e',	'\u0425': '\u314e',	//x
119'\u0446': '\u3149',	'\u0426': '\u3149',	//ts
120'\u0447': '\u3148',	'\u0427': '\u3149',	//ch, JJ
121'\u0448': '\u3145',	'\u0428': '\u3145',	//sh
122'\u0449': '\u3145',	'\u0429': '\u3145',	//shch
123'\u044a': '\u044a',
124'\u044b': '\u3161',	'\u042b': '\u3161',	//eu
125'\u044c': '\u3153',	'\u042c': '\u3153',	// soft sign
126'\u044d': '\u3150',	'\u042d': '\u3150',	//ae
127'\u044e': '\u3160',	'\u042e': '\u3160',	//yu
128'\u044f': '\u3151', '\u042f': '\u3151'//ya
129},
130RuVowels:                "\u044c\u042c\u0410\u0430\u0415\u0435\u0401\u0451\u0418\u0438\u0419\u0439\u041e\u043e\u0423\u0443\u042b\u044b\u042d\u044d\u042e\u044e\u042f\u044f",
131Ru2KorJotVowels:  "\u3155\u3155\u3151\u3151\u3156\u3156\u3155\u315b\u3163\u3163\u3163\u3163\u3155\u315b\u3160\u3160\u3161\u3161\u3152\u3152\u3160\u3160\u3151\u3151",
132flags:0 //for some crosstalk
133/*
1341 -sh
1352 -jot
1364 -w
1378 -
13816 -
139*/
140}
141function parseHangul(bufchar){
142	if(bufchar=='' || bufchar.length>1) return null
143  var code=bufchar.charCodeAt()
144	if(code<0x3131 || code >0xD7A3) return null // non Korean buffer
145  else if(code<0x314F && code>0x3130) return [Korean.Jamo[bufchar][1],-1,0] // consonant in buffer
146        code -= 44032
147        var arr=[]
148        arr[0]=44032+588*(code / 588 >>0)
149        code %= 588
150        arr[1]= 28*(code / 28 >>0)
151        arr[2]= code % 28
152        return arr
153}
154
155function KoreanCharProcessor(chr, buf, CVC, rukbd){
156	var jamo=Korean.Jamo[chr]
157  if(!CVC) CVC=parseHangul(buf)
158      if(CVC==null){
159                if(!jamo)       return [chr,0]
160                else{
161                        if(jamo[0] & 2) return [chr,1] //can start a syllable
162                        else return [chr,0]
163                }
164        }else{ // full buf
165                if(chr=='\u0008'){
166                        if(CVC[2]) return [ String.fromCharCode( CVC[0]+CVC[1]+Korean.PP2P[CVC[2]]), 1]
167                        else if(CVC[1]>-1){
168                                var VV2V=Korean.VV2V[CVC[1]/28]
169                                if(VV2V) return [String.fromCharCode(CVC[0]+VV2V), 1]
170                                else return [Korean.CV2C[(CVC[0]-44032)/588], 1]
171                        }
172                        else if(Korean.CC2C[buf])return [Korean.CC2C[buf],1]
173                        else{
174                        	Korean.flags=0
175                        	 return['',0]
176                        }
177                }else if(!jamo){
178                	Korean.flags=0
179                  return [buf+chr,0]
180                }else if(CVC[2]){ // [CVC]
181                        if(jamo[0] & 2) { //[CVC] +C
182                                var P2PP = Korean.P2PP[CVC[2]][chr]
183                                if(P2PP) return [ String.fromCharCode( CVC[0]+CVC[1]+P2PP), 1] // [CVCC]
184                                else return [buf+chr, 1] // CVC, [C]
185                        }else if(jamo[0] & 1){// [CVC] +V
186                        		if(rukbd && CVC[2]==21) return [buf+String.fromCharCode(50500+jamo[1]),1]
187                                 return [String.fromCharCode( CVC[0]+CVC[1]+Korean.PP2PC[CVC[2]][0])+
188                                 String.fromCharCode( Korean.PP2PC[CVC[2]][1]+Korean.Jamo[chr][1]),
189                                 1] // CV(P) [PV]
190                        }else{ // [CVC] + PP
191                        	return [buf+chr, 0]
192                        }
193                }else if(CVC[1]>-1){ // [CV]
194                		Korean.flags &=~ 3
195                        if(jamo[0] & 4) // [CV] +P
196                                return [String.fromCharCode(CVC[0]+CVC[1]+jamo[2]), 1] // [CVC]
197                        else if(jamo[0] & 1){ // [CV]+V
198                        	     if(rukbd){
199                                		var vow
200                                		if(Korean.flags & 4 && (vow='\u3153\u3154\u3163'.indexOf(chr))!=-1){//weo, we, wi
201                                			Korean.flags &=~4
202                                			return [String.fromCharCode(CVC[0]+[392,308,448][vow]),1]
203                                		}
204                                }
205                                var V2VV = Korean.V2VV[CVC[1]/28][chr]
206                                if(V2VV) {// [CVV]
207                                	//Korean.flags &=~7
208                                	return [String.fromCharCode(CVC[0]+V2VV), 1]
209                                }else {// CV,[V]
210                                	if(rukbd){
211                                  			//Korean.flags &=~7
212                                			return [buf+String.fromCharCode(50500+jamo[1]),1]
213                                	}
214                                	else return [buf+chr, 0]
215                                }
216                        }
217                        else return [buf+chr, 1] //CV [C]
218                }
219                else if(jamo[0] & 1) {// [C] +V
220                                return [String.fromCharCode(Korean.Jamo[buf][1]+jamo[1]), 1]
221                }else{ //[C]+C
222                                if(buf==chr && Korean.C2CC[buf]) return [Korean.C2CC[buf],1]
223                                else return [buf+chr, 1]
224                }
225        }
226}
227
228VirtualKeyboard.addLayout('kr', '2 Beolsik',
229[96,49,50,51,52,53,54,55,56,57,48,45,61,92,12610,12616,12599,12593,12613,12635,12629,12625,12624,12628,91,93,12609,12596,12615,12601,12622,12631,12627,12623,12643,59,39,12619,12620,12618,12621,12640,12636,12641,44,46,47],
230{'0': [126,33,64,35,36,37,94,38,42,40,41,95,43,124,12611,12617,12600,12594,12614,12635,12629,12625,12626,12630,123,125],
231'35': [58,34],
232'44': [60,62,63]},
233null,
234KoreanCharProcessor
235);
236
237VirtualKeyboard.addLayout('kr', '3Beolsik Fin.',
238[96, 12622,12614,12610,12635,12640,12625,12630,12642,12636,12619, 41, 62, 58,
23912613,12601,12629,12624,12627,12601,12599,12609,12618,12621, 40, 60,
24012615,12596,12643,12623,12641,12596,12615,12593,12616,12610,12620,
24112609,12593,12628,12631,12636,12613,12622, 44,46, 12631],
242{0 : [126, 12594,12602,12616,12607,12606,61,34,34,39,126,59,43,92 /*]*/,
243/*16 : [*/12621,12620,12597,12608,12605,53,54,55,56,57,37,47]
244/*,30*/
245,26 : [12599,12598,12604,12603,12626,48,49,50,51,52,34]
246/*,42*/
247,37 : [12618,12612,12619,12595,63,45,34,39,46,33]
248},
249null,
250KoreanCharProcessor
251);
252
253VirtualKeyboard.addLayout('kr','Ru-Kor',
254[1105,49,50,51,52,53,54,55,56,57,48,45,61,92,1081,1094,1091,1082,1077,1085,1075,1096,1097,1079,1093,1098,1092,1099,1074,1072,1087,1088,1086,1083,1076,1078,1101,1103,1095,1089,1084,1080,1090,1100,1073,1102,46],
255{'1': [33,34,8470,59,37,58,63,42,40,41,95,43,47],
256'46': [44]},
257null,
258function(chr, buf){
259	var CVC=parseHangul(buf)
260	if(CVC==null){
261		var kor, jamo
262		if((kor= Korean.Ru2Kor[chr]) && (jamo = Korean.Jamo[kor])){
263			var flagged='\u0448\u0428\u0439\u0419\u0432\u0412'.indexOf(chr)
264			if(flagged >=0) Korean.flags |= parseInt('112244'.charAt(flagged), 16)
265			if(jamo[0] & 1) {// V
266				return [String.fromCharCode(50500+jamo[1]),1]
267			}
268		}
269	}else{
270		switch (chr) {
271		case '-': // -
272			Korean.flags=0
273			return	[buf, 0]
274		case '\u044a': // tv.znak
275				if(CVC && CVC[2] && CVC[2]==4)// n->ng
276						return [String.fromCharCode(CVC[0]+CVC[1]+21), 1]
277				else return [buf, buf && 1 || 0]
278				break
279/*		case '\u044c': //m.znak
280				return [buf, buf && 1 || 0]
281				break
282*/
283		case '\u0445': // h
284			var pos= '\u3142\u3137\u3148\u3131'.indexOf(buf) // p t c k
285			if (pos!=-1 ) return ['\u314d\u314c\u314a\u314b'.charAt(pos), 1]
286			else if(CVC[2]) switch (CVC[2]){
287				case 1: return [String.fromCharCode(CVC[0]+CVC[1]+24), 1] // k>kh
288				case 7: return [String.fromCharCode(CVC[0]+CVC[1]+25), 1] // t>th
289				case 17: return [String.fromCharCode(CVC[0]+CVC[1]+26), 1] // p>ph
290				case 22: return [String.fromCharCode(CVC[0]+CVC[1]+23), 1] // j>ch
291				case 11: return [String.fromCharCode(CVC[0]+CVC[1]+14), 1] // lp>lph
292			}
293			break
294		case '\u0436': // zh
295			if(buf=='\u3148' || buf=='\u3137') return ['\u3148', 1]
296			else if(CVC[2]){
297				if(CVC[2]==22) return [buf, 1];
298				else if (CVC[2]==7) return [String.fromCharCode(CVC[0]+CVC[1]+22), 1]
299			}
300			break
301		case '\u0448': case '\u0428': // sh
302			Korean.flags =1
303			return[buf+'\u3145',1]
304			break
305		case '\u0439': case '\u0419': // yot
306		//debugger
307			if(CVC[1] == -1 || CVC[2]) Korean.flags =2 //s-y, sas-y
308			break
309		case '\u0432': case '\u0412': //w
310			Korean.flags =4
311			break
312		default:
313		if(CVC && (Korean.flags & 1 &&  CVC[1]==-1 || Korean.flags & 2 && CVC[2]==0)){//sha, rya
314				var vow
315				if((vow=Korean.RuVowels.indexOf(chr))!=-1) {//vowel
316						Korean.flags &=~ 3
317						return KoreanCharProcessor(Korean.Ru2KorJotVowels.charAt(vow), Korean.CV2C[(CVC[0]-44032)/588], [CVC[0],-1,0])
318				}
319			}
320		}
321	}
322	return KoreanCharProcessor(Korean.Ru2Kor[chr]||chr, buf, CVC, 1)
323}
324);