1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//! The one scroll driver every screen taller than its terminal shares.
//!
//! [`Viewport`](crate::lookout::viewport::Viewport) scrolls in data rows,
//! while the height a screen is drawn into counts lines. A screen with
//! chrome (a section header, a blank separator, a caption, a column
//! header, two hidden-count markers) cannot ask the viewport how much
//! fits and get an answer about its own body.
//!
//! The fix is the same shape on every screen: treat the viewport's offset
//! as a starting point, lay the body out from there, and walk down one
//! row at a time until the cursor's row is among the lines that came
//! back. The walk and its last resort live here.
//!
//! What the two screens share is the invariant this module holds: the
//! cursor is drawn at every height a screen claims it can be drawn at.
use Line;
/// One attempt at a body, laid out from a given data row.
///
/// No `Debug`: it is built and consumed inside [`to_cursor`], and a
/// `Vec<Line>` prints as noise rather than as anything a test would assert
/// on.
pub
/// Lays the body out from the first offset at or below `start` whose
/// attempt draws the cursor's row, and falls back when none does.
///
/// The walk can run out. A four-line body has no room for a section's own
/// header, blank separator and both markers above a single row, and at
/// `view::MIN_HEIGHT` that is the whole budget. When it runs out it gives up
/// on the layout rather than on the cursor: `fallback` draws the cursor's
/// row without its section chrome. The cursor is therefore drawn at every
/// height the screen claims to support, and the frame at the floor looks
/// unlike every other frame on purpose.
///
/// At most one pass per row, and each pass is bounded by the budget.
pub