aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toys/pending/vi.c203
1 files changed, 107 insertions, 96 deletions
diff --git a/toys/pending/vi.c b/toys/pending/vi.c
index ab15bfe0..c5c87507 100644
--- a/toys/pending/vi.c
+++ b/toys/pending/vi.c
@@ -31,20 +31,20 @@ GLOBALS(
*
* TODO:
* BUGS: screen pos adjust does not cover "widelines"
- *
+ *
*
* REFACTOR: use dllist functions where possible.
* draw_page dont draw full page at time if nothing changed...
* ex callbacks
- *
+ *
* FEATURE: ex: / ? % //atleast easy cases
- * vi: x dw d$ d0
+ * vi: x dw d$ d0
* vi: yw yy (y0 y$)
* vi+ex: gg G //line movements
- * ex: r
+ * ex: r
* ex: !external programs
* ex: w filename //only writes to same file now
- * big file support?
+ * big file support?
*/
@@ -75,7 +75,7 @@ static void adjust_screen_buffer();
struct str_line {
int alloc_len;
- int str_len;
+ int str_len;
char *str_data;
};
@@ -90,7 +90,7 @@ struct linelist {
struct str_line *il;
struct linelist *text; //file loaded into buffer
struct linelist *scr_r;//current screen coord 0 row
-struct linelist *c_r;//cursor position row
+struct linelist *c_r;//cursor position row
int modified;
void dlist_insert_nomalloc(struct double_list **list, struct double_list *new)
@@ -113,9 +113,9 @@ struct double_list *dlist_insert(struct double_list **list, char *data)
return new;
}
-void linelist_unload()
+void linelist_unload()
{
-
+
}
void write_file(char *filename)
@@ -133,7 +133,7 @@ void write_file(char *filename)
fclose(fp);
}
-int linelist_load(char *filename)
+int linelist_load(char *filename)
{
struct linelist *lst = c_r;//cursor position or 0
FILE *fp = 0;
@@ -141,7 +141,18 @@ int linelist_load(char *filename)
filename = (char*)*toys.optargs;
fp = fopen(filename, "r");
- if (!fp) return 0;
+ if (!fp) {
+ char *line = xzalloc(80);
+ ssize_t alc = 80;
+ lst = (struct linelist*)dlist_add((struct double_list**)&lst,
+ xzalloc(sizeof(struct str_line)));
+ lst->line->alloc_len = alc;
+ lst->line->str_len = 0;
+ lst->line->str_data = line;
+ text = lst;
+ dlist_terminate(text->up);
+ return 1;
+ }
for (;;) {
char *line = xzalloc(80);
@@ -177,7 +188,7 @@ int linelist_load(char *filename)
}
//TODO this is overly complicated refactor with lib dllist
-int ex_dd(int count)
+int ex_dd(int count)
{
struct linelist *lst = c_r;
if (c_r == text && text == scr_r) {
@@ -185,7 +196,7 @@ int ex_dd(int count)
text->line->str_len = 1;
sprintf(text->line->str_data, " ");
goto success_exit;
- }
+ }
if (text->down) {
text = text->down;
text->up = 0;
@@ -236,7 +247,7 @@ int ex_dw(int count)
return 1;
}
-int ex_deol(int count)
+int ex_deol(int count)
{
return 1;
}
@@ -253,27 +264,27 @@ int vi_x(int count)
l = &c_r->line->str_len;
p = &TT.cur_col;
if (!(*l)) return 0;
- if ((*p) == (*l)-1) {
+ if ((*p) == (*l)-1) {
s[*p] = 0;
- if (*p) (*p)--;
+ if (*p) (*p)--;
+ (*l)--;
+ } else {
+ memmove(s+(*p), s+(*p)+1, (*l)-(*p));
+ s[*l] = 0;
(*l)--;
- } else {
- memmove(s+(*p), s+(*p)+1, (*l)-(*p));
- s[*l] = 0;
- (*l)--;
}
count--;
- return (count) ? vi_x(count) : 1;
+ return (count) ? vi_x(count) : 1;
}
//move commands does not behave correct way yet.
//only jump to next space for now.
-int vi_movw(int count)
+int vi_movw(int count)
{
if (!c_r)
return 0;
//could we call moveend first
- while (c_r->line->str_data[TT.cur_col] > ' ')
+ while (c_r->line->str_data[TT.cur_col] > ' ')
TT.cur_col++;
while (c_r->line->str_data[TT.cur_col] <= ' ') {
TT.cur_col++;
@@ -283,7 +294,7 @@ int vi_movw(int count)
c_r = c_r->down;
TT.cur_col = 0;
}
- }
+ }
count--;
if (count>1)
return vi_movw(count);
@@ -293,7 +304,7 @@ int vi_movw(int count)
return 1;
}
-int vi_movb(int count)
+int vi_movb(int count)
{
if (!c_r)
return 0;
@@ -308,7 +319,7 @@ int vi_movb(int count)
while (c_r->line->str_data[TT.cur_col] <= ' ') {
if (TT.cur_col) TT.cur_col--;
else goto exit_function;
- }
+ }
while (c_r->line->str_data[TT.cur_col] > ' ') {
if (TT.cur_col)TT.cur_col--;
else goto exit_function;
@@ -323,15 +334,15 @@ exit_function:
return 1;
}
-int vi_move(int count)
+int vi_move(int count)
{
if (!c_r)
return 0;
if (TT.cur_col < c_r->line->str_len)
TT.cur_col++;
if (c_r->line->str_data[TT.cur_col] <= ' ' || count > 1)
- vi_movw(count); //find next word;
- while (c_r->line->str_data[TT.cur_col] > ' ')
+ vi_movw(count); //find next word;
+ while (c_r->line->str_data[TT.cur_col] > ' ')
TT.cur_col++;
if (TT.cur_col) TT.cur_col--;
@@ -348,11 +359,11 @@ void i_insert()
strncpy(t, &s[TT.cur_col], sel);
t[sel+1] = 0;
if (c_r->line->alloc_len < c_r->line->str_len+il->str_len+5) {
- c_r->line->str_data = xrealloc(c_r->line->str_data,
+ c_r->line->str_data = xrealloc(c_r->line->str_data,
c_r->line->alloc_len*2+il->alloc_len*2);
c_r->line->alloc_len = c_r->line->alloc_len*2+2*il->alloc_len;
- memset(&c_r->line->str_data[c_r->line->str_len], 0,
+ memset(&c_r->line->str_data[c_r->line->str_len], 0,
c_r->line->alloc_len-c_r->line->str_len);
s = c_r->line->str_data;
@@ -402,7 +413,7 @@ struct vi_cmd_param vi_cmds[7] =
{"x", &vi_x},
};
-int run_vi_cmd(char *cmd)
+int run_vi_cmd(char *cmd)
{
int val = 0;
char *cmd_e;
@@ -441,11 +452,11 @@ int search_str(char *s)
TT.cur_col = c-c_r->line->str_data;
return 0;
}
-
+
int run_ex_cmd(char *cmd)
{
if (cmd[0] == '/') {
- //search pattern
+ //search pattern
if (!search_str(&cmd[1]) ) {
check_cursor_bounds();
adjust_screen_buffer();
@@ -532,7 +543,8 @@ void vi_main(void)
il->str_len++;
break;
case 'a':
- TT.cur_col++;
+ if (c_r && c_r->line->str_len)
+ TT.cur_col++;
case 'i':
TT.vi_mode = 2;
break;
@@ -552,7 +564,7 @@ void vi_main(void)
vi_buf_pos = 0;
}
- }
+ }
break;
}
@@ -649,6 +661,7 @@ static void draw_page()
char* line = 0;
int bytes = 0;
int drawn = 0;
+ int x = 0;
struct linelist *scr_buf= scr_r;
//clear screen
tty_esc("2J");
@@ -665,12 +678,14 @@ static void draw_page()
y++;
tty_jump(0, y);
} else if (scr_buf && scr_buf->line->str_data && scr_buf->line->str_len) {
- if (scr_buf == c_r)
+ if (scr_buf == c_r)
break;
line = scr_buf->line->str_data;
bytes = scr_buf->line->str_len;
scr_buf = scr_buf->down;
} else {
+ if (scr_buf == c_r)
+ break;
y++;
tty_jump(0, y);
//printf(" \n");
@@ -680,64 +695,59 @@ static void draw_page()
}
//draw cursor row until cursor
//this is to calculate cursor position on screen and possible insert
- if (TT.cur_col) {
- int x = 0;
- line = scr_buf->line->str_data;
- bytes = TT.cur_col;
+ line = scr_buf->line->str_data;
+ bytes = TT.cur_col;
+ for (; y < TT.screen_height; ) {
+ if (bytes) {
+ x = draw_str_until(&drawn, line, TT.screen_width, bytes);
+ bytes = drawn ? (bytes-drawn) : 0;
+ line = bytes ? (line+drawn) : 0;
+ }
+ if (!bytes) break;
+ y++;
+ tty_jump(0, y);
+ }
+ if (TT.vi_mode == 2 && il->str_len) {
+ line = il->str_data;
+ bytes = il->str_len;
+ cx_scr = x;
+ cy_scr = y;
+ x = draw_str_until(&drawn, line, TT.screen_width-x, bytes);
+ bytes = drawn ? (bytes-drawn) : 0;
+ line = bytes ? (line+drawn) : 0;
+ cx_scr += x;
for (; y < TT.screen_height; ) {
if (bytes) {
x = draw_str_until(&drawn, line, TT.screen_width, bytes);
bytes = drawn ? (bytes-drawn) : 0;
line = bytes ? (line+drawn) : 0;
+ cx_scr = x;
}
if (!bytes) break;
y++;
- tty_jump(0, y);
- }
- if (TT.vi_mode == 2 && il->str_len) {
- line = il->str_data;
- bytes = il->str_len;
- cx_scr = x;
- cy_scr = y;
- x = draw_str_until(&drawn, line, TT.screen_width-x, bytes);
- bytes = drawn ? (bytes-drawn) : 0;
- line = bytes ? (line+drawn) : 0;
- cx_scr += x;
- for (; y < TT.screen_height; ) {
- if (bytes) {
- x = draw_str_until(&drawn, line, TT.screen_width, bytes);
- bytes = drawn ? (bytes-drawn) : 0;
- line = bytes ? (line+drawn) : 0;
- cx_scr = x;
- }
- if (!bytes) break;
- y++;
- cy_scr = y;
- tty_jump(0, y);
- }
- } else {
cy_scr = y;
- cx_scr = x;
+ tty_jump(0, y);
}
- line = scr_buf->line->str_data+TT.cur_col;
- bytes = scr_buf->line->str_len-TT.cur_col;
- scr_buf = scr_buf->down;
- x = draw_str_until(&drawn,line, TT.screen_width-x, bytes);
- bytes = drawn ? (bytes-drawn) : 0;
- line = bytes ? (line+drawn) : 0;
- y++;
- tty_jump(0, y);
} else {
cy_scr = y;
- cx_scr = 0;
+ cx_scr = x;
}
+ line = scr_buf->line->str_data+TT.cur_col;
+ bytes = scr_buf->line->str_len-TT.cur_col;
+ scr_buf = scr_buf->down;
+ x = draw_str_until(&drawn,line, TT.screen_width-x, bytes);
+ bytes = drawn ? (bytes-drawn) : 0;
+ line = bytes ? (line+drawn) : 0;
+ y++;
+ tty_jump(0, y);
+
//draw until end
for (; y < TT.screen_height; ) {
if (line && bytes) {
draw_str_until(&drawn, line, TT.screen_width, bytes);
bytes = drawn ? (bytes-drawn) : 0;
line = bytes ? (line+drawn) : 0;
- y++;
+ y++;
tty_jump(0, y);
} else if (scr_buf && scr_buf->line->str_data && scr_buf->line->str_len) {
line = scr_buf->line->str_data;
@@ -754,22 +764,22 @@ static void draw_page()
tty_jump(0, TT.screen_height);
switch (TT.vi_mode) {
case 0:
- tty_esc("30;44m");
+ tty_esc("30;44m");
printf("COMMAND|");
break;
case 1:
- tty_esc("30;42m");
+ tty_esc("30;42m");
printf("NORMAL|");
break;
case 2:
- tty_esc("30;41m");
+ tty_esc("30;41m");
printf("INSERT|");
break;
}
//DEBUG
- tty_esc("47m");
- tty_esc("30m");
+ tty_esc("47m");
+ tty_esc("30m");
utf_l = utf8_len(&c_r->line->str_data[TT.cur_col]);
if (utf_l) {
char t[5] = {0, 0, 0, 0, 0};
@@ -777,10 +787,10 @@ static void draw_page()
printf("utf: %d %s", utf_l, t);
}
printf("| %d, %d\n", cx_scr, cy_scr); //screen coord
-
+
tty_jump(TT.screen_width-12, TT.screen_height);
printf("| %d, %d\n", TT.cur_row, TT.cur_col);
- tty_esc("37m");
+ tty_esc("37m");
tty_esc("40m");
if (!TT.vi_mode) {
tty_esc("1m");
@@ -788,17 +798,17 @@ static void draw_page()
printf("%s", il->str_data);
tty_esc("0m");
} else tty_jump(cx_scr, cy_scr);
-
+
xflush();
}
-static void draw_char(char c, int x, int y, int highlight)
+static void draw_char(char c, int x, int y, int highlight)
{
tty_jump(x, y);
if (highlight) {
tty_esc("30m"); //foreground black
- tty_esc("47m"); //background white
+ tty_esc("47m"); //background white
}
printf("%c", c);
}
@@ -814,7 +824,7 @@ static int draw_rune(char *c, int x, int y, int highlight)
tty_esc("0m");
if (highlight) {
tty_esc("30m"); //foreground black
- tty_esc("47m"); //background white
+ tty_esc("47m"); //background white
}
strncpy(t, c, 5);
printf("%s", t);
@@ -832,7 +842,7 @@ static void check_cursor_bounds()
}
}
-static void adjust_screen_buffer()
+static void adjust_screen_buffer()
{
//search cursor and screen TODO move this perhaps
struct linelist *t = text;
@@ -855,7 +865,7 @@ static void adjust_screen_buffer()
else if ( c > s ) {
//should count multiline long strings!
int distance = c - s + 1;
- //TODO instead iterate scr_r up and check strlen%screen_width
+ //TODO instead iterate scr_r up and check strlen%screen_width
//for each iteration
if (distance >= (int)TT.screen_height) {
int adj = distance - TT.screen_height;
@@ -880,9 +890,9 @@ static int utf8_len(char *str)
{
int len = 0;
int i = 0;
- uint8_t *c = (uint8_t*)str;
- if (!c || !(*c)) return 0;
- if (*c < 0x7F) return 1;
+ uint8_t *c = (uint8_t*)str;
+ if (!c || !(*c)) return 0;
+ if (*c < 0x7F) return 1;
if ((*c & 0xE0) == 0xc0) len = 2;
else if ((*c & 0xF0) == 0xE0 ) len = 3;
else if ((*c & 0xF8) == 0xF0 ) len = 4;
@@ -931,7 +941,7 @@ static int utf8_width(char *str, int bytes)
return 0;
}
-static int utf8_dec(char key, char *utf8_scratch, int *sta_p)
+static int utf8_dec(char key, char *utf8_scratch, int *sta_p)
{
int len = 0;
char *c = utf8_scratch;
@@ -942,14 +952,14 @@ static int utf8_dec(char key, char *utf8_scratch, int *sta_p)
else if ((*c & 0xF0) == 0xE0 ) len = 3;
else if ((*c & 0xF8) == 0xF0 ) len = 4;
else {*sta_p = 0; return 0; }
-
+
(*sta_p)++;
if (*sta_p == 1) return 0;
if ((c[*sta_p-1] & 0xc0) != 0x80) {*sta_p = 0; return 0; }
if (*sta_p == len) { c[(*sta_p)] = 0; return 1; }
-
+
return 0;
}
@@ -963,7 +973,7 @@ static int draw_str_until(int *drawn, char *str, int width, int bytes)
for (;width && bytes;) {
rune_bytes = utf8_lnw(&rune_width, end, 4);
if (!rune_bytes) break;
- if (width - rune_width < 0) goto write_bytes;
+ if (width - rune_width < 0) goto write_bytes;
width -= rune_width;
bytes -= rune_bytes;
end += rune_bytes;
@@ -991,6 +1001,7 @@ static void cur_left()
static void cur_right()
{
+ if (c_r->line->str_len <= 1) return;
if (TT.cur_col == c_r->line->str_len-1) return;
TT.cur_col++;
if (!utf8_len(&c_r->line->str_data[TT.cur_col])) cur_right();