1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use winapi::{WORD, COORD, SMALL_RECT, STD_OUTPUT_HANDLE, FOREGROUND_RED, FOREGROUND_BLUE, FOREGROUND_GREEN, BACKGROUND_RED, BACKGROUND_BLUE, BACKGROUND_GREEN,
             CONSOLE_SCREEN_BUFFER_INFO};
use kernel32::{GetStdHandle, SetConsoleTextAttribute, GetConsoleScreenBufferInfo};
use self::super::{BgColour, Colour, Reset};
use std::fmt;


lazy_static! {
    static ref DEFAULT_ATTRIBUTES: WORD = current_csbi().wAttributes;
}

fn current_csbi() -> CONSOLE_SCREEN_BUFFER_INFO {
    let mut info = CONSOLE_SCREEN_BUFFER_INFO {
        dwSize: COORD { X: 0, Y: 0 },
        dwCursorPosition: COORD { X: 0, Y: 0 },
        wAttributes: 0,
        srWindow: SMALL_RECT {
            Left: 0,
            Top: 0,
            Right: 0,
            Bottom: 0,
        },
        dwMaximumWindowSize: COORD { X: 0, Y: 0 },
    };

    unsafe {
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &mut info);
    }

    info
}

fn set_clr(slf: usize, r: u32, g: u32, b: u32, mask: WORD) {
    let mut attrs = current_csbi().wAttributes;

    let cid = match slf {
        0 => 0,
        1 => r,
        2 => g,
        3 => g | r,
        4 => b,
        5 => b | r,
        6 => b | g,
        7 => b | g | r,
        _ => 0,
    };

    attrs = attrs & !(attrs & mask);
    attrs = attrs | (cid as u16);
    unsafe {
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), attrs);
    }
}


impl fmt::Display for Colour {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if f.precision() != Some(0) {
            set_clr(*self as usize, FOREGROUND_RED, FOREGROUND_GREEN, FOREGROUND_BLUE, 0x0F);
        }
        Ok(())
    }
}

impl fmt::Display for BgColour {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if f.precision() != Some(0) {
            set_clr(*self as usize, BACKGROUND_RED, BACKGROUND_GREEN, BACKGROUND_BLUE, 0xF0);
        }
        Ok(())
    }
}

impl fmt::Display for Reset {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if f.precision() != Some(0) {
            unsafe {
                SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), *DEFAULT_ATTRIBUTES);
            }
        }
        Ok(())
    }
}