shithub: orca

Download patch

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);