diff --git a/srcs/juloo.keyboard2/KeyModifier.java b/srcs/juloo.keyboard2/KeyModifier.java index 3dc50a9..f358e97 100644 --- a/srcs/juloo.keyboard2/KeyModifier.java +++ b/srcs/juloo.keyboard2/KeyModifier.java @@ -52,6 +52,12 @@ public final class KeyModifier return modify(k, mod.getModifier()); case Compose_pending: return ComposeKey.apply(mod.getPendingCompose(), k); + case Hangul_initial: + if (k.equals(mod)) // Allow typing the initial in letter form + return KeyValue.makeStringKey(k.getString(), KeyValue.FLAG_GREYED); + return combine_hangul_initial(k, mod.getHangulPrecomposed()); + case Hangul_medial: + return combine_hangul_medial(k, mod.getHangulPrecomposed()); } return k; } @@ -1234,4 +1240,108 @@ public final class KeyModifier } } }; + + /** Compose the precomposed initial with the medial [kv]. */ + private static KeyValue combine_hangul_initial(KeyValue kv, int precomposed) + { + switch (kv.getKind()) + { + case Char: + return combine_hangul_initial(kv, kv.getChar(), precomposed); + case Hangul_initial: + // No initials are expected to compose, grey out + return kv.withFlags(kv.getFlags() | KeyValue.FLAG_GREYED); + default: + return kv; + } + } + + private static KeyValue combine_hangul_initial(KeyValue kv, char medial, + int precomposed) + { + int medial_idx; + switch (medial) + { + // Vowels + case 'ㅏ': medial_idx = 0; break; + case 'ㅐ': medial_idx = 1; break; + case 'ㅑ': medial_idx = 2; break; + case 'ㅒ': medial_idx = 3; break; + case 'ㅓ': medial_idx = 4; break; + case 'ㅔ': medial_idx = 5; break; + case 'ㅕ': medial_idx = 6; break; + case 'ㅖ': medial_idx = 7; break; + case 'ㅗ': medial_idx = 8; break; + case 'ㅘ': medial_idx = 9; break; + case 'ㅙ': medial_idx = 10; break; + case 'ㅚ': medial_idx = 11; break; + case 'ㅛ': medial_idx = 12; break; + case 'ㅜ': medial_idx = 13; break; + case 'ㅝ': medial_idx = 14; break; + case 'ㅞ': medial_idx = 15; break; + case 'ㅟ': medial_idx = 16; break; + case 'ㅠ': medial_idx = 17; break; + case 'ㅡ': medial_idx = 18; break; + case 'ㅢ': medial_idx = 19; break; + case 'ㅣ': medial_idx = 20; break; + // Grey-out uncomposable characters + default: return kv.withFlags(kv.getFlags() | KeyValue.FLAG_GREYED); + } + return KeyValue.makeHangulMedial(precomposed, medial_idx); + } + + /** Combine the precomposed medial with the final [kv]. */ + private static KeyValue combine_hangul_medial(KeyValue kv, int precomposed) + { + switch (kv.getKind()) + { + case Char: + return combine_hangul_medial(kv, kv.getChar(), precomposed); + case Hangul_initial: + // Finals that can also be initials have this kind. + return combine_hangul_medial(kv, kv.getString().charAt(0), precomposed); + default: + return kv; + } + } + + private static KeyValue combine_hangul_medial(KeyValue kv, char c, + int precomposed) + { + int final_idx; + switch (c) + { + case ' ': final_idx = 0; break; + case 'ㄱ': final_idx = 1; break; + case 'ㄲ': final_idx = 2; break; + case 'ㄳ': final_idx = 3; break; + case 'ㄴ': final_idx = 4; break; + case 'ㄵ': final_idx = 5; break; + case 'ㄶ': final_idx = 6; break; + case 'ㄷ': final_idx = 7; break; + case 'ㄹ': final_idx = 8; break; + case 'ㄺ': final_idx = 9; break; + case 'ㄻ': final_idx = 10; break; + case 'ㄼ': final_idx = 11; break; + case 'ㄽ': final_idx = 12; break; + case 'ㄾ': final_idx = 13; break; + case 'ㄿ': final_idx = 14; break; + case 'ㅀ': final_idx = 15; break; + case 'ㅁ': final_idx = 16; break; + case 'ㅂ': final_idx = 17; break; + case 'ㅄ': final_idx = 18; break; + case 'ㅅ': final_idx = 19; break; + case 'ㅆ': final_idx = 20; break; + case 'ㅇ': final_idx = 21; break; + case 'ㅈ': final_idx = 22; break; + case 'ㅊ': final_idx = 23; break; + case 'ㅋ': final_idx = 24; break; + case 'ㅌ': final_idx = 25; break; + case 'ㅍ': final_idx = 26; break; + case 'ㅎ': final_idx = 27; break; + // Grey-out uncomposable characters + default: return kv.withFlags(kv.getFlags() | KeyValue.FLAG_GREYED); + } + return KeyValue.makeHangulFinal(precomposed, final_idx); + } } diff --git a/srcs/juloo.keyboard2/KeyValue.java b/srcs/juloo.keyboard2/KeyValue.java index 1f00464..8435cae 100644 --- a/srcs/juloo.keyboard2/KeyValue.java +++ b/srcs/juloo.keyboard2/KeyValue.java @@ -86,8 +86,8 @@ public final class KeyValue implements Comparable public static enum Kind { - Char, String, Keyevent, Event, Compose_pending, Modifier, Editing, - Placeholder, + Char, String, Keyevent, Event, Compose_pending, Hangul_initial, + Hangul_medial, Modifier, Editing, Placeholder, Cursor_move // Value is encoded as a 16-bit integer } @@ -195,6 +195,13 @@ public final class KeyValue implements Comparable return (_code & VALUE_BITS); } + /** Defined only when [getKind()] is [Kind.Hangul_initial] or + [Kind.Hangul_medial]. */ + public int getHangulPrecomposed() + { + return (_code & VALUE_BITS); + } + /** Defined only when [getKind() == Kind.Cursor_move]. */ public short getCursorMove() { @@ -368,6 +375,25 @@ public final class KeyValue implements Comparable flags | FLAG_KEY_FONT); } + public static KeyValue makeHangulInitial(String symbol, int initial_idx) + { + return new KeyValue(symbol, Kind.Hangul_initial, initial_idx * 588 + 44032, + FLAG_LATCH); + } + + public static KeyValue makeHangulMedial(int precomposed, int medial_idx) + { + precomposed += medial_idx * 28; + return new KeyValue(String.valueOf((char)precomposed), Kind.Hangul_medial, + precomposed, FLAG_LATCH); + } + + public static KeyValue makeHangulFinal(int precomposed, int final_idx) + { + precomposed += final_idx; + return KeyValue.makeCharKey((char)precomposed); + } + /** Make a key that types a string. A char key is returned for a string of length 1. */ public static KeyValue makeStringKey(String str, int flags) @@ -538,6 +564,27 @@ public final class KeyValue implements Comparable case "f11_placeholder": return placeholderKey(Placeholder.F11); case "f12_placeholder": return placeholderKey(Placeholder.F12); + // Korean Hangul + case "ㄱ": return makeHangulInitial("ㄱ", 0); + case "ㄲ": return makeHangulInitial("ㄲ", 1); + case "ㄴ": return makeHangulInitial("ㄴ", 2); + case "ㄷ": return makeHangulInitial("ㄷ", 3); + case "ㄸ": return makeHangulInitial("ㄸ", 4); + case "ㄹ": return makeHangulInitial("ㄹ", 5); + case "ㅁ": return makeHangulInitial("ㅁ", 6); + case "ㅂ": return makeHangulInitial("ㅂ", 7); + case "ㅃ": return makeHangulInitial("ㅃ", 8); + case "ㅅ": return makeHangulInitial("ㅅ", 9); + case "ㅆ": return makeHangulInitial("ㅆ", 10); + case "ㅇ": return makeHangulInitial("ㅇ", 11); + case "ㅈ": return makeHangulInitial("ㅈ", 12); + case "ㅉ": return makeHangulInitial("ㅉ", 13); + case "ㅊ": return makeHangulInitial("ㅊ", 14); + case "ㅋ": return makeHangulInitial("ㅋ", 15); + case "ㅌ": return makeHangulInitial("ㅌ", 16); + case "ㅍ": return makeHangulInitial("ㅍ", 17); + case "ㅎ": return makeHangulInitial("ㅎ", 18); + /* Fallback to a string key that types its name */ default: return makeStringKey(name); } diff --git a/srcs/layouts/hang_dubeolsik_kr.xml b/srcs/layouts/hang_dubeolsik_kr.xml index 29dd01b..0b11539 100644 --- a/srcs/layouts/hang_dubeolsik_kr.xml +++ b/srcs/layouts/hang_dubeolsik_kr.xml @@ -1,5 +1,16 @@ + + + + + + + + + +