reorganise code and new file - gramscii - A simple editor for ASCII box-and-arrow charts
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Tags
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 2f5d0a4be8c029c5a4d1279be8823604db2c0fc2
 (DIR) parent a4c6053e9df10cc4060696d6c29e84fa3105ad0e
 (HTM) Author: KatolaZ <katolaz@freaknet.org>
       Date:   Sat, 20 Jul 2019 10:39:38 +0100
       
       reorganise code and new file
       
       Diffstat:
         M TODO                                |       2 +-
         M gramscii.c                          |     461 +++++++++++++++++--------------
       
       2 files changed, 249 insertions(+), 214 deletions(-)
       ---
 (DIR) diff --git a/TODO b/TODO
       @@ -1,7 +1,6 @@
        + optimize redraws (i.e., avoid to redraw if possible)
        - (?) change cursor shape according to action
        - auto-arrow 'A' (automatic end-char)
       -- load from file
        - read file at point
        - visual selection
          - crop
       @@ -13,6 +12,7 @@
          (also do not print unmanaged chars!)
        - get screen geometry
        - allow scrolling (both vertical and horizontal)
       +* load from file
        * check if modified on exit
        * write to new file / default file
        * delete -- 'x' 
 (DIR) diff --git a/gramscii.c b/gramscii.c
       @@ -89,6 +89,70 @@ void cleanup(int s){
                exit(0);
        }
        
       +/*** Status bar ***/
       +
       +char* state_str(){
       +        switch(state){
       +                case MOVE:
       +                        return "mov";
       +                case TEXT:
       +                        return "txt";
       +                case BOX:
       +                        return "box";
       +                case ARROW:
       +                        return "arr";
       +                case DEL:
       +                        return "del";
       +                default:
       +                        return "ERR";
       +        }
       +        return "ERR";        
       +}
       +
       +
       +void status_bar(){
       +        
       +        printf("\033[%d;1f\033[7m", HEIGHT+1);
       +        printf("%100s", " ");
       +        printf("\033[%d;1f\033[7m", HEIGHT+1);
       +        printf(" x: %3d y: %3d -- mode: %4s hl: %c vl: %c cn: %c <: %c >: %c %10s", 
       +                x, y, state_str(), line_h, line_v, corner, mark_st, mark_end, "");
       +        printf(" [%s]", fname );
       +        printf("\033[0m");
       +}
       +
       +char get_key(char *s){
       +
       +        printf("\033[%d;1f\033[7m", HEIGHT+1);
       +        printf("%100s", " ");
       +        printf("\033[%d;1f\033[7m", HEIGHT+1);
       +        printf("%s ", s);
       +        printf("\033[0m");
       +        return getchar();
       +}
       +
       +void get_string(char *msg, char *s, int sz){
       +
       +        printf("\033[%d;1f\033[7m", HEIGHT+1);
       +        printf("%100s", " ");
       +        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, stdin);
       +        s[strlen(s)-1] = '\0';
       +        tcsetattr(0, TCSANOW, &t2);
       +}
       +
       +int is_yes(char c){
       +        return c=='y' ? 1 : c == 'Y'? 1 : 0;
       +}
       +
       +/*** Screen management ***/
       +
        void show_cursor(){
                printf("\033[%d;%df", y+1, x+1);
        }
       @@ -108,6 +172,31 @@ void draw_xy(int x, int y, char c){
                putchar(c);        
        }
        
       +void update_current(){
       +        printf("\033[%d'%df",y+1,x+1);
       +        putchar(screen[y][x]);
       +}
       +
       +void erase_line(char *s){
       +        while(*s){
       +                *s++ = BG;
       +        }
       +}
       +
       +void erase_screen(){
       +        int i;
       +        for(i=0;i<HEIGHT; i++)
       +                erase_line(screen[i]);
       +}
       +
       +
       +void check_bound(){
       +        if (x<0) x=0;
       +        else if (x>=WIDTH) x = WIDTH-1;
       +        if (y<0) y=0;
       +        else if (y>=HEIGHT) y = HEIGHT -1; 
       +}
       +
        void init_screen(){
                int i;
                for(i=0; i<HEIGHT; i++){
       @@ -124,36 +213,6 @@ void init_screen(){
                mark_end = end_marks[cur_end];
        }
        
       -char* state_str(){
       -        switch(state){
       -                case MOVE:
       -                        return "mov";
       -                case TEXT:
       -                        return "txt";
       -                case BOX:
       -                        return "box";
       -                case ARROW:
       -                        return "arr";
       -                case DEL:
       -                        return "del";
       -                default:
       -                        return "ERR";
       -        }
       -        return "ERR";        
       -}
       -
       -
       -void status_bar(){
       -        
       -        printf("\033[%d;1f\033[7m", HEIGHT+1);
       -        printf("%100s", " ");
       -        printf("\033[%d;1f\033[7m", HEIGHT+1);
       -        printf(" x: %3d y: %3d -- mode: %4s hl: %c vl: %c cn: %c <: %c >: %c %10s", 
       -                x, y, state_str(), line_h, line_v, corner, mark_st, mark_end, "");
       -        printf(" [%s]", fname );
       -        printf("\033[0m");
       -}
       -
        void redraw(){
                int i;
                
       @@ -165,12 +224,99 @@ void redraw(){
                show_cursor();
        }
        
       -void update_current(){
       -        printf("\033[%d'%df",y+1,x+1);
       -        putchar(screen[y][x]);
       +int move_around(char c){
       +
       +        switch(c){
       +                case 'H': step = 5;
       +                case 'h': 
       +                        dir = DIR_L;
       +                        x -= step;
       +                        break;        
       +                case 'J': step = 5;
       +                case 'j':
       +                        dir = DIR_D;
       +                        y += step;
       +                        break;
       +                case 'K': step = 5;
       +                case 'k':
       +                        dir = DIR_U;
       +                        y -= step;
       +                        break;
       +                case 'L': step = 5;
       +                case 'l':
       +                        dir = DIR_R;
       +                        x += step;
       +                        break;
       +                default:
       +                        return 0;
       +        }
       +        return 1;
       +}
       +
       +void go_to(int where){
       +        switch(where){
       +                case HOME:
       +                        x = y = 0;
       +                        break;
       +                case END:
       +                        x = WIDTH-1;
       +                        y = HEIGHT-1;
       +                        break;
       +                case MIDDLE:
       +                        x = WIDTH/2;
       +                        y = HEIGHT/2;
       +                        break;
       +        }
       +        check_bound();
       +        show_cursor();
       +}
       +
       +int progr_x(int dir){
       +        return dir == DIR_L ? -1 : dir == DIR_R ? 1: 0;
        }
        
        
       +int progr_y(int dir){
       +        return dir == DIR_U ? -1 : dir == DIR_D ? 1: 0;
       +}
       +
       +/*** 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];
       +}
       +
       +
       +
        void init(){
        
                signal(SIGHUP, cleanup);
       @@ -191,13 +337,6 @@ void init(){
                redraw();
        }
        
       -void check_bound(){
       -        if (x<0) x=0;
       -        else if (x>=WIDTH) x = WIDTH-1;
       -        if (y<0) y=0;
       -        else if (y>=HEIGHT) y = HEIGHT -1; 
       -}
       -
        
        /*****  text, box, arrows  *****/
        
       @@ -215,6 +354,7 @@ void get_text(){
                        else {
                                set(c);
                                update_current();
       +                        modified = 1;
                                x += 1;
                                if (x >= WIDTH)
                                        x = orig_x;
       @@ -259,35 +399,6 @@ void draw_box(int x1, int y1, int fix){
        }
        
        
       -int move_around(char c){
       -
       -        switch(c){
       -                case 'H': step = 5;
       -                case 'h': 
       -                        dir = DIR_L;
       -                        x -= step;
       -                        break;        
       -                case 'J': step = 5;
       -                case 'j':
       -                        dir = DIR_D;
       -                        y += step;
       -                        break;
       -                case 'K': step = 5;
       -                case 'k':
       -                        dir = DIR_U;
       -                        y -= step;
       -                        break;
       -                case 'L': step = 5;
       -                case 'l':
       -                        dir = DIR_R;
       -                        x += step;
       -                        break;
       -                default:
       -                        return 1;
       -        }
       -        return 0;
       -}
       -
        
        void get_box(){
                char c;
       @@ -296,7 +407,7 @@ void get_box(){
                step = 1;
                draw_box(x,y,NOFIX);
                while((c=getchar())!=EOF && c != 27 && c!= 'b'){
       -                if (move_around(c)) continue;
       +                if (!move_around(c)) continue;
                        check_bound();
                        redraw();
                        step = 1;
       @@ -312,17 +423,6 @@ void get_box(){
                state = MOVE;
        }
        
       -
       -int progr_x(int dir){
       -        return dir == DIR_L ? -1 : dir == DIR_R ? 1: 0;
       -}
       -
       -
       -int progr_y(int dir){
       -        return dir == DIR_U ? -1 : dir == DIR_D ? 1: 0;
       -}
       -
       -
        void draw_arrow(int x, int y, char *a, int a_len, int fix){
        
                int i, j, cur_dir;
       @@ -381,7 +481,7 @@ void get_arrow(){
                step = 1;
                draw_arrow(x,y, arrow, 0, NOFIX);
                while((c=getchar())!=EOF && c != 27 && c!= 'a'){
       -                if (move_around(c)) continue;
       +                if (!move_around(c)) continue;
                        check_bound();
                        /* FIXME: if we are out of bound, do nothing? */
                        if (arrow_len == arrow_sz){
       @@ -404,112 +504,6 @@ void get_arrow(){
                state = MOVE;
        }
        
       -char get_key(char *s){
       -
       -        printf("\033[%d;1f\033[7m", HEIGHT+1);
       -        printf("%100s", " ");
       -        printf("\033[%d;1f\033[7m", HEIGHT+1);
       -        printf("%s ", s);
       -        printf("\033[0m");
       -        return getchar();
       -}
       -
       -void get_string(char *s, int sz){
       -
       -        printf("\033[%d;1f\033[7m", HEIGHT+1);
       -        printf("%100s", " ");
       -        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("Write to: ");
       -        printf("\033[0m");
       -        fgets(s, sz, stdin);
       -        s[strlen(s)-1] = '\0';
       -        tcsetattr(0, TCSANOW, &t2);
       -}
       -
       -int is_yes(char c){
       -        return c=='y' ? 1 : c == 'Y'? 1 : 0;
       -}
       -
       -void write_file(){
       -        FILE *f;
       -        int i;
       -        
       -        if (!fname[0] || force_new){
       -                get_string(fname, 255);
       -                if (f=fopen(fname, "r")){
       -                        if (!is_yes(get_key("File exists. Overwrite [y/n]?")) ){
       -                                fclose(f);
       -                                return;
       -                        }
       -                        fclose(f);
       -                }
       -        }
       -        if((f=fopen(fname, "w"))==NULL){
       -                get_key("Error opening file.");
       -                return;
       -        }
       -        for (i=0; i<HEIGHT; i++){
       -                fprintf(f, "%s\n", screen[i]);
       -        }
       -        fclose(f);
       -        modified = 0;
       -        get_key("File saved.");
       -}
       -
       -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];
       -}
       -
       -void go_to(int where){
       -        switch(where){
       -                case HOME:
       -                        x = y = 0;
       -                        break;
       -                case END:
       -                        x = WIDTH-1;
       -                        y = HEIGHT-1;
       -                        break;
       -                case MIDDLE:
       -                        x = WIDTH/2;
       -                        y = HEIGHT/2;
       -                        break;
       -        }
       -        check_bound();
       -        show_cursor();
       -}
        
        void do_delete(int x1, int y1){
                int i;
       @@ -536,7 +530,7 @@ void delete(){
                status_bar();
                show_cursor();
                while((c=getchar())!=EOF && c!=27 && c!= 'x'){
       -                if (move_around(c)) continue;
       +                if (!move_around(c)) continue;
                        check_bound();
                        step = 1;
                        do_delete(orig_x, orig_y);
       @@ -550,6 +544,34 @@ void delete(){
                state = MOVE;
        }
        
       +/*** File management ***/
       +
       +void write_file(){
       +        FILE *f;
       +        int i;
       +        
       +        if (!fname[0] || force_new){
       +                get_string("Write to: ", fname, 255);
       +                if (f=fopen(fname, "r")){
       +                        if (!is_yes(get_key("File exists. Overwrite [y/n]?")) ){
       +                                fclose(f);
       +                                return;
       +                        }
       +                        fclose(f);
       +                }
       +        }
       +        if((f=fopen(fname, "w"))==NULL){
       +                get_key("Error opening file.");
       +                return;
       +        }
       +        for (i=0; i<HEIGHT; i++){
       +                fprintf(f, "%s\n", screen[i]);
       +        }
       +        fclose(f);
       +        modified = 0;
       +        get_key("File saved.");
       +}
       +
        void check_modified(){
        
                if (modified){
       @@ -560,34 +582,41 @@ void check_modified(){
                }
        }
        
       +void load_file(){
       +
       +        char newfname[256];
       +        FILE *f;
       +        int i;
       +
       +        get_string("Load file: ", newfname, 255);
       +        if ((f=fopen(newfname, "r")) != NULL){
       +                i = 0;
       +                while((fgets(screen[i], WIDTH+2, f)) != NULL && i<HEIGHT)
       +                        screen[i++][WIDTH-1]='\0';
       +                for(;i<HEIGHT; i++){
       +                        erase_line(screen[i]);
       +                }
       +                fclose(f);
       +        }
       +        strcpy(fname, newfname);
       +        modified=0;
       +        redraw();
       +}
        
       +void new_file(){
       +        check_modified();
       +        erase_screen();
       +        go_to(MIDDLE);
       +        redraw();
       +        fname[0] = '\0';
       +        modified=0;
       +}
        
        void commands(){
        
                char c;
                while((c=getchar())!=EOF){
       -                //screen[y][x]=BG;
       -                switch(c){
       -                        case 'H':
       -                                step=5;
       -                        case 'h':
       -                                x-=step;
       -                                break;
       -                        case 'J':
       -                                step=5;
       -                        case 'j':
       -                                y+=step;
       -                                break;
       -                        case 'K':
       -                                step=5;
       -                        case 'k':
       -                                y-=step;
       -                                break;
       -                        case 'L':
       -                                step=5;
       -                        case 'l':
       -                                x+=step;
       -                                break;
       +                if (!move_around(c)) switch(c){
                                case 'i':
                                        state = TEXT;
                                        get_text();
       @@ -608,6 +637,14 @@ void commands(){
                                case 'w':
                                        write_file();
                                        break;
       +                        case 'e':
       +                                check_modified();
       +                        case 'E':
       +                                load_file();
       +                                break;
       +                        case 'N':
       +                                new_file();
       +                                break;
                                case 'g':
                                        go_to(HOME);
                                        break;
       @@ -642,8 +679,6 @@ void commands(){
                                        cleanup(0);
                                        exit(0);
                                        break;
       -                        default:;
       -                                //statu("got: %d\n", c);
                        }
                        check_bound();
                        status_bar();