diff --git a/src/context/linux.rs b/src/context/linux.rs index 152ed0b..f0ccab7 100644 --- a/src/context/linux.rs +++ b/src/context/linux.rs @@ -18,12 +18,13 @@ */ use std::sync::mpsc::Sender; -use std::os::raw::c_void; +use std::os::raw::{c_void, c_char}; use crate::event::*; use crate::event::KeyModifier::*; use crate::bridge::linux::*; use std::process::exit; use log::error; +use std::ffi::CStr; #[repr(C)] pub struct LinuxContext { @@ -74,14 +75,19 @@ extern fn keypress_callback(_self: *mut c_void, raw_buffer: *const u8, len: i32, let _self = _self as *mut LinuxContext; if is_modifier == 0 { // Char event - // Convert the received buffer to a character - let buffer = std::slice::from_raw_parts(raw_buffer, len as usize); - let r = String::from_utf8_lossy(buffer).chars().nth(0); + // Convert the received buffer to a string + let c_str = CStr::from_ptr(raw_buffer as (*const c_char)); + let char_str = c_str.to_str(); // Send the char through the channel - if let Some(c) = r { - let event = Event::Key(KeyEvent::Char(c)); - (*_self).send_channel.send(event).unwrap(); + match char_str { + Ok(char_str) => { + let event = Event::Key(KeyEvent::Char(char_str.to_owned())); + (*_self).send_channel.send(event).unwrap(); + }, + Err(e) => { + error!("Unable to receive char: {}",e); + }, } }else{ // Modifier event let modifier: Option = match key_code { diff --git a/src/engine.rs b/src/engine.rs index 84cb22b..d848b27 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -110,7 +110,7 @@ impl <'a, S: KeyboardManager, C: ClipboardManager, M: ConfigManager<'a>, U: UIMa return; } - self.keyboard_manager.delete_string(m.trigger.len() as i32); + self.keyboard_manager.delete_string(m.trigger.chars().count() as i32); let target_string = if m._has_vars { let mut output_map = HashMap::new(); diff --git a/src/event/mod.rs b/src/event/mod.rs index abcfdcc..aeb50da 100644 --- a/src/event/mod.rs +++ b/src/event/mod.rs @@ -52,7 +52,7 @@ impl From for ActionType { #[derive(Debug, Clone)] pub enum KeyEvent { - Char(char), + Char(String), Modifier(KeyModifier) } diff --git a/src/matcher/mod.rs b/src/matcher/mod.rs index ece4eac..59b9ca7 100644 --- a/src/matcher/mod.rs +++ b/src/matcher/mod.rs @@ -90,7 +90,7 @@ pub trait MatchReceiver { } pub trait Matcher : KeyEventReceiver { - fn handle_char(&self, c: char); + fn handle_char(&self, c: &str); fn handle_modifier(&self, m: KeyModifier); } @@ -98,7 +98,7 @@ impl KeyEventReceiver for M { fn on_key_event(&self, e: KeyEvent) { match e { KeyEvent::Char(c) => { - self.handle_char(c); + self.handle_char(&c); }, KeyEvent::Modifier(m) => { self.handle_modifier(m); diff --git a/src/matcher/scrolling.rs b/src/matcher/scrolling.rs index 7df7894..3d919db 100644 --- a/src/matcher/scrolling.rs +++ b/src/matcher/scrolling.rs @@ -35,6 +35,7 @@ pub struct ScrollingMatcher<'a, R: MatchReceiver, M: ConfigManager<'a>> { struct MatchEntry<'a> { start: usize, + count: usize, _match: &'a Match } @@ -68,7 +69,7 @@ impl <'a, R: MatchReceiver, M: ConfigManager<'a>> ScrollingMatcher<'a, R, M> { } impl <'a, R: MatchReceiver, M: ConfigManager<'a>> super::Matcher for ScrollingMatcher<'a, R, M> { - fn handle_char(&self, c: char) { + fn handle_char(&self, c: &str) { // if not enabled, avoid any processing if !*(self.is_enabled.borrow()) { return; @@ -77,8 +78,12 @@ impl <'a, R: MatchReceiver, M: ConfigManager<'a>> super::Matcher for ScrollingMa let mut current_set_queue = self.current_set_queue.borrow_mut(); let new_matches: Vec = self.config_manager.matches().iter() - .filter(|&x| x.trigger.chars().nth(0).unwrap() == c) - .map(|x | MatchEntry{start: 1, _match: &x}) + .filter(|&x| x.trigger.starts_with(c)) + .map(|x | MatchEntry{ + start: 1, + count: x.trigger.chars().count(), + _match: &x + }) .collect(); // TODO: use an associative structure to improve the efficiency of this first "new_matches" lookup. @@ -86,9 +91,18 @@ impl <'a, R: MatchReceiver, M: ConfigManager<'a>> super::Matcher for ScrollingMa Some(last_matches) => { let mut updated: Vec = last_matches.iter() .filter(|&x| { - x._match.trigger[x.start..].chars().nth(0).unwrap() == c + let nchar = x._match.trigger.chars().nth(x.start); + if let Some(nchar) = nchar { + c.starts_with(nchar) + }else{ + false + } + }) + .map(|x | MatchEntry{ + start: x.start+1, + count: x.count, + _match: &x._match }) - .map(|x | MatchEntry{start: x.start+1, _match: &x._match}) .collect(); updated.extend(new_matches); @@ -100,7 +114,7 @@ impl <'a, R: MatchReceiver, M: ConfigManager<'a>> super::Matcher for ScrollingMa let mut found_match = None; for entry in combined_matches.iter() { - if entry.start == entry._match.trigger.len() { + if entry.start == entry.count { found_match = Some(entry._match); break; }