foot/commands.c
Campbell Barton d28ac267d2 Add an optional build-time switch to disable scrollback support
This change introduces a new `scrollback` Meson build option (enabled
by default) that lets foot be compiled without scrollback history.
When the option is off, `FOOT_HAVE_SCROLLBACK` is left
undefined and the relevant code is excluded from the build,
producing a slimmer terminal for use cases that do not need it.

With scrollback disabled:

- The `[scrollback]` section in `foot.ini` and its key bindings
  become no-ops.
- In-terminal search is removed,
  along with the "pipe scrollback" action, the scrollback indicator,
  and their colors/overlays.
- IME hooks for the search box, mouse-wheel scrollback handling,
  and related `terminal` state are compiled out.
- Selection auto-scroll (the timer that scrolls the viewport while
  a drag-selection extends past the visible area) is removed,
  since with no scrollback there is nowhere to scroll to.
  The associated function declarations,
  `enum selection_scroll_direction`,
  the `auto_scroll` field on `terminal::selection`,
  and their init/teardown sites are all excluded from the build.

To keep action enumerations stable across build configurations,
two range markers (`BIND_ACTION_PIPE_FIRST` / `BIND_ACTION_PIPE_LAST`)
are introduced so that pipe-action handling does not depend on
`PIPE_SCROLLBACK` being present. The build summary and
`foot --version` now report `+scrollback` or `-scrollback`,
and the config tests have been updated to account for optional section.
2026-05-19 16:29:34 +10:00

117 lines
3.1 KiB
C

#include "commands.h"
#define LOG_MODULE "commands"
#define LOG_ENABLE_DBG 0
#include "log.h"
#include "grid.h"
#include "render.h"
#include "selection.h"
#include "terminal.h"
#include "url-mode.h"
#include "util.h"
#if defined(FOOT_HAVE_SCROLLBACK)
void
cmd_scrollback_up(struct terminal *term, int rows)
{
if (term->grid == &term->alt)
return;
if (urls_mode_is_active(term))
return;
const struct grid *grid = term->grid;
const int view = grid->view;
const int grid_rows = grid->num_rows;
/* The view row number in scrollback relative coordinates. This is
* the maximum number of rows we're allowed to scroll */
int sb_start = grid_sb_start_ignore_uninitialized(grid, term->rows);
int view_sb_rel =
grid_row_abs_to_sb_precalc_sb_start(grid, sb_start, view);
rows = min(rows, view_sb_rel);
if (rows == 0)
return;
int new_view = (view + grid_rows) - rows;
new_view &= grid_rows - 1;
xassert(new_view != view);
xassert(grid->rows[new_view] != NULL);
#if defined(_DEBUG)
for (int r = 0; r < term->rows; r++)
xassert(grid->rows[(new_view + r) & (grid->num_rows - 1)] != NULL);
#endif
LOG_DBG("scrollback UP: %d -> %d (offset = %d, rows = %d)",
view, new_view, offset, grid_rows);
selection_view_up(term, new_view);
term->grid->view = new_view;
if (rows < term->rows) {
term_damage_scroll(
term, DAMAGE_SCROLL_REVERSE_IN_VIEW,
(struct scroll_region){0, term->rows}, rows);
term_damage_rows_in_view(term, 0, rows - 1);
} else
term_damage_view(term);
render_refresh_urls(term);
render_refresh(term);
}
void
cmd_scrollback_down(struct terminal *term, int rows)
{
if (term->grid == &term->alt)
return;
if (urls_mode_is_active(term))
return;
const struct grid *grid = term->grid;
const int offset = grid->offset;
const int view = grid->view;
const int grid_rows = grid->num_rows;
const int screen_rows = term->rows;
const int scrollback_end = offset;
/* Number of rows to scroll, without going past the scrollback end */
int max_rows = 0;
if (view <= scrollback_end)
max_rows = scrollback_end - view;
else
max_rows = offset + (grid_rows - view);
rows = min(rows, max_rows);
if (rows == 0)
return;
int new_view = (view + rows) & (grid_rows - 1);
xassert(new_view != view);
xassert(grid->rows[new_view] != NULL);
#if defined(_DEBUG)
for (int r = 0; r < term->rows; r++)
xassert(grid->rows[(new_view + r) & (grid_rows - 1)] != NULL);
#endif
LOG_DBG("scrollback DOWN: %d -> %d (offset = %d, rows = %d)",
view, new_view, offset, grid_rows);
selection_view_down(term, new_view);
term->grid->view = new_view;
if (rows < term->rows) {
term_damage_scroll(
term, DAMAGE_SCROLL_IN_VIEW,
(struct scroll_region){0, term->rows}, rows);
term_damage_rows_in_view(term, term->rows - rows, screen_rows - 1);
} else
term_damage_view(term);
render_refresh_urls(term);
render_refresh(term);
}
#endif /* FOOT_HAVE_SCROLLBACK */