yansi/
windows.rs

1#[cfg(windows)]
2mod windows_console {
3    use std::os::raw::c_void;
4
5    #[allow(non_camel_case_types)] type c_ulong = u32;
6    #[allow(non_camel_case_types)] type c_int = i32;
7    type DWORD = c_ulong;
8    type LPDWORD = *mut DWORD;
9    type HANDLE = *mut c_void;
10    type BOOL = c_int;
11
12    const ENABLE_VIRTUAL_TERMINAL_PROCESSING: DWORD = 0x0004;
13    const STD_OUTPUT_HANDLE: DWORD = 0xFFFFFFF5;
14    const STD_ERROR_HANDLE: DWORD = 0xFFFFFFF4;
15    const INVALID_HANDLE_VALUE: HANDLE = -1isize as HANDLE;
16    const FALSE: BOOL = 0;
17    const TRUE: BOOL = 1;
18
19    // This is the win32 console API, taken from the 'winapi' crate.
20    extern "system" {
21        fn GetStdHandle(nStdHandle: DWORD) -> HANDLE;
22        fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL;
23        fn SetConsoleMode(hConsoleHandle: HANDLE, dwMode: DWORD) -> BOOL;
24    }
25
26    unsafe fn get_handle(handle_num: DWORD) -> Result<HANDLE, ()> {
27        match GetStdHandle(handle_num) {
28            handle if handle == INVALID_HANDLE_VALUE => Err(()),
29            handle => Ok(handle)
30        }
31    }
32
33    unsafe fn enable_vt(handle: HANDLE) -> Result<(), ()> {
34        let mut dw_mode: DWORD = 0;
35        if GetConsoleMode(handle, &mut dw_mode) == FALSE {
36            return Err(());
37        }
38
39        dw_mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
40        match SetConsoleMode(handle, dw_mode) {
41            result if result == TRUE => Ok(()),
42            _ => Err(())
43        }
44    }
45
46    unsafe fn enable_ascii_colors_raw() -> Result<bool, ()> {
47        let stdout_handle = get_handle(STD_OUTPUT_HANDLE)?;
48        let stderr_handle = get_handle(STD_ERROR_HANDLE)?;
49
50        enable_vt(stdout_handle)?;
51        if stdout_handle != stderr_handle {
52            enable_vt(stderr_handle)?;
53        }
54
55        Ok(true)
56    }
57
58    #[inline]
59    pub fn enable_ascii_colors() -> bool {
60        unsafe { enable_ascii_colors_raw().unwrap_or(false) }
61    }
62}
63
64#[cfg(not(windows))]
65mod windows_console {
66    pub fn enable_ascii_colors() -> bool { true }
67}
68
69pub use self::windows_console::enable_ascii_colors;