diff options
author | Thiago de Arruda <tpadilha84@gmail.com> | 2015-08-26 09:07:04 -0300 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2015-09-06 09:18:52 -0300 |
commit | f5c5cdb306704e40019fb0eb9457e64bda8ee7cc (patch) | |
tree | 07bc347ee6f3af269710e42e3d40aa3c06190489 /src/nvim/ugrid.c | |
parent | cb9ae4e373af5d436499531698cec96ffc9bc39d (diff) | |
download | rneovim-f5c5cdb306704e40019fb0eb9457e64bda8ee7cc.tar.gz rneovim-f5c5cdb306704e40019fb0eb9457e64bda8ee7cc.tar.bz2 rneovim-f5c5cdb306704e40019fb0eb9457e64bda8ee7cc.zip |
tui: Move screen state tracking to new "ugrid" module
The ugrid module implements a unicode "drawing" grid and is used to store TUI
screen state. Later this module will be reused in other layers.
Diffstat (limited to 'src/nvim/ugrid.c')
-rw-r--r-- | src/nvim/ugrid.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/src/nvim/ugrid.c b/src/nvim/ugrid.c new file mode 100644 index 0000000000..127b18feb6 --- /dev/null +++ b/src/nvim/ugrid.c @@ -0,0 +1,137 @@ +#include <assert.h> +#include <stdbool.h> +#include <stdio.h> +#include <limits.h> + +#include "nvim/vim.h" +#include "nvim/ui.h" +#include "nvim/ugrid.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "ugrid.c.generated.h" +#endif + +void ugrid_init(UGrid *grid) +{ + grid->attrs = EMPTY_ATTRS; + grid->fg = grid->bg = -1; + grid->cells = NULL; +} + +void ugrid_free(UGrid *grid) +{ + destroy_cells(grid); +} + +void ugrid_resize(UGrid *grid, int width, int height) +{ + destroy_cells(grid); + grid->cells = xmalloc((size_t)height * sizeof(UCell *)); + for (int i = 0; i < height; i++) { + grid->cells[i] = xcalloc((size_t)width, sizeof(UCell)); + } + + grid->top = 0; + grid->bot = height - 1; + grid->left = 0; + grid->right = width - 1; + grid->row = grid->col = 0; + grid->width = width; + grid->height = height; +} + +void ugrid_clear(UGrid *grid) +{ + clear_region(grid, grid->top, grid->bot, grid->left, grid->right); +} + +void ugrid_eol_clear(UGrid *grid) +{ + clear_region(grid, grid->row, grid->row, grid->col, grid->right); +} + +void ugrid_goto(UGrid *grid, int row, int col) +{ + grid->row = row; + grid->col = col; +} + +void ugrid_set_scroll_region(UGrid *grid, int top, int bot, int left, int right) +{ + grid->top = top; + grid->bot = bot; + grid->left = left; + grid->right = right; +} + +void ugrid_scroll(UGrid *grid, int count, int *clear_top, int *clear_bot) +{ + // Compute start/stop/step for the loop below + int start, stop, step; + if (count > 0) { + start = grid->top; + stop = grid->bot - count + 1; + step = 1; + } else { + start = grid->bot; + stop = grid->top - count - 1; + step = -1; + } + + int i; + + // Copy cell data + for (i = start; i != stop; i += step) { + UCell *target_row = grid->cells[i] + grid->left; + UCell *source_row = grid->cells[i + count] + grid->left; + memcpy(target_row, source_row, + sizeof(UCell) * (size_t)(grid->right - grid->left + 1)); + } + + // clear cells in the emptied region, + if (count > 0) { + *clear_top = stop; + *clear_bot = stop + count - 1; + } else { + *clear_bot = stop; + *clear_top = stop + count + 1; + } + clear_region(grid, *clear_top, *clear_bot, grid->left, grid->right); +} + +UCell *ugrid_put(UGrid *grid, uint8_t *text, size_t size) +{ + UCell *cell = grid->cells[grid->row] + grid->col; + cell->data[size] = 0; + cell->attrs = grid->attrs; + + if (text) { + memcpy(cell->data, text, size); + } + + grid->col += 1; + return cell; +} + +static void clear_region(UGrid *grid, int top, int bot, int left, int right) +{ + HlAttrs clear_attrs = EMPTY_ATTRS; + clear_attrs.foreground = grid->fg; + clear_attrs.background = grid->bg; + UGRID_FOREACH_CELL(grid, top, bot, left, right, { + cell->data[0] = ' '; + cell->data[1] = 0; + cell->attrs = clear_attrs; + }); +} + +static void destroy_cells(UGrid *grid) +{ + if (grid->cells) { + for (int i = 0; i < grid->height; i++) { + xfree(grid->cells[i]); + } + xfree(grid->cells); + } +} + |