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