Fix up vendor for... linux?
This commit is contained in:
parent
b799fedeec
commit
81de013103
114 changed files with 21002 additions and 21002 deletions
472
vendor/crossterm_winapi/src/console.rs
vendored
472
vendor/crossterm_winapi/src/console.rs
vendored
|
|
@ -1,236 +1,236 @@
|
|||
use std::io::{self, Result};
|
||||
use std::iter;
|
||||
use std::slice;
|
||||
use std::str;
|
||||
|
||||
use winapi::ctypes::c_void;
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::shared::ntdef::NULL;
|
||||
use winapi::um::consoleapi::{GetNumberOfConsoleInputEvents, ReadConsoleInputW, WriteConsoleW};
|
||||
use winapi::um::wincon::{
|
||||
FillConsoleOutputAttribute, FillConsoleOutputCharacterA, GetLargestConsoleWindowSize,
|
||||
SetConsoleTextAttribute, SetConsoleWindowInfo, COORD, INPUT_RECORD, SMALL_RECT,
|
||||
};
|
||||
|
||||
use super::{result, Coord, Handle, HandleType, InputRecord, WindowPositions};
|
||||
|
||||
/// A wrapper around a screen buffer.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Console {
|
||||
handle: Handle,
|
||||
}
|
||||
|
||||
impl Console {
|
||||
/// Create new instance of `Console`.
|
||||
///
|
||||
/// This created instance will use the default output handle (STD_OUTPUT_HANDLE) as handle for the function call it wraps.
|
||||
pub fn output() -> Result<Console> {
|
||||
Ok(Console {
|
||||
handle: Handle::new(HandleType::OutputHandle)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets the attributes of characters written to the console screen buffer by the `WriteFile` or `WriteConsole` functions, or echoed by the `ReadFile` or `ReadConsole` functions.
|
||||
/// This function affects text written after the function call.
|
||||
///
|
||||
/// The attributes is a bitmask of possible [character
|
||||
/// attributes](https://docs.microsoft.com/en-us/windows/console/console-screen-buffers#character-attributes).
|
||||
///
|
||||
/// This wraps
|
||||
/// [`SetConsoleTextAttribute`](https://docs.microsoft.com/en-us/windows/console/setconsoletextattribute).
|
||||
pub fn set_text_attribute(&self, value: u16) -> Result<()> {
|
||||
result(unsafe { SetConsoleTextAttribute(*self.handle, value) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the current size and position of a console screen buffer's window.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`SetConsoleWindowInfo`](https://docs.microsoft.com/en-us/windows/console/setconsolewindowinfo).
|
||||
pub fn set_console_info(&self, absolute: bool, rect: WindowPositions) -> Result<()> {
|
||||
let absolute = match absolute {
|
||||
true => 1,
|
||||
false => 0,
|
||||
};
|
||||
let a = SMALL_RECT::from(rect);
|
||||
|
||||
result(unsafe { SetConsoleWindowInfo(*self.handle, absolute, &a) })?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Writes a character to the console screen buffer a specified number of times, beginning at the specified coordinates.
|
||||
/// Returns the number of characters that have been written.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`FillConsoleOutputCharacterA`](https://docs.microsoft.com/en-us/windows/console/fillconsoleoutputcharacter).
|
||||
pub fn fill_whit_character(
|
||||
&self,
|
||||
start_location: Coord,
|
||||
cells_to_write: u32,
|
||||
filling_char: char,
|
||||
) -> Result<u32> {
|
||||
let mut chars_written = 0;
|
||||
result(unsafe {
|
||||
// fill the cells in console with blanks
|
||||
FillConsoleOutputCharacterA(
|
||||
*self.handle,
|
||||
filling_char as i8,
|
||||
cells_to_write,
|
||||
COORD::from(start_location),
|
||||
&mut chars_written,
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(chars_written)
|
||||
}
|
||||
|
||||
/// Sets the character attributes for a specified number of character cells, beginning at the specified coordinates in a screen buffer.
|
||||
/// Returns the number of cells that have been modified.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`FillConsoleOutputAttribute`](https://docs.microsoft.com/en-us/windows/console/fillconsoleoutputattribute).
|
||||
pub fn fill_whit_attribute(
|
||||
&self,
|
||||
start_location: Coord,
|
||||
cells_to_write: u32,
|
||||
dw_attribute: u16,
|
||||
) -> Result<u32> {
|
||||
let mut cells_written = 0;
|
||||
// Get the position of the current console window
|
||||
result(unsafe {
|
||||
FillConsoleOutputAttribute(
|
||||
*self.handle,
|
||||
dw_attribute,
|
||||
cells_to_write,
|
||||
COORD::from(start_location),
|
||||
&mut cells_written,
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(cells_written)
|
||||
}
|
||||
|
||||
/// Retrieves the size of the largest possible console window, based on the current text and the size of the display.
|
||||
///
|
||||
/// This wraps [`GetLargestConsoleWindowSize`](https://docs.microsoft.com/en-us/windows/console/getlargestconsolewindowsize)
|
||||
pub fn largest_window_size(&self) -> Result<Coord> {
|
||||
crate::coord_result(unsafe { GetLargestConsoleWindowSize(*self.handle) })
|
||||
}
|
||||
|
||||
/// Writes a character string to a console screen buffer beginning at the current cursor location.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`WriteConsoleW`](https://docs.microsoft.com/en-us/windows/console/writeconsole).
|
||||
pub fn write_char_buffer(&self, buf: &[u8]) -> Result<usize> {
|
||||
// get string from u8[] and parse it to an c_str
|
||||
let utf8 = match str::from_utf8(buf) {
|
||||
Ok(string) => string,
|
||||
Err(_) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Could not parse to utf8 string",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let utf16: Vec<u16> = utf8.encode_utf16().collect();
|
||||
let utf16_ptr: *const c_void = utf16.as_ptr() as *const _ as *const c_void;
|
||||
|
||||
let mut cells_written: u32 = 0;
|
||||
|
||||
result(unsafe {
|
||||
WriteConsoleW(
|
||||
*self.handle,
|
||||
utf16_ptr,
|
||||
utf16.len() as u32,
|
||||
&mut cells_written,
|
||||
NULL,
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(utf8.as_bytes().len())
|
||||
}
|
||||
|
||||
/// Read one input event.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`ReadConsoleInputW`](https://docs.microsoft.com/en-us/windows/console/readconsoleinput).
|
||||
pub fn read_single_input_event(&self) -> Result<InputRecord> {
|
||||
let mut record: INPUT_RECORD = INPUT_RECORD::default();
|
||||
|
||||
{
|
||||
// Convert an INPUT_RECORD to an &mut [INPUT_RECORD] of length 1
|
||||
let buf = slice::from_mut(&mut record);
|
||||
let num_read = self.read_input(buf)?;
|
||||
|
||||
// The windows API promises that ReadConsoleInput returns at least
|
||||
// 1 element
|
||||
debug_assert!(num_read == 1);
|
||||
}
|
||||
|
||||
Ok(record.into())
|
||||
}
|
||||
|
||||
/// Read all available input events without blocking.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`ReadConsoleInputW`](https://docs.microsoft.com/en-us/windows/console/readconsoleinput).
|
||||
pub fn read_console_input(&self) -> Result<Vec<InputRecord>> {
|
||||
let buf_len = self.number_of_console_input_events()?;
|
||||
|
||||
// Fast-skipping all the code below if there is nothing to read at all
|
||||
if buf_len == 0 {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
|
||||
let mut buf: Vec<INPUT_RECORD> = iter::repeat_with(INPUT_RECORD::default)
|
||||
.take(buf_len as usize)
|
||||
.collect();
|
||||
|
||||
let num_read = self.read_input(buf.as_mut_slice())?;
|
||||
|
||||
Ok(buf
|
||||
.into_iter()
|
||||
.take(num_read)
|
||||
.map(InputRecord::from)
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// Get the number of available input events that can be read without blocking.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`GetNumberOfConsoleInputEvents`](https://docs.microsoft.com/en-us/windows/console/getnumberofconsoleinputevents).
|
||||
pub fn number_of_console_input_events(&self) -> Result<u32> {
|
||||
let mut buf_len: DWORD = 0;
|
||||
result(unsafe { GetNumberOfConsoleInputEvents(*self.handle, &mut buf_len) })?;
|
||||
Ok(buf_len)
|
||||
}
|
||||
|
||||
/// Read input (via ReadConsoleInputW) into buf and return the number
|
||||
/// of events read. ReadConsoleInputW guarantees that at least one event
|
||||
/// is read, even if it means blocking the thread. buf.len() must fit in
|
||||
/// a u32.
|
||||
fn read_input(&self, buf: &mut [INPUT_RECORD]) -> Result<usize> {
|
||||
let mut num_records = 0;
|
||||
debug_assert!(buf.len() < std::u32::MAX as usize);
|
||||
|
||||
result(unsafe {
|
||||
ReadConsoleInputW(
|
||||
*self.handle,
|
||||
buf.as_mut_ptr(),
|
||||
buf.len() as u32,
|
||||
&mut num_records,
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(num_records as usize)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Handle> for Console {
|
||||
/// Create a `Console` instance who's functions will be executed on the the given `Handle`
|
||||
fn from(handle: Handle) -> Self {
|
||||
Console { handle }
|
||||
}
|
||||
}
|
||||
use std::io::{self, Result};
|
||||
use std::iter;
|
||||
use std::slice;
|
||||
use std::str;
|
||||
|
||||
use winapi::ctypes::c_void;
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::shared::ntdef::NULL;
|
||||
use winapi::um::consoleapi::{GetNumberOfConsoleInputEvents, ReadConsoleInputW, WriteConsoleW};
|
||||
use winapi::um::wincon::{
|
||||
FillConsoleOutputAttribute, FillConsoleOutputCharacterA, GetLargestConsoleWindowSize,
|
||||
SetConsoleTextAttribute, SetConsoleWindowInfo, COORD, INPUT_RECORD, SMALL_RECT,
|
||||
};
|
||||
|
||||
use super::{result, Coord, Handle, HandleType, InputRecord, WindowPositions};
|
||||
|
||||
/// A wrapper around a screen buffer.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Console {
|
||||
handle: Handle,
|
||||
}
|
||||
|
||||
impl Console {
|
||||
/// Create new instance of `Console`.
|
||||
///
|
||||
/// This created instance will use the default output handle (STD_OUTPUT_HANDLE) as handle for the function call it wraps.
|
||||
pub fn output() -> Result<Console> {
|
||||
Ok(Console {
|
||||
handle: Handle::new(HandleType::OutputHandle)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets the attributes of characters written to the console screen buffer by the `WriteFile` or `WriteConsole` functions, or echoed by the `ReadFile` or `ReadConsole` functions.
|
||||
/// This function affects text written after the function call.
|
||||
///
|
||||
/// The attributes is a bitmask of possible [character
|
||||
/// attributes](https://docs.microsoft.com/en-us/windows/console/console-screen-buffers#character-attributes).
|
||||
///
|
||||
/// This wraps
|
||||
/// [`SetConsoleTextAttribute`](https://docs.microsoft.com/en-us/windows/console/setconsoletextattribute).
|
||||
pub fn set_text_attribute(&self, value: u16) -> Result<()> {
|
||||
result(unsafe { SetConsoleTextAttribute(*self.handle, value) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the current size and position of a console screen buffer's window.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`SetConsoleWindowInfo`](https://docs.microsoft.com/en-us/windows/console/setconsolewindowinfo).
|
||||
pub fn set_console_info(&self, absolute: bool, rect: WindowPositions) -> Result<()> {
|
||||
let absolute = match absolute {
|
||||
true => 1,
|
||||
false => 0,
|
||||
};
|
||||
let a = SMALL_RECT::from(rect);
|
||||
|
||||
result(unsafe { SetConsoleWindowInfo(*self.handle, absolute, &a) })?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Writes a character to the console screen buffer a specified number of times, beginning at the specified coordinates.
|
||||
/// Returns the number of characters that have been written.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`FillConsoleOutputCharacterA`](https://docs.microsoft.com/en-us/windows/console/fillconsoleoutputcharacter).
|
||||
pub fn fill_whit_character(
|
||||
&self,
|
||||
start_location: Coord,
|
||||
cells_to_write: u32,
|
||||
filling_char: char,
|
||||
) -> Result<u32> {
|
||||
let mut chars_written = 0;
|
||||
result(unsafe {
|
||||
// fill the cells in console with blanks
|
||||
FillConsoleOutputCharacterA(
|
||||
*self.handle,
|
||||
filling_char as i8,
|
||||
cells_to_write,
|
||||
COORD::from(start_location),
|
||||
&mut chars_written,
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(chars_written)
|
||||
}
|
||||
|
||||
/// Sets the character attributes for a specified number of character cells, beginning at the specified coordinates in a screen buffer.
|
||||
/// Returns the number of cells that have been modified.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`FillConsoleOutputAttribute`](https://docs.microsoft.com/en-us/windows/console/fillconsoleoutputattribute).
|
||||
pub fn fill_whit_attribute(
|
||||
&self,
|
||||
start_location: Coord,
|
||||
cells_to_write: u32,
|
||||
dw_attribute: u16,
|
||||
) -> Result<u32> {
|
||||
let mut cells_written = 0;
|
||||
// Get the position of the current console window
|
||||
result(unsafe {
|
||||
FillConsoleOutputAttribute(
|
||||
*self.handle,
|
||||
dw_attribute,
|
||||
cells_to_write,
|
||||
COORD::from(start_location),
|
||||
&mut cells_written,
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(cells_written)
|
||||
}
|
||||
|
||||
/// Retrieves the size of the largest possible console window, based on the current text and the size of the display.
|
||||
///
|
||||
/// This wraps [`GetLargestConsoleWindowSize`](https://docs.microsoft.com/en-us/windows/console/getlargestconsolewindowsize)
|
||||
pub fn largest_window_size(&self) -> Result<Coord> {
|
||||
crate::coord_result(unsafe { GetLargestConsoleWindowSize(*self.handle) })
|
||||
}
|
||||
|
||||
/// Writes a character string to a console screen buffer beginning at the current cursor location.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`WriteConsoleW`](https://docs.microsoft.com/en-us/windows/console/writeconsole).
|
||||
pub fn write_char_buffer(&self, buf: &[u8]) -> Result<usize> {
|
||||
// get string from u8[] and parse it to an c_str
|
||||
let utf8 = match str::from_utf8(buf) {
|
||||
Ok(string) => string,
|
||||
Err(_) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Could not parse to utf8 string",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let utf16: Vec<u16> = utf8.encode_utf16().collect();
|
||||
let utf16_ptr: *const c_void = utf16.as_ptr() as *const _ as *const c_void;
|
||||
|
||||
let mut cells_written: u32 = 0;
|
||||
|
||||
result(unsafe {
|
||||
WriteConsoleW(
|
||||
*self.handle,
|
||||
utf16_ptr,
|
||||
utf16.len() as u32,
|
||||
&mut cells_written,
|
||||
NULL,
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(utf8.as_bytes().len())
|
||||
}
|
||||
|
||||
/// Read one input event.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`ReadConsoleInputW`](https://docs.microsoft.com/en-us/windows/console/readconsoleinput).
|
||||
pub fn read_single_input_event(&self) -> Result<InputRecord> {
|
||||
let mut record: INPUT_RECORD = INPUT_RECORD::default();
|
||||
|
||||
{
|
||||
// Convert an INPUT_RECORD to an &mut [INPUT_RECORD] of length 1
|
||||
let buf = slice::from_mut(&mut record);
|
||||
let num_read = self.read_input(buf)?;
|
||||
|
||||
// The windows API promises that ReadConsoleInput returns at least
|
||||
// 1 element
|
||||
debug_assert!(num_read == 1);
|
||||
}
|
||||
|
||||
Ok(record.into())
|
||||
}
|
||||
|
||||
/// Read all available input events without blocking.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`ReadConsoleInputW`](https://docs.microsoft.com/en-us/windows/console/readconsoleinput).
|
||||
pub fn read_console_input(&self) -> Result<Vec<InputRecord>> {
|
||||
let buf_len = self.number_of_console_input_events()?;
|
||||
|
||||
// Fast-skipping all the code below if there is nothing to read at all
|
||||
if buf_len == 0 {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
|
||||
let mut buf: Vec<INPUT_RECORD> = iter::repeat_with(INPUT_RECORD::default)
|
||||
.take(buf_len as usize)
|
||||
.collect();
|
||||
|
||||
let num_read = self.read_input(buf.as_mut_slice())?;
|
||||
|
||||
Ok(buf
|
||||
.into_iter()
|
||||
.take(num_read)
|
||||
.map(InputRecord::from)
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// Get the number of available input events that can be read without blocking.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`GetNumberOfConsoleInputEvents`](https://docs.microsoft.com/en-us/windows/console/getnumberofconsoleinputevents).
|
||||
pub fn number_of_console_input_events(&self) -> Result<u32> {
|
||||
let mut buf_len: DWORD = 0;
|
||||
result(unsafe { GetNumberOfConsoleInputEvents(*self.handle, &mut buf_len) })?;
|
||||
Ok(buf_len)
|
||||
}
|
||||
|
||||
/// Read input (via ReadConsoleInputW) into buf and return the number
|
||||
/// of events read. ReadConsoleInputW guarantees that at least one event
|
||||
/// is read, even if it means blocking the thread. buf.len() must fit in
|
||||
/// a u32.
|
||||
fn read_input(&self, buf: &mut [INPUT_RECORD]) -> Result<usize> {
|
||||
let mut num_records = 0;
|
||||
debug_assert!(buf.len() < std::u32::MAX as usize);
|
||||
|
||||
result(unsafe {
|
||||
ReadConsoleInputW(
|
||||
*self.handle,
|
||||
buf.as_mut_ptr(),
|
||||
buf.len() as u32,
|
||||
&mut num_records,
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(num_records as usize)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Handle> for Console {
|
||||
/// Create a `Console` instance who's functions will be executed on the the given `Handle`
|
||||
fn from(handle: Handle) -> Self {
|
||||
Console { handle }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
150
vendor/crossterm_winapi/src/console_mode.rs
vendored
150
vendor/crossterm_winapi/src/console_mode.rs
vendored
|
|
@ -1,75 +1,75 @@
|
|||
use std::io::Result;
|
||||
|
||||
use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode};
|
||||
|
||||
use super::{result, Handle, HandleType};
|
||||
|
||||
/// A wrapper around a screen buffer, focusing on calls to get and set the console mode.
|
||||
///
|
||||
/// This wraps [`SetConsoleMode`](https://docs.microsoft.com/en-us/windows/console/setconsolemode)
|
||||
/// and [`GetConsoleMode`](https://docs.microsoft.com/en-us/windows/console/getconsolemode).
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ConsoleMode {
|
||||
// the handle used for the functions of this type.
|
||||
handle: Handle,
|
||||
}
|
||||
|
||||
impl ConsoleMode {
|
||||
/// Create a new `ConsoleMode` instance.
|
||||
///
|
||||
/// This will use the standard output as its handle.
|
||||
/// When you explicitly want to specify the handle used for the function calls use `ConsoleMode::from(handle)` instead.
|
||||
pub fn new() -> Result<ConsoleMode> {
|
||||
Ok(ConsoleMode {
|
||||
handle: Handle::new(HandleType::OutputHandle)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Set the console mode to the given console mode.
|
||||
///
|
||||
/// This function sets the `dwMode`.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`SetConsoleMode`](https://docs.microsoft.com/en-us/windows/console/setconsolemode).
|
||||
pub fn set_mode(&self, console_mode: u32) -> Result<()> {
|
||||
result(unsafe { SetConsoleMode(*self.handle, console_mode) })
|
||||
}
|
||||
|
||||
/// Get the console mode.
|
||||
///
|
||||
/// This function returns the `lpMode`.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`GetConsoleMode`](https://docs.microsoft.com/en-us/windows/console/getconsolemode).
|
||||
pub fn mode(&self) -> Result<u32> {
|
||||
let mut console_mode = 0;
|
||||
result(unsafe { GetConsoleMode(*self.handle, &mut console_mode) })?;
|
||||
Ok(console_mode)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Handle> for ConsoleMode {
|
||||
fn from(handle: Handle) -> Self {
|
||||
ConsoleMode { handle }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ConsoleMode;
|
||||
|
||||
// TODO - Test is ignored, because it's failing on Travis CI
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_set_get_mode() {
|
||||
let mode = ConsoleMode::new().unwrap();
|
||||
|
||||
let original_mode = mode.mode().unwrap();
|
||||
|
||||
mode.set_mode(0x0004).unwrap();
|
||||
let console_mode = mode.mode().unwrap();
|
||||
assert_eq!(console_mode & 0x0004, mode.mode().unwrap());
|
||||
|
||||
mode.set_mode(original_mode).unwrap();
|
||||
}
|
||||
}
|
||||
use std::io::Result;
|
||||
|
||||
use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode};
|
||||
|
||||
use super::{result, Handle, HandleType};
|
||||
|
||||
/// A wrapper around a screen buffer, focusing on calls to get and set the console mode.
|
||||
///
|
||||
/// This wraps [`SetConsoleMode`](https://docs.microsoft.com/en-us/windows/console/setconsolemode)
|
||||
/// and [`GetConsoleMode`](https://docs.microsoft.com/en-us/windows/console/getconsolemode).
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ConsoleMode {
|
||||
// the handle used for the functions of this type.
|
||||
handle: Handle,
|
||||
}
|
||||
|
||||
impl ConsoleMode {
|
||||
/// Create a new `ConsoleMode` instance.
|
||||
///
|
||||
/// This will use the standard output as its handle.
|
||||
/// When you explicitly want to specify the handle used for the function calls use `ConsoleMode::from(handle)` instead.
|
||||
pub fn new() -> Result<ConsoleMode> {
|
||||
Ok(ConsoleMode {
|
||||
handle: Handle::new(HandleType::OutputHandle)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Set the console mode to the given console mode.
|
||||
///
|
||||
/// This function sets the `dwMode`.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`SetConsoleMode`](https://docs.microsoft.com/en-us/windows/console/setconsolemode).
|
||||
pub fn set_mode(&self, console_mode: u32) -> Result<()> {
|
||||
result(unsafe { SetConsoleMode(*self.handle, console_mode) })
|
||||
}
|
||||
|
||||
/// Get the console mode.
|
||||
///
|
||||
/// This function returns the `lpMode`.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`GetConsoleMode`](https://docs.microsoft.com/en-us/windows/console/getconsolemode).
|
||||
pub fn mode(&self) -> Result<u32> {
|
||||
let mut console_mode = 0;
|
||||
result(unsafe { GetConsoleMode(*self.handle, &mut console_mode) })?;
|
||||
Ok(console_mode)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Handle> for ConsoleMode {
|
||||
fn from(handle: Handle) -> Self {
|
||||
ConsoleMode { handle }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ConsoleMode;
|
||||
|
||||
// TODO - Test is ignored, because it's failing on Travis CI
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_set_get_mode() {
|
||||
let mode = ConsoleMode::new().unwrap();
|
||||
|
||||
let original_mode = mode.mode().unwrap();
|
||||
|
||||
mode.set_mode(0x0004).unwrap();
|
||||
let console_mode = mode.mode().unwrap();
|
||||
assert_eq!(console_mode & 0x0004, mode.mode().unwrap());
|
||||
|
||||
mode.set_mode(original_mode).unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
164
vendor/crossterm_winapi/src/csbi.rs
vendored
164
vendor/crossterm_winapi/src/csbi.rs
vendored
|
|
@ -1,82 +1,82 @@
|
|||
use std::fmt;
|
||||
use std::mem::zeroed;
|
||||
|
||||
use winapi::um::wincon::CONSOLE_SCREEN_BUFFER_INFO;
|
||||
|
||||
use super::{Coord, Size, WindowPositions};
|
||||
|
||||
/// Information about a console screen buffer.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`CONSOLE_SCREEN_BUFFER_INFO`](https://docs.microsoft.com/en-us/windows/console/console-screen-buffer-info-str).
|
||||
// TODO: replace the innards of this type with our own, more friendly types, like Coord.
|
||||
// This will obviously be a breaking change.
|
||||
#[derive(Clone)]
|
||||
pub struct ScreenBufferInfo(pub CONSOLE_SCREEN_BUFFER_INFO);
|
||||
|
||||
// TODO: replace this with a derive ASAP
|
||||
impl fmt::Debug for ScreenBufferInfo {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("ScreenBufferInfo")
|
||||
.field("dwSize", &self.buffer_size())
|
||||
.field("dwCursorPosition", &self.cursor_pos())
|
||||
.field("wAttributes", &self.attributes()) // TODO: hex print this
|
||||
.field("srWindow", &self.terminal_window())
|
||||
.field(
|
||||
"dwMaximumWindowSize",
|
||||
&Size::from(self.0.dwMaximumWindowSize),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl ScreenBufferInfo {
|
||||
/// Create a new console screen buffer without all zeroed properties.
|
||||
pub fn new() -> ScreenBufferInfo {
|
||||
ScreenBufferInfo(unsafe { zeroed() })
|
||||
}
|
||||
|
||||
/// Get the size of the screen buffer.
|
||||
///
|
||||
/// Will take `dwSize` from the current screen buffer and convert it into a [`Size`].
|
||||
pub fn buffer_size(&self) -> Size {
|
||||
Size::from(self.0.dwSize)
|
||||
}
|
||||
|
||||
/// Get the size of the terminal display window.
|
||||
///
|
||||
/// Will calculate the width and height from `srWindow` and convert it into a [`Size`].
|
||||
pub fn terminal_size(&self) -> Size {
|
||||
Size::new(
|
||||
self.0.srWindow.Right - self.0.srWindow.Left,
|
||||
self.0.srWindow.Bottom - self.0.srWindow.Top,
|
||||
)
|
||||
}
|
||||
|
||||
/// Get the position and size of the terminal display window.
|
||||
///
|
||||
/// Will take `srWindow` and convert it into the `WindowPositions` type.
|
||||
pub fn terminal_window(&self) -> WindowPositions {
|
||||
WindowPositions::from(self.0)
|
||||
}
|
||||
|
||||
/// Get the current attributes of the characters that are being written to the console.
|
||||
///
|
||||
/// Will take `wAttributes` from the current screen buffer.
|
||||
pub fn attributes(&self) -> u16 {
|
||||
self.0.wAttributes
|
||||
}
|
||||
|
||||
/// Get the current column and row of the terminal cursor in the screen buffer.
|
||||
///
|
||||
/// Will take `dwCursorPosition` from the current screen buffer.
|
||||
pub fn cursor_pos(&self) -> Coord {
|
||||
Coord::from(self.0.dwCursorPosition)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CONSOLE_SCREEN_BUFFER_INFO> for ScreenBufferInfo {
|
||||
fn from(csbi: CONSOLE_SCREEN_BUFFER_INFO) -> Self {
|
||||
ScreenBufferInfo(csbi)
|
||||
}
|
||||
}
|
||||
use std::fmt;
|
||||
use std::mem::zeroed;
|
||||
|
||||
use winapi::um::wincon::CONSOLE_SCREEN_BUFFER_INFO;
|
||||
|
||||
use super::{Coord, Size, WindowPositions};
|
||||
|
||||
/// Information about a console screen buffer.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`CONSOLE_SCREEN_BUFFER_INFO`](https://docs.microsoft.com/en-us/windows/console/console-screen-buffer-info-str).
|
||||
// TODO: replace the innards of this type with our own, more friendly types, like Coord.
|
||||
// This will obviously be a breaking change.
|
||||
#[derive(Clone)]
|
||||
pub struct ScreenBufferInfo(pub CONSOLE_SCREEN_BUFFER_INFO);
|
||||
|
||||
// TODO: replace this with a derive ASAP
|
||||
impl fmt::Debug for ScreenBufferInfo {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("ScreenBufferInfo")
|
||||
.field("dwSize", &self.buffer_size())
|
||||
.field("dwCursorPosition", &self.cursor_pos())
|
||||
.field("wAttributes", &self.attributes()) // TODO: hex print this
|
||||
.field("srWindow", &self.terminal_window())
|
||||
.field(
|
||||
"dwMaximumWindowSize",
|
||||
&Size::from(self.0.dwMaximumWindowSize),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl ScreenBufferInfo {
|
||||
/// Create a new console screen buffer without all zeroed properties.
|
||||
pub fn new() -> ScreenBufferInfo {
|
||||
ScreenBufferInfo(unsafe { zeroed() })
|
||||
}
|
||||
|
||||
/// Get the size of the screen buffer.
|
||||
///
|
||||
/// Will take `dwSize` from the current screen buffer and convert it into a [`Size`].
|
||||
pub fn buffer_size(&self) -> Size {
|
||||
Size::from(self.0.dwSize)
|
||||
}
|
||||
|
||||
/// Get the size of the terminal display window.
|
||||
///
|
||||
/// Will calculate the width and height from `srWindow` and convert it into a [`Size`].
|
||||
pub fn terminal_size(&self) -> Size {
|
||||
Size::new(
|
||||
self.0.srWindow.Right - self.0.srWindow.Left,
|
||||
self.0.srWindow.Bottom - self.0.srWindow.Top,
|
||||
)
|
||||
}
|
||||
|
||||
/// Get the position and size of the terminal display window.
|
||||
///
|
||||
/// Will take `srWindow` and convert it into the `WindowPositions` type.
|
||||
pub fn terminal_window(&self) -> WindowPositions {
|
||||
WindowPositions::from(self.0)
|
||||
}
|
||||
|
||||
/// Get the current attributes of the characters that are being written to the console.
|
||||
///
|
||||
/// Will take `wAttributes` from the current screen buffer.
|
||||
pub fn attributes(&self) -> u16 {
|
||||
self.0.wAttributes
|
||||
}
|
||||
|
||||
/// Get the current column and row of the terminal cursor in the screen buffer.
|
||||
///
|
||||
/// Will take `dwCursorPosition` from the current screen buffer.
|
||||
pub fn cursor_pos(&self) -> Coord {
|
||||
Coord::from(self.0.dwCursorPosition)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CONSOLE_SCREEN_BUFFER_INFO> for ScreenBufferInfo {
|
||||
fn from(csbi: CONSOLE_SCREEN_BUFFER_INFO) -> Self {
|
||||
ScreenBufferInfo(csbi)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
438
vendor/crossterm_winapi/src/handle.rs
vendored
438
vendor/crossterm_winapi/src/handle.rs
vendored
|
|
@ -1,219 +1,219 @@
|
|||
//! This module contains some logic for working with the console handle.
|
||||
|
||||
use std::io::Result;
|
||||
use std::ops::Deref;
|
||||
use std::ptr::null_mut;
|
||||
use std::sync::Arc;
|
||||
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::um::{
|
||||
fileapi::{CreateFileW, OPEN_EXISTING},
|
||||
handleapi::{CloseHandle, INVALID_HANDLE_VALUE},
|
||||
processenv::GetStdHandle,
|
||||
winbase::{STD_INPUT_HANDLE, STD_OUTPUT_HANDLE},
|
||||
winnt::{FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE, HANDLE},
|
||||
};
|
||||
|
||||
use super::handle_result;
|
||||
|
||||
/// The standard handles of a process.
|
||||
///
|
||||
/// See [the Windows documentation on console
|
||||
/// handles](https://docs.microsoft.com/en-us/windows/console/console-handles) for more info.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum HandleType {
|
||||
/// The process' standard output.
|
||||
OutputHandle,
|
||||
/// The process' standard input.
|
||||
InputHandle,
|
||||
/// The process' active console screen buffer, `CONOUT$`.
|
||||
CurrentOutputHandle,
|
||||
/// The process' console input buffer, `CONIN$`.
|
||||
CurrentInputHandle,
|
||||
}
|
||||
|
||||
/// Inner structure for closing a handle on Drop.
|
||||
///
|
||||
/// The second parameter indicates if the HANDLE is exclusively owned or not.
|
||||
/// A non-exclusive handle can be created using for example
|
||||
/// `Handle::input_handle` or `Handle::output_handle`, which corresponds to
|
||||
/// stdin and stdout respectively.
|
||||
#[derive(Debug)]
|
||||
struct Inner {
|
||||
handle: HANDLE,
|
||||
is_exclusive: bool,
|
||||
}
|
||||
|
||||
impl Inner {
|
||||
fn new_exclusive(handle: HANDLE) -> Self {
|
||||
Inner {
|
||||
handle,
|
||||
is_exclusive: true,
|
||||
}
|
||||
}
|
||||
|
||||
fn new_shared(handle: HANDLE) -> Self {
|
||||
Inner {
|
||||
handle,
|
||||
is_exclusive: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Inner {
|
||||
fn drop(&mut self) {
|
||||
if self.is_exclusive {
|
||||
assert!(
|
||||
unsafe { CloseHandle(self.handle) != 0 },
|
||||
"failed to close handle"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for Inner {}
|
||||
|
||||
unsafe impl Sync for Inner {}
|
||||
|
||||
/// This abstracts away some WinAPI calls to set and get some console handles.
|
||||
///
|
||||
/// It wraps WinAPI's [`HANDLE`] type.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Handle {
|
||||
handle: Arc<Inner>,
|
||||
}
|
||||
|
||||
impl Handle {
|
||||
/// Create a new handle of a certaint type.
|
||||
pub fn new(handle: HandleType) -> Result<Handle> {
|
||||
match handle {
|
||||
HandleType::OutputHandle => Handle::output_handle(),
|
||||
HandleType::InputHandle => Handle::input_handle(),
|
||||
HandleType::CurrentOutputHandle => Handle::current_out_handle(),
|
||||
HandleType::CurrentInputHandle => Handle::current_in_handle(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a handle from a raw handle.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This is unsafe since there is not guarantee that the underlying HANDLE is thread-safe to implement `Send` and `Sync`.
|
||||
/// Most HANDLE's however, are thread safe.
|
||||
pub unsafe fn from_raw(handle: HANDLE) -> Self {
|
||||
Self {
|
||||
handle: Arc::new(Inner::new_exclusive(handle)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the handle of the active screen buffer.
|
||||
/// When using multiple screen buffers this will always point to the to the current screen output buffer.
|
||||
///
|
||||
/// This function uses `CONOUT$` to create a file handle to the current output buffer.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`CreateFileW`](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew).
|
||||
pub fn current_out_handle() -> Result<Handle> {
|
||||
let utf16: Vec<u16> = "CONOUT$\0".encode_utf16().collect();
|
||||
let utf16_ptr: *const u16 = utf16.as_ptr();
|
||||
|
||||
let handle = handle_result(unsafe {
|
||||
CreateFileW(
|
||||
utf16_ptr,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
null_mut(),
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
null_mut(),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(Handle {
|
||||
handle: Arc::new(Inner::new_exclusive(handle)),
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the handle of the console input buffer.
|
||||
///
|
||||
/// This function uses `CONIN$` to create a file handle to the current input buffer.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`CreateFileW`](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew).
|
||||
pub fn current_in_handle() -> Result<Handle> {
|
||||
let utf16: Vec<u16> = "CONIN$\0".encode_utf16().collect();
|
||||
let utf16_ptr: *const u16 = utf16.as_ptr();
|
||||
|
||||
let handle = handle_result(unsafe {
|
||||
CreateFileW(
|
||||
utf16_ptr,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
null_mut(),
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
null_mut(),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(Handle {
|
||||
handle: Arc::new(Inner::new_exclusive(handle)),
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the handle of the standard output.
|
||||
///
|
||||
/// On success this function returns the `HANDLE` to `STD_OUTPUT_HANDLE`.
|
||||
///
|
||||
/// This wraps [`GetStdHandle`](https://docs.microsoft.com/en-us/windows/console/getstdhandle)
|
||||
/// called with `STD_OUTPUT_HANDLE`.
|
||||
pub fn output_handle() -> Result<Handle> {
|
||||
Self::std_handle(STD_OUTPUT_HANDLE)
|
||||
}
|
||||
|
||||
/// Get the handle of the input screen buffer.
|
||||
///
|
||||
/// On success this function returns the `HANDLE` to `STD_INPUT_HANDLE`.
|
||||
///
|
||||
/// This wraps [`GetStdHandle`](https://docs.microsoft.com/en-us/windows/console/getstdhandle)
|
||||
/// called with `STD_INPUT_HANDLE`.
|
||||
pub fn input_handle() -> Result<Handle> {
|
||||
Self::std_handle(STD_INPUT_HANDLE)
|
||||
}
|
||||
|
||||
fn std_handle(which_std: DWORD) -> Result<Handle> {
|
||||
let handle = handle_result(unsafe { GetStdHandle(which_std) })?;
|
||||
|
||||
Ok(Handle {
|
||||
handle: Arc::new(Inner::new_shared(handle)),
|
||||
})
|
||||
}
|
||||
|
||||
/// Checks if the console handle is an invalid handle value.
|
||||
///
|
||||
/// This is done by checking if the passed `HANDLE` is equal to `INVALID_HANDLE_VALUE`.
|
||||
pub fn is_valid_handle(handle: &HANDLE) -> bool {
|
||||
*handle != INVALID_HANDLE_VALUE
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Handle {
|
||||
type Target = HANDLE;
|
||||
|
||||
fn deref(&self) -> &HANDLE {
|
||||
&self.handle.handle
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Handle, HandleType};
|
||||
|
||||
#[test]
|
||||
fn test_get_handle() {
|
||||
assert!(Handle::new(HandleType::OutputHandle).is_ok());
|
||||
assert!(Handle::new(HandleType::InputHandle).is_ok());
|
||||
assert!(Handle::new(HandleType::CurrentOutputHandle).is_ok());
|
||||
assert!(Handle::new(HandleType::CurrentInputHandle).is_ok());
|
||||
}
|
||||
}
|
||||
//! This module contains some logic for working with the console handle.
|
||||
|
||||
use std::io::Result;
|
||||
use std::ops::Deref;
|
||||
use std::ptr::null_mut;
|
||||
use std::sync::Arc;
|
||||
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::um::{
|
||||
fileapi::{CreateFileW, OPEN_EXISTING},
|
||||
handleapi::{CloseHandle, INVALID_HANDLE_VALUE},
|
||||
processenv::GetStdHandle,
|
||||
winbase::{STD_INPUT_HANDLE, STD_OUTPUT_HANDLE},
|
||||
winnt::{FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE, HANDLE},
|
||||
};
|
||||
|
||||
use super::handle_result;
|
||||
|
||||
/// The standard handles of a process.
|
||||
///
|
||||
/// See [the Windows documentation on console
|
||||
/// handles](https://docs.microsoft.com/en-us/windows/console/console-handles) for more info.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum HandleType {
|
||||
/// The process' standard output.
|
||||
OutputHandle,
|
||||
/// The process' standard input.
|
||||
InputHandle,
|
||||
/// The process' active console screen buffer, `CONOUT$`.
|
||||
CurrentOutputHandle,
|
||||
/// The process' console input buffer, `CONIN$`.
|
||||
CurrentInputHandle,
|
||||
}
|
||||
|
||||
/// Inner structure for closing a handle on Drop.
|
||||
///
|
||||
/// The second parameter indicates if the HANDLE is exclusively owned or not.
|
||||
/// A non-exclusive handle can be created using for example
|
||||
/// `Handle::input_handle` or `Handle::output_handle`, which corresponds to
|
||||
/// stdin and stdout respectively.
|
||||
#[derive(Debug)]
|
||||
struct Inner {
|
||||
handle: HANDLE,
|
||||
is_exclusive: bool,
|
||||
}
|
||||
|
||||
impl Inner {
|
||||
fn new_exclusive(handle: HANDLE) -> Self {
|
||||
Inner {
|
||||
handle,
|
||||
is_exclusive: true,
|
||||
}
|
||||
}
|
||||
|
||||
fn new_shared(handle: HANDLE) -> Self {
|
||||
Inner {
|
||||
handle,
|
||||
is_exclusive: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Inner {
|
||||
fn drop(&mut self) {
|
||||
if self.is_exclusive {
|
||||
assert!(
|
||||
unsafe { CloseHandle(self.handle) != 0 },
|
||||
"failed to close handle"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for Inner {}
|
||||
|
||||
unsafe impl Sync for Inner {}
|
||||
|
||||
/// This abstracts away some WinAPI calls to set and get some console handles.
|
||||
///
|
||||
/// It wraps WinAPI's [`HANDLE`] type.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Handle {
|
||||
handle: Arc<Inner>,
|
||||
}
|
||||
|
||||
impl Handle {
|
||||
/// Create a new handle of a certaint type.
|
||||
pub fn new(handle: HandleType) -> Result<Handle> {
|
||||
match handle {
|
||||
HandleType::OutputHandle => Handle::output_handle(),
|
||||
HandleType::InputHandle => Handle::input_handle(),
|
||||
HandleType::CurrentOutputHandle => Handle::current_out_handle(),
|
||||
HandleType::CurrentInputHandle => Handle::current_in_handle(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a handle from a raw handle.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This is unsafe since there is not guarantee that the underlying HANDLE is thread-safe to implement `Send` and `Sync`.
|
||||
/// Most HANDLE's however, are thread safe.
|
||||
pub unsafe fn from_raw(handle: HANDLE) -> Self {
|
||||
Self {
|
||||
handle: Arc::new(Inner::new_exclusive(handle)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the handle of the active screen buffer.
|
||||
/// When using multiple screen buffers this will always point to the to the current screen output buffer.
|
||||
///
|
||||
/// This function uses `CONOUT$` to create a file handle to the current output buffer.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`CreateFileW`](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew).
|
||||
pub fn current_out_handle() -> Result<Handle> {
|
||||
let utf16: Vec<u16> = "CONOUT$\0".encode_utf16().collect();
|
||||
let utf16_ptr: *const u16 = utf16.as_ptr();
|
||||
|
||||
let handle = handle_result(unsafe {
|
||||
CreateFileW(
|
||||
utf16_ptr,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
null_mut(),
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
null_mut(),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(Handle {
|
||||
handle: Arc::new(Inner::new_exclusive(handle)),
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the handle of the console input buffer.
|
||||
///
|
||||
/// This function uses `CONIN$` to create a file handle to the current input buffer.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`CreateFileW`](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew).
|
||||
pub fn current_in_handle() -> Result<Handle> {
|
||||
let utf16: Vec<u16> = "CONIN$\0".encode_utf16().collect();
|
||||
let utf16_ptr: *const u16 = utf16.as_ptr();
|
||||
|
||||
let handle = handle_result(unsafe {
|
||||
CreateFileW(
|
||||
utf16_ptr,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
null_mut(),
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
null_mut(),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(Handle {
|
||||
handle: Arc::new(Inner::new_exclusive(handle)),
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the handle of the standard output.
|
||||
///
|
||||
/// On success this function returns the `HANDLE` to `STD_OUTPUT_HANDLE`.
|
||||
///
|
||||
/// This wraps [`GetStdHandle`](https://docs.microsoft.com/en-us/windows/console/getstdhandle)
|
||||
/// called with `STD_OUTPUT_HANDLE`.
|
||||
pub fn output_handle() -> Result<Handle> {
|
||||
Self::std_handle(STD_OUTPUT_HANDLE)
|
||||
}
|
||||
|
||||
/// Get the handle of the input screen buffer.
|
||||
///
|
||||
/// On success this function returns the `HANDLE` to `STD_INPUT_HANDLE`.
|
||||
///
|
||||
/// This wraps [`GetStdHandle`](https://docs.microsoft.com/en-us/windows/console/getstdhandle)
|
||||
/// called with `STD_INPUT_HANDLE`.
|
||||
pub fn input_handle() -> Result<Handle> {
|
||||
Self::std_handle(STD_INPUT_HANDLE)
|
||||
}
|
||||
|
||||
fn std_handle(which_std: DWORD) -> Result<Handle> {
|
||||
let handle = handle_result(unsafe { GetStdHandle(which_std) })?;
|
||||
|
||||
Ok(Handle {
|
||||
handle: Arc::new(Inner::new_shared(handle)),
|
||||
})
|
||||
}
|
||||
|
||||
/// Checks if the console handle is an invalid handle value.
|
||||
///
|
||||
/// This is done by checking if the passed `HANDLE` is equal to `INVALID_HANDLE_VALUE`.
|
||||
pub fn is_valid_handle(handle: &HANDLE) -> bool {
|
||||
*handle != INVALID_HANDLE_VALUE
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Handle {
|
||||
type Target = HANDLE;
|
||||
|
||||
fn deref(&self) -> &HANDLE {
|
||||
&self.handle.handle
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Handle, HandleType};
|
||||
|
||||
#[test]
|
||||
fn test_get_handle() {
|
||||
assert!(Handle::new(HandleType::OutputHandle).is_ok());
|
||||
assert!(Handle::new(HandleType::InputHandle).is_ok());
|
||||
assert!(Handle::new(HandleType::CurrentOutputHandle).is_ok());
|
||||
assert!(Handle::new(HandleType::CurrentInputHandle).is_ok());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
142
vendor/crossterm_winapi/src/lib.rs
vendored
142
vendor/crossterm_winapi/src/lib.rs
vendored
|
|
@ -1,71 +1,71 @@
|
|||
#![cfg(windows)]
|
||||
#![deny(unused_imports)]
|
||||
|
||||
use std::io;
|
||||
|
||||
use winapi::shared::minwindef::BOOL;
|
||||
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
|
||||
use winapi::um::wincontypes::COORD;
|
||||
use winapi::um::winnt::HANDLE;
|
||||
|
||||
pub use self::{
|
||||
console::Console,
|
||||
console_mode::ConsoleMode,
|
||||
csbi::ScreenBufferInfo,
|
||||
handle::{Handle, HandleType},
|
||||
screen_buffer::ScreenBuffer,
|
||||
semaphore::Semaphore,
|
||||
structs::{
|
||||
ButtonState, ControlKeyState, Coord, EventFlags, InputRecord, KeyEventRecord, MouseEvent,
|
||||
Size, WindowPositions,
|
||||
},
|
||||
};
|
||||
|
||||
mod console;
|
||||
mod console_mode;
|
||||
mod csbi;
|
||||
mod handle;
|
||||
mod screen_buffer;
|
||||
mod semaphore;
|
||||
mod structs;
|
||||
|
||||
/// Get the result of a call to WinAPI as an [`io::Result`].
|
||||
#[inline]
|
||||
pub fn result(return_value: BOOL) -> io::Result<()> {
|
||||
if return_value != 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the result of a call to WinAPI that returns a
|
||||
/// [`COORD`](https://docs.microsoft.com/en-us/windows/console/coord-str) as an [`io::Result`].
|
||||
#[inline]
|
||||
pub fn coord_result(return_value: COORD) -> io::Result<Coord> {
|
||||
if return_value.X != 0 && return_value.Y != 0 {
|
||||
Ok(Coord::from(return_value))
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the result of a call to WinAPI that returns a handle or `INVALID_HANDLE_VALUE`.
|
||||
#[inline]
|
||||
pub fn handle_result(return_value: HANDLE) -> io::Result<HANDLE> {
|
||||
if return_value != INVALID_HANDLE_VALUE {
|
||||
Ok(return_value)
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the result of a call to WinAPI that returns a handle or `NULL`.
|
||||
#[inline]
|
||||
pub fn nonnull_handle_result(return_value: HANDLE) -> io::Result<HANDLE> {
|
||||
if return_value.is_null() {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(return_value)
|
||||
}
|
||||
}
|
||||
#![cfg(windows)]
|
||||
#![deny(unused_imports)]
|
||||
|
||||
use std::io;
|
||||
|
||||
use winapi::shared::minwindef::BOOL;
|
||||
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
|
||||
use winapi::um::wincontypes::COORD;
|
||||
use winapi::um::winnt::HANDLE;
|
||||
|
||||
pub use self::{
|
||||
console::Console,
|
||||
console_mode::ConsoleMode,
|
||||
csbi::ScreenBufferInfo,
|
||||
handle::{Handle, HandleType},
|
||||
screen_buffer::ScreenBuffer,
|
||||
semaphore::Semaphore,
|
||||
structs::{
|
||||
ButtonState, ControlKeyState, Coord, EventFlags, InputRecord, KeyEventRecord, MouseEvent,
|
||||
Size, WindowPositions,
|
||||
},
|
||||
};
|
||||
|
||||
mod console;
|
||||
mod console_mode;
|
||||
mod csbi;
|
||||
mod handle;
|
||||
mod screen_buffer;
|
||||
mod semaphore;
|
||||
mod structs;
|
||||
|
||||
/// Get the result of a call to WinAPI as an [`io::Result`].
|
||||
#[inline]
|
||||
pub fn result(return_value: BOOL) -> io::Result<()> {
|
||||
if return_value != 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the result of a call to WinAPI that returns a
|
||||
/// [`COORD`](https://docs.microsoft.com/en-us/windows/console/coord-str) as an [`io::Result`].
|
||||
#[inline]
|
||||
pub fn coord_result(return_value: COORD) -> io::Result<Coord> {
|
||||
if return_value.X != 0 && return_value.Y != 0 {
|
||||
Ok(Coord::from(return_value))
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the result of a call to WinAPI that returns a handle or `INVALID_HANDLE_VALUE`.
|
||||
#[inline]
|
||||
pub fn handle_result(return_value: HANDLE) -> io::Result<HANDLE> {
|
||||
if return_value != INVALID_HANDLE_VALUE {
|
||||
Ok(return_value)
|
||||
} else {
|
||||
Err(io::Error::last_os_error())
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the result of a call to WinAPI that returns a handle or `NULL`.
|
||||
#[inline]
|
||||
pub fn nonnull_handle_result(return_value: HANDLE) -> io::Result<HANDLE> {
|
||||
if return_value.is_null() {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(return_value)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
234
vendor/crossterm_winapi/src/screen_buffer.rs
vendored
234
vendor/crossterm_winapi/src/screen_buffer.rs
vendored
|
|
@ -1,117 +1,117 @@
|
|||
//! This contains the logic for working with the console buffer.
|
||||
|
||||
use std::io::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::{handle_result, result, Handle, HandleType, ScreenBufferInfo};
|
||||
|
||||
/// A wrapper around a screen buffer.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ScreenBuffer {
|
||||
handle: Handle,
|
||||
}
|
||||
|
||||
impl ScreenBuffer {
|
||||
/// Create a wrapper around a screen buffer from its handle.
|
||||
pub fn new(handle: Handle) -> Self {
|
||||
Self { handle }
|
||||
}
|
||||
|
||||
/// Get the current console screen buffer
|
||||
pub fn current() -> Result<ScreenBuffer> {
|
||||
Ok(ScreenBuffer {
|
||||
handle: Handle::new(HandleType::CurrentOutputHandle)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Create new console screen buffer.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`CreateConsoleScreenBuffer`](https://docs.microsoft.com/en-us/windows/console/createconsolescreenbuffer)
|
||||
pub fn create() -> Result<ScreenBuffer> {
|
||||
let security_attr: SECURITY_ATTRIBUTES = SECURITY_ATTRIBUTES {
|
||||
nLength: size_of::<SECURITY_ATTRIBUTES>() as u32,
|
||||
lpSecurityDescriptor: NULL,
|
||||
bInheritHandle: TRUE,
|
||||
};
|
||||
|
||||
let new_screen_buffer = handle_result(unsafe {
|
||||
CreateConsoleScreenBuffer(
|
||||
GENERIC_READ | // read/write access
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, // shared
|
||||
&security_attr, // default security attributes
|
||||
CONSOLE_TEXTMODE_BUFFER, // must be TEXTMODE
|
||||
NULL,
|
||||
)
|
||||
})?;
|
||||
Ok(ScreenBuffer {
|
||||
handle: unsafe { Handle::from_raw(new_screen_buffer) },
|
||||
})
|
||||
}
|
||||
|
||||
/// Set this screen buffer to the current one.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`SetConsoleActiveScreenBuffer`](https://docs.microsoft.com/en-us/windows/console/setconsoleactivescreenbuffer).
|
||||
pub fn show(&self) -> Result<()> {
|
||||
result(unsafe { SetConsoleActiveScreenBuffer(*self.handle) })
|
||||
}
|
||||
|
||||
/// Get the screen buffer information like terminal size, cursor position, buffer size.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`GetConsoleScreenBufferInfo`](https://docs.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo).
|
||||
pub fn info(&self) -> Result<ScreenBufferInfo> {
|
||||
let mut csbi = ScreenBufferInfo::new();
|
||||
result(unsafe { GetConsoleScreenBufferInfo(*self.handle, &mut csbi.0) })?;
|
||||
Ok(csbi)
|
||||
}
|
||||
|
||||
/// Set the console screen buffer size to the given size.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`SetConsoleScreenBufferSize`](https://docs.microsoft.com/en-us/windows/console/setconsolescreenbuffersize).
|
||||
pub fn set_size(&self, x: i16, y: i16) -> Result<()> {
|
||||
result(unsafe { SetConsoleScreenBufferSize(*self.handle, COORD { X: x, Y: y }) })
|
||||
}
|
||||
|
||||
/// Get the underlying raw `HANDLE` used by this type to execute with.
|
||||
pub fn handle(&self) -> &Handle {
|
||||
&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();
|
||||
}
|
||||
}
|
||||
//! This contains the logic for working with the console buffer.
|
||||
|
||||
use std::io::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::{handle_result, result, Handle, HandleType, ScreenBufferInfo};
|
||||
|
||||
/// A wrapper around a screen buffer.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ScreenBuffer {
|
||||
handle: Handle,
|
||||
}
|
||||
|
||||
impl ScreenBuffer {
|
||||
/// Create a wrapper around a screen buffer from its handle.
|
||||
pub fn new(handle: Handle) -> Self {
|
||||
Self { handle }
|
||||
}
|
||||
|
||||
/// Get the current console screen buffer
|
||||
pub fn current() -> Result<ScreenBuffer> {
|
||||
Ok(ScreenBuffer {
|
||||
handle: Handle::new(HandleType::CurrentOutputHandle)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Create new console screen buffer.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`CreateConsoleScreenBuffer`](https://docs.microsoft.com/en-us/windows/console/createconsolescreenbuffer)
|
||||
pub fn create() -> Result<ScreenBuffer> {
|
||||
let security_attr: SECURITY_ATTRIBUTES = SECURITY_ATTRIBUTES {
|
||||
nLength: size_of::<SECURITY_ATTRIBUTES>() as u32,
|
||||
lpSecurityDescriptor: NULL,
|
||||
bInheritHandle: TRUE,
|
||||
};
|
||||
|
||||
let new_screen_buffer = handle_result(unsafe {
|
||||
CreateConsoleScreenBuffer(
|
||||
GENERIC_READ | // read/write access
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, // shared
|
||||
&security_attr, // default security attributes
|
||||
CONSOLE_TEXTMODE_BUFFER, // must be TEXTMODE
|
||||
NULL,
|
||||
)
|
||||
})?;
|
||||
Ok(ScreenBuffer {
|
||||
handle: unsafe { Handle::from_raw(new_screen_buffer) },
|
||||
})
|
||||
}
|
||||
|
||||
/// Set this screen buffer to the current one.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`SetConsoleActiveScreenBuffer`](https://docs.microsoft.com/en-us/windows/console/setconsoleactivescreenbuffer).
|
||||
pub fn show(&self) -> Result<()> {
|
||||
result(unsafe { SetConsoleActiveScreenBuffer(*self.handle) })
|
||||
}
|
||||
|
||||
/// Get the screen buffer information like terminal size, cursor position, buffer size.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`GetConsoleScreenBufferInfo`](https://docs.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo).
|
||||
pub fn info(&self) -> Result<ScreenBufferInfo> {
|
||||
let mut csbi = ScreenBufferInfo::new();
|
||||
result(unsafe { GetConsoleScreenBufferInfo(*self.handle, &mut csbi.0) })?;
|
||||
Ok(csbi)
|
||||
}
|
||||
|
||||
/// Set the console screen buffer size to the given size.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`SetConsoleScreenBufferSize`](https://docs.microsoft.com/en-us/windows/console/setconsolescreenbuffersize).
|
||||
pub fn set_size(&self, x: i16, y: i16) -> Result<()> {
|
||||
result(unsafe { SetConsoleScreenBufferSize(*self.handle, COORD { X: x, Y: y }) })
|
||||
}
|
||||
|
||||
/// Get the underlying raw `HANDLE` used by this type to execute with.
|
||||
pub fn handle(&self) -> &Handle {
|
||||
&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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
82
vendor/crossterm_winapi/src/semaphore.rs
vendored
82
vendor/crossterm_winapi/src/semaphore.rs
vendored
|
|
@ -1,41 +1,41 @@
|
|||
use std::{io, ptr};
|
||||
|
||||
use winapi::um::synchapi::{CreateSemaphoreW, ReleaseSemaphore};
|
||||
|
||||
use crate::{nonnull_handle_result, result, Handle};
|
||||
|
||||
/// A [Windows semaphore](https://docs.microsoft.com/en-us/windows/win32/sync/semaphore-objects).
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Semaphore(Handle);
|
||||
|
||||
impl Semaphore {
|
||||
/// Construct a new semaphore.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`CreateSemaphoreW`](https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createsemaphorew).
|
||||
pub fn new() -> io::Result<Self> {
|
||||
let handle = nonnull_handle_result(unsafe {
|
||||
CreateSemaphoreW(ptr::null_mut(), 0, 1, ptr::null_mut())
|
||||
})?;
|
||||
|
||||
let handle = unsafe { Handle::from_raw(handle) };
|
||||
Ok(Self(handle))
|
||||
}
|
||||
|
||||
/// Release a permit on the semaphore.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`ReleaseSemaphore`](https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-releasesemaphore).
|
||||
pub fn release(&self) -> io::Result<()> {
|
||||
result(unsafe { ReleaseSemaphore(*self.0, 1, ptr::null_mut()) })
|
||||
}
|
||||
|
||||
/// Access the underlying handle to the semaphore.
|
||||
pub fn handle(&self) -> &Handle {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for Semaphore {}
|
||||
|
||||
unsafe impl Sync for Semaphore {}
|
||||
use std::{io, ptr};
|
||||
|
||||
use winapi::um::synchapi::{CreateSemaphoreW, ReleaseSemaphore};
|
||||
|
||||
use crate::{nonnull_handle_result, result, Handle};
|
||||
|
||||
/// A [Windows semaphore](https://docs.microsoft.com/en-us/windows/win32/sync/semaphore-objects).
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Semaphore(Handle);
|
||||
|
||||
impl Semaphore {
|
||||
/// Construct a new semaphore.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`CreateSemaphoreW`](https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createsemaphorew).
|
||||
pub fn new() -> io::Result<Self> {
|
||||
let handle = nonnull_handle_result(unsafe {
|
||||
CreateSemaphoreW(ptr::null_mut(), 0, 1, ptr::null_mut())
|
||||
})?;
|
||||
|
||||
let handle = unsafe { Handle::from_raw(handle) };
|
||||
Ok(Self(handle))
|
||||
}
|
||||
|
||||
/// Release a permit on the semaphore.
|
||||
///
|
||||
/// This wraps
|
||||
/// [`ReleaseSemaphore`](https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-releasesemaphore).
|
||||
pub fn release(&self) -> io::Result<()> {
|
||||
result(unsafe { ReleaseSemaphore(*self.0, 1, ptr::null_mut()) })
|
||||
}
|
||||
|
||||
/// Access the underlying handle to the semaphore.
|
||||
pub fn handle(&self) -> &Handle {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for Semaphore {}
|
||||
|
||||
unsafe impl Sync for Semaphore {}
|
||||
|
|
|
|||
22
vendor/crossterm_winapi/src/structs.rs
vendored
22
vendor/crossterm_winapi/src/structs.rs
vendored
|
|
@ -1,11 +1,11 @@
|
|||
pub use self::coord::Coord;
|
||||
pub use self::input::{
|
||||
ButtonState, ControlKeyState, EventFlags, InputRecord, KeyEventRecord, MouseEvent,
|
||||
};
|
||||
pub use self::size::Size;
|
||||
pub use self::window_coords::WindowPositions;
|
||||
|
||||
mod coord;
|
||||
mod input;
|
||||
mod size;
|
||||
mod window_coords;
|
||||
pub use self::coord::Coord;
|
||||
pub use self::input::{
|
||||
ButtonState, ControlKeyState, EventFlags, InputRecord, KeyEventRecord, MouseEvent,
|
||||
};
|
||||
pub use self::size::Size;
|
||||
pub use self::window_coords::WindowPositions;
|
||||
|
||||
mod coord;
|
||||
mod input;
|
||||
mod size;
|
||||
mod window_coords;
|
||||
|
|
|
|||
84
vendor/crossterm_winapi/src/structs/coord.rs
vendored
84
vendor/crossterm_winapi/src/structs/coord.rs
vendored
|
|
@ -1,42 +1,42 @@
|
|||
//! This module provides a type that represents some location/coordination.
|
||||
//! For example, in WinAPI we have `COORD` which looks and feels inconvenient.
|
||||
//! This module provides also some trait implementations who will make parsing and working with `COORD` easier.
|
||||
|
||||
use winapi::um::wincon::COORD;
|
||||
|
||||
/// This is type represents the position of something on a certain 'x' and 'y'.
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd)]
|
||||
pub struct Coord {
|
||||
/// the position on the x axis
|
||||
pub x: i16,
|
||||
/// the position on the y axis
|
||||
pub y: i16,
|
||||
}
|
||||
|
||||
impl Coord {
|
||||
/// Create a new coordinate from its x and y position.
|
||||
pub fn new(x: i16, y: i16) -> Coord {
|
||||
Coord { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<COORD> for Coord {
|
||||
fn from(coord: COORD) -> Self {
|
||||
Coord::new(coord.X, coord.Y)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Coord> for COORD {
|
||||
fn from(location: Coord) -> Self {
|
||||
COORD {
|
||||
X: location.x,
|
||||
Y: location.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<(u16, u16)> for Coord {
|
||||
fn into(self) -> (u16, u16) {
|
||||
(self.x as u16, self.y as u16)
|
||||
}
|
||||
}
|
||||
//! This module provides a type that represents some location/coordination.
|
||||
//! For example, in WinAPI we have `COORD` which looks and feels inconvenient.
|
||||
//! This module provides also some trait implementations who will make parsing and working with `COORD` easier.
|
||||
|
||||
use winapi::um::wincon::COORD;
|
||||
|
||||
/// This is type represents the position of something on a certain 'x' and 'y'.
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd)]
|
||||
pub struct Coord {
|
||||
/// the position on the x axis
|
||||
pub x: i16,
|
||||
/// the position on the y axis
|
||||
pub y: i16,
|
||||
}
|
||||
|
||||
impl Coord {
|
||||
/// Create a new coordinate from its x and y position.
|
||||
pub fn new(x: i16, y: i16) -> Coord {
|
||||
Coord { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<COORD> for Coord {
|
||||
fn from(coord: COORD) -> Self {
|
||||
Coord::new(coord.X, coord.Y)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Coord> for COORD {
|
||||
fn from(location: Coord) -> Self {
|
||||
COORD {
|
||||
X: location.x,
|
||||
Y: location.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<(u16, u16)> for Coord {
|
||||
fn into(self) -> (u16, u16) {
|
||||
(self.x as u16, self.y as u16)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
654
vendor/crossterm_winapi/src/structs/input.rs
vendored
654
vendor/crossterm_winapi/src/structs/input.rs
vendored
|
|
@ -1,327 +1,327 @@
|
|||
//! This module provides a few structs to wrap common input struts to a rusty interface
|
||||
//!
|
||||
//! Types like:
|
||||
//! - `KEY_EVENT_RECORD`
|
||||
//! - `MOUSE_EVENT_RECORD`
|
||||
//! - `ControlKeyState`
|
||||
//! - `ButtonState`
|
||||
//! - `EventFlags`
|
||||
//! - `InputEventType`
|
||||
//! - `INPUT_RECORD`
|
||||
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::um::wincon::{
|
||||
FOCUS_EVENT, FOCUS_EVENT_RECORD, FROM_LEFT_1ST_BUTTON_PRESSED, FROM_LEFT_2ND_BUTTON_PRESSED,
|
||||
FROM_LEFT_3RD_BUTTON_PRESSED, FROM_LEFT_4TH_BUTTON_PRESSED, INPUT_RECORD, KEY_EVENT,
|
||||
KEY_EVENT_RECORD, MENU_EVENT, MENU_EVENT_RECORD, MOUSE_EVENT, MOUSE_EVENT_RECORD,
|
||||
RIGHTMOST_BUTTON_PRESSED, WINDOW_BUFFER_SIZE_EVENT, WINDOW_BUFFER_SIZE_RECORD,
|
||||
};
|
||||
|
||||
use super::Coord;
|
||||
use crate::ScreenBuffer;
|
||||
|
||||
/// A [keyboard input event](https://docs.microsoft.com/en-us/windows/console/key-event-record-str).
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct KeyEventRecord {
|
||||
/// If the key is pressed, this member is true. Otherwise, this member is
|
||||
/// false (the key is released).
|
||||
pub key_down: bool,
|
||||
/// The repeat count, which indicates that a key is being held down.
|
||||
/// For example, when a key is held down, you might get five events with
|
||||
/// this member equal to 1, one event with this member equal to 5, or
|
||||
/// multiple events with this member greater than or equal to 1.
|
||||
pub repeat_count: u16,
|
||||
/// A virtual-key code that identifies the given key in a
|
||||
/// device-independent manner.
|
||||
pub virtual_key_code: u16,
|
||||
/// The virtual scan code of the given key that represents the
|
||||
/// device-dependent value generated by the keyboard hardware.
|
||||
pub virtual_scan_code: u16,
|
||||
/// The translated Unicode character (as a WCHAR, or utf-16 value)
|
||||
pub u_char: u16,
|
||||
/// The state of the control keys.
|
||||
pub control_key_state: ControlKeyState,
|
||||
}
|
||||
|
||||
impl KeyEventRecord {
|
||||
/// Convert a `KEY_EVENT_RECORD` to KeyEventRecord. This function is private
|
||||
/// because the `KEY_EVENT_RECORD` has several union fields for characters
|
||||
/// (u8 vs u16) that we always interpret as u16. We always use the wide
|
||||
/// versions of windows API calls to support this.
|
||||
#[inline]
|
||||
fn from_winapi(record: &KEY_EVENT_RECORD) -> Self {
|
||||
KeyEventRecord {
|
||||
key_down: record.bKeyDown != 0,
|
||||
repeat_count: record.wRepeatCount,
|
||||
virtual_key_code: record.wVirtualKeyCode,
|
||||
virtual_scan_code: record.wVirtualScanCode,
|
||||
u_char: unsafe { *record.uChar.UnicodeChar() },
|
||||
control_key_state: ControlKeyState(record.dwControlKeyState),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A [mouse input event](https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str).
|
||||
#[derive(PartialEq, Debug, Copy, Clone, Eq)]
|
||||
pub struct MouseEvent {
|
||||
/// The position of the mouse when the event occurred in cell coordinates.
|
||||
pub mouse_position: Coord,
|
||||
/// The state of the mouse's buttons.
|
||||
pub button_state: ButtonState,
|
||||
/// The state of the control keys.
|
||||
pub control_key_state: ControlKeyState,
|
||||
/// What type of mouse event it is.
|
||||
pub event_flags: EventFlags,
|
||||
}
|
||||
|
||||
impl From<MOUSE_EVENT_RECORD> for MouseEvent {
|
||||
#[inline]
|
||||
fn from(event: MOUSE_EVENT_RECORD) -> Self {
|
||||
MouseEvent {
|
||||
mouse_position: event.dwMousePosition.into(),
|
||||
button_state: event.dwButtonState.into(),
|
||||
control_key_state: ControlKeyState(event.dwControlKeyState),
|
||||
event_flags: event.dwEventFlags.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The status of the mouse buttons.
|
||||
/// The least significant bit corresponds to the leftmost mouse button.
|
||||
/// The next least significant bit corresponds to the rightmost mouse button.
|
||||
/// The next bit indicates the next-to-leftmost mouse button.
|
||||
/// The bits then correspond left to right to the mouse buttons.
|
||||
/// A bit is 1 if the button was pressed.
|
||||
///
|
||||
/// The state can be one of the following:
|
||||
///
|
||||
/// ```
|
||||
/// # enum __ {
|
||||
/// Release = 0x0000,
|
||||
/// /// The leftmost mouse button.
|
||||
/// FromLeft1stButtonPressed = 0x0001,
|
||||
/// /// The second button from the left.
|
||||
/// FromLeft2ndButtonPressed = 0x0004,
|
||||
/// /// The third button from the left.
|
||||
/// FromLeft3rdButtonPressed = 0x0008,
|
||||
/// /// The fourth button from the left.
|
||||
/// FromLeft4thButtonPressed = 0x0010,
|
||||
/// /// The rightmost mouse button.
|
||||
/// RightmostButtonPressed = 0x0002,
|
||||
/// /// This button state is not recognized.
|
||||
/// Unknown = 0x0021,
|
||||
/// /// The wheel was rotated backward, toward the user; this will only be activated for `MOUSE_WHEELED ` from `dwEventFlags`
|
||||
/// Negative = 0x0020,
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// [Ms Docs](https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str#members)
|
||||
#[derive(PartialEq, Debug, Copy, Clone, Eq)]
|
||||
pub struct ButtonState {
|
||||
state: i32,
|
||||
}
|
||||
|
||||
impl From<DWORD> for ButtonState {
|
||||
#[inline]
|
||||
fn from(event: DWORD) -> Self {
|
||||
let state = event as i32;
|
||||
ButtonState { state }
|
||||
}
|
||||
}
|
||||
|
||||
impl ButtonState {
|
||||
/// Get whether no buttons are being pressed.
|
||||
pub fn release_button(&self) -> bool {
|
||||
self.state == 0
|
||||
}
|
||||
|
||||
/// Returns whether the left button was pressed.
|
||||
pub fn left_button(&self) -> bool {
|
||||
self.state as u32 & FROM_LEFT_1ST_BUTTON_PRESSED != 0
|
||||
}
|
||||
|
||||
/// Returns whether the right button was pressed.
|
||||
pub fn right_button(&self) -> bool {
|
||||
self.state as u32
|
||||
& (RIGHTMOST_BUTTON_PRESSED
|
||||
| FROM_LEFT_3RD_BUTTON_PRESSED
|
||||
| FROM_LEFT_4TH_BUTTON_PRESSED)
|
||||
!= 0
|
||||
}
|
||||
|
||||
/// Returns whether the right button was pressed.
|
||||
pub fn middle_button(&self) -> bool {
|
||||
self.state as u32 & FROM_LEFT_2ND_BUTTON_PRESSED != 0
|
||||
}
|
||||
|
||||
/// Returns whether there is a down scroll.
|
||||
pub fn scroll_down(&self) -> bool {
|
||||
self.state < 0
|
||||
}
|
||||
|
||||
/// Returns whether there is a up scroll.
|
||||
pub fn scroll_up(&self) -> bool {
|
||||
self.state > 0
|
||||
}
|
||||
|
||||
/// Returns the raw state.
|
||||
pub fn state(&self) -> i32 {
|
||||
self.state
|
||||
}
|
||||
}
|
||||
|
||||
/// The state of the control keys.
|
||||
///
|
||||
/// This is a bitmask of the following values.
|
||||
///
|
||||
/// | Description | Value |
|
||||
/// | --- | --- |
|
||||
/// | The right alt key is pressed | `0x0001` |
|
||||
/// | The left alt key is pressed | `x0002` |
|
||||
/// | The right control key is pressed | `0x0004` |
|
||||
/// | The left control key is pressed | `x0008` |
|
||||
/// | The shift key is pressed | `0x0010` |
|
||||
/// | The num lock light is on | `0x0020` |
|
||||
/// | The scroll lock light is on | `0x0040` |
|
||||
/// | The caps lock light is on | `0x0080` |
|
||||
/// | The key is [enhanced](https://docs.microsoft.com/en-us/windows/console/key-event-record-str#remarks) | `0x0100` |
|
||||
#[derive(PartialEq, Debug, Copy, Clone, Eq)]
|
||||
pub struct ControlKeyState(u32);
|
||||
|
||||
impl ControlKeyState {
|
||||
/// Whether the control key has a state.
|
||||
pub fn has_state(&self, state: u32) -> bool {
|
||||
(state & self.0) != 0
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of mouse event.
|
||||
/// If this value is zero, it indicates a mouse button being pressed or released.
|
||||
/// Otherwise, this member is one of the following values.
|
||||
///
|
||||
/// [Ms Docs](https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str#members)
|
||||
#[derive(PartialEq, Debug, Copy, Clone, Eq)]
|
||||
pub enum EventFlags {
|
||||
PressOrRelease = 0x0000,
|
||||
/// The second click (button press) of a double-click occurred. The first click is returned as a regular button-press event.
|
||||
DoubleClick = 0x0002,
|
||||
/// The horizontal mouse wheel was moved.
|
||||
MouseHwheeled = 0x0008,
|
||||
/// If the high word of the dwButtonState member contains a positive value, the wheel was rotated to the right. Otherwise, the wheel was rotated to the left.
|
||||
MouseMoved = 0x0001,
|
||||
/// A change in mouse position occurred.
|
||||
/// The vertical mouse wheel was moved, if the high word of the dwButtonState member contains a positive value, the wheel was rotated forward, away from the user.
|
||||
/// Otherwise, the wheel was rotated backward, toward the user.
|
||||
MouseWheeled = 0x0004,
|
||||
// This button state is not recognized.
|
||||
Unknown = 0x0021,
|
||||
}
|
||||
|
||||
// TODO: Replace with TryFrom.
|
||||
impl From<DWORD> for EventFlags {
|
||||
fn from(event: DWORD) -> Self {
|
||||
match event {
|
||||
0x0000 => EventFlags::PressOrRelease,
|
||||
0x0002 => EventFlags::DoubleClick,
|
||||
0x0008 => EventFlags::MouseHwheeled,
|
||||
0x0001 => EventFlags::MouseMoved,
|
||||
0x0004 => EventFlags::MouseWheeled,
|
||||
_ => EventFlags::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The [size of console screen
|
||||
/// buffer](https://docs.microsoft.com/en-us/windows/console/window-buffer-size-record-str).
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct WindowBufferSizeRecord {
|
||||
pub size: Coord,
|
||||
}
|
||||
|
||||
impl From<WINDOW_BUFFER_SIZE_RECORD> for WindowBufferSizeRecord {
|
||||
#[inline]
|
||||
fn from(record: WINDOW_BUFFER_SIZE_RECORD) -> Self {
|
||||
WindowBufferSizeRecord {
|
||||
size: record.dwSize.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A [focus event](https://docs.microsoft.com/en-us/windows/console/focus-event-record-str). This
|
||||
/// is used only internally by Windows and should be ignored.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct FocusEventRecord {
|
||||
/// Reserved; do not use.
|
||||
pub set_focus: bool,
|
||||
}
|
||||
|
||||
impl From<FOCUS_EVENT_RECORD> for FocusEventRecord {
|
||||
#[inline]
|
||||
fn from(record: FOCUS_EVENT_RECORD) -> Self {
|
||||
FocusEventRecord {
|
||||
set_focus: record.bSetFocus != 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A [menu event](https://docs.microsoft.com/en-us/windows/console/menu-event-record-str). This is
|
||||
/// used only internally by Windows and should be ignored.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct MenuEventRecord {
|
||||
/// Reserved; do not use.
|
||||
pub command_id: u32,
|
||||
}
|
||||
|
||||
impl From<MENU_EVENT_RECORD> for MenuEventRecord {
|
||||
#[inline]
|
||||
fn from(record: MENU_EVENT_RECORD) -> Self {
|
||||
MenuEventRecord {
|
||||
command_id: record.dwCommandId,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An [input event](https://docs.microsoft.com/en-us/windows/console/input-record-str).
|
||||
///
|
||||
/// These records can be read from the input buffer by using the `ReadConsoleInput`
|
||||
/// or `PeekConsoleInput` function, or written to the input buffer by using the
|
||||
/// `WriteConsoleInput` function.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum InputRecord {
|
||||
/// A keyboard event occurred.
|
||||
KeyEvent(KeyEventRecord),
|
||||
/// The mouse was moved or a mouse button was pressed.
|
||||
MouseEvent(MouseEvent),
|
||||
/// A console screen buffer was resized.
|
||||
WindowBufferSizeEvent(WindowBufferSizeRecord),
|
||||
/// A focus event occured. This is used only internally by Windows and should be ignored.
|
||||
FocusEvent(FocusEventRecord),
|
||||
/// A menu event occurred. This is used only internally by Windows and should be ignored.
|
||||
MenuEvent(MenuEventRecord),
|
||||
}
|
||||
|
||||
impl From<INPUT_RECORD> for InputRecord {
|
||||
#[inline]
|
||||
fn from(record: INPUT_RECORD) -> Self {
|
||||
match record.EventType {
|
||||
KEY_EVENT => InputRecord::KeyEvent(KeyEventRecord::from_winapi(unsafe {
|
||||
record.Event.KeyEvent()
|
||||
})),
|
||||
MOUSE_EVENT => InputRecord::MouseEvent(unsafe { *record.Event.MouseEvent() }.into()),
|
||||
WINDOW_BUFFER_SIZE_EVENT => InputRecord::WindowBufferSizeEvent({
|
||||
let mut buffer =
|
||||
unsafe { WindowBufferSizeRecord::from(*record.Event.WindowBufferSizeEvent()) };
|
||||
let window = ScreenBuffer::current().unwrap().info().unwrap();
|
||||
let screen_size = window.terminal_size();
|
||||
|
||||
buffer.size.y = screen_size.height;
|
||||
buffer.size.x = screen_size.width;
|
||||
|
||||
buffer
|
||||
}),
|
||||
FOCUS_EVENT => InputRecord::FocusEvent(unsafe { *record.Event.FocusEvent() }.into()),
|
||||
MENU_EVENT => InputRecord::MenuEvent(unsafe { *record.Event.MenuEvent() }.into()),
|
||||
code => panic!("Unexpected INPUT_RECORD EventType: {}", code),
|
||||
}
|
||||
}
|
||||
}
|
||||
//! This module provides a few structs to wrap common input struts to a rusty interface
|
||||
//!
|
||||
//! Types like:
|
||||
//! - `KEY_EVENT_RECORD`
|
||||
//! - `MOUSE_EVENT_RECORD`
|
||||
//! - `ControlKeyState`
|
||||
//! - `ButtonState`
|
||||
//! - `EventFlags`
|
||||
//! - `InputEventType`
|
||||
//! - `INPUT_RECORD`
|
||||
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::um::wincon::{
|
||||
FOCUS_EVENT, FOCUS_EVENT_RECORD, FROM_LEFT_1ST_BUTTON_PRESSED, FROM_LEFT_2ND_BUTTON_PRESSED,
|
||||
FROM_LEFT_3RD_BUTTON_PRESSED, FROM_LEFT_4TH_BUTTON_PRESSED, INPUT_RECORD, KEY_EVENT,
|
||||
KEY_EVENT_RECORD, MENU_EVENT, MENU_EVENT_RECORD, MOUSE_EVENT, MOUSE_EVENT_RECORD,
|
||||
RIGHTMOST_BUTTON_PRESSED, WINDOW_BUFFER_SIZE_EVENT, WINDOW_BUFFER_SIZE_RECORD,
|
||||
};
|
||||
|
||||
use super::Coord;
|
||||
use crate::ScreenBuffer;
|
||||
|
||||
/// A [keyboard input event](https://docs.microsoft.com/en-us/windows/console/key-event-record-str).
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct KeyEventRecord {
|
||||
/// If the key is pressed, this member is true. Otherwise, this member is
|
||||
/// false (the key is released).
|
||||
pub key_down: bool,
|
||||
/// The repeat count, which indicates that a key is being held down.
|
||||
/// For example, when a key is held down, you might get five events with
|
||||
/// this member equal to 1, one event with this member equal to 5, or
|
||||
/// multiple events with this member greater than or equal to 1.
|
||||
pub repeat_count: u16,
|
||||
/// A virtual-key code that identifies the given key in a
|
||||
/// device-independent manner.
|
||||
pub virtual_key_code: u16,
|
||||
/// The virtual scan code of the given key that represents the
|
||||
/// device-dependent value generated by the keyboard hardware.
|
||||
pub virtual_scan_code: u16,
|
||||
/// The translated Unicode character (as a WCHAR, or utf-16 value)
|
||||
pub u_char: u16,
|
||||
/// The state of the control keys.
|
||||
pub control_key_state: ControlKeyState,
|
||||
}
|
||||
|
||||
impl KeyEventRecord {
|
||||
/// Convert a `KEY_EVENT_RECORD` to KeyEventRecord. This function is private
|
||||
/// because the `KEY_EVENT_RECORD` has several union fields for characters
|
||||
/// (u8 vs u16) that we always interpret as u16. We always use the wide
|
||||
/// versions of windows API calls to support this.
|
||||
#[inline]
|
||||
fn from_winapi(record: &KEY_EVENT_RECORD) -> Self {
|
||||
KeyEventRecord {
|
||||
key_down: record.bKeyDown != 0,
|
||||
repeat_count: record.wRepeatCount,
|
||||
virtual_key_code: record.wVirtualKeyCode,
|
||||
virtual_scan_code: record.wVirtualScanCode,
|
||||
u_char: unsafe { *record.uChar.UnicodeChar() },
|
||||
control_key_state: ControlKeyState(record.dwControlKeyState),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A [mouse input event](https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str).
|
||||
#[derive(PartialEq, Debug, Copy, Clone, Eq)]
|
||||
pub struct MouseEvent {
|
||||
/// The position of the mouse when the event occurred in cell coordinates.
|
||||
pub mouse_position: Coord,
|
||||
/// The state of the mouse's buttons.
|
||||
pub button_state: ButtonState,
|
||||
/// The state of the control keys.
|
||||
pub control_key_state: ControlKeyState,
|
||||
/// What type of mouse event it is.
|
||||
pub event_flags: EventFlags,
|
||||
}
|
||||
|
||||
impl From<MOUSE_EVENT_RECORD> for MouseEvent {
|
||||
#[inline]
|
||||
fn from(event: MOUSE_EVENT_RECORD) -> Self {
|
||||
MouseEvent {
|
||||
mouse_position: event.dwMousePosition.into(),
|
||||
button_state: event.dwButtonState.into(),
|
||||
control_key_state: ControlKeyState(event.dwControlKeyState),
|
||||
event_flags: event.dwEventFlags.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The status of the mouse buttons.
|
||||
/// The least significant bit corresponds to the leftmost mouse button.
|
||||
/// The next least significant bit corresponds to the rightmost mouse button.
|
||||
/// The next bit indicates the next-to-leftmost mouse button.
|
||||
/// The bits then correspond left to right to the mouse buttons.
|
||||
/// A bit is 1 if the button was pressed.
|
||||
///
|
||||
/// The state can be one of the following:
|
||||
///
|
||||
/// ```
|
||||
/// # enum __ {
|
||||
/// Release = 0x0000,
|
||||
/// /// The leftmost mouse button.
|
||||
/// FromLeft1stButtonPressed = 0x0001,
|
||||
/// /// The second button from the left.
|
||||
/// FromLeft2ndButtonPressed = 0x0004,
|
||||
/// /// The third button from the left.
|
||||
/// FromLeft3rdButtonPressed = 0x0008,
|
||||
/// /// The fourth button from the left.
|
||||
/// FromLeft4thButtonPressed = 0x0010,
|
||||
/// /// The rightmost mouse button.
|
||||
/// RightmostButtonPressed = 0x0002,
|
||||
/// /// This button state is not recognized.
|
||||
/// Unknown = 0x0021,
|
||||
/// /// The wheel was rotated backward, toward the user; this will only be activated for `MOUSE_WHEELED ` from `dwEventFlags`
|
||||
/// Negative = 0x0020,
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// [Ms Docs](https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str#members)
|
||||
#[derive(PartialEq, Debug, Copy, Clone, Eq)]
|
||||
pub struct ButtonState {
|
||||
state: i32,
|
||||
}
|
||||
|
||||
impl From<DWORD> for ButtonState {
|
||||
#[inline]
|
||||
fn from(event: DWORD) -> Self {
|
||||
let state = event as i32;
|
||||
ButtonState { state }
|
||||
}
|
||||
}
|
||||
|
||||
impl ButtonState {
|
||||
/// Get whether no buttons are being pressed.
|
||||
pub fn release_button(&self) -> bool {
|
||||
self.state == 0
|
||||
}
|
||||
|
||||
/// Returns whether the left button was pressed.
|
||||
pub fn left_button(&self) -> bool {
|
||||
self.state as u32 & FROM_LEFT_1ST_BUTTON_PRESSED != 0
|
||||
}
|
||||
|
||||
/// Returns whether the right button was pressed.
|
||||
pub fn right_button(&self) -> bool {
|
||||
self.state as u32
|
||||
& (RIGHTMOST_BUTTON_PRESSED
|
||||
| FROM_LEFT_3RD_BUTTON_PRESSED
|
||||
| FROM_LEFT_4TH_BUTTON_PRESSED)
|
||||
!= 0
|
||||
}
|
||||
|
||||
/// Returns whether the right button was pressed.
|
||||
pub fn middle_button(&self) -> bool {
|
||||
self.state as u32 & FROM_LEFT_2ND_BUTTON_PRESSED != 0
|
||||
}
|
||||
|
||||
/// Returns whether there is a down scroll.
|
||||
pub fn scroll_down(&self) -> bool {
|
||||
self.state < 0
|
||||
}
|
||||
|
||||
/// Returns whether there is a up scroll.
|
||||
pub fn scroll_up(&self) -> bool {
|
||||
self.state > 0
|
||||
}
|
||||
|
||||
/// Returns the raw state.
|
||||
pub fn state(&self) -> i32 {
|
||||
self.state
|
||||
}
|
||||
}
|
||||
|
||||
/// The state of the control keys.
|
||||
///
|
||||
/// This is a bitmask of the following values.
|
||||
///
|
||||
/// | Description | Value |
|
||||
/// | --- | --- |
|
||||
/// | The right alt key is pressed | `0x0001` |
|
||||
/// | The left alt key is pressed | `x0002` |
|
||||
/// | The right control key is pressed | `0x0004` |
|
||||
/// | The left control key is pressed | `x0008` |
|
||||
/// | The shift key is pressed | `0x0010` |
|
||||
/// | The num lock light is on | `0x0020` |
|
||||
/// | The scroll lock light is on | `0x0040` |
|
||||
/// | The caps lock light is on | `0x0080` |
|
||||
/// | The key is [enhanced](https://docs.microsoft.com/en-us/windows/console/key-event-record-str#remarks) | `0x0100` |
|
||||
#[derive(PartialEq, Debug, Copy, Clone, Eq)]
|
||||
pub struct ControlKeyState(u32);
|
||||
|
||||
impl ControlKeyState {
|
||||
/// Whether the control key has a state.
|
||||
pub fn has_state(&self, state: u32) -> bool {
|
||||
(state & self.0) != 0
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of mouse event.
|
||||
/// If this value is zero, it indicates a mouse button being pressed or released.
|
||||
/// Otherwise, this member is one of the following values.
|
||||
///
|
||||
/// [Ms Docs](https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str#members)
|
||||
#[derive(PartialEq, Debug, Copy, Clone, Eq)]
|
||||
pub enum EventFlags {
|
||||
PressOrRelease = 0x0000,
|
||||
/// The second click (button press) of a double-click occurred. The first click is returned as a regular button-press event.
|
||||
DoubleClick = 0x0002,
|
||||
/// The horizontal mouse wheel was moved.
|
||||
MouseHwheeled = 0x0008,
|
||||
/// If the high word of the dwButtonState member contains a positive value, the wheel was rotated to the right. Otherwise, the wheel was rotated to the left.
|
||||
MouseMoved = 0x0001,
|
||||
/// A change in mouse position occurred.
|
||||
/// The vertical mouse wheel was moved, if the high word of the dwButtonState member contains a positive value, the wheel was rotated forward, away from the user.
|
||||
/// Otherwise, the wheel was rotated backward, toward the user.
|
||||
MouseWheeled = 0x0004,
|
||||
// This button state is not recognized.
|
||||
Unknown = 0x0021,
|
||||
}
|
||||
|
||||
// TODO: Replace with TryFrom.
|
||||
impl From<DWORD> for EventFlags {
|
||||
fn from(event: DWORD) -> Self {
|
||||
match event {
|
||||
0x0000 => EventFlags::PressOrRelease,
|
||||
0x0002 => EventFlags::DoubleClick,
|
||||
0x0008 => EventFlags::MouseHwheeled,
|
||||
0x0001 => EventFlags::MouseMoved,
|
||||
0x0004 => EventFlags::MouseWheeled,
|
||||
_ => EventFlags::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The [size of console screen
|
||||
/// buffer](https://docs.microsoft.com/en-us/windows/console/window-buffer-size-record-str).
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct WindowBufferSizeRecord {
|
||||
pub size: Coord,
|
||||
}
|
||||
|
||||
impl From<WINDOW_BUFFER_SIZE_RECORD> for WindowBufferSizeRecord {
|
||||
#[inline]
|
||||
fn from(record: WINDOW_BUFFER_SIZE_RECORD) -> Self {
|
||||
WindowBufferSizeRecord {
|
||||
size: record.dwSize.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A [focus event](https://docs.microsoft.com/en-us/windows/console/focus-event-record-str). This
|
||||
/// is used only internally by Windows and should be ignored.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct FocusEventRecord {
|
||||
/// Reserved; do not use.
|
||||
pub set_focus: bool,
|
||||
}
|
||||
|
||||
impl From<FOCUS_EVENT_RECORD> for FocusEventRecord {
|
||||
#[inline]
|
||||
fn from(record: FOCUS_EVENT_RECORD) -> Self {
|
||||
FocusEventRecord {
|
||||
set_focus: record.bSetFocus != 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A [menu event](https://docs.microsoft.com/en-us/windows/console/menu-event-record-str). This is
|
||||
/// used only internally by Windows and should be ignored.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct MenuEventRecord {
|
||||
/// Reserved; do not use.
|
||||
pub command_id: u32,
|
||||
}
|
||||
|
||||
impl From<MENU_EVENT_RECORD> for MenuEventRecord {
|
||||
#[inline]
|
||||
fn from(record: MENU_EVENT_RECORD) -> Self {
|
||||
MenuEventRecord {
|
||||
command_id: record.dwCommandId,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An [input event](https://docs.microsoft.com/en-us/windows/console/input-record-str).
|
||||
///
|
||||
/// These records can be read from the input buffer by using the `ReadConsoleInput`
|
||||
/// or `PeekConsoleInput` function, or written to the input buffer by using the
|
||||
/// `WriteConsoleInput` function.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum InputRecord {
|
||||
/// A keyboard event occurred.
|
||||
KeyEvent(KeyEventRecord),
|
||||
/// The mouse was moved or a mouse button was pressed.
|
||||
MouseEvent(MouseEvent),
|
||||
/// A console screen buffer was resized.
|
||||
WindowBufferSizeEvent(WindowBufferSizeRecord),
|
||||
/// A focus event occured. This is used only internally by Windows and should be ignored.
|
||||
FocusEvent(FocusEventRecord),
|
||||
/// A menu event occurred. This is used only internally by Windows and should be ignored.
|
||||
MenuEvent(MenuEventRecord),
|
||||
}
|
||||
|
||||
impl From<INPUT_RECORD> for InputRecord {
|
||||
#[inline]
|
||||
fn from(record: INPUT_RECORD) -> Self {
|
||||
match record.EventType {
|
||||
KEY_EVENT => InputRecord::KeyEvent(KeyEventRecord::from_winapi(unsafe {
|
||||
record.Event.KeyEvent()
|
||||
})),
|
||||
MOUSE_EVENT => InputRecord::MouseEvent(unsafe { *record.Event.MouseEvent() }.into()),
|
||||
WINDOW_BUFFER_SIZE_EVENT => InputRecord::WindowBufferSizeEvent({
|
||||
let mut buffer =
|
||||
unsafe { WindowBufferSizeRecord::from(*record.Event.WindowBufferSizeEvent()) };
|
||||
let window = ScreenBuffer::current().unwrap().info().unwrap();
|
||||
let screen_size = window.terminal_size();
|
||||
|
||||
buffer.size.y = screen_size.height;
|
||||
buffer.size.x = screen_size.width;
|
||||
|
||||
buffer
|
||||
}),
|
||||
FOCUS_EVENT => InputRecord::FocusEvent(unsafe { *record.Event.FocusEvent() }.into()),
|
||||
MENU_EVENT => InputRecord::MenuEvent(unsafe { *record.Event.MenuEvent() }.into()),
|
||||
code => panic!("Unexpected INPUT_RECORD EventType: {}", code),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
62
vendor/crossterm_winapi/src/structs/size.rs
vendored
62
vendor/crossterm_winapi/src/structs/size.rs
vendored
|
|
@ -1,31 +1,31 @@
|
|||
//! This module provides a type that represents some size.
|
||||
//! For example, in WinAPI we have `COORD` to represent screen/buffer size but this is a little inconvenient.
|
||||
//! This module provides some trait implementations who will make parsing and working with `COORD` easier.
|
||||
|
||||
use winapi::um::wincon::COORD;
|
||||
|
||||
/// This is type represents the size of something in width and height.
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Size {
|
||||
pub width: i16,
|
||||
pub height: i16,
|
||||
}
|
||||
|
||||
impl Size {
|
||||
/// Create a new size instance by passing in the width and height.
|
||||
pub fn new(width: i16, height: i16) -> Size {
|
||||
Size { width, height }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<COORD> for Size {
|
||||
fn from(coord: COORD) -> Self {
|
||||
Size::new(coord.X, coord.Y)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<(u16, u16)> for Size {
|
||||
fn into(self) -> (u16, u16) {
|
||||
(self.width as u16, self.height as u16)
|
||||
}
|
||||
}
|
||||
//! This module provides a type that represents some size.
|
||||
//! For example, in WinAPI we have `COORD` to represent screen/buffer size but this is a little inconvenient.
|
||||
//! This module provides some trait implementations who will make parsing and working with `COORD` easier.
|
||||
|
||||
use winapi::um::wincon::COORD;
|
||||
|
||||
/// This is type represents the size of something in width and height.
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Size {
|
||||
pub width: i16,
|
||||
pub height: i16,
|
||||
}
|
||||
|
||||
impl Size {
|
||||
/// Create a new size instance by passing in the width and height.
|
||||
pub fn new(width: i16, height: i16) -> Size {
|
||||
Size { width, height }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<COORD> for Size {
|
||||
fn from(coord: COORD) -> Self {
|
||||
Size::new(coord.X, coord.Y)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<(u16, u16)> for Size {
|
||||
fn into(self) -> (u16, u16) {
|
||||
(self.width as u16, self.height as u16)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,46 +1,46 @@
|
|||
//! This module provides a type that represents some rectangle.
|
||||
//! For example, in WinAPI we have `SMALL_RECT` to represent a window size but this is a little inconvenient.
|
||||
//! This module provides some trait implementations who will make parsing and working with `SMALL_RECT` easier.
|
||||
|
||||
use winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, SMALL_RECT};
|
||||
|
||||
/// This is a wrapper for the locations of a rectangle.
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct WindowPositions {
|
||||
/// The rectangle's offset from the left.
|
||||
pub left: i16,
|
||||
/// The rectangle's offset from the right.
|
||||
pub right: i16,
|
||||
/// The rectangle's offset from the bottom.
|
||||
pub bottom: i16,
|
||||
/// The rectangle's offset from the top.
|
||||
pub top: i16,
|
||||
}
|
||||
|
||||
impl From<CONSOLE_SCREEN_BUFFER_INFO> for WindowPositions {
|
||||
fn from(csbi: CONSOLE_SCREEN_BUFFER_INFO) -> Self {
|
||||
csbi.srWindow.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WindowPositions> for SMALL_RECT {
|
||||
fn from(positions: WindowPositions) -> Self {
|
||||
SMALL_RECT {
|
||||
Top: positions.top,
|
||||
Right: positions.right,
|
||||
Bottom: positions.bottom,
|
||||
Left: positions.left,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SMALL_RECT> for WindowPositions {
|
||||
fn from(rect: SMALL_RECT) -> Self {
|
||||
WindowPositions {
|
||||
left: rect.Left,
|
||||
right: rect.Right,
|
||||
bottom: rect.Bottom,
|
||||
top: rect.Top,
|
||||
}
|
||||
}
|
||||
}
|
||||
//! This module provides a type that represents some rectangle.
|
||||
//! For example, in WinAPI we have `SMALL_RECT` to represent a window size but this is a little inconvenient.
|
||||
//! This module provides some trait implementations who will make parsing and working with `SMALL_RECT` easier.
|
||||
|
||||
use winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, SMALL_RECT};
|
||||
|
||||
/// This is a wrapper for the locations of a rectangle.
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct WindowPositions {
|
||||
/// The rectangle's offset from the left.
|
||||
pub left: i16,
|
||||
/// The rectangle's offset from the right.
|
||||
pub right: i16,
|
||||
/// The rectangle's offset from the bottom.
|
||||
pub bottom: i16,
|
||||
/// The rectangle's offset from the top.
|
||||
pub top: i16,
|
||||
}
|
||||
|
||||
impl From<CONSOLE_SCREEN_BUFFER_INFO> for WindowPositions {
|
||||
fn from(csbi: CONSOLE_SCREEN_BUFFER_INFO) -> Self {
|
||||
csbi.srWindow.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WindowPositions> for SMALL_RECT {
|
||||
fn from(positions: WindowPositions) -> Self {
|
||||
SMALL_RECT {
|
||||
Top: positions.top,
|
||||
Right: positions.right,
|
||||
Bottom: positions.bottom,
|
||||
Left: positions.left,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SMALL_RECT> for WindowPositions {
|
||||
fn from(rect: SMALL_RECT) -> Self {
|
||||
WindowPositions {
|
||||
left: rect.Left,
|
||||
right: rect.Right,
|
||||
bottom: rect.Bottom,
|
||||
top: rect.Top,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue