diff options
Diffstat (limited to 'vendor/yansi-term/src/windows.rs')
-rw-r--r-- | vendor/yansi-term/src/windows.rs | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/vendor/yansi-term/src/windows.rs b/vendor/yansi-term/src/windows.rs new file mode 100644 index 000000000..3df9ff4ac --- /dev/null +++ b/vendor/yansi-term/src/windows.rs @@ -0,0 +1,61 @@ +/// Enables ANSI code support on Windows 10. +/// +/// This uses Windows API calls to alter the properties of the console that +/// the program is running in. +/// +/// https://msdn.microsoft.com/en-us/library/windows/desktop/mt638032(v=vs.85).aspx +/// +/// Returns a `Result` with the Windows error code if unsuccessful. +#[cfg(windows)] +pub fn enable_ansi_support() -> Result<(), u32> { + // ref: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#EXAMPLE_OF_ENABLING_VIRTUAL_TERMINAL_PROCESSING @@ https://archive.is/L7wRJ#76% + + use std::{ffi::OsStr, iter::once, os::windows::ffi::OsStrExt, ptr::null_mut}; + use winapi::um::{ + consoleapi::{GetConsoleMode, SetConsoleMode}, + errhandlingapi::GetLastError, + fileapi::{CreateFileW, OPEN_EXISTING}, + handleapi::INVALID_HANDLE_VALUE, + winnt::{FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE}, + }; + + const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 0x0004; + + unsafe { + // ref: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew + // Using `CreateFileW("CONOUT$", ...)` to retrieve the console handle works correctly even if STDOUT and/or STDERR are redirected + let console_out_name: Vec<u16> = + OsStr::new("CONOUT$").encode_wide().chain(once(0)).collect(); + let console_handle = CreateFileW( + console_out_name.as_ptr(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE, + null_mut(), + OPEN_EXISTING, + 0, + null_mut(), + ); + if console_handle == INVALID_HANDLE_VALUE { + return Err(GetLastError()); + } + + // ref: https://docs.microsoft.com/en-us/windows/console/getconsolemode + let mut console_mode: u32 = 0; + if 0 == GetConsoleMode(console_handle, &mut console_mode) { + return Err(GetLastError()); + } + + // VT processing not already enabled? + if console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0 { + // https://docs.microsoft.com/en-us/windows/console/setconsolemode + if 0 == SetConsoleMode( + console_handle, + console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING, + ) { + return Err(GetLastError()); + } + } + } + + return Ok(()); +} |