#pragma once #include namespace fgc { // Viewport arithmetic for the scrollable TUI panes. Pure integer math with no // FTXUI types, so it lives in fgc_core and is unit-testable without a terminal - // mirroring UiSnapshot's formatting helpers. // // The model is a line-anchored viewport: `top` is the first body LINE we want // visible. Heights come from the previous frame's measurements, so every entry // point has to tolerate `view_h == 0` (nothing measured yet) without dividing by // zero or handing back a position the renderer can't honour. // Largest valid `top` for a body of `content_h` lines in a `view_h` window. // 0 when it all fits, and 0 while the view is still unmeasured. int scrollMax(int content_h, int view_h); int scrollClamp(int top, int content_h, int view_h); // One line per keypress; `delta` is +/-1. int scrollBy(int top, int delta, int content_h, int view_h); // A screenful less two lines of overlap, so the eye keeps its place. `dir` is // +/-1; the step is at least 1 even in a one-line pane. int scrollPage(int top, int dir, int content_h, int view_h); // Rows per column for a wrapped grid. Short grids keep a compact multi-column // look (at least `min_rows` per column); past `max_cols` columns the grid grows // DOWNWARD instead of off the right edge, where vertical scrolling can reach it. std::size_t gridRowsPerColumn(std::size_t item_count, std::size_t max_cols, std::size_t min_rows); } // namespace fgc