mirror of
https://git.jabber.space/devs/cproof.git
synced 2026-07-18 20:46:21 +00:00
Four-level refactor of the chat-window scrolling state:
L1. Extract win_page_space() and unify the two-branch clamp at the end of
win_page_down into a single last_page_start formula. Removes the
duplicated `getmaxy(stdscr) - 4` magic across page_up / page_down /
sub_page_up / sub_page_down and the off-by-one between the two clamp
branches.
L2. Remove ProfLayout::paged sticky flag. Replace with win_is_paged(),
derived from y_pos and the current pad height. Eliminates the entire
bug class of "stuck paged=1" — there is no flag to drift, no manual
reset to forget. The earlier non-CHAT bottom-reach reset, the
WIN_SCROLL_REACHED_BOTTOM reset, the win_clear paged=1 line, and the
cl_ev_send_ai_msg paged=0 workaround all collapse into "y_pos governs
everything." cl_ev_send_ai_msg now calls win_move_to_end so the user's
own message is visible after scroll-up.
L3. _win_printf no longer drops messages when paged. The line is appended
to the buffer and to the curses pad unconditionally; it lands below
the visible viewport so the user's reading position is unchanged. The
unread badge still increments. Suppressed messages are no longer lost
forever — page-down naturally reveals them.
L4. Replace the win_scroll_state_t enum (INNER / REACHED_TOP /
REACHED_BOTTOM, conflating layout edge with DB exhaustion) with a
ScrollEdges struct of two independent booleans:
db_exhausted_above — a previous page-up DB fetch returned empty
db_exhausted_below — same for page-down
The flags are flipped to TRUE on DB_RESPONSE_EMPTY and cleared by a
scroll in the opposite direction (so MAM late-delivery and /history
switch can re-trigger fetches). Buffer-edge state is no longer
encoded here — y_pos handles that.
Tests: stub_ui gets a no-op win_move_to_end. 545/545 unit tests pass.