ANSI/DEC VT Terminal Keycode Sequences ====================================== ANSI terminal keycode sequences are followed by one or more characters that are used to encode non-character keypresses, such as function and editing keys. While they have not been formally standardised by ANSI/ECMA like terminal output sequences, most terminals and consoles have standardised on common similar sequences. Keyboard input needs to have the ability to poll the input to see if any characters are pending without waiting if there are no characters are present, as on its own is terminated by the *absense* of a following character character. +----------+----------+----------+-----------+-----------+---------------+---------------+---------------+-----+ | | UKNC/15 | UKNC/52 | VT52 | VT100 | VT220/320 | Wyse | xterm |Rglar| +----------+----------+----------+-----------+-----------+---------------+---------------+---------------+-----+ | BS | 7F | 7F | 08 | 08 | 08 | 08 | 08 | 008 | | TAB | 09 | 09 | 09 | 09 | 09 | 09 | 09 | 009 | | LF | | | 0A | 0A | | | | 00A | | Return | 0D 0A | 0D 0A | 0D | 0D | 0D | 0D | 0D | 00D | | Right | 19 | | | | | | | 1CD | | Left | 1A | | | | | | | 1CC | | Escape | | | | | | | | 01B | | Up | 1C | | | | | | | 1CF | | Down | 1D | | | | | | | 1CE | | SPC | 20 | 20 | 20 | 20 | 20 | 20 | 20 | 020 | | | | | | | | | | | | f4 | | | | | | [ @ | | 184 | | Up | | A | A | O A | [ A | [ A | [ A | 1CF | | Down | | B | B | O B | [ B | [ B | [ B | 1CE | | Right | | C | C | O C | [ C | [ C | [ C | 1CD | | Left | | D | D | O D | [ D | [ D | [ D | 1CC | | Begin (Keypad-5) | | | O E | [ E | | [ E | 1C5 | | End | | | F | O F | | | [ F | 1C9 | | Next | | | | | | | [ G | 1CA | | Home | | | H | O H | | [ H | [ H | 1C8 | | Tab | | | | | | | ? I | 009 | | Tab | | | | | | | I | 009 | | Clear | | | | | | |( J) | 11B | | Sh-f5 | | | | | | [ K | | 195 | | Sh-f4 | | | | | | [ L | | 194 | | f5 | | | | | | [ M | | 185 | | KPent | | | ? M | O M | O M | O M | O M | 10D | | Enter | | | | | | | ? M | 00D | | Enter | | | | | | | M | 00D | | | | | | | | | | | | f1/PF1 | P | P | P | O P | O P | O P | O P | 181 | | f2/PF2 | Q | Q | Q | O Q | O Q | O Q | O Q | 182 | | f3/PF3 | R | R | R | O R | O R | O R | O R | 183 | | f4/PF4 | S | S | S | O S | O S | O S | O S | 184 | | f5 | T | T | | | | | | 185 | | PgDn/Next| | | | | | [ U | | 1CA | | PgUp/Prev| | | | | | [ V | | 1CB | | | | | | | | | | | | KP= | | | | O X | O X | | O X | 13D | | | | | | | | | | | | Sh-TAB | | | | | | [ Z | | 1D5 | | | | | | | | | | | | KP* | | | | | O j | O j | O j | 12A | | KP+ | | | | | O k | O k | O k | 12B | | KP, | | | | O l | O l | O l | O l | 12C | | KP- | | | | O m | O m | O m | O m | 12D | | KP. | | | ? n | O n | O n | O n | O n | 12E | | KP/ | | | | | O o | O o | O o | 12F | | KP0 | | | ? p | O p | O p | O p | O p | 130 | | KP1 | | | ? q | O q | O q | O q | O q | 131 | | KP2 | | | ? r | O r | O r | O r | O r | 132 | | KP3 | | | ? s | O s | O s | O s | O s | 133 | | KP4 | | | ? t | O t | O t | O t | O t | 134 | | KP5 | | | ? u | O u | O u | O u | O u | 135 | | KP6 | | | ? v | O v | O v | O v | O v | 136 | | KP7 | | | ? w | O w | O w | O w | O w | 137 | | KP8 | | | ? x | O x | O x | O x | O x | 138 | | KP9 | | | ? y | O y | O y | O y | O y | 139 | | | | | | | | | | | | f6 | ~ | ~ | | | | | | 186 | | f8 | 7F | 7F | | | | | | 188 | | | | | | | | | | | | f6 | ~ | ~ | | | | | | 186 | | Home/Find| | | | | [ 1 ~ | [ 1 ~ | [ 1 ~ | 1C8 | | Insert | | | | | [ 2 ~ | [ 2 ~ | [ 2 ~ | 1C6 | | Del/Remove | | | | [ 3 ~ | [ 3 ~ | [ 3 ~ | 1C7 | | End/Select | | | | [ 4 ~ | [ 4 ~ | [ 4 ~ | 1C9 | | PgUp/Prev| | | | | [ 5 ~ | [ 5 ~ | [ 5 ~ | 1CB | | PgDn/Next| | | | | [ 6 ~ | [ 6 ~ | [ 6 ~ | 1CA | | Home | | | | | [ 7 ~ | | | 1C8 | | End | | | | | [ 8 ~ | | | 1C9 | | NumLock | | | | | [ 9 ~ | | | 18D | | | | | | | | | | | | f0/Print | | | | | [ 1 0 ~ | | | 180 | | f1 | | | | | [ 1 1 ~ | | [ 1 1 ~ | 181 | | f2 | | | | | [ 1 2 ~ | | [ 1 2 ~ | 182 | | f3 | | | | | [ 1 3 ~ | | [ 1 3 ~ | 183 | | f4 | | | | | [ 1 4 ~ | | [ 1 4 ~ | 184 | | f5 | | | | | [ 1 5 ~ | | [ 1 5 ~ | 185 | | | | | | | | | | | | f6 | | | | | [ 1 7 ~ | [ 1 7 ~ | [ 1 7 ~ | 186 | | f7 | | | | | [ 1 8 ~ | [ 1 8 ~ | [ 1 8 ~ | 187 | | f8 | | | | | [ 1 9 ~ | [ 1 9 ~ | [ 1 9 ~ | 188 | | f9 | | | | | [ 2 0 ~ | [ 2 0 ~ | [ 2 0 ~ | 189 | | f10 | | | | | [ 2 1 ~ | [ 2 1 ~ | [ 2 1 ~ | 18A | | | | | | | | | | | | f11 | | | | | [ 2 3 ~ | [ 2 3 ~ | [ 2 3 ~ | 18B | | f12 | | | | | [ 2 4 ~ | [ 2 4 ~ | [ 2 4 ~ | 18C | | f13/Print| | | | | [ 2 5 ~ | [ 2 5 ~ | [ 2 5 ~ | 180 | | f14/Scrll| | | | | [ 2 6 ~ | [ 2 6 ~ | [ 2 6 ~ | 18E | | | | | | | | | | | | f15/Help/Brk | | | | [ 2 8 ~ | [ 2 8 ~ | [ 2 8 ~ | 18F | | f16/Do/Menu | | | | [ 2 9 ~ | [ 2 9 ~ | [ 2 9 ~ | 1C1 | | | | | | | | | | | | f17/Shf6 | | | | | [ 3 1 ~ | [ 3 1 ~ | [ 3 1 ~ | 196 | | f18/Shf7 | (print?) | | | | [ 3 2 ~ | [ 3 2 ~ | [ 3 2 ~ | 197 | | f19/Shf8 | (scroll?)| | | | [ 3 3 ~ | [ 3 3 ~ | [ 3 3 ~ | 198 | | f20/Shf9 | (pause?) | | | | [ 3 4 ~ | [ 3 4 ~ | [ 3 4 ~ | 199 | | Shf10 | | | | | [ 3 5 ~ | [ 3 5 ~ | | 19A | +----------+----------+----------+-----------+-----------+---------------+---------------+---------------+-----+ [ may have numeric parameters: [() eg [A [2B [(;)~ eg [10~ [20;2~ The value defaults to 1, and after subtracting 1 is a bitmap of modifier keys being pressed: b0=Shift eg [15;2~ or [2A b1=Alt eg [15;3~ or O3A b2=Ctrl eg [15;5~ or [5A b3=Meta eg [15;9~ or O9A The prefix is sometimes doubled, eg [3A, after reading an parsing code should loop until a non- character or is read. The X, ?X, OX, [X sequences are essentially identical, so can be merged together to a single decoding table. The lower-case sequences are simply the terminating charcter minus &40. +---+-----------+-----+---+-----------+-----+---+-----------+-----+---+-----------+-----+ | X ?X OX [X | +---+-----------+-----+---+-----------+-----+---+-----------+-----+---+-----------+-----+ | @ : f4 : 184 | H : Home : 1C8 | P : PF1/f1 : 181 | X : KP= : 13D | | A : Up : 1CF | I : Tab : 009 | Q : PF2/f2 : 182 | Y : : | | B : Down : 1CE | J : Clear : 11B | R : PF3/f3 : 183 | Z : Sh-TAB : 1D5 | | C : Right : 1CD | K : Sh-f5 : 195 | S : PF4/f4 : 184 | [ : ->next : | | D : Left : 1CC | L : Sh-f4 : 194 | T : f5 : 185 | \ : : | | E : Begin KP5 : 1C5 | M : KPent : 10D | U : Next/PgDn : 1CA | ] : : | | F : End : 1C9 | N : : | V : Prev/PgUp : 1CB | ^ : : | | G : Next : 1CA | O : ->next : | W : : | _ : : | +---+-----------+-----+---+-----------+-----+---+-----------+-----+---+-----------+-----+ | ` : : | h : : | p : KP0 : 130 | x : KP8 : 138 | | a : : | i : : | q : KP1 : 131 | y : KP9 : 139 | | b : : | j : KP* : 12A | r : KP2 : 132 | z : : | | c : : | k : KP+ : 12B | s : KP3 : 133 | { : : | | d : : | l : KP, : 12C | t : KP4 : 134 | | : : | | e : : | m : KP- : 12D | u : KP5 : 135 | } : : | | f : : | n : KP. : 12E | v : KP6 : 136 | ~ : ->next : | | g : : | o : KP/ : 12F | w : KP7 : 137 |del: : | +---+-----------+-----+---+-----------+-----+---+-----------+-----+---+-----------+-----+ Decoding process ---------------- Parsing input from an ANSI keyboard stream can be optimised by combining all keycode sequences into a superset that represents all sources: {'?' or 'O' or '['} {{;}} {'@'-'~'} Example code: * 'C' ANSI key sequence parsing - mdfs.net/Docs/Comp/Comms/ANSIParse * PDP11 ANSI key seequence parsing - mdfs.net/Info/Comp/PDP11/ProgTips * PDP11 BBC BASIC Console I/O - mdfs.net/Software/PDP11/BBCBASIC * JGH Console Library - mdfs.net/System/C/Lib References ---------- * invisible-island.net/xterm/ctlseqs/ctlseqs.html * www.xfree86.org/current/ctlseqs.html * www.gnu.org/software/screen/manual/html_node/Input-Translation.html#Input-Translation * https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences Updates ------- 22-Jun-2020: Testing suggests malformed sequences are ignored. Slight formatting changes.