From abf31616c33923d7097ab985e5cea9839ca7922c Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Sat, 2 Jul 2022 20:58:51 +0200 Subject: [PATCH] feat: implement alt-code emulation. #988 (#1277) --- espanso-config/src/config/mod.rs | 8 + espanso-config/src/config/parse/mod.rs | 1 + espanso-config/src/config/parse/yaml.rs | 7 + espanso-config/src/config/resolve.rs | 5 + espanso-config/src/legacy/mod.rs | 4 + espanso-detect/src/evdev/mod.rs | 12 + espanso-detect/src/event.rs | 12 + espanso-detect/src/mac/mod.rs | 12 + espanso-detect/src/win32/mod.rs | 12 + espanso-detect/src/x11/mod.rs | 12 + espanso-engine/src/event/input.rs | 12 + espanso-engine/src/process/default.rs | 13 +- .../middleware/alt_code_synthesizer.rs | 675 ++++++++++++++++++ espanso-engine/src/process/middleware/mod.rs | 1 + espanso-engine/src/process/mod.rs | 3 + espanso/src/cli/worker/config.rs | 6 + .../engine/dispatch/executor/key_injector.rs | 10 + .../src/cli/worker/engine/funnel/detect.rs | 10 + espanso/src/cli/worker/engine/mod.rs | 1 + .../engine/process/middleware/matcher/mod.rs | 1 + espanso/src/patch/patches/mod.rs | 1 + 21 files changed, 814 insertions(+), 4 deletions(-) create mode 100644 espanso-engine/src/process/middleware/alt_code_synthesizer.rs diff --git a/espanso-config/src/config/mod.rs b/espanso-config/src/config/mod.rs index bab51d9..ed1bb51 100644 --- a/espanso-config/src/config/mod.rs +++ b/espanso-config/src/config/mod.rs @@ -162,6 +162,14 @@ pub trait Config: Send + Sync { // not be targeted to the right application. fn post_search_delay(&self) -> usize; + // If enabled, Espanso emulates the Alt Code feature available on Windows + // (keeping ALT pressed and then typing a char code with the numpad). + // This feature is necessary on Windows because the mechanism used by Espanso + // to intercept keystrokes disables the Windows' native Alt code functionality + // as a side effect. + // Because many users relied on this feature, we try to bring it back by emulating it. + fn emulate_alt_codes(&self) -> bool; + // If true, use the `xclip` command to implement the clipboard instead of // the built-in native module on X11. fn x11_use_xclip_backend(&self) -> bool; diff --git a/espanso-config/src/config/parse/mod.rs b/espanso-config/src/config/parse/mod.rs index 6f1d0c4..c641684 100644 --- a/espanso-config/src/config/parse/mod.rs +++ b/espanso-config/src/config/parse/mod.rs @@ -46,6 +46,7 @@ pub(crate) struct ParsedConfig { pub secure_input_notification: Option, pub post_form_delay: Option, pub post_search_delay: Option, + pub emulate_alt_codes: Option, pub win32_exclude_orphan_events: Option, pub win32_keyboard_layout_cache_interval: Option, pub x11_use_xclip_backend: Option, diff --git a/espanso-config/src/config/parse/yaml.rs b/espanso-config/src/config/parse/yaml.rs index 66605ad..10e06f4 100644 --- a/espanso-config/src/config/parse/yaml.rs +++ b/espanso-config/src/config/parse/yaml.rs @@ -112,6 +112,9 @@ pub(crate) struct YAMLConfig { #[serde(default)] pub secure_input_notification: Option, + #[serde(default)] + pub emulate_alt_codes: Option, + #[serde(default)] pub win32_exclude_orphan_events: Option, @@ -213,6 +216,8 @@ impl TryFrom for ParsedConfig { post_form_delay: yaml_config.post_form_delay, post_search_delay: yaml_config.post_search_delay, + emulate_alt_codes: yaml_config.emulate_alt_codes, + win32_exclude_orphan_events: yaml_config.win32_exclude_orphan_events, win32_keyboard_layout_cache_interval: yaml_config.win32_keyboard_layout_cache_interval, x11_use_xclip_backend: yaml_config.x11_use_xclip_backend, @@ -274,6 +279,7 @@ mod tests { secure_input_notification: false post_form_delay: 300 post_search_delay: 400 + emulate_alt_codes: true win32_exclude_orphan_events: false win32_keyboard_layout_cache_interval: 300 x11_use_xclip_backend: true @@ -329,6 +335,7 @@ mod tests { show_icon: Some(false), show_notifications: Some(false), secure_input_notification: Some(false), + emulate_alt_codes: Some(true), post_form_delay: Some(300), post_search_delay: Some(400), win32_exclude_orphan_events: Some(false), diff --git a/espanso-config/src/config/resolve.rs b/espanso-config/src/config/resolve.rs index 352500c..76a9c28 100644 --- a/espanso-config/src/config/resolve.rs +++ b/espanso-config/src/config/resolve.rs @@ -299,6 +299,10 @@ impl Config for ResolvedConfig { self.parsed.secure_input_notification.unwrap_or(true) } + fn emulate_alt_codes(&self) -> bool { + self.parsed.emulate_alt_codes.unwrap_or(false) + } + fn post_form_delay(&self) -> usize { self .parsed @@ -416,6 +420,7 @@ impl ResolvedConfig { show_icon, show_notifications, secure_input_notification, + emulate_alt_codes, post_form_delay, post_search_delay, win32_exclude_orphan_events, diff --git a/espanso-config/src/legacy/mod.rs b/espanso-config/src/legacy/mod.rs index 3cdd8d7..33589de 100644 --- a/espanso-config/src/legacy/mod.rs +++ b/espanso-config/src/legacy/mod.rs @@ -395,6 +395,10 @@ impl Config for LegacyInteropConfig { crate::config::default::DEFAULT_POST_SEARCH_DELAY } + fn emulate_alt_codes(&self) -> bool { + false + } + fn win32_exclude_orphan_events(&self) -> bool { true } diff --git a/espanso-detect/src/evdev/mod.rs b/espanso-detect/src/evdev/mod.rs index 4f5f5c3..9c90ca3 100644 --- a/espanso-detect/src/evdev/mod.rs +++ b/espanso-detect/src/evdev/mod.rs @@ -379,6 +379,18 @@ fn key_sym_to_key(key_sym: i32) -> (Key, Option) { 0xFFD0 => (F19, None), 0xFFD1 => (F20, None), + // Numpad + 0xFFB0 => (Numpad0, None), + 0xFFB1 => (Numpad1, None), + 0xFFB2 => (Numpad2, None), + 0xFFB3 => (Numpad3, None), + 0xFFB4 => (Numpad4, None), + 0xFFB5 => (Numpad5, None), + 0xFFB6 => (Numpad6, None), + 0xFFB7 => (Numpad7, None), + 0xFFB8 => (Numpad8, None), + 0xFFB9 => (Numpad9, None), + // Other keys, includes the raw code provided by the operating system _ => (Other(key_sym), None), } diff --git a/espanso-detect/src/event.rs b/espanso-detect/src/event.rs index bfd8914..30090c5 100644 --- a/espanso-detect/src/event.rs +++ b/espanso-detect/src/event.rs @@ -125,6 +125,18 @@ pub enum Key { F19, F20, + // Numpad keys + Numpad0, + Numpad1, + Numpad2, + Numpad3, + Numpad4, + Numpad5, + Numpad6, + Numpad7, + Numpad8, + Numpad9, + // Other keys, includes the raw code provided by the operating system Other(i32), } diff --git a/espanso-detect/src/mac/mod.rs b/espanso-detect/src/mac/mod.rs index 5f49ea0..88606a1 100644 --- a/espanso-detect/src/mac/mod.rs +++ b/espanso-detect/src/mac/mod.rs @@ -448,6 +448,18 @@ fn key_code_to_key(key_code: i32) -> (Key, Option) { 0x50 => (F19, None), 0x5A => (F20, None), + // Numpad + 0x52 => (Numpad0, None), + 0x53 => (Numpad1, None), + 0x54 => (Numpad2, None), + 0x55 => (Numpad3, None), + 0x56 => (Numpad4, None), + 0x57 => (Numpad5, None), + 0x58 => (Numpad6, None), + 0x59 => (Numpad7, None), + 0x5B => (Numpad8, None), + 0x5C => (Numpad9, None), + // Other keys, includes the raw code provided by the operating system _ => (Other(key_code), None), } diff --git a/espanso-detect/src/win32/mod.rs b/espanso-detect/src/win32/mod.rs index dbde573..c0f8738 100644 --- a/espanso-detect/src/win32/mod.rs +++ b/espanso-detect/src/win32/mod.rs @@ -395,6 +395,18 @@ fn key_code_to_key(key_code: i32) -> (Key, Option) { 0x82 => (F19, None), 0x83 => (F20, None), + // Numpad + 0x60 => (Numpad0, None), + 0x61 => (Numpad1, None), + 0x62 => (Numpad2, None), + 0x63 => (Numpad3, None), + 0x64 => (Numpad4, None), + 0x65 => (Numpad5, None), + 0x66 => (Numpad6, None), + 0x67 => (Numpad7, None), + 0x68 => (Numpad8, None), + 0x69 => (Numpad9, None), + // Other keys, includes the raw code provided by the operating system _ => (Other(key_code), None), } diff --git a/espanso-detect/src/x11/mod.rs b/espanso-detect/src/x11/mod.rs index 8665ee4..9680d5a 100644 --- a/espanso-detect/src/x11/mod.rs +++ b/espanso-detect/src/x11/mod.rs @@ -396,6 +396,18 @@ fn key_sym_to_key(key_sym: i32) -> (Key, Option) { 0xFFD0 => (F19, None), 0xFFD1 => (F20, None), + // Numpad + 0xFFB0 => (Numpad0, None), + 0xFFB1 => (Numpad1, None), + 0xFFB2 => (Numpad2, None), + 0xFFB3 => (Numpad3, None), + 0xFFB4 => (Numpad4, None), + 0xFFB5 => (Numpad5, None), + 0xFFB6 => (Numpad6, None), + 0xFFB7 => (Numpad7, None), + 0xFFB8 => (Numpad8, None), + 0xFFB9 => (Numpad9, None), + // Other keys, includes the raw code provided by the operating system _ => (Other(key_sym), None), } diff --git a/espanso-engine/src/event/input.rs b/espanso-engine/src/event/input.rs index ebe830e..fc22cf5 100644 --- a/espanso-engine/src/event/input.rs +++ b/espanso-engine/src/event/input.rs @@ -108,6 +108,18 @@ pub enum Key { F19, F20, + // Numpad keys + Numpad0, + Numpad1, + Numpad2, + Numpad3, + Numpad4, + Numpad5, + Numpad6, + Numpad7, + Numpad8, + Numpad9, + // Other keys, includes the raw code provided by the operating system Other(i32), } diff --git a/espanso-engine/src/process/default.rs b/espanso-engine/src/process/default.rs index 4bb8efd..0c94340 100644 --- a/espanso-engine/src/process/default.rs +++ b/espanso-engine/src/process/default.rs @@ -22,6 +22,7 @@ use log::trace; use super::{ middleware::{ action::{ActionMiddleware, EventSequenceProvider}, + alt_code_synthesizer::AltCodeSynthesizerMiddleware, cause::CauseCompensateMiddleware, cursor_hint::CursorHintMiddleware, delay_modifiers::{DelayForModifierReleaseMiddleware, ModifierStatusProvider}, @@ -32,10 +33,10 @@ use super::{ multiplex::MultiplexMiddleware, render::RenderMiddleware, }, - DisableOptions, EnabledStatusProvider, MatchFilter, MatchInfoProvider, MatchProvider, - MatchResolver, MatchSelector, Matcher, MatcherMiddlewareConfigProvider, Middleware, - ModifierStateProvider, Multiplexer, NotificationManager, PathProvider, Processor, Renderer, - UndoEnabledProvider, + AltCodeSynthEnabledProvider, DisableOptions, EnabledStatusProvider, MatchFilter, + MatchInfoProvider, MatchProvider, MatchResolver, MatchSelector, Matcher, + MatcherMiddlewareConfigProvider, Middleware, ModifierStateProvider, Multiplexer, + NotificationManager, PathProvider, Processor, Renderer, UndoEnabledProvider, }; use crate::{ event::{Event, EventType}, @@ -74,6 +75,7 @@ impl<'a> DefaultProcessor<'a> { modifier_state_provider: &'a dyn ModifierStateProvider, match_resolver: &'a dyn MatchResolver, notification_manager: &'a dyn NotificationManager, + alt_code_synth_enabled_provider: &'a dyn AltCodeSynthEnabledProvider, ) -> DefaultProcessor<'a> { Self { event_queue: VecDeque::new(), @@ -81,6 +83,9 @@ impl<'a> DefaultProcessor<'a> { Box::new(EventsDiscardMiddleware::new()), Box::new(DisableMiddleware::new(disable_options)), Box::new(IconStatusMiddleware::new()), + Box::new(AltCodeSynthesizerMiddleware::new( + alt_code_synth_enabled_provider, + )), Box::new(MatcherMiddleware::new( matchers, matcher_options_provider, diff --git a/espanso-engine/src/process/middleware/alt_code_synthesizer.rs b/espanso-engine/src/process/middleware/alt_code_synthesizer.rs new file mode 100644 index 0000000..9cbd78f --- /dev/null +++ b/espanso-engine/src/process/middleware/alt_code_synthesizer.rs @@ -0,0 +1,675 @@ +/* + * This file is part of espanso. + * + * Copyright (C) 2019-2022 Federico Terzi + * + * espanso is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * espanso is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with espanso. If not, see . + */ + +use std::cell::RefCell; + +use log::debug; + +use super::super::Middleware; +use crate::event::{ + effect::TextInjectRequest, + input::{Key, Status}, + Event, EventType, +}; + +pub trait AltCodeSynthEnabledProvider { + fn is_alt_code_synthesizer_enabled(&self) -> bool; +} + +pub struct AltCodeSynthesizerMiddleware<'a> { + code_buffer: RefCell>, + enabled_state_provider: &'a dyn AltCodeSynthEnabledProvider, +} + +impl<'a> AltCodeSynthesizerMiddleware<'a> { + pub fn new(enabled_state_provider: &'a dyn AltCodeSynthEnabledProvider) -> Self { + Self { + code_buffer: RefCell::new(None), + enabled_state_provider, + } + } +} + +impl<'a> Middleware for AltCodeSynthesizerMiddleware<'a> { + fn name(&self) -> &'static str { + "alt_code_synthesizer" + } + + fn next(&self, event: Event, dispatch: &mut dyn FnMut(Event)) -> Event { + match &event.etype { + EventType::Keyboard(keyboard_event) + if self + .enabled_state_provider + .is_alt_code_synthesizer_enabled() => + { + let mut code_buffer = self.code_buffer.borrow_mut(); + + if keyboard_event.status == Status::Pressed { + if let Key::Alt = &keyboard_event.key { + *code_buffer = Some("".to_owned()); + } else if let Some(buffer) = &mut *code_buffer { + match keyboard_event.key { + Key::Numpad0 => buffer.push('0'), + Key::Numpad1 => buffer.push('1'), + Key::Numpad2 => buffer.push('2'), + Key::Numpad3 => buffer.push('3'), + Key::Numpad4 => buffer.push('4'), + Key::Numpad5 => buffer.push('5'), + Key::Numpad6 => buffer.push('6'), + Key::Numpad7 => buffer.push('7'), + Key::Numpad8 => buffer.push('8'), + Key::Numpad9 => buffer.push('9'), + _ => {} + } + } + } else if keyboard_event.key == Key::Alt { + if let Some(codes) = &*code_buffer { + if let Some(target_char) = convert_buffer_into_char(codes) { + dispatch(Event::caused_by( + event.source_id, + EventType::TextInject(TextInjectRequest { + text: target_char, + ..Default::default() + }), + )); + } + } + + *code_buffer = None; + } + } + _ => {} + } + + event + } +} + +fn convert_buffer_into_char(buffer: &str) -> Option { + if buffer.is_empty() { + debug!("unable to generate ALT code as the buffer is empty"); + return None; + } + + if !buffer.chars().all(char::is_numeric) { + debug!("unable to generate ALT code as some of the buffer chars are not numeric"); + return None; + } + + // According to: https://en.wikipedia.org/wiki/Alt_code + // The conversion works as follow: + // * If the number is smaller than 256 and does not start with 0, then we use a patched version of the CP437 encoding + // * If the number is smaller than 256 and starts with 0 we use the CP1252 encoding + // * If the number is greater or equal than 256 we use the unicode encoding + + let code = buffer.parse::().ok()?; + let unicode_code = if code >= 256 { + // Unicode + code + } else if buffer.starts_with('0') { + // CP1252 + convert_cp1252_code_to_unicode(code)? + } else { + // CP437 + convert_cp437_code_to_unicode(code)? + }; + + char::from_u32(unicode_code).map(|c| c.to_string()) +} + +// Taken from: https://altcodeunicode.com/ +fn convert_cp437_code_to_unicode(code: u32) -> Option { + match code { + 0 => Some(0x0000), // Control character - null (NUL) + 1 => Some(0x263A), // White smiling face, smiley face + 2 => Some(0x263B), // Black smiling face + 3 => Some(0x2665), // Black heart suit + 4 => Some(0x2666), // Black diamond suit + 5 => Some(0x2663), // Black club suit + 6 => Some(0x2660), // Black spade suit + 7 => Some(0x2022), // Bullet + 8 => Some(0x25D8), // Inverse bullet + 9 => Some(0x25CB), // White circle + 10 => Some(0x25D9), // Inverse white circle + 11 => Some(0x2642), // Male sign, mars, alchemical symbol for iron + 12 => Some(0x2640), // Female sign, venus, alchemical symbol for copper + 13 => Some(0x266A), // Eighth note, quaver + 14 => Some(0x266B), // Beamed eighth notes, barred eighth notes, beamed quavers + 15 => Some(0x263C), // White sun with rays + 16 => Some(0x25BA), // Black right-pointing pointer + 17 => Some(0x25C4), // Black left-pointing pointer + 18 => Some(0x2195), // Up down arrow + 19 => Some(0x203C), // Double exclamation mark + 20 => Some(0x00B6), // Pilcrow sign, paragraph sign + 21 => Some(0x00A7), // Section sign + 22 => Some(0x25AC), // Black rectangle + 23 => Some(0x21A8), // Up down arrow with base + 24 => Some(0x2191), // Upwards arrow + 25 => Some(0x2193), // Downwards arrow + 26 => Some(0x2192), // Rightwards arrow, Z notation total function + 27 => Some(0x2190), // Leftwards arrow + 28 => Some(0x221F), // Right angle + 29 => Some(0x2194), // Left right arrow, Z notation relation + 30 => Some(0x25B2), // Black up-pointing triangle + 31 => Some(0x25BC), // Black down-pointing triangle + 32 => Some(0x0020), // Space + 33 => Some(0x0021), // Exclamation mark, factorial + 34 => Some(0x0022), // Quotation mark + 35 => Some(0x0023), // Number sign, pound sign, hash, crosshatch, octothorpe + 36 => Some(0x0024), // Dollar sign, milréis, escudo + 37 => Some(0x0025), // Percent sign + 38 => Some(0x0026), // Ampersand + 39 => Some(0x0027), // Apostrophe + 40 => Some(0x0028), // Left parenthesis, opening parenthesis + 41 => Some(0x0029), // Right parenthesis, closing parenthesis + 42 => Some(0x002A), // Asterisk, star + 43 => Some(0x002B), // Plus sign + 44 => Some(0x002C), // Comma, decimal separator + 45 => Some(0x002D), // Hyphen, minus sign + 46 => Some(0x002E), // Full stop, period, dot, decimal point + 47 => Some(0x002F), // Solidus, slash, forward slash, virgule + 48 => Some(0x0030), // Digit zero + 49 => Some(0x0031), // Digit one + 50 => Some(0x0032), // Digit two + 51 => Some(0x0033), // Digit three + 52 => Some(0x0034), // Digit four + 53 => Some(0x0035), // Digit five + 54 => Some(0x0036), // Digit six + 55 => Some(0x0037), // Digit seven + 56 => Some(0x0038), // Digit eight + 57 => Some(0x0039), // Digit nine + 58 => Some(0x003A), // Colon + 59 => Some(0x003B), // Semicolon + 60 => Some(0x003C), // Less-than sign + 61 => Some(0x003D), // Equals sign + 62 => Some(0x003E), // Greater-than sign + 63 => Some(0x003F), // Question mark + 64 => Some(0x0040), // Commercial at, at sign + 65 => Some(0x0041), // Latin capital letter A + 66 => Some(0x0042), // Latin capital letter B + 67 => Some(0x0043), // Latin capital letter C + 68 => Some(0x0044), // Latin capital letter D + 69 => Some(0x0045), // Latin capital letter E + 70 => Some(0x0046), // Latin capital letter F + 71 => Some(0x0047), // Latin capital letter G + 72 => Some(0x0048), // Latin capital letter H + 73 => Some(0x0049), // Latin capital letter I + 74 => Some(0x004A), // Latin capital letter J + 75 => Some(0x004B), // Latin capital letter K + 76 => Some(0x004C), // Latin capital letter L + 77 => Some(0x004D), // Latin capital letter M + 78 => Some(0x004E), // Latin capital letter N + 79 => Some(0x004F), // Latin capital letter O + 80 => Some(0x0050), // Latin capital letter P + 81 => Some(0x0051), // Latin capital letter Q + 82 => Some(0x0052), // Latin capital letter R + 83 => Some(0x0053), // Latin capital letter S + 84 => Some(0x0054), // Latin capital letter T + 85 => Some(0x0055), // Latin capital letter U + 86 => Some(0x0056), // Latin capital letter V + 87 => Some(0x0057), // Latin capital letter W + 88 => Some(0x0058), // Latin capital letter X + 89 => Some(0x0059), // Latin capital letter Y + 90 => Some(0x005A), // Latin capital letter Z + 91 => Some(0x005B), // Left square bracket, opening square bracket + 92 => Some(0x005C), // Reverse solidus, back slash + 93 => Some(0x005D), // Right square bracket, closing square bracket + 94 => Some(0x005E), // Circumflex accent + 95 => Some(0x005F), // Low line, underscore + 96 => Some(0x0060), // Grave accent + 97 => Some(0x0061), // Latin small letter a + 98 => Some(0x0062), // Latin small letter b + 99 => Some(0x0063), // Latin small letter c + 100 => Some(0x0064), // Latin small letter d + 101 => Some(0x0065), // Latin small letter e + 102 => Some(0x0066), // Latin small letter f + 103 => Some(0x0067), // Latin small letter g + 104 => Some(0x0068), // Latin small letter h + 105 => Some(0x0069), // Latin small letter i + 106 => Some(0x006A), // Latin small letter j + 107 => Some(0x006B), // Latin small letter k + 108 => Some(0x006C), // Latin small letter l + 109 => Some(0x006D), // Latin small letter m + 110 => Some(0x006E), // Latin small letter n + 111 => Some(0x006F), // Latin small letter o + 112 => Some(0x0070), // Latin small letter p + 113 => Some(0x0071), // Latin small letter q + 114 => Some(0x0072), // Latin small letter r + 115 => Some(0x0073), // Latin small letter s + 116 => Some(0x0074), // Latin small letter t + 117 => Some(0x0075), // Latin small letter u + 118 => Some(0x0076), // Latin small letter v + 119 => Some(0x0077), // Latin small letter w + 120 => Some(0x0078), // Latin small letter x + 121 => Some(0x0079), // Latin small letter y + 122 => Some(0x007A), // Latin small letter z + 123 => Some(0x007B), // Left curly bracket, opening curly bracket, left brace + 124 => Some(0x007C), // Vertical line, vertical bar + 125 => Some(0x007D), // Right curly bracket, closing curly bracket, right brace + 126 => Some(0x007E), // Tilde + 127 => Some(0x2302), // House + 128 => Some(0x00C7), // Latin capital letter C with cedilla + 129 => Some(0x00FC), // Latin small letter u with diaeresis + 130 => Some(0x00E9), // Latin small letter e with acute + 131 => Some(0x00E2), // Latin small letter a with circumflex + 132 => Some(0x00E4), // Latin small letter a with diaeresis + 133 => Some(0x00E0), // Latin small letter a with grave + 134 => Some(0x00E5), // Latin small letter a with ring above + 135 => Some(0x00E7), // Latin small letter c with cedilla + 136 => Some(0x00EA), // Latin small letter e with circumflex + 137 => Some(0x00EB), // Latin small letter e with diaeresis + 138 => Some(0x00E8), // Latin small letter e with grave + 139 => Some(0x00EF), // Latin small letter i with diaeresis + 140 => Some(0x00EE), // Latin small letter i with circumflex + 141 => Some(0x00EC), // Latin small letter i with grave + 142 => Some(0x00C4), // Latin capital letter A with diaeresis + 143 => Some(0x00C5), // Latin capital letter A with ring above + 144 => Some(0x00C9), // Latin capital letter E with acute + 145 => Some(0x00E6), // Latin small letter ae, ash (from Old English æsc) + 146 => Some(0x00C6), // Latin capital letter AE + 147 => Some(0x00F4), // Latin small letter o with circumflex + 148 => Some(0x00F6), // Latin small letter o with diaeresis + 149 => Some(0x00F2), // Latin small letter o with grave + 150 => Some(0x00FB), // Latin small letter u with circumflex + 151 => Some(0x00F9), // Latin small letter u with grave + 152 => Some(0x00FF), // Latin small letter y with diaeresis + 153 => Some(0x00D6), // Latin capital letter O with diaeresis + 154 => Some(0x00DC), // Latin capital letter U with diaeresis + 155 => Some(0x00A2), // Cent sign + 156 => Some(0x00A3), // Pound sign, pound sterling, Irish punt, lira sign + 157 => Some(0x00A5), // Yen sign, yuan sign + 158 => Some(0x20A7), // Peseta sign + 159 => Some(0x0192), // Latin small letter f with hook, florin currency symbol, function symbol + 160 => Some(0x00E1), // Latin small letter a with acute + 161 => Some(0x00ED), // Latin small letter i with acute + 162 => Some(0x00F3), // Latin small letter o with acute + 163 => Some(0x00FA), // Latin small letter u with acute + 164 => Some(0x00F1), // Latin small letter n with tilde, small letter enye + 165 => Some(0x00D1), // Latin capital letter N with tilde, capital letter enye + 166 => Some(0x00AA), // Feminine ordinal indicator + 167 => Some(0x00BA), // Masculine ordinal indicator + 168 => Some(0x00BF), // Inverted question mark, turned question mark + 169 => Some(0x2310), // Reversed not sign, beginning of line + 170 => Some(0x00AC), // Not sign, angled dash + 171 => Some(0x00BD), // Vulgar fraction one half + 172 => Some(0x00BC), // Vulgar fraction one quarter + 173 => Some(0x00A1), // Inverted exclamation mark + 174 => Some(0x00AB), // Left-pointing double angle quotation mark, left guillemet, chevrons (in typography) + 175 => Some(0x00BB), // Right-pointing double angle quotation mark, right guillemet + 176 => Some(0x2591), // Light shade + 177 => Some(0x2592), // Medium shade, speckles fill, dotted fill + 178 => Some(0x2593), // Dark shade + 179 => Some(0x2502), // Box drawings light vertical + 180 => Some(0x2524), // Box drawings light vertical and left + 181 => Some(0x2561), // Box drawings vertical single and left double + 182 => Some(0x2562), // Box drawings vertical double and left single + 183 => Some(0x2556), // Box drawings down double and left single + 184 => Some(0x2555), // Box drawings down single and left double + 185 => Some(0x2563), // Box drawings double vertical and left + 186 => Some(0x2551), // Box drawings double vertical + 187 => Some(0x2557), // Box drawings double down and left + 188 => Some(0x255D), // Box drawings double up and left + 189 => Some(0x255C), // Box drawings up double and left single + 190 => Some(0x255B), // Box drawings up single and left double + 191 => Some(0x2510), // Box drawings light down and left + 192 => Some(0x2514), // Box drawings light up and right + 193 => Some(0x2534), // Box drawings light up and horizontal + 194 => Some(0x252C), // Box drawings light down and horizontal + 195 => Some(0x251C), // Box drawings light vertical and right + 196 => Some(0x2500), // Box drawings light horizontal + 197 => Some(0x253C), // Box drawings light vertical and horizontal + 198 => Some(0x255E), // Box drawings vertical single and right double + 199 => Some(0x255F), // Box drawings vertical double and right single + 200 => Some(0x255A), // Box drawings double up and right + 201 => Some(0x2554), // Box drawings double down and right + 202 => Some(0x2569), // Box drawings double up and horizontal + 203 => Some(0x2566), // Box drawings double down and horizontal + 204 => Some(0x2560), // Box drawings double vertical and right + 205 => Some(0x2550), // Box drawings double horizontal + 206 => Some(0x256C), // Box drawings double vertical and horizontal + 207 => Some(0x2567), // Box drawings up single and horizontal double + 208 => Some(0x2568), // Box drawings up double and horizontal single + 209 => Some(0x2564), // Box drawings down single and horizontal double + 210 => Some(0x2565), // Box drawings down double and horizontal single + 211 => Some(0x2559), // Box drawings up double and right single + 212 => Some(0x2558), // Box drawings up single and right double + 213 => Some(0x2552), // Box drawings down single and right double + 214 => Some(0x2553), // Box drawings down double and right single + 215 => Some(0x256B), // Box drawings vertical double and horizontal single + 216 => Some(0x256A), // Box drawings vertical single and horizontal double + 217 => Some(0x2518), // Box drawings light up and left + 218 => Some(0x250C), // Box drawings light down and right + 219 => Some(0x2588), // Full block, solid block + 220 => Some(0x2584), // Lower half block + 221 => Some(0x258C), // Left half block + 222 => Some(0x2590), // Right half block + 223 => Some(0x2580), // Upper half block + 224 => Some(0x03B1), // Greek small letter alpha + 225 => Some(0x00DF), // Latin small letter sharp s, eszett + 226 => Some(0x0393), // Greek capital letter gamma + 227 => Some(0x03C0), // Greek small letter pi + 228 => Some(0x03A3), // Greek capital letter sigma + 229 => Some(0x03C3), // Greek small letter sigma + 230 => Some(0x00B5), // Micro sign + 231 => Some(0x03A4), // Greek capital letter tau + 232 => Some(0x03A6), // Greek capital letter phi + 233 => Some(0x0398), // Greek capital letter theta + 234 => Some(0x03A9), // Greek capital letter omega + 235 => Some(0x03B4), // Greek small letter delta + 236 => Some(0x221E), // Infinity + 237 => Some(0x03C6), // Greek small letter phi + 238 => Some(0x03B5), // Greek small letter epsilon + 239 => Some(0x2229), // Intersection + 240 => Some(0x2261), // Identical to + 241 => Some(0x00B1), // Plus-minus sign + 242 => Some(0x2265), // Greater-than or equal to + 243 => Some(0x2264), // Less-than or equal to + 244 => Some(0x2320), // Top half integral + 245 => Some(0x2321), // Bottom half integral + 246 => Some(0x00F7), // Division sign, obelus + 247 => Some(0x2248), // Almost equal to, asymptotic to + 248 => Some(0x00B0), // Degree sign + 249 => Some(0x2219), // Bullet operator + 250 => Some(0x00B7), // Middle dot, midpoint (in typography), interpunct, Georgian comma, Greek ano teleia + 251 => Some(0x221A), // Square root, radical sign + 252 => Some(0x207F), // Superscript Latin small letter n + 253 => Some(0x00B2), // Superscript two, squared + 254 => Some(0x25A0), // Black square + 255 => Some(0x00A0), // No-break space, non-breaking space, nbsp + _ => None, + } +} + +// Taken from here: https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT +/* +# +# Name: cp1252 to Unicode table +# Unicode version: 2.0 +# Table version: 2.01 +# Table format: Format A +# Date: 04/15/98 +# +# Contact: Shawn.Steele@microsoft.com +# +# General notes: none +# +# Format: Three tab-separated columns +# Column #1 is the cp1252 code (in hex) +# Column #2 is the Unicode (in hex as 0xXXXX) +# Column #3 is the Unicode name (follows a comment sign, '#') +# +# The entries are in cp1252 order +# +*/ +fn convert_cp1252_code_to_unicode(code: u32) -> Option { + match code { + 0x00 => Some(0x0000), // #NULL + 0x01 => Some(0x0001), // #START OF HEADING + 0x02 => Some(0x0002), // #START OF TEXT + 0x03 => Some(0x0003), // #END OF TEXT + 0x04 => Some(0x0004), // #END OF TRANSMISSION + 0x05 => Some(0x0005), // #ENQUIRY + 0x06 => Some(0x0006), // #ACKNOWLEDGE + 0x07 => Some(0x0007), // #BELL + 0x08 => Some(0x0008), // #BACKSPACE + 0x09 => Some(0x0009), // #HORIZONTAL TABULATION + 0x0A => Some(0x000A), // #LINE FEED + 0x0B => Some(0x000B), // #VERTICAL TABULATION + 0x0C => Some(0x000C), // #FORM FEED + 0x0D => Some(0x000D), // #CARRIAGE RETURN + 0x0E => Some(0x000E), // #SHIFT OUT + 0x0F => Some(0x000F), // #SHIFT IN + 0x10 => Some(0x0010), // #DATA LINK ESCAPE + 0x11 => Some(0x0011), // #DEVICE CONTROL ONE + 0x12 => Some(0x0012), // #DEVICE CONTROL TWO + 0x13 => Some(0x0013), // #DEVICE CONTROL THREE + 0x14 => Some(0x0014), // #DEVICE CONTROL FOUR + 0x15 => Some(0x0015), // #NEGATIVE ACKNOWLEDGE + 0x16 => Some(0x0016), // #SYNCHRONOUS IDLE + 0x17 => Some(0x0017), // #END OF TRANSMISSION BLOCK + 0x18 => Some(0x0018), // #CANCEL + 0x19 => Some(0x0019), // #END OF MEDIUM + 0x1A => Some(0x001A), // #SUBSTITUTE + 0x1B => Some(0x001B), // #ESCAPE + 0x1C => Some(0x001C), // #FILE SEPARATOR + 0x1D => Some(0x001D), // #GROUP SEPARATOR + 0x1E => Some(0x001E), // #RECORD SEPARATOR + 0x1F => Some(0x001F), // #UNIT SEPARATOR + 0x20 => Some(0x0020), // #SPACE + 0x21 => Some(0x0021), // #EXCLAMATION MARK + 0x22 => Some(0x0022), // #QUOTATION MARK + 0x23 => Some(0x0023), // #NUMBER SIGN + 0x24 => Some(0x0024), // #DOLLAR SIGN + 0x25 => Some(0x0025), // #PERCENT SIGN + 0x26 => Some(0x0026), // #AMPERSAND + 0x27 => Some(0x0027), // #APOSTROPHE + 0x28 => Some(0x0028), // #LEFT PARENTHESIS + 0x29 => Some(0x0029), // #RIGHT PARENTHESIS + 0x2A => Some(0x002A), // #ASTERISK + 0x2B => Some(0x002B), // #PLUS SIGN + 0x2C => Some(0x002C), // #COMMA + 0x2D => Some(0x002D), // #HYPHEN-MINUS + 0x2E => Some(0x002E), // #FULL STOP + 0x2F => Some(0x002F), // #SOLIDUS + 0x30 => Some(0x0030), // #DIGIT ZERO + 0x31 => Some(0x0031), // #DIGIT ONE + 0x32 => Some(0x0032), // #DIGIT TWO + 0x33 => Some(0x0033), // #DIGIT THREE + 0x34 => Some(0x0034), // #DIGIT FOUR + 0x35 => Some(0x0035), // #DIGIT FIVE + 0x36 => Some(0x0036), // #DIGIT SIX + 0x37 => Some(0x0037), // #DIGIT SEVEN + 0x38 => Some(0x0038), // #DIGIT EIGHT + 0x39 => Some(0x0039), // #DIGIT NINE + 0x3A => Some(0x003A), // #COLON + 0x3B => Some(0x003B), // #SEMICOLON + 0x3C => Some(0x003C), // #LESS-THAN SIGN + 0x3D => Some(0x003D), // #EQUALS SIGN + 0x3E => Some(0x003E), // #GREATER-THAN SIGN + 0x3F => Some(0x003F), // #QUESTION MARK + 0x40 => Some(0x0040), // #COMMERCIAL AT + 0x41 => Some(0x0041), // #LATIN CAPITAL LETTER A + 0x42 => Some(0x0042), // #LATIN CAPITAL LETTER B + 0x43 => Some(0x0043), // #LATIN CAPITAL LETTER C + 0x44 => Some(0x0044), // #LATIN CAPITAL LETTER D + 0x45 => Some(0x0045), // #LATIN CAPITAL LETTER E + 0x46 => Some(0x0046), // #LATIN CAPITAL LETTER F + 0x47 => Some(0x0047), // #LATIN CAPITAL LETTER G + 0x48 => Some(0x0048), // #LATIN CAPITAL LETTER H + 0x49 => Some(0x0049), // #LATIN CAPITAL LETTER I + 0x4A => Some(0x004A), // #LATIN CAPITAL LETTER J + 0x4B => Some(0x004B), // #LATIN CAPITAL LETTER K + 0x4C => Some(0x004C), // #LATIN CAPITAL LETTER L + 0x4D => Some(0x004D), // #LATIN CAPITAL LETTER M + 0x4E => Some(0x004E), // #LATIN CAPITAL LETTER N + 0x4F => Some(0x004F), // #LATIN CAPITAL LETTER O + 0x50 => Some(0x0050), // #LATIN CAPITAL LETTER P + 0x51 => Some(0x0051), // #LATIN CAPITAL LETTER Q + 0x52 => Some(0x0052), // #LATIN CAPITAL LETTER R + 0x53 => Some(0x0053), // #LATIN CAPITAL LETTER S + 0x54 => Some(0x0054), // #LATIN CAPITAL LETTER T + 0x55 => Some(0x0055), // #LATIN CAPITAL LETTER U + 0x56 => Some(0x0056), // #LATIN CAPITAL LETTER V + 0x57 => Some(0x0057), // #LATIN CAPITAL LETTER W + 0x58 => Some(0x0058), // #LATIN CAPITAL LETTER X + 0x59 => Some(0x0059), // #LATIN CAPITAL LETTER Y + 0x5A => Some(0x005A), // #LATIN CAPITAL LETTER Z + 0x5B => Some(0x005B), // #LEFT SQUARE BRACKET + 0x5C => Some(0x005C), // #REVERSE SOLIDUS + 0x5D => Some(0x005D), // #RIGHT SQUARE BRACKET + 0x5E => Some(0x005E), // #CIRCUMFLEX ACCENT + 0x5F => Some(0x005F), // #LOW LINE + 0x60 => Some(0x0060), // #GRAVE ACCENT + 0x61 => Some(0x0061), // #LATIN SMALL LETTER A + 0x62 => Some(0x0062), // #LATIN SMALL LETTER B + 0x63 => Some(0x0063), // #LATIN SMALL LETTER C + 0x64 => Some(0x0064), // #LATIN SMALL LETTER D + 0x65 => Some(0x0065), // #LATIN SMALL LETTER E + 0x66 => Some(0x0066), // #LATIN SMALL LETTER F + 0x67 => Some(0x0067), // #LATIN SMALL LETTER G + 0x68 => Some(0x0068), // #LATIN SMALL LETTER H + 0x69 => Some(0x0069), // #LATIN SMALL LETTER I + 0x6A => Some(0x006A), // #LATIN SMALL LETTER J + 0x6B => Some(0x006B), // #LATIN SMALL LETTER K + 0x6C => Some(0x006C), // #LATIN SMALL LETTER L + 0x6D => Some(0x006D), // #LATIN SMALL LETTER M + 0x6E => Some(0x006E), // #LATIN SMALL LETTER N + 0x6F => Some(0x006F), // #LATIN SMALL LETTER O + 0x70 => Some(0x0070), // #LATIN SMALL LETTER P + 0x71 => Some(0x0071), // #LATIN SMALL LETTER Q + 0x72 => Some(0x0072), // #LATIN SMALL LETTER R + 0x73 => Some(0x0073), // #LATIN SMALL LETTER S + 0x74 => Some(0x0074), // #LATIN SMALL LETTER T + 0x75 => Some(0x0075), // #LATIN SMALL LETTER U + 0x76 => Some(0x0076), // #LATIN SMALL LETTER V + 0x77 => Some(0x0077), // #LATIN SMALL LETTER W + 0x78 => Some(0x0078), // #LATIN SMALL LETTER X + 0x79 => Some(0x0079), // #LATIN SMALL LETTER Y + 0x7A => Some(0x007A), // #LATIN SMALL LETTER Z + 0x7B => Some(0x007B), // #LEFT CURLY BRACKET + 0x7C => Some(0x007C), // #VERTICAL LINE + 0x7D => Some(0x007D), // #RIGHT CURLY BRACKET + 0x7E => Some(0x007E), // #TILDE + 0x7F => Some(0x007F), // #DELETE + 0x80 => Some(0x20AC), // #EURO SIGN + 0x82 => Some(0x201A), // #SINGLE LOW-9 QUOTATION MARK + 0x83 => Some(0x0192), // #LATIN SMALL LETTER F WITH HOOK + 0x84 => Some(0x201E), // #DOUBLE LOW-9 QUOTATION MARK + 0x85 => Some(0x2026), // #HORIZONTAL ELLIPSIS + 0x86 => Some(0x2020), // #DAGGER + 0x87 => Some(0x2021), // #DOUBLE DAGGER + 0x88 => Some(0x02C6), // #MODIFIER LETTER CIRCUMFLEX ACCENT + 0x89 => Some(0x2030), // #PER MILLE SIGN + 0x8A => Some(0x0160), // #LATIN CAPITAL LETTER S WITH CARON + 0x8B => Some(0x2039), // #SINGLE LEFT-POINTING ANGLE QUOTATION MARK + 0x8C => Some(0x0152), // #LATIN CAPITAL LIGATURE OE + 0x8E => Some(0x017D), // #LATIN CAPITAL LETTER Z WITH CARON + 0x91 => Some(0x2018), // #LEFT SINGLE QUOTATION MARK + 0x92 => Some(0x2019), // #RIGHT SINGLE QUOTATION MARK + 0x93 => Some(0x201C), // #LEFT DOUBLE QUOTATION MARK + 0x94 => Some(0x201D), // #RIGHT DOUBLE QUOTATION MARK + 0x95 => Some(0x2022), // #BULLET + 0x96 => Some(0x2013), // #EN DASH + 0x97 => Some(0x2014), // #EM DASH + 0x98 => Some(0x02DC), // #SMALL TILDE + 0x99 => Some(0x2122), // #TRADE MARK SIGN + 0x9A => Some(0x0161), // #LATIN SMALL LETTER S WITH CARON + 0x9B => Some(0x203A), // #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + 0x9C => Some(0x0153), // #LATIN SMALL LIGATURE OE + 0x9E => Some(0x017E), // #LATIN SMALL LETTER Z WITH CARON + 0x9F => Some(0x0178), // #LATIN CAPITAL LETTER Y WITH DIAERESIS + 0xA0 => Some(0x00A0), // #NO-BREAK SPACE + 0xA1 => Some(0x00A1), // #INVERTED EXCLAMATION MARK + 0xA2 => Some(0x00A2), // #CENT SIGN + 0xA3 => Some(0x00A3), // #POUND SIGN + 0xA4 => Some(0x00A4), // #CURRENCY SIGN + 0xA5 => Some(0x00A5), // #YEN SIGN + 0xA6 => Some(0x00A6), // #BROKEN BAR + 0xA7 => Some(0x00A7), // #SECTION SIGN + 0xA8 => Some(0x00A8), // #DIAERESIS + 0xA9 => Some(0x00A9), // #COPYRIGHT SIGN + 0xAA => Some(0x00AA), // #FEMININE ORDINAL INDICATOR + 0xAB => Some(0x00AB), // #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0xAC => Some(0x00AC), // #NOT SIGN + 0xAD => Some(0x00AD), // #SOFT HYPHEN + 0xAE => Some(0x00AE), // #REGISTERED SIGN + 0xAF => Some(0x00AF), // #MACRON + 0xB0 => Some(0x00B0), // #DEGREE SIGN + 0xB1 => Some(0x00B1), // #PLUS-MINUS SIGN + 0xB2 => Some(0x00B2), // #SUPERSCRIPT TWO + 0xB3 => Some(0x00B3), // #SUPERSCRIPT THREE + 0xB4 => Some(0x00B4), // #ACUTE ACCENT + 0xB5 => Some(0x00B5), // #MICRO SIGN + 0xB6 => Some(0x00B6), // #PILCROW SIGN + 0xB7 => Some(0x00B7), // #MIDDLE DOT + 0xB8 => Some(0x00B8), // #CEDILLA + 0xB9 => Some(0x00B9), // #SUPERSCRIPT ONE + 0xBA => Some(0x00BA), // #MASCULINE ORDINAL INDICATOR + 0xBB => Some(0x00BB), // #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0xBC => Some(0x00BC), // #VULGAR FRACTION ONE QUARTER + 0xBD => Some(0x00BD), // #VULGAR FRACTION ONE HALF + 0xBE => Some(0x00BE), // #VULGAR FRACTION THREE QUARTERS + 0xBF => Some(0x00BF), // #INVERTED QUESTION MARK + 0xC0 => Some(0x00C0), // #LATIN CAPITAL LETTER A WITH GRAVE + 0xC1 => Some(0x00C1), // #LATIN CAPITAL LETTER A WITH ACUTE + 0xC2 => Some(0x00C2), // #LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0xC3 => Some(0x00C3), // #LATIN CAPITAL LETTER A WITH TILDE + 0xC4 => Some(0x00C4), // #LATIN CAPITAL LETTER A WITH DIAERESIS + 0xC5 => Some(0x00C5), // #LATIN CAPITAL LETTER A WITH RING ABOVE + 0xC6 => Some(0x00C6), // #LATIN CAPITAL LETTER AE + 0xC7 => Some(0x00C7), // #LATIN CAPITAL LETTER C WITH CEDILLA + 0xC8 => Some(0x00C8), // #LATIN CAPITAL LETTER E WITH GRAVE + 0xC9 => Some(0x00C9), // #LATIN CAPITAL LETTER E WITH ACUTE + 0xCA => Some(0x00CA), // #LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0xCB => Some(0x00CB), // #LATIN CAPITAL LETTER E WITH DIAERESIS + 0xCC => Some(0x00CC), // #LATIN CAPITAL LETTER I WITH GRAVE + 0xCD => Some(0x00CD), // #LATIN CAPITAL LETTER I WITH ACUTE + 0xCE => Some(0x00CE), // #LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0xCF => Some(0x00CF), // #LATIN CAPITAL LETTER I WITH DIAERESIS + 0xD0 => Some(0x00D0), // #LATIN CAPITAL LETTER ETH + 0xD1 => Some(0x00D1), // #LATIN CAPITAL LETTER N WITH TILDE + 0xD2 => Some(0x00D2), // #LATIN CAPITAL LETTER O WITH GRAVE + 0xD3 => Some(0x00D3), // #LATIN CAPITAL LETTER O WITH ACUTE + 0xD4 => Some(0x00D4), // #LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0xD5 => Some(0x00D5), // #LATIN CAPITAL LETTER O WITH TILDE + 0xD6 => Some(0x00D6), // #LATIN CAPITAL LETTER O WITH DIAERESIS + 0xD7 => Some(0x00D7), // #MULTIPLICATION SIGN + 0xD8 => Some(0x00D8), // #LATIN CAPITAL LETTER O WITH STROKE + 0xD9 => Some(0x00D9), // #LATIN CAPITAL LETTER U WITH GRAVE + 0xDA => Some(0x00DA), // #LATIN CAPITAL LETTER U WITH ACUTE + 0xDB => Some(0x00DB), // #LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0xDC => Some(0x00DC), // #LATIN CAPITAL LETTER U WITH DIAERESIS + 0xDD => Some(0x00DD), // #LATIN CAPITAL LETTER Y WITH ACUTE + 0xDE => Some(0x00DE), // #LATIN CAPITAL LETTER THORN + 0xDF => Some(0x00DF), // #LATIN SMALL LETTER SHARP S + 0xE0 => Some(0x00E0), // #LATIN SMALL LETTER A WITH GRAVE + 0xE1 => Some(0x00E1), // #LATIN SMALL LETTER A WITH ACUTE + 0xE2 => Some(0x00E2), // #LATIN SMALL LETTER A WITH CIRCUMFLEX + 0xE3 => Some(0x00E3), // #LATIN SMALL LETTER A WITH TILDE + 0xE4 => Some(0x00E4), // #LATIN SMALL LETTER A WITH DIAERESIS + 0xE5 => Some(0x00E5), // #LATIN SMALL LETTER A WITH RING ABOVE + 0xE6 => Some(0x00E6), // #LATIN SMALL LETTER AE + 0xE7 => Some(0x00E7), // #LATIN SMALL LETTER C WITH CEDILLA + 0xE8 => Some(0x00E8), // #LATIN SMALL LETTER E WITH GRAVE + 0xE9 => Some(0x00E9), // #LATIN SMALL LETTER E WITH ACUTE + 0xEA => Some(0x00EA), // #LATIN SMALL LETTER E WITH CIRCUMFLEX + 0xEB => Some(0x00EB), // #LATIN SMALL LETTER E WITH DIAERESIS + 0xEC => Some(0x00EC), // #LATIN SMALL LETTER I WITH GRAVE + 0xED => Some(0x00ED), // #LATIN SMALL LETTER I WITH ACUTE + 0xEE => Some(0x00EE), // #LATIN SMALL LETTER I WITH CIRCUMFLEX + 0xEF => Some(0x00EF), // #LATIN SMALL LETTER I WITH DIAERESIS + 0xF0 => Some(0x00F0), // #LATIN SMALL LETTER ETH + 0xF1 => Some(0x00F1), // #LATIN SMALL LETTER N WITH TILDE + 0xF2 => Some(0x00F2), // #LATIN SMALL LETTER O WITH GRAVE + 0xF3 => Some(0x00F3), // #LATIN SMALL LETTER O WITH ACUTE + 0xF4 => Some(0x00F4), // #LATIN SMALL LETTER O WITH CIRCUMFLEX + 0xF5 => Some(0x00F5), // #LATIN SMALL LETTER O WITH TILDE + 0xF6 => Some(0x00F6), // #LATIN SMALL LETTER O WITH DIAERESIS + 0xF7 => Some(0x00F7), // #DIVISION SIGN + 0xF8 => Some(0x00F8), // #LATIN SMALL LETTER O WITH STROKE + 0xF9 => Some(0x00F9), // #LATIN SMALL LETTER U WITH GRAVE + 0xFA => Some(0x00FA), // #LATIN SMALL LETTER U WITH ACUTE + 0xFB => Some(0x00FB), // #LATIN SMALL LETTER U WITH CIRCUMFLEX + 0xFC => Some(0x00FC), // #LATIN SMALL LETTER U WITH DIAERESIS + 0xFD => Some(0x00FD), // #LATIN SMALL LETTER Y WITH ACUTE + 0xFE => Some(0x00FE), // #LATIN SMALL LETTER THORN + 0xFF => Some(0x00FF), // #LATIN SMALL LETTER Y WITH DIAERESIS + _ => None, + } +} diff --git a/espanso-engine/src/process/middleware/mod.rs b/espanso-engine/src/process/middleware/mod.rs index d42e5c5..2396138 100644 --- a/espanso-engine/src/process/middleware/mod.rs +++ b/espanso-engine/src/process/middleware/mod.rs @@ -18,6 +18,7 @@ */ pub mod action; +pub mod alt_code_synthesizer; pub mod cause; pub mod context_menu; pub mod cursor_hint; diff --git a/espanso-engine/src/process/mod.rs b/espanso-engine/src/process/mod.rs index f55e520..6430c3e 100644 --- a/espanso-engine/src/process/mod.rs +++ b/espanso-engine/src/process/mod.rs @@ -34,6 +34,7 @@ pub trait Processor { // Dependency inversion entities pub use middleware::action::{EventSequenceProvider, MatchInfoProvider}; +pub use middleware::alt_code_synthesizer::AltCodeSynthEnabledProvider; pub use middleware::delay_modifiers::ModifierStatusProvider; pub use middleware::disable::DisableOptions; pub use middleware::image_resolve::PathProvider; @@ -69,6 +70,7 @@ pub fn default<'a, MatcherState>( modifier_state_provider: &'a dyn ModifierStateProvider, match_resolver: &'a dyn MatchResolver, notification_manager: &'a dyn NotificationManager, + alt_code_synth_enabled_provider: &'a dyn AltCodeSynthEnabledProvider, ) -> impl Processor + 'a { default::DefaultProcessor::new( matchers, @@ -88,5 +90,6 @@ pub fn default<'a, MatcherState>( modifier_state_provider, match_resolver, notification_manager, + alt_code_synth_enabled_provider, ) } diff --git a/espanso/src/cli/worker/config.rs b/espanso/src/cli/worker/config.rs index abc7dce..8960173 100644 --- a/espanso/src/cli/worker/config.rs +++ b/espanso/src/cli/worker/config.rs @@ -211,3 +211,9 @@ impl<'a> crate::gui::modulo::search::ModuloSearchUIOptionProvider for ConfigMana self.active().post_search_delay() } } + +impl<'a> espanso_engine::process::AltCodeSynthEnabledProvider for ConfigManager<'a> { + fn is_alt_code_synthesizer_enabled(&self) -> bool { + self.active().emulate_alt_codes() + } +} diff --git a/espanso/src/cli/worker/engine/dispatch/executor/key_injector.rs b/espanso/src/cli/worker/engine/dispatch/executor/key_injector.rs index 26e732b..669d030 100644 --- a/espanso/src/cli/worker/engine/dispatch/executor/key_injector.rs +++ b/espanso/src/cli/worker/engine/dispatch/executor/key_injector.rs @@ -108,6 +108,16 @@ fn convert_to_inject_key(key: &espanso_engine::event::input::Key) -> espanso_inj espanso_engine::event::input::Key::F18 => espanso_inject::keys::Key::F18, espanso_engine::event::input::Key::F19 => espanso_inject::keys::Key::F19, espanso_engine::event::input::Key::F20 => espanso_inject::keys::Key::F20, + espanso_engine::event::input::Key::Numpad0 => espanso_inject::keys::Key::Numpad0, + espanso_engine::event::input::Key::Numpad1 => espanso_inject::keys::Key::Numpad1, + espanso_engine::event::input::Key::Numpad2 => espanso_inject::keys::Key::Numpad2, + espanso_engine::event::input::Key::Numpad3 => espanso_inject::keys::Key::Numpad3, + espanso_engine::event::input::Key::Numpad4 => espanso_inject::keys::Key::Numpad4, + espanso_engine::event::input::Key::Numpad5 => espanso_inject::keys::Key::Numpad5, + espanso_engine::event::input::Key::Numpad6 => espanso_inject::keys::Key::Numpad6, + espanso_engine::event::input::Key::Numpad7 => espanso_inject::keys::Key::Numpad7, + espanso_engine::event::input::Key::Numpad8 => espanso_inject::keys::Key::Numpad8, + espanso_engine::event::input::Key::Numpad9 => espanso_inject::keys::Key::Numpad9, espanso_engine::event::input::Key::Other(raw) => espanso_inject::keys::Key::Raw(*raw), } } diff --git a/espanso/src/cli/worker/engine/funnel/detect.rs b/espanso/src/cli/worker/engine/funnel/detect.rs index c587f30..8e3e1e2 100644 --- a/espanso/src/cli/worker/engine/funnel/detect.rs +++ b/espanso/src/cli/worker/engine/funnel/detect.rs @@ -110,6 +110,16 @@ pub fn convert_to_engine_key(key: espanso_detect::event::Key) -> Key { espanso_detect::event::Key::F18 => Key::F18, espanso_detect::event::Key::F19 => Key::F19, espanso_detect::event::Key::F20 => Key::F20, + espanso_detect::event::Key::Numpad0 => Key::Numpad0, + espanso_detect::event::Key::Numpad1 => Key::Numpad1, + espanso_detect::event::Key::Numpad2 => Key::Numpad2, + espanso_detect::event::Key::Numpad3 => Key::Numpad3, + espanso_detect::event::Key::Numpad4 => Key::Numpad4, + espanso_detect::event::Key::Numpad5 => Key::Numpad5, + espanso_detect::event::Key::Numpad6 => Key::Numpad6, + espanso_detect::event::Key::Numpad7 => Key::Numpad7, + espanso_detect::event::Key::Numpad8 => Key::Numpad8, + espanso_detect::event::Key::Numpad9 => Key::Numpad9, espanso_detect::event::Key::Other(code) => Key::Other(code), } } diff --git a/espanso/src/cli/worker/engine/mod.rs b/espanso/src/cli/worker/engine/mod.rs index d48269d..a30262f 100644 --- a/espanso/src/cli/worker/engine/mod.rs +++ b/espanso/src/cli/worker/engine/mod.rs @@ -243,6 +243,7 @@ pub fn initialize_and_spawn( &modifier_state_store, &combined_match_cache, ¬ification_manager, + &config_manager, ); let event_injector = EventInjectorAdapter::new(&*injector, &config_manager); diff --git a/espanso/src/cli/worker/engine/process/middleware/matcher/mod.rs b/espanso/src/cli/worker/engine/process/middleware/matcher/mod.rs index 9eda638..58b2bd7 100644 --- a/espanso/src/cli/worker/engine/process/middleware/matcher/mod.rs +++ b/espanso/src/cli/worker/engine/process/middleware/matcher/mod.rs @@ -98,5 +98,6 @@ pub fn convert_to_match_key(key: Key) -> espanso_match::event::Key { Key::F19 => espanso_match::event::Key::F19, Key::F20 => espanso_match::event::Key::F20, Key::Other(_) => espanso_match::event::Key::Other, + _ => espanso_match::event::Key::Other, } } diff --git a/espanso/src/patch/patches/mod.rs b/espanso/src/patch/patches/mod.rs index f652011..30c29eb 100644 --- a/espanso/src/patch/patches/mod.rs +++ b/espanso/src/patch/patches/mod.rs @@ -50,6 +50,7 @@ generate_patchable_config!( undo_backspace -> bool, post_form_delay -> usize, post_search_delay -> usize, + emulate_alt_codes -> bool, win32_exclude_orphan_events -> bool, win32_keyboard_layout_cache_interval -> i64, x11_use_xclip_backend -> bool,