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;
}