From 65a63788bc2e785b879493725283d1a22e314bf2 Mon Sep 17 00:00:00 2001
From: Andrew Gallant <jamslam@gmail.com>
Date: Sat, 10 Feb 2018 18:41:07 -0500
Subject: [PATCH] wincolor: add support for enabling VT100

This commit adds a new method to the Console type which permits toggling
the VIRTUAL_TERMINAL_PROCESSING mode on a console. Specifically, this
enables the use of ANSI escape sequences for color in Windows terminals.
---
 wincolor/Cargo.toml |  5 +++--
 wincolor/src/win.rs | 30 ++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/wincolor/Cargo.toml b/wincolor/Cargo.toml
index af509ebc..29aa757a 100644
--- a/wincolor/Cargo.toml
+++ b/wincolor/Cargo.toml
@@ -16,5 +16,6 @@ license = "Unlicense/MIT"
 name = "wincolor"
 bench = false
 
-[dependencies]
-winapi = { version = "0.3", features = ["minwindef", "processenv", "winbase", "wincon"] }
+[dependencies.winapi]
+version = "0.3"
+features = ["consoleapi", "minwindef", "processenv", "winbase", "wincon"]
diff --git a/wincolor/src/win.rs b/wincolor/src/win.rs
index 8d5594c8..43ccdcdd 100644
--- a/wincolor/src/win.rs
+++ b/wincolor/src/win.rs
@@ -2,6 +2,7 @@ use std::io;
 use std::mem;
 
 use winapi::shared::minwindef::{DWORD, WORD};
+use winapi::um::consoleapi;
 use winapi::um::processenv;
 use winapi::um::winbase::{STD_ERROR_HANDLE, STD_OUTPUT_HANDLE};
 use winapi::um::wincon::{
@@ -115,6 +116,35 @@ impl Console {
         self.cur_attr = self.start_attr;
         self.set()
     }
+
+    /// Toggle virtual terminal processing.
+    ///
+    /// This method attempts to toggle virtual terminal processing for this
+    /// console. If there was a problem toggling it, then an error returned.
+    /// On success, the caller may assume that toggling it was successful.
+    ///
+    /// When virtual terminal processing is enabled, characters emitted to the
+    /// console are parsed for VT100 and similar control character sequences
+    /// that control color and other similar operations.
+    pub fn set_virtual_terminal_processing(
+        &mut self,
+        yes: bool,
+    ) -> io::Result<()> {
+        let mut lpmode = 0;
+        let handle = unsafe { processenv::GetStdHandle(self.handle_id) };
+        if unsafe { consoleapi::GetConsoleMode(handle, &mut lpmode) } == 0 {
+            return Err(io::Error::last_os_error());
+        }
+        if yes {
+            lpmode |= wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
+        } else {
+            lpmode &= !wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
+        }
+        if unsafe { consoleapi::SetConsoleMode(handle, lpmode) } == 0 {
+            return Err(io::Error::last_os_error());
+        }
+        Ok(())
+    }
 }
 
 /// A representation of text attributes for the Windows console.