foot/grid.h
Daniel Eklöf 3d66db63cc
grid: refactor reflow
We've been trying to performance optimize reflow by "chunking" cells;
try to gather as many as possible, and memcpy a chunk at once.

The problem is that a) this quickly becomes very complex, and b) is
very hard to get right for multi-column characters, especially when we
need to truncate long ones due to the window being too small.

Refactor, and once again walk and copy all cells one by one. This is
slower, but at least it's correct.
2025-02-10 13:19:50 +01:00

138 lines
3.8 KiB
C

#pragma once
#include <stddef.h>
#include "debug.h"
#include "terminal.h"
struct grid *grid_snapshot(const struct grid *grid);
void grid_free(struct grid *grid);
void grid_swap_row(struct grid *grid, int row_a, int row_b);
struct row *grid_row_alloc(int cols, bool initialize);
void grid_row_free(struct row *row);
void grid_resize_without_reflow(
struct grid *grid, int new_rows, int new_cols,
int old_screen_rows, int new_screen_rows);
void grid_resize_and_reflow(
struct grid *grid, const struct terminal *term, int new_rows, int new_cols,
int old_screen_rows, int new_screen_rows,
size_t tracking_points_count,
struct coord *const _tracking_points[static tracking_points_count]);
/* Convert row numbers between scrollback-relative and absolute coordinates */
int grid_row_abs_to_sb(const struct grid *grid, int screen_rows, int abs_row);
int grid_row_sb_to_abs(const struct grid *grid, int screen_rows, int sb_rel_row);
int grid_sb_start_ignore_uninitialized(const struct grid *grid, int screen_rows);
int grid_row_abs_to_sb_precalc_sb_start(
const struct grid *grid, int sb_start, int abs_row);
int grid_row_sb_to_abs_precalc_sb_start(
const struct grid *grid, int sb_start, int sb_rel_row);
static inline int
grid_row_absolute(const struct grid *grid, int row_no)
{
return (grid->offset + row_no) & (grid->num_rows - 1);
}
static inline int
grid_row_absolute_in_view(const struct grid *grid, int row_no)
{
return (grid->view + row_no) & (grid->num_rows - 1);
}
static inline struct row *
_grid_row_maybe_alloc(struct grid *grid, int row_no, bool alloc_if_null)
{
xassert(grid->offset >= 0);
int real_row = grid_row_absolute(grid, row_no);
struct row *row = grid->rows[real_row];
if (row == NULL && alloc_if_null) {
row = grid_row_alloc(grid->num_cols, false);
grid->rows[real_row] = row;
}
xassert(row != NULL);
return row;
}
static inline struct row *
grid_row(struct grid *grid, int row_no)
{
return _grid_row_maybe_alloc(grid, row_no, false);
}
static inline struct row *
grid_row_and_alloc(struct grid *grid, int row_no)
{
return _grid_row_maybe_alloc(grid, row_no, true);
}
static inline struct row *
grid_row_in_view(struct grid *grid, int row_no)
{
xassert(grid->view >= 0);
int real_row = grid_row_absolute_in_view(grid, row_no);
struct row *row = grid->rows[real_row];
xassert(row != NULL);
return row;
}
void grid_row_uri_range_put(
struct row *row, int col, const char *uri, uint64_t id);
void grid_row_uri_range_erase(struct row *row, int start, int end);
void grid_row_underline_range_put(
struct row *row, int col, struct underline_range_data data);
void grid_row_underline_range_erase(struct row *row, int start, int end);
static inline void
grid_row_uri_range_destroy(struct row_range *range)
{
free(range->uri.uri);
}
static inline void
grid_row_underline_range_destroy(struct row_range *range)
{
}
static inline void
grid_row_range_destroy(struct row_range *range, enum row_range_type type)
{
switch (type) {
case ROW_RANGE_URI: grid_row_uri_range_destroy(range); break;
case ROW_RANGE_UNDERLINE: grid_row_underline_range_destroy(range); break;
}
}
static inline void
grid_row_ranges_destroy(struct row_ranges *ranges, enum row_range_type type)
{
for (int i = 0; i < ranges->count; i++) {
grid_row_range_destroy(&ranges->v[i], type);
}
}
static inline void
grid_row_reset_extra(struct row *row)
{
struct row_data *extra = row->extra;
if (likely(extra == NULL))
return;
grid_row_ranges_destroy(&extra->uri_ranges, ROW_RANGE_URI);
grid_row_ranges_destroy(&extra->underline_ranges, ROW_RANGE_UNDERLINE);
free(extra->uri_ranges.v);
free(extra->underline_ranges.v);
free(extra);
row->extra = NULL;
}