#![allow(unsafe_code)]
use super::modes::{not_a_terminal, windows_input_mode, windows_output_mode};
use std::io;
const STD_INPUT_HANDLE: u32 = -10i32 as u32;
const STD_OUTPUT_HANDLE: u32 = -11i32 as u32;
const INVALID_HANDLE_VALUE: isize = -1;
#[link(name = "kernel32")]
extern "system" {
fn GetStdHandle(id: u32) -> isize;
fn GetConsoleMode(handle: isize, mode: *mut u32) -> i32;
fn SetConsoleMode(handle: isize, mode: u32) -> i32;
}
pub(super) struct Saved {
input: (isize, u32),
output: Option<(isize, u32)>,
}
fn console(id: u32) -> Option<(isize, u32)> {
let handle = unsafe { GetStdHandle(id) };
if handle == 0 || handle == INVALID_HANDLE_VALUE {
return None;
}
let mut mode = 0u32;
if unsafe { GetConsoleMode(handle, &mut mode) } == 0 {
return None;
}
Some((handle, mode))
}
pub(super) fn enable() -> io::Result<Saved> {
let input = console(STD_INPUT_HANDLE).ok_or_else(not_a_terminal)?;
let output = console(STD_OUTPUT_HANDLE);
if unsafe { SetConsoleMode(input.0, windows_input_mode(input.1)) } == 0 {
return Err(io::Error::last_os_error());
}
if let Some((handle, mode)) = output {
unsafe { SetConsoleMode(handle, windows_output_mode(mode)) };
}
Ok(Saved { input, output })
}
pub(super) fn restore(saved: &Saved) {
unsafe { SetConsoleMode(saved.input.0, saved.input.1) };
if let Some((handle, mode)) = saved.output {
unsafe { SetConsoleMode(handle, mode) };
}
}