summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKatolaZ <katolaz@freaknet.org>2019-07-31 11:19:55 +0100
committerKatolaZ <katolaz@freaknet.org>2019-07-31 11:19:55 +0100
commitf3100ddd486d6f39b0c97c9c492bb6020bf3caf1 (patch)
tree729407153bc35d950ef5a46045f5d6a9c71bdcf2
parent526ce3a130732d4a2374a6e36a689d9e0cf5cc34 (diff)
add undo support for box, visual, cut/paste
-rw-r--r--TODO4
-rw-r--r--draw.c32
-rw-r--r--gramscii.124
-rw-r--r--gramscii.h4
-rw-r--r--lineset.c38
-rw-r--r--screen.c4
6 files changed, 69 insertions, 37 deletions
diff --git a/TODO b/TODO
index 4b893ea..2514376 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,9 @@
+ optimize redraws (redraw only the modified rectangle)
+ undo (by storing lines changed across insert/remove operations)
+ * re-organise undo-ring management
+ - add undo for arrow mode
+ - add undo for text mode
+ - add undo for erase mode
- fix bug with 'g' commands in arrow mode
- add screen geometry option (-g 25x80?)
- read file at point
diff --git a/draw.c b/draw.c
index e3bdbce..e4c3250 100644
--- a/draw.c
+++ b/draw.c
@@ -112,7 +112,7 @@ void draw_box(int x1, int y1, int fix){
if (fix == FIX){
f = set_xy;
- copy_lines_to_ring(ymin, ymax, CUR);
+ copy_lines_to_ring(ymin, ymax, PRV_STATE);
}
else
f = draw_xy;
@@ -130,7 +130,7 @@ void draw_box(int x1, int y1, int fix){
f(xmax, ymin, corner);
f(xmax, ymax, corner);
if (fix == FIX)
- copy_lines_to_ring(ymin, ymax, LST);
+ copy_lines_to_ring(ymin, ymax, NEW_STATE);
show_cursor();
}
@@ -316,10 +316,10 @@ 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);
+ copy_lines_to_ring(MIN(orig_y, y), MAX(orig_y, y), PRV_STATE);
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);
+ copy_lines_to_ring(MIN(orig_y, y), MAX(orig_y, y), NEW_STATE);
modified = 1;
goto vis_exit;
@@ -345,9 +345,9 @@ void paste(){
int y2;
y2 = y + cutbuf.num - 1;
- copy_lines_to_ring(y, y2, CUR);
+ copy_lines_to_ring(y, y2, PRV_STATE);
paste_region(x, y);
- copy_lines_to_ring(y, y2, LST);
+ copy_lines_to_ring(y, y2, NEW_STATE);
redraw();
}
@@ -356,28 +356,32 @@ void put_lines(lineset_t *u){
for (i=0; i< u->num; i++){
n = u->l[i].n;
- ensure_line_length(&(screen.l[i]), u->l[i].lst);
+ ensure_line_length(&(screen.l[i]), strlen(u->l[i].s));
strcpy(screen.l[n].s, u->l[i].s);
- screen.l[n].lst = u->l[i].lst;
+ screen.l[n].lst = strlen(u->l[i].s)-1;
}
}
void undo_change(){
if (undo_cur >= 0){
+ if (undo_cur > undo_lst)
+ undo_cur = undo_lst;
put_lines(& (undo[undo_cur]));
- undo_cur --;
+ undo_cur -= 2;
+ modified = 1;
}
redraw();
- modified = 1;
}
void redo_change(){
- if (undo_cur < undo_lst){
- undo_cur ++;
- put_lines(& (undo[undo_cur]));
+ if (undo_cur <= undo_lst-2){
+ if (undo_cur > 0)
+ put_lines(& (undo[undo_cur+1]));
+ undo_cur +=2;
+ put_lines(& (undo[undo_cur+1]));
+ modified = 1;
}
redraw();
- modified = 1;
}
diff --git a/gramscii.1 b/gramscii.1
index 95b2719..aa88386 100644
--- a/gramscii.1
+++ b/gramscii.1
@@ -63,6 +63,26 @@ buffer contains the rectangle yanked/cut in
.B visual
mode.
.TP 5m
+.BI u
+Undo the last change. gramscii supports an undo history of indefinite
+length. The command
+.BI u
+gets the last change from the history, and moves the history pointer
+back by one change. See the related command
+.BI U
+below.
+.TP 5m
+.BI U
+Redo, i.e., cancel a previous
+.BI u
+command. gramscii supports an undo history of indefinite length. The
+command
+.BI U
+moves to the following change, if possible. For instance, the sequence
+.BI uuU
+will go back two changes, and then forward one, effectively resetting
+the state of the screen to what it was before the last change occurred.
+.TP 5m
.BI q
Quit gramscii, and prompt for a filename if the current screen contains
unsaved changes.
@@ -516,8 +536,8 @@ support scrolling and "virtual" screens of any (reasonable) size.
.PP
gramscii currently does
.B not
-provide an "undo" command. This requires a restructuring of buffer
-management, and will most probably be implemented in a future release.
+support "undo" commands for arrow, text, and erase mode. This will be
+added soon.
.SH AUTHORS
gramscii is written and maintained by Vincenzo "KatolaZ" Nicosia
<katolaz@freaknet.org>. You can use, copy, modify, and redistribute
diff --git a/gramscii.h b/gramscii.h
index 73b9db7..cadde2d 100644
--- a/gramscii.h
+++ b/gramscii.h
@@ -44,8 +44,8 @@
#define VIDEO_NRM 0
#define VIDEO_REV 7
-#define CUR 0x01
-#define LST 0x02
+#define PRV_STATE 0x01
+#define NEW_STATE 0x02
/** types **/
diff --git a/lineset.c b/lineset.c
index 40fe3f0..75ae1d3 100644
--- a/lineset.c
+++ b/lineset.c
@@ -127,19 +127,24 @@ void paste_region(int x1, int y1){
}
void copy_lines_to_ring(int y1, int y2, int which){
- lineset_t *tmp;
- int i, len, *idx;
+ int i, len, idx;
+ int offset;
+ lineset_t *tmp;
if (y1 > y2){
y1 ^= y2;
y2 ^= y1;
y1 ^= y2;
}
- if (which == CUR)
- idx = &undo_cur;
+ if (undo_cur > undo_lst)
+ undo_cur = undo_lst;
+ if (which == PRV_STATE){ /* adding a new previous state */
+ undo_cur += 2;
+ idx = undo_cur;
+ }
else
- idx = &undo_lst;
- if (*idx == undo_sz - 1){
+ idx = undo_cur + 1;
+ if (idx >= undo_sz - 1){
undo_sz += 10;
tmp = realloc(undo, undo_sz * sizeof(lineset_t));
if (tmp == NULL){
@@ -148,22 +153,21 @@ void copy_lines_to_ring(int y1, int y2, int which){
}
undo = tmp;
}
- (*idx) ++;
- ensure_num_lines(&(undo[*idx]), y2 - y1 + 1);
+ 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;
+ 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[idx].num = y2 - y1 + 1;
+ if (which == PRV_STATE)
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);
+ fprintf(stderr, "undo_ring: y1: %d y2: %d idx: %d\n", y1, y2, idx);
+ for(i=0; i<undo[idx].num; i++){
+ fprintf(stderr, "UU: %d| %s\n", undo[idx].l[i].n, undo[idx].l[i].s);
}
#endif
}
diff --git a/screen.c b/screen.c
index 93dd459..b769641 100644
--- a/screen.c
+++ b/screen.c
@@ -410,8 +410,8 @@ void init_screen(){
cutbuf.num = 0;
undo_sz = 0;
- undo_cur = -1;
- undo_lst = -1;
+ undo_cur = -2;
+ undo_lst = -2;
}
void find_nonblank_rect(int *x1, int *y1, int *x2, int *y2){