minicrossterm/src/kernel/windows_kernel/writing.rs

137 lines
3.6 KiB
Rust

//! This module contains the logic to write to the terminal.
use winapi::ctypes::c_void;
use winapi::shared::ntdef::NULL;
use winapi::um::consoleapi::WriteConsoleW;
use winapi::um::wincon::{
self, FillConsoleOutputAttribute, FillConsoleOutputCharacterA, WriteConsoleOutputA, CHAR_INFO,
COORD, PSMALL_RECT,
};
use winapi::um::winnt::HANDLE;
use super::{csbi, handle, kernel, ScreenManager};
use std::io::{self, ErrorKind, Result};
use std::str;
/// Fill a certain block with characters.
pub fn fill_console_output_character(
cells_written: &mut u32,
start_location: COORD,
cells_to_write: u32,
screen_manager: &ScreenManager,
) -> bool {
let handle = handle::get_current_handle(screen_manager).unwrap();
unsafe {
// fill the cells in console with blanks
let success = FillConsoleOutputCharacterA(
handle,
' ' as i8,
cells_to_write,
start_location,
cells_written,
);
kernel::is_true(success)
}
}
/// Set console ouput attribute for certain block.
pub fn fill_console_output_attribute(
cells_written: &mut u32,
start_location: COORD,
cells_to_write: u32,
screen_manager: &ScreenManager,
) -> bool {
// Get the position of the current console window
let (csbi, mut handle) = csbi::get_csbi_and_handle(screen_manager).unwrap();
let success;
unsafe {
success = FillConsoleOutputAttribute(
handle,
csbi.wAttributes,
cells_to_write,
start_location,
cells_written,
);
}
kernel::is_true(success)
}
/// Write console output.
pub fn write_console_output(
write_buffer: &HANDLE,
copy_buffer: &mut [CHAR_INFO; 160],
buffer_size: COORD,
buffer_coord: COORD,
source_buffer: PSMALL_RECT,
) -> Result<()> {
unsafe {
if !kernel::is_true(
WriteConsoleOutputA(
*write_buffer, // screen buffer to write to
copy_buffer.as_mut_ptr(), // buffer to copy into
buffer_size, // col-row size of chiBuffer
buffer_coord, // top left dest. cell in chiBuffer
source_buffer,
), // screen buffer source rectangle
) {
return Err(io::Error::new(
io::ErrorKind::Other,
"Could not write to terminal",
));
}
}
Ok(())
}
/// Write utf8 buffer to console.
pub fn write_char_buffer(handle: &HANDLE, buf: &[u8]) -> ::std::io::Result<usize> {
// get string from u8[] and parse it to an c_str
let mut utf8 = match str::from_utf8(buf) {
Ok(string) => string,
Err(_) => {
return Err(io::Error::new(
io::ErrorKind::Other,
"Could not parse input 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;
// get buffer info
let csbi = csbi::get_csbi_by_handle(handle)?;
// get current position
let current_pos = COORD {
X: csbi.dwCursorPosition.X,
Y: csbi.dwCursorPosition.Y,
};
let mut cells_written: u32 = 0;
let mut success = false;
// write to console
unsafe {
success = kernel::is_true(WriteConsoleW(
*handle,
utf16_ptr,
utf16.len() as u32,
&mut cells_written,
NULL,
));
}
match success {
// think this is wrong could be done better!
true => Ok(utf8.as_bytes().len()),
false => Ok(0),
}
}