Skip to content

Commit ec603c3

Browse files
committed
Support for Unicode Input by Ctrl-Alt-u
1 parent 19f5b6e commit ec603c3

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

src/terminal_box.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,9 @@ where
597597
key_code,
598598
modifiers,
599599
}) if state.is_focused => {
600+
if state.is_unicode_input {
601+
return Status::Captured;
602+
}
600603
let mod_no = calculate_modifier_number(state);
601604
let escape_code = match key_code {
602605
KeyCode::Insert => csi("2", "~", mod_no),
@@ -712,6 +715,10 @@ where
712715
state.modifiers = modifiers;
713716
}
714717
Event::Keyboard(KeyEvent::CharacterReceived(character)) if state.is_focused => {
718+
if unicode_input(character, state, &terminal) {
719+
return Status::Captured;
720+
}
721+
715722
match (
716723
state.modifiers.logo(),
717724
state.modifiers.control(),
@@ -1002,6 +1009,64 @@ where
10021009
}
10031010
}
10041011

1012+
fn unicode_input(character: char, state: &mut State, terminal: &Terminal) -> bool {
1013+
match state.is_unicode_input {
1014+
false => {
1015+
//Should we enter unicode input mode
1016+
match (
1017+
state.modifiers.logo(),
1018+
state.modifiers.control(),
1019+
state.modifiers.alt(),
1020+
state.modifiers.shift(),
1021+
) {
1022+
(false, true, true, false) if character == '\x15' => {
1023+
state.is_unicode_input = true;
1024+
true
1025+
}
1026+
_ => false,
1027+
}
1028+
}
1029+
true if state.modifiers.is_empty() => {
1030+
if character.is_ascii_hexdigit() {
1031+
state.unicode_input.push(character);
1032+
} else if character == '\x1b' {
1033+
state.is_unicode_input = false;
1034+
state.unicode_input.clear();
1035+
} else {
1036+
if let Some(unicode_char) = unicode_input_to_char(state) {
1037+
let mut buf = [0, 0, 0, 0];
1038+
let str = unicode_char.encode_utf8(&mut buf);
1039+
terminal.input_scroll(str.as_bytes().to_vec());
1040+
}
1041+
state.is_unicode_input = false;
1042+
state.unicode_input.clear();
1043+
}
1044+
true
1045+
}
1046+
true => {
1047+
//Exit unicode mode on any modifier
1048+
state.is_unicode_input = false;
1049+
state.unicode_input.clear();
1050+
true
1051+
}
1052+
}
1053+
}
1054+
1055+
fn unicode_input_to_char(state: &mut State) -> Option<char> {
1056+
if state.unicode_input.is_empty() {
1057+
return None;
1058+
}
1059+
let hex_str: String = state.unicode_input.iter().collect();
1060+
state.unicode_input.clear();
1061+
match u32::from_str_radix(&hex_str, 16) {
1062+
Ok(value) => char::from_u32(value),
1063+
Err(err) => {
1064+
log::error!("Failed to convert hex string {hex_str} to a u32 value {err}");
1065+
None
1066+
}
1067+
}
1068+
}
1069+
10051070
fn shade(color: cosmic_text::Color, is_focused: bool) -> cosmic_text::Color {
10061071
if is_focused {
10071072
color
@@ -1046,6 +1111,8 @@ pub struct State {
10461111
is_focused: bool,
10471112
scroll_pixels: f32,
10481113
scrollbar_rect: Cell<Rectangle<f32>>,
1114+
unicode_input: Vec<char>,
1115+
is_unicode_input: bool,
10491116
}
10501117

10511118
impl State {
@@ -1058,6 +1125,8 @@ impl State {
10581125
is_focused: false,
10591126
scroll_pixels: 0.0,
10601127
scrollbar_rect: Cell::new(Rectangle::default()),
1128+
unicode_input: Vec::with_capacity(6),
1129+
is_unicode_input: false,
10611130
}
10621131
}
10631132
}

0 commit comments

Comments
 (0)