summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKatolaZ <katolaz@freaknet.org>2019-07-31 00:10:35 +0100
committerKatolaZ <katolaz@freaknet.org>2019-07-31 00:10:35 +0100
commit526ce3a130732d4a2374a6e36a689d9e0cf5cc34 (patch)
tree9b6f76dbc70bf9a4d2becb9b9d8103eb57663aa0
parent6da2f3f89afda08eeba385da1c36414154113d47 (diff)
preliminary support for undo
-rw-r--r--TODO2
-rw-r--r--draw.c55
-rw-r--r--gramscii.h13
-rw-r--r--lineset.c43
-rw-r--r--main.c6
-rw-r--r--screen.c4
6 files changed, 117 insertions, 6 deletions
diff --git a/TODO b/TODO
index 71689fc..4b893ea 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,5 @@
+ optimize redraws (redraw only the modified rectangle)
++ undo (by storing lines changed across insert/remove operations)
- fix bug with 'g' commands in arrow mode
- add screen geometry option (-g 25x80?)
- read file at point
@@ -18,7 +19,6 @@
* yank
* fill
* cut
-- undo (by storing lines changed across insert/remove operations)
- manage special chars (DEL/CANC) during text insert
(also do not print unmanaged chars!)
- allow scrolling (both vertical and horizontal)
diff --git a/draw.c b/draw.c
index 3c98534..e3bdbce 100644
--- a/draw.c
+++ b/draw.c
@@ -1,4 +1,5 @@
#include <stdlib.h>
+#include <string.h>
#include "gramscii.h"
#include "config.h"
@@ -103,16 +104,19 @@ void draw_box(int x1, int y1, int fix){
int i;
void (*f)(int, int, char);
- if (fix == FIX)
- f = set_xy;
- else
- f = draw_xy;
xmin = MIN(x, x1);
xmax = MAX(x, x1);
ymin = MIN(y, y1);
ymax = MAX(y, y1);
+ if (fix == FIX){
+ f = set_xy;
+ copy_lines_to_ring(ymin, ymax, CUR);
+ }
+ else
+ f = draw_xy;
+
for(i=xmin+1; i<=xmax; i++){
f(i, ymin, line_h);
f(i, ymax, line_h);
@@ -125,6 +129,8 @@ void draw_box(int x1, int y1, int fix){
f(xmin, ymax, corner);
f(xmax, ymin, corner);
f(xmax, ymax, corner);
+ if (fix == FIX)
+ copy_lines_to_ring(ymin, ymax, LST);
show_cursor();
}
@@ -157,6 +163,7 @@ update_box:
void draw_arrow(int x, int y, char *a, int a_len, int fix){
+ /* FIXME: copy affected lines to undo */
int i, j, cur_dir;
char line;
void (*f)(int, int, char);
@@ -266,6 +273,7 @@ void do_erase(int x1, int y1){
void erase(FILE *fc){
+ /*FIXME: add affected lines to undo */
char c;
int orig_x = x, orig_y = y;
status_bar();
@@ -308,8 +316,11 @@ void visual_box(FILE *fc){
case 'x':/* erase */
if (c == 'x')
yank_region(MIN(orig_x,x), MIN(orig_y,y), MAX(orig_x, x), MAX(orig_y, y));
+ copy_lines_to_ring(MIN(orig_y, y), MAX(orig_y, y), CUR);
erase_box(orig_x, orig_y, f);
erase_blank_lines(MIN(y,orig_y), MAX(y, orig_y));
+ copy_lines_to_ring(MIN(orig_y, y), MAX(orig_y, y), LST);
+
modified = 1;
goto vis_exit;
break;
@@ -331,6 +342,42 @@ vis_exit:
}
void paste(){
+ int y2;
+
+ y2 = y + cutbuf.num - 1;
+ copy_lines_to_ring(y, y2, CUR);
paste_region(x, y);
+ copy_lines_to_ring(y, y2, LST);
+ redraw();
+}
+
+void put_lines(lineset_t *u){
+ int i, n;
+
+ for (i=0; i< u->num; i++){
+ n = u->l[i].n;
+ ensure_line_length(&(screen.l[i]), u->l[i].lst);
+ strcpy(screen.l[n].s, u->l[i].s);
+ screen.l[n].lst = u->l[i].lst;
+ }
+}
+
+
+void undo_change(){
+ if (undo_cur >= 0){
+ put_lines(& (undo[undo_cur]));
+ undo_cur --;
+ }
+ redraw();
+ modified = 1;
+}
+
+void redo_change(){
+ if (undo_cur < undo_lst){
+ undo_cur ++;
+ put_lines(& (undo[undo_cur]));
+ }
redraw();
+ modified = 1;
}
+
diff --git a/gramscii.h b/gramscii.h
index a08d211..73b9db7 100644
--- a/gramscii.h
+++ b/gramscii.h
@@ -44,6 +44,9 @@
#define VIDEO_NRM 0
#define VIDEO_REV 7
+#define CUR 0x01
+#define LST 0x02
+
/** types **/
typedef struct{
@@ -59,6 +62,7 @@ typedef struct{
line_t *l;
} lineset_t;
+
/** MACROS **/
#define MIN(x,y) (x) < (y) ? (x) : (y)
@@ -73,6 +77,11 @@ typedef struct{
lineset_t screen;
lineset_t cutbuf;
+lineset_t *undo;
+
+int undo_sz;
+int undo_cur;
+int undo_lst;
int WIDTH, HEIGHT;
@@ -155,6 +164,8 @@ void ensure_line_length(line_t *l, int len);
void ensure_num_lines(lineset_t *ls, int n);
void yank_region(int x1, int y1, int x2, int y2);
void paste_region(int x1, int y1);
-
+void copy_lines_to_ring(int y1, int y2, int which);
+void undo_change();
+void redo_change();
#endif
diff --git a/lineset.c b/lineset.c
index f672798..40fe3f0 100644
--- a/lineset.c
+++ b/lineset.c
@@ -58,6 +58,7 @@ void ensure_num_lines(lineset_t *ls, int n){
}
}
+
void dump_lines(lineset_t ls, FILE *f){
int i;
for (i=0; i<ls.num ;i++){
@@ -124,3 +125,45 @@ void paste_region(int x1, int y1){
}
redraw();
}
+
+void copy_lines_to_ring(int y1, int y2, int which){
+ lineset_t *tmp;
+ int i, len, *idx;
+
+ if (y1 > y2){
+ y1 ^= y2;
+ y2 ^= y1;
+ y1 ^= y2;
+ }
+ if (which == CUR)
+ idx = &undo_cur;
+ else
+ idx = &undo_lst;
+ if (*idx == undo_sz - 1){
+ undo_sz += 10;
+ tmp = realloc(undo, undo_sz * sizeof(lineset_t));
+ if (tmp == NULL){
+ fprintf(stderr, "Error allocating undo buffer");
+ exit(1);
+ }
+ undo = tmp;
+ }
+ (*idx) ++;
+ ensure_num_lines(&(undo[*idx]), y2 - y1 + 1);
+ for(i=y1; i<=y2; i++){
+ len = strlen(screen.l[i].s);
+ ensure_line_length(&(undo[*idx].l[i-y1]), len);
+ strcpy(undo[*idx].l[i-y1].s, screen.l[i].s);
+ undo[*idx].l[i-y1].n = i;
+ undo[*idx].l[i-y1].lst = screen.l[i].lst;
+ }
+ undo[*idx].num = y2 - y1 + 1;
+ if (which == CUR)
+ undo_lst = undo_cur;
+#ifdef DEBUG
+ fprintf(stderr, "undo_ring: y1: %d y2: %d idx: %d\n", y1, y2, *idx);
+ for(i=0; i<undo[undo_cur].num; i++){
+ fprintf(stderr, "UU: %d| %s\n", undo[*idx].l[i].n, undo[*idx].l[i].s);
+ }
+#endif
+}
diff --git a/main.c b/main.c
index d2d5a55..4118ecc 100644
--- a/main.c
+++ b/main.c
@@ -122,6 +122,12 @@ void commands(FILE *fc){
case 'p':
paste();
break;
+ case 'u':
+ undo_change();
+ break;
+ case 'U':
+ redo_change();
+ break;
case 'q':
check_modified(fc);/** FALLTHROUGH **/
case 'Q':
diff --git a/screen.c b/screen.c
index 3cbfe12..93dd459 100644
--- a/screen.c
+++ b/screen.c
@@ -408,6 +408,10 @@ void init_screen(){
cutbuf.sz = 0;
cutbuf.l = NULL;
cutbuf.num = 0;
+
+ undo_sz = 0;
+ undo_cur = -1;
+ undo_lst = -1;
}
void find_nonblank_rect(int *x1, int *y1, int *x2, int *y2){