tren: insertion offset for bidirectional text - 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 587184fefe29e50689e767573d9af112e2824ddd
 (DIR) parent 1ed75144175e7ea9b167a76c9b096b4c144ddfad
 (HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
       Date:   Tue,  5 May 2015 22:39:51 +0430
       
       ren: insertion offset for bidirectional text
       
       See the comments of ren_insertionoffset().
       
       Diffstat:
         M ren.c                               |      40 +++++++++++++++++++++++++++----
         M vi.c                                |      23 +++--------------------
       
       2 files changed, 38 insertions(+), 25 deletions(-)
       ---
 (DIR) diff --git a/ren.c b/ren.c
       t@@ -262,9 +262,39 @@ int ren_cmp(char *s, int pos1, int pos2)
         */
        int ren_insertionoffset(char *s, int pos, int pre)
        {
       -        int l1;
       -        if (!s)
       -                return 0;
       -        l1 = ren_off(s, pos);
       -        return pre ? l1 : l1 + 1;
       +        int *ord;                /* ord[i]: the order of the i-th char on the screen */
       +        int *map;                /* map[i]: the char appearing i-th on the screen */
       +        int n = uc_slen(s);
       +        int oprev, o, onext;        /* the offset the of previous, current, and next positions */
       +        int cord;                /* the order of the current position on the screen */
       +        int i;
       +        ord = malloc(n * sizeof(ord[0]));
       +        for (i = 0; i < n; i++)
       +                ord[i] = i;
       +        ren_reorder(s, ord);
       +        map = malloc(n * sizeof(map[0]));
       +        for (i = 0; i < n; i++)
       +                map[ord[i]] = i;
       +        if (uc_chr(s, n - 1)[0] == '\n')
       +                n--;
       +        o = ren_off(s, pos);
       +        cord = ord[o];
       +        oprev = cord > 0 ? map[cord - 1] : -1;
       +        onext = cord < n - 1 ? map[cord + 1] : -1;
       +        free(map);
       +        free(ord);
       +        if (oprev < 0 && onext < 0)
       +                return pre ? o : o + 1;
       +        if (pre) {
       +                if (oprev >= 0)
       +                        return oprev < o ? o : o + 1;
       +                else
       +                        return onext > o ? o : o + 1;
       +        } else {
       +                if (onext >= 0)
       +                        return onext > o ? o + 1 : o;
       +                else
       +                        return oprev < o ? o + 1 : o;
       +        }
       +        return 0;
        }
 (DIR) diff --git a/vi.c b/vi.c
       t@@ -110,28 +110,11 @@ static char *lbuf_chr(struct lbuf *lb, int r, int c)
                return "";
        }
        
       -static int lbuf_indents(struct lbuf *lb, int r)
       -{
       -        char *ln = lbuf_get(lb, r);
       -        int n;
       -        char **chrs;
       -        int i = 0;
       -        if (!ln)
       -                return 0;
       -        chrs = uc_chop(ln ? ln : "", &n);
       -        while (i < n && chrs[i][0] != '\n' && uc_isspace(chrs[i]))
       -                i++;
       -        free(chrs);
       -        return i;
       -}
       -
        static void lbuf_postindents(struct lbuf *lb, int *r, int *c)
        {
       -        char *ln = lbuf_get(lb, *r);
       -        if (ln)
       -                *c = ren_pos(ln, lbuf_indents(lb, *r));
       -        else
       -                lbuf_eol(lb, r, c, -1);
       +        lbuf_eol(lb, r, c, -1);
       +        while (uc_isspace(lbuf_chr(lb, *r, *c)))
       +                lbuf_lnnext(lb, r, c, +1);
        }
        
        static void lbuf_findchar(struct lbuf *lb, int *row, int *col, char *cs, int dir, int n)