Skip to content

Commit 9006bed

Browse files
committed
auto allocation
1 parent 85c3ba2 commit 9006bed

1 file changed

Lines changed: 71 additions & 7 deletions

File tree

specs/glyph-protocol.md

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
**Author:** Raphael Amorim
44
**Year:** 2026
5-
**Last updated:** 2026-04-20
5+
**Last updated:** 2026-04-21
66

77
**See also:**
88
- Blog post introducing the protocol and its rationale:
@@ -201,14 +201,18 @@ For non-PUA codepoints only `0` and `1` are possible.
201201
### 6.1 Request
202202

203203
```
204-
ESC _ 25a1 ; r ; cp=<hex> ; fmt=glyf ; reply=<0|1|2> ; upm=<int> ; <base64-payload> ESC \
204+
ESC _ 25a1 ; r ; cp=<hex|auto> ; fmt=glyf ; reply=<0|1|2> ; upm=<int> ; <base64-payload> ESC \
205205
```
206206

207207
Parameters:
208208

209-
- `cp` — target codepoint in hex. MUST be in one of the PUA ranges
210-
defined in §4. Otherwise the request is rejected with
211-
`reason=out_of_namespace`.
209+
- `cp` — target codepoint in hex, OR the literal string `auto` to
210+
request terminal-side auto-allocation.
211+
- When hex: MUST be in one of the PUA ranges defined in §4.
212+
Otherwise the request is rejected with `reason=out_of_namespace`.
213+
- When `auto`: the terminal picks a free PUA codepoint, registers
214+
the payload there, and echoes the allocated codepoint in the
215+
reply's `cp` field. See §6.5.
212216
- `fmt` — payload format. One of `glyf`, `colrv0`, `colrv1`.
213217
Optional; `glyf` is the default. See §8 for each format's wire
214218
layout.
@@ -236,7 +240,9 @@ For `reply=1` (the default), successful registrations emit:
236240
ESC _ 25a1 ; r ; cp=<hex> ; status=0 ESC \
237241
```
238242

239-
`cp` is echoed from the request.
243+
`cp` is echoed from the request. When the request used `cp=auto`,
244+
the reply's `cp` is the hex codepoint the terminal allocated (never
245+
the literal `auto`), so the client can emit it.
240246

241247
Failures, when not suppressed by `reply=0`, emit:
242248

@@ -257,6 +263,8 @@ Defined error codes:
257263
| `hinting_unsupported` | Payload contains hinting instructions. |
258264
| `malformed_payload` | Payload failed to parse as `glyf`. |
259265
| `payload_too_large` | Payload exceeds 64 KiB post-base64-decode. |
266+
| `auto_unsupported` | `cp=auto` was requested but this terminal does not implement auto-allocation. |
267+
| `glossary_exhausted` | `cp=auto` was requested and no free PUA codepoint was available (see §6.5). |
260268

261269
### 6.3 Overwrite and eviction
262270

@@ -276,6 +284,59 @@ Registrations live for the duration of the terminal session. A
276284
terminal reset (e.g. `ESC c`) MAY clear the entire glossary.
277285
Registrations MUST NOT persist across terminal restarts.
278286

287+
### 6.5 Auto-allocation (`cp=auto`)
288+
289+
`cp=auto` asks the terminal to pick the codepoint on the client's
290+
behalf. It exists so applications that do not care *which* PUA
291+
slot their icon lands at — the common case — do not have to hand-
292+
pick a codepoint, coordinate with other apps, or hardcode a range.
293+
294+
**Allocation.** On `cp=auto` the terminal MUST allocate a codepoint
295+
that:
296+
297+
1. Is in one of the three PUA ranges defined in §4.
298+
2. Is not currently registered in this session's glossary.
299+
300+
Terminals SHOULD allocate from Supplementary PUA-B
301+
(`U+100000``U+10FFFD`) by default, because that range has no
302+
existing convention — no Nerd Font, Powerline, or Font Awesome
303+
mapping — so the allocated codepoint is unambiguously the
304+
registration's, not a system font's. The exact allocation strategy
305+
(sequential, random, recycled on clear) is implementation-defined;
306+
clients MUST NOT assume any particular ordering.
307+
308+
**Reply.** The allocated codepoint is communicated to the client
309+
via the `cp=<hex>` field of the success reply (§6.2). Because the
310+
client has no other way to learn which codepoint was allocated,
311+
`cp=auto` MUST produce a reply regardless of the `reply` parameter:
312+
313+
- `reply=1` (default) — normal success/failure replies. No change.
314+
- `reply=2` — the terminal MUST still emit the success reply for
315+
`cp=auto` requests, because the allocated codepoint is carried
316+
in it. For non-`auto` registrations in the same stream `reply=2`
317+
still suppresses success ACKs as specified in §6.1.
318+
- `reply=0` — the terminal MUST still emit the success reply for
319+
`cp=auto` requests for the same reason. A client that genuinely
320+
wants fire-and-forget registration cannot use `cp=auto`; it must
321+
pick its own codepoint.
322+
323+
**Allocation failure.** If every PUA codepoint in the terminal's
324+
chosen allocation pool is already registered, the terminal MAY
325+
either evict the oldest registration in FIFO order (as with
326+
explicit `cp`, §6.3) and reuse that slot, or reject the request
327+
with `reason=glossary_exhausted`. With the default 1024-slot cap
328+
and ~64K codepoints in PUA-B alone, exhaustion is not reachable
329+
in practice; the error code exists so non-default allocation
330+
strategies (e.g. a small reserved window) remain conformant.
331+
332+
**Unsupported.** Terminals that implement Glyph Protocol v1.4 or
333+
earlier will not recognise `cp=auto` and will most likely reject
334+
the request with `reason=malformed_payload` (the value fails hex
335+
parsing). Terminals that understand `cp=auto` but choose not to
336+
implement it SHOULD reject with `reason=auto_unsupported` so
337+
clients can distinguish a protocol-level "no" from a payload
338+
error and fall back to hand-picking a codepoint.
339+
279340
## 7. Clear (`c`)
280341

281342
### 7.1 Request
@@ -529,7 +590,9 @@ A terminal emulator is Glyph Protocol v1 conformant if it:
529590
defined in this specification, and advertises every accepted
530591
payload format via the `fmt=` bitfield in the `s` reply.
531592
3. Restricts register/clear `cp` to the three PUA ranges; rejects
532-
anything else with `reason=out_of_namespace`.
593+
anything else with `reason=out_of_namespace`. Accepts `cp=auto`
594+
on `r` and allocates a free PUA codepoint per §6.5, OR rejects
595+
with `reason=auto_unsupported`.
533596
4. Holds at most 1024 simultaneous registrations per session and
534597
evicts in FIFO order when full.
535598
5. Accepts the `glyf` simple-glyph subset defined in §8.2. The
@@ -660,3 +723,4 @@ rather than serving a stale bitmap.
660723
| 2026-04-19 | v1.2 | Added `fmt=colrv0` and `fmt=colrv1` payload formats wrapping OpenType `COLR` / `CPAL` tables with sidecar `glyf` outlines. Both advertised via bits 1 and 2 of the `s` reply's `fmt=` bitfield. |
661724
| 2026-04-19 | v1.3 | Added `reply=0|1|2` parameter to the `r` verb so bulk registrations can suppress success ACKs (`reply=2`) or go fully fire-and-forget (`reply=0`). Default `reply=1` preserves v1.0 behaviour. |
662725
| 2026-04-19 | v1.4 | Raised the glossary capacity from 256 to 1024 simultaneous registrations per session, and raised the `n_glyphs` cap in `fmt=colrv0`/`colrv1` containers from 256 to 1024 outlines. Both bumps quadruple the worst-case memory footprint; the 64 KiB per-payload cap is unchanged. |
726+
| 2026-04-21 | v1.5 | Added `cp=auto` to the `r` verb: the terminal allocates a free PUA codepoint (SHOULD come from PUA-B) and echoes it in the success reply so the client can emit it. Added `reason=auto_unsupported` and `reason=glossary_exhausted` error codes. `cp=auto` forces a success reply regardless of `reply=0|2` because the allocated codepoint is only carried in the reply. |

0 commit comments

Comments
 (0)