From 072d88358366a01eaa91aada18cfad1199c46614 Mon Sep 17 00:00:00 2001
From: Federico Terzi <federico-terzi@users.noreply.github.com>
Date: Fri, 6 Sep 2019 10:21:33 +0200
Subject: [PATCH] Add experimental new line support for windows

---
 native/libwinbridge/bridge.cpp | 20 +++++++++++++++++++-
 native/libwinbridge/bridge.h   |  5 +++++
 src/engine.rs                  | 12 +++++++++++-
 src/keyboard/mod.rs            |  1 +
 src/keyboard/windows.rs        |  8 ++++++++
 5 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/native/libwinbridge/bridge.cpp b/native/libwinbridge/bridge.cpp
index cb55b10..eafd536 100644
--- a/native/libwinbridge/bridge.cpp
+++ b/native/libwinbridge/bridge.cpp
@@ -223,10 +223,28 @@ void delete_string(int32_t count) {
         input.ki.dwFlags = 0; // 0 for key press
         vec.push_back(input);
 
-        // Release the "A" key
         input.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
         vec.push_back(input);
     }
 
+    SendInput(vec.size(), vec.data(), sizeof(INPUT));
+}
+
+void send_vkey(int32_t vk) {
+    std::vector<INPUT> vec;
+
+    INPUT input = { 0 };
+
+    input.type = INPUT_KEYBOARD;
+    input.ki.wScan = 0;
+    input.ki.time = 0;
+    input.ki.dwExtraInfo = 0;
+    input.ki.wVk = vk;
+    input.ki.dwFlags = 0; // 0 for key press
+    vec.push_back(input);
+
+    input.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
+    vec.push_back(input);
+
     SendInput(vec.size(), vec.data(), sizeof(INPUT));
 }
\ No newline at end of file
diff --git a/native/libwinbridge/bridge.h b/native/libwinbridge/bridge.h
index 8a89442..7353f22 100644
--- a/native/libwinbridge/bridge.h
+++ b/native/libwinbridge/bridge.h
@@ -34,6 +34,11 @@ extern "C" void eventloop();
  */
 extern "C" void send_string(const wchar_t * string);
 
+/*
+ * Send the given Virtual Key press
+ */
+extern "C" void send_vkey(int32_t vk);
+
 /*
  * Send the backspace keypress, *count* times.
  */
diff --git a/src/engine.rs b/src/engine.rs
index 688cc04..40d93fe 100644
--- a/src/engine.rs
+++ b/src/engine.rs
@@ -16,6 +16,16 @@ impl <S> Engine<S> where S: KeyboardSender{
 impl <S> MatchReceiver for Engine<S> where S: KeyboardSender{
     fn on_match(&self, m: &Match) {
         self.sender.delete_string(m.trigger.len() as i32);
-        self.sender.send_string(m.replace.as_str());
+
+        // To handle newlines, substitute each "\n" char with an Enter key press.
+        let splits = m.replace.lines();
+
+        for (i, split) in splits.enumerate() {
+            if i > 0 {
+                self.sender.send_enter();
+            }
+
+            self.sender.send_string(split);
+        }
     }
 }
\ No newline at end of file
diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs
index 1c38cd5..f94938e 100644
--- a/src/keyboard/mod.rs
+++ b/src/keyboard/mod.rs
@@ -38,6 +38,7 @@ pub enum KeyEvent {
 
 pub trait KeyboardSender {
     fn send_string(&self, s: &str);
+    fn send_enter(&self);
     fn delete_string(&self, count: i32);
 }
 
diff --git a/src/keyboard/windows.rs b/src/keyboard/windows.rs
index 3fb9825..c8ea2c1 100644
--- a/src/keyboard/windows.rs
+++ b/src/keyboard/windows.rs
@@ -40,6 +40,13 @@ impl super::KeyboardSender for WindowsKeyboardSender {
 
     }
 
+    fn send_enter(&self) {
+        unsafe {
+            // Send the VK_RETURN key press
+            send_vkey(0x0D);
+        }
+    }
+
     fn delete_string(&self, count: i32) {
         unsafe {
             delete_string(count)
@@ -87,5 +94,6 @@ extern {
     fn initialize_window();
     fn eventloop();
     fn send_string(string: *const u16);
+    fn send_vkey(vk: i32);
     fn delete_string(count: i32);
 }
\ No newline at end of file