diff --git a/capi/src/io.rs b/capi/src/io.rs index 699a6bdc..90296fc3 100644 --- a/capi/src/io.rs +++ b/capi/src/io.rs @@ -560,6 +560,7 @@ pub unsafe extern "C" fn chewing_config_set_str( AnyKeyboardLayout::colemak_dh_orth(), Box::new(Standard::new()), ), + KB::Workman => (AnyKeyboardLayout::workman(), Box::new(Standard::new())), }; ctx.keyboard = keyboard; ctx.editor.set_syllable_editor(syl); @@ -614,6 +615,7 @@ pub unsafe extern "C" fn chewing_set_KBType(ctx: *mut ChewingContext, kbtype: c_ AnyKeyboardLayout::colemak_dh_orth(), Box::new(Standard::new()), ), + KB::Workman => (AnyKeyboardLayout::workman(), Box::new(Standard::new())), }; ctx.kb_compat = kb_compat; ctx.keyboard = keyboard; diff --git a/capi/src/lib.rs b/capi/src/lib.rs index c42b3acd..b6f06432 100644 --- a/capi/src/lib.rs +++ b/capi/src/lib.rs @@ -318,6 +318,9 @@ pub mod layout { /// * KB_THL_PINYIN /// * KB_MPS2_PINYIN /// * KB_CARPALX + /// * KB_COLEMAK_DH_ANSI + /// * KB_COLEMAK_DH_ORTH + /// * KB_WORKMAN /// /// See also [chewing_kbtype_Enumerate] for getting the list of supported /// layouts programmatically. diff --git a/capi/src/public.rs b/capi/src/public.rs index 41a2c5c6..ddce7afa 100644 --- a/capi/src/public.rs +++ b/capi/src/public.rs @@ -109,6 +109,7 @@ pub enum KB { Carpalx, ColemakDhAnsi, ColemakDhOrth, + Workman, } /// Opaque context handle used for chewing APIs. diff --git a/include/chewing.h b/include/chewing.h index 646b0a3b..f7534dea 100644 --- a/include/chewing.h +++ b/include/chewing.h @@ -153,6 +153,7 @@ typedef enum KB { KB_CARPALX, KB_COLEMAK_DH_ANSI, KB_COLEMAK_DH_ORTH, + KB_WORKMAN, KB_TYPE_NUM, } KB; diff --git a/src/editor/keyboard/mod.rs b/src/editor/keyboard/mod.rs index 73142a11..b6d3cddd 100644 --- a/src/editor/keyboard/mod.rs +++ b/src/editor/keyboard/mod.rs @@ -11,6 +11,7 @@ mod dvorak; mod dvorak_on_qwerty; mod qgmlwy; mod qwerty; +mod workman; use core::fmt; @@ -20,6 +21,7 @@ pub use dvorak::Dvorak; pub use dvorak_on_qwerty::DvorakOnQwerty; pub use qgmlwy::Qgmlwy; pub use qwerty::Qwerty; +pub use workman::Workman; const MATRIX_SIZE: usize = 63; @@ -139,6 +141,7 @@ pub enum AnyKeyboardLayout { Qgmlwy(Qgmlwy), ColemakDhAnsi(ColemakDhAnsi), ColemakDhOrth(ColemakDhOrth), + Workman(Workman), } impl AnyKeyboardLayout { @@ -160,6 +163,9 @@ impl AnyKeyboardLayout { pub fn colemak_dh_orth() -> AnyKeyboardLayout { AnyKeyboardLayout::ColemakDhOrth(ColemakDhOrth) } + pub fn workman() -> AnyKeyboardLayout { + AnyKeyboardLayout::Workman(Workman) + } } impl KeyboardLayout for AnyKeyboardLayout { @@ -171,6 +177,7 @@ impl KeyboardLayout for AnyKeyboardLayout { AnyKeyboardLayout::Qgmlwy(kb) => kb.map_with_mod(keycode, modifiers), AnyKeyboardLayout::ColemakDhAnsi(kb) => kb.map_with_mod(keycode, modifiers), AnyKeyboardLayout::ColemakDhOrth(kb) => kb.map_with_mod(keycode, modifiers), + AnyKeyboardLayout::Workman(kb) => kb.map_with_mod(keycode, modifiers), } } } diff --git a/src/editor/keyboard/workman.rs b/src/editor/keyboard/workman.rs new file mode 100644 index 00000000..150a1294 --- /dev/null +++ b/src/editor/keyboard/workman.rs @@ -0,0 +1,48 @@ +use super::{ + generic_map_keycode, + KeyCode::{self, *}, + KeyEvent, KeyboardLayout, Modifiers, MATRIX_SIZE, +}; + +/// A Workman keyboard. +#[derive(Debug)] +pub struct Workman; + +#[rustfmt::skip] +pub(crate) static KEYCODE_INDEX: [KeyCode; MATRIX_SIZE] = [ + Unknown, + N1, N2, N3, N4, N5, N6, N7, N8, N9, N0, Minus, Equal, BSlash, Grave, + Q, D, R, W, B, J, F, U, P, SColon, LBracket, RBracket, + A, S, H, T, G, Y, N, E, O, I, Quote, + Z, X, M, C, V, K, L, Comma, Dot, Slash, Space, + Esc, Enter, Del, Backspace, Tab, Left, Right, Up, Down, Home, End, + PageUp, PageDown, NumLock, +]; + +#[rustfmt::skip] +pub(crate) static UNICODE_MAP: [char; MATRIX_SIZE] = [ + '�', + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\\', '`', + 'q', 'd', 'r', 'w', 'b', 'j', 'f', 'u', 'p', ';', '[', ']', + 'a', 's', 'h', 't', 'g', 'y', 'n', 'e', 'o', 'i', '\'', + 'z', 'x', 'm', 'c', 'v', 'k', 'l', ',', '.', '/', ' ', + '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', + '�', '�', '�', '�', +]; + +#[rustfmt::skip] +pub(crate) static SHIFT_MAP: [char; MATRIX_SIZE] = [ + '�', + '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '|', '~', + 'Q', 'D', 'R', 'W', 'B', 'J', 'F', 'U', 'P', ':', '{', '}', + 'A', 'S', 'H', 'T', 'G', 'Y', 'N', 'E', 'O', 'I', '"', + 'Z', 'X', 'M', 'C', 'V', 'K', 'L', '<', '>', '?', ' ', + '�', '�', '�', '�', '�', '�', '�', '�', '�', '�', + '�', '�', '�', '�', +]; + +impl KeyboardLayout for Workman { + fn map_with_mod(&self, keycode: KeyCode, modifiers: Modifiers) -> KeyEvent { + generic_map_keycode(&KEYCODE_INDEX, &UNICODE_MAP, &SHIFT_MAP, keycode, modifiers) + } +} diff --git a/src/editor/zhuyin_layout/mod.rs b/src/editor/zhuyin_layout/mod.rs index 5bf87730..2a41b00b 100644 --- a/src/editor/zhuyin_layout/mod.rs +++ b/src/editor/zhuyin_layout/mod.rs @@ -78,6 +78,8 @@ pub enum KeyboardLayoutCompat { ColemakDhAnsi, /// TODO: docs ColemakDhOrth, + /// Workman standard layout + Workman, } #[derive(Debug)] @@ -109,6 +111,7 @@ impl FromStr for KeyboardLayoutCompat { "KB_CARPALX" => Self::Carpalx, "KB_COLEMAK_DH_ANSI" => Self::ColemakDhAnsi, "KB_COLEMAK_DH_ORTH" => Self::ColemakDhOrth, + "KB_WORKMAN" => Self::Workman, _ => return Err(ParseKeyboardLayoutError), }; Ok(layout) @@ -133,6 +136,7 @@ impl Display for KeyboardLayoutCompat { KeyboardLayoutCompat::Carpalx => f.write_str("KB_CARPALX"), KeyboardLayoutCompat::ColemakDhAnsi => f.write_str("KB_COLEMAK_DH_ANSI"), KeyboardLayoutCompat::ColemakDhOrth => f.write_str("KB_COLEMAK_DH_ORTH"), + KeyboardLayoutCompat::Workman => f.write_str("KB_WORKMAN"), } } } @@ -157,6 +161,7 @@ impl TryFrom for KeyboardLayoutCompat { 12 => Self::Carpalx, 13 => Self::ColemakDhAnsi, 14 => Self::ColemakDhOrth, + 15 => Self::Workman, _ => return Err(()), }) } diff --git a/tests/test-keyboard.c b/tests/test-keyboard.c index 7293dbe6..d84f520f 100644 --- a/tests/test-keyboard.c +++ b/tests/test-keyboard.c @@ -35,6 +35,7 @@ static const char *const KEYBOARD_STRING[] = { "KB_CARPALX", "KB_COLEMAK_DH_ANSI", "KB_COLEMAK_DH_ORTH", + "KB_WORKMAN" }; static const int KEYBOARD_DEFAULT_TYPE = 0;