From 493945dc656f899e7a8a69304f7e57182fccf3e3 Mon Sep 17 00:00:00 2001 From: Shirayama Kazatsuyu Date: Thu, 11 Jan 2024 01:35:43 +0900 Subject: [PATCH 1/3] Fixed Windows Terminal UTF-16 surrogate pair issue --- src/event/sys/windows/parse.rs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/event/sys/windows/parse.rs b/src/event/sys/windows/parse.rs index 97677ecf..f5ee1f12 100644 --- a/src/event/sys/windows/parse.rs +++ b/src/event/sys/windows/parse.rs @@ -61,19 +61,16 @@ pub(crate) fn handle_key_event( } fn handle_surrogate(surrogate_buffer: &mut Option, new_surrogate: u16) -> Option { - match *surrogate_buffer { - Some(buffered_surrogate) => { - *surrogate_buffer = None; - std::char::decode_utf16([buffered_surrogate, new_surrogate]) - .next() - .unwrap() - .ok() - } - None => { - *surrogate_buffer = Some(new_surrogate); - None - } + if new_surrogate < 0xDC00 { + // Discard any buffered surrogate value if another high surrogate comes. + *surrogate_buffer = Some(new_surrogate); + return None; } + let buffered_surrogate = surrogate_buffer.take()?; + std::char::decode_utf16([buffered_surrogate, new_surrogate]) + .next() + .unwrap() + .ok() } impl From<&ControlKeyState> for KeyModifiers { From 3649710a436ed02dd647cb20f1fe773a9fa4caa1 Mon Sep 17 00:00:00 2001 From: Shirayama Kazatsuyu Date: Thu, 16 May 2024 21:06:31 +0900 Subject: [PATCH 2/3] Name the constants --- src/event/sys/windows/parse.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/event/sys/windows/parse.rs b/src/event/sys/windows/parse.rs index f5ee1f12..693304f8 100644 --- a/src/event/sys/windows/parse.rs +++ b/src/event/sys/windows/parse.rs @@ -61,7 +61,7 @@ pub(crate) fn handle_key_event( } fn handle_surrogate(surrogate_buffer: &mut Option, new_surrogate: u16) -> Option { - if new_surrogate < 0xDC00 { + if new_surrogate < LOW_SURROGATE_FIRST { // Discard any buffered surrogate value if another high surrogate comes. *surrogate_buffer = Some(new_surrogate); return None; @@ -265,7 +265,7 @@ fn parse_key_event_record(key_event: &KeyEventRecord) -> Option // are handled by their virtual key codes above. get_char_for_key(key_event).map(KeyCode::Char) } - surrogate @ 0xD800..=0xDFFF => { + surrogate @ HIGH_SURROGATE_FIRST..=LOW_SURROGATE_LAST => { return Some(WindowsKeyEvent::Surrogate(surrogate)); } unicode_scalar_value => { @@ -373,3 +373,8 @@ fn parse_mouse_event_record( modifiers, })) } + +const HIGH_SURROGATE_FIRST: u16 = 0xD800; +const LOW_SURROGATE_FIRST: u16 = 0xDC00; +const LOW_SURROGATE_LAST: u16 = 0xDFFF; + From 9a14e07635ba1ea87743c798887fdca4334badf1 Mon Sep 17 00:00:00 2001 From: Shirayama Kazatsuyu Date: Thu, 16 May 2024 21:06:54 +0900 Subject: [PATCH 3/3] Add test --- src/event/sys/windows/parse.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/event/sys/windows/parse.rs b/src/event/sys/windows/parse.rs index 693304f8..ffaaa792 100644 --- a/src/event/sys/windows/parse.rs +++ b/src/event/sys/windows/parse.rs @@ -378,3 +378,37 @@ const HIGH_SURROGATE_FIRST: u16 = 0xD800; const LOW_SURROGATE_FIRST: u16 = 0xDC00; const LOW_SURROGATE_LAST: u16 = 0xDFFF; +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_handle_surrogate() { + fn testcase(mut buf: Option, new: u16) -> (Option, Option) { + let ch = handle_surrogate(&mut buf, new); + (buf, ch) + } + assert_eq!( + [ + // Continuous high surrogates + testcase(Some(0xD800), 0xDBFF), + // A normal surrogate pair + testcase(Some(0xD800), 0xDC00), + // An empty buffer and a high surrogate + testcase(None, 0xDBFF), + // An empty buffer and a low surrogate + testcase(None, 0xDC00), + ], + [ + // The newer one will be stored + (Some(0xDBFF), None), + // A valid char will return + (None, Some('\u{10000}')), + // The high surrogate will be stored + (Some(0xDBFF), None), + // The low surrogate will be ignored + (None, None), + ] + ); + } +}