1#[cfg(windows)]
2#[allow(non_camel_case_types, non_snake_case)]
3mod windows_console {
4 use core::ffi::c_void;
5
6 type c_ulong = u32;
7 type c_int = i32;
8 type wchar_t = u16;
9
10 type DWORD = c_ulong;
11 type LPDWORD = *mut DWORD;
12 type HANDLE = *mut c_void;
13 type BOOL = c_int;
14 type LPCWSTR = *const WCHAR;
15 type WCHAR = wchar_t;
16 type LPSECURITY_ATTRIBUTES = *mut SECURITY_ATTRIBUTES;
17 type LPVOID = *mut c_void;
18
19 #[repr(C)]
20 pub struct SECURITY_ATTRIBUTES {
21 pub nLength: DWORD,
22 pub lpSecurityDescriptor: LPVOID,
23 pub bInheritHandle: BOOL,
24 }
25
26 const ENABLE_VIRTUAL_TERMINAL_PROCESSING: DWORD = 0x0004;
27 const INVALID_HANDLE_VALUE: HANDLE = -1isize as HANDLE;
28 const FALSE: BOOL = 0;
29 const TRUE: BOOL = 1;
30
31 const GENERIC_READ: DWORD = 0x80000000;
32 const GENERIC_WRITE: DWORD = 0x40000000;
33
34 const FILE_SHARE_READ: DWORD = 0x00000001;
35 const FILE_SHARE_WRITE: DWORD = 0x00000002;
36 const OPEN_EXISTING: DWORD = 3;
37
38 extern "system" {
40 fn CreateFileW(
41 lpFileName: LPCWSTR,
42 dwDesiredAccess: DWORD,
43 dwShareMode: DWORD,
44 lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
45 dwCreationDisposition: DWORD,
46 dwFlagsAndAttributes: DWORD,
47 hTemplateFile: HANDLE
48 ) -> HANDLE;
49
50 fn GetLastError() -> DWORD;
51 fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL;
52 fn SetConsoleMode(hConsoleHandle: HANDLE, dwMode: DWORD) -> BOOL;
53 }
54
55 fn get_output_handle() -> Result<HANDLE, DWORD> {
56 const CONOUT: &[u16] = &[0x43, 0x4F, 0x4E, 0x4F, 0x55, 0x54, 0x24, 0x00];
58
59 let raw_handle = unsafe {
60 CreateFileW(
61 CONOUT.as_ptr(),
62 GENERIC_READ | GENERIC_WRITE,
63 FILE_SHARE_READ | FILE_SHARE_WRITE,
64 core::ptr::null_mut(),
65 OPEN_EXISTING,
66 0,
67 core::ptr::null_mut(),
68 )
69 };
70
71 if raw_handle == INVALID_HANDLE_VALUE {
72 return Err(6);
73 }
74
75 Ok(raw_handle)
76 }
77
78 unsafe fn enable_vt(handle: HANDLE) -> Result<(), DWORD> {
79 let mut dw_mode: DWORD = 0;
80 if GetConsoleMode(handle, &mut dw_mode) == FALSE {
81 return Err(GetLastError());
82 }
83
84 dw_mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
85 match SetConsoleMode(handle, dw_mode) {
86 result if result == TRUE => Ok(()),
87 _ => Err(GetLastError())
88 }
89 }
90
91 unsafe fn enable_ansi_colors_raw() -> Result<bool, DWORD> {
92 enable_vt(get_output_handle()?)?;
93 Ok(true)
94 }
95
96 #[inline(always)]
97 pub fn enable() -> bool {
98 unsafe { enable_ansi_colors_raw().unwrap_or(false) }
99 }
100
101 pub fn cache_enable() -> bool {
103 use crate::condition::CachedBool;
104
105 static ENABLED: CachedBool = CachedBool::new();
106 ENABLED.get_or_init(enable)
107 }
108}
109
110#[cfg(not(windows))]
111mod windows_console {
112 #[inline(always)]
113 #[allow(dead_code)]
114 pub fn enable() -> bool { true }
115
116 #[inline(always)]
117 pub fn cache_enable() -> bool { true }
118}
119
120pub use self::windows_console::cache_enable;