diff --git a/srcs/juloo.keyboard2/Config.java b/srcs/juloo.keyboard2/Config.java index f2fe1b8..054fc41 100644 --- a/srcs/juloo.keyboard2/Config.java +++ b/srcs/juloo.keyboard2/Config.java @@ -47,7 +47,7 @@ final class Config public String actionLabel; // Might be 'null' public int actionId; // Meaningful only when 'actionLabel' isn't 'null' public boolean swapEnterActionKey; // Swap the "enter" and "action" keys - public Set extra_keys; // 'null' means all the keys + public Set extra_keys; // 'null' means all the keys public final IKeyEventHandler handler; @@ -151,18 +151,18 @@ final class Config { // Update the name to avoid caching in KeyModifier final KeyValue action_key = (actionLabel == null) ? null : - KeyValue.getKeyByName("action").withNameAndSymbol(actionLabel, actionLabel); + KeyValue.getKeyByName("action").withSymbol(actionLabel); // Extra keys are removed from the set as they are encountered during the // first iteration then automatically added. - final Set extra_keys = new HashSet(this.extra_keys); + final Set extra_keys = new HashSet(this.extra_keys); KeyboardData kw = original_kw.mapKeys(new KeyboardData.MapKeyValues() { public KeyValue apply(KeyValue key) { if (key == null) return null; - boolean is_extra_key = extra_keys.contains(key.name); + boolean is_extra_key = extra_keys.contains(key); if (is_extra_key) - extra_keys.remove(key.name); + extra_keys.remove(key); int flags = key.getFlags(); if ((flags & KeyValue.FLAG_LOCALIZED) != 0 && !is_extra_key) return null; @@ -196,15 +196,7 @@ final class Config } }); if (extra_keys.size() > 0) - { - final Iterator extra_keys_it = extra_keys.iterator(); - kw = kw.addExtraKeys( - new Iterator() - { - public boolean hasNext() { return extra_keys_it.hasNext(); } - public KeyValue next() { return KeyValue.getKeyByName(extra_keys_it.next()); } - }); - } + kw = kw.addExtraKeys(extra_keys.iterator()); return kw; } diff --git a/srcs/juloo.keyboard2/Emoji.java b/srcs/juloo.keyboard2/Emoji.java index 28c4f9f..2f00181 100644 --- a/srcs/juloo.keyboard2/Emoji.java +++ b/srcs/juloo.keyboard2/Emoji.java @@ -10,6 +10,7 @@ import java.util.HashMap; public class Emoji { + private final String _name; private final KeyValue _kv; private final String _desc; @@ -17,14 +18,15 @@ public class Emoji protected Emoji(String name, String bytecode, String desc) { - _kv = new KeyValue(name, bytecode, KeyValue.KIND_STRING, 0, 0); + _name = name; + _kv = new KeyValue(bytecode, KeyValue.KIND_STRING, 0, 0); _desc = desc; emojis_by_name.put(name, this); } public String name() { - return _kv.name; + return _name; } public KeyValue kv() diff --git a/srcs/juloo.keyboard2/KeyModifier.java b/srcs/juloo.keyboard2/KeyModifier.java index 4089ab8..fa23217 100644 --- a/srcs/juloo.keyboard2/KeyModifier.java +++ b/srcs/juloo.keyboard2/KeyModifier.java @@ -7,11 +7,8 @@ import java.util.HashMap; class KeyModifier { /** Cache key is KeyValue's name */ - private static HashMap> _cache = - new HashMap>(); - - /** Represents a removed key, because a cache entry can't be [null]. */ - private static final KeyValue removed_key = KeyValue.getKeyByName("removed"); + private static HashMap> _cache = + new HashMap>(); /** Modify a key according to modifiers. */ public static KeyValue modify(KeyValue k, Pointers.Modifiers mods) @@ -27,10 +24,10 @@ class KeyModifier /* Order: Fn, Shift, accents */ for (int i = 0; i < n_mods; i++) r = modify(r, mods.get(i)); - r = remove_placeholders(r); ks.put(mods, r); } - return (r == removed_key) ? null : r; + /* Keys with an empty string are placeholder keys. */ + return (r.getString().length() == 0) ? null : r; } public static KeyValue modify(KeyValue k, KeyValue.Modifier mod) @@ -117,70 +114,97 @@ class KeyModifier private static KeyValue apply_fn(KeyValue k) { - String name; - switch (k.name) + String name = null; + switch (k.getKind()) { - case "1": name = "f1"; break; - case "2": name = "f2"; break; - case "3": name = "f3"; break; - case "4": name = "f4"; break; - case "5": name = "f5"; break; - case "6": name = "f6"; break; - case "7": name = "f7"; break; - case "8": name = "f8"; break; - case "9": name = "f9"; break; - case "0": name = "f10"; break; - case "f11_placeholder": name = "f11"; break; - case "f12_placeholder": name = "f12"; break; - case "up": name = "page_up"; break; - case "down": name = "page_down"; break; - case "left": name = "home"; break; - case "right": name = "end"; break; - case "<": name = "«"; break; - case ">": name = "»"; break; - case "{": name = "‹"; break; - case "}": name = "›"; break; - case "[": name = "‘"; break; - case "]": name = "’"; break; - case "(": name = "“"; break; - case ")": name = "”"; break; - case "'": name = "‚"; break; - case "\"": name = "„"; break; - case "-": name = "–"; break; - case "_": name = "—"; break; - case "^": name = "¬"; break; - case "%": name = "‰"; break; - case "=": name = "≈"; break; - case "u": name = "µ"; break; - case "a": name = "æ"; break; - case "o": name = "œ"; break; - case "esc": name = "insert"; break; - case "*": name = "°"; break; - case ".": name = "…"; break; - case ",": name = "·"; break; - case "!": name = "¡"; break; - case "?": name = "¿"; break; - case "tab": name = "\\t"; break; - case "space": name = "nbsp"; break; - case "↖": name = "⇖"; break; - case "↑": name = "⇑"; break; - case "↗": name = "⇗"; break; - case "←": name = "⇐"; break; - case "→": name = "⇒"; break; - case "↙": name = "⇙"; break; - case "↓": name = "⇓"; break; - case "↘": name = "⇘"; break; - // Currency symbols - case "e": name = "€"; break; - case "l": name = "£"; break; - case "r": name = "₹"; break; - case "y": name = "¥"; break; - case "c": name = "¢"; break; - case "p": name = "₱"; break; - case "€": case "£": return removed_key; // Avoid showing these twice - default: return k; + case Char: name = apply_fn_char(k.getChar()); break; + case Keyevent: name = apply_fn_keyevent(k.getKeyevent()); break; + case String: + switch (k.getString()) + { + case "": + if (k == KeyValue.getKeyByName("f11_placeholder")) + name = "f11"; + else if (k == KeyValue.getKeyByName("f12_placeholder")) + name = "f12"; + break; + } + break; + } + return (name == null) ? k : KeyValue.getKeyByName(name); + } + + private static String apply_fn_keyevent(int code) + { + switch (code) + { + case KeyEvent.KEYCODE_DPAD_UP: return "page_up"; + case KeyEvent.KEYCODE_DPAD_DOWN: return "page_down"; + case KeyEvent.KEYCODE_DPAD_LEFT: return "home"; + case KeyEvent.KEYCODE_DPAD_RIGHT: return "end"; + case KeyEvent.KEYCODE_ESCAPE: return "insert"; + default: return null; + } + } + + /** Return the name of modified key, or [null]. */ + private static String apply_fn_char(char c) + { + switch (c) + { + case '1': return "f1"; + case '2': return "f2"; + case '3': return "f3"; + case '4': return "f4"; + case '5': return "f5"; + case '6': return "f6"; + case '7': return "f7"; + case '8': return "f8"; + case '9': return "f9"; + case '0': return "f10"; + case '<': return "«"; + case '>': return "»"; + case '{': return "‹"; + case '}': return "›"; + case '[': return "‘"; + case ']': return "’"; + case '(': return "“"; + case ')': return "”"; + case '\'': return "‚"; + case '"': return "„"; + case '-': return "–"; + case '_': return "—"; + case '^': return "¬"; + case '%': return "‰"; + case '=': return "≈"; + case 'u': return "µ"; + case 'a': return "æ"; + case 'o': return "œ"; + case '*': return "°"; + case '.': return "…"; + case ',': return "·"; + case '!': return "¡"; + case '?': return "¿"; + case '↖': return "⇖"; + case '↑': return "⇑"; + case '↗': return "⇗"; + case '←': return "⇐"; + case '→': return "⇒"; + case '↙': return "⇙"; + case '↓': return "⇓"; + case '↘': return "⇘"; + // Currency symbols + case 'e': return "€"; + case 'l': return "£"; + case 'r': return "₹"; + case 'y': return "¥"; + case 'c': return "¢"; + case 'p': return "₱"; + case '€': case '£': return "removed"; // Avoid showing these twice + case '\t': return "\\t"; + case ' ': return "nbsp"; + default: return null; } - return KeyValue.getKeyByName(name); } private static KeyValue turn_into_keyevent(KeyValue k) @@ -249,25 +273,14 @@ class KeyModifier return k.withKeyevent(e); } - /** Remove placeholder keys that haven't been modified into something. */ - private static KeyValue remove_placeholders(KeyValue k) - { - switch (k.name) - { - case "f11_placeholder": - case "f12_placeholder": return removed_key; - default: return k; - } - } - /* Lookup the cache entry for a key. Create it needed. */ private static HashMap cacheEntry(KeyValue k) { - HashMap ks = _cache.get(k.name); + HashMap ks = _cache.get(k); if (ks == null) { ks = new HashMap(); - _cache.put(k.name, ks); + _cache.put(k, ks); } return ks; } diff --git a/srcs/juloo.keyboard2/KeyValue.java b/srcs/juloo.keyboard2/KeyValue.java index f91e22d..4009525 100644 --- a/srcs/juloo.keyboard2/KeyValue.java +++ b/srcs/juloo.keyboard2/KeyValue.java @@ -78,7 +78,6 @@ final class KeyValue check((FLAGS_BITS | KIND_BITS | VALUE_BITS) == ~0); // No holes } - public final String name; private final String _symbol; /** This field encodes three things: @@ -150,37 +149,49 @@ final class KeyValue /* Update the char and the symbol. */ public KeyValue withChar(char c) { - return new KeyValue(name, String.valueOf(c), KIND_CHAR, c, getFlags()); + return new KeyValue(String.valueOf(c), KIND_CHAR, c, getFlags()); } public KeyValue withString(String s) { - return new KeyValue(name, s, KIND_STRING, 0, getFlags()); + return new KeyValue(s, KIND_STRING, 0, getFlags()); } - public KeyValue withNameAndSymbol(String n, String s) + public KeyValue withSymbol(String s) { - return new KeyValue(n, s, (_code & KIND_BITS), (_code & VALUE_BITS), getFlags()); + return new KeyValue(s, (_code & KIND_BITS), (_code & VALUE_BITS), getFlags()); } public KeyValue withKeyevent(int code) { - return new KeyValue(name, _symbol, KIND_KEYEVENT, code, getFlags()); + return new KeyValue(_symbol, KIND_KEYEVENT, code, getFlags()); } public KeyValue withFlags(int f) { - return new KeyValue(name, _symbol, (_code & KIND_BITS), (_code & VALUE_BITS), f); + return new KeyValue(_symbol, (_code & KIND_BITS), (_code & VALUE_BITS), f); + } + + @Override + public boolean equals(Object obj) + { + KeyValue snd = (KeyValue)obj; + return _symbol.equals(snd._symbol) && _code == snd._code; + } + + @Override + public int hashCode() + { + return _symbol.hashCode() + _code; } private static HashMap keys = new HashMap(); - public KeyValue(String n, String s, int kind, int value, int flags) + public KeyValue(String s, int kind, int value, int flags) { check((kind & ~KIND_BITS) == 0); check((flags & ~FLAGS_BITS) == 0); check((value & ~VALUE_BITS) == 0); - name = n; _symbol = s; _code = kind | flags | value; } @@ -207,14 +218,14 @@ final class KeyValue return kv.withFlags(kv.getFlags() | FLAG_LOCALIZED); } if (name.length() == 1) - return new KeyValue(name, name, KIND_CHAR, name.charAt(0), 0); + return new KeyValue(name, KIND_CHAR, name.charAt(0), 0); else - return new KeyValue(name, name, KIND_STRING, 0, 0); + return new KeyValue(name, KIND_STRING, 0, 0); } private static void addKey(String name, String symbol, int kind, int code, int flags) { - keys.put(name, new KeyValue(name, symbol, kind, code, flags)); + keys.put(name, new KeyValue(symbol, kind, code, flags)); } private static void addCharKey(String name, String symbol, char c, int flags) @@ -238,6 +249,11 @@ final class KeyValue addKey(name, symbol, KIND_KEYEVENT, code, flags); } + private static void addPlaceholderKey(String name) + { + addKey(name, "", KIND_STRING, 0, 0); + } + static { addModifierKey("shift", "\n", // Can't write u000A because Java is stupid @@ -307,7 +323,9 @@ final class KeyValue addCharKey("space", "\r", ' ', FLAG_KEY_FONT); addCharKey("nbsp", "\u237d", '\u00a0', FLAG_KEY_FONT | FLAG_SMALLER_FONT); - addKey("removed", "", KIND_STRING, 0, 0); // Dummy key used in [KeyModifier] + addPlaceholderKey("removed"); + addPlaceholderKey("f11_placeholder"); + addPlaceholderKey("f12_placeholder"); } // Substitute for [assert], which has no effect on Android. diff --git a/srcs/juloo.keyboard2/Keyboard2.java b/srcs/juloo.keyboard2/Keyboard2.java index 32a27a8..77fc0bf 100644 --- a/srcs/juloo.keyboard2/Keyboard2.java +++ b/srcs/juloo.keyboard2/Keyboard2.java @@ -80,19 +80,19 @@ public class Keyboard2 extends InputMethodService _currentTextLayout = l; } - private void extra_keys_of_subtype(Set dst, InputMethodSubtype subtype) + private void extra_keys_of_subtype(Set dst, InputMethodSubtype subtype) { String extra_keys = subtype.getExtraValueOf("extra_keys"); if (extra_keys == null) return; String[] ks = extra_keys.split("\\|"); for (int i = 0; i < ks.length; i++) - dst.add(ks[i]); + dst.add(KeyValue.getKeyByName(ks[i])); } private void refreshAccentsOption(InputMethodManager imm, InputMethodSubtype subtype) { - HashSet extra_keys = new HashSet(); + HashSet extra_keys = new HashSet(); List enabled_subtypes = getEnabledSubtypes(imm); switch (_config.accents) { @@ -119,7 +119,7 @@ public class Keyboard2 extends InputMethodService switch (_config.accents) { case 1: case 2: case 3: _config.extra_keys = null; break; - case 4: _config.extra_keys = new HashSet(); break; + case 4: _config.extra_keys = new HashSet(); break; } // Fallback for the layout option: Use qwerty in the "system settings" case _currentTextLayout = (_config.layout == -1) ? R.xml.qwerty : _config.layout; diff --git a/srcs/juloo.keyboard2/Pointers.java b/srcs/juloo.keyboard2/Pointers.java index 7ef714b..0548b88 100644 --- a/srcs/juloo.keyboard2/Pointers.java +++ b/srcs/juloo.keyboard2/Pointers.java @@ -68,11 +68,8 @@ public final class Pointers implements Handler.Callback */ public int getKeyFlags(KeyValue kv) { - // Comparing names because the keys might have been modified. - // Physical equality works because names are never computed or shared. - String name = kv.name; for (Pointer p : _ptrs) - if (p.value != null && p.value.name == name) + if (p.value != null && p.value.equals(kv)) return p.flags; return -1; } @@ -214,7 +211,7 @@ public final class Pointers implements Handler.Callback { ptr.selected_direction = direction; KeyValue newValue = getKeyAtDirection(ptr, direction); - if (newValue != null && (ptr.value == null || newValue.name != ptr.value.name)) + if (newValue != null && (ptr.value == null || !newValue.equals(ptr.value))) { int old_flags = ptr.flags; ptr.value = newValue; @@ -253,7 +250,7 @@ public final class Pointers implements Handler.Callback if (v == null) return null; for (Pointer p : _ptrs) - if (p.key == k && p.pointerId == -1 && p.value != null && p.value.name == v.name) + if (p.key == k && p.pointerId == -1 && p.value != null && p.value.equals(v)) return p; return null; }