Zutty key mapping sequences
This is a summary of the character sequences Zutty emits in response to various special keys, and how this mapping depends on the state of the terminal.
Mode settings affecting the emitted sequences
Mode | Description | Setting |
---|---|---|
DECANM | VT52 Mode | CSI ? 2 l |
DECANM | VT100 mode | CSI ? 2 h |
DECCKM/N | Cursor Key Mode: Normal/Cursor | CSI ? 1 l |
DECAKM/A | Cursor Key Mode: Application | CSI ? 1 h |
DECKPNM | Normal/Numeric Keypad Mode | ESC > |
DECKPAM | Alternate/Application Keypad Mode | ESC = |
Effect of modifier keys
In case of modifiers being held while a key is pressed, a derived sequence is sent that includes a Modifier Code as an additional (last) parameter of the original sequence. If the original sequence did not start with CSI, the start is changed to CSI (with the exception of keypad keys). If there were no original parameters in the sequence, a first default parameter of 1 is added before appending the Modifier Code.
Modifier codes:
Modifier(s) | Code |
---|---|
Shift | 2 |
Alt | 3 |
Alt + Shift | 4 |
Control | 5 |
Control + Shift | 6 |
Control + Alt | 7 |
Control + Alt + Shift | 8 |
To make it clearer, in each section we will include some examples of what sequences will result when some modifiers are applied.
Modifiers are generally not applicable to VT52 mode, but are uniform across ANSI and keypad modes.
Sequences that are the same regardless of state
Key | Sequence |
---|---|
Insert, KP_Insert | CSI 2 ~ |
Delete, KP_Delete | CSI 3 ~ |
Prior (PageUp), KP_Prior | CSI 5 ~ |
Next (PageDown), KP_Next | CSI 6 ~ |
Modifier examples:
- Shift + Insert: CSI 2 ; 2 ~
- Control + PageUp: CSI 5 ; 5 ~
Modifiers work even in VT52 mode.
Function keys
These are independent of cursor key and numeric keypad modes.
Key | VT100 | VT52 |
---|---|---|
F1, KP_F1 | SS3 P | ESC P |
F2, KP_F2 | SS3 Q | ESC Q |
F3, KP_F3 | SS3 R | ESC R |
F4, KP_F4 | SS3 S | ESC S |
F5 | CSI 1 5 ~ | CSI 1 5 ~ |
F6 | CSI 1 7 ~ | CSI 1 7 ~ |
F7 | CSI 1 8 ~ | … |
F8 | CSI 1 9 ~ | |
F9 | CSI 2 0 ~ | |
F10 | CSI 2 1 ~ | |
F11 | CSI 2 3 ~ | |
F12 | CSI 2 4 ~ | |
F13 | CSI 2 5 ~ | |
F14 | CSI 2 6 ~ | |
F15 | CSI 2 8 ~ | |
F16 | CSI 2 9 ~ | |
F17 | CSI 3 1 ~ | |
F18 | CSI 3 2 ~ | |
F19 | CSI 3 3 ~ | |
F20 | CSI 3 4 ~ |
Modifier examples:
- Shift + F1: CSI 1 ; 2 P
- Alt + F4: CSI 1 ; 3 S
- Shift + F5: CSI 1 5 ; 2 ~
- Control + Shift + F10: CSI 2 1 ; 6 ~
Modifiers are not applied in VT52 mode.
Sequences dependent on cursor key mode setting
Key | VT100 Normal | VT100 App | VT52 |
---|---|---|---|
Up | CSI A | SS3 A | ESC A |
Down | CSI B | SS3 B | ESC B |
Right | CSI C | SS3 C | ESC C |
Left | CSI D | SS3 D | ESC D |
Home | CSI H | SS3 H | ESC H |
End | CSI F | SS3 F | ESC F |
Examples (apply both in Normal and App mode):
- Alt + Left: CSI 1 ; 3 D
- Control + Home: CSI 1 ; 5 H
Modifiers are not applied in VT52 mode.
Note that arrow keys on the numeric keypad (KP_Up
, etc.) are handled
as completely different keys; their encoding method is described in
the next section.
Sequences dependent on keypad mode setting
This only affects the keypad. The corresponding non-keypad keys always send the literals in the Normal column. Normal (aka. numeric) mode is shared between VT100 and VT52.
Some keys are received from X with different keysyms based on the NumLock state; for these keys, the second column shows the keysym with NumLock off. In VT100 App mode with NumLock on, all keys generate their literals (as in normal mode), but see further below regarding the Shift key. With NumLock off, mappings are generated as per the below table, depending on the terminal mode setting.
NumLock on | NumLock off | Normal | VT100 App | VT52 App |
---|---|---|---|---|
KP_Space | SP | SS3 SP | ESC ? SP | |
KP_Tab | TAB | SS3 I | ESC ? I | |
KP_Enter | CR | SS3 M | ESC ? M | |
KP_Multiply | * | SS3 j | ESC ? j | |
KP_Add | + | SS3 k | ESC ? k | |
KP_Separator | , | SS3 l | ESC ? l | |
KP_Subtract | - | SS3 m | ESC ? m | |
KP_Decimal | KP_Delete | . | SS3 n | ESC ? n |
KP_Divide | / | SS3 o | ESC ? o | |
KP_0 | KP_Insert | 0 | SS3 p | ESC ? p |
KP_1 | KP_End | 1 | SS3 q | ESC ? q |
KP_2 | KP_Down | 2 | SS3 r | ESC ? r |
KP_3 | KP_Page_Down | 3 | SS3 s | ESC ? s |
KP_4 | KP_Left | 4 | SS3 t | ESC ? t |
KP_5 | KP_Begin | 5 | SS3 u | ESC ? u |
KP_6 | KP_Right | 6 | SS3 v | ESC ? v |
KP_7 | KP_Home | 7 | SS3 w | ESC ? w |
KP_8 | KP_Up | 8 | SS3 x | ESC ? x |
KP_9 | KP_Page_Up | 9 | SS3 y | ESC ? y |
KP_Equal | = | SS3 X | ESC ? X |
Modifier keys do not cause the SS3 to change to CSI. This is how xterm behaves, and Zutty emulates that behaviour.
Examples:
- Alt + KP_Minus: SS3 3 m
- Control + KP_Enter: SS3 5 M
- Control + KP_Plus: SS3 5 k
- Control + Shift + KP_Left: SS3 6 t
Modifiers are not applied in VT52 mode.
There is some additional subtlety related to use of the Shift key.
Pressing Shift has a momentary effect of inverting the NumLock state.
This is not specific to Zutty; it works on the X level and is easily
seen via e.g., xev
. For example, with NumLock off, hitting "4" on
the numeric keypad will generate KP_Left
, while hitting the same key
with Shift held down will generate KP_4
. With NumLock on, results
will be reversed: an unmodified keypress will generate KP_4
, while a
Shift-press will generate KP_Left
.
Why is this interesting? Let's go through the encodings of these keys. In normal (numeric) mode, Zutty generates the literals shown in the Normal column regardless of the NumLock state, and without any modifier encoding. That is, hitting "4" on the keypad will yield a "4" with or without NumLock, and all modifiers will be discarded.
In application (aka. ANSI, aka. alternate) keypad mode, however, all
the details come into play. Hitting keypad "4" will generate "4" only
if NumLock is on; with NumLock off, it will be encoded as the escape
sequence SS3 t
. Further, holding Shift while hitting the same key
will have slightly asymmetrical results depending on NumLock state:
- With NumLock off, Zutty will consider the keypress as a modifier
combination of Shift plus
KP_Left
, and encode it asSS3 2 t
. In the same manner, Control plusKP_Left
will be encoded asSS3 5 t
, and so on for other (possibly compounded) modifiers and keys. - With NumLock on, the baseline is to generate literals only, just as
in numeric mode. Modifiers will be ignored, so Control +
KP_4
(the keysym Zutty sees due to NumLock being on) will still generate a "4" only. However, if Shift is among the active modifiers, it will turnKP_4
back intoKP_Left
, and the result will be, again, encoded asSS3 2 t
(or the corresponding modifier code).
The intention is that Zutty behaves just like xterm with VT220-style
function keys. In case of manual side-by-side comparisons, please
remember to put xterm into "VT220 Keyboard" mode (by choosing it in
the Control + left-click menu, setting the XTerm.keyboardType
X
resource to vt220
, or passing -kt vt220
on the command line).
Special key combinations
The resource settings altSendsEscape
and modifyOtherKeys
(modeled
after xterm) control how other key combinations (not specified in the
above tables) are encoded.
The encoding rules are, by and large, meant to be the same as that of
xterm; please refer to its extensive documentation for details. As a
complement, below we present several example key encodings for
different values of modifyOtherKeys
(columns 0, 1 and 2), with an
altSendsEscape
setting of true (the default).
Key | 0 | 1 | 2 |
---|---|---|---|
Shift-a | A | A | CSI 27 ; 2 ; 65 ~ |
Shift-Space | Space | Space | CSI 27 ; 2 ; 32 ~ |
Shift-TAB | CSI Z | CSI Z | CSI 27 ; 2 ; 9 ~ |
Shift-Return | Return | CSI 27 ; 2 ; 13 ~ | CSI 27 ; 2 ; 13 ~ |
Control-Space | ^@ | ^@ | CSI 27 ; 5 ; 32 ~ |
Control-Alt-Space | ESC ^@ | ESC ^@ | CSI 27 ; 7 ; 32 ~ |
Control-Shift-Space | ^@ | ^@ | CSI 27 ; 6 ; 32 ~ |
Control-Alt-Shift-Space | ESC ^@ | ESC ^@ | CSI 27 ; 8 ; 32 ~ |
Control-TAB | TAB | CSI 27 ; 5 ; 9 ~ | CSI 27 ; 5 ; 9 ~ |
Control-Return | Return | CSI 27 ; 5 ; 13 ~ | CSI 27 ; 5 ; 13 ~ |
Control-Alt-Return | ESC Return | CSI 27 ; 7 ; 13 ~ | CSI 27 ; 7 ; 13 ~ |
Control-Alt-Shift-Return | ESC Return | CSI 27 ; 8 ; 13 ~ | CSI 27 ; 8 ; 13 ~ |
Control-/ | ^_ | ^_ | CSI 27 ; 5 ; 47 ~ |
Control-0 | 0 | CSI 27 ; 5 ; 48 ~ | CSI 27 ; 5 ; 48 ~ |
Control-1 | 1 | CSI 27 ; 5 ; 49 ~ | CSI 27 ; 5 ; 49 ~ |
Control-2 | ^@ | ^@ | CSI 27 ; 5 ; 50 ~ |
Control-3 | ESC | ESC | CSI 27 ; 5 ; 51 ~ |
Control-4 | ^\ | ^\ | CSI 27 ; 5 ; 52 ~ |
Control-5 | ^] | ^] | CSI 27 ; 5 ; 53 ~ |
Control-6 | ^^ | ^^ | CSI 27 ; 5 ; 54 ~ |
Control-7 | ^_ | ^_ | CSI 27 ; 5 ; 55 ~ |
Control-8 | DEL | DEL | CSI 27 ; 5 ; 56 ~ |
Control-9 | 9 | CSI 27 ; 5 ; 57 ~ | CSI 27 ; 5 ; 57 ~ |
Control-! (Control-Shift-1) | ! | CSI 27 ; 6 ; 33 ~ | CSI 27 ; 6 ; 33 ~ |
Control-@ (Control-Shift-2) | ^@ | ^@ | CSI 27 ; 6 ; 64 ~ |
Control-# (Control-Shift-3) | # | CSI 27 ; 6 ; 35 ~ | CSI 27 ; 6 ; 35 ~ |
Control-$ (Control-Shift-4) | $ | CSI 27 ; 6 ; 36 ~ | CSI 27 ; 6 ; 36 ~ |
Control-% (Control-Shift-5) | % | CSI 27 ; 6 ; 37 ~ | CSI 27 ; 6 ; 37 ~ |
Control-^ (Control-Shift-6) | ^^ | ^^ | CSI 27 ; 6 ; 94 ~ |
Control-& (Control-Shift-7) | & | CSI 27 ; 6 ; 38 ~ | CSI 27 ; 6 ; 38 ~ |
Control-* (Control-Shift-8) | * | CSI 27 ; 6 ; 42 ~ | CSI 27 ; 6 ; 42 ~ |
Control-( (Control-Shift-9) | ( | CSI 27 ; 6 ; 40 ~ | CSI 27 ; 6 ; 40 ~ |
Control-) (Control-Shift-0) | ) | CSI 27 ; 6 ; 41 ~ | CSI 27 ; 6 ; 41 ~ |
Control-[ | ^[ | ^[ | CSI 27 ; 5 ; 91 ~ |
Control-] | ^] | ^] | CSI 27 ; 5 ; 93 ~ |
Control-{ (Control-Shift-[) | ^[ | ^[ | CSI 27 ; 6 ; 123 ~ |
Control-} (Control-Shift-]) | ^] | ^] | CSI 27 ; 6 ; 125 ~ |
Control-c | ^C | ^C | CSI 27 ; 5 ; 99 ~ |
Control-d | ^D | ^D | CSI 27 ; 5 ; 100 ~ |
Control-i | TAB | TAB | CSI 27 ; 5 ; 105 ~ |
Control-Shift-I | TAB | TAB | CSI 27 ; 6 ; 73 ~ |
Control-x | ^X | ^X | CSI 27 ; 5 ; 120 ~ |
Control-Alt-x | ESC ^X | ESC ^X | CSI 27 ; 7 ; 120 ~ |
Control-Shift-D | ^D | ^D | CSI 27 ; 6 ; 68 ~ |
Control-Alt-Shift-D | ESC ESC | ESC ESC | CSI 27 ; 8 ; 68 ~ |
Control-; | ; | CSI 27 ; 5 ; 59 ~ | CSI 27 ; 5 ; 59 ~ |
Control-: (Control-Shift-;) | : | CSI 27 ; 6 ; 58 ~ | CSI 27 ; 6 ; 58 ~ |
Control-\ | ^\ | ^\ | CSI 27 ; 5 ; 92 ~ |
Control-¦ (Control-Shift-\) | ^\ | ^\ | CSI 27 ; 6 ; 124 ~ |
Control-` | ^@ | ^@ | CSI 27 ; 5 ; 96 ~ |
Control-~ (Control-Shift-`) | ^^ | ^^ | CSI 27 ; 6 ; 126 ~ |
Alt-Space | ESC Space | ESC Space | CSI 27 ; 3 ; 32 ~ |
Alt-Shift-Space | ESC Space | ESC Space | CSI 27 ; 4 ; 32 ~ |
Alt-TAB | ESC TAB | ESC TAB | CSI 27 ; 3 ; 9 ~ |
Alt-Return | ESC Return | CSI 27 ; 3 ; 13 ~ | CSI 27 ; 3 ; 13 ~ |
Alt-Shift-Return | ESC Return | CSI 27 ; 4 ; 13 ~ | CSI 27 ; 4 ; 13 ~ |
Alt-d | ESC d | ESC d | CSI 27 ; 3 ; 100 ~ |
Alt-Shift-d | ESC D | ESC D | CSI 27 ; 4 ; 68 ~ |
Alt-x | ESC x | ESC x | CSI 27 ; 3 ; 120 ~ |
Alt-Shift-X | ESC X | ESC X | CSI 27 ; 4 ; 88 ~ |