From 8e3d23b921d9bbcb7c53017bacff8a3050a34b55 Mon Sep 17 00:00:00 2001 From: KatolaZ Date: Sat, 27 Jul 2019 06:57:12 +0100 Subject: reorganise code --- Makefile | 6 +- TODO | 6 +- arg.h | 37 +++ config.h | 14 +- draw.c | 324 +++++++++++++++++++ files.c | 73 +++++ gramscii.c | 1057 ------------------------------------------------------------ gramscii.h | 138 ++++++++ main.c | 175 ++++++++++ screen.c | 419 ++++++++++++++++++++++++ 10 files changed, 1183 insertions(+), 1066 deletions(-) create mode 100644 arg.h create mode 100644 draw.c create mode 100644 files.c delete mode 100644 gramscii.c create mode 100644 gramscii.h create mode 100644 main.c create mode 100644 screen.c diff --git a/Makefile b/Makefile index 55959ce..b88dbf5 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,8 @@ include config.mk -SRC = gramscii.c -INC = config.h +SRC = main.c draw.c screen.c files.c +INC = config.h gramscii.h all: options gramscii @@ -22,7 +22,7 @@ gramscii: ${SRC} ${INC} clean: @echo cleaning - @rm -f $(SRC:.c=) + @rm -f $(SRC:.c=) gramscii install: all @echo installing executable to ${DESTDIR}${BINDIR} diff --git a/TODO b/TODO index 222bad1..d521256 100644 --- a/TODO +++ b/TODO @@ -5,10 +5,13 @@ - 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) +- implement comment (#: ignore until the end of the line) + parse control characters + parse arrows (text-mode will allow movements as well) - (?) implement CTRL+G as abort (aside ESC) -- add crop command (c) +- add crop command (C) - (?) remove extra blanks until EOL when saving to file + visual selection - crop-to @@ -21,6 +24,7 @@ - allow scrolling (both vertical and horizontal) - catch SIGWINCH and react appropriately (after scrolling is enabled) +* reorganise code * change screen management (i.e., dynamic array of lines) * add action multiplier (e.g., "7h" moves left by 7 cols) * add scripting mode option ("-s"?) diff --git a/arg.h b/arg.h new file mode 100644 index 0000000..1b1fd63 --- /dev/null +++ b/arg.h @@ -0,0 +1,37 @@ +#ifndef ARG_H +#define ARG_H + +#define USED(x) ((void)(x)) + +extern char *argv0; + +#define ARGBEGIN for(argv0 = *argv, argv++, argc--;\ + argv[0] && argv[0][0] == '-'\ + && argv[0][1];\ + argc--, argv++) {\ + char _argc;\ + char **_argv;\ + if(argv[0][1] == '-' && argv[0][2] == '\0') {\ + argv++;\ + argc--;\ + break;\ + }\ + int i_;\ + for(i_ = 1, _argv = argv; argv[0][i_];\ + i_++) {\ + if(_argv != argv)\ + break;\ + _argc = argv[0][i_];\ + switch(_argc) + +#define ARGEND }\ + USED(_argc);\ + }\ + USED(argv);\ + USED(argc); + +#define EARGF(x) ((argv[1] == NULL)? ((x), abort(), (char *)0) :\ + (argc--, argv++, argv[0])) + +#endif + diff --git a/config.h b/config.h index a9e5ddc..fa2eb7a 100644 --- a/config.h +++ b/config.h @@ -1,18 +1,22 @@ /* This is part of `gramscii`` -- see COPYING for details */ +#ifndef __LOCAL_CONFIG_H__ +#define __LOCAL_CONFIG_H__ /* Config options */ /** MARKERS -- the first character is the default one **/ /* markers for horizontal lines */ -char hlines[] = {"-~=#*@._ "}; +static char hlines[] = {"-~=#*@._ "}; /* markers for vertical lines */ -char vlines[] = {"|H#*@:;i "}; +static char vlines[] = {"|H#*@:;i "}; /* markers for corners */ -char corners[] = {"+'H#*@.\"`"}; +static char corners[] = {"+'H#*@.\"`"}; /* markers for arrow start points */ -char st_marks[] = {"+o-|<>^v*"}; +static char st_marks[] = {"+o-|<>^v*"}; /* markers for arrow endpoints */ -char end_marks[] = {">+o-|<^v*"}; +static char end_marks[] = {">+o-|<^v*"}; /** LONG_STEP (movements through uppercase HJKL) **/ #define LONG_STEP 5 + +#endif diff --git a/draw.c b/draw.c new file mode 100644 index 0000000..9e20601 --- /dev/null +++ b/draw.c @@ -0,0 +1,324 @@ +#include + +#include "gramscii.h" +#include "config.h" + +/*** drawing-related functions ***/ + +/*** Lines and markers ***/ + +void toggle_hline(){ + + cur_hl = (cur_hl + 1) % hlines_sz; + line_h = hlines[cur_hl]; + +} + +void toggle_corner(){ + + cur_corn = (cur_corn + 1 ) % corners_sz; + corner = corners[cur_corn]; + +} + +void toggle_vline(){ + + cur_vl = (cur_vl + 1) % vlines_sz; + line_v = vlines[cur_vl]; + +} + +void toggle_st_mark(){ + + cur_start = (cur_start + 1 ) % stmarks_sz; + mark_st = st_marks[cur_start]; +} + +void toggle_end_mark(){ + + cur_end = (cur_end+ 1 ) % endmarks_sz; + mark_end = end_marks[cur_end]; +} + +int change_style(char c){ + switch(c){ + case '-': + toggle_hline(); + break; + case '|': + toggle_vline(); + break; + case '+': + toggle_corner(); + break; + case '<': + toggle_st_mark(); + break; + case '>': + toggle_end_mark(); + break; + case '.': + reset_styles(); + break; + default: + return 0; + } + return c; +} + + + + +/***** text, box, arrows *****/ + +void get_text(FILE *fc){ + char c; + int orig_x = x; + + redraw(); + while((c=fgetc(fc))!=EOF && c != 27){ + if(c=='\n'){ + set_cur(BG); + y += 1; + x = orig_x; + } + else { + set_cur(c); + update_current(); + modified = 1; + x += 1; + if (x >= WIDTH) + x = orig_x; + } + check_bound(); + status_bar(); + show_cursor(); + } + mode=MOVE; +} + +void draw_box(int x1, int y1, int fix){ + + int xmin, ymin, xmax, ymax; + 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); + + for(i=xmin+1; i<=xmax; i++){ + f(i, ymin, line_h); + f(i, ymax, line_h); + } + for(i=ymin+1; i<=ymax; i++){ + f(xmin, i, line_v); + f(xmax, i, line_v); + } + f(xmin, ymin, corner); + f(xmin, ymax, corner); + f(xmax, ymin, corner); + f(xmax, ymax, corner); + show_cursor(); +} + +void get_box(FILE *fc){ + char c; + int orig_x=x, orig_y=y; + redraw(); + step = 1; + draw_box(x,y,NOFIX); + while((c=fgetc(fc))!=EOF && c != 27 && c!= 'b' && c != '\n'){ + if (change_style(c)) + goto update_box; + if (!move_around(c, fc)) + continue; + check_bound(); + redraw(); + step = 1; +update_box: + draw_box(orig_x, orig_y, NOFIX); + status_bar(); + show_cursor(); + } + if (c == 'b' || c == '\n'){ + draw_box(orig_x, orig_y, FIX); + modified = 1; + } + redraw(); + mode = MOVE; +} + +void draw_arrow(int x, int y, char *a, int a_len, int fix){ + + int i, j, cur_dir; + char line; + void (*f)(int, int, char); + + + if (fix == FIX) + f = set_xy; + else + f = draw_xy; + + f(x,y,mark_st); + if (!a_len){ + show_cursor(); + return; + } + cur_dir=DIR_N; + for (i=0; i0) { + /* If we are switching between horizontal and vertical, put a "corner" */ + if (((cur_dir & DIR_HOR) && (a[i] & DIR_VER)) || + ((cur_dir & DIR_VER) && (a[i] & DIR_HOR))){ + f(x,y,corner); + show_cursor(); + } + } + for(j=0; j=x; i--) set_xy(i,y,BG); + break; + case DIR_U: + for(i=y1; i>=y; i--) set_xy(x,i,BG); + break; + case DIR_D: + for(i=y1; i<=y; i++) set_xy(x,i,BG); + break; + } +} + + +void erase(FILE *fc){ + char c; + int orig_x = x, orig_y = y; + status_bar(); + show_cursor(); + while((c=fgetc(fc))!=EOF && c!=27 && c!= 'x' && c != '\n'){ + if (!move_around(c, fc)) continue; + check_bound(); + do_erase(orig_x, orig_y); + step = 1; + modified = 1; + orig_x = x; + orig_y = y; + redraw(); + status_bar(); + show_cursor(); + } + mode = MOVE; +} + + +/*** Visual ***/ + + +void visual_box(FILE *fc){ + int orig_x =x, orig_y = y; + char c, f = BG; + + redraw(); + step = 1; + set_video(VIDEO_REV); + draw_box(x,y,NOFIX); + while((c=fgetc(fc))!=EOF && c != 27 && c!= 'v' && c != '\n'){ + if (!move_around(c, fc)) switch(c){ + case 'f':/* fill */ + f = get_key(fc, "fill char: "); /** FALLTHROUGH **/ + case 'x':/* erase */ + erase_box(orig_x, orig_y, f); + modified = 1; + goto vis_exit; + break; + } + check_bound(); + set_video(VIDEO_NRM); + redraw(); + step = 1; + f = BG; + set_video(VIDEO_REV); + draw_box(orig_x, orig_y, NOFIX); + status_bar(); + show_cursor(); + } +vis_exit: + set_video(VIDEO_NRM); + redraw(); + mode = MOVE; +} diff --git a/files.c b/files.c new file mode 100644 index 0000000..811a9bc --- /dev/null +++ b/files.c @@ -0,0 +1,73 @@ +#include +#include +#include "gramscii.h" + + +/*** File management ***/ + +void write_file(FILE *fc){ + FILE *fout; + int i; + + if (!fname[0] || force_new){ + get_string(fc, "Write to: ", fname, 255); + if ((fout=fopen(fname, "r"))!=NULL){ + if (!is_yes(get_key(fc,"File exists. Overwrite [y/n]?")) ){ + fclose(fout); + return; + } + fclose(fout); + } + } + if((fout=fopen(fname, "w"))==NULL){ + get_key(fc, "Error opening file."); + return; + } + for (i=0; i -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. Please see the attached file COPYING. -* Otherwise, please visit . -* -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" - -#include "arg.h" - -typedef struct{ - int sz; - int lst; - char *s; -} line_t; - - -#define MOVE 0x00 -#define BOX 0x01 -#define ARROW 0x02 -#define TEXT 0x04 -#define DEL 0x08 -#define VIS 0x10 - -#define DIR_N 0x00 -#define DIR_R 0x01 -#define DIR_U 0x02 -#define DIR_D 0x04 -#define DIR_L 0x08 - -#define DIR_HOR (DIR_R | DIR_L) -#define DIR_VER (DIR_D | DIR_U) - - -#define NOFIX 0x0 -#define FIX 0x1 - -#define BG ' ' -#define PTR '+' -#define UND '_' -#define ARR_L '<' -#define ARR_R '>' -#define ARR_U '^' -#define ARR_D 'v' - -#define HOME 0x01 -#define END 0x02 -#define MIDDLE 0x04 - -#define VIDEO_NRM 0 -#define VIDEO_REV 7 - -#define MIN(x,y) (x) < (y) ? (x) : (y) -#define MAX(x,y) (x) > (y) ? (x) : (y) - -#define DEBUG 1 - -line_t *screen; -int num_lines; -int WIDTH, HEIGHT; - -int state; -int dir; -int x; -int y; -int step; -int mult; -int force_new; -char cursor; -char corner; - -int hlines_sz= sizeof(hlines) -1; -int vlines_sz= sizeof(vlines) -1; -int corners_sz = sizeof(corners) -1; -int stmarks_sz = sizeof(st_marks) - 1; -int endmarks_sz = sizeof(st_marks) - 1; - -int cur_hl, cur_vl, cur_corn, cur_start, cur_end; -char line_h; -char line_v; -char mark_st; -char mark_end; - -char modified; -char fname[256]; - -char visual; -char silent; -char autoend; - -char *argv0; - -struct termios t1, t2, t3; - - -void dump_lines(){ - int i; - for (i=0; i'; - } - return '>'; -} - - -void status_bar(){ - - if (silent) - return; - printf("\033[%d;1f\033[7m", HEIGHT+1); - printf("%*s", WIDTH-1, ""); - printf("\033[%d;1f\033[7m", HEIGHT+1); - printf(" x:%3d y:%3d -- MODE:%4s HL:%c VL:%c CN:%c SP:%c EP:%c %10s", - x, y, state_str(), line_h, line_v, corner, mark_st, mark_end, ""); - if (!modified) - printf(" [%s]", fname ); - else - printf(" *%s*", fname ); -#ifdef DEBUG - printf(" '%d' ", screen[y].s[x]); -#endif - printf("\033[0m"); - fflush(stdout); -} - -char get_key(FILE *fc, char *msg){ - - if (silent) - return 0; - printf("\033[%d;1f\033[7m", HEIGHT+1); - printf("%*s", WIDTH, ""); - printf("\033[%d;1f\033[7m", HEIGHT+1); - printf("%s", msg); - fflush(stdout); - printf("\033[0m"); - fflush(stdout); - return fgetc(fc); -} - -void get_string(FILE *fc, char *msg, char *s, int sz){ - - if (!silent){ - printf("\033[%d;1f\033[7m", HEIGHT+1); - printf("%*s", WIDTH, ""); - printf("\033[%d;1f\033[7m", HEIGHT+1); - - /* We must activate echo now */ - t3 = t2; - t3.c_lflag |= (ECHO | ICANON); - tcsetattr(0, TCSANOW, &t3); - printf("%s", msg); - printf("\033[0m"); - } - fgets(s, sz, fc); - s[strlen(s)-1] = '\0'; - tcsetattr(0, TCSANOW, &t2); - if (!silent) - fflush(stdout); -} - -int is_yes(char c){ - return c=='y' ? 1 : c == 'Y'? 1 : 0; -} - -/*** Screen management ***/ - -void show_cursor(){ - if (silent) - return; - printf("\033[%d;%df", y+1, x+1); - fflush(stdout); -} - - -void set_xy(int _x, int _y, char c){ - line_t *tmp; - if (_y >= num_lines){ - tmp = realloc(screen, (_y + LONG_STEP)* sizeof(line_t)); - if (tmp == NULL){ - fprintf(stderr, "Unable to allocate memory for more lines"); - exit(1); - } - else while ( num_lines < _y + LONG_STEP){ - screen[num_lines].sz = WIDTH+1; - screen[num_lines].s = malloc((screen[num_lines].sz) * sizeof(char)); - if (screen[num_lines].s == NULL){ - perror("allocating screen[num_lines].s"); - exit(1); - } - memset(screen[num_lines].s, BG, screen[num_lines].sz); - screen[num_lines].lst = 0; - screen[num_lines].s[screen[num_lines].lst+1]='\0'; - num_lines ++; - } - } - if (screen[_y].sz < _x + 2){ - screen[_y].sz = (_x +2) * 2; - screen[_y].s = realloc(screen[_y].s, screen[_y].sz * sizeof(char)); - } - while (screen[_y].lst<_x){ - screen[_y].lst ++; - screen[_y].s[screen[_y].lst] = BG; - } - screen[_y].s[_x] = c; - if (_x == screen[_y].lst) - screen[_y].s[_x+1] = '\0'; -} - -void set_cur(char c){ - set_xy(x, y, c); -} - -void draw_xy(int x, int y, char c){ - /* FIXME: check if x and y are valid!!!! */ - if (silent) - return; - printf("\033[%d;%df",y+1,x+1); - putchar(c); - fflush(stdout); -} - -void update_current(){ - if (silent) - return; - printf("\033[%d'%df",y+1,x+1); - putchar(screen[y].s[x]); - fflush(stdout); -} - -void erase_line(char *s){ - while(*s){ - *s = BG; - s++; - } -} - -void erase_box(int x1, int y1, char c){ - int x_incr, y_incr, i; - - x_incr = x1 < x? +1: -1; - y_incr = y1 < y? +1: -1; - do{ - i = y1; - do{ - set_xy(x1, i, c); - } while(i != y && (1 | (i += y_incr))); - } while(x1 != x && (1 | (x1 += x_incr))); - -} - -void erase_screen(){ - int i; - for(i=0;i=WIDTH) x = WIDTH-1; - if (y<0) y=0; - else if (y>=HEIGHT) y = HEIGHT -1; -} - -void reset_styles(){ - - cur_corn = 0; - corner = corners[0]; - cur_hl = cur_vl = 0; - cur_start = cur_end = 0; - line_h = hlines[cur_hl]; - line_v = vlines[cur_vl]; - mark_st = st_marks[cur_start]; - mark_end = end_marks[cur_end]; -} - -void redraw(){ - int i; - - if (silent) - return; - printf("\033[2J\033[1;1H"); - for (i=0;i': - toggle_end_mark(); - break; - case '.': - reset_styles(); - break; - default: - return 0; - } - return c; -} - - - - -/***** text, box, arrows *****/ - -void get_text(FILE *fc){ - char c; - int orig_x = x; - - redraw(); - while((c=fgetc(fc))!=EOF && c != 27){ - if(c=='\n'){ - set_cur(BG); - y += 1; - x = orig_x; - } - else { - set_cur(c); - update_current(); - modified = 1; - x += 1; - if (x >= WIDTH) - x = orig_x; - } - check_bound(); - status_bar(); - show_cursor(); - } - state=MOVE; -} - -void draw_box(int x1, int y1, int fix){ - - int xmin, ymin, xmax, ymax; - 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); - - for(i=xmin+1; i<=xmax; i++){ - f(i, ymin, line_h); - f(i, ymax, line_h); - } - for(i=ymin+1; i<=ymax; i++){ - f(xmin, i, line_v); - f(xmax, i, line_v); - } - f(xmin, ymin, corner); - f(xmin, ymax, corner); - f(xmax, ymin, corner); - f(xmax, ymax, corner); - show_cursor(); -} - -void get_box(FILE *fc){ - char c; - int orig_x=x, orig_y=y; - redraw(); - step = 1; - draw_box(x,y,NOFIX); - while((c=fgetc(fc))!=EOF && c != 27 && c!= 'b' && c != '\n'){ - if (change_style(c)) - goto update_box; - if (!move_around(c, fc)) - continue; - check_bound(); - redraw(); - step = 1; -update_box: - draw_box(orig_x, orig_y, NOFIX); - status_bar(); - show_cursor(); - } - if (c == 'b' || c == '\n'){ - draw_box(orig_x, orig_y, FIX); - modified = 1; - } - redraw(); - state = MOVE; -} - -void draw_arrow(int x, int y, char *a, int a_len, int fix){ - - int i, j, cur_dir; - char line; - void (*f)(int, int, char); - - - if (fix == FIX) - f = set_xy; - else - f = draw_xy; - - f(x,y,mark_st); - if (!a_len){ - show_cursor(); - return; - } - cur_dir=DIR_N; - for (i=0; i0) { - /* If we are switching between horizontal and vertical, put a "corner" */ - if (((cur_dir & DIR_HOR) && (a[i] & DIR_VER)) || - ((cur_dir & DIR_VER) && (a[i] & DIR_HOR))){ - f(x,y,corner); - show_cursor(); - } - } - for(j=0; j=x; i--) set_xy(i,y,BG); - break; - case DIR_U: - for(i=y1; i>=y; i--) set_xy(x,i,BG); - break; - case DIR_D: - for(i=y1; i<=y; i++) set_xy(x,i,BG); - break; - } -} - - -void delete(FILE *fc){ - char c; - int orig_x = x, orig_y = y; - status_bar(); - show_cursor(); - while((c=fgetc(fc))!=EOF && c!=27 && c!= 'x' && c != '\n'){ - if (!move_around(c, fc)) continue; - check_bound(); - do_delete(orig_x, orig_y); - step = 1; - modified = 1; - orig_x = x; - orig_y = y; - redraw(); - status_bar(); - show_cursor(); - } - state = MOVE; -} - -/*** File management ***/ - -void write_file(FILE *fc){ - FILE *fout; - int i; - - if (!fname[0] || force_new){ - get_string(fc, "Write to: ", fname, 255); - if ((fout=fopen(fname, "r"))!=NULL){ - if (!is_yes(get_key(fc,"File exists. Overwrite [y/n]?")) ){ - fclose(fout); - return; - } - fclose(fout); - } - } - if((fout=fopen(fname, "w"))==NULL){ - get_key(fc, "Error opening file."); - return; - } - for (i=0; i +#include +#include + +/** types **/ + +typedef struct{ + int sz; + int lst; + char *s; +} line_t; + +/** constants **/ + +#define MOVE 0x00 +#define BOX 0x01 +#define ARROW 0x02 +#define TEXT 0x04 +#define DEL 0x08 +#define VIS 0x10 + +#define DIR_N 0x00 +#define DIR_R 0x01 +#define DIR_U 0x02 +#define DIR_D 0x04 +#define DIR_L 0x08 + +#define DIR_HOR (DIR_R | DIR_L) +#define DIR_VER (DIR_D | DIR_U) + + +#define NOFIX 0x0 +#define FIX 0x1 + +#define BG ' ' +#define PTR '+' +#define UND '_' +#define ARR_L '<' +#define ARR_R '>' +#define ARR_U '^' +#define ARR_D 'v' + +#define HOME 0x01 +#define END 0x02 +#define MIDDLE 0x04 + +#define VIDEO_NRM 0 +#define VIDEO_REV 7 + + +/** MACROS **/ + +#define MIN(x,y) (x) < (y) ? (x) : (y) +#define MAX(x,y) (x) > (y) ? (x) : (y) + +#define progr_x(d) ((d) == DIR_L ? -1 : (d) == DIR_R ? 1 : 0) +#define progr_y(d) ((d) == DIR_U ? -1 : (d) == DIR_D ? 1 : 0) + +/* #define DEBUG 1 */ + +/** global variables **/ + +line_t *screen; +int num_lines; +int WIDTH, HEIGHT; + +int mode; +int dir; +int x; +int y; +int step; +int mult; +int force_new; +char cursor; +char corner; + +int hlines_sz; +int vlines_sz; +int corners_sz; +int stmarks_sz; +int endmarks_sz; + +int cur_hl, cur_vl, cur_corn, cur_start, cur_end; +char line_h; +char line_v; +char mark_st; +char mark_end; + +char modified; +char fname[256]; + +char visual; +char silent; +char autoend; + +struct termios t1, t2, t3; + +/** screen-related functions **/ +void reset_styles(); +void redraw(); +int move_around(char c, FILE *fc); +void check_bound(); +void status_bar(); +void show_cursor(); +void set_cur(char c); +void update_current(); +void set_xy(int _x, int _y, char c); +void draw_xy(int x, int y, char c); +char get_mark(char dir); +void set_video(int v); +char get_key(FILE *fc, char *msg); +void get_string(FILE *fc, char *msg, char *s, int sz); +void erase_box(int x1, int y1, char c); +int is_yes(char c); +void init_screen(); +void erase_line(char *s); +void erase_screen(); +void go_to(int where); + +/** drawing-related functions **/ +int change_style(char c); +void get_text(FILE *fc); +void get_box(FILE *fc); +void get_arrow(FILE *fc); +void erase(FILE *fc); +void visual_box(FILE *fc); + +/** file-related functions **/ +void write_file(FILE *fc); +void check_modified(FILE *fc); +void load_file(FILE *fc); +void new_file(FILE *fc); + + +#endif diff --git a/main.c b/main.c new file mode 100644 index 0000000..c0f4b6b --- /dev/null +++ b/main.c @@ -0,0 +1,175 @@ +/* +* +* gramscii: a simple editor for ASCII box-and-arrow charts +* +* Copyright (c) 2019 Vincenzo "KatolaZ" Nicosia +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. Please see the attached file COPYING. +* Otherwise, please visit . +* +*/ + +#include +#include +#include + +#include "arg.h" +#include "gramscii.h" + + +char *argv0; + +void dump_lines(){ + int i; + for (i=0; i +#include +#include +#include +#include +#include + +#include "gramscii.h" +#include "config.h" + +/*** screen management functions ***/ + + +/*** Status bar ***/ + +char* mode_str(){ + switch(mode){ + case MOVE: + return "mov"; + case TEXT: + return "txt"; + case BOX: + return "box"; + case ARROW: + return "arr"; + case DEL: + return "del"; + case VIS: + return "vis"; + default: + return "ERR"; + } + return "ERR"; +} + +char get_mark(char dir){ + switch(dir){ + case DIR_U: + return '^'; + case DIR_D: + return 'v'; + case DIR_L: + return '<'; + case DIR_R: + return '>'; + } + return '>'; +} + + +void status_bar(){ + + if (silent) + return; + printf("\033[%d;1f\033[7m", HEIGHT+1); + printf("%*s", WIDTH-1, ""); + printf("\033[%d;1f\033[7m", HEIGHT+1); + printf(" x:%3d y:%3d -- MODE:%4s HL:%c VL:%c CN:%c SP:%c EP:%c %10s", + x, y, mode_str(), line_h, line_v, corner, mark_st, mark_end, ""); + if (!modified) + printf(" [%s]", fname ); + else + printf(" *%s*", fname ); +#ifdef DEBUG + printf(" '%d' ", screen[y].s[x]); +#endif + printf("\033[0m"); + fflush(stdout); +} + +char get_key(FILE *fc, char *msg){ + + if (silent) + return 0; + printf("\033[%d;1f\033[7m", HEIGHT+1); + printf("%*s", WIDTH, ""); + printf("\033[%d;1f\033[7m", HEIGHT+1); + printf("%s", msg); + fflush(stdout); + printf("\033[0m"); + fflush(stdout); + return fgetc(fc); +} + +void get_string(FILE *fc, char *msg, char *s, int sz){ + + if (!silent){ + printf("\033[%d;1f\033[7m", HEIGHT+1); + printf("%*s", WIDTH, ""); + printf("\033[%d;1f\033[7m", HEIGHT+1); + + /* We must activate echo now */ + t3 = t2; + t3.c_lflag |= (ECHO | ICANON); + tcsetattr(0, TCSANOW, &t3); + printf("%s", msg); + printf("\033[0m"); + } + fgets(s, sz, fc); + s[strlen(s)-1] = '\0'; + tcsetattr(0, TCSANOW, &t2); + if (!silent) + fflush(stdout); +} + +int is_yes(char c){ + return c=='y' ? 1 : c == 'Y'? 1 : 0; +} + +/*** Screen management ***/ + +void show_cursor(){ + if (silent) + return; + printf("\033[%d;%df", y+1, x+1); + fflush(stdout); +} + + +void set_xy(int _x, int _y, char c){ + line_t *tmp; + if (_y >= num_lines){ + tmp = realloc(screen, (_y + LONG_STEP)* sizeof(line_t)); + if (tmp == NULL){ + fprintf(stderr, "Unable to allocate memory for more lines"); + exit(1); + } + else while ( num_lines < _y + LONG_STEP){ + screen[num_lines].sz = WIDTH+1; + screen[num_lines].s = malloc((screen[num_lines].sz) * sizeof(char)); + if (screen[num_lines].s == NULL){ + perror("allocating screen[num_lines].s"); + exit(1); + } + memset(screen[num_lines].s, BG, screen[num_lines].sz); + screen[num_lines].lst = 0; + screen[num_lines].s[screen[num_lines].lst+1]='\0'; + num_lines ++; + } + } + if (screen[_y].sz < _x + 2){ + screen[_y].sz = (_x +2) * 2; + screen[_y].s = realloc(screen[_y].s, screen[_y].sz * sizeof(char)); + } + while (screen[_y].lst<_x){ + screen[_y].lst ++; + screen[_y].s[screen[_y].lst] = BG; + } + screen[_y].s[_x] = c; + if (_x == screen[_y].lst) + screen[_y].s[_x+1] = '\0'; +} + +void set_cur(char c){ + set_xy(x, y, c); +} + +void draw_xy(int x, int y, char c){ + /* FIXME: check if x and y are valid!!!! */ + if (silent) + return; + printf("\033[%d;%df",y+1,x+1); + putchar(c); + fflush(stdout); +} + +void update_current(){ + if (silent) + return; + printf("\033[%d'%df",y+1,x+1); + putchar(screen[y].s[x]); + fflush(stdout); +} + +void erase_line(char *s){ + while(*s){ + *s = BG; + s++; + } +} + +void erase_box(int x1, int y1, char c){ + int x_incr, y_incr, i; + + x_incr = x1 < x? +1: -1; + y_incr = y1 < y? +1: -1; + do{ + i = y1; + do{ + set_xy(x1, i, c); + } while(i != y && (1 | (i += y_incr))); + } while(x1 != x && (1 | (x1 += x_incr))); + +} + +void erase_screen(){ + int i; + for(i=0;i=WIDTH) x = WIDTH-1; + if (y<0) y=0; + else if (y>=HEIGHT) y = HEIGHT -1; +} + +void reset_styles(){ + + cur_corn = 0; + corner = corners[0]; + cur_hl = cur_vl = 0; + cur_start = cur_end = 0; + line_h = hlines[cur_hl]; + line_v = vlines[cur_vl]; + mark_st = st_marks[cur_start]; + mark_end = end_marks[cur_end]; +} + +void redraw(){ + int i; + + if (silent) + return; + printf("\033[2J\033[1;1H"); + for (i=0;i