From 3818cbd93ca7ff4a2dc33b40d408fc18e60c605e Mon Sep 17 00:00:00 2001 From: Matheus Afonso Martins Moreira Date: Sun, 7 Apr 2024 05:46:31 -0300 Subject: [PATCH] grid: define capacity expansion function Allocates a new array of rows of the desired capacity and copies all the grid's rows over to it. Assumes the new capacity is greater than the old capacity. In other words, can only be used to expand capacity, not shrink it. --- grid.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ grid.h | 4 ++++ 2 files changed, 63 insertions(+) diff --git a/grid.c b/grid.c index 85e6183f..91af22ce 100644 --- a/grid.c +++ b/grid.c @@ -13,8 +13,10 @@ #include "stride.h" #include "util.h" #include "xmalloc.h" +#include "misc.h" #define TIME_REFLOW 0 +#define TIME_EXPAND 0 /* * "sb" (scrollback relative) coordinates @@ -674,6 +676,63 @@ tp_cmp(const void *_a, const void *_b) return 0; } +void +grid_expand_capacity( + struct grid *grid, int minimum, int scrollback_lines) +{ +#if defined(TIME_EXPAND) && TIME_EXPAND + struct timespec start; + clock_gettime(CLOCK_MONOTONIC, &start); + + int old_row_capacity = grid->num_rows; +#endif + + const int new_row_capacity = 1 << (32 - __builtin_clz(grid->num_rows + minimum + scrollback_lines - 1)); + + LOG_INFO("grid: expanding capacity to %d", new_row_capacity); + + struct row **new_rows = xcalloc(new_row_capacity, sizeof(*new_rows)); + + /* Copy the old grid's rows to the new grid. + * The new capacity was zero filled by xcalloc. + * Geometry is the same but capacity is higher. + * So there is no need to reflow its contents. + * No need to check for overflow here either + * since a calloc has been called with these + * same parameters before and it would have + * failed had an integer overflow occurred. + */ + memcpy(new_rows, grid->rows, (grid->offset + 1) * sizeof(*grid->rows)); + + /* TODO: Figure out how to get rid of these allocations. + * Ensure the rows have been allocated before returning. + * The rows are supposed to be allocated on demand but + * too much code depends on them not being NULL, + * specifically the terminal scrolling code. + */ + for (int i = grid->offset + 1; i < new_row_capacity; i++) { + new_rows[i] = grid_row_alloc(grid->num_cols, true); + } + + free(grid->rows); + + grid->rows = new_rows; + grid->num_rows = new_row_capacity; + +#if defined(TIME_EXPAND) && TIME_EXPAND + struct timespec stop; + clock_gettime(CLOCK_MONOTONIC, &stop); + + struct timespec diff; + timespec_sub(&stop, &start, &diff); + + LOG_INFO("expanded grid capacity, %d -> %d rows in %lds %ldns", + old_row_capacity, new_row_capacity, + (long) diff.tv_sec, + diff.tv_nsec); +#endif +} + void grid_resize_and_reflow( struct grid *grid, int new_rows, int new_cols, diff --git a/grid.h b/grid.h index 8ea5200b..b165a3d4 100644 --- a/grid.h +++ b/grid.h @@ -11,6 +11,10 @@ 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_expand_capacity( + struct grid *grid, int minimum, + int scrollback_lines); + void grid_resize_without_reflow( struct grid *grid, int new_rows, int new_cols, int old_screen_rows, int new_screen_rows);