1use std::mem;
10
11use crate::helpers::{CoordType, Point, Size};
12use crate::vt;
13
14#[repr(transparent)]
21#[derive(Clone, Copy, PartialEq, Eq)]
22pub struct InputKey(u32);
23
24impl InputKey {
25 pub(crate) const fn new(v: u32) -> Self {
26 Self(v)
27 }
28
29 pub(crate) const fn from_ascii(ch: char) -> Option<Self> {
30 if ch == ' ' || (ch >= '0' && ch <= '9') {
31 Some(Self(ch as u32))
32 } else if ch >= 'a' && ch <= 'z' {
33 Some(Self(ch as u32 & !0x20)) } else if ch >= 'A' && ch <= 'Z' {
35 Some(Self(kbmod::SHIFT.0 | ch as u32))
36 } else {
37 None
38 }
39 }
40
41 pub(crate) const fn value(&self) -> u32 {
42 self.0
43 }
44
45 pub(crate) const fn key(&self) -> Self {
46 Self(self.0 & 0x00FFFFFF)
47 }
48
49 pub(crate) const fn modifiers(&self) -> InputKeyMod {
50 InputKeyMod(self.0 & 0xFF000000)
51 }
52
53 pub(crate) const fn modifiers_contains(&self, modifier: InputKeyMod) -> bool {
54 (self.0 & modifier.0) != 0
55 }
56
57 pub(crate) const fn with_modifiers(&self, modifiers: InputKeyMod) -> Self {
58 Self(self.0 | modifiers.0)
59 }
60}
61
62#[repr(transparent)]
64#[derive(Clone, Copy, PartialEq, Eq)]
65pub struct InputKeyMod(u32);
66
67impl InputKeyMod {
68 const fn new(v: u32) -> Self {
69 Self(v)
70 }
71
72 pub(crate) const fn contains(&self, modifier: Self) -> bool {
73 (self.0 & modifier.0) != 0
74 }
75}
76
77impl std::ops::BitOr<InputKeyMod> for InputKey {
78 type Output = Self;
79
80 fn bitor(self, rhs: InputKeyMod) -> Self {
81 Self(self.0 | rhs.0)
82 }
83}
84
85impl std::ops::BitOr<InputKey> for InputKeyMod {
86 type Output = InputKey;
87
88 fn bitor(self, rhs: InputKey) -> InputKey {
89 InputKey(self.0 | rhs.0)
90 }
91}
92
93impl std::ops::BitOrAssign for InputKeyMod {
94 fn bitor_assign(&mut self, rhs: Self) {
95 self.0 |= rhs.0;
96 }
97}
98
99pub mod vk {
104 use super::InputKey;
105
106 pub const NULL: InputKey = InputKey::new('\0' as u32);
107 pub const BACK: InputKey = InputKey::new(0x08);
108 pub const TAB: InputKey = InputKey::new('\t' as u32);
109 pub const RETURN: InputKey = InputKey::new('\r' as u32);
110 pub const ESCAPE: InputKey = InputKey::new(0x1B);
111 pub const SPACE: InputKey = InputKey::new(' ' as u32);
112 pub const PRIOR: InputKey = InputKey::new(0x21);
113 pub const NEXT: InputKey = InputKey::new(0x22);
114
115 pub const END: InputKey = InputKey::new(0x23);
116 pub const HOME: InputKey = InputKey::new(0x24);
117
118 pub const LEFT: InputKey = InputKey::new(0x25);
119 pub const UP: InputKey = InputKey::new(0x26);
120 pub const RIGHT: InputKey = InputKey::new(0x27);
121 pub const DOWN: InputKey = InputKey::new(0x28);
122
123 pub const INSERT: InputKey = InputKey::new(0x2D);
124 pub const DELETE: InputKey = InputKey::new(0x2E);
125
126 pub const N0: InputKey = InputKey::new('0' as u32);
127 pub const N1: InputKey = InputKey::new('1' as u32);
128 pub const N2: InputKey = InputKey::new('2' as u32);
129 pub const N3: InputKey = InputKey::new('3' as u32);
130 pub const N4: InputKey = InputKey::new('4' as u32);
131 pub const N5: InputKey = InputKey::new('5' as u32);
132 pub const N6: InputKey = InputKey::new('6' as u32);
133 pub const N7: InputKey = InputKey::new('7' as u32);
134 pub const N8: InputKey = InputKey::new('8' as u32);
135 pub const N9: InputKey = InputKey::new('9' as u32);
136
137 pub const A: InputKey = InputKey::new('A' as u32);
138 pub const B: InputKey = InputKey::new('B' as u32);
139 pub const C: InputKey = InputKey::new('C' as u32);
140 pub const D: InputKey = InputKey::new('D' as u32);
141 pub const E: InputKey = InputKey::new('E' as u32);
142 pub const F: InputKey = InputKey::new('F' as u32);
143 pub const G: InputKey = InputKey::new('G' as u32);
144 pub const H: InputKey = InputKey::new('H' as u32);
145 pub const I: InputKey = InputKey::new('I' as u32);
146 pub const J: InputKey = InputKey::new('J' as u32);
147 pub const K: InputKey = InputKey::new('K' as u32);
148 pub const L: InputKey = InputKey::new('L' as u32);
149 pub const M: InputKey = InputKey::new('M' as u32);
150 pub const N: InputKey = InputKey::new('N' as u32);
151 pub const O: InputKey = InputKey::new('O' as u32);
152 pub const P: InputKey = InputKey::new('P' as u32);
153 pub const Q: InputKey = InputKey::new('Q' as u32);
154 pub const R: InputKey = InputKey::new('R' as u32);
155 pub const S: InputKey = InputKey::new('S' as u32);
156 pub const T: InputKey = InputKey::new('T' as u32);
157 pub const U: InputKey = InputKey::new('U' as u32);
158 pub const V: InputKey = InputKey::new('V' as u32);
159 pub const W: InputKey = InputKey::new('W' as u32);
160 pub const X: InputKey = InputKey::new('X' as u32);
161 pub const Y: InputKey = InputKey::new('Y' as u32);
162 pub const Z: InputKey = InputKey::new('Z' as u32);
163
164 pub const NUMPAD0: InputKey = InputKey::new(0x60);
165 pub const NUMPAD1: InputKey = InputKey::new(0x61);
166 pub const NUMPAD2: InputKey = InputKey::new(0x62);
167 pub const NUMPAD3: InputKey = InputKey::new(0x63);
168 pub const NUMPAD4: InputKey = InputKey::new(0x64);
169 pub const NUMPAD5: InputKey = InputKey::new(0x65);
170 pub const NUMPAD6: InputKey = InputKey::new(0x66);
171 pub const NUMPAD7: InputKey = InputKey::new(0x67);
172 pub const NUMPAD8: InputKey = InputKey::new(0x68);
173 pub const NUMPAD9: InputKey = InputKey::new(0x69);
174 pub const MULTIPLY: InputKey = InputKey::new(0x6A);
175 pub const ADD: InputKey = InputKey::new(0x6B);
176 pub const SEPARATOR: InputKey = InputKey::new(0x6C);
177 pub const SUBTRACT: InputKey = InputKey::new(0x6D);
178 pub const DECIMAL: InputKey = InputKey::new(0x6E);
179 pub const DIVIDE: InputKey = InputKey::new(0x6F);
180
181 pub const F1: InputKey = InputKey::new(0x70);
182 pub const F2: InputKey = InputKey::new(0x71);
183 pub const F3: InputKey = InputKey::new(0x72);
184 pub const F4: InputKey = InputKey::new(0x73);
185 pub const F5: InputKey = InputKey::new(0x74);
186 pub const F6: InputKey = InputKey::new(0x75);
187 pub const F7: InputKey = InputKey::new(0x76);
188 pub const F8: InputKey = InputKey::new(0x77);
189 pub const F9: InputKey = InputKey::new(0x78);
190 pub const F10: InputKey = InputKey::new(0x79);
191 pub const F11: InputKey = InputKey::new(0x7A);
192 pub const F12: InputKey = InputKey::new(0x7B);
193 pub const F13: InputKey = InputKey::new(0x7C);
194 pub const F14: InputKey = InputKey::new(0x7D);
195 pub const F15: InputKey = InputKey::new(0x7E);
196 pub const F16: InputKey = InputKey::new(0x7F);
197 pub const F17: InputKey = InputKey::new(0x80);
198 pub const F18: InputKey = InputKey::new(0x81);
199 pub const F19: InputKey = InputKey::new(0x82);
200 pub const F20: InputKey = InputKey::new(0x83);
201 pub const F21: InputKey = InputKey::new(0x84);
202 pub const F22: InputKey = InputKey::new(0x85);
203 pub const F23: InputKey = InputKey::new(0x86);
204 pub const F24: InputKey = InputKey::new(0x87);
205}
206
207pub mod kbmod {
209 use super::InputKeyMod;
210
211 pub const NONE: InputKeyMod = InputKeyMod::new(0x00000000);
212 pub const CTRL: InputKeyMod = InputKeyMod::new(0x01000000);
213 pub const ALT: InputKeyMod = InputKeyMod::new(0x02000000);
214 pub const SHIFT: InputKeyMod = InputKeyMod::new(0x04000000);
215
216 pub const CTRL_ALT: InputKeyMod = InputKeyMod::new(0x03000000);
217 pub const CTRL_SHIFT: InputKeyMod = InputKeyMod::new(0x05000000);
218 pub const ALT_SHIFT: InputKeyMod = InputKeyMod::new(0x06000000);
219 pub const CTRL_ALT_SHIFT: InputKeyMod = InputKeyMod::new(0x07000000);
220}
221
222#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
224pub enum InputMouseState {
225 #[default]
226 None,
227
228 Left,
230 Middle,
231 Right,
232
233 Release,
235 Scroll,
236}
237
238#[derive(Clone, Copy)]
240pub struct InputMouse {
241 pub state: InputMouseState,
243 pub modifiers: InputKeyMod,
245 pub position: Point,
247 pub scroll: Point,
249}
250
251pub enum Input<'input> {
253 Resize(Size),
255 Text(&'input str),
258 Paste(Vec<u8>),
260 Keyboard(InputKey),
262 Mouse(InputMouse),
264}
265
266pub struct Parser {
268 bracketed_paste: bool,
269 bracketed_paste_buf: Vec<u8>,
270 x10_mouse_want: bool,
271 x10_mouse_buf: [u8; 3],
272 x10_mouse_len: usize,
273}
274
275impl Parser {
276 pub fn new() -> Self {
280 Self {
281 bracketed_paste: false,
282 bracketed_paste_buf: Vec::new(),
283 x10_mouse_want: false,
284 x10_mouse_buf: [0; 3],
285 x10_mouse_len: 0,
286 }
287 }
288
289 pub fn parse<'parser, 'vt, 'input>(
292 &'parser mut self,
293 stream: vt::Stream<'vt, 'input>,
294 ) -> Stream<'parser, 'vt, 'input> {
295 Stream { parser: self, stream }
296 }
297}
298
299pub struct Stream<'parser, 'vt, 'input> {
301 parser: &'parser mut Parser,
302 stream: vt::Stream<'vt, 'input>,
303}
304
305impl<'input> Iterator for Stream<'_, '_, 'input> {
306 type Item = Input<'input>;
307
308 fn next(&mut self) -> Option<Input<'input>> {
309 loop {
310 if self.parser.bracketed_paste {
311 return self.handle_bracketed_paste();
312 }
313
314 if self.parser.x10_mouse_want {
315 return self.parse_x10_mouse_coordinates();
316 }
317
318 const KEYPAD_LUT: [u8; 8] = [
319 vk::UP.value() as u8, vk::DOWN.value() as u8, vk::RIGHT.value() as u8, vk::LEFT.value() as u8, 0, vk::END.value() as u8, 0, vk::HOME.value() as u8, ];
328
329 match self.stream.next()? {
330 vt::Token::Text(text) => {
331 return Some(Input::Text(text));
332 }
333 vt::Token::Ctrl(ch) => match ch {
334 '\0' | '\t' | '\r' => return Some(Input::Keyboard(InputKey::new(ch as u32))),
335 '\n' => return Some(Input::Keyboard(kbmod::CTRL | vk::RETURN)),
336 ..='\x1a' => {
337 let key = ch as u32 | 0x40;
339 return Some(Input::Keyboard(kbmod::CTRL | InputKey::new(key)));
340 }
341 '\x7f' => return Some(Input::Keyboard(vk::BACK)),
342 _ => {}
343 },
344 vt::Token::Esc(ch) => {
345 match ch {
346 '\0' => return Some(Input::Keyboard(vk::ESCAPE)),
347 '\n' => return Some(Input::Keyboard(kbmod::CTRL_ALT | vk::RETURN)),
348 ' '..='~' => {
349 let ch = ch as u32;
350 let key = ch & !0x20; let modifiers =
352 if (ch & 0x20) != 0 { kbmod::ALT } else { kbmod::ALT_SHIFT };
353 return Some(Input::Keyboard(modifiers | InputKey::new(key)));
354 }
355 _ => {}
356 }
357 }
358 vt::Token::SS3(ch) => match ch {
359 'A'..='H' => {
360 let vk = KEYPAD_LUT[ch as usize - 'A' as usize];
361 if vk != 0 {
362 return Some(Input::Keyboard(InputKey::new(vk as u32)));
363 }
364 }
365 'P'..='S' => {
366 let key = vk::F1.value() + ch as u32 - 'P' as u32;
367 return Some(Input::Keyboard(InputKey::new(key)));
368 }
369 _ => {}
370 },
371 vt::Token::Csi(csi) => {
372 match csi.final_byte {
373 'A'..='H' => {
374 let vk = KEYPAD_LUT[csi.final_byte as usize - 'A' as usize];
375 if vk != 0 {
376 return Some(Input::Keyboard(
377 InputKey::new(vk as u32) | Self::parse_modifiers(csi),
378 ));
379 }
380 }
381 'Z' => return Some(Input::Keyboard(kbmod::SHIFT | vk::TAB)),
382 '~' => {
383 const LUT: [u8; 35] = [
384 0,
385 vk::HOME.value() as u8, vk::INSERT.value() as u8, vk::DELETE.value() as u8, vk::END.value() as u8, vk::PRIOR.value() as u8, vk::NEXT.value() as u8, 0,
392 0,
393 0,
394 0,
395 0,
396 0,
397 0,
398 0,
399 vk::F5.value() as u8, 0,
401 vk::F6.value() as u8, vk::F7.value() as u8, vk::F8.value() as u8, vk::F9.value() as u8, vk::F10.value() as u8, 0,
407 vk::F11.value() as u8, vk::F12.value() as u8, vk::F13.value() as u8, vk::F14.value() as u8, 0,
412 vk::F15.value() as u8, vk::F16.value() as u8, 0,
415 vk::F17.value() as u8, vk::F18.value() as u8, vk::F19.value() as u8, vk::F20.value() as u8, ];
420 const LUT_LEN: u16 = LUT.len() as u16;
421
422 match csi.params[0] {
423 0..LUT_LEN => {
424 let vk = LUT[csi.params[0] as usize];
425 if vk != 0 {
426 return Some(Input::Keyboard(
427 InputKey::new(vk as u32) | Self::parse_modifiers(csi),
428 ));
429 }
430 }
431 200 => self.parser.bracketed_paste = true,
432 _ => {}
433 }
434 }
435 'm' | 'M' if csi.private_byte == '<' => {
436 let btn = csi.params[0];
437 let mut mouse = InputMouse {
438 state: InputMouseState::None,
439 modifiers: kbmod::NONE,
440 position: Default::default(),
441 scroll: Default::default(),
442 };
443
444 mouse.state = InputMouseState::None;
445 if (btn & 0x40) != 0 {
446 mouse.state = InputMouseState::Scroll;
447 mouse.scroll.y += if (btn & 0x01) != 0 { 3 } else { -3 };
448 } else if csi.final_byte == 'M' {
449 const STATES: [InputMouseState; 4] = [
450 InputMouseState::Left,
451 InputMouseState::Middle,
452 InputMouseState::Right,
453 InputMouseState::None,
454 ];
455 mouse.state = STATES[(btn as usize) & 0x03];
456 }
457
458 mouse.modifiers = kbmod::NONE;
459 mouse.modifiers |=
460 if (btn & 0x04) != 0 { kbmod::SHIFT } else { kbmod::NONE };
461 mouse.modifiers |=
462 if (btn & 0x08) != 0 { kbmod::ALT } else { kbmod::NONE };
463 mouse.modifiers |=
464 if (btn & 0x10f) != 0 { kbmod::CTRL } else { kbmod::NONE };
465
466 mouse.position.x = csi.params[1] as CoordType - 1;
467 mouse.position.y = csi.params[2] as CoordType - 1;
468 return Some(Input::Mouse(mouse));
469 }
470 'M' if csi.param_count == 0 => {
471 self.parser.x10_mouse_want = true;
472 }
473 't' if csi.params[0] == 8 => {
474 let width = (csi.params[2] as CoordType).clamp(1, 32767);
476 let height = (csi.params[1] as CoordType).clamp(1, 32767);
477 return Some(Input::Resize(Size { width, height }));
478 }
479 _ => {}
480 }
481 }
482 _ => {}
483 }
484 }
485 }
486}
487
488impl<'input> Stream<'_, '_, 'input> {
489 #[cold]
501 fn handle_bracketed_paste(&mut self) -> Option<Input<'input>> {
502 let beg = self.stream.offset();
503 let mut end = beg;
504
505 while let Some(token) = self.stream.next() {
506 if let vt::Token::Csi(csi) = token
507 && csi.final_byte == '~'
508 && csi.params[0] == 201
509 {
510 self.parser.bracketed_paste = false;
511 break;
512 }
513 end = self.stream.offset();
514 }
515
516 if end != beg {
517 self.parser
518 .bracketed_paste_buf
519 .extend_from_slice(&self.stream.input().as_bytes()[beg..end]);
520 }
521
522 if !self.parser.bracketed_paste {
523 Some(Input::Paste(mem::take(&mut self.parser.bracketed_paste_buf)))
524 } else {
525 None
526 }
527 }
528
529 #[cold]
537 fn parse_x10_mouse_coordinates(&mut self) -> Option<Input<'input>> {
538 self.parser.x10_mouse_len +=
539 self.stream.read(&mut self.parser.x10_mouse_buf[self.parser.x10_mouse_len..]);
540 if self.parser.x10_mouse_len < 3 {
541 return None;
542 }
543
544 let button = self.parser.x10_mouse_buf[0] & 0b11;
545 let modifier = self.parser.x10_mouse_buf[0] & 0b11100;
546 let x = self.parser.x10_mouse_buf[1] as CoordType - 0x21;
547 let y = self.parser.x10_mouse_buf[2] as CoordType - 0x21;
548 let action = match button {
549 0 => InputMouseState::Left,
550 1 => InputMouseState::Middle,
551 2 => InputMouseState::Right,
552 _ => InputMouseState::None,
553 };
554 let modifiers = match modifier {
555 4 => kbmod::SHIFT,
556 8 => kbmod::ALT,
557 16 => kbmod::CTRL,
558 _ => kbmod::NONE,
559 };
560
561 self.parser.x10_mouse_want = false;
562 self.parser.x10_mouse_len = 0;
563
564 Some(Input::Mouse(InputMouse {
565 state: action,
566 modifiers,
567 position: Point { x, y },
568 scroll: Default::default(),
569 }))
570 }
571
572 fn parse_modifiers(csi: &vt::Csi) -> InputKeyMod {
573 let mut modifiers = kbmod::NONE;
574 let p1 = csi.params[1].saturating_sub(1);
575 if (p1 & 0x01) != 0 {
576 modifiers |= kbmod::SHIFT;
577 }
578 if (p1 & 0x02) != 0 {
579 modifiers |= kbmod::ALT;
580 }
581 if (p1 & 0x04) != 0 {
582 modifiers |= kbmod::CTRL;
583 }
584 modifiers
585 }
586}