Follow-up testing showed that the mailbox limit did not fix the base64
hang: moving the pointer stalled the app, and opening a tab could hang it.
Mouse link lookup copied the entire wrapped line before checking modifier
eligibility, while renderer link searches had no whole-search work budget.
Filter eligible links before traversing scrollback. Add bounded logical
line selection and skip automatic regex lookup on lines exceeding 65,536
grid cells. Keep explicit line selection and OSC8 handling unrestricted.
Skip oversized lines instead of truncating URLs into different targets.
Apply the existing terminal StringMap retry budget to renderer searches
and handle search errors without panicking. The regression triggered a
retry-limit panic through the old onig search API and now returns normally,
allowing subsequent link patterns to run.
Document the lookup limits and correct the earlier mailbox fix entry to
record that it did not resolve the reported hang on its own.
Test Plan:
- 1,513 unit/integration tests and one doctest pass across core, renderer,
and terminal with Mesa software OpenGL; one existing doctest is ignored.
- Release application build, formatting, and all-target Clippy pass.
- GTK handles 400 pointer moves, including Ctrl hover, during continuous
base64 output, opens/closes a tab, handles Ctrl+C, prints a marker, and
exits cleanly. Normal URL hover still works after a hard newline.
Reference: docs/rewrite/DEVIANT_FIXES.md (entry 41)
Resolves the 13 rows still partial in docs/rewrite/notes/review-rv4-
codex.md (details in final-Z5.md):
- Escaped config strings are decoded to raw bytes at every OS boundary:
Flatpak cwd/argv to D-Bus, screen-file paths, the default config
template, GHOSTTY_RESOURCES_DIR/TERMINFO/shell integration/
bindtextdomain consumers, custom shader loading, list-themes hyperlinks.
- osbytes escapes literal U+FDD0 on non-Unix too (bijective everywhere);
the GTK paste dialog only decodes text that was actually encoded.
- shadertoy: whole-array uses of iChannelTime rebuild a plain float[4]
from the std140-padded members (naga-validated, MSL offsets checked).
- libghostty-vt: the OSC parser holds caller-allocated storage inline
and command payloads borrow from it, so ghostty_osc_end performs no
global allocations (verified from Rust and C).
- crash: aarch64 Linux minidump context fixed; macOS fatal signals record
siginfo, registers and a fault-safe stack walk.
- tripwire: selectionString map allocation-failure cleanup test ported.
- libghostty-vt emits the versioned soname libghostty-vt.so.0 at build
time (no patchelf needed at install).
Test Plan:
- cargo test --workspace (3342 passed)
- just check-macos; just check-macos x86_64-apple-darwin;
just check-windows; just check-wasm
- cargo check --target aarch64-unknown-linux-gnu -p ghostty-crash
rustfmt.toml sets group_imports, imports_granularity and imports_layout,
which are nightly-only; agents formatted with stable rustfmt, which
ignored them. This is a formatting-only pass with `cargo +nightly fmt`.
Test Plan:
- cargo clippy --workspace --all-targets -- -D warnings
- cargo test --workspace
Second pass over the page memory model (done by Codex/gpt-6-astra in an
isolated worktree, reviewed and merged here):
- Resize/reflow now port Zig's incremental ReflowCursor algorithm with
page backfill and the same capacity growth/split sequence, instead of
rebuilding a snapshot, so page boundaries, pruning and tracked-pin
remapping match Ghostty.
- Point<->pin conversion for the active area starts at the list tail and
the viewport offset is cached, so hot-path operations no longer walk
the whole scrollback from the head.
- RefCountedSet reproduces Zig's observable ID reuse and error points.
- All 202 PageList tests are ported (plus 13 extra regressions).
With this, the five Screen/Terminal tests previously ignored as blocked
on PageList behaviour pass and are re-enabled.
Test Plan:
- cargo test -p ghostty-terminal (913 passed, 0 ignored)
- cargo clippy -p ghostty-terminal --all-targets -- -D warnings
Ports ZIG/src/terminal/{Screen,ScreenSet,Tabstops,Selection}.zig on top
of the page/PageList layer. The cursor holds a TrackedPin; Zig's cached
page_row/page_cell pointers become accessor methods. Selection methods
take the PageList explicitly because tracked bounds are handles.
Screen tests use minimal plain-text dump/selection-string helpers that
follow the formatter's semantics; they will delegate to the real
formatter once formatter.zig is ported.
Gaps found in the PageList layer are recorded for the parity pass in
docs/rewrite/notes/ghostty-terminal-pagelist-requests.md; three resize
tests are #[ignore]d pending those fixes (PageList::resize keeps
trailing blank rows Zig drops). Kitty image storage and StringMap are
placeholders.
Test Plan:
- cargo test -p ghostty-terminal (443 passed, 3 ignored; Screen 183/184,
Selection 18/18, Tabstops 4/5 - skipped tests use allocator failure
injection)