add position marks (Ma/g'a) - gramscii - A simple editor for ASCII box-and-arrow charts
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Tags
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit ce2bfb4d3a49a27bde7c8bbc6c6b1ef6f80054aa
 (DIR) parent 02c54fe6f289901f5b356ca98a81dec78fef4f36
 (HTM) Author: KatolaZ <katolaz@freaknet.org>
       Date:   Fri, 16 Aug 2019 23:43:24 +0100
       
       add position marks (Ma/g'a)
       
       Diffstat:
         M TODO                                |       2 ++
         M gramscii.1                          |      48 ++++++++++++++++++++++++-------
         M gramscii.c                          |       3 +++
         M gramscii.h                          |       9 +++++++++
         M screen.c                            |      37 ++++++++++++++++++++++++++++++-
       
       5 files changed, 88 insertions(+), 11 deletions(-)
       ---
 (DIR) diff --git a/TODO b/TODO
       @@ -1,6 +1,7 @@
        + optimize redraws (redraw only the modified rectangle)
        - add screen geometry option (-g 25x80?)
        - (?)maybe move "text" mode to "t"
       +- implement trapezium
        - implement ellipse
        - (?) filled box (B)
        - (?) manage filled box character (as for other styles)
       @@ -13,6 +14,7 @@
        - allow scrolling (both vertical and horizontal)
        - catch SIGWINCH and react appropriately (after scrolling is 
          enabled)
       +* add position marks (Ma / g'a)
        * implement comment (#: ignore everything until the end of the line)
        * implement parallelogram mode (z/Z)
        * fix bug in reading commands from files
 (DIR) diff --git a/gramscii.1 b/gramscii.1
       @@ -86,6 +86,17 @@ command).
        Load (edit) an existing file from disk, discarding any change to the
        current screen.
        .TP 5m
       +.BI M a
       +Mark (label) the current cursor position as 'a'. The label 'a' must be
       +one of the 26 ASCII alphabetic characters. The cursor can be moved to a
       +previously marked position using the global positioning command
       +.B g
       +(see below). Position marks are case-insensitive, meaning that both 
       +.I 'c'
       +and
       +.I 'C'
       +indicate the same mark.
       +.TP 5m
        .BI N
        Start a new empty screen. If the current screen has been modified since
        the last
       @@ -178,11 +189,13 @@ units at a time (defaults to 5, change LONG_STEP in config.h as you
        wish).
        .TP 5m
        .BI g
       -Initiate a global positioning command (go). These are two-letter
       -commands starting with a
       +Initiate a global positioning command (go). These are two- or
       +three-letter commands starting with a
        .BI g
       -and followed by a direction command or by a character that indicates a
       -global position, namely:
       +and followed by a direction command, or by a character that indicates a
       +global position, or by a valid position mark previously defined with 
       +.B M
       +and preceded by a single quote. In particular:
        .RS
        .TP 5m
        .BI h
       @@ -205,9 +218,24 @@ move the cursor to the bottom-right corner of the screen
        .TP 5m
        .BI m
        move the cursor to the middle of the screen.
       +.TP 5m
       +.BI 'a
       +(single-quote followed by a character) move the cursor to the position
       +previously marked (labelled) with character
       +.BI 'a'
       +by the command
       +.B M
       +(mark). The character 'a' must be one of the 26 ASCII alphabetic
       +characters. Notice that position marks are case-insensitive, so the two
       +commands:
       +.B g'b
       +and
       +.B g'B
       +move the cursor to the position mark associated to the letter 'b', if it
       +exists.
        .PP
       -For instance, if you want to move the cursor to the first row of the
       -current column, you would use the two-letter command 
       +If you want to move the cursor to the first row of the current
       +column, you could use the two-letter command 
        .B gk 
        (which can be read as "go-up"). Similarly, the command
        .B gh
       @@ -227,13 +255,13 @@ is equivalent to
        ).
        .PP
        Global positioning commands are available in 
       -.B box, arrow, visual,
       +.B box, arrow, visual, parallelogram, 
        and 
        .B erase
        mode. Notice that
       -.B gg, gG, 
       -and 
       -.B gm, 
       +.B gg, gG, gm 
       +and moves to position marks like
       +.B g'b, 
        are not available in 
        .B arrow
        mode.
 (DIR) diff --git a/gramscii.c b/gramscii.c
       @@ -142,6 +142,9 @@ void commands(FILE *fc){
                                                mode = REM;
                                                get_comment(fc);
                                                break;
       +                                case 'M':
       +                                        mark_pos(fc);
       +                                        break;
                                        case 'q':
                                                check_modified(fc);/** FALLTHROUGH **/
                                        case 'Q':
 (DIR) diff --git a/gramscii.h b/gramscii.h
       @@ -90,6 +90,11 @@ typedef struct{
                line_t *l;
        } lineset_t;
        
       +typedef struct{
       +        int x;
       +        int y;
       +} pos_t;
       +
        
        /** MACROS **/
        
       @@ -105,6 +110,9 @@ lineset_t screen; /* what is visualised */
        lineset_t cutbuf; /* cut/paste buffer */
        lineset_t *undo;  /* undo list */
        
       +pos_t marks[26]; /* position marks */
       +char mark_map[26]; /* marks map */
       +
        int undo_sz;/* allocated size of undo list*/
        int undo_cur;/* undo position */
        int undo_lst;/* last valid undo position */
       @@ -175,6 +183,7 @@ void crop_to_nonblank();
        void crop_to_rect();
        void erase_blank_lines(int y1, int y2);
        int _isblank(int c);
       +void mark_pos(FILE *fc);
        /**/
        
        /** drawing-related functions **/
 (DIR) diff --git a/screen.c b/screen.c
       @@ -301,6 +301,24 @@ void handle_goto(FILE *fc, char global){
                                        go_to(MIDDLE);
                                } else step = 0;
                                break;
       +                case '\'':
       +                        c = tolower(fgetc(fc));
       +                        if (global) {
       +                                dir = DIR_N;
       +                                if (isalpha(c) && mark_map[c - 'a']){
       +                                        x = marks[c - 'a'].x;
       +                                        y = marks[c - 'a'].y;
       +#ifdef DEBUG
       +                                        fprintf(stderr, "going to valid mark '%c' (%d, %d)\n", c, x, y);
       +#endif
       +                                }
       +#ifdef DEBUG
       +                                else 
       +                                        fprintf(stderr, "invalid mark '%c'\n", c);
       +#endif
       +                        } else step = 0;
       +                        break;
       +
                }
        
        #ifdef DEBUG
       @@ -435,20 +453,23 @@ void init_screen(){
                for (i=0; i<HEIGHT; i++){
                        alloc_line(&(screen.l[i]));
                }
       +        /* init markers */
                hlines_sz= sizeof(hlines) -1;
                vlines_sz= sizeof(vlines) -1;
                corners_sz = sizeof(corners) -1;
                stmarks_sz = sizeof(st_marks) - 1;
                endmarks_sz = sizeof(st_marks) - 1;
                reset_styles();
       +        /* init undo ring */        
                cutbuf.sz = 0;
                cutbuf.l = NULL;
                cutbuf.num = 0;
       -        
                undo = NULL;
                undo_sz = 0;
                undo_cur = -2;
                undo_lst = -2;
       +        /* init pos marks */
       +        memset(mark_map, 0, 26 * sizeof(char));
        }
        
        void find_nonblank_rect(int *x1, int *y1, int *x2, int *y2){
       @@ -507,4 +528,18 @@ void crop_to_nonblank(){
                redraw();
        }
        
       +/** position marks **/
        
       +void mark_pos(FILE *fc){
       +
       +        char c;
       +        c = tolower(fgetc(fc));
       +        if (isalpha(c)){
       +                marks[c - 'a'].x = x;
       +                marks[c - 'a'].y = y;
       +                mark_map[c - 'a'] = 1;
       +#ifdef DEBUG
       +                fprintf(stderr, "marking pos (%d, %d) as '%c'\n", x, y, c);
       +#endif
       +        }
       +}