tty: the grid was 80x24 on a 160x50 screen, and wrapping was eager
Three symptoms, two causes, both in the terminal layer.
**The grid and TIOCGWINSZ disagreed about the size.** vt_init() sizes every
grid from gfx_cols()/gfx_rows(), and it runs at main.c:75 -- while the display
driver attaches its scanout from the PCI bus walk at main.c:99. So the grids
were the 80x24 fallback, and TIOCGWINSZ, which computed its own answer live,
said 160x50.
That one disagreement produced all three things visible in the report: text
stopped two thirds of the way down the screen, `ls` laid out 160 columns into
an 80-column grid so words split across the wrap ("vers" / "ion"), and zsh's
cursor tracking was wrong on every line.
Fixed in two places, because either alone would leave the trap set:
gfx_attach_scanout() now calls vt_resize(), so the grids learn the real screen
the moment there is one; and TIOCGWINSZ reports v->cols/v->rows rather than
measuring again. One number, from the terminal being asked.
**Wrapping was eager.** A glyph printed in the last column moved the cursor to
the next line immediately. Real terminals set a pending-wrap flag and wrap when
the *next* glyph arrives -- which is why a line exactly as wide as the screen
takes one row and not two, and why a program can write the bottom-right cell
without scrolling.
zsh's partial-line marker depends on that rule directly: it writes exactly
COLUMNS-1 spaces and expects to still be on the line. With eager wrap it left a
reverse-video '#' above every prompt, which is the hashtag in the report. Both
are gone.
Verified by screendump: `ls /proc` now fits one line with "version" intact, no
markers, and output fills the screen to the last row. schfs-check passes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
This commit is contained in:
parent
1c1b0c9570
commit
a5b0d5a0ef
5 changed files with 137 additions and 25 deletions
|
|
@ -109,6 +109,30 @@ keyboard driver names it and stops.
|
|||
Input goes to whichever terminal is on screen. That is what makes a terminal a
|
||||
terminal: the keyboard follows the eyes.
|
||||
|
||||
## Two rules that are easy to get wrong
|
||||
|
||||
**The grid is the only source of truth for the size.** `TIOCGWINSZ` reports
|
||||
`v->cols`/`v->rows`, not a fresh `gfx_cols()`/`gfx_rows()`. When it computed
|
||||
its own answer there were two, and they disagreed: the grids are sized at
|
||||
`vt_init()`, which runs before the display driver is found on the PCI bus, so
|
||||
they were 80x24 while `TIOCGWINSZ` said 160x50. Text stopped two thirds of the
|
||||
way down the screen, `ls` formatted for a width the grid did not have and split
|
||||
words across the wrap, and zsh's cursor tracking was wrong on every line --
|
||||
three symptoms, one disagreement. `vt_resize()` now corrects the grids when a
|
||||
scanout arrives, and the ioctl reads them.
|
||||
|
||||
**A glyph in the last column does not wrap.** It sets `wrap_pending`, and the
|
||||
wrap happens when the *next* glyph arrives. Every real terminal behaves this
|
||||
way and none of them document it clearly. Wrapping immediately makes a line
|
||||
exactly as wide as the screen take two rows instead of one, and makes it
|
||||
impossible to write the bottom-right cell without scrolling -- and zsh's
|
||||
partial-line marker depends on the rule directly: it writes exactly
|
||||
`COLUMNS - 1` spaces and expects the cursor to still be on that line. With
|
||||
immediate wrap, a reverse-video `#` appeared above every prompt.
|
||||
|
||||
Anything that moves the cursor deliberately -- CR, LF, backspace, an escape
|
||||
sequence -- clears the debt.
|
||||
|
||||
## What it does not do
|
||||
|
||||
- **No scrollback.** The grid is exactly the visible screen. Shift+PageUp does
|
||||
|
|
|
|||
Loading…
Reference in a new issue