DECUDK User Defined Keys
Load the strings the function keys send, and optionally lock them against being loaded again.
DCS Pc ; Pl | Ky1/St1 ; … ; Kyn/Stn ST
- Defaults
- Pc = 0, clear all keys first; Pl = 0, lock the keys
- DEC STD 070
- §11.3 User Defined Keys, p. 11-9
- VT220
- §4.15 User Defined Keys (DECUDK)
- VT510
- DECUDK—User Defined Keys
DECUDK is a device control string that tells the terminal what its shifted function keys should send. Each definition in the string is a key number, a /, and the string the key sends, written as pairs of hexadecimal digits: 17/414243 makes F6 send ABC. Definitions are separated by ;.
The two parameters decide what happens to the keys already defined. DEC STD 070 describes them on p. 11-11:
| Parameter | 0, or left out | 1 |
|---|---|---|
Pc, clear (DEC STD 070 calls it Pe) | clear every key before loading | clear only the keys being loaded |
Pl, lock | lock the keys against being loaded again | leave them unlocked |
Locking “causes all subsequent DECUDK sequences to be ignored (until the lock is cleared by the terminal user under local control)”. The host can ask whether the keys are locked with the DEC device status report CSI ? 25 n, which answers CSI ? 20 n for unlocked and CSI ? 21 n for locked (p. 11-7). DECUDK is defined for level 2 and above.
xterm implements DECUDK at level 2 and above, which takes in its default level 4. It clears the keys when Pc is 0, and loads the definitions (misc.c, parse_decudk). It never looks at Pl, so the keys are never locked, and its answer to CSI ? 25 n is always the same (charproc.c):
reply.a_param[count++] = 20; /* UDK always unlocked */
The cases follow xterm, so a lock asked for with Pl 0 is not taken.
What a key sends once it is defined is keyboard input, which the case runner cannot press, so the cases check only that the string is consumed and what the terminal reports afterwards.
Not in libghostty-vt
libghostty-vt has no user-defined keys. Its DCS handler in dcs.zig recognizes tmux control mode, XTGETTCAP (DCS + q) and DECRQSS (DCS $ q), and drops every other device control string, DECUDK included, without acting on it. It does not answer CSI ? 25 n at all (see DECDSR), which is why DECUDK-2 fails.
Validation
DECUDK-1: The definitions are not displayed
\eP0;1|17/414243;18/444546\e\\ # F6 sends ABC, F7 sends DEF
X
|X____|
cursor 1,2
reply none
DECUDK-2: xterm does not lock the keys
\eP1;0|17/414243\e\\ # Pl 0 asks for the keys to be locked
\e[?25n # are they?
|_____|
reply \e[?20n
xterm answers that the keys are unlocked, as it always does. DEC STD 070 would lock them and answer CSI ? 21 n. libghostty-vt sends nothing.