2015-07-30 20:14:55 +02:00
|
|
|
package juloo.keyboard2;
|
|
|
|
|
|
|
|
import android.view.KeyEvent;
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
2024-03-18 00:14:19 +01:00
|
|
|
public final class KeyValue implements Comparable<KeyValue>
|
2015-07-30 20:14:55 +02:00
|
|
|
{
|
2022-06-05 19:30:53 +02:00
|
|
|
public static enum Event
|
|
|
|
{
|
|
|
|
CONFIG,
|
|
|
|
SWITCH_TEXT,
|
|
|
|
SWITCH_NUMERIC,
|
|
|
|
SWITCH_EMOJI,
|
|
|
|
SWITCH_BACK_EMOJI,
|
2024-01-15 22:09:15 +01:00
|
|
|
CHANGE_METHOD_PICKER,
|
|
|
|
CHANGE_METHOD_AUTO,
|
2022-06-05 19:30:53 +02:00
|
|
|
ACTION,
|
2023-07-29 18:37:06 +02:00
|
|
|
SWITCH_FORWARD,
|
|
|
|
SWITCH_BACKWARD,
|
2022-10-23 21:34:05 +02:00
|
|
|
SWITCH_GREEKMATH,
|
|
|
|
CAPS_LOCK,
|
2023-06-03 18:11:42 +02:00
|
|
|
SWITCH_VOICE_TYPING,
|
2023-12-30 01:24:21 +01:00
|
|
|
SWITCH_VOICE_TYPING_CHOOSER,
|
2022-06-05 19:30:53 +02:00
|
|
|
}
|
|
|
|
|
2022-06-05 01:38:42 +02:00
|
|
|
// Must be evaluated in the reverse order of their values.
|
2022-06-05 19:30:53 +02:00
|
|
|
public static enum Modifier
|
|
|
|
{
|
|
|
|
SHIFT,
|
2024-05-25 02:19:55 +02:00
|
|
|
GESTURE,
|
2022-06-05 19:30:53 +02:00
|
|
|
CTRL,
|
|
|
|
ALT,
|
|
|
|
META,
|
|
|
|
DOUBLE_AIGU,
|
|
|
|
DOT_ABOVE,
|
2023-02-09 18:40:48 +01:00
|
|
|
DOT_BELOW,
|
2022-06-05 19:30:53 +02:00
|
|
|
GRAVE,
|
|
|
|
AIGU,
|
|
|
|
CIRCONFLEXE,
|
|
|
|
TILDE,
|
|
|
|
CEDILLE,
|
|
|
|
TREMA,
|
2023-02-09 18:40:48 +01:00
|
|
|
HORN,
|
|
|
|
HOOK_ABOVE,
|
2022-06-05 19:30:53 +02:00
|
|
|
SUPERSCRIPT,
|
|
|
|
SUBSCRIPT,
|
|
|
|
RING,
|
|
|
|
CARON,
|
|
|
|
MACRON,
|
|
|
|
ORDINAL,
|
|
|
|
ARROWS,
|
|
|
|
BOX,
|
|
|
|
OGONEK,
|
|
|
|
SLASH,
|
2022-10-15 23:28:36 +02:00
|
|
|
ARROW_RIGHT,
|
2022-11-05 10:29:36 +01:00
|
|
|
BREVE,
|
2022-11-05 19:26:49 +01:00
|
|
|
BAR,
|
2024-05-25 02:19:55 +02:00
|
|
|
FN,
|
|
|
|
} // Last is be applied first
|
2022-06-05 01:38:42 +02:00
|
|
|
|
2022-11-13 16:45:57 +01:00
|
|
|
public static enum Editing
|
|
|
|
{
|
|
|
|
COPY,
|
|
|
|
PASTE,
|
|
|
|
CUT,
|
|
|
|
SELECT_ALL,
|
2022-12-30 15:15:58 +01:00
|
|
|
PASTE_PLAIN,
|
|
|
|
UNDO,
|
|
|
|
REDO,
|
|
|
|
// Android context menu actions
|
|
|
|
REPLACE,
|
|
|
|
SHARE,
|
|
|
|
ASSIST,
|
|
|
|
AUTOFILL,
|
2022-11-13 16:45:57 +01:00
|
|
|
}
|
|
|
|
|
2023-01-30 21:29:59 +01:00
|
|
|
public static enum Placeholder
|
|
|
|
{
|
|
|
|
REMOVED,
|
|
|
|
F11,
|
2023-01-20 03:58:40 +01:00
|
|
|
F12,
|
|
|
|
SHINDOT,
|
|
|
|
SINDOT,
|
|
|
|
OLE,
|
|
|
|
METEG
|
2023-01-30 21:29:59 +01:00
|
|
|
}
|
|
|
|
|
2022-11-13 15:19:50 +01:00
|
|
|
public static enum Kind
|
|
|
|
{
|
2024-05-02 20:52:18 +02:00
|
|
|
Char, String, Keyevent, Event, Compose_pending, Hangul_initial,
|
|
|
|
Hangul_medial, Modifier, Editing, Placeholder,
|
2024-05-02 19:31:48 +02:00
|
|
|
Cursor_move // Value is encoded as a 16-bit integer
|
2022-11-13 15:19:50 +01:00
|
|
|
}
|
|
|
|
|
2024-02-16 20:43:39 +01:00
|
|
|
private static final int FLAGS_OFFSET = 19;
|
|
|
|
private static final int KIND_OFFSET = 28;
|
|
|
|
|
2022-06-05 19:55:55 +02:00
|
|
|
// Behavior flags.
|
2024-02-16 20:43:39 +01:00
|
|
|
public static final int FLAG_LATCH = (1 << FLAGS_OFFSET << 0);
|
2024-03-11 00:10:12 +01:00
|
|
|
// Key can be locked by typing twice
|
2024-02-16 20:43:39 +01:00
|
|
|
public static final int FLAG_LOCK = (1 << FLAGS_OFFSET << 1);
|
2022-06-05 19:55:55 +02:00
|
|
|
// Special keys are not repeated and don't clear latched modifiers.
|
2024-02-16 20:43:39 +01:00
|
|
|
public static final int FLAG_SPECIAL = (1 << FLAGS_OFFSET << 2);
|
2024-02-17 19:31:52 +01:00
|
|
|
// Whether the symbol should be greyed out. For example, keys that are not
|
|
|
|
// part of the pending compose sequence.
|
|
|
|
public static final int FLAG_GREYED = (1 << FLAGS_OFFSET << 3);
|
2022-06-05 19:55:55 +02:00
|
|
|
// Rendering flags.
|
2024-02-16 20:43:39 +01:00
|
|
|
public static final int FLAG_KEY_FONT = (1 << FLAGS_OFFSET << 4); // special font file
|
|
|
|
public static final int FLAG_SMALLER_FONT = (1 << FLAGS_OFFSET << 5); // 25% smaller symbols
|
|
|
|
public static final int FLAG_SECONDARY = (1 << FLAGS_OFFSET << 6); // dimmer
|
2022-06-05 19:55:55 +02:00
|
|
|
// Used by [Pointers].
|
2024-03-11 00:10:12 +01:00
|
|
|
// Free: (1 << FLAGS_OFFSET << 7)
|
|
|
|
// Free: (1 << FLAGS_OFFSET << 8)
|
2022-06-05 19:55:55 +02:00
|
|
|
|
|
|
|
// Ranges for the different components
|
2024-02-16 20:43:39 +01:00
|
|
|
private static final int FLAGS_BITS =
|
2024-02-17 19:31:52 +01:00
|
|
|
FLAG_LATCH | FLAG_LOCK | FLAG_SPECIAL | FLAG_GREYED | FLAG_KEY_FONT |
|
2024-03-11 00:10:12 +01:00
|
|
|
FLAG_SMALLER_FONT | FLAG_SECONDARY;
|
2024-02-16 20:43:39 +01:00
|
|
|
private static final int KIND_BITS = (0b1111 << KIND_OFFSET); // 4 bits wide
|
2022-06-05 19:55:55 +02:00
|
|
|
private static final int VALUE_BITS = ~(FLAGS_BITS | KIND_BITS); // 20 bits wide
|
2024-02-16 20:43:39 +01:00
|
|
|
|
2022-06-05 19:55:55 +02:00
|
|
|
static
|
|
|
|
{
|
|
|
|
check((FLAGS_BITS & KIND_BITS) == 0); // No overlap
|
|
|
|
check((FLAGS_BITS | KIND_BITS | VALUE_BITS) == ~0); // No holes
|
2024-02-16 20:43:39 +01:00
|
|
|
// No kind is out of range
|
|
|
|
check((((Kind.values().length - 1) << KIND_OFFSET) & ~KIND_BITS) == 0);
|
2022-06-05 19:55:55 +02:00
|
|
|
}
|
2022-06-05 18:14:50 +02:00
|
|
|
|
2022-06-05 17:26:34 +02:00
|
|
|
private final String _symbol;
|
2022-06-05 01:38:42 +02:00
|
|
|
|
2022-11-13 15:19:50 +01:00
|
|
|
/** This field encodes three things: Kind, flags and value. */
|
2022-06-05 17:26:34 +02:00
|
|
|
private final int _code;
|
|
|
|
|
|
|
|
public Kind getKind()
|
|
|
|
{
|
2024-02-16 20:43:39 +01:00
|
|
|
return Kind.values()[(_code & KIND_BITS) >>> KIND_OFFSET];
|
2022-06-05 17:26:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public int getFlags()
|
|
|
|
{
|
2022-06-05 19:55:55 +02:00
|
|
|
return (_code & FLAGS_BITS);
|
2022-06-05 17:26:34 +02:00
|
|
|
}
|
|
|
|
|
2024-02-17 19:31:52 +01:00
|
|
|
public boolean hasFlagsAny(int has)
|
2022-06-05 17:26:34 +02:00
|
|
|
{
|
2024-02-17 19:31:52 +01:00
|
|
|
return ((_code & has) != 0);
|
2022-06-05 17:26:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** The string to render on the keyboard.
|
|
|
|
When [getKind() == Kind.String], also the string to send. */
|
|
|
|
public String getString()
|
|
|
|
{
|
|
|
|
return _symbol;
|
|
|
|
}
|
|
|
|
|
2022-06-05 19:30:53 +02:00
|
|
|
/** Defined only when [getKind() == Kind.Char]. */
|
2022-06-05 17:26:34 +02:00
|
|
|
public char getChar()
|
|
|
|
{
|
2022-06-05 19:55:55 +02:00
|
|
|
return (char)(_code & VALUE_BITS);
|
2022-06-05 17:26:34 +02:00
|
|
|
}
|
|
|
|
|
2022-06-05 19:30:53 +02:00
|
|
|
/** Defined only when [getKind() == Kind.Keyevent]. */
|
|
|
|
public int getKeyevent()
|
2022-06-05 17:26:34 +02:00
|
|
|
{
|
2022-06-05 19:55:55 +02:00
|
|
|
return (_code & VALUE_BITS);
|
2022-06-05 17:26:34 +02:00
|
|
|
}
|
|
|
|
|
2022-06-05 19:30:53 +02:00
|
|
|
/** Defined only when [getKind() == Kind.Event]. */
|
|
|
|
public Event getEvent()
|
2022-06-05 17:26:34 +02:00
|
|
|
{
|
2022-06-05 19:55:55 +02:00
|
|
|
return Event.values()[(_code & VALUE_BITS)];
|
2022-06-05 19:30:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Defined only when [getKind() == Kind.Modifier]. */
|
|
|
|
public Modifier getModifier()
|
|
|
|
{
|
2022-06-05 19:55:55 +02:00
|
|
|
return Modifier.values()[(_code & VALUE_BITS)];
|
2022-06-05 17:26:34 +02:00
|
|
|
}
|
2021-04-18 23:28:49 +02:00
|
|
|
|
2022-11-13 16:45:57 +01:00
|
|
|
/** Defined only when [getKind() == Kind.Editing]. */
|
|
|
|
public Editing getEditing()
|
|
|
|
{
|
|
|
|
return Editing.values()[(_code & VALUE_BITS)];
|
|
|
|
}
|
|
|
|
|
2024-02-11 20:46:36 +01:00
|
|
|
/** Defined only when [getKind() == Kind.Placeholder]. */
|
2023-01-30 21:29:59 +01:00
|
|
|
public Placeholder getPlaceholder()
|
|
|
|
{
|
|
|
|
return Placeholder.values()[(_code & VALUE_BITS)];
|
|
|
|
}
|
|
|
|
|
2024-02-11 20:46:36 +01:00
|
|
|
/** Defined only when [getKind() == Kind.Compose_pending]. */
|
|
|
|
public int getPendingCompose()
|
|
|
|
{
|
|
|
|
return (_code & VALUE_BITS);
|
|
|
|
}
|
|
|
|
|
2024-05-02 20:52:18 +02:00
|
|
|
/** Defined only when [getKind()] is [Kind.Hangul_initial] or
|
|
|
|
[Kind.Hangul_medial]. */
|
|
|
|
public int getHangulPrecomposed()
|
|
|
|
{
|
|
|
|
return (_code & VALUE_BITS);
|
|
|
|
}
|
|
|
|
|
2024-05-02 19:31:48 +02:00
|
|
|
/** Defined only when [getKind() == Kind.Cursor_move]. */
|
|
|
|
public short getCursorMove()
|
|
|
|
{
|
|
|
|
return (short)(_code & VALUE_BITS);
|
|
|
|
}
|
|
|
|
|
2021-05-08 02:00:47 +02:00
|
|
|
/* Update the char and the symbol. */
|
2022-06-05 18:14:50 +02:00
|
|
|
public KeyValue withChar(char c)
|
2021-05-08 02:00:47 +02:00
|
|
|
{
|
2022-11-13 15:19:50 +01:00
|
|
|
return new KeyValue(String.valueOf(c), Kind.Char, c, getFlags());
|
2021-05-08 02:00:47 +02:00
|
|
|
}
|
|
|
|
|
2022-06-06 00:23:45 +02:00
|
|
|
public KeyValue withSymbol(String s)
|
2022-03-06 19:36:09 +01:00
|
|
|
{
|
2022-06-06 00:23:45 +02:00
|
|
|
return new KeyValue(s, (_code & KIND_BITS), (_code & VALUE_BITS), getFlags());
|
2022-03-06 19:36:09 +01:00
|
|
|
}
|
|
|
|
|
2022-06-05 19:30:53 +02:00
|
|
|
public KeyValue withKeyevent(int code)
|
2022-06-05 17:44:00 +02:00
|
|
|
{
|
2022-11-13 15:19:50 +01:00
|
|
|
return new KeyValue(_symbol, Kind.Keyevent, code, getFlags());
|
2022-06-05 17:44:00 +02:00
|
|
|
}
|
|
|
|
|
2022-03-05 20:17:45 +01:00
|
|
|
public KeyValue withFlags(int f)
|
|
|
|
{
|
2022-06-06 00:23:45 +02:00
|
|
|
return new KeyValue(_symbol, (_code & KIND_BITS), (_code & VALUE_BITS), f);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean equals(Object obj)
|
|
|
|
{
|
2023-03-03 19:44:05 +01:00
|
|
|
return sameKey((KeyValue)obj);
|
|
|
|
}
|
|
|
|
|
2024-03-18 00:14:19 +01:00
|
|
|
public int compareTo(KeyValue snd)
|
|
|
|
{
|
|
|
|
// Compare the kind and value first, then the flags.
|
|
|
|
int d = (_code & ~FLAGS_BITS) - (snd._code & ~FLAGS_BITS);
|
|
|
|
if (d != 0)
|
|
|
|
return d;
|
|
|
|
d = _code - snd._code;
|
|
|
|
if (d != 0)
|
|
|
|
return d;
|
|
|
|
return _symbol.compareTo(snd._symbol);
|
|
|
|
}
|
|
|
|
|
2023-03-03 19:44:05 +01:00
|
|
|
/** Type-safe alternative to [equals]. */
|
|
|
|
public boolean sameKey(KeyValue snd)
|
|
|
|
{
|
|
|
|
if (snd == null)
|
|
|
|
return false;
|
2022-06-06 00:23:45 +02:00
|
|
|
return _symbol.equals(snd._symbol) && _code == snd._code;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int hashCode()
|
|
|
|
{
|
|
|
|
return _symbol.hashCode() + _code;
|
2022-03-05 20:17:45 +01:00
|
|
|
}
|
|
|
|
|
2022-06-06 00:23:45 +02:00
|
|
|
public KeyValue(String s, int kind, int value, int flags)
|
2021-04-18 23:28:49 +02:00
|
|
|
{
|
2022-06-05 17:26:34 +02:00
|
|
|
_symbol = s;
|
2024-02-16 20:43:39 +01:00
|
|
|
_code = (kind & KIND_BITS) | (flags & FLAGS_BITS) | (value & VALUE_BITS);
|
2021-04-18 23:28:49 +02:00
|
|
|
}
|
|
|
|
|
2022-11-13 15:19:50 +01:00
|
|
|
public KeyValue(String s, Kind k, int v, int f)
|
|
|
|
{
|
2024-02-16 20:43:39 +01:00
|
|
|
this(s, (k.ordinal() << KIND_OFFSET), v, f);
|
2022-11-13 15:19:50 +01:00
|
|
|
}
|
|
|
|
|
2023-01-29 19:38:54 +01:00
|
|
|
private static KeyValue charKey(String symbol, char c, int flags)
|
2021-04-18 23:28:49 +02:00
|
|
|
{
|
2023-01-29 19:38:54 +01:00
|
|
|
return new KeyValue(symbol, Kind.Char, c, flags);
|
2021-04-18 23:28:49 +02:00
|
|
|
}
|
2015-08-01 16:33:30 +02:00
|
|
|
|
2024-04-03 23:55:38 +02:00
|
|
|
private static KeyValue charKey(int symbol, char c, int flags)
|
|
|
|
{
|
|
|
|
return charKey(String.valueOf((char)symbol), c, flags);
|
|
|
|
}
|
|
|
|
|
2023-01-29 19:38:54 +01:00
|
|
|
private static KeyValue modifierKey(String symbol, Modifier m, int flags)
|
2021-04-18 21:58:13 +02:00
|
|
|
{
|
2022-10-23 21:42:03 +02:00
|
|
|
if (symbol.length() > 1)
|
|
|
|
flags |= FLAG_SMALLER_FONT;
|
2023-01-29 19:38:54 +01:00
|
|
|
return new KeyValue(symbol, Kind.Modifier, m.ordinal(),
|
2022-11-11 19:15:25 +01:00
|
|
|
FLAG_LATCH | FLAG_SPECIAL | FLAG_SECONDARY | flags);
|
2022-02-13 13:46:37 +01:00
|
|
|
}
|
|
|
|
|
2023-01-29 19:38:54 +01:00
|
|
|
private static KeyValue modifierKey(int symbol, Modifier m, int flags)
|
2022-10-15 23:28:36 +02:00
|
|
|
{
|
2023-01-29 19:38:54 +01:00
|
|
|
return modifierKey(String.valueOf((char)symbol), m, flags | FLAG_KEY_FONT);
|
2022-10-23 21:42:03 +02:00
|
|
|
}
|
|
|
|
|
2023-01-29 19:38:54 +01:00
|
|
|
private static KeyValue diacritic(int symbol, Modifier m)
|
2022-10-23 21:42:03 +02:00
|
|
|
{
|
2023-01-29 19:38:54 +01:00
|
|
|
return new KeyValue(String.valueOf((char)symbol), Kind.Modifier, m.ordinal(),
|
2022-11-11 19:15:25 +01:00
|
|
|
FLAG_LATCH | FLAG_SPECIAL | FLAG_KEY_FONT);
|
2022-10-15 23:28:36 +02:00
|
|
|
}
|
|
|
|
|
2023-01-29 19:38:54 +01:00
|
|
|
private static KeyValue eventKey(String symbol, Event e, int flags)
|
2022-02-13 13:46:37 +01:00
|
|
|
{
|
2023-01-29 19:38:54 +01:00
|
|
|
return new KeyValue(symbol, Kind.Event, e.ordinal(), flags | FLAG_SPECIAL | FLAG_SECONDARY);
|
2021-04-18 21:58:13 +02:00
|
|
|
}
|
|
|
|
|
2023-01-29 19:38:54 +01:00
|
|
|
private static KeyValue eventKey(int symbol, Event e, int flags)
|
2022-10-23 21:42:03 +02:00
|
|
|
{
|
2023-01-29 19:38:54 +01:00
|
|
|
return eventKey(String.valueOf((char)symbol), e, flags | FLAG_KEY_FONT);
|
2022-10-23 21:42:03 +02:00
|
|
|
}
|
|
|
|
|
2023-01-29 19:38:54 +01:00
|
|
|
private static KeyValue keyeventKey(String symbol, int code, int flags)
|
2021-04-19 22:29:20 +02:00
|
|
|
{
|
2023-01-29 19:38:54 +01:00
|
|
|
return new KeyValue(symbol, Kind.Keyevent, code, flags | FLAG_SECONDARY);
|
2021-04-19 22:29:20 +02:00
|
|
|
}
|
|
|
|
|
2023-01-29 19:38:54 +01:00
|
|
|
private static KeyValue keyeventKey(int symbol, int code, int flags)
|
2022-10-23 21:42:03 +02:00
|
|
|
{
|
2023-01-29 19:38:54 +01:00
|
|
|
return keyeventKey(String.valueOf((char)symbol), code, flags | FLAG_KEY_FONT);
|
2022-10-23 21:42:03 +02:00
|
|
|
}
|
|
|
|
|
2023-08-06 19:17:05 +02:00
|
|
|
private static KeyValue editingKey(String symbol, Editing action, int flags)
|
2022-11-13 16:45:57 +01:00
|
|
|
{
|
2023-01-29 19:38:54 +01:00
|
|
|
return new KeyValue(symbol, Kind.Editing, action.ordinal(),
|
2023-08-06 19:17:05 +02:00
|
|
|
flags | FLAG_SPECIAL | FLAG_SECONDARY);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static KeyValue editingKey(String symbol, Editing action)
|
|
|
|
{
|
|
|
|
return editingKey(symbol, action, FLAG_SMALLER_FONT);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static KeyValue editingKey(int symbol, Editing action)
|
|
|
|
{
|
|
|
|
return editingKey(String.valueOf((char)symbol), action, FLAG_KEY_FONT);
|
2022-11-13 16:45:57 +01:00
|
|
|
}
|
|
|
|
|
2024-05-02 19:31:48 +02:00
|
|
|
/** A key that moves the cursor [d] times to the right. If [d] is negative,
|
|
|
|
it moves the cursor [abs(d)] times to the left. */
|
|
|
|
public static KeyValue cursorMoveKey(int d)
|
|
|
|
{
|
|
|
|
int symbol = (d < 0) ? 0xE008 : 0xE006;
|
|
|
|
return new KeyValue(String.valueOf((char)symbol), Kind.Cursor_move,
|
|
|
|
((short)d) & 0xFFFF,
|
|
|
|
FLAG_SPECIAL | FLAG_SECONDARY | FLAG_KEY_FONT);
|
|
|
|
}
|
|
|
|
|
2023-01-30 21:29:59 +01:00
|
|
|
/** A key that do nothing but has a unique ID. */
|
|
|
|
private static KeyValue placeholderKey(Placeholder id)
|
2022-06-06 00:23:45 +02:00
|
|
|
{
|
2023-01-30 21:29:59 +01:00
|
|
|
return new KeyValue("", Kind.Placeholder, id.ordinal(), 0);
|
2022-06-06 00:23:45 +02:00
|
|
|
}
|
|
|
|
|
2023-07-17 00:05:27 +02:00
|
|
|
public static KeyValue makeStringKey(String str)
|
2023-08-20 00:44:22 +02:00
|
|
|
{
|
|
|
|
return makeStringKey(str, 0);
|
|
|
|
}
|
|
|
|
|
2024-02-11 20:46:36 +01:00
|
|
|
public static KeyValue makeCharKey(char c)
|
|
|
|
{
|
|
|
|
return new KeyValue(String.valueOf(c), Kind.Char, c, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static KeyValue makeComposePending(String symbol, int state, int flags)
|
|
|
|
{
|
|
|
|
return new KeyValue(symbol, Kind.Compose_pending, state,
|
2024-03-18 01:00:22 +01:00
|
|
|
flags | FLAG_LATCH);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static KeyValue makeComposePending(int symbol, int state, int flags)
|
|
|
|
{
|
|
|
|
return makeComposePending(String.valueOf((char)symbol), state,
|
|
|
|
flags | FLAG_KEY_FONT);
|
2024-02-11 20:46:36 +01:00
|
|
|
}
|
|
|
|
|
2024-05-02 20:52:18 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2023-08-20 00:44:22 +02:00
|
|
|
/** 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)
|
2023-01-29 19:38:54 +01:00
|
|
|
{
|
2023-07-17 00:05:27 +02:00
|
|
|
if (str.length() == 1)
|
2023-08-20 00:44:22 +02:00
|
|
|
return new KeyValue(str, Kind.Char, str.charAt(0), flags);
|
2023-01-29 19:38:54 +01:00
|
|
|
else
|
2023-08-20 00:44:22 +02:00
|
|
|
return new KeyValue(str, Kind.String, 0, flags | FLAG_SMALLER_FONT);
|
2023-01-29 19:38:54 +01:00
|
|
|
}
|
|
|
|
|
2024-05-25 02:19:55 +02:00
|
|
|
/** Make a modifier key for passing to [KeyModifier]. */
|
|
|
|
public static KeyValue makeInternalModifier(Modifier mod)
|
|
|
|
{
|
|
|
|
return new KeyValue("", Kind.Modifier, mod.ordinal(), 0);
|
|
|
|
}
|
|
|
|
|
2023-01-29 19:38:54 +01:00
|
|
|
public static KeyValue getKeyByName(String name)
|
2021-04-18 21:58:13 +02:00
|
|
|
{
|
2023-01-29 19:38:54 +01:00
|
|
|
switch (name)
|
|
|
|
{
|
2024-01-21 16:34:49 +01:00
|
|
|
/* These symbols have special meaning when in `srcs/layouts` and are
|
|
|
|
escaped in standard layouts. The backslash is not stripped when parsed
|
|
|
|
from the custom layout option. */
|
2023-07-17 00:05:27 +02:00
|
|
|
case "\\?": return makeStringKey("?");
|
|
|
|
case "\\#": return makeStringKey("#");
|
|
|
|
case "\\@": return makeStringKey("@");
|
|
|
|
case "\\\\": return makeStringKey("\\");
|
2023-06-28 18:02:01 +02:00
|
|
|
|
2023-08-17 12:47:44 +02:00
|
|
|
/* Modifiers and dead-keys */
|
2023-08-02 20:39:37 +02:00
|
|
|
case "shift": return modifierKey(0xE00A, Modifier.SHIFT, 0);
|
2023-01-29 19:38:54 +01:00
|
|
|
case "ctrl": return modifierKey("Ctrl", Modifier.CTRL, 0);
|
|
|
|
case "alt": return modifierKey("Alt", Modifier.ALT, 0);
|
2023-08-02 20:39:37 +02:00
|
|
|
case "accent_aigu": return diacritic(0xE050, Modifier.AIGU);
|
|
|
|
case "accent_caron": return diacritic(0xE051, Modifier.CARON);
|
|
|
|
case "accent_cedille": return diacritic(0xE052, Modifier.CEDILLE);
|
|
|
|
case "accent_circonflexe": return diacritic(0xE053, Modifier.CIRCONFLEXE);
|
|
|
|
case "accent_grave": return diacritic(0xE054, Modifier.GRAVE);
|
|
|
|
case "accent_macron": return diacritic(0xE055, Modifier.MACRON);
|
|
|
|
case "accent_ring": return diacritic(0xE056, Modifier.RING);
|
|
|
|
case "accent_tilde": return diacritic(0xE057, Modifier.TILDE);
|
|
|
|
case "accent_trema": return diacritic(0xE058, Modifier.TREMA);
|
|
|
|
case "accent_ogonek": return diacritic(0xE059, Modifier.OGONEK);
|
|
|
|
case "accent_dot_above": return diacritic(0xE05A, Modifier.DOT_ABOVE);
|
|
|
|
case "accent_double_aigu": return diacritic(0xE05B, Modifier.DOUBLE_AIGU);
|
|
|
|
case "accent_slash": return diacritic(0xE05C, Modifier.SLASH);
|
|
|
|
case "accent_arrow_right": return diacritic(0xE05D, Modifier.ARROW_RIGHT);
|
|
|
|
case "accent_breve": return diacritic(0xE05E, Modifier.BREVE);
|
|
|
|
case "accent_bar": return diacritic(0xE05F, Modifier.BAR);
|
|
|
|
case "accent_dot_below": return diacritic(0xE060, Modifier.DOT_BELOW);
|
|
|
|
case "accent_horn": return diacritic(0xE061, Modifier.HORN);
|
|
|
|
case "accent_hook_above": return diacritic(0xE062, Modifier.HOOK_ABOVE);
|
2023-01-29 19:38:54 +01:00
|
|
|
case "superscript": return modifierKey("Sup", Modifier.SUPERSCRIPT, 0);
|
|
|
|
case "subscript": return modifierKey("Sub", Modifier.SUBSCRIPT, 0);
|
|
|
|
case "ordinal": return modifierKey("Ord", Modifier.ORDINAL, 0);
|
|
|
|
case "arrows": return modifierKey("Arr", Modifier.ARROWS, 0);
|
|
|
|
case "box": return modifierKey("Box", Modifier.BOX, 0);
|
|
|
|
case "fn": return modifierKey("Fn", Modifier.FN, 0);
|
|
|
|
case "meta": return modifierKey("Meta", Modifier.META, 0);
|
|
|
|
|
2023-08-17 12:47:44 +02:00
|
|
|
/* Special event keys */
|
2023-08-02 20:39:37 +02:00
|
|
|
case "config": return eventKey(0xE004, Event.CONFIG, FLAG_SMALLER_FONT);
|
2023-01-29 19:38:54 +01:00
|
|
|
case "switch_text": return eventKey("ABC", Event.SWITCH_TEXT, FLAG_SMALLER_FONT);
|
|
|
|
case "switch_numeric": return eventKey("123+", Event.SWITCH_NUMERIC, FLAG_SMALLER_FONT);
|
2023-08-02 20:39:37 +02:00
|
|
|
case "switch_emoji": return eventKey(0xE001, Event.SWITCH_EMOJI, FLAG_SMALLER_FONT);
|
2023-01-29 19:38:54 +01:00
|
|
|
case "switch_back_emoji": return eventKey("ABC", Event.SWITCH_BACK_EMOJI, 0);
|
2023-08-02 20:39:37 +02:00
|
|
|
case "switch_forward": return eventKey(0xE013, Event.SWITCH_FORWARD, FLAG_SMALLER_FONT);
|
|
|
|
case "switch_backward": return eventKey(0xE014, Event.SWITCH_BACKWARD, FLAG_SMALLER_FONT);
|
2023-01-29 19:38:54 +01:00
|
|
|
case "switch_greekmath": return eventKey("πλ∇¬", Event.SWITCH_GREEKMATH, FLAG_SMALLER_FONT);
|
2024-01-15 22:09:15 +01:00
|
|
|
case "change_method": return eventKey(0xE009, Event.CHANGE_METHOD_PICKER, FLAG_SMALLER_FONT);
|
|
|
|
case "change_method_prev": return eventKey(0xE009, Event.CHANGE_METHOD_AUTO, FLAG_SMALLER_FONT);
|
2023-01-29 19:38:54 +01:00
|
|
|
case "action": return eventKey("Action", Event.ACTION, FLAG_SMALLER_FONT); // Will always be replaced
|
2023-08-02 20:39:37 +02:00
|
|
|
case "capslock": return eventKey(0xE012, Event.CAPS_LOCK, 0);
|
|
|
|
case "voice_typing": return eventKey(0xE015, Event.SWITCH_VOICE_TYPING, FLAG_SMALLER_FONT);
|
2023-12-30 01:24:21 +01:00
|
|
|
case "voice_typing_chooser": return eventKey(0xE015, Event.SWITCH_VOICE_TYPING_CHOOSER, FLAG_SMALLER_FONT);
|
2023-01-29 19:38:54 +01:00
|
|
|
|
2023-08-17 12:47:44 +02:00
|
|
|
/* Key events */
|
2023-01-29 19:38:54 +01:00
|
|
|
case "esc": return keyeventKey("Esc", KeyEvent.KEYCODE_ESCAPE, FLAG_SMALLER_FONT);
|
2023-08-02 20:39:37 +02:00
|
|
|
case "enter": return keyeventKey(0xE00E, KeyEvent.KEYCODE_ENTER, 0);
|
|
|
|
case "up": return keyeventKey(0xE005, KeyEvent.KEYCODE_DPAD_UP, 0);
|
|
|
|
case "right": return keyeventKey(0xE006, KeyEvent.KEYCODE_DPAD_RIGHT, 0);
|
|
|
|
case "down": return keyeventKey(0xE007, KeyEvent.KEYCODE_DPAD_DOWN, 0);
|
|
|
|
case "left": return keyeventKey(0xE008, KeyEvent.KEYCODE_DPAD_LEFT, 0);
|
|
|
|
case "page_up": return keyeventKey(0xE002, KeyEvent.KEYCODE_PAGE_UP, 0);
|
|
|
|
case "page_down": return keyeventKey(0xE003, KeyEvent.KEYCODE_PAGE_DOWN, 0);
|
|
|
|
case "home": return keyeventKey(0xE00B, KeyEvent.KEYCODE_MOVE_HOME, 0);
|
|
|
|
case "end": return keyeventKey(0xE00C, KeyEvent.KEYCODE_MOVE_END, 0);
|
|
|
|
case "backspace": return keyeventKey(0xE011, KeyEvent.KEYCODE_DEL, 0);
|
|
|
|
case "delete": return keyeventKey(0xE010, KeyEvent.KEYCODE_FORWARD_DEL, 0);
|
2023-01-29 19:38:54 +01:00
|
|
|
case "insert": return keyeventKey("Ins", KeyEvent.KEYCODE_INSERT, FLAG_SMALLER_FONT);
|
|
|
|
case "f1": return keyeventKey("F1", KeyEvent.KEYCODE_F1, 0);
|
|
|
|
case "f2": return keyeventKey("F2", KeyEvent.KEYCODE_F2, 0);
|
|
|
|
case "f3": return keyeventKey("F3", KeyEvent.KEYCODE_F3, 0);
|
|
|
|
case "f4": return keyeventKey("F4", KeyEvent.KEYCODE_F4, 0);
|
|
|
|
case "f5": return keyeventKey("F5", KeyEvent.KEYCODE_F5, 0);
|
|
|
|
case "f6": return keyeventKey("F6", KeyEvent.KEYCODE_F6, 0);
|
|
|
|
case "f7": return keyeventKey("F7", KeyEvent.KEYCODE_F7, 0);
|
|
|
|
case "f8": return keyeventKey("F8", KeyEvent.KEYCODE_F8, 0);
|
|
|
|
case "f9": return keyeventKey("F9", KeyEvent.KEYCODE_F9, 0);
|
|
|
|
case "f10": return keyeventKey("F10", KeyEvent.KEYCODE_F10, 0);
|
|
|
|
case "f11": return keyeventKey("F11", KeyEvent.KEYCODE_F11, FLAG_SMALLER_FONT);
|
|
|
|
case "f12": return keyeventKey("F12", KeyEvent.KEYCODE_F12, FLAG_SMALLER_FONT);
|
2023-08-02 20:39:37 +02:00
|
|
|
case "tab": return keyeventKey(0xE00F, KeyEvent.KEYCODE_TAB, FLAG_SMALLER_FONT);
|
2023-01-29 19:38:54 +01:00
|
|
|
|
2023-08-17 12:47:44 +02:00
|
|
|
/* Spaces */
|
2023-01-29 19:38:54 +01:00
|
|
|
case "\\t": return charKey("\\t", '\t', 0); // Send the tab character
|
2024-05-02 19:37:18 +02:00
|
|
|
case "\\n": return charKey("\\n", '\n', 0); // Send the newline character
|
2024-04-03 23:55:38 +02:00
|
|
|
case "space": return charKey(0xE00D, ' ', FLAG_KEY_FONT | FLAG_SMALLER_FONT | FLAG_GREYED);
|
2023-01-29 19:38:54 +01:00
|
|
|
case "nbsp": return charKey("\u237d", '\u00a0', FLAG_SMALLER_FONT);
|
|
|
|
|
2023-01-20 03:58:40 +01:00
|
|
|
/* bidi */
|
|
|
|
case "lrm": return charKey("↱", '\u200e', 0); // Send left-to-right mark
|
|
|
|
case "rlm": return charKey("↰", '\u200f', 0); // Send right-to-left mark
|
|
|
|
case "b(": return charKey("(", ')', 0);
|
|
|
|
case "b)": return charKey(")", '(', 0);
|
|
|
|
case "b[": return charKey("[", ']', 0);
|
|
|
|
case "b]": return charKey("]", '[', 0);
|
|
|
|
case "b{": return charKey("{", '}', 0);
|
|
|
|
case "b}": return charKey("}", '{', 0);
|
|
|
|
case "blt": return charKey("<", '>', 0);
|
|
|
|
case "bgt": return charKey(">", '<', 0);
|
|
|
|
|
|
|
|
/* hebrew niqqud */
|
|
|
|
case "qamats": return charKey("\u05E7\u05B8", '\u05B8', 0); // kamatz
|
|
|
|
case "patah": return charKey("\u05E4\u05B7", '\u05B7', 0); // patach
|
|
|
|
case "sheva": return charKey("\u05E9\u05B0", '\u05B0', 0);
|
|
|
|
case "dagesh": return charKey("\u05D3\u05BC", '\u05BC', 0); // or mapiq
|
|
|
|
case "hiriq": return charKey("\u05D7\u05B4", '\u05B4', 0);
|
|
|
|
case "segol": return charKey("\u05E1\u05B6", '\u05B6', 0);
|
|
|
|
case "tsere": return charKey("\u05E6\u05B5", '\u05B5', 0);
|
|
|
|
case "holam": return charKey("\u05D5\u05B9", '\u05B9', 0);
|
|
|
|
case "qubuts": return charKey("\u05E7\u05BB", '\u05BB', 0); // kubuts
|
|
|
|
case "hataf_patah": return charKey("\u05D7\u05B2\u05E4\u05B7", '\u05B2', 0); // reduced patach
|
|
|
|
case "hataf_qamats": return charKey("\u05D7\u05B3\u05E7\u05B8", '\u05B3', 0); // reduced kamatz
|
|
|
|
case "hataf_segol": return charKey("\u05D7\u05B1\u05E1\u05B6", '\u05B1', 0); // reduced segol
|
|
|
|
case "shindot": return charKey("\u05E9\u05C1", '\u05C1', 0);
|
|
|
|
case "shindot_placeholder": return placeholderKey(Placeholder.SHINDOT);
|
|
|
|
case "sindot": return charKey("\u05E9\u05C2", '\u05C2', 0);
|
|
|
|
case "sindot_placeholder": return placeholderKey(Placeholder.SINDOT);
|
|
|
|
/* hebrew punctuation */
|
|
|
|
case "geresh": return charKey("\u05F3", '\u05F3', 0);
|
|
|
|
case "gershayim": return charKey("\u05F4", '\u05F4', 0);
|
|
|
|
case "maqaf": return charKey("\u05BE", '\u05BE', 0);
|
|
|
|
/* hebrew biblical */
|
|
|
|
case "rafe": return charKey("\u05E4\u05BF", '\u05BF', 0);
|
|
|
|
case "ole": return charKey("\u05E2\u05AB", '\u05AB', 0);
|
|
|
|
case "ole_placeholder": return placeholderKey(Placeholder.OLE);
|
|
|
|
case "meteg": return charKey("\u05DE\u05BD", '\u05BD', 0); // or siluq or sof-pasuq
|
|
|
|
case "meteg_placeholder": return placeholderKey(Placeholder.METEG);
|
2023-06-25 12:12:46 +02:00
|
|
|
/* intending/preventing ligature - supported by many scripts*/
|
|
|
|
case "zwj": return charKey("zwj", '\u200D', 0); // zero-width joiner (provides ligature)
|
|
|
|
case "zwnj": return charKey("zwnj", '\u200C', 0); // zero-width non joiner (prevents unintended ligature)
|
2023-01-20 03:58:40 +01:00
|
|
|
|
2023-08-17 12:47:44 +02:00
|
|
|
/* Editing keys */
|
2023-08-06 19:17:05 +02:00
|
|
|
case "copy": return editingKey(0xE030, Editing.COPY);
|
|
|
|
case "paste": return editingKey(0xE032, Editing.PASTE);
|
|
|
|
case "cut": return editingKey(0xE031, Editing.CUT);
|
|
|
|
case "selectAll": return editingKey(0xE033, Editing.SELECT_ALL);
|
|
|
|
case "shareText": return editingKey(0xE034, Editing.SHARE);
|
|
|
|
case "pasteAsPlainText": return editingKey(0xE035, Editing.PASTE_PLAIN);
|
|
|
|
case "undo": return editingKey(0xE036, Editing.UNDO);
|
|
|
|
case "redo": return editingKey(0xE037, Editing.REDO);
|
2024-05-02 19:31:48 +02:00
|
|
|
case "cursor_left": return cursorMoveKey(-1);
|
|
|
|
case "cursor_right": return cursorMoveKey(1);
|
2023-09-03 15:05:23 +02:00
|
|
|
// These keys are not used
|
2023-08-06 19:17:05 +02:00
|
|
|
case "replaceText": return editingKey("repl", Editing.REPLACE);
|
|
|
|
case "textAssist": return editingKey(0xE038, Editing.ASSIST);
|
|
|
|
case "autofill": return editingKey("auto", Editing.AUTOFILL);
|
2023-08-17 12:47:44 +02:00
|
|
|
|
2024-02-11 20:46:36 +01:00
|
|
|
/* The compose key */
|
2024-03-18 01:00:22 +01:00
|
|
|
case "compose": return makeComposePending(0xE016, 0, FLAG_SECONDARY | FLAG_SMALLER_FONT | FLAG_SPECIAL);
|
2024-02-11 20:46:36 +01:00
|
|
|
|
2023-08-17 12:47:44 +02:00
|
|
|
/* Placeholder keys */
|
|
|
|
case "removed": return placeholderKey(Placeholder.REMOVED);
|
|
|
|
case "f11_placeholder": return placeholderKey(Placeholder.F11);
|
|
|
|
case "f12_placeholder": return placeholderKey(Placeholder.F12);
|
|
|
|
|
2024-05-02 20:52:18 +02:00
|
|
|
// 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);
|
|
|
|
|
2023-08-17 12:47:44 +02:00
|
|
|
/* Fallback to a string key that types its name */
|
2023-07-17 00:05:27 +02:00
|
|
|
default: return makeStringKey(name);
|
2023-01-29 19:38:54 +01:00
|
|
|
}
|
2021-04-18 21:58:13 +02:00
|
|
|
}
|
2022-06-05 19:55:55 +02:00
|
|
|
|
|
|
|
// Substitute for [assert], which has no effect on Android.
|
|
|
|
private static void check(boolean b)
|
|
|
|
{
|
|
|
|
if (!b)
|
|
|
|
throw new RuntimeException("Assertion failure");
|
|
|
|
}
|
2015-07-30 20:14:55 +02:00
|
|
|
}
|