set the code page correctly

parse-tree
Jordan Orelli 2 years ago
parent 05c3d0832c
commit edcabd16c7

@ -1,37 +1,39 @@
mod error; mod error;
mod log; mod log;
use std::ffi::OsString;
use windows::Win32::{Foundation::HANDLE, System::Console}; use windows::Win32::{Foundation::HANDLE, System::Console};
use windows::{h, s, w};
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use crate::{error::Error, log::*}; use crate::{error::Error, log::*};
fn print_input_mode(mode: Console::CONSOLE_MODE) { fn log_input_mode(mode: Console::CONSOLE_MODE) {
// Characters read by the ReadFile or ReadConsole function are written to the active screen // Characters read by the ReadFile or ReadConsole function are written to the active screen
// buffer as they are typed into the console. This mode can be used only if the // buffer as they are typed into the console. This mode can be used only if the
// ENABLE_LINE_INPUT mode is also enabled. // ENABLE_LINE_INPUT mode is also enabled.
if (mode & Console::ENABLE_ECHO_INPUT).0 > 0 { if (mode & Console::ENABLE_ECHO_INPUT).0 > 0 {
println!("Echo Input: Enabled"); debug!("Echo Input: Enabled");
} else { } else {
println!("Echo Input: Disabled"); debug!("Echo Input: Disabled");
} }
// When enabled, text entered in a console window will be inserted at the current cursor // When enabled, text entered in a console window will be inserted at the current cursor
// location and all text following that location will not be overwritten. When disabled, all // location and all text following that location will not be overwritten. When disabled, all
// following text will be overwritten. // following text will be overwritten.
if (mode & Console::ENABLE_INSERT_MODE).0 > 0 { if (mode & Console::ENABLE_INSERT_MODE).0 > 0 {
println!("Insert Mode: Enabled"); debug!("Insert Mode: Enabled");
} else { } else {
println!("Insert Mode: Disabled"); debug!("Insert Mode: Disabled");
} }
// The ReadFile or ReadConsole function returns only when a carriage return character is read. // The ReadFile or ReadConsole function returns only when a carriage return character is read.
// If this mode is disabled, the functions return when one or more characters are available. // If this mode is disabled, the functions return when one or more characters are available.
if (mode & Console::ENABLE_LINE_INPUT).0 > 0 { if (mode & Console::ENABLE_LINE_INPUT).0 > 0 {
println!("Line Input Mode: Enabled"); debug!("Line Input Mode: Enabled");
} else { } else {
println!("Line Input Mode: Disabled"); debug!("Line Input Mode: Disabled");
} }
// If the mouse pointer is within the borders of the console window and the window has the // If the mouse pointer is within the borders of the console window and the window has the
@ -40,9 +42,9 @@ fn print_input_mode(mode: Console::CONSOLE_MODE) {
// is enabled. The ReadConsoleInput function can be used to read MOUSE_EVENT input records from // is enabled. The ReadConsoleInput function can be used to read MOUSE_EVENT input records from
// the input buffer. // the input buffer.
if (mode & Console::ENABLE_MOUSE_INPUT).0 > 0 { if (mode & Console::ENABLE_MOUSE_INPUT).0 > 0 {
println!("Mouse Input: Enabled"); debug!("Mouse Input: Enabled");
} else { } else {
println!("Mouse Input: Disabled"); debug!("Mouse Input: Disabled");
} }
// CTRL+C is processed by the system and is not placed in the input buffer. If the input buffer // CTRL+C is processed by the system and is not placed in the input buffer. If the input buffer
@ -51,18 +53,18 @@ fn print_input_mode(mode: Console::CONSOLE_MODE) {
// also enabled, backspace, carriage return, and line feed characters are handled by the // also enabled, backspace, carriage return, and line feed characters are handled by the
// system. // system.
if (mode & Console::ENABLE_PROCESSED_INPUT).0 > 0 { if (mode & Console::ENABLE_PROCESSED_INPUT).0 > 0 {
println!("Processed Input: Enabled"); debug!("Processed Input: Enabled");
} else { } else {
println!("Processed Input: Disabled"); debug!("Processed Input: Disabled");
} }
// This flag enables the user to use the mouse to select and edit text. To enable this mode, // This flag enables the user to use the mouse to select and edit text. To enable this mode,
// use ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS. To disable this mode, use // use ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS. To disable this mode, use
// ENABLE_EXTENDED_FLAGS without this flag. // ENABLE_EXTENDED_FLAGS without this flag.
if (mode & Console::ENABLE_QUICK_EDIT_MODE).0 > 0 { if (mode & Console::ENABLE_QUICK_EDIT_MODE).0 > 0 {
println!("Quick Edit Mode: Enabled"); debug!("Quick Edit Mode: Enabled");
} else { } else {
println!("Quick Edit Mode: Disabled"); debug!("Quick Edit Mode: Disabled");
} }
// User interactions that change the size of the console screen buffer are reported in the // User interactions that change the size of the console screen buffer are reported in the
@ -70,9 +72,9 @@ fn print_input_mode(mode: Console::CONSOLE_MODE) {
// applications using the ReadConsoleInput function, but not by those using ReadFile or // applications using the ReadConsoleInput function, but not by those using ReadFile or
// ReadConsole. // ReadConsole.
if (mode & Console::ENABLE_WINDOW_INPUT).0 > 0 { if (mode & Console::ENABLE_WINDOW_INPUT).0 > 0 {
println!("Window Input: Enabled"); debug!("Window Input: Enabled");
} else { } else {
println!("Window Input: Disabled"); debug!("Window Input: Disabled");
} }
// Setting this flag directs the Virtual Terminal processing engine to convert user input // Setting this flag directs the Virtual Terminal processing engine to convert user input
@ -83,22 +85,22 @@ fn print_input_mode(mode: Console::CONSOLE_MODE) {
// ENABLE_VIRTUAL_TERMINAL_PROCESSING on the output handle to connect to an application that // ENABLE_VIRTUAL_TERMINAL_PROCESSING on the output handle to connect to an application that
// communicates exclusively via virtual terminal sequences. // communicates exclusively via virtual terminal sequences.
if (mode & Console::ENABLE_VIRTUAL_TERMINAL_INPUT).0 > 0 { if (mode & Console::ENABLE_VIRTUAL_TERMINAL_INPUT).0 > 0 {
println!("Virtual Terminal Input: Enabled"); debug!("Virtual Terminal Input: Enabled");
} else { } else {
println!("Virtual Terminal Input: Disabled"); debug!("Virtual Terminal Input: Disabled");
} }
} }
fn print_output_mode(mode: Console::CONSOLE_MODE) { fn log_output_mode(mode: Console::CONSOLE_MODE) {
// Characters written by the WriteFile or WriteConsole function or echoed by the ReadFile or // Characters written by the WriteFile or WriteConsole function or echoed by the ReadFile or
// ReadConsole function are parsed for ASCII control sequences, and the correct action is // ReadConsole function are parsed for ASCII control sequences, and the correct action is
// performed. Backspace, tab, bell, carriage return, and line feed characters are processed. It // performed. Backspace, tab, bell, carriage return, and line feed characters are processed. It
// should be enabled when using control sequences or when ENABLE_VIRTUAL_TERMINAL_PROCESSING is // should be enabled when using control sequences or when ENABLE_VIRTUAL_TERMINAL_PROCESSING is
// set. // set.
if (mode & Console::ENABLE_PROCESSED_OUTPUT).0 > 0 { if (mode & Console::ENABLE_PROCESSED_OUTPUT).0 > 0 {
println!("Processed Output: Enabled"); debug!("Processed Output: Enabled");
} else { } else {
println!("Processed Output: Disabled"); debug!("Processed Output: Disabled");
} }
// When writing with WriteFile or WriteConsole or echoing with ReadFile or ReadConsole, the // When writing with WriteFile or WriteConsole or echoing with ReadFile or ReadConsole, the
@ -109,9 +111,9 @@ fn print_output_mode(mode: Console::CONSOLE_MODE) {
// when the cursor advances beyond the last row in the console screen buffer. If this mode is // when the cursor advances beyond the last row in the console screen buffer. If this mode is
// disabled, the last character in the row is overwritten with any subsequent characters. // disabled, the last character in the row is overwritten with any subsequent characters.
if (mode & Console::ENABLE_WRAP_AT_EOL_OUTPUT).0 > 0 { if (mode & Console::ENABLE_WRAP_AT_EOL_OUTPUT).0 > 0 {
println!("Wrap at EOL: Enabled"); debug!("Wrap at EOL: Enabled");
} else { } else {
println!("Wrap at EOL: Disabled"); debug!("Wrap at EOL: Disabled");
} }
// When writing with WriteFile or WriteConsole, characters are parsed for VT100 and similar // When writing with WriteFile or WriteConsole, characters are parsed for VT100 and similar
@ -121,9 +123,9 @@ fn print_output_mode(mode: Console::CONSOLE_MODE) {
// //
// Ensure ENABLE_PROCESSED_OUTPUT is set when using this flag. // Ensure ENABLE_PROCESSED_OUTPUT is set when using this flag.
if (mode & Console::ENABLE_VIRTUAL_TERMINAL_PROCESSING).0 > 0 { if (mode & Console::ENABLE_VIRTUAL_TERMINAL_PROCESSING).0 > 0 {
println!("Terminal Processing: Enabled"); debug!("Terminal Processing: Enabled");
} else { } else {
println!("Terminal Processing: Disabled"); debug!("Terminal Processing: Disabled");
} }
// When writing with WriteFile or WriteConsole, this adds an additional state to end-of-line // When writing with WriteFile or WriteConsole, this adds an additional state to end-of-line
@ -144,9 +146,9 @@ fn print_output_mode(mode: Console::CONSOLE_MODE) {
// final character on the screen (../in the bottom right corner) without triggering an // final character on the screen (../in the bottom right corner) without triggering an
// immediate scroll is the desired behavior. // immediate scroll is the desired behavior.
if (mode & Console::DISABLE_NEWLINE_AUTO_RETURN).0 > 0 { if (mode & Console::DISABLE_NEWLINE_AUTO_RETURN).0 > 0 {
println!("Newline Auto Return: Enabled"); debug!("Newline Auto Return: Enabled");
} else { } else {
println!("Newline Auto Return: Disabled"); debug!("Newline Auto Return: Disabled");
} }
// The APIs for writing character attributes including WriteConsoleOutput and // The APIs for writing character attributes including WriteConsoleOutput and
@ -170,9 +172,9 @@ fn print_output_mode(mode: Console::CONSOLE_MODE) {
// reverse video flags being set while this flag is still off if the attached application // reverse video flags being set while this flag is still off if the attached application
// requests underlining or inverse video via Console Virtual Terminal Sequences. // requests underlining or inverse video via Console Virtual Terminal Sequences.
if (mode & Console::ENABLE_LVB_GRID_WORLDWIDE).0 > 0 { if (mode & Console::ENABLE_LVB_GRID_WORLDWIDE).0 > 0 {
println!("LVB Grid: Enabled"); debug!("LVB Grid: Enabled");
} else { } else {
println!("LVB Grid: Disabled"); debug!("LVB Grid: Disabled");
} }
} }
@ -215,19 +217,23 @@ fn setup_stdin() -> Result<()> {
Error::check(Console::SetConsoleMode(handle, mode))?; Error::check(Console::SetConsoleMode(handle, mode))?;
Error::check(Console::GetConsoleMode(handle, &mut mode))?; Error::check(Console::GetConsoleMode(handle, &mut mode))?;
println!("Stdin details:"); debug!("Stdin details:");
print_input_mode(mode); log_input_mode(mode);
} }
Ok(()) Ok(())
} }
fn setup_stdout() -> Result<()> { fn setup_stdout() -> Result<()> {
unsafe {
Console::SetConsoleOutputCP(65001);
}
let mut mode = Console::CONSOLE_MODE(0); let mut mode = Console::CONSOLE_MODE(0);
unsafe { unsafe {
let handle = stdout_handle()?; let handle = stdout_handle()?;
if Console::GetConsoleMode(handle, &mut mode).as_bool() { if Console::GetConsoleMode(handle, &mut mode).as_bool() {
println!("Stdout details:"); debug!("Stdout details:");
print_output_mode(mode); log_output_mode(mode);
} else { } else {
return Err(Error::last_error().into()); return Err(Error::last_error().into());
} }
@ -241,23 +247,24 @@ fn main() -> Result<()> {
setup_stdout()?; setup_stdout()?;
let stdin = stdin_handle()?; let stdin = stdin_handle()?;
let stdout = stdout_handle()?;
let mut buf = [Console::INPUT_RECORD::default(); 100]; let mut buf = [Console::INPUT_RECORD::default(); 100];
loop { loop {
let mut n: u32 = 0; let mut n: u32 = 0;
unsafe { unsafe {
Error::check(Console::ReadConsoleInputW(stdin, &mut buf, &mut n))?; Error::check(Console::ReadConsoleInputW(stdin, &mut buf, &mut n))?;
} }
let n = n as usize; let n = n as usize;
println!("read: {:?}", n);
for rec in &buf[0..n] { for rec in &buf[0..n] {
println!("Event Type: {}", rec.EventType); debug!("Event Type: {}", rec.EventType);
match rec.EventType as u32 { match rec.EventType as u32 {
Console::FOCUS_EVENT => { Console::FOCUS_EVENT => {
// The Event member contains a FOCUS_EVENT_RECORD structure. These events are // The Event member contains a FOCUS_EVENT_RECORD structure. These events are
// used internally and should be ignored. // used internally and should be ignored.
unsafe { unsafe {
let event = rec.Event.FocusEvent; let event = rec.Event.FocusEvent;
println!("Focus Event: {:?}", event); debug!("Focus Event: {:?}", event);
} }
} }
Console::MENU_EVENT => { Console::MENU_EVENT => {
@ -265,7 +272,7 @@ fn main() -> Result<()> {
// used internally and should be ignored. // used internally and should be ignored.
unsafe { unsafe {
let event = rec.Event.MenuEvent; let event = rec.Event.MenuEvent;
println!("Menu Event: {:?}", event); debug!("Menu Event: {:?}", event);
} }
} }
Console::KEY_EVENT => { Console::KEY_EVENT => {
@ -273,13 +280,72 @@ fn main() -> Result<()> {
// about a keyboard event. // about a keyboard event.
unsafe { unsafe {
let event = rec.Event.KeyEvent; let event = rec.Event.KeyEvent;
let down = event.bKeyDown; let down = event.bKeyDown.as_bool();
let repeats = event.wRepeatCount; let repeats = event.wRepeatCount;
let key_code = event.wVirtualKeyCode; let key_code = event.wVirtualKeyCode;
let scan_code = event.wVirtualScanCode; let scan_code = event.wVirtualScanCode;
let c = event.uChar.UnicodeChar; let c = event.uChar.UnicodeChar;
let modifiers = event.dwControlKeyState; let modifiers = event.dwControlKeyState;
println!( // handle key presses on key up, not key down. This is a little weird but
// it's sending both down and up events when you hit the key anyway. I
// dunno if this is right. But for some reason, the down events don't have
// the modifiers
if !down {
// Carriage Return (Enter key)
if c == 13 {
let mask = Console::LEFT_ALT_PRESSED
| Console::RIGHT_ALT_PRESSED
| Console::LEFT_CTRL_PRESSED
| Console::RIGHT_CTRL_PRESSED
| Console::SHIFT_PRESSED;
if modifiers & mask == 0 {
Error::check(Console::WriteConsoleA(
stdout,
"\r\n".as_bytes(),
None,
None,
))?;
}
} else if key_code == 74 && modifiers == 40 {
// key j modifier ctrl
// let text = "X";
let text = "•";
// let z = text.encode_utf16().map(|c| c.to_ne_bytes());
//let t16: Vec<u16> = text
// .encode_utf16()
// .chain(std::iter::once(0 as u16))
// .collect();
// t16.as_ptr()
// let (_, k, _) = t16.align_to::<u8>();
// let x: &[u8] = &[0x20, 0x22, 0x00, 0x00];
//let x: &[u16] = &[0x2022];
//let mut z = x[0].to_ne_bytes();
//let z: [u8] = [(0x2022 as u16).to_ne_bytes()];
//let mut z = Vec<u8>::new();
//text.as_bytes()
Error::check(Console::WriteConsoleA(
stdout,
text.as_bytes(),
None,
None,
))?;
} else {
if let Some(c) = char::from_u32(event.uChar.UnicodeChar as u32) {
if !c.is_control() {
let mut buf = [0 as u8; 2];
let s = c.encode_utf8(&mut buf);
Error::check(Console::WriteConsoleW(
stdout,
s.as_bytes(),
None,
None,
))?;
}
}
}
}
debug!(
"Key Event: down: {down:?} repeats: {repeats} key-code: {key_code} scan-code: {scan_code} char: {c} modifiers: {modifiers}" "Key Event: down: {down:?} repeats: {repeats} key-code: {key_code} scan-code: {scan_code} char: {c} modifiers: {modifiers}"
); );
} }
@ -289,7 +355,7 @@ fn main() -> Result<()> {
// about a mouse movement or button press event. // about a mouse movement or button press event.
unsafe { unsafe {
let event = rec.Event.MouseEvent; let event = rec.Event.MouseEvent;
println!("Mouse Event: {:?}", event); debug!("Mouse Event: {:?}", event);
} }
} }
Console::WINDOW_BUFFER_SIZE_EVENT => { Console::WINDOW_BUFFER_SIZE_EVENT => {
@ -297,7 +363,7 @@ fn main() -> Result<()> {
// information about the new size of the console screen buffer. // information about the new size of the console screen buffer.
unsafe { unsafe {
let event = rec.Event.WindowBufferSizeEvent; let event = rec.Event.WindowBufferSizeEvent;
println!("Window Buffer Event: {:?}", event); debug!("Window Buffer Event: {:?}", event);
} }
} }
_ => {} _ => {}

Loading…
Cancel
Save