termwiz/
input.rs

1//! This module provides an InputParser struct to help with parsing
2//! input received from a terminal.
3use crate::bail;
4use crate::error::Result;
5use crate::escape::csi::{KittyKeyboardFlags, MouseReport};
6use crate::escape::parser::Parser;
7use crate::escape::{Action, CSI};
8use crate::keymap::{Found, KeyMap};
9use crate::readbuf::ReadBuffer;
10use bitflags::bitflags;
11#[cfg(feature = "use_serde")]
12use serde::{Deserialize, Serialize};
13use std::fmt::Write;
14use wezterm_input_types::ctrl_mapping;
15
16pub use wezterm_input_types::Modifiers;
17
18pub const CSI: &str = "\x1b[";
19pub const SS3: &str = "\x1bO";
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum KeyboardEncoding {
23    Xterm,
24    /// <http://www.leonerd.org.uk/hacks/fixterms/>
25    CsiU,
26    /// <https://github.com/microsoft/terminal/blob/main/doc/specs/%234999%20-%20Improved%20keyboard%20handling%20in%20Conpty.md>
27    Win32,
28    /// <https://sw.kovidgoyal.net/kitty/keyboard-protocol/>
29    Kitty(KittyKeyboardFlags),
30}
31
32/// Specifies terminal modes/configuration that can influence how a KeyCode
33/// is encoded when being sent to and application via the pty.
34#[derive(Debug, Clone, Copy)]
35pub struct KeyCodeEncodeModes {
36    pub encoding: KeyboardEncoding,
37    pub application_cursor_keys: bool,
38    pub newline_mode: bool,
39    pub modify_other_keys: Option<i64>,
40}
41
42#[cfg(windows)]
43use winapi::um::wincon::{
44    INPUT_RECORD, KEY_EVENT, KEY_EVENT_RECORD, MOUSE_EVENT, MOUSE_EVENT_RECORD,
45    WINDOW_BUFFER_SIZE_EVENT, WINDOW_BUFFER_SIZE_RECORD,
46};
47
48bitflags! {
49    #[cfg_attr(feature="use_serde", derive(Serialize, Deserialize))]
50    #[derive(Debug, Default, Clone, PartialEq, Eq)]
51    pub struct MouseButtons: u8 {
52        const NONE = 0;
53        const LEFT = 1<<1;
54        const RIGHT = 1<<2;
55        const MIDDLE = 1<<3;
56        const VERT_WHEEL = 1<<4;
57        const HORZ_WHEEL = 1<<5;
58        /// if set then the wheel movement was in the positive
59        /// direction, else the negative direction
60        const WHEEL_POSITIVE = 1<<6;
61    }
62}
63
64#[derive(Debug, Clone, PartialEq, Eq)]
65pub enum InputEvent {
66    Key(KeyEvent),
67    Mouse(MouseEvent),
68    PixelMouse(PixelMouseEvent),
69    /// Detected that the user has resized the terminal
70    Resized {
71        cols: usize,
72        rows: usize,
73    },
74    /// For terminals that support Bracketed Paste mode,
75    /// pastes are collected and reported as this variant.
76    Paste(String),
77    /// The program has woken the input thread.
78    Wake,
79}
80
81#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
82#[derive(Debug, Clone, PartialEq, Eq)]
83pub struct MouseEvent {
84    pub x: u16,
85    pub y: u16,
86    pub mouse_buttons: MouseButtons,
87    pub modifiers: Modifiers,
88}
89
90#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
91#[derive(Debug, Clone, PartialEq, Eq)]
92pub struct PixelMouseEvent {
93    pub x_pixels: u16,
94    pub y_pixels: u16,
95    pub mouse_buttons: MouseButtons,
96    pub modifiers: Modifiers,
97}
98
99#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
100#[derive(Debug, Clone, PartialEq, Eq)]
101pub struct KeyEvent {
102    /// Which key was pressed
103    pub key: KeyCode,
104
105    /// Which modifiers are down
106    pub modifiers: Modifiers,
107}
108
109/// Which key is pressed.  Not all of these are probable to appear
110/// on most systems.  A lot of this list is @wez trawling docs and
111/// making an entry for things that might be possible in this first pass.
112#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
113#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
114pub enum KeyCode {
115    /// The decoded unicode character
116    Char(char),
117
118    Hyper,
119    Super,
120    Meta,
121
122    /// Ctrl-break on windows
123    Cancel,
124    Backspace,
125    Tab,
126    Clear,
127    Enter,
128    Shift,
129    Escape,
130    LeftShift,
131    RightShift,
132    Control,
133    LeftControl,
134    RightControl,
135    Alt,
136    LeftAlt,
137    RightAlt,
138    Menu,
139    LeftMenu,
140    RightMenu,
141    Pause,
142    CapsLock,
143    PageUp,
144    PageDown,
145    End,
146    Home,
147    LeftArrow,
148    RightArrow,
149    UpArrow,
150    DownArrow,
151    Select,
152    Print,
153    Execute,
154    PrintScreen,
155    Insert,
156    Delete,
157    Help,
158    LeftWindows,
159    RightWindows,
160    Applications,
161    Sleep,
162    Numpad0,
163    Numpad1,
164    Numpad2,
165    Numpad3,
166    Numpad4,
167    Numpad5,
168    Numpad6,
169    Numpad7,
170    Numpad8,
171    Numpad9,
172    Multiply,
173    Add,
174    Separator,
175    Subtract,
176    Decimal,
177    Divide,
178    /// F1-F24 are possible
179    Function(u8),
180    NumLock,
181    ScrollLock,
182    Copy,
183    Cut,
184    Paste,
185    BrowserBack,
186    BrowserForward,
187    BrowserRefresh,
188    BrowserStop,
189    BrowserSearch,
190    BrowserFavorites,
191    BrowserHome,
192    VolumeMute,
193    VolumeDown,
194    VolumeUp,
195    MediaNextTrack,
196    MediaPrevTrack,
197    MediaStop,
198    MediaPlayPause,
199    ApplicationLeftArrow,
200    ApplicationRightArrow,
201    ApplicationUpArrow,
202    ApplicationDownArrow,
203    KeyPadHome,
204    KeyPadEnd,
205    KeyPadPageUp,
206    KeyPadPageDown,
207    KeyPadBegin,
208
209    #[doc(hidden)]
210    InternalPasteStart,
211    #[doc(hidden)]
212    InternalPasteEnd,
213}
214
215impl KeyCode {
216    /// if SHIFT is held and we have KeyCode::Char('c') we want to normalize
217    /// that keycode to KeyCode::Char('C'); that is what this function does.
218    /// In theory we should give the same treatment to keys like `[` -> `{`
219    /// but that assumes something about the keyboard layout and is probably
220    /// better done in the gui frontend rather than this layer.
221    /// In fact, this function might be better off if it lived elsewhere.
222    pub fn normalize_shift_to_upper_case(self, modifiers: Modifiers) -> KeyCode {
223        if modifiers.contains(Modifiers::SHIFT) {
224            match self {
225                KeyCode::Char(c) if c.is_ascii_lowercase() => KeyCode::Char(c.to_ascii_uppercase()),
226                _ => self,
227            }
228        } else {
229            self
230        }
231    }
232
233    /// Return true if the key represents a modifier key.
234    pub fn is_modifier(self) -> bool {
235        matches!(
236            self,
237            Self::Hyper
238                | Self::Super
239                | Self::Meta
240                | Self::Shift
241                | Self::LeftShift
242                | Self::RightShift
243                | Self::Control
244                | Self::LeftControl
245                | Self::RightControl
246                | Self::Alt
247                | Self::LeftAlt
248                | Self::RightAlt
249                | Self::LeftWindows
250                | Self::RightWindows
251        )
252    }
253
254    /// Returns the byte sequence that represents this KeyCode and Modifier combination,
255    pub fn encode(
256        &self,
257        mods: Modifiers,
258        modes: KeyCodeEncodeModes,
259        is_down: bool,
260    ) -> Result<String> {
261        if !is_down {
262            // We only want down events
263            return Ok(String::new());
264        }
265        // We are encoding the key as an xterm-compatible sequence, which does not support
266        // positional modifiers.
267        let mods = mods.remove_positional_mods();
268
269        use KeyCode::*;
270
271        let key = self.normalize_shift_to_upper_case(mods);
272        // Normalize the modifier state for Char's that are uppercase; remove
273        // the SHIFT modifier so that reduce ambiguity below
274        let mods = match key {
275            Char(c)
276                if (c.is_ascii_punctuation() || c.is_ascii_uppercase())
277                    && mods.contains(Modifiers::SHIFT) =>
278            {
279                mods & !Modifiers::SHIFT
280            }
281            _ => mods,
282        };
283
284        // Normalize Backspace and Delete
285        let key = match key {
286            Char('\x7f') => Delete,
287            Char('\x08') => Backspace,
288            c => c,
289        };
290
291        let mut buf = String::new();
292
293        // TODO: also respect self.application_keypad
294
295        match key {
296            Char(c)
297                if is_ambiguous_ascii_ctrl(c)
298                    && mods.contains(Modifiers::CTRL)
299                    && modes.encoding == KeyboardEncoding::CsiU =>
300            {
301                csi_u_encode(&mut buf, c, mods, &modes)?;
302            }
303            Char(c) if c.is_ascii_uppercase() && mods.contains(Modifiers::CTRL) => {
304                csi_u_encode(&mut buf, c, mods, &modes)?;
305            }
306
307            Char(c) if mods.contains(Modifiers::CTRL) && modes.modify_other_keys == Some(2) => {
308                csi_u_encode(&mut buf, c, mods, &modes)?;
309            }
310            Char(c) if mods.contains(Modifiers::CTRL) && ctrl_mapping(c).is_some() => {
311                let c = ctrl_mapping(c).unwrap();
312                if mods.contains(Modifiers::ALT) {
313                    buf.push(0x1b as char);
314                }
315                buf.push(c);
316            }
317
318            // When alt is pressed, send escape first to indicate to the peer that
319            // ALT is pressed.  We do this only for ascii alnum characters because
320            // eg: on macOS generates altgr style glyphs and keeps the ALT key
321            // in the modifier set.  This confuses eg: zsh which then just displays
322            // <fffffffff> as the input, so we want to avoid that.
323            Char(c)
324                if (c.is_ascii_alphanumeric() || c.is_ascii_punctuation())
325                    && mods.contains(Modifiers::ALT) =>
326            {
327                buf.push(0x1b as char);
328                buf.push(c);
329            }
330
331            Backspace => {
332                // Backspace sends the default VERASE which is confusingly
333                // the DEL ascii codepoint rather than BS.
334                // We only send BS when CTRL is held.
335                if mods.contains(Modifiers::CTRL) {
336                    csi_u_encode(&mut buf, '\x08', mods, &modes)?;
337                } else if mods.contains(Modifiers::SHIFT) {
338                    csi_u_encode(&mut buf, '\x7f', mods, &modes)?;
339                } else {
340                    if mods.contains(Modifiers::ALT) {
341                        buf.push(0x1b as char);
342                    }
343                    buf.push('\x7f');
344                }
345            }
346
347            Enter | Escape => {
348                let c = match key {
349                    Enter => '\r',
350                    Escape => '\x1b',
351                    _ => unreachable!(),
352                };
353                if mods.contains(Modifiers::SHIFT) || mods.contains(Modifiers::CTRL) {
354                    csi_u_encode(&mut buf, c, mods, &modes)?;
355                } else {
356                    if mods.contains(Modifiers::ALT) {
357                        buf.push(0x1b as char);
358                    }
359                    buf.push(c);
360                    if modes.newline_mode && key == Enter {
361                        buf.push(0x0a as char);
362                    }
363                }
364            }
365
366            Tab if !mods.is_empty() && modes.modify_other_keys.is_some() => {
367                csi_u_encode(&mut buf, '\t', mods, &modes)?;
368            }
369
370            Tab => {
371                if mods.contains(Modifiers::ALT) {
372                    buf.push(0x1b as char);
373                }
374                let mods = mods & !Modifiers::ALT;
375                if mods == Modifiers::CTRL {
376                    buf.push_str("\x1b[9;5u");
377                } else if mods == Modifiers::CTRL | Modifiers::SHIFT {
378                    buf.push_str("\x1b[1;5Z");
379                } else if mods == Modifiers::SHIFT {
380                    buf.push_str("\x1b[Z");
381                } else {
382                    buf.push('\t');
383                }
384            }
385
386            Char(c) => {
387                if mods.is_empty() {
388                    buf.push(c);
389                } else {
390                    csi_u_encode(&mut buf, c, mods, &modes)?;
391                }
392            }
393
394            Home
395            | KeyPadHome
396            | End
397            | KeyPadEnd
398            | UpArrow
399            | DownArrow
400            | RightArrow
401            | LeftArrow
402            | ApplicationUpArrow
403            | ApplicationDownArrow
404            | ApplicationRightArrow
405            | ApplicationLeftArrow => {
406                let (force_app, c) = match key {
407                    UpArrow => (false, 'A'),
408                    DownArrow => (false, 'B'),
409                    RightArrow => (false, 'C'),
410                    LeftArrow => (false, 'D'),
411                    KeyPadHome | Home => (false, 'H'),
412                    End | KeyPadEnd => (false, 'F'),
413                    ApplicationUpArrow => (true, 'A'),
414                    ApplicationDownArrow => (true, 'B'),
415                    ApplicationRightArrow => (true, 'C'),
416                    ApplicationLeftArrow => (true, 'D'),
417                    _ => unreachable!(),
418                };
419
420                let csi_or_ss3 = if force_app
421                    || (
422                        modes.application_cursor_keys
423                        // Strict reading of DECCKM suggests that application_cursor_keys
424                        // only applies when DECANM and DECKPAM are active, but that seems
425                        // to break unmodified cursor keys in vim
426                        /* && self.dec_ansi_mode && self.application_keypad */
427                    ) {
428                    // Use SS3 in application mode
429                    SS3
430                } else {
431                    // otherwise use regular CSI
432                    CSI
433                };
434
435                if mods.contains(Modifiers::ALT)
436                    || mods.contains(Modifiers::SHIFT)
437                    || mods.contains(Modifiers::CTRL)
438                {
439                    write!(buf, "{}1;{}{}", CSI, 1 + mods.encode_xterm(), c)?;
440                } else {
441                    write!(buf, "{}{}", csi_or_ss3, c)?;
442                }
443            }
444
445            PageUp | PageDown | KeyPadPageUp | KeyPadPageDown | Insert | Delete => {
446                let c = match key {
447                    Insert => 2,
448                    Delete => 3,
449                    KeyPadPageUp | PageUp => 5,
450                    KeyPadPageDown | PageDown => 6,
451                    _ => unreachable!(),
452                };
453
454                if mods.contains(Modifiers::ALT)
455                    || mods.contains(Modifiers::SHIFT)
456                    || mods.contains(Modifiers::CTRL)
457                {
458                    write!(buf, "\x1b[{};{}~", c, 1 + mods.encode_xterm())?;
459                } else {
460                    write!(buf, "\x1b[{}~", c)?;
461                }
462            }
463
464            Function(n) => {
465                if mods.is_empty() && n < 5 {
466                    // F1-F4 are encoded using SS3 if there are no modifiers
467                    write!(
468                        buf,
469                        "{}",
470                        match n {
471                            1 => "\x1bOP",
472                            2 => "\x1bOQ",
473                            3 => "\x1bOR",
474                            4 => "\x1bOS",
475                            _ => unreachable!("wat?"),
476                        }
477                    )?;
478                } else if n < 5 {
479                    // Special case for F1-F4 with modifiers
480                    let code = match n {
481                        1 => 'P',
482                        2 => 'Q',
483                        3 => 'R',
484                        4 => 'S',
485                        _ => unreachable!("wat?"),
486                    };
487                    write!(buf, "\x1b[1;{}{code}", 1 + mods.encode_xterm())?;
488                } else {
489                    // Higher numbered F-keys using CSI instead of SS3.
490                    let intro = match n {
491                        1 => "\x1b[11",
492                        2 => "\x1b[12",
493                        3 => "\x1b[13",
494                        4 => "\x1b[14",
495                        5 => "\x1b[15",
496                        6 => "\x1b[17",
497                        7 => "\x1b[18",
498                        8 => "\x1b[19",
499                        9 => "\x1b[20",
500                        10 => "\x1b[21",
501                        11 => "\x1b[23",
502                        12 => "\x1b[24",
503                        13 => "\x1b[25",
504                        14 => "\x1b[26",
505                        15 => "\x1b[28",
506                        16 => "\x1b[29",
507                        17 => "\x1b[31",
508                        18 => "\x1b[32",
509                        19 => "\x1b[33",
510                        20 => "\x1b[34",
511                        21 => "\x1b[42",
512                        22 => "\x1b[43",
513                        23 => "\x1b[44",
514                        24 => "\x1b[45",
515                        _ => bail!("unhandled fkey number {}", n),
516                    };
517                    let encoded_mods = mods.encode_xterm();
518                    if encoded_mods == 0 {
519                        // If no modifiers are held, don't send the modifier
520                        // sequence, as the modifier encoding is a CSI-u extension.
521                        write!(buf, "{}~", intro)?;
522                    } else {
523                        write!(buf, "{};{}~", intro, 1 + encoded_mods)?;
524                    }
525                }
526            }
527
528            Numpad0 | Numpad3 | Numpad9 | Decimal => {
529                let intro = match key {
530                    Numpad0 => "\x1b[2",
531                    Numpad3 => "\x1b[6",
532                    Numpad9 => "\x1b[6",
533                    Decimal => "\x1b[3",
534                    _ => unreachable!(),
535                };
536
537                let encoded_mods = mods.encode_xterm();
538                if encoded_mods == 0 {
539                    // If no modifiers are held, don't send the modifier
540                    // sequence, as the modifier encoding is a CSI-u extension.
541                    write!(buf, "{}~", intro)?;
542                } else {
543                    write!(buf, "{};{}~", intro, 1 + encoded_mods)?;
544                }
545            }
546
547            Numpad1 | Numpad2 | Numpad4 | Numpad5 | KeyPadBegin | Numpad6 | Numpad7 | Numpad8 => {
548                let c = match key {
549                    Numpad1 => "F",
550                    Numpad2 => "B",
551                    Numpad4 => "D",
552                    KeyPadBegin | Numpad5 => "E",
553                    Numpad6 => "C",
554                    Numpad7 => "H",
555                    Numpad8 => "A",
556                    _ => unreachable!(),
557                };
558
559                let encoded_mods = mods.encode_xterm();
560                if encoded_mods == 0 {
561                    // If no modifiers are held, don't send the modifier
562                    write!(buf, "{}{}", CSI, c)?;
563                } else {
564                    write!(buf, "{}1;{}{}", CSI, 1 + encoded_mods, c)?;
565                }
566            }
567
568            Multiply | Add | Separator | Subtract | Divide => {}
569
570            // Modifier keys pressed on their own don't expand to anything
571            Control | LeftControl | RightControl | Alt | LeftAlt | RightAlt | Menu | LeftMenu
572            | RightMenu | Super | Hyper | Shift | LeftShift | RightShift | Meta | LeftWindows
573            | RightWindows | NumLock | ScrollLock | Cancel | Clear | Pause | CapsLock | Select
574            | Print | PrintScreen | Execute | Help | Applications | Sleep | Copy | Cut | Paste
575            | BrowserBack | BrowserForward | BrowserRefresh | BrowserStop | BrowserSearch
576            | BrowserFavorites | BrowserHome | VolumeMute | VolumeDown | VolumeUp
577            | MediaNextTrack | MediaPrevTrack | MediaStop | MediaPlayPause | InternalPasteStart
578            | InternalPasteEnd => {}
579        };
580
581        Ok(buf)
582    }
583}
584
585/// characters that when masked for CTRL could be an ascii control character
586/// or could be a key that a user legitimately wants to process in their
587/// terminal application
588fn is_ambiguous_ascii_ctrl(c: char) -> bool {
589    match c {
590        'i' | 'I' | 'm' | 'M' | '[' | '{' | '@' => true,
591        _ => false,
592    }
593}
594
595fn is_ascii(c: char) -> bool {
596    (c as u32) < 0x80
597}
598
599fn csi_u_encode(
600    buf: &mut String,
601    c: char,
602    mods: Modifiers,
603    modes: &KeyCodeEncodeModes,
604) -> Result<()> {
605    if modes.encoding == KeyboardEncoding::CsiU && is_ascii(c) {
606        write!(buf, "\x1b[{};{}u", c as u32, 1 + mods.encode_xterm())?;
607        return Ok(());
608    }
609
610    // <https://invisible-island.net/xterm/modified-keys.html>
611    match (c, modes.modify_other_keys) {
612        ('c' | 'd' | '\x1b' | '\x7f' | '\x08', Some(1)) => {
613            // Exclude well-known keys from modifyOtherKeys mode 1
614        }
615        (c, Some(_)) => {
616            write!(buf, "\x1b[27;{};{}~", 1 + mods.encode_xterm(), c as u32)?;
617            return Ok(());
618        }
619        _ => {}
620    }
621
622    let c = if mods.contains(Modifiers::CTRL) && ctrl_mapping(c).is_some() {
623        ctrl_mapping(c).unwrap()
624    } else {
625        c
626    };
627    if mods.contains(Modifiers::ALT) {
628        buf.push(0x1b as char);
629    }
630    write!(buf, "{}", c)?;
631    Ok(())
632}
633
634#[derive(Debug, Clone, Copy, PartialEq, Eq)]
635enum InputState {
636    Normal,
637    EscapeMaybeAlt,
638    Pasting(usize),
639}
640
641#[derive(Debug)]
642pub struct InputParser {
643    key_map: KeyMap<InputEvent>,
644    buf: ReadBuffer,
645    state: InputState,
646}
647
648#[cfg(windows)]
649mod windows {
650    use super::*;
651    use std;
652    use winapi::um::winuser;
653
654    fn modifiers_from_ctrl_key_state(state: u32) -> Modifiers {
655        use winapi::um::wincon::*;
656
657        let mut mods = Modifiers::NONE;
658
659        if (state & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) != 0 {
660            mods |= Modifiers::ALT;
661        }
662
663        if (state & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0 {
664            mods |= Modifiers::CTRL;
665        }
666
667        if (state & SHIFT_PRESSED) != 0 {
668            mods |= Modifiers::SHIFT;
669        }
670
671        // TODO: we could report caps lock, numlock and scrolllock
672
673        mods
674    }
675    impl InputParser {
676        fn decode_key_record<F: FnMut(InputEvent)>(
677            &mut self,
678            event: &KEY_EVENT_RECORD,
679            callback: &mut F,
680        ) {
681            // TODO: do we want downs instead of ups?
682            if event.bKeyDown == 0 {
683                return;
684            }
685
686            let key_code = match std::char::from_u32(*unsafe { event.uChar.UnicodeChar() } as u32) {
687                Some(unicode) if unicode > '\x00' => {
688                    let mut buf = [0u8; 4];
689                    self.buf
690                        .extend_with(unicode.encode_utf8(&mut buf).as_bytes());
691                    self.process_bytes(callback, true);
692                    return;
693                }
694                _ => match event.wVirtualKeyCode as i32 {
695                    winuser::VK_CANCEL => KeyCode::Cancel,
696                    winuser::VK_BACK => KeyCode::Backspace,
697                    winuser::VK_TAB => KeyCode::Tab,
698                    winuser::VK_CLEAR => KeyCode::Clear,
699                    winuser::VK_RETURN => KeyCode::Enter,
700                    winuser::VK_SHIFT => KeyCode::Shift,
701                    winuser::VK_CONTROL => KeyCode::Control,
702                    winuser::VK_MENU => KeyCode::Menu,
703                    winuser::VK_PAUSE => KeyCode::Pause,
704                    winuser::VK_CAPITAL => KeyCode::CapsLock,
705                    winuser::VK_ESCAPE => KeyCode::Escape,
706                    winuser::VK_PRIOR => KeyCode::PageUp,
707                    winuser::VK_NEXT => KeyCode::PageDown,
708                    winuser::VK_END => KeyCode::End,
709                    winuser::VK_HOME => KeyCode::Home,
710                    winuser::VK_LEFT => KeyCode::LeftArrow,
711                    winuser::VK_RIGHT => KeyCode::RightArrow,
712                    winuser::VK_UP => KeyCode::UpArrow,
713                    winuser::VK_DOWN => KeyCode::DownArrow,
714                    winuser::VK_SELECT => KeyCode::Select,
715                    winuser::VK_PRINT => KeyCode::Print,
716                    winuser::VK_EXECUTE => KeyCode::Execute,
717                    winuser::VK_SNAPSHOT => KeyCode::PrintScreen,
718                    winuser::VK_INSERT => KeyCode::Insert,
719                    winuser::VK_DELETE => KeyCode::Delete,
720                    winuser::VK_HELP => KeyCode::Help,
721                    winuser::VK_LWIN => KeyCode::LeftWindows,
722                    winuser::VK_RWIN => KeyCode::RightWindows,
723                    winuser::VK_APPS => KeyCode::Applications,
724                    winuser::VK_SLEEP => KeyCode::Sleep,
725                    winuser::VK_NUMPAD0 => KeyCode::Numpad0,
726                    winuser::VK_NUMPAD1 => KeyCode::Numpad1,
727                    winuser::VK_NUMPAD2 => KeyCode::Numpad2,
728                    winuser::VK_NUMPAD3 => KeyCode::Numpad3,
729                    winuser::VK_NUMPAD4 => KeyCode::Numpad4,
730                    winuser::VK_NUMPAD5 => KeyCode::Numpad5,
731                    winuser::VK_NUMPAD6 => KeyCode::Numpad6,
732                    winuser::VK_NUMPAD7 => KeyCode::Numpad7,
733                    winuser::VK_NUMPAD8 => KeyCode::Numpad8,
734                    winuser::VK_NUMPAD9 => KeyCode::Numpad9,
735                    winuser::VK_MULTIPLY => KeyCode::Multiply,
736                    winuser::VK_ADD => KeyCode::Add,
737                    winuser::VK_SEPARATOR => KeyCode::Separator,
738                    winuser::VK_SUBTRACT => KeyCode::Subtract,
739                    winuser::VK_DECIMAL => KeyCode::Decimal,
740                    winuser::VK_DIVIDE => KeyCode::Divide,
741                    winuser::VK_F1 => KeyCode::Function(1),
742                    winuser::VK_F2 => KeyCode::Function(2),
743                    winuser::VK_F3 => KeyCode::Function(3),
744                    winuser::VK_F4 => KeyCode::Function(4),
745                    winuser::VK_F5 => KeyCode::Function(5),
746                    winuser::VK_F6 => KeyCode::Function(6),
747                    winuser::VK_F7 => KeyCode::Function(7),
748                    winuser::VK_F8 => KeyCode::Function(8),
749                    winuser::VK_F9 => KeyCode::Function(9),
750                    winuser::VK_F10 => KeyCode::Function(10),
751                    winuser::VK_F11 => KeyCode::Function(11),
752                    winuser::VK_F12 => KeyCode::Function(12),
753                    winuser::VK_F13 => KeyCode::Function(13),
754                    winuser::VK_F14 => KeyCode::Function(14),
755                    winuser::VK_F15 => KeyCode::Function(15),
756                    winuser::VK_F16 => KeyCode::Function(16),
757                    winuser::VK_F17 => KeyCode::Function(17),
758                    winuser::VK_F18 => KeyCode::Function(18),
759                    winuser::VK_F19 => KeyCode::Function(19),
760                    winuser::VK_F20 => KeyCode::Function(20),
761                    winuser::VK_F21 => KeyCode::Function(21),
762                    winuser::VK_F22 => KeyCode::Function(22),
763                    winuser::VK_F23 => KeyCode::Function(23),
764                    winuser::VK_F24 => KeyCode::Function(24),
765                    winuser::VK_NUMLOCK => KeyCode::NumLock,
766                    winuser::VK_SCROLL => KeyCode::ScrollLock,
767                    winuser::VK_LSHIFT => KeyCode::LeftShift,
768                    winuser::VK_RSHIFT => KeyCode::RightShift,
769                    winuser::VK_LCONTROL => KeyCode::LeftControl,
770                    winuser::VK_RCONTROL => KeyCode::RightControl,
771                    winuser::VK_LMENU => KeyCode::LeftMenu,
772                    winuser::VK_RMENU => KeyCode::RightMenu,
773                    winuser::VK_BROWSER_BACK => KeyCode::BrowserBack,
774                    winuser::VK_BROWSER_FORWARD => KeyCode::BrowserForward,
775                    winuser::VK_BROWSER_REFRESH => KeyCode::BrowserRefresh,
776                    winuser::VK_BROWSER_STOP => KeyCode::BrowserStop,
777                    winuser::VK_BROWSER_SEARCH => KeyCode::BrowserSearch,
778                    winuser::VK_BROWSER_FAVORITES => KeyCode::BrowserFavorites,
779                    winuser::VK_BROWSER_HOME => KeyCode::BrowserHome,
780                    winuser::VK_VOLUME_MUTE => KeyCode::VolumeMute,
781                    winuser::VK_VOLUME_DOWN => KeyCode::VolumeDown,
782                    winuser::VK_VOLUME_UP => KeyCode::VolumeUp,
783                    winuser::VK_MEDIA_NEXT_TRACK => KeyCode::MediaNextTrack,
784                    winuser::VK_MEDIA_PREV_TRACK => KeyCode::MediaPrevTrack,
785                    winuser::VK_MEDIA_STOP => KeyCode::MediaStop,
786                    winuser::VK_MEDIA_PLAY_PAUSE => KeyCode::MediaPlayPause,
787                    _ => return,
788                },
789            };
790            let mut modifiers = modifiers_from_ctrl_key_state(event.dwControlKeyState);
791
792            let key_code = key_code.normalize_shift_to_upper_case(modifiers);
793            if let KeyCode::Char(c) = key_code {
794                if c.is_ascii_uppercase() {
795                    modifiers.remove(Modifiers::SHIFT);
796                }
797            }
798
799            let input_event = InputEvent::Key(KeyEvent {
800                key: key_code,
801                modifiers,
802            });
803            for _ in 0..event.wRepeatCount {
804                callback(input_event.clone());
805            }
806        }
807
808        fn decode_mouse_record<F: FnMut(InputEvent)>(
809            &self,
810            event: &MOUSE_EVENT_RECORD,
811            callback: &mut F,
812        ) {
813            use winapi::um::wincon::*;
814            let mut buttons = MouseButtons::NONE;
815
816            if (event.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) != 0 {
817                buttons |= MouseButtons::LEFT;
818            }
819            if (event.dwButtonState & RIGHTMOST_BUTTON_PRESSED) != 0 {
820                buttons |= MouseButtons::RIGHT;
821            }
822            if (event.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) != 0 {
823                buttons |= MouseButtons::MIDDLE;
824            }
825
826            let modifiers = modifiers_from_ctrl_key_state(event.dwControlKeyState);
827
828            if (event.dwEventFlags & MOUSE_WHEELED) != 0 {
829                buttons |= MouseButtons::VERT_WHEEL;
830                if (event.dwButtonState >> 8) != 0 {
831                    buttons |= MouseButtons::WHEEL_POSITIVE;
832                }
833            } else if (event.dwEventFlags & MOUSE_HWHEELED) != 0 {
834                buttons |= MouseButtons::HORZ_WHEEL;
835                if (event.dwButtonState >> 8) != 0 {
836                    buttons |= MouseButtons::WHEEL_POSITIVE;
837                }
838            }
839
840            let mouse = InputEvent::Mouse(MouseEvent {
841                x: event.dwMousePosition.X as u16,
842                y: event.dwMousePosition.Y as u16,
843                mouse_buttons: buttons,
844                modifiers,
845            });
846
847            if (event.dwEventFlags & DOUBLE_CLICK) != 0 {
848                callback(mouse.clone());
849            }
850            callback(mouse);
851        }
852
853        fn decode_resize_record<F: FnMut(InputEvent)>(
854            &self,
855            event: &WINDOW_BUFFER_SIZE_RECORD,
856            callback: &mut F,
857        ) {
858            callback(InputEvent::Resized {
859                rows: event.dwSize.Y as usize,
860                cols: event.dwSize.X as usize,
861            });
862        }
863
864        pub fn decode_input_records<F: FnMut(InputEvent)>(
865            &mut self,
866            records: &[INPUT_RECORD],
867            callback: &mut F,
868        ) {
869            for record in records {
870                match record.EventType {
871                    KEY_EVENT => {
872                        self.decode_key_record(unsafe { record.Event.KeyEvent() }, callback)
873                    }
874                    MOUSE_EVENT => {
875                        self.decode_mouse_record(unsafe { record.Event.MouseEvent() }, callback)
876                    }
877                    WINDOW_BUFFER_SIZE_EVENT => self.decode_resize_record(
878                        unsafe { record.Event.WindowBufferSizeEvent() },
879                        callback,
880                    ),
881                    _ => {}
882                }
883            }
884            self.process_bytes(callback, false);
885        }
886    }
887}
888
889impl Default for InputParser {
890    fn default() -> Self {
891        Self::new()
892    }
893}
894
895impl InputParser {
896    pub fn new() -> Self {
897        Self {
898            key_map: Self::build_basic_key_map(),
899            buf: ReadBuffer::new(),
900            state: InputState::Normal,
901        }
902    }
903
904    fn build_basic_key_map() -> KeyMap<InputEvent> {
905        let mut map = KeyMap::new();
906
907        let modifier_combos = &[
908            ("", Modifiers::NONE),
909            (";1", Modifiers::NONE),
910            (";2", Modifiers::SHIFT),
911            (";3", Modifiers::ALT),
912            (";4", Modifiers::ALT | Modifiers::SHIFT),
913            (";5", Modifiers::CTRL),
914            (";6", Modifiers::CTRL | Modifiers::SHIFT),
915            (";7", Modifiers::CTRL | Modifiers::ALT),
916            (";8", Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT),
917        ];
918        // Meta is theoretically a distinct modifier of its own, but modern systems don't
919        // have a dedicated Meta key and use the Alt/Option key instead.  The mapping
920        // below is reproduced from the xterm documentation from a time where it was
921        // possible to hold both Alt and Meta down as modifiers.  Since we define meta to
922        // ALT, the use of `meta | ALT` in the table below appears to be redundant,
923        // but makes it easier to see that the mapping matches xterm when viewing
924        // its documentation.
925        let meta = Modifiers::ALT;
926        let meta_modifier_combos = &[
927            (";9", meta),
928            (";10", meta | Modifiers::SHIFT),
929            (";11", meta | Modifiers::ALT),
930            (";12", meta | Modifiers::ALT | Modifiers::SHIFT),
931            (";13", meta | Modifiers::CTRL),
932            (";14", meta | Modifiers::CTRL | Modifiers::SHIFT),
933            (";15", meta | Modifiers::CTRL | Modifiers::ALT),
934            (
935                ";16",
936                meta | Modifiers::CTRL | Modifiers::ALT | Modifiers::SHIFT,
937            ),
938        ];
939
940        let modifier_combos_including_meta =
941            || modifier_combos.iter().chain(meta_modifier_combos.iter());
942
943        for alpha in b'A'..=b'Z' {
944            // Ctrl-[A..=Z] are sent as 1..=26
945            let ctrl = [alpha & 0x1f];
946            map.insert(
947                &ctrl,
948                InputEvent::Key(KeyEvent {
949                    key: KeyCode::Char((alpha as char).to_ascii_lowercase()),
950                    modifiers: Modifiers::CTRL,
951                }),
952            );
953
954            // ALT A-Z is often sent with a leading ESC
955            let alt = [0x1b, alpha];
956            map.insert(
957                &alt,
958                InputEvent::Key(KeyEvent {
959                    key: KeyCode::Char(alpha as char),
960                    modifiers: Modifiers::ALT,
961                }),
962            );
963        }
964
965        for c in 0..=0x7fu8 {
966            for (suffix, modifiers) in modifier_combos {
967                // `CSI u` encodings for the ascii range;
968                // see http://www.leonerd.org.uk/hacks/fixterms/
969                let key = format!("\x1b[{}{}u", c, suffix);
970                map.insert(
971                    key,
972                    InputEvent::Key(KeyEvent {
973                        key: KeyCode::Char(c as char),
974                        modifiers: *modifiers,
975                    }),
976                );
977
978                if !suffix.is_empty() {
979                    // xterm modifyOtherKeys sequences
980                    let key = format!("\x1b[27{};{}~", suffix, c);
981                    map.insert(
982                        key,
983                        InputEvent::Key(KeyEvent {
984                            key: match c {
985                                8 | 0x7f => KeyCode::Backspace,
986                                0x1b => KeyCode::Escape,
987                                9 => KeyCode::Tab,
988                                10 | 13 => KeyCode::Enter,
989                                _ => KeyCode::Char(c as char),
990                            },
991                            modifiers: *modifiers,
992                        }),
993                    );
994                }
995            }
996        }
997
998        // Common arrow keys
999        for (keycode, dir) in &[
1000            (KeyCode::UpArrow, b'A'),
1001            (KeyCode::DownArrow, b'B'),
1002            (KeyCode::RightArrow, b'C'),
1003            (KeyCode::LeftArrow, b'D'),
1004            (KeyCode::Home, b'H'),
1005            (KeyCode::End, b'F'),
1006        ] {
1007            // Arrow keys in normal mode encoded using CSI
1008            let arrow = [0x1b, b'[', *dir];
1009            map.insert(
1010                &arrow,
1011                InputEvent::Key(KeyEvent {
1012                    key: *keycode,
1013                    modifiers: Modifiers::NONE,
1014                }),
1015            );
1016            for (suffix, modifiers) in modifier_combos_including_meta() {
1017                let key = format!("\x1b[1{}{}", suffix, *dir as char);
1018                map.insert(
1019                    key,
1020                    InputEvent::Key(KeyEvent {
1021                        key: *keycode,
1022                        modifiers: *modifiers,
1023                    }),
1024                );
1025            }
1026        }
1027        for &(keycode, dir) in &[
1028            (KeyCode::UpArrow, b'a'),
1029            (KeyCode::DownArrow, b'b'),
1030            (KeyCode::RightArrow, b'c'),
1031            (KeyCode::LeftArrow, b'd'),
1032        ] {
1033            // rxvt-specific modified arrows.
1034            for &(seq, mods) in &[
1035                ([0x1b, b'[', dir], Modifiers::SHIFT),
1036                ([0x1b, b'O', dir], Modifiers::CTRL),
1037            ] {
1038                map.insert(
1039                    &seq,
1040                    InputEvent::Key(KeyEvent {
1041                        key: keycode,
1042                        modifiers: mods,
1043                    }),
1044                );
1045            }
1046        }
1047
1048        for (keycode, dir) in &[
1049            (KeyCode::ApplicationUpArrow, b'A'),
1050            (KeyCode::ApplicationDownArrow, b'B'),
1051            (KeyCode::ApplicationRightArrow, b'C'),
1052            (KeyCode::ApplicationLeftArrow, b'D'),
1053        ] {
1054            // Arrow keys in application cursor mode encoded using SS3
1055            let app = [0x1b, b'O', *dir];
1056            map.insert(
1057                &app,
1058                InputEvent::Key(KeyEvent {
1059                    key: *keycode,
1060                    modifiers: Modifiers::NONE,
1061                }),
1062            );
1063            for (suffix, modifiers) in modifier_combos {
1064                let key = format!("\x1bO1{}{}", suffix, *dir as char);
1065                map.insert(
1066                    key,
1067                    InputEvent::Key(KeyEvent {
1068                        key: *keycode,
1069                        modifiers: *modifiers,
1070                    }),
1071                );
1072            }
1073        }
1074
1075        // Function keys 1-4 with no modifiers encoded using SS3
1076        for (keycode, c) in &[
1077            (KeyCode::Function(1), b'P'),
1078            (KeyCode::Function(2), b'Q'),
1079            (KeyCode::Function(3), b'R'),
1080            (KeyCode::Function(4), b'S'),
1081        ] {
1082            let key = [0x1b, b'O', *c];
1083            map.insert(
1084                &key,
1085                InputEvent::Key(KeyEvent {
1086                    key: *keycode,
1087                    modifiers: Modifiers::NONE,
1088                }),
1089            );
1090        }
1091
1092        // Function keys 1-4 with modifiers
1093        for (keycode, c) in &[
1094            (KeyCode::Function(1), b'P'),
1095            (KeyCode::Function(2), b'Q'),
1096            (KeyCode::Function(3), b'R'),
1097            (KeyCode::Function(4), b'S'),
1098        ] {
1099            for (suffix, modifiers) in modifier_combos_including_meta() {
1100                let key = format!("\x1b[1{suffix}{code}", code = *c as char, suffix = suffix);
1101                map.insert(
1102                    key,
1103                    InputEvent::Key(KeyEvent {
1104                        key: *keycode,
1105                        modifiers: *modifiers,
1106                    }),
1107                );
1108            }
1109        }
1110
1111        // Function keys with modifiers encoded using CSI.
1112        // http://aperiodic.net/phil/archives/Geekery/term-function-keys.html
1113        for (range, offset) in &[
1114            // F1-F5 encoded as 11-15
1115            (1..=5, 10),
1116            // F6-F10 encoded as 17-21
1117            (6..=10, 11),
1118            // F11-F14 encoded as 23-26
1119            (11..=14, 12),
1120            // F15-F16 encoded as 28-29
1121            (15..=16, 13),
1122            // F17-F20 encoded as 31-34
1123            (17..=20, 14),
1124        ] {
1125            for n in range.clone() {
1126                for (suffix, modifiers) in modifier_combos_including_meta() {
1127                    let key = format!("\x1b[{code}{suffix}~", code = n + offset, suffix = suffix);
1128                    map.insert(
1129                        key,
1130                        InputEvent::Key(KeyEvent {
1131                            key: KeyCode::Function(n),
1132                            modifiers: *modifiers,
1133                        }),
1134                    );
1135                }
1136            }
1137        }
1138
1139        for (keycode, c) in &[
1140            (KeyCode::Insert, b'2'),
1141            (KeyCode::Delete, b'3'),
1142            (KeyCode::Home, b'1'),
1143            (KeyCode::End, b'4'),
1144            (KeyCode::PageUp, b'5'),
1145            (KeyCode::PageDown, b'6'),
1146            // rxvt
1147            (KeyCode::Home, b'7'),
1148            (KeyCode::End, b'8'),
1149        ] {
1150            for (suffix, modifiers) in &[
1151                (b'~', Modifiers::NONE),
1152                (b'$', Modifiers::SHIFT),
1153                (b'^', Modifiers::CTRL),
1154                (b'@', Modifiers::SHIFT | Modifiers::CTRL),
1155            ] {
1156                let key = [0x1b, b'[', *c, *suffix];
1157                map.insert(
1158                    key,
1159                    InputEvent::Key(KeyEvent {
1160                        key: *keycode,
1161                        modifiers: *modifiers,
1162                    }),
1163                );
1164            }
1165        }
1166
1167        map.insert(
1168            &[0x7f],
1169            InputEvent::Key(KeyEvent {
1170                key: KeyCode::Backspace,
1171                modifiers: Modifiers::NONE,
1172            }),
1173        );
1174
1175        map.insert(
1176            &[0x8],
1177            InputEvent::Key(KeyEvent {
1178                key: KeyCode::Backspace,
1179                modifiers: Modifiers::NONE,
1180            }),
1181        );
1182
1183        map.insert(
1184            &[0x1b],
1185            InputEvent::Key(KeyEvent {
1186                key: KeyCode::Escape,
1187                modifiers: Modifiers::NONE,
1188            }),
1189        );
1190
1191        map.insert(
1192            &[b'\t'],
1193            InputEvent::Key(KeyEvent {
1194                key: KeyCode::Tab,
1195                modifiers: Modifiers::NONE,
1196            }),
1197        );
1198        map.insert(
1199            b"\x1b[Z",
1200            InputEvent::Key(KeyEvent {
1201                key: KeyCode::Tab,
1202                modifiers: Modifiers::SHIFT,
1203            }),
1204        );
1205
1206        map.insert(
1207            &[b'\r'],
1208            InputEvent::Key(KeyEvent {
1209                key: KeyCode::Enter,
1210                modifiers: Modifiers::NONE,
1211            }),
1212        );
1213        map.insert(
1214            &[b'\n'],
1215            InputEvent::Key(KeyEvent {
1216                key: KeyCode::Enter,
1217                modifiers: Modifiers::NONE,
1218            }),
1219        );
1220
1221        map.insert(
1222            b"\x1b[200~",
1223            InputEvent::Key(KeyEvent {
1224                key: KeyCode::InternalPasteStart,
1225                modifiers: Modifiers::NONE,
1226            }),
1227        );
1228        map.insert(
1229            b"\x1b[201~",
1230            InputEvent::Key(KeyEvent {
1231                key: KeyCode::InternalPasteEnd,
1232                modifiers: Modifiers::NONE,
1233            }),
1234        );
1235        map.insert(
1236            b"\x1b[",
1237            InputEvent::Key(KeyEvent {
1238                key: KeyCode::Char('['),
1239                modifiers: Modifiers::ALT,
1240            }),
1241        );
1242
1243        map
1244    }
1245
1246    /// Returns the first char from a str and the length of that char
1247    /// in *bytes*.
1248    fn first_char_and_len(s: &str) -> (char, usize) {
1249        let mut iter = s.chars();
1250        let c = iter.next().unwrap();
1251        (c, c.len_utf8())
1252    }
1253
1254    /// This is a horrible function to pull off the first unicode character
1255    /// from the sequence of bytes and return it and the remaining slice.
1256    fn decode_one_char(bytes: &[u8]) -> Option<(char, usize)> {
1257        // This has the potential to be an ugly hotspot since the complexity
1258        // is a function of the length of the entire buffer rather than the length
1259        // of the first char component.  A simple mitigation might be to slice off
1260        // the first 4 bytes.  We pick 4 bytes because the docs for str::len_utf8()
1261        // state that the maximum expansion for a `char` is 4 bytes.
1262        let bytes = &bytes[..bytes.len().min(4)];
1263        match std::str::from_utf8(bytes) {
1264            Ok(s) => {
1265                let (c, len) = Self::first_char_and_len(s);
1266                Some((c, len))
1267            }
1268            Err(err) => {
1269                let (valid, _after_valid) = bytes.split_at(err.valid_up_to());
1270                if !valid.is_empty() {
1271                    let s = unsafe { std::str::from_utf8_unchecked(valid) };
1272                    let (c, len) = Self::first_char_and_len(s);
1273                    Some((c, len))
1274                } else {
1275                    None
1276                }
1277            }
1278        }
1279    }
1280
1281    fn dispatch_callback<F: FnMut(InputEvent)>(&mut self, mut callback: F, event: InputEvent) {
1282        match (self.state, event) {
1283            (
1284                InputState::Normal,
1285                InputEvent::Key(KeyEvent {
1286                    key: KeyCode::InternalPasteStart,
1287                    ..
1288                }),
1289            ) => {
1290                self.state = InputState::Pasting(0);
1291            }
1292            (
1293                InputState::EscapeMaybeAlt,
1294                InputEvent::Key(KeyEvent {
1295                    key: KeyCode::InternalPasteStart,
1296                    ..
1297                }),
1298            ) => {
1299                // The prior ESC was not part of an ALT sequence, so emit
1300                // it before we start collecting for paste.
1301                callback(InputEvent::Key(KeyEvent {
1302                    key: KeyCode::Escape,
1303                    modifiers: Modifiers::NONE,
1304                }));
1305                self.state = InputState::Pasting(0);
1306            }
1307            (InputState::EscapeMaybeAlt, InputEvent::Key(KeyEvent { key, modifiers })) => {
1308                // Treat this as ALT-key
1309                self.state = InputState::Normal;
1310                callback(InputEvent::Key(KeyEvent {
1311                    key,
1312                    modifiers: modifiers | Modifiers::ALT,
1313                }));
1314            }
1315            (InputState::EscapeMaybeAlt, event) => {
1316                // The prior ESC was not part of an ALT sequence, so emit
1317                // both it and the current event
1318                callback(InputEvent::Key(KeyEvent {
1319                    key: KeyCode::Escape,
1320                    modifiers: Modifiers::NONE,
1321                }));
1322                callback(event);
1323            }
1324            (_, event) => callback(event),
1325        }
1326    }
1327
1328    fn process_bytes<F: FnMut(InputEvent)>(&mut self, mut callback: F, maybe_more: bool) {
1329        while !self.buf.is_empty() {
1330            match self.state {
1331                InputState::Pasting(offset) => {
1332                    let end_paste = b"\x1b[201~";
1333                    if let Some(idx) = self.buf.find_subsequence(offset, end_paste) {
1334                        let pasted =
1335                            String::from_utf8_lossy(&self.buf.as_slice()[0..idx]).to_string();
1336                        self.buf.advance(pasted.len() + end_paste.len());
1337                        callback(InputEvent::Paste(pasted));
1338                        self.state = InputState::Normal;
1339                    } else {
1340                        // Advance our offset so that in the case where we receive a paste that
1341                        // is spread across N reads of size 8K, we don't need to search for the
1342                        // end marker in 8K, 16K, 24K etc. of text until the final buffer is received.
1343                        // Ensure that we use saturating math here for the case where the amount
1344                        // of buffered data after the begin paste is smaller than the end paste marker
1345                        // <https://github.com/wezterm/wezterm/pull/1832>
1346                        self.state =
1347                            InputState::Pasting(self.buf.len().saturating_sub(end_paste.len()));
1348                        return;
1349                    }
1350                }
1351                InputState::EscapeMaybeAlt | InputState::Normal => {
1352                    if self.state == InputState::Normal && self.buf.as_slice()[0] == b'\x1b' {
1353                        // This feels a bit gross because we have two different parsers at play
1354                        // here.  We want to re-use the escape sequence parser to crack the
1355                        // parameters out from things like mouse reports.  The keymap tree doesn't
1356                        // know how to grok this.
1357                        let mut parser = Parser::new();
1358                        if let Some((Action::CSI(CSI::Mouse(mouse)), len)) =
1359                            parser.parse_first(self.buf.as_slice())
1360                        {
1361                            self.buf.advance(len);
1362
1363                            match mouse {
1364                                MouseReport::SGR1006 {
1365                                    x,
1366                                    y,
1367                                    button,
1368                                    modifiers,
1369                                } => {
1370                                    callback(InputEvent::Mouse(MouseEvent {
1371                                        x,
1372                                        y,
1373                                        mouse_buttons: button.into(),
1374                                        modifiers,
1375                                    }));
1376                                }
1377                                MouseReport::SGR1016 {
1378                                    x_pixels,
1379                                    y_pixels,
1380                                    button,
1381                                    modifiers,
1382                                } => {
1383                                    callback(InputEvent::PixelMouse(PixelMouseEvent {
1384                                        x_pixels: x_pixels,
1385                                        y_pixels: y_pixels,
1386                                        mouse_buttons: button.into(),
1387                                        modifiers,
1388                                    }));
1389                                }
1390                            }
1391                            continue;
1392                        }
1393                    }
1394
1395                    match (
1396                        self.key_map.lookup(self.buf.as_slice(), maybe_more),
1397                        maybe_more,
1398                    ) {
1399                        // If we got an unambiguous ESC and we have more data to
1400                        // follow, then this is likely the Meta version of the
1401                        // following keypress.  Buffer up the escape key and
1402                        // consume it from the input.  dispatch_callback() will
1403                        // emit either the ESC or the ALT modified following key.
1404                        (
1405                            Found::Exact(
1406                                len,
1407                                InputEvent::Key(KeyEvent {
1408                                    key: KeyCode::Escape,
1409                                    modifiers: Modifiers::NONE,
1410                                }),
1411                            ),
1412                            _,
1413                        ) if self.state == InputState::Normal && self.buf.len() > len => {
1414                            self.state = InputState::EscapeMaybeAlt;
1415                            self.buf.advance(len);
1416                        }
1417                        (Found::Exact(len, event), _) | (Found::Ambiguous(len, event), false) => {
1418                            self.dispatch_callback(&mut callback, event.clone());
1419                            self.buf.advance(len);
1420                        }
1421                        (Found::Ambiguous(_, _), true) | (Found::NeedData, true) => {
1422                            return;
1423                        }
1424                        (Found::None, _) | (Found::NeedData, false) => {
1425                            // No pre-defined key, so pull out a unicode character
1426                            if let Some((c, len)) = Self::decode_one_char(self.buf.as_slice()) {
1427                                self.buf.advance(len);
1428                                self.dispatch_callback(
1429                                    &mut callback,
1430                                    InputEvent::Key(KeyEvent {
1431                                        key: KeyCode::Char(c),
1432                                        modifiers: Modifiers::NONE,
1433                                    }),
1434                                );
1435                            } else {
1436                                // We need more data to recognize the input, so
1437                                // yield the remainder of the slice
1438                                return;
1439                            }
1440                        }
1441                    }
1442                }
1443            }
1444        }
1445    }
1446
1447    /// Push a sequence of bytes into the parser.
1448    /// Each time input is recognized, the provided `callback` will be passed
1449    /// the decoded `InputEvent`.
1450    /// If not enough data are available to fully decode a sequence, the
1451    /// remaining data will be buffered until the next call.
1452    /// The `maybe_more` flag controls how ambiguous partial sequences are
1453    /// handled. The intent is that `maybe_more` should be set to true if
1454    /// you believe that you will be able to provide more data momentarily.
1455    /// This will cause the parser to defer judgement on partial prefix
1456    /// matches. You should attempt to read and pass the new data in
1457    /// immediately afterwards. If you have attempted a read and no data is
1458    /// immediately available, you should follow up with a call to parse
1459    /// with an empty slice and `maybe_more=false` to allow the partial
1460    /// data to be recognized and processed.
1461    pub fn parse<F: FnMut(InputEvent)>(&mut self, bytes: &[u8], callback: F, maybe_more: bool) {
1462        self.buf.extend_with(bytes);
1463        self.process_bytes(callback, maybe_more);
1464    }
1465
1466    pub fn parse_as_vec(&mut self, bytes: &[u8], maybe_more: bool) -> Vec<InputEvent> {
1467        let mut result = Vec::new();
1468        self.parse(bytes, |event| result.push(event), maybe_more);
1469        result
1470    }
1471
1472    #[cfg(windows)]
1473    pub fn decode_input_records_as_vec(&mut self, records: &[INPUT_RECORD]) -> Vec<InputEvent> {
1474        let mut result = Vec::new();
1475        self.decode_input_records(records, &mut |event| result.push(event));
1476        result
1477    }
1478}
1479
1480#[cfg(test)]
1481mod test {
1482    use super::*;
1483
1484    const NO_MORE: bool = false;
1485    const MAYBE_MORE: bool = true;
1486
1487    #[test]
1488    fn simple() {
1489        let mut p = InputParser::new();
1490        let inputs = p.parse_as_vec(b"hello", NO_MORE);
1491        assert_eq!(
1492            vec![
1493                InputEvent::Key(KeyEvent {
1494                    modifiers: Modifiers::NONE,
1495                    key: KeyCode::Char('h'),
1496                }),
1497                InputEvent::Key(KeyEvent {
1498                    modifiers: Modifiers::NONE,
1499                    key: KeyCode::Char('e'),
1500                }),
1501                InputEvent::Key(KeyEvent {
1502                    modifiers: Modifiers::NONE,
1503                    key: KeyCode::Char('l'),
1504                }),
1505                InputEvent::Key(KeyEvent {
1506                    modifiers: Modifiers::NONE,
1507                    key: KeyCode::Char('l'),
1508                }),
1509                InputEvent::Key(KeyEvent {
1510                    modifiers: Modifiers::NONE,
1511                    key: KeyCode::Char('o'),
1512                }),
1513            ],
1514            inputs
1515        );
1516    }
1517
1518    #[test]
1519    fn control_characters() {
1520        let mut p = InputParser::new();
1521        let inputs = p.parse_as_vec(b"\x03\x1bJ\x7f", NO_MORE);
1522        assert_eq!(
1523            vec![
1524                InputEvent::Key(KeyEvent {
1525                    modifiers: Modifiers::CTRL,
1526                    key: KeyCode::Char('c'),
1527                }),
1528                InputEvent::Key(KeyEvent {
1529                    modifiers: Modifiers::ALT,
1530                    key: KeyCode::Char('J'),
1531                }),
1532                InputEvent::Key(KeyEvent {
1533                    modifiers: Modifiers::NONE,
1534                    key: KeyCode::Backspace,
1535                }),
1536            ],
1537            inputs
1538        );
1539    }
1540
1541    #[test]
1542    fn arrow_keys() {
1543        let mut p = InputParser::new();
1544        let inputs = p.parse_as_vec(b"\x1bOA\x1bOB\x1bOC\x1bOD", NO_MORE);
1545        assert_eq!(
1546            vec![
1547                InputEvent::Key(KeyEvent {
1548                    modifiers: Modifiers::NONE,
1549                    key: KeyCode::ApplicationUpArrow,
1550                }),
1551                InputEvent::Key(KeyEvent {
1552                    modifiers: Modifiers::NONE,
1553                    key: KeyCode::ApplicationDownArrow,
1554                }),
1555                InputEvent::Key(KeyEvent {
1556                    modifiers: Modifiers::NONE,
1557                    key: KeyCode::ApplicationRightArrow,
1558                }),
1559                InputEvent::Key(KeyEvent {
1560                    modifiers: Modifiers::NONE,
1561                    key: KeyCode::ApplicationLeftArrow,
1562                }),
1563            ],
1564            inputs
1565        );
1566    }
1567
1568    #[test]
1569    fn partial() {
1570        let mut p = InputParser::new();
1571        let mut inputs = Vec::new();
1572        // Fragment this F-key sequence across two different pushes
1573        p.parse(b"\x1b[11", |evt| inputs.push(evt), true);
1574        p.parse(b"~", |evt| inputs.push(evt), true);
1575        // make sure we recognize it as just the F-key
1576        assert_eq!(
1577            vec![InputEvent::Key(KeyEvent {
1578                modifiers: Modifiers::NONE,
1579                key: KeyCode::Function(1),
1580            })],
1581            inputs
1582        );
1583    }
1584
1585    #[test]
1586    fn partial_ambig() {
1587        let mut p = InputParser::new();
1588
1589        assert_eq!(
1590            vec![InputEvent::Key(KeyEvent {
1591                key: KeyCode::Escape,
1592                modifiers: Modifiers::NONE,
1593            })],
1594            p.parse_as_vec(b"\x1b", false)
1595        );
1596
1597        let mut inputs = Vec::new();
1598        // An incomplete F-key sequence fragmented across two different pushes
1599        p.parse(b"\x1b[11", |evt| inputs.push(evt), MAYBE_MORE);
1600        p.parse(b"", |evt| inputs.push(evt), NO_MORE);
1601        // since we finish with maybe_more false (NO_MORE), the results should be the longest matching
1602        // parts of said f-key sequence
1603        assert_eq!(
1604            vec![
1605                InputEvent::Key(KeyEvent {
1606                    modifiers: Modifiers::ALT,
1607                    key: KeyCode::Char('['),
1608                }),
1609                InputEvent::Key(KeyEvent {
1610                    modifiers: Modifiers::NONE,
1611                    key: KeyCode::Char('1'),
1612                }),
1613                InputEvent::Key(KeyEvent {
1614                    modifiers: Modifiers::NONE,
1615                    key: KeyCode::Char('1'),
1616                }),
1617            ],
1618            inputs
1619        );
1620    }
1621
1622    #[test]
1623    fn alt_left_bracket() {
1624        // tests that `Alt` + `[` is recognized as a single
1625        // event rather than two events (one `Esc` the second `Char('[')`)
1626        let mut p = InputParser::new();
1627
1628        let mut inputs = Vec::new();
1629        p.parse(b"\x1b[", |evt| inputs.push(evt), false);
1630
1631        assert_eq!(
1632            vec![InputEvent::Key(KeyEvent {
1633                modifiers: Modifiers::ALT,
1634                key: KeyCode::Char('['),
1635            }),],
1636            inputs
1637        );
1638    }
1639
1640    #[test]
1641    fn modify_other_keys_parse() {
1642        let mut p = InputParser::new();
1643        let inputs = p.parse_as_vec(
1644            b"\x1b[27;5;13~\x1b[27;5;9~\x1b[27;6;8~\x1b[27;2;127~\x1b[27;6;27~",
1645            NO_MORE,
1646        );
1647        assert_eq!(
1648            vec![
1649                InputEvent::Key(KeyEvent {
1650                    key: KeyCode::Enter,
1651                    modifiers: Modifiers::CTRL,
1652                }),
1653                InputEvent::Key(KeyEvent {
1654                    key: KeyCode::Tab,
1655                    modifiers: Modifiers::CTRL,
1656                }),
1657                InputEvent::Key(KeyEvent {
1658                    key: KeyCode::Backspace,
1659                    modifiers: Modifiers::CTRL | Modifiers::SHIFT,
1660                }),
1661                InputEvent::Key(KeyEvent {
1662                    key: KeyCode::Backspace,
1663                    modifiers: Modifiers::SHIFT,
1664                }),
1665                InputEvent::Key(KeyEvent {
1666                    key: KeyCode::Escape,
1667                    modifiers: Modifiers::CTRL | Modifiers::SHIFT,
1668                }),
1669            ],
1670            inputs
1671        );
1672    }
1673
1674    #[test]
1675    fn modify_other_keys_encode() {
1676        let mode = KeyCodeEncodeModes {
1677            encoding: KeyboardEncoding::Xterm,
1678            newline_mode: false,
1679            application_cursor_keys: false,
1680            modify_other_keys: None,
1681        };
1682        let mode_1 = KeyCodeEncodeModes {
1683            encoding: KeyboardEncoding::Xterm,
1684            newline_mode: false,
1685            application_cursor_keys: false,
1686            modify_other_keys: Some(1),
1687        };
1688        let mode_2 = KeyCodeEncodeModes {
1689            encoding: KeyboardEncoding::Xterm,
1690            newline_mode: false,
1691            application_cursor_keys: false,
1692            modify_other_keys: Some(2),
1693        };
1694
1695        assert_eq!(
1696            KeyCode::Enter.encode(Modifiers::CTRL, mode, true).unwrap(),
1697            "\r".to_string()
1698        );
1699        assert_eq!(
1700            KeyCode::Enter
1701                .encode(Modifiers::CTRL, mode_1, true)
1702                .unwrap(),
1703            "\x1b[27;5;13~".to_string()
1704        );
1705        assert_eq!(
1706            KeyCode::Enter
1707                .encode(Modifiers::CTRL | Modifiers::SHIFT, mode_1, true)
1708                .unwrap(),
1709            "\x1b[27;6;13~".to_string()
1710        );
1711
1712        // This case is not conformant with xterm!
1713        // xterm just returns tab for CTRL-Tab when modify_other_keys
1714        // is not set.
1715        assert_eq!(
1716            KeyCode::Tab.encode(Modifiers::CTRL, mode, true).unwrap(),
1717            "\x1b[9;5u".to_string()
1718        );
1719        assert_eq!(
1720            KeyCode::Tab.encode(Modifiers::CTRL, mode_1, true).unwrap(),
1721            "\x1b[27;5;9~".to_string()
1722        );
1723        assert_eq!(
1724            KeyCode::Tab
1725                .encode(Modifiers::CTRL | Modifiers::SHIFT, mode_1, true)
1726                .unwrap(),
1727            "\x1b[27;6;9~".to_string()
1728        );
1729
1730        assert_eq!(
1731            KeyCode::Char('c')
1732                .encode(Modifiers::CTRL, mode, true)
1733                .unwrap(),
1734            "\x03".to_string()
1735        );
1736        assert_eq!(
1737            KeyCode::Char('c')
1738                .encode(Modifiers::CTRL, mode_1, true)
1739                .unwrap(),
1740            "\x03".to_string()
1741        );
1742        assert_eq!(
1743            KeyCode::Char('c')
1744                .encode(Modifiers::CTRL, mode_2, true)
1745                .unwrap(),
1746            "\x1b[27;5;99~".to_string()
1747        );
1748
1749        assert_eq!(
1750            KeyCode::Char('1')
1751                .encode(Modifiers::CTRL, mode, true)
1752                .unwrap(),
1753            "1".to_string()
1754        );
1755        assert_eq!(
1756            KeyCode::Char('1')
1757                .encode(Modifiers::CTRL, mode_2, true)
1758                .unwrap(),
1759            "\x1b[27;5;49~".to_string()
1760        );
1761
1762        assert_eq!(
1763            KeyCode::Char(',')
1764                .encode(Modifiers::CTRL, mode, true)
1765                .unwrap(),
1766            ",".to_string()
1767        );
1768        assert_eq!(
1769            KeyCode::Char(',')
1770                .encode(Modifiers::CTRL, mode_2, true)
1771                .unwrap(),
1772            "\x1b[27;5;44~".to_string()
1773        );
1774    }
1775
1776    #[test]
1777    fn encode_issue_892() {
1778        let mode = KeyCodeEncodeModes {
1779            encoding: KeyboardEncoding::Xterm,
1780            newline_mode: false,
1781            application_cursor_keys: false,
1782            modify_other_keys: None,
1783        };
1784
1785        assert_eq!(
1786            KeyCode::LeftArrow
1787                .encode(Modifiers::NONE, mode, true)
1788                .unwrap(),
1789            "\x1b[D".to_string()
1790        );
1791        assert_eq!(
1792            KeyCode::LeftArrow
1793                .encode(Modifiers::ALT, mode, true)
1794                .unwrap(),
1795            "\x1b[1;3D".to_string()
1796        );
1797        assert_eq!(
1798            KeyCode::Home.encode(Modifiers::NONE, mode, true).unwrap(),
1799            "\x1b[H".to_string()
1800        );
1801        assert_eq!(
1802            KeyCode::Home.encode(Modifiers::ALT, mode, true).unwrap(),
1803            "\x1b[1;3H".to_string()
1804        );
1805        assert_eq!(
1806            KeyCode::End.encode(Modifiers::NONE, mode, true).unwrap(),
1807            "\x1b[F".to_string()
1808        );
1809        assert_eq!(
1810            KeyCode::End.encode(Modifiers::ALT, mode, true).unwrap(),
1811            "\x1b[1;3F".to_string()
1812        );
1813        assert_eq!(
1814            KeyCode::Tab.encode(Modifiers::ALT, mode, true).unwrap(),
1815            "\x1b\t".to_string()
1816        );
1817        assert_eq!(
1818            KeyCode::PageUp.encode(Modifiers::ALT, mode, true).unwrap(),
1819            "\x1b[5;3~".to_string()
1820        );
1821        assert_eq!(
1822            KeyCode::Function(1)
1823                .encode(Modifiers::NONE, mode, true)
1824                .unwrap(),
1825            "\x1bOP".to_string()
1826        );
1827    }
1828
1829    #[test]
1830    fn partial_bracketed_paste() {
1831        let mut p = InputParser::new();
1832
1833        let input = b"\x1b[200~1234";
1834        let input2 = b"5678\x1b[201~";
1835
1836        let mut inputs = vec![];
1837
1838        p.parse(input, |e| inputs.push(e), false);
1839        p.parse(input2, |e| inputs.push(e), false);
1840
1841        assert_eq!(vec![InputEvent::Paste("12345678".to_owned())], inputs)
1842    }
1843
1844    #[test]
1845    fn mouse_horizontal_scroll() {
1846        let mut p = InputParser::new();
1847
1848        let input = b"\x1b[<66;42;12M\x1b[<67;42;12M";
1849        let res = p.parse_as_vec(input, MAYBE_MORE);
1850
1851        assert_eq!(
1852            vec![
1853                InputEvent::Mouse(MouseEvent {
1854                    x: 42,
1855                    y: 12,
1856                    mouse_buttons: MouseButtons::HORZ_WHEEL | MouseButtons::WHEEL_POSITIVE,
1857                    modifiers: Modifiers::NONE,
1858                }),
1859                InputEvent::Mouse(MouseEvent {
1860                    x: 42,
1861                    y: 12,
1862                    mouse_buttons: MouseButtons::HORZ_WHEEL,
1863                    modifiers: Modifiers::NONE,
1864                })
1865            ],
1866            res
1867        );
1868    }
1869
1870    #[test]
1871    fn encode_issue_3478_xterm() {
1872        let mode = KeyCodeEncodeModes {
1873            encoding: KeyboardEncoding::Xterm,
1874            newline_mode: false,
1875            application_cursor_keys: false,
1876            modify_other_keys: None,
1877        };
1878
1879        assert_eq!(
1880            KeyCode::Numpad0
1881                .encode(Modifiers::NONE, mode, true)
1882                .unwrap(),
1883            "\u{1b}[2~".to_string()
1884        );
1885        assert_eq!(
1886            KeyCode::Numpad0
1887                .encode(Modifiers::SHIFT, mode, true)
1888                .unwrap(),
1889            "\u{1b}[2;2~".to_string()
1890        );
1891
1892        assert_eq!(
1893            KeyCode::Numpad1
1894                .encode(Modifiers::NONE, mode, true)
1895                .unwrap(),
1896            "\u{1b}[F".to_string()
1897        );
1898        assert_eq!(
1899            KeyCode::Numpad1
1900                .encode(Modifiers::NONE | Modifiers::SHIFT, mode, true)
1901                .unwrap(),
1902            "\u{1b}[1;2F".to_string()
1903        );
1904    }
1905
1906    #[test]
1907    fn encode_tab_with_modifiers() {
1908        let mode = KeyCodeEncodeModes {
1909            encoding: KeyboardEncoding::Xterm,
1910            newline_mode: false,
1911            application_cursor_keys: false,
1912            modify_other_keys: None,
1913        };
1914
1915        let mods_to_result = [
1916            (Modifiers::SHIFT, "\u{1b}[Z"),
1917            (Modifiers::SHIFT | Modifiers::LEFT_SHIFT, "\u{1b}[Z"),
1918            (Modifiers::SHIFT | Modifiers::RIGHT_SHIFT, "\u{1b}[Z"),
1919            (Modifiers::CTRL, "\u{1b}[9;5u"),
1920            (Modifiers::CTRL | Modifiers::LEFT_CTRL, "\u{1b}[9;5u"),
1921            (Modifiers::CTRL | Modifiers::RIGHT_CTRL, "\u{1b}[9;5u"),
1922            (
1923                Modifiers::SHIFT | Modifiers::CTRL | Modifiers::LEFT_CTRL | Modifiers::LEFT_SHIFT,
1924                "\u{1b}[1;5Z",
1925            ),
1926        ];
1927        for (mods, result) in mods_to_result {
1928            assert_eq!(
1929                KeyCode::Tab.encode(mods, mode, true).unwrap(),
1930                result,
1931                "{:?}",
1932                mods
1933            );
1934        }
1935    }
1936}