sex

simple editor extended using libtermbox
git clone git://z3bra.org/sex
Log | Files | Refs | README

commit 1c558c8e5d2f22d1afec3650f434ec266779753c
parent 3aac5bf10075d6c48b717b843bd7d3e4a14b20fb
Author: dcat <dcat@iotek.org>
Date:   Mon Apr  4 20:04:11 2016

Implement cursor moves and basic scrolling

Diffstat:
 sex.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 116 insertions(+), 28 deletions(-)

diff --git a/sex.c b/sex.c @@ -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; }; @@ -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) @@ -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; @@ -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 @@ -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); @@ -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) { @@ -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; } @@ -183,12 +270,13 @@ edit(char *path) } if (needs_redraw) { - ui_redraw(); + ui_redraw(&window); needs_redraw = 0; } } } + int main(int argc, char **argv) { @@ -206,7 +294,7 @@ main(int argc, char **argv) atexit(cleanup); while (*argv) - edit(*argv++); + ui_edit(*argv++); return 0; }