tvi: horizontal scrolling for long lines - 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 2cf2cba137d3316342f56e7e035c74e214b1cbb2
 (DIR) parent e7975f55419e9eea1dc579bcf0aa7e53b0db479b
 (HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
       Date:   Tue,  1 Sep 2015 11:47:22 +0430
       
       vi: horizontal scrolling for long lines
       
       Diffstat:
         M ex.c                                |       1 +
         M led.c                               |      52 ++++++++++++++++---------------
         M vi.c                                |      10 +++++++++-
         M vi.h                                |       1 +
       
       4 files changed, 38 insertions(+), 26 deletions(-)
       ---
 (DIR) diff --git a/ex.c b/ex.c
       t@@ -8,6 +8,7 @@
        #include "vi.h"
        
        int xrow, xoff, xtop;                /* current row, column, and top row */
       +int xleft;                        /* the first visible column */
        int xquit;                        /* exit if set */
        int xvis;                        /* visual mode */
        int xai = 1;                        /* autoindent option */
 (DIR) diff --git a/led.c b/led.c
       t@@ -25,15 +25,15 @@ static char *kmap_map(char *kmap, int c)
                return keymap[c] ? keymap[c] : cs;
        }
        
       -/* map cursor horizontal position to terminal column number */
       -int led_pos(char *s, int pos)
       +static int led_posctx(int dir, int pos)
        {
       -        return dir_context(s) >= 0 ? pos : xcols - pos - 1;
       +        return dir >= 0 ? pos - xleft : xcols - (pos - xleft) - 1;
        }
        
       -static int led_posctx(int dir, int pos)
       +/* map cursor horizontal position to terminal column number */
       +int led_pos(char *s, int pos)
        {
       -        return dir >= 0 ? pos : xcols - pos - 1;
       +        return led_posctx(dir_context(s), pos);
        }
        
        static int led_offdir(char **chrs, int *pos, int i)
       t@@ -63,9 +63,9 @@ static void led_markrev(int n, char **chrs, int *pos, int *att)
                }
        }
        
       -static char *led_render(char *s0)
       +static char *led_render(char *s0, int cbeg, int cend)
        {
       -        int n, maxcol = 0;
       +        int n;
                int *pos;        /* pos[i]: the screen position of the i-th character */
                int *off;        /* off[i]: the character at screen position i */
                int *att;        /* att[i]: the attributes of i-th character */
       t@@ -76,25 +76,23 @@ static char *led_render(char *s0)
                int ctx = dir_context(s0);
                chrs = uc_chop(s0, &n);
                pos = ren_position(s0);
       -        off = malloc(xcols * sizeof(off[0]));
       -        memset(off, 0xff, xcols * sizeof(off[0]));
       +        off = malloc((cend - cbeg) * sizeof(off[0]));
       +        memset(off, 0xff, (cend - cbeg) * sizeof(off[0]));
                for (i = 0; i < n; i++) {
       -                int curpos = pos[i];
       -                int curwid = ren_cwid(chrs[i], curpos);
       -                if (curpos >= 0 && curpos + curwid < xcols) {
       -                        for (j = 0; j < curwid; j++) {
       -                                off[led_posctx(ctx, curpos + j)] = i;
       -                                if (led_posctx(ctx, curpos + j) > maxcol)
       -                                        maxcol = led_posctx(ctx, curpos + j);
       -                        }
       -                }
       +                int curwid = ren_cwid(chrs[i], pos[i]);
       +                int curbeg = led_posctx(ctx, pos[i]);
       +                int curend = led_posctx(ctx, pos[i] + curwid - 1);
       +                if (curbeg >= 0 && curbeg < (cend - cbeg) &&
       +                                curend >= 0 && curend < (cend - cbeg))
       +                        for (j = 0; j < curwid; j++)
       +                                off[led_posctx(ctx, pos[i] + j)] = i;
                }
                att = syn_highlight(ex_filetype(), s0);
                led_markrev(n, chrs, pos, att);
                out = sbuf_make();
       -        i = 0;
       -        while (i <= maxcol) {
       -                int o = off[i];
       +        i = cbeg;
       +        while (i < cend) {
       +                int o = off[i - cbeg];
                        int att_new = o >= 0 ? att[o] : 0;
                        sbuf_str(out, term_att(att_new, att_old));
                        att_old = att_new;
       t@@ -104,9 +102,9 @@ static char *led_render(char *s0)
                                else if (uc_isprint(chrs[o]))
                                        sbuf_mem(out, chrs[o], uc_len(chrs[o]));
                                else
       -                                for (j = i; j <= maxcol && off[j] == o; j++)
       +                                for (j = i; j < cend && off[j - cbeg] == o; j++)
                                                sbuf_chr(out, ' ');
       -                        while (i <= maxcol && off[i] == o)
       +                        while (i < cend && off[i - cbeg] == o)
                                        i++;
                        } else {
                                sbuf_chr(out, ' ');
       t@@ -123,7 +121,7 @@ static char *led_render(char *s0)
        
        void led_print(char *s, int row)
        {
       -        char *r = led_render(s);
       +        char *r = led_render(s, xleft, xleft + xcols);
                term_pos(row, 0);
                term_kill();
                term_str(r);
       t@@ -171,8 +169,12 @@ static void led_printparts(char *ai, char *pref, char *main, char *post, char *k
                }
                term_record();
                sbuf_str(ln, post);
       -        led_print(sbuf_buf(ln), -1);
                pos = ren_cursor(sbuf_buf(ln), ren_pos(sbuf_buf(ln), MAX(0, off - 1)));
       +        if (pos >= xleft + xcols)
       +                xleft = pos - xcols / 2;
       +        if (pos < xleft)
       +                xleft = pos < xcols ? 0 : pos - xcols / 2;
       +        led_print(sbuf_buf(ln), -1);
                term_pos(-1, led_pos(sbuf_buf(ln), pos + idir));
                sbuf_free(ln);
                term_commit();
 (DIR) diff --git a/vi.c b/vi.c
       t@@ -33,8 +33,11 @@ static void vi_wait(void)
        
        static void vi_drawmsg(void)
        {
       +        int oleft = xleft;
       +        xleft = 0;
                led_print(vi_msg, xrows);
                vi_msg[0] = '\0';
       +        xleft = oleft;
        }
        
        /* redraw the screen */
       t@@ -1010,6 +1013,7 @@ static void vi(void)
                        int nrow = xrow;
                        int noff = ren_noeol(lbuf_get(xb, xrow), xoff);
                        int otop = xtop;
       +                int oleft = xleft;
                        int mv, n;
                        term_cmd(&n);
                        vi_arg2 = 0;
       t@@ -1265,8 +1269,12 @@ static void vi(void)
                        xoff = ren_noeol(lbuf_get(xb, xrow), xoff);
                        if (redraw)
                                xcol = vi_off2col(xb, xrow, xoff);
       +                if (xcol >= xleft + xcols)
       +                        xleft = xcol - xcols / 2;
       +                if (xcol < xleft)
       +                        xleft = xcol < xcols ? 0 : xcol - xcols / 2;
                        vi_wait();
       -                if (redraw || xtop != otop)
       +                if (redraw || xtop != otop || xleft != oleft)
                                vi_draw(xcol);
                        if (vi_msg[0])
                                vi_drawmsg();
 (DIR) diff --git a/vi.h b/vi.h
       t@@ -182,6 +182,7 @@ int conf_highlight_revdir(int *att);
        extern int xrow;
        extern int xoff;
        extern int xtop;
       +extern int xleft;
        extern int xvis;
        extern int xled;
        extern int xquit;