From eebc645dee0d15871d6cc46f156d424cd916b191 Mon Sep 17 00:00:00 2001 From: KatolaZ Date: Tue, 30 Jul 2019 12:15:54 +0100 Subject: yank buffer and initial copy/cut/paste support --- Makefile | 2 +- TODO | 11 +++--- draw.c | 11 ++++++ files.c | 6 ++-- gramscii.1 | 20 +++++++++-- gramscii.h | 36 ++++++++++++++----- lineset.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.c | 11 +++--- screen.c | 117 ++++++++++++++++++++----------------------------------------- 9 files changed, 227 insertions(+), 104 deletions(-) create mode 100644 lineset.c diff --git a/Makefile b/Makefile index b88dbf5..dd32b20 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ include config.mk -SRC = main.c draw.c screen.c files.c +SRC = main.c draw.c screen.c files.c lineset.c INC = config.h gramscii.h all: options gramscii diff --git a/TODO b/TODO index c04d8f3..71689fc 100644 --- a/TODO +++ b/TODO @@ -6,8 +6,8 @@ - use [ENTER] to exit from text insert - maybe move "text" mode to "t" - implement ellipse -- filled box (B) -- manage fill character (as for other styles) +- (?) filled box (B) +- (?) manage filled box character (as for other styles) - implement comment (#: ignore until the end of the line) + parse control characters + parse arrows (text-mode will allow movements as well) @@ -15,15 +15,18 @@ - (?) remove extra blanks until EOL when saving to file + visual selection - crop-to - - yank/put + * yank * fill - * delete + * 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) - catch SIGWINCH and react appropriately (after scrolling is enabled) +* put yanked content (p) +* turn screen into a lineset +* change alloc/ensure functions to work on line_t* and lineset_t* * add crop command (C) * reorganise code * change screen management (i.e., dynamic array of lines) diff --git a/draw.c b/draw.c index 9724a1f..3c98534 100644 --- a/draw.c +++ b/draw.c @@ -299,9 +299,15 @@ void visual_box(FILE *fc){ draw_box(x,y,NOFIX); while((c=fgetc(fc))!=EOF && c != 27 && c!= 'v' && c != '\n'){ if (!move_around(c, fc)) switch(c){ + case 'y': /* yank (copy) */ + yank_region(MIN(orig_x,x), MIN(orig_y,y), MAX(orig_x, x), MAX(orig_y, y)); + goto vis_exit; + break; case 'f':/* fill */ f = get_key(fc, "fill char: "); /** FALLTHROUGH **/ case 'x':/* erase */ + if (c == 'x') + yank_region(MIN(orig_x,x), MIN(orig_y,y), MAX(orig_x, x), MAX(orig_y, y)); erase_box(orig_x, orig_y, f); erase_blank_lines(MIN(y,orig_y), MAX(y, orig_y)); modified = 1; @@ -323,3 +329,8 @@ vis_exit: redraw(); mode = MOVE; } + +void paste(){ + paste_region(x, y); + redraw(); +} diff --git a/files.c b/files.c index c007eac..245b29b 100644 --- a/files.c +++ b/files.c @@ -24,7 +24,7 @@ void write_file(FILE *fc){ return; } for (i=0; i #include -/** types **/ -typedef struct{ - int sz; - int lst; - char *s; -} line_t; /** constants **/ @@ -50,6 +44,20 @@ typedef struct{ #define VIDEO_NRM 0 #define VIDEO_REV 7 +/** types **/ + +typedef struct{ + int sz;/* allocated size*/ + int n;/* line number */ + int lst;/* last visible char (before the first \0) */ + char *s; +} line_t; + +typedef struct{ + int sz;/* allocated size */ + int num;/* number of lines stored */ + line_t *l; +} lineset_t; /** MACROS **/ @@ -63,8 +71,9 @@ typedef struct{ /** global variables **/ -line_t *screen; -int num_lines; +lineset_t screen; +lineset_t cutbuf; + int WIDTH, HEIGHT; int mode; @@ -96,6 +105,7 @@ char visual; char silent; char autoend; + struct termios t1, t2, t3; /** screen-related functions **/ @@ -129,6 +139,7 @@ void get_box(FILE *fc); void get_arrow(FILE *fc); void erase(FILE *fc); void visual_box(FILE *fc); +void paste(); /** file-related functions **/ void write_file(FILE *fc); @@ -136,5 +147,14 @@ void check_modified(FILE *fc); void load_file(FILE *fc); void new_file(FILE *fc); +/** line-related functions **/ + +void dump_lines(lineset_t ls, FILE *f); +void alloc_line(line_t *l); +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); + #endif diff --git a/lineset.c b/lineset.c new file mode 100644 index 0000000..faabb30 --- /dev/null +++ b/lineset.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include "gramscii.h" + +static int LONG_STEP; + +/* line_t and lineset_t management */ + +void ensure_line_length(line_t *l, int len){ + char *tmp; + + if (l->sz < len + 1){ + tmp = realloc(l->s, (len+1) * 2 * sizeof(char)); + if (!tmp){ + fprintf(stderr, "Unable to allocate string\n"); + exit(1); + } + l->s = tmp; + l->sz = (len + 1) * 2; + } +} + + +void alloc_line(line_t *l){ + char *tmp; + + l->sz = WIDTH+1; + tmp = malloc((l->sz) * sizeof(char)); + if (tmp == NULL){ + fprintf(stderr, "unable to allocate line\n"); + exit(1); + } + l->s = tmp; + memset(l->s, BG, l->sz); + l->lst = -1; + l->s[0]='\0'; +} + +void ensure_num_lines(lineset_t *ls, int n){ + line_t *tmp; + + if (n > ls->sz){ + if (ls->sz == 0) + ls->l=NULL; + tmp = realloc(ls->l, (n + LONG_STEP) * sizeof(line_t)); + if (tmp == NULL){ + fprintf(stderr, "Unable to allocate memory for more lines"); + exit(1); + } + else { + ls->l = tmp; + while ( ls->sz < n + LONG_STEP){ + alloc_line(&(ls->l[ls->sz])); + ls->sz ++; + } + } + } +} + +void dump_lines(lineset_t ls, FILE *f){ + int i; + for (i=0; i #include #include -#include #include #include +#include #include "gramscii.h" #include "config.h" @@ -62,7 +62,7 @@ void status_bar(){ else printf(" *%s*", fname ); #ifdef DEBUG - printf(" '%d' ", screen[y].s[x]); + printf(" '%d' ", screen.l[y].s[x]); #endif printf("\033[0m"); fflush(stdout); @@ -109,52 +109,6 @@ int is_yes(char c){ /*** Screen management ***/ -void ensure_line_length(int i, int len){ - char *tmp; - - if (screen[i].sz < len + 1){ - tmp = realloc(screen[i].s, (len+1) * 2 * sizeof(char)); - if (!tmp){ - fprintf(stderr, "Unable to allocate string\n"); - exit(1); - } - screen[i].s = tmp; - screen[i].sz = (len + 1) * 2; - } -} - - -void alloc_line(int i){ - char *tmp; - - screen[i].sz = WIDTH+1; - tmp = malloc((screen[i].sz) * sizeof(char)); - if (tmp == NULL){ - fprintf(stderr, "unable to allocate line %d\n", i+1); - exit(1); - } - screen[i].s = tmp; - memset(screen[i].s, BG, screen[i].sz); - screen[i].lst = -1; - screen[i].s[0]='\0'; -} - -void ensure_num_lines(int n){ - line_t *tmp; - - if (n > num_lines){ - tmp = realloc(screen, (n + LONG_STEP) * sizeof(line_t)); - if (tmp == NULL){ - fprintf(stderr, "Unable to allocate memory for more lines"); - exit(1); - } - else while ( num_lines < n + LONG_STEP){ - alloc_line(num_lines); - num_lines ++; - } - } -} - void show_cursor(){ if (silent) @@ -165,15 +119,15 @@ void show_cursor(){ void set_xy(int _x, int _y, char c){ - ensure_num_lines(_y + 1); - ensure_line_length(_y, _x + 1); - while (screen[_y].lst<_x){ - screen[_y].lst ++; - screen[_y].s[screen[_y].lst] = BG; + ensure_num_lines(&screen, _y + 1); + ensure_line_length(&(screen.l[_y]), _x + 1); + while (screen.l[_y].lst<_x){ + screen.l[_y].lst ++; + screen.l[_y].s[screen.l[_y].lst] = BG; } - screen[_y].s[_x] = c; - if (_x == screen[_y].lst) - screen[_y].s[_x+1] = '\0'; + screen.l[_y].s[_x] = c; + if (_x == screen.l[_y].lst) + screen.l[_y].s[_x+1] = '\0'; } void set_cur(char c){ @@ -193,7 +147,7 @@ void update_current(){ if (silent) return; printf("\033[%d'%df",y+1,x+1); - putchar(screen[y].s[x]); + putchar(screen.l[y].s[x]); fflush(stdout); } @@ -206,20 +160,20 @@ void erase_blank_lines(int y1, int y2){ } for (; y1 <= y2; y1++){ - j = screen[y1].lst; - while (j>=0 && isblank(screen[y1].s[j])) + j = screen.l[y1].lst; + while (j>=0 && isblank(screen.l[y1].s[j])) j--; if (j<0){ - screen[y1].lst = -1; - screen[y1].s[0] = '\0'; + screen.l[y1].lst = -1; + screen.l[y1].s[0] = '\0'; } } } void erase_line(int i){ - screen[i].lst = -1; - screen[i].s[0] = '\0'; + screen.l[i].lst = -1; + screen.l[i].s[0] = '\0'; } void erase_box(int x1, int y1, char c){ @@ -268,7 +222,7 @@ void redraw(){ return; printf("\033[2J\033[1;1H"); for (i=0;i *x2) *x2 = j; @@ -483,13 +441,13 @@ void crop_to_rect(int x1, int y1, int x2, int y2){ int i; for (i=0; i<= y2-y1; i ++){ - ensure_line_length(i, screen[i+y1].lst); - sprintf(screen[i].s, "%s", screen[i+y1].s + x1); - screen[i].lst = screen[i+y1].lst - x1; + ensure_line_length(&(screen.l[i]), screen.l[i+y1].lst); + sprintf(screen.l[i].s, "%s", screen.l[i+y1].s + x1); + screen.l[i].lst = screen.l[i+y1].lst - x1; } while (i<=y2){ - screen[i].lst = -1; - screen[i].s[0]= '\0'; + screen.l[i].lst = -1; + screen.l[i].s[0]= '\0'; i ++; } } @@ -505,3 +463,4 @@ void crop_to_nonblank(){ redraw(); } + -- cgit v1.2.3