Introduction
Introduction Statistics Contact Development Disclaimer Help
preliminary support for undo - gramscii - A simple editor for ASCII box-and-arr…
Log
Files
Refs
Tags
README
LICENSE
---
commit 526ce3a130732d4a2374a6e36a689d9e0cf5cc34
parent 6da2f3f89afda08eeba385da1c36414154113d47
Author: KatolaZ <[email protected]>
Date: Wed, 31 Jul 2019 00:10:35 +0100
preliminary support for undo
Diffstat:
M TODO | 2 +-
M draw.c | 55 ++++++++++++++++++++++++++++-…
M gramscii.h | 13 ++++++++++++-
M lineset.c | 43 ++++++++++++++++++++++++++++++
M main.c | 6 ++++++
M screen.c | 4 ++++
6 files changed, 117 insertions(+), 6 deletions(-)
---
diff --git 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
@@ -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,…
+ copy_lines_to_ring(MIN(orig_y, y), MAX(orig_y,…
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,…
+
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
@@ -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
@@ -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].…
+ }
+#endif
+}
diff --git 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
@@ -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){
You are viewing proxied material from bitreich.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.