summaryrefslogtreecommitdiffstats
path: root/rsnix/src/ps2.rs
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-07-31 17:19:09 +0200
committersalmonik <salmonik@tuta.io>2026-07-31 17:19:09 +0200
commitfa06681a8418b7e31af96e010bb424e178402f4d (patch)
tree3b2fa8674384078f73b62274c71e8279ca6d0644 /rsnix/src/ps2.rs
parentshell: ^C cancels the line / aborts streams, ^D = EOF → poweroff (diff)
downloadrs-dos-fa06681a8418b7e31af96e010bb424e178402f4d.tar.gz
rs-dos-fa06681a8418b7e31af96e010bb424e178402f4d.zip
tty + vt terminal split, rsdosedit editor (1:1 UNIX console)
Kernel now has the classic UNIX console split, so full-screen ANSI apps can run in ring 0: - vt.rs: terminal emulator owning the text screen — cell grid (char + fg/bg), logical cursor (inverse-video), scrolling, and a small ANSI CSI parser (cursor position H/f, erase J/K, moves A-D, SGR 16-colour with correct ANSI→VGA mapping, cursor show/hide ?25). Blits only changed cells; scroll shifts cell grids + pixels and re-rasterises only the exposed bottom row. gop_println!/clear_screen now render through the vt; gop.rs is the raw rasteriser (colored glyph blits, pixel shift). - tty.rs: line discipline — canonical read_line (echo, line buffer, ^C cancel, ^D EOF) moved out of the shell, and raw read_byte that translates KeyEvents to the terminal byte protocol (arrows → ESC[A-D, Backspace → 0x7f, ^X → 0x18, Ctrl+arrows → ESC[1;5A-D, Home/End/PgUp/ PgDn/Delete). interrupt_pressed() stays for streaming commands. - ps2: generic Ctrl(char) + CtrlArrow events (was: only CtrlC/CtrlD). - rsdosedit: no_std port of the RNG rsedit editor as the first real app — undo, syntax highlighting (verified green/gray/yellow on the framebuffer), search, word nav, smart indent, ^S save / ^X exit / ^X again to discard. termios → tty raw, stdout → vt, std::fs → VFS (ramfs), SIGWINCH → fixed geometry, force-exit window → key counter. - shell: 'edit <path>' command; read_line/strbuf moved to rsnix. - CONTEXT.md: layout + milestones + known-issue perf notes. Verified in QEMU: full edit → type → arrow-move → insert → save → exit round trip with byte-exact file content; ANSI colors via screendump.
Diffstat (limited to 'rsnix/src/ps2.rs')
-rw-r--r--rsnix/src/ps2.rs31
1 files changed, 20 insertions, 11 deletions
diff --git a/rsnix/src/ps2.rs b/rsnix/src/ps2.rs
index 1b10b3b..8dd58a0 100644
--- a/rsnix/src/ps2.rs
+++ b/rsnix/src/ps2.rs
@@ -22,8 +22,10 @@ pub enum KeyEvent {
22 Backspace, 22 Backspace,
23 Tab, 23 Tab,
24 Escape, 24 Escape,
25 CtrlC, 25 /// Ctrl + key (e.g. Ctrl('c') = ^C, Ctrl('s') = ^S).
26 CtrlD, 26 Ctrl(char),
27 /// Ctrl + arrow (0=up, 1=down, 2=left, 3=right) — word/page nav.
28 CtrlArrow(u8),
27 ArrowUp, 29 ArrowUp,
28 ArrowDown, 30 ArrowDown,
29 ArrowLeft, 31 ArrowLeft,
@@ -306,13 +308,14 @@ fn process_byte(byte: u8) -> Option<KeyEvent> {
306 ch.to_ascii_uppercase() 308 ch.to_ascii_uppercase()
307 }; 309 };
308 } 310 }
309 // Ctrl+letter — the shell uses ^C (interrupt) and ^D (EOF). 311 // Ctrl+key — the terminal control-byte protocol (^C, ^D, ^S, ^X, …).
310 let ctrl = state.modifiers & (MOD_LCTRL | MOD_RCTRL) != 0; 312 let ctrl = state.modifiers & (MOD_LCTRL | MOD_RCTRL) != 0;
311 if ctrl { 313 if ctrl {
312 return match ch.to_ascii_lowercase() { 314 let lc = ch.to_ascii_lowercase();
313 b'c' => Some(KeyEvent::CtrlC), 315 return if lc.is_ascii_graphic() {
314 b'd' => Some(KeyEvent::CtrlD), 316 Some(KeyEvent::Ctrl(lc as char))
315 _ => None, // swallow other Ctrl+key combinations 317 } else {
318 None // swallow non-graphic Ctrl combos
316 }; 319 };
317 } 320 }
318 if ch != 0 { 321 if ch != 0 {
@@ -334,10 +337,10 @@ fn process_e0(byte: u8) -> Option<KeyEvent> {
334 update_modifiers(byte, true, true); 337 update_modifiers(byte, true, true);
335 338
336 match byte { 339 match byte {
337 0x48 => Some(KeyEvent::ArrowUp), 340 0x48 => Some(if ctrl_held() { KeyEvent::CtrlArrow(0) } else { KeyEvent::ArrowUp }),
338 0x50 => Some(KeyEvent::ArrowDown), 341 0x50 => Some(if ctrl_held() { KeyEvent::CtrlArrow(1) } else { KeyEvent::ArrowDown }),
339 0x4B => Some(KeyEvent::ArrowLeft), 342 0x4B => Some(if ctrl_held() { KeyEvent::CtrlArrow(2) } else { KeyEvent::ArrowLeft }),
340 0x4D => Some(KeyEvent::ArrowRight), 343 0x4D => Some(if ctrl_held() { KeyEvent::CtrlArrow(3) } else { KeyEvent::ArrowRight }),
341 0x47 => Some(KeyEvent::Home), 344 0x47 => Some(KeyEvent::Home),
342 0x4F => Some(KeyEvent::End), 345 0x4F => Some(KeyEvent::End),
343 0x49 => Some(KeyEvent::PageUp), 346 0x49 => Some(KeyEvent::PageUp),
@@ -371,3 +374,9 @@ fn set_mod(state: &mut KbdState, bit: u8, pressed: bool) {
371 state.modifiers &= !bit; 374 state.modifiers &= !bit;
372 } 375 }
373} 376}
377
378/// Is either Ctrl key held?
379fn ctrl_held() -> bool {
380 let state = unsafe { &mut KBD };
381 state.modifiers & (MOD_LCTRL | MOD_RCTRL) != 0
382}