Files
tty7/src
webdev 010457132f fix(terminal): shape a regional-indicator pair as the one flag it is (#686) (#691)
A flag such as 🇨🇳 is two Regional Indicator symbols, U+1F1E8 U+1F1F3.
Each is width 1 to unicode-width, so the grid gives each its own column
and no spacer: the pair already sits in exactly the two columns a flag
occupies. But `segment_row` sent each one to `Solo`, and a `Solo` is its
own `shape_line` call. The shaper never saw the two together, so it had
no chance to form the flag ligature, and each half came out as the
letter-in-a-box glyph an emoji face draws for a lone indicator. A `Solo`
also clips to two cells so a fallback face's advance has room, and that
box is two cells wide, so each half spilled into the next column as well.

Join a Regional Indicator and the one after it into a single two-cell
`Cluster`, the move a7835a0 made for SARA AM: two width-1 codepoints
that own a column each but are not atomic to the shaper. The check sits
ahead of the marks branch so a stray mark on either half (a VS16 on the
first, say) rides along in the cluster text instead of splitting the
pair — split, the other half paints alone as a box again.

`wide_base` stays false. With the ligature there is one glyph at
position zero and the pinning is moot. Without it — a font that lacks
the flag — the shaper returns two glyphs, and `force_width = cell_width`
pins the second into the second column, where it stays visible — the
two legible halves such a setup shows today. `wide_base: true` would
pin it at `2 × cell_width`, past the cluster's two-cell clip, and
swallow half the pair.

The edges fall out of the scan. An indicator in the last column has no
partner on its row and stays `Solo`; two halves of a flag on different
rows cannot be joined, and drawing them apart is the honest answer.
Three in a row pair greedily left to right, which is UAX #29's rule for
them. A style change between the halves keeps the cluster under the
first cell's style, as for SARA AM: a recoloured flag beats two boxes.
Selection, copy, cursor placement and reflow read the alacritty grid,
not `RowSeg`, and are untouched.

A grid-level test feeds 🇨🇳x through the emulator, `snapshot_cell` and
`segment_row`, pinning the premise that each indicator lands in one
plain column. A unicode-width or alacritty bump that changes that fails
there rather than misdrawing quietly.

Out of scope: skin-tone modifiers and ZWJ sequences. Those are a
grid-width problem — alacritty reserves four or six columns for them —
and nothing here touches them.
2026-08-20 08:56:09 +08:00
..