diff options
| -rw-r--r-- | TODO | 2 | ||||
| -rw-r--r-- | draw.c | 55 | ||||
| -rw-r--r-- | gramscii.h | 13 | ||||
| -rw-r--r-- | lineset.c | 43 | ||||
| -rw-r--r-- | main.c | 6 | ||||
| -rw-r--r-- | screen.c | 4 | 
6 files changed, 117 insertions, 6 deletions
| @@ -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) @@ -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;  } + @@ -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 @@ -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	 +} @@ -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': @@ -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){ | 
