tvi: find cursor position after insertion in vi_input() - neatvi - [fork] simple vi-type editor with UTF-8 support
 (HTM) git clone git://src.adamsgaard.dk/neatvi
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) commit 674db133b8d6995f54c4cb682d7193dbda7ca62a
 (DIR) parent 7344f210fcb3b51fa46f90f0ace3bbe126cb47b8
 (HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
       Date:   Tue, 12 May 2015 22:45:59 +0430
       
       vi: find cursor position after insertion in vi_input()
       
       Diffstat:
         M led.c                               |      36 +++++++++++--------------------
         M ren.c                               |       9 ---------
         M uc.c                                |      14 --------------
         M vi.c                                |      51 ++++++++++++++++++++++++++++---
         M vi.h                                |       4 +---
       
       5 files changed, 60 insertions(+), 54 deletions(-)
       ---
 (DIR) diff --git a/led.c b/led.c
       t@@ -90,30 +90,26 @@ static int led_lastword(char *s)
                return r - s;
        }
        
       -/* the position of the cursor for inserting another character */
       -static int led_insertionpos(struct sbuf *sb)
       -{
       -        int len = sbuf_len(sb);
       -        char *chr = keymap(led_kmap, 'a');
       -        int col;
       -        sbuf_str(sb, chr);
       -        col = ren_cursor(sbuf_buf(sb),
       -                ren_pos(sbuf_buf(sb), uc_slen(sbuf_buf(sb)) - 1));
       -        sbuf_cut(sb, len);
       -        return col;
       -}
       -
        static void led_printparts(char *pref, char *main, char *post)
        {
                struct sbuf *ln;
       -        int col;
       +        int off, pos;
                ln = sbuf_make();
                sbuf_str(ln, pref);
                sbuf_str(ln, main);
       -        col = led_insertionpos(ln);
       +        off = uc_slen(sbuf_buf(ln));
                sbuf_str(ln, post);
       +        /* cursor position for inserting the next character */
       +        if (post[0]) {
       +                pos = ren_cursor(sbuf_buf(ln), ren_pos(sbuf_buf(ln), off));
       +        } else {
       +                int len = sbuf_len(ln);
       +                sbuf_str(ln, keymap(led_kmap, 'a'));
       +                pos = ren_pos(sbuf_buf(ln), off);
       +                sbuf_cut(ln, len);
       +        }
                led_print(sbuf_buf(ln), -1);
       -        term_pos(-1, led_pos(sbuf_buf(ln), col));
       +        term_pos(-1, led_pos(sbuf_buf(ln), ren_cursor(sbuf_buf(ln), pos)));
                sbuf_free(ln);
        }
        
       t@@ -177,19 +173,15 @@ char *led_prompt(char *pref, char *post)
        }
        
        /* read visual command input */
       -char *led_input(char *pref, char *post, int *row, int *col)
       +char *led_input(char *pref, char *post)
        {
                struct sbuf *sb = sbuf_make();
                int key;
       -        *row = 0;
                while (1) {
                        char *ln = led_line(pref, post, &key, &led_kmap);
       -                if (pref)
       -                        sbuf_str(sb, pref);
                        sbuf_str(sb, ln);
                        if (key == '\n')
                                sbuf_chr(sb, '\n');
       -                *col = ren_last(pref ? sbuf_buf(sb) : ln);
                        led_printparts(pref ? pref : "", ln, key == '\n' ? "" : post);
                        if (key == '\n')
                                term_chr('\n');
       t@@ -198,9 +190,7 @@ char *led_input(char *pref, char *post, int *row, int *col)
                        free(ln);
                        if (key != '\n')
                                break;
       -                (*row)++;
                }
       -        sbuf_str(sb, post);
                if (key == TERMESC)
                        return sbuf_done(sb);
                sbuf_free(sb);
 (DIR) diff --git a/ren.c b/ren.c
       t@@ -55,15 +55,6 @@ char *ren_translate(char *s)
                return sbuf_done(sb);
        }
        
       -int ren_last(char *s)
       -{
       -        int n = uc_slen(s);
       -        int *pos = ren_position(s);
       -        int ret = n ? pos[n - 1] : 0;
       -        free(pos);
       -        return ret;
       -}
       -
        /* find the next character after visual position p; if cur start from p itself */
        static int pos_next(int *pos, int n, int p, int cur)
        {
 (DIR) diff --git a/uc.c b/uc.c
       t@@ -285,20 +285,6 @@ static int uc_comb(int c)
                        c == 0x0670;                                /* superscript alef */
        }
        
       -/* the direction of the given utf-8 character */
       -int uc_dir(char *s)
       -{
       -        int u, c = (unsigned char) s[0];
       -        if (c < 128 && (ispunct(c) || isspace(c)))
       -                return 0;
       -        if (c < 128 && isalnum(c))
       -                return 1;
       -        u = uc_code(s);
       -        if (UC_R2L(u))
       -                return -1;
       -        return 1;
       -}
       -
        static void uc_cput(char *d, int c)
        {
                int l = 0;
 (DIR) diff --git a/vi.c b/vi.c
       t@@ -398,7 +398,12 @@ static int vi_insertionoffset(char *s, int c1, int before)
                                return l2 < l1 ? l1 + 1 : l1;
                }
                ren_region(s, c1, c2, &l1, &l2, 0);
       -        return l1 < l2 ? l2 : l1;
       +        c1 = ren_pos(s, l1);
       +        c2 = ren_pos(s, l2);
       +        if (c1 < c2)
       +                return l1 < l2 ? l2 : l1;
       +        else
       +                return l1 < l2 ? l1 : l2;
        }
        
        static void vi_commandregion(int *r1, int *r2, int *c1, int *c2, int *l1, int *l2, int closed)
       t@@ -454,6 +459,42 @@ static void vi_delete(int r1, int c1, int r2, int c2, int lnmode, int closed)
                free(post);
        }
        
       +static int lastline(char *str)
       +{
       +        char *s = str;
       +        char *r = s;
       +        while (s && s[0]) {
       +                r = s;
       +                s = strchr(s == str ? s : s + 1, '\n');
       +        }
       +        return r - str;
       +}
       +
       +static int linecount(char *s)
       +{
       +        int n;
       +        for (n = 0; s; n++)
       +                if ((s = strchr(s, '\n')))
       +                        s++;
       +        return n;
       +}
       +
       +static char *vi_input(char *pref, char *post, int *row, int *col)
       +{
       +        char *rep = led_input(pref, post);
       +        struct sbuf *sb = sbuf_make();
       +        int last, off;
       +        sbuf_str(sb, pref);
       +        sbuf_str(sb, rep);
       +        last = lastline(sbuf_buf(sb));
       +        off = uc_slen(sbuf_buf(sb) + last);
       +        sbuf_str(sb, post);
       +        *row = linecount(sbuf_buf(sb)) - 1;
       +        *col = ren_pos(sbuf_buf(sb) + last, MAX(0, off - 1));
       +        free(rep);
       +        return sbuf_done(sb);
       +}
       +
        static void vi_change(int r1, int c1, int r2, int c2, int lnmode, int closed)
        {
                char *region;
       t@@ -467,11 +508,11 @@ static void vi_change(int r1, int c1, int r2, int c2, int lnmode, int closed)
                free(region);
                pref = lnmode ? uc_dup("") : uc_sub(lbuf_get(xb, r1), 0, l1);
                post = lnmode ? uc_dup("\n") : uc_sub(lbuf_get(xb, r2), l2, -1);
       -        rep = led_input(pref, post, &row, &col);
       +        rep = vi_input(pref, post, &row, &col);
                if (rep) {
                        lbuf_rm(xb, r1, r2 + 1);
                        lbuf_put(xb, r1, rep);
       -                xrow = r1 + row;
       +                xrow = r1 + row - 1;
                        xcol = col;
                        free(rep);
                }
       t@@ -529,14 +570,14 @@ static void vc_insert(int cmd)
                        off = ln ? vi_insertionoffset(ln, xcol, 0) : 0;
                pref = ln ? uc_sub(ln, 0, off) : uc_dup("");
                post = ln ? uc_sub(ln, off, -1) : uc_dup("\n");
       -        rep = led_input(pref, post, &row, &col);
       +        rep = vi_input(pref, post, &row, &col);
                if ((cmd == 'o' || cmd == 'O') && !lbuf_len(xb))
                        lbuf_put(xb, 0, "\n");
                if (rep) {
                        if (cmd != 'o' && cmd != 'O')
                                lbuf_rm(xb, xrow, xrow + 1);
                        lbuf_put(xb, xrow, rep);
       -                xrow += row;
       +                xrow += row - 1;
                        xcol = col;
                        free(rep);
                }
 (DIR) diff --git a/vi.h b/vi.h
       t@@ -49,7 +49,6 @@ int ren_next(char *s, int p, int dir);
        int ren_eol(char *s, int dir);
        int ren_pos(char *s, int off);
        int ren_off(char *s, int pos);
       -int ren_last(char *s);
        int ren_wid(char *s);
        int ren_region(char *s, int c1, int c2, int *l1, int *l2, int closed);
        
       t@@ -66,7 +65,6 @@ void reg_done(void);
        
        /* utf-8 helper functions */
        int uc_len(char *s);
       -int uc_dir(char *s);
        int uc_wid(char *s);
        int uc_slen(char *s);
        int uc_code(char *s);
       t@@ -106,7 +104,7 @@ void term_commit(void);
        
        /* line-oriented input and output */
        char *led_prompt(char *pref, char *post);
       -char *led_input(char *pref, char *post, int *row, int *col);
       +char *led_input(char *pref, char *post);
        void led_print(char *msg, int row);
        char *led_keymap(int c);
        int led_pos(char *s, int pos);