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
|
//! 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},
},
};
use super::{is_true, Handle, HandleType, ScreenBufferInfo};
#[derive(Clone, Debug)]
pub struct ScreenBuffer {
handle: Handle,
}
impl ScreenBuffer {
pub fn new(handle: Handle) -> Self {
Self { handle }
}
/// 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_raw(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 }
}
}
#[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();
}
}
|