ref: e0fe4647c1884d294d0f4a5d63b4905032475a9d
parent: 4905ef58af57b9fec259db4870f1183571cc3343
author: cancel <cancel@cancel.fm>
date: Mon Dec 3 10:57:20 EST 2018
Add partial support for resizing grids (WIP)
--- a/field.c
+++ b/field.c
@@ -17,6 +17,8 @@
f->width = (U16)width;
}
+void field_deinit(Field* f) { free(f->buffer); }
+
void field_resize_raw(Field* f, Usz height, Usz width) {
assert(height <= ORCA_Y_MAX && width <= ORCA_X_MAX);
Usz cells = height * width;
@@ -31,13 +33,27 @@
}
}
-void field_deinit(Field* f) { free(f->buffer); }
-
void field_copy(Field* src, Field* dest) {
field_resize_raw_if_necessary(dest, src->height, src->width);
gbuffer_copy_subrect(src->buffer, dest->buffer, src->height, src->width,
dest->height, dest->width, 0, 0, 0, 0, src->height,
src->width);
+}
+
+void field_resize_filled(Field* field, Usz height, Usz width, Glyph fill_char) {
+ assert(height <= ORCA_Y_MAX && width <= ORCA_X_MAX);
+ Usz old_height = field->height;
+ Usz old_width = field->width;
+ if (old_height == height && old_width == width)
+ return;
+ Usz old_cells = old_height * old_width;
+ Usz new_cells = height * width;
+ field->buffer = realloc(field->buffer, new_cells * sizeof(Glyph));
+ if (old_cells < new_cells) {
+ memset(field->buffer + old_cells, fill_char, (new_cells - old_cells) * sizeof(Glyph));
+ }
+ field->height = (U16)height;
+ field->width = (U16)width;
}
static inline bool glyph_char_is_valid(char c) { return c >= '!' && c <= '~'; }
--- a/field.h
+++ b/field.h
@@ -3,9 +3,10 @@
void field_init(Field* field);
void field_init_fill(Field* field, Usz height, Usz width, Glyph fill_char);
+void field_deinit(Field* field);
void field_resize_raw(Field* field, Usz height, Usz width);
void field_resize_raw_if_necessary(Field* field, Usz height, Usz width);
-void field_deinit(Field* field);
+void field_resize_filled(Field* field, Usz height, Usz width, Glyph fill_char);
void field_copy(Field* src, Field* dest);
void field_fput(Field* field, FILE* stream);
--- a/gbuffer.c
+++ b/gbuffer.c
@@ -26,16 +26,16 @@
Usz copy_bytes = row_copy * sizeof(Glyph);
Glyph* src_p = src + src_y * src_width + src_x;
Glyph* dest_p = dest + dest_y * dest_width + dest_x;
- Usz src_stride;
- Usz dest_stride;
+ Isz src_stride;
+ Isz dest_stride;
if (src_y >= dest_y) {
- src_stride = src_width;
- dest_stride = dest_width;
+ src_stride = (Isz)src_width;
+ dest_stride = (Isz)dest_width;
} else {
src_p += (ny - 1) * src_width;
dest_p += (ny - 1) * dest_width;
- src_stride = -src_width;
- dest_stride = -dest_width;
+ src_stride = -(Isz)src_width;
+ dest_stride = -(Isz)dest_width;
}
Usz iy = 0;
for (;;) {
--- a/tui_main.c
+++ b/tui_main.c
@@ -296,13 +296,21 @@
(void)term_w;
if (field_w > Bufcount)
return;
+ if (pos_y >= term_h || pos_x >= term_w)
+ return;
+ Usz num_y = (Usz)term_h - (Usz)pos_y;
+ Usz num_x = (Usz)term_w - (Usz)pos_x;
+ if (field_h < num_y)
+ num_y = field_h;
+ if (field_w < num_x)
+ num_x = field_w;
chtype buffer[Bufcount];
bool use_rulers = ruler_spacing_y != 0 && ruler_spacing_x != 0;
- for (Usz y = 0; y < field_h; ++y) {
+ for (Usz y = 0; y < num_y; ++y) {
Glyph const* gline = gbuffer + y * field_w;
Mark const* mline = mbuffer + y * field_w;
bool use_y_ruler = use_rulers && y % ruler_spacing_y == 0;
- for (Usz x = 0; x < field_w; ++x) {
+ for (Usz x = 0; x < num_x; ++x) {
Glyph g = gline[x];
Mark m = mline[x];
if (g == '.') {
@@ -312,10 +320,43 @@
buffer[x] = chtype_of_cell(g, m);
}
wmove(win, pos_y + (int)y, pos_x);
- waddchnstr(win, buffer, (int)field_w);
+ waddchnstr(win, buffer, (int)num_x);
+ // Trying to clear to eol with 0 chars remaining on line will clear whole
+ // line from start
+ if (pos_x + (int)num_x != term_w) {
+ wmove(win, pos_y + (int)y, pos_x + (int)num_x);
+ wclrtoeol(win);
+ }
}
}
+void tui_cursor_confine(Tui_cursor* tc, Usz height, Usz width) {
+ if (height == 0 || width == 0)
+ return;
+ if (tc->y >= height)
+ tc->y = height - 1;
+ if (tc->x >= width)
+ tc->x = width - 1;
+}
+
+void tui_resize_grid(Field* field, Markmap_reusable* markmap,
+ Field* scratch_field, Isz delta_h, Isz delta_w,
+ Tui_cursor* tui_cursor, bool* needs_remarking) {
+ Isz new_height = (Isz)field->height + delta_h;
+ Isz new_width = (Isz)field->width + delta_w;
+ if (new_height < 1 || new_width < 1)
+ return;
+ field_copy(field, scratch_field);
+ field_resize_filled(field, (Usz)new_height, (Usz)new_width, '.');
+ gbuffer_copy_subrect(scratch_field->buffer, field->buffer,
+ scratch_field->height, scratch_field->width,
+ field->height, field->width, 0, 0, 0, 0,
+ scratch_field->height, scratch_field->width);
+ tui_cursor_confine(tui_cursor, (Usz)new_height, (Usz)new_width);
+ markmap_reusable_ensure_size(markmap, (Usz)new_height, (Usz)new_width);
+ *needs_remarking = true;
+}
+
int main(int argc, char** argv) {
static struct option tui_options[] = {{"help", no_argument, 0, 'h'},
{NULL, 0, NULL, 0}};
@@ -526,6 +567,22 @@
case '}':
if (ruler_spacing_y < 16)
++ruler_spacing_y;
+ break;
+ case '(':
+ tui_resize_grid(&field, &markmap_r, &scratch_field, 0, -1, &tui_cursor,
+ &needs_remarking);
+ break;
+ case ')':
+ tui_resize_grid(&field, &markmap_r, &scratch_field, 0, 1, &tui_cursor,
+ &needs_remarking);
+ break;
+ case '_':
+ tui_resize_grid(&field, &markmap_r, &scratch_field, -1, 0, &tui_cursor,
+ &needs_remarking);
+ break;
+ case '+':
+ tui_resize_grid(&field, &markmap_r, &scratch_field, 1, 0, &tui_cursor,
+ &needs_remarking);
break;
case ' ':
undo_history_push(&undo_hist, &field, tick_num);