diff --git a/NEWS b/NEWS index 02c4a3dd7..c95f98731 100644 --- a/NEWS +++ b/NEWS @@ -1,9 +1,11 @@ -What's New in libchewing 0.8.4 (May 27, 2024) +What's New in libchewing 0.8.4 (Jun 1, 2024) --------------------------------------------------------- * Bug fixed - Config options were incorrectly reset after certain operations. (introduced - in v0.8.0) + in v0.8.0) + - Incorrect mapping for KB_DVORAK and KB_DVORAK_HSU layouts. (introduced in + v0.8.0) - Installation failure if build with testing off. (introduced in v0.8.3) diff --git a/capi/src/io.rs b/capi/src/io.rs index 81c167eef..fea47919c 100644 --- a/capi/src/io.rs +++ b/capi/src/io.rs @@ -297,8 +297,8 @@ pub unsafe extern "C" fn chewing_set_KBType(ctx: *mut ChewingContext, kbtype: c_ KB::GinYieh => (AnyKeyboardLayout::qwerty(), Box::new(GinYieh::new())), KB::Et => (AnyKeyboardLayout::qwerty(), Box::new(Et::new())), KB::Et26 => (AnyKeyboardLayout::qwerty(), Box::new(Et26::new())), - KB::Dvorak => (AnyKeyboardLayout::qwerty(), Box::new(Standard::new())), - KB::DvorakHsu => (AnyKeyboardLayout::qwerty(), Box::new(Hsu::new())), + KB::Dvorak => (AnyKeyboardLayout::dvorak(), Box::new(Standard::new())), + KB::DvorakHsu => (AnyKeyboardLayout::dvorak_on_qwerty(), Box::new(Hsu::new())), KB::DachenCp26 => (AnyKeyboardLayout::qwerty(), Box::new(DaiChien26::new())), KB::HanyuPinyin => (AnyKeyboardLayout::qwerty(), Box::new(Pinyin::hanyu())), KB::ThlPinyin => (AnyKeyboardLayout::qwerty(), Box::new(Pinyin::thl())), diff --git a/src/editor/keyboard/dvorak.rs b/src/editor/keyboard/dvorak.rs index 047f83c7e..f87af3e3c 100644 --- a/src/editor/keyboard/dvorak.rs +++ b/src/editor/keyboard/dvorak.rs @@ -9,7 +9,7 @@ use super::{ pub struct Dvorak; #[rustfmt::skip] -static KEYCODE_INDEX: [KeyCode; MATRIX_SIZE] = [ +pub(crate) static KEYCODE_INDEX: [KeyCode; MATRIX_SIZE] = [ Unknown, N1, N2, N3, N4, N5, N6, N7, N8, N9, N0, LBracket, RBracket, BSlash, Grave, Quote, Comma, Dot, P, Y, F, G, C, R, L, Slash, Equal, @@ -20,7 +20,7 @@ static KEYCODE_INDEX: [KeyCode; MATRIX_SIZE] = [ ]; #[rustfmt::skip] -static UNICODE_MAP: [char; MATRIX_SIZE] = [ +pub(crate) static UNICODE_MAP: [char; MATRIX_SIZE] = [ '�', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '[', ']', '\\', '`', '\'', ',', '.', 'p', 'y', 'f', 'g', 'c', 'r', 'l', '/', '=', @@ -31,7 +31,7 @@ static UNICODE_MAP: [char; MATRIX_SIZE] = [ ]; #[rustfmt::skip] -static SHIFT_MAP: [char; MATRIX_SIZE] = [ +pub(crate) static SHIFT_MAP: [char; MATRIX_SIZE] = [ '�', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '{', '}', '|', '~', '"', '<', '>', 'P', 'Y', 'F', 'G', 'C', 'R', 'L', '?', '+', diff --git a/src/editor/keyboard/dvorak_on_qwerty.rs b/src/editor/keyboard/dvorak_on_qwerty.rs new file mode 100644 index 000000000..2c816559a --- /dev/null +++ b/src/editor/keyboard/dvorak_on_qwerty.rs @@ -0,0 +1,25 @@ +use super::{dvorak, qwerty, KeyCode, KeyEvent, KeyboardLayout, Modifiers, INDEX_MAP}; + +/// A Dvorak keyboard. +#[derive(Debug)] +pub struct DvorakOnQwerty; + +impl KeyboardLayout for DvorakOnQwerty { + fn map_with_mod(&self, keycode: KeyCode, modifiers: Modifiers) -> KeyEvent { + let index = qwerty::KEYCODE_INDEX + .iter() + .position(|key| *key == keycode) + .expect("invalid keycode"); + let unicode = if modifiers.capslock || modifiers.shift { + dvorak::SHIFT_MAP[index] + } else { + dvorak::UNICODE_MAP[index] + }; + KeyEvent { + index: INDEX_MAP[index], + code: dvorak::KEYCODE_INDEX[index], + unicode, + modifiers, + } + } +} diff --git a/src/editor/keyboard/mod.rs b/src/editor/keyboard/mod.rs index 0e81a980c..421e836ea 100644 --- a/src/editor/keyboard/mod.rs +++ b/src/editor/keyboard/mod.rs @@ -8,6 +8,7 @@ mod colemak_dh_ansi; mod colemak_dh_orth; mod dvorak; +mod dvorak_on_qwerty; mod qgmlwy; mod qwerty; @@ -16,6 +17,7 @@ use core::fmt; pub use colemak_dh_ansi::ColemakDhAnsi; pub use colemak_dh_orth::ColemakDhOrth; pub use dvorak::Dvorak; +pub use dvorak_on_qwerty::DvorakOnQwerty; pub use qgmlwy::Qgmlwy; pub use qwerty::Qwerty; @@ -129,9 +131,11 @@ pub trait KeyboardLayout { } #[derive(Debug)] +#[non_exhaustive] pub enum AnyKeyboardLayout { Qwerty(Qwerty), Dvorak(Dvorak), + DvorakOnQwerty(DvorakOnQwerty), Qgmlwy(Qgmlwy), ColemakDhAnsi(ColemakDhAnsi), ColemakDhOrth(ColemakDhOrth), @@ -144,6 +148,9 @@ impl AnyKeyboardLayout { pub fn dvorak() -> AnyKeyboardLayout { AnyKeyboardLayout::Dvorak(Dvorak) } + pub fn dvorak_on_qwerty() -> AnyKeyboardLayout { + AnyKeyboardLayout::DvorakOnQwerty(DvorakOnQwerty) + } pub fn qgmlwy() -> AnyKeyboardLayout { AnyKeyboardLayout::Qgmlwy(Qgmlwy) } @@ -160,6 +167,7 @@ impl KeyboardLayout for AnyKeyboardLayout { match self { AnyKeyboardLayout::Qwerty(kb) => kb.map_with_mod(keycode, modifiers), AnyKeyboardLayout::Dvorak(kb) => kb.map_with_mod(keycode, modifiers), + AnyKeyboardLayout::DvorakOnQwerty(kb) => kb.map_with_mod(keycode, modifiers), 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), diff --git a/src/editor/keyboard/qwerty.rs b/src/editor/keyboard/qwerty.rs index ee9622c7a..7049bf571 100644 --- a/src/editor/keyboard/qwerty.rs +++ b/src/editor/keyboard/qwerty.rs @@ -9,7 +9,7 @@ use super::{ pub struct Qwerty; #[rustfmt::skip] -static KEYCODE_INDEX: [KeyCode; MATRIX_SIZE] = [ +pub(crate) static KEYCODE_INDEX: [KeyCode; MATRIX_SIZE] = [ Unknown, N1, N2, N3, N4, N5, N6, N7, N8, N9, N0, Minus, Equal, BSlash, Grave, Q, W, E, R, T, Y, U, I, O, P, LBracket, RBracket, @@ -20,7 +20,7 @@ static KEYCODE_INDEX: [KeyCode; MATRIX_SIZE] = [ ]; #[rustfmt::skip] -static UNICODE_MAP: [char; MATRIX_SIZE] = [ +pub(crate) static UNICODE_MAP: [char; MATRIX_SIZE] = [ '�', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\\', '`', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', @@ -31,7 +31,7 @@ static UNICODE_MAP: [char; MATRIX_SIZE] = [ ]; #[rustfmt::skip] -static SHIFT_MAP: [char; MATRIX_SIZE] = [ +pub(crate) static SHIFT_MAP: [char; MATRIX_SIZE] = [ '�', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '|', '~', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', diff --git a/tests/genkeystroke.c b/tests/genkeystroke.c index 0ac279bcb..2999bb23a 100644 --- a/tests/genkeystroke.c +++ b/tests/genkeystroke.c @@ -317,7 +317,7 @@ int main(int argc, char *argv[]) ctx = chewing_new2(NULL, NULL, logger, log); /* Set keyboard type */ - chewing_set_KBType(ctx, chewing_KBStr2Num("KB_DEFAULT")); + chewing_set_KBType(ctx, chewing_KBStr2Num("KB_DVORAK_HSU")); /* Fill configuration values */ chewing_set_candPerPage(ctx, 9); diff --git a/tests/test-bopomofo.c b/tests/test-bopomofo.c index 482923212..e95db7f87 100644 --- a/tests/test-bopomofo.c +++ b/tests/test-bopomofo.c @@ -2076,6 +2076,42 @@ void test_KB_MPS2() chewing_delete(ctx); } +void test_KB_DVORAK() +{ + ChewingContext *ctx; + + ctx = chewing_new(); + start_testcase(ctx, fd); + + chewing_set_KBType(ctx, KB_DVORAK); + type_keystroke_by_string(ctx, "kgl eh4gl 5l 2t7jl31s4"); + chewing_set_ChiEngMode(ctx, SYMBOL_MODE); + type_keystroke_by_string(ctx, "testTEST"); + ok_preedit_buffer(ctx, "\xE6\x96\xB0\xE9\x85\xB7\xE9\x9F\xB3\xE7\x9C\x9F\xE7\x9A\x84\xE5\xBE\x88\xE6\xA3\x92testTEST" + /* 新酷音真的很棒 */ ); + chewing_clean_preedit_buf(ctx); + + chewing_delete(ctx); +} + +void test_KB_DVORAK_HSU() +{ + ChewingContext *ctx; + + ctx = chewing_new(); + start_testcase(ctx, fd); + + chewing_set_KBType(ctx, KB_DVORAK_HSU); + type_keystroke_by_string(ctx, "idl vbcdl cl hu;jlynvc"); + chewing_set_ChiEngMode(ctx, SYMBOL_MODE); + type_keystroke_by_string(ctx, "kd;kKD:K"); + ok_preedit_buffer(ctx, "\xE6\x96\xB0\xE9\x85\xB7\xE9\x9F\xB3\xE7\x9C\x9F\xE7\x9A\x84\xE5\xBE\x88\xE6\xA3\x92testTEST" + /* 新酷音真的很棒 */ ); + chewing_clean_preedit_buf(ctx); + + chewing_delete(ctx); +} + void test_KB_COLEMAK_DH_ANSI() { ChewingContext *ctx; @@ -2120,8 +2156,10 @@ void test_KB() test_KB_ET26(); test_KB_ET26_choice_append(); test_KB_DACHEN_CP26(); - test_KB_COLEMAK_DH_ANSI(); - test_KB_COLEMAK_DH_ORTH(); + test_KB_DVORAK(); + test_KB_DVORAK_HSU(); + test_KB_COLEMAK_DH_ANSI(); + test_KB_COLEMAK_DH_ORTH(); test_KB_HANYU(); test_KB_THL();