URI: 
       tImplement cursor moves and basic scrolling - sex - libtermbox based text editor
  HTML git clone git://z3bra.org/sex
   DIR Log
   DIR Files
   DIR Refs
   DIR README
       ---
   DIR commit 1c558c8e5d2f22d1afec3650f434ec266779753c
   DIR parent 3aac5bf10075d6c48b717b843bd7d3e4a14b20fb
  HTML Author: dcat <dcat@iotek.org>
       Date:   Mon,  4 Apr 2016 20:04:11 +0200
       
       Implement cursor moves and basic scrolling
       
       Diffstat:
         M sex.c                               |     144 +++++++++++++++++++++++++------
       
       1 file changed, 116 insertions(+), 28 deletions(-)
       ---
   DIR diff --git a/sex.c b/sex.c
       t@@ -15,9 +15,12 @@
        
        #define TAB_WIDTH 8
        
       +typedef enum { UP, DOWN, RIGHT, LEFT } direction;
       +
        struct line_s {
                char  *p;
                size_t len;
       +        size_t number;
                TAILQ_ENTRY(line_s) entries;
        };
        
       t@@ -30,9 +33,21 @@ struct file_s {
                struct line_s *ln;
        };
        
       +struct coord_s {
       +        int x;
       +        int y;
       +};
       +
       +struct ui_s {
       +        struct line_s *top;
       +        struct line_s *cur;
       +        int width;
       +        int height;
       +        struct coord_s pos;
       +};
       +
        static struct file_s f;
        TAILQ_HEAD(line_s_head, line_s) head;
       -struct line_s *cur;
        
        void
        cleanup(void)
       t@@ -55,7 +70,7 @@ void
        open_file(char *path)
        {
                size_t i, last_eol;
       -        int d;
       +        int d, ln = 1;
                struct stat s;
                struct line_s *tmp;
        
       t@@ -86,11 +101,11 @@ open_file(char *path)
        
                                tmp->p = f.map + last_eol;
                                tmp->len = i - last_eol + 1;
       +                        tmp->number = ln++;
                                last_eol = i + 1;
                                TAILQ_INSERT_TAIL(&head, tmp, entries);
                        }
                }
       -        cur = TAILQ_FIRST(&head);
        }
        
        ssize_t
       t@@ -105,13 +120,12 @@ ui_expand_tab(int x, int y, uint8_t tw)
                return tabsize;
        }
        
       -void
       +int
        ui_print(char *str, int x, int y, int len) {
       -        int n = 0;
       +        size_t n = 0;
       +        uint32_t uni;
        
                while (*str) {
       -                uint32_t uni;
       -
                        switch(*str) {
                        case '\t':
                                x += ui_expand_tab(x, y, TAB_WIDTH);
       t@@ -123,32 +137,102 @@ ui_print(char *str, int x, int y, int len) {
                                x++;
                        }
        
       -                if (++n == len)
       -                        return;
       +                if (++n == len || x >= tb_width())
       +                        break;
                }
       +        return x - 1;
        }
        
        void
       -ui_redraw(void) {
       +ui_redraw(struct ui_s *ui) {
                /* redraw screen */
                struct line_s *tmp;
       -        int i = 0;
       +        int row, j;
       +        size_t s = 0;
       +
       +        tmp = ui->top;
       +
       +        tb_clear();
       +        tb_present();
        
       -        TAILQ_FOREACH(tmp, &head, entries) {
       -                ui_print(tmp->p, 0, i++, tmp->len);
       +        for (row = 0; row < tb_height() - 1; row++) {
       +                if (tmp && tmp->p)
       +                        ui_print(tmp->p, 0, row, tmp->len);
       +                else {
       +                        ui_print("~", 0, row, 1);
       +                        continue;
       +                }
       +
       +                tmp = TAILQ_NEXT(tmp, entries);
                }
        
                tb_present();
        }
        
        void
       -edit(char *path)
       +ui_init(struct ui_s *ui)
       +{
       +        ui->width  = tb_width();
       +        ui->height = tb_height();
       +        ui->top    = TAILQ_FIRST(&head);
       +        ui->pos.x  = 0;
       +        ui->pos.y  = 0;
       +        ui->cur    = ui->top;
       +}
       +
       +void
       +scroll(struct ui_s *window, direction dir)
       +{
       +
       +        switch (dir) {
       +        case UP:
       +                if (window->pos.y == 0) {
       +                        if (window->top == TAILQ_FIRST(&head))
       +                                break;
       +                        window->top = TAILQ_PREV(window->top, line_s_head,
       +                                        entries);
       +                } else {
       +                        tb_set_cursor(window->pos.x, --window->pos.y);
       +                        break;
       +                }
       +                window->cur = TAILQ_PREV(window->cur, line_s_head, entries);
       +                break;
       +        case DOWN:
       +                if (window->pos.y == tb_height() - 2) {
       +                        if (window->top == TAILQ_LAST(&head, line_s_head))
       +                                break;
       +                        window->top = TAILQ_NEXT(window->top, entries);
       +                } else {
       +                        if (window->cur == TAILQ_LAST(&head, line_s_head))
       +                                break;
       +                        tb_set_cursor(window->pos.x, ++window->pos.y);
       +                        break;
       +                }
       +                window->cur = TAILQ_NEXT(window->cur, entries);
       +                break;
       +        case RIGHT:
       +                if (window->pos.x < window->cur->len - 1)
       +                        tb_set_cursor(++window->pos.x, window->pos.y);
       +                break;
       +        case LEFT:
       +                if (window->pos.x > 0)
       +                        tb_set_cursor(--window->pos.x, window->pos.y);
       +                break;
       +        }
       +}
       +
       +void
       +ui_edit(char *path)
        {
                int needs_redraw;
                struct tb_event ev;
       +        struct ui_s window;
        
                open_file(path);
       -        ui_redraw();
       +
       +        ui_init(&window);
       +        tb_set_cursor(0,0);
       +        ui_redraw(&window);
        
                while (tb_poll_event(&ev)) {
                        switch (ev.type) {
       t@@ -158,20 +242,23 @@ edit(char *path)
                                case TB_KEY_CTRL_C:
                                        return;
                                        /* NOTREACHED */
       -                        case 'j':
       -                        case TB_KEY_ARROW_DOWN:
       -                                if (cur == TAILQ_LAST(&head, line_s_head))
       -                                        break;
       -
       -                                cur = TAILQ_NEXT(cur, entries);
       +                        case TB_KEY_CTRL_L:
                                        needs_redraw = 1;
                                        break;
       -                        case 'k':
                                case TB_KEY_ARROW_UP:
       -                                if (cur == TAILQ_FIRST(&head))
       -                                        break;
       -
       -                                cur = TAILQ_PREV(cur, line_s_head, entries);
       +                                scroll(&window, UP);
       +                                needs_redraw = 1;
       +                                break;
       +                        case TB_KEY_ARROW_DOWN:
       +                                scroll(&window, DOWN);
       +                                needs_redraw = 1;
       +                                break;
       +                        case TB_KEY_ARROW_RIGHT:
       +                                scroll(&window, RIGHT);
       +                                needs_redraw = 1;
       +                                break;
       +                        case TB_KEY_ARROW_LEFT:
       +                                scroll(&window, LEFT);
                                        needs_redraw = 1;
                                        break;
                                }
       t@@ -183,12 +270,13 @@ edit(char *path)
                        }
        
                        if (needs_redraw) {
       -                        ui_redraw();
       +                        ui_redraw(&window);
                                needs_redraw = 0;
                        }
                }
        }
        
       +
        int
        main(int argc, char **argv)
        {
       t@@ -206,7 +294,7 @@ main(int argc, char **argv)
                atexit(cleanup);
        
                while (*argv)
       -                edit(*argv++);
       +                ui_edit(*argv++);
        
                return 0;
        }