mirror of
https://github.com/Xyverle/neutuino.git
synced 2026-06-26 22:23:14 -04:00
Clean up and fix Windows code
This commit is contained in:
40
src/unix.rs
40
src/unix.rs
@@ -1,4 +1,5 @@
|
||||
use std::ffi::{c_int, c_short, c_uint, c_ulong, c_ushort};
|
||||
use std::io;
|
||||
|
||||
unsafe extern "C" {
|
||||
fn ioctl(fd: c_int, request: c_ulong, argp: *mut u8) -> c_int;
|
||||
@@ -10,6 +11,7 @@ unsafe extern "C" {
|
||||
const STDIN_FILENO: c_int = 0;
|
||||
const STDOUT_FILENO: c_int = 1;
|
||||
const POLLIN: c_short = 1;
|
||||
const ICRNL: c_uint = 0x40;
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
const TIOCGWINSZ: c_ulong = 0x5413;
|
||||
@@ -40,11 +42,29 @@ struct Termios {
|
||||
cc: [u8; NCCS],
|
||||
}
|
||||
|
||||
fn get_attributes(fd: c_int, termios: &mut Termios) -> io::Result<()> {
|
||||
if unsafe { tcgetattr(fd, &raw mut *termios) } != 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_attributes(fd: c_int, termios: &mut Termios) -> io::Result<()> {
|
||||
if unsafe { tcsetattr(fd, 0, std::ptr::from_mut(termios)) } != 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn make_raw(termios: &mut Termios) {
|
||||
cfmakeraw(termios);
|
||||
termios.iflag |= !(ICRNL);
|
||||
}
|
||||
|
||||
pub mod os {
|
||||
use super::{STDIN_FILENO, STDOUT_FILENO, TIOCGWINSZ};
|
||||
use super::{Termios, Winsize};
|
||||
use super::{cfmakeraw, ioctl, tcgetattr, tcsetattr};
|
||||
use std::ffi::c_int;
|
||||
use super::{get_attributes, set_attributes, make_raw, ioctl};
|
||||
use std::io;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
@@ -64,7 +84,7 @@ pub mod os {
|
||||
pub fn enable_raw_mode() -> io::Result<()> {
|
||||
let mut termios =
|
||||
(*TERMIOS).ok_or(io::Error::other("Failed to get terminal properties"))?;
|
||||
cfmakeraw(&raw mut termios);
|
||||
make_raw(&mut termios);
|
||||
set_attributes(STDIN_FILENO, &mut termios)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -120,20 +140,6 @@ pub mod os {
|
||||
Err(io::Error::last_os_error())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_attributes(fd: c_int, termios: &mut Termios) -> io::Result<()> {
|
||||
if unsafe { tcgetattr(fd, &raw mut *termios) } != 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_attributes(fd: c_int, termios: &mut Termios) -> io::Result<()> {
|
||||
if unsafe { tcsetattr(fd, 0, std::ptr::from_mut(termios)) } != 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub mod input {
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
use std::io;
|
||||
use std::os::windows::raw::HANDLE;
|
||||
|
||||
#[link(name = "kernel32")]
|
||||
unsafe extern "system" {
|
||||
fn GetStdHandle(std_handle: u32) -> usize;
|
||||
fn GetConsoleMode(console_handle: usize, mode: *mut u32) -> u32;
|
||||
fn SetConsoleMode(console_handle: usize, mode: *mut u32) -> u32;
|
||||
fn GetStdHandle(std_handle: i32) -> HANDLE;
|
||||
fn GetConsoleMode(console_handle: HANDLE, mode: *mut u32) -> u32;
|
||||
fn SetConsoleMode(console_handle: HANDLE, mode: u32) -> u32;
|
||||
fn GetConsoleScreenBufferInfo(
|
||||
console_output: usize,
|
||||
console_output: HANDLE,
|
||||
console_screen_buffer_info: *mut ConsoleScreenBufferInfo,
|
||||
) -> u32;
|
||||
}
|
||||
|
||||
const STD_INPUT_HANDLE: u32 = 0xFFFF_FFF6;
|
||||
const STD_OUTPUT_HANDLE: u32 = 0xFFFF_FFF5;
|
||||
const STD_INPUT_HANDLE: i32 = -10;
|
||||
const STD_OUTPUT_HANDLE: i32 = -11;
|
||||
const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 4;
|
||||
const ENABLE_ECHO_INPUT: u32 = 4;
|
||||
const ENABLE_LINE_INPUT: u32 = 2;
|
||||
const ENABLE_PROCESSED_INPUT: u32 = 1;
|
||||
const INVALID_HANDLE_VALUE: usize = usize::MAX - 1;
|
||||
const INVALID_HANDLE_VALUE: HANDLE = -1isize as HANDLE;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Default)]
|
||||
@@ -26,8 +28,8 @@ struct ConsoleScreenBufferInfo {
|
||||
_unused: [u16; 9],
|
||||
}
|
||||
|
||||
fn get_std_handle(handle: u32) -> io::Result<usize> {
|
||||
let handle = unsafe { GetStdHandle(handle) };
|
||||
fn get_stdin_handle() -> io::Result<HANDLE> {
|
||||
let handle = unsafe { GetStdHandle(STD_INPUT_HANDLE) };
|
||||
if handle == INVALID_HANDLE_VALUE {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
@@ -35,7 +37,16 @@ fn get_std_handle(handle: u32) -> io::Result<usize> {
|
||||
}
|
||||
}
|
||||
|
||||
fn set_console_mode(handle: usize, mode: &mut u32) -> io::Result<()> {
|
||||
fn get_stdout_handle() -> io::Result<HANDLE> {
|
||||
let handle = unsafe { GetStdHandle(STD_OUTPUT_HANDLE) };
|
||||
if handle == INVALID_HANDLE_VALUE {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(handle)
|
||||
}
|
||||
}
|
||||
|
||||
fn set_console_mode(handle: HANDLE, mode: u32) -> io::Result<()> {
|
||||
if unsafe { SetConsoleMode(handle, mode) == 0 } {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
@@ -43,7 +54,7 @@ fn set_console_mode(handle: usize, mode: &mut u32) -> io::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_console_mode(handle: usize, mode: &mut u32) -> io::Result<()> {
|
||||
fn get_console_mode(handle: HANDLE, mode: &mut u32) -> io::Result<()> {
|
||||
if unsafe { GetConsoleMode(handle, mode) == 0 } {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
@@ -52,12 +63,11 @@ fn get_console_mode(handle: usize, mode: &mut u32) -> io::Result<()> {
|
||||
}
|
||||
|
||||
pub mod os {
|
||||
use super::{ConsoleScreenBufferInfo, get_console_mode, get_std_handle, set_console_mode};
|
||||
use super::{GetConsoleScreenBufferInfo, ConsoleScreenBufferInfo, get_console_mode, get_stdin_handle, get_stdout_handle, set_console_mode};
|
||||
use super::{
|
||||
ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT,
|
||||
ENABLE_VIRTUAL_TERMINAL_PROCESSING,
|
||||
};
|
||||
use super::{GetConsoleScreenBufferInfo, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE};
|
||||
use std::io;
|
||||
|
||||
/// Enables raw mode, which disables line buffering, input echoing, and output canonicalization
|
||||
@@ -68,11 +78,11 @@ pub mod os {
|
||||
/// stdin is not a tty,
|
||||
/// or it fails to change terminal settings
|
||||
pub fn enable_raw_mode() -> io::Result<()> {
|
||||
let handle = get_std_handle(STD_INPUT_HANDLE)?;
|
||||
let handle = get_stdin_handle()?;
|
||||
let mut mode = 0;
|
||||
get_console_mode(handle, &mut mode)?;
|
||||
mode &= !(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
|
||||
set_console_mode(handle, &mut mode)?;
|
||||
set_console_mode(handle, mode)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -84,11 +94,11 @@ pub mod os {
|
||||
/// stdin is not a tty,
|
||||
/// or it fails to change terminal settings
|
||||
pub fn disable_raw_mode() -> io::Result<()> {
|
||||
let handle = get_std_handle(STD_INPUT_HANDLE)?;
|
||||
let handle = get_stdin_handle()?;
|
||||
let mut mode = 0;
|
||||
get_console_mode(handle, &mut mode)?;
|
||||
mode |= ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
|
||||
set_console_mode(handle, &mut mode)?;
|
||||
set_console_mode(handle, mode)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -104,11 +114,11 @@ pub mod os {
|
||||
/// if stdout isn't a TTY, or
|
||||
/// if it cannot change terminal properties
|
||||
pub fn enable_ansi() -> io::Result<()> {
|
||||
let handle = get_std_handle(STD_OUTPUT_HANDLE)?;
|
||||
let handle = get_stdout_handle()?;
|
||||
let mut mode = 0;
|
||||
get_console_mode(handle, &mut mode)?;
|
||||
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
set_console_mode(handle, &mut mode)?;
|
||||
set_console_mode(handle, mode)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -122,7 +132,7 @@ pub mod os {
|
||||
/// if stdout isn't a TTY, or
|
||||
/// if it fails to retrieve the terminal size
|
||||
pub fn get_terminal_size() -> io::Result<(u16, u16)> {
|
||||
let handle = get_std_handle(STD_OUTPUT_HANDLE)?;
|
||||
let handle = get_stdout_handle()?;
|
||||
let mut csbi = ConsoleScreenBufferInfo::default();
|
||||
if unsafe { GetConsoleScreenBufferInfo(handle, &mut csbi) != 0 } {
|
||||
let width = csbi.x;
|
||||
@@ -134,10 +144,11 @@ pub mod os {
|
||||
}
|
||||
|
||||
pub mod input {
|
||||
use super::{STD_INPUT_HANDLE, get_std_handle};
|
||||
use super::get_stdin_handle;
|
||||
use crate::input::{Event, KeyEvent};
|
||||
|
||||
use std::{io, mem, time::Duration};
|
||||
use std::os::windows::raw::HANDLE;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
@@ -179,12 +190,12 @@ pub mod input {
|
||||
|
||||
unsafe extern "system" {
|
||||
fn ReadConsoleInputW(
|
||||
console_input: usize,
|
||||
console_input: HANDLE,
|
||||
buffer: *mut InputRecord,
|
||||
length: u32,
|
||||
number_of_events_read: *mut u32,
|
||||
) -> i32;
|
||||
fn WaitForSingleObject(handle: usize, wait_time_ms: u32) -> u32;
|
||||
fn WaitForSingleObject(handle: HANDLE, wait_time_ms: u32) -> u32;
|
||||
}
|
||||
|
||||
/// Attempts to fetch input from stdin
|
||||
@@ -193,7 +204,7 @@ pub mod input {
|
||||
/// If the timeout has expired or
|
||||
/// there was an error getting the data
|
||||
pub fn poll_input(timeout: Duration) -> io::Result<Event> {
|
||||
let handle = get_std_handle(STD_INPUT_HANDLE)?;
|
||||
let handle = get_stdin_handle()?;
|
||||
let mut record: InputRecord = unsafe { mem::zeroed() };
|
||||
let mut read = 0;
|
||||
|
||||
@@ -222,7 +233,10 @@ pub mod input {
|
||||
// Key Event
|
||||
let key_event: KeyEventRecord = unsafe { record.event.key };
|
||||
if key_event.key_down == 0 {
|
||||
return Ok(Event::Key(KeyEvent::Null));
|
||||
// return Ok(Event::Key(KeyEvent::Null));
|
||||
// I don't quite know why but this seems to happen a lot, until I investigate
|
||||
// more this will have to do
|
||||
return Err(io::ErrorKind::Other.into());
|
||||
}
|
||||
Ok(Event::Key(parse_key_event(&key_event)))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user