1 | // This is an open source non-commercial project. Dear PVS-Studio, please check |
2 | // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com |
3 | |
4 | #include <assert.h> |
5 | #include <stdbool.h> |
6 | #include <stdio.h> |
7 | #include <limits.h> |
8 | |
9 | #include "nvim/assert.h" |
10 | #include "nvim/vim.h" |
11 | #include "nvim/ui.h" |
12 | #include "nvim/ugrid.h" |
13 | |
14 | #ifdef INCLUDE_GENERATED_DECLARATIONS |
15 | # include "ugrid.c.generated.h" |
16 | #endif |
17 | |
18 | void ugrid_init(UGrid *grid) |
19 | { |
20 | grid->cells = NULL; |
21 | } |
22 | |
23 | void ugrid_free(UGrid *grid) |
24 | { |
25 | destroy_cells(grid); |
26 | } |
27 | |
28 | void ugrid_resize(UGrid *grid, int width, int height) |
29 | { |
30 | destroy_cells(grid); |
31 | grid->cells = xmalloc((size_t)height * sizeof(UCell *)); |
32 | for (int i = 0; i < height; i++) { |
33 | grid->cells[i] = xcalloc((size_t)width, sizeof(UCell)); |
34 | } |
35 | |
36 | grid->width = width; |
37 | grid->height = height; |
38 | } |
39 | |
40 | void ugrid_clear(UGrid *grid) |
41 | { |
42 | clear_region(grid, 0, grid->height-1, 0, grid->width-1, 0); |
43 | } |
44 | |
45 | void ugrid_clear_chunk(UGrid *grid, int row, int col, int endcol, sattr_T attr) |
46 | { |
47 | clear_region(grid, row, row, col, endcol-1, attr); |
48 | } |
49 | |
50 | void ugrid_goto(UGrid *grid, int row, int col) |
51 | { |
52 | grid->row = row; |
53 | grid->col = col; |
54 | } |
55 | |
56 | void ugrid_scroll(UGrid *grid, int top, int bot, int left, int right, int count) |
57 | { |
58 | // Compute start/stop/step for the loop below |
59 | int start, stop, step; |
60 | if (count > 0) { |
61 | start = top; |
62 | stop = bot - count + 1; |
63 | step = 1; |
64 | } else { |
65 | start = bot; |
66 | stop = top - count - 1; |
67 | step = -1; |
68 | } |
69 | |
70 | int i; |
71 | |
72 | // Copy cell data |
73 | for (i = start; i != stop; i += step) { |
74 | UCell *target_row = grid->cells[i] + left; |
75 | UCell *source_row = grid->cells[i + count] + left; |
76 | assert(right >= left && left >= 0); |
77 | memcpy(target_row, source_row, |
78 | sizeof(UCell) * ((size_t)right - (size_t)left + 1)); |
79 | } |
80 | } |
81 | |
82 | static void clear_region(UGrid *grid, int top, int bot, int left, int right, |
83 | sattr_T attr) |
84 | { |
85 | for (int row = top; row <= bot; row++) { |
86 | UGRID_FOREACH_CELL(grid, row, left, right+1, { |
87 | cell->data[0] = ' '; |
88 | cell->data[1] = 0; |
89 | cell->attr = attr; |
90 | }); |
91 | } |
92 | } |
93 | |
94 | static void destroy_cells(UGrid *grid) |
95 | { |
96 | if (grid->cells) { |
97 | for (int i = 0; i < grid->height; i++) { |
98 | xfree(grid->cells[i]); |
99 | } |
100 | XFREE_CLEAR(grid->cells); |
101 | } |
102 | } |
103 | |
104 | |