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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//! This contains the logic for working with the console buffer.
use std::io::{Error, Result};
use std::mem::size_of;
use winapi::{
shared::minwindef::TRUE,
shared::ntdef::NULL,
um::{
minwinbase::SECURITY_ATTRIBUTES,
wincon::{
CreateConsoleScreenBuffer, GetConsoleScreenBufferInfo, SetConsoleActiveScreenBuffer,
SetConsoleScreenBufferSize, CONSOLE_TEXTMODE_BUFFER, COORD,
},
winnt::{FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE, HANDLE},
},
};
use super::{is_true, Handle, HandleType, ScreenBufferInfo};
pub struct ScreenBuffer {
handle: Handle,
}
impl ScreenBuffer {
/// Create an instance of `ScreenBuffer` where the `HANDLE`, used for the functions this type wraps, is the current output handle.
pub fn current() -> Result<ScreenBuffer> {
Ok(ScreenBuffer {
handle: Handle::new(HandleType::CurrentOutputHandle)?,
})
}
/// Create new console screen buffer.
///
/// Wraps the underlying function call: [CreateConsoleScreenBuffer]
/// link: [https://docs.microsoft.com/en-us/windows/console/createconsolescreenbuffer]
pub fn create() -> ScreenBuffer {
let mut security_attr: SECURITY_ATTRIBUTES = SECURITY_ATTRIBUTES {
nLength: size_of::<SECURITY_ATTRIBUTES>() as u32,
lpSecurityDescriptor: NULL,
bInheritHandle: TRUE,
};
unsafe {
let new_screen_buffer = CreateConsoleScreenBuffer(
GENERIC_READ | // read/write access
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, // shared
&mut security_attr, // default security attributes
CONSOLE_TEXTMODE_BUFFER, // must be TEXTMODE
NULL,
);
ScreenBuffer {
handle: Handle::from(new_screen_buffer),
}
}
}
/// This will make this `ScreenBuffer` the active one.
///
/// Wraps the underlying function call: [SetConsoleActiveScreenBuffer]
/// link: [https://docs.microsoft.com/en-us/windows/console/setconsoleactivescreenbuffer]
pub fn show(&self) -> Result<()> {
unsafe {
if !is_true(SetConsoleActiveScreenBuffer(*self.handle)) {
return Err(Error::last_os_error());
}
}
Ok(())
}
/// Get the screen buffer information like terminal size, cursor position, buffer size.
///
/// Wraps the underlying function call: [GetConsoleScreenBufferInfo]
/// link: [https://docs.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo]
pub fn info(&self) -> Result<ScreenBufferInfo> {
let mut csbi = ScreenBufferInfo::new();
unsafe {
if !is_true(GetConsoleScreenBufferInfo(*self.handle, &mut csbi.0)) {
return Err(Error::last_os_error());
}
}
Ok(csbi)
}
/// Set the console screen buffer size to the given size.
///
/// Wraps the underlying function call: [SetConsoleScreenBufferSize]
/// link: [https://docs.microsoft.com/en-us/windows/console/setconsolescreenbuffersize]
pub fn set_size(&self, x: i16, y: i16) -> Result<()> {
unsafe {
if !is_true(SetConsoleScreenBufferSize(
*self.handle,
COORD { X: x, Y: y },
)) {
return Err(Error::last_os_error());
}
}
Ok(())
}
/// Get the underlining raw `HANDLE` used by this type to execute whit.
pub fn handle(&self) -> &Handle {
return &self.handle;
}
}
impl From<Handle> for ScreenBuffer {
fn from(handle: Handle) -> Self {
ScreenBuffer { handle }
}
}
impl From<HANDLE> for ScreenBuffer {
fn from(handle: HANDLE) -> Self {
ScreenBuffer {
handle: Handle::from(handle),
}
}
}
#[cfg(test)]
mod tests {
use super::ScreenBuffer;
#[test]
fn test_screen_buffer_info() {
let buffer = ScreenBuffer::current().unwrap();
let info = buffer.info().unwrap();
info.terminal_size();
info.terminal_window();
info.attributes();
info.cursor_pos();
}
}