diff options
-rw-r--r-- | toys/pending/vi.c | 141 |
1 files changed, 86 insertions, 55 deletions
diff --git a/toys/pending/vi.c b/toys/pending/vi.c index 50b8f0ab..9334e033 100644 --- a/toys/pending/vi.c +++ b/toys/pending/vi.c @@ -22,6 +22,9 @@ config VI GLOBALS( int cur_col; int cur_row; + int scr_row; + int drawn_row; + int drawn_col; unsigned screen_height; unsigned screen_width; int vi_mode; @@ -91,6 +94,8 @@ struct yank_buf yank; //single yank // 0x1 = Command needs argument (f,F,r...) // 0x2 = Move 1 right on yank/delete/insert (e, $...) // 0x4 = yank/delete last line fully +// 0x10000000 = redraw after cursor needed +// 0x20000000 = full redraw needed // 0x40000000 = count0 not given // 0x80000000 = move was reverse @@ -211,7 +216,6 @@ int vi_dd(char reg, int count0, int count1) vi_delete(reg, pos, 0, 0); check_cursor_bounds(); - adjust_screen_buffer(); return 1; } @@ -287,7 +291,6 @@ next_line: return vi_movw(count, 1, 0); check_cursor_bounds(); - adjust_screen_buffer(); return 1; } @@ -319,7 +322,6 @@ exit_function: return vi_movb(count, 1, 0); TT.vi_mov_flag |= 0x80000000; check_cursor_bounds(); - adjust_screen_buffer(); return 1; } @@ -338,7 +340,6 @@ static int vi_move(int count0, int count1, char *unused) TT.vi_mov_flag |= 2; check_cursor_bounds(); - adjust_screen_buffer(); return 1; } @@ -388,7 +389,6 @@ void i_split() c_r->line = l; TT.cur_col = 0; check_cursor_bounds(); - adjust_screen_buffer(); } @@ -415,10 +415,12 @@ static int vi_eol(int count0, int count1, char *unused) //TODO check register where to push from static int vi_push(char reg, int count0, int count1) { - char *start = yank.data; - char *end = yank.data+strlen(yank.data); + char *start = yank.data, *end = yank.data+strlen(yank.data); + struct linelist *cursor = c_r; + int col = TT.cur_col; //insert into new lines if (*(end-1) == '\n') for (;start != end;) { + TT.vi_mov_flag |= 0x10000000; char *next = strchr(start, '\n'); vi_eol(1, 1, 0); i_split(); @@ -432,6 +434,7 @@ static int vi_push(char reg, int count0, int count1) else for (;start != end;) { char *next = strchr(start, '\n'); if (next) { + TT.vi_mov_flag |= 0x10000000; i_insert(start, next-start); i_split(); start = next+1; @@ -440,6 +443,10 @@ static int vi_push(char reg, int count0, int count1) start = end; } } + //if row changes during push original cursor position is kept + //vi inconsistancy + if (c_r != cursor) c_r = cursor, TT.cur_col = col; + return 1; } @@ -475,7 +482,6 @@ static int vi_go(int count0, int count1, char *symbol) TT.cur_col = 0; check_cursor_bounds(); //adjusts cursor column - adjust_screen_buffer(); //adjusts screen buffer if (prev_row>TT.cur_row) TT.vi_mov_flag |= 0x80000000; return 1; @@ -505,6 +511,7 @@ static int vi_delete(char reg, struct linelist *row, int col, int flags) start = start->down; full_line_delete: + TT.vi_mov_flag |= 0x10000000; for (;start != end;) { struct linelist* lst = start; //struct linelist *lst = dlist_pop(&start); @@ -518,6 +525,7 @@ full_line_delete: free(lst); } last_line_delete: + TT.vi_mov_flag |= 0x10000000; if (TT.vi_mov_flag&2) col_e = start->line->str_len; if (TT.vi_mov_flag&4) { if (!end->down && !end->up) @@ -813,7 +821,6 @@ static int search_str(char *s) c_r = lst; TT.cur_col = c-c_r->line->str_data; check_cursor_bounds(); - adjust_screen_buffer(); return 0; } @@ -882,6 +889,7 @@ void vi_main(void) tty_esc("?1049h"); tty_esc("H"); xflush(1); + TT.vi_mov_flag = 0x20000000; draw_page(); while(1) { int key = scan_key(keybuf, -1); @@ -1080,7 +1088,7 @@ int crunch_nstr(char **str, int width, int n, FILE *out, char *escmore, static void draw_page() { - struct linelist *scr_buf = scr_r; + struct linelist *scr_buf = 0; unsigned y = 0; int x = 0; @@ -1093,26 +1101,26 @@ static void draw_page() //variables used only for cursor handling int aw = 0, iw = 0, clip = 0, margin = 8; - //clear screen - tty_esc("2J"); - tty_esc("H"); + int scroll = 0, redraw = 0; - //draw lines until cursor row + adjust_screen_buffer(); + scr_buf = scr_r; + redraw = (TT.vi_mov_flag & 0x30000000)>>28; + + scroll = TT.drawn_row-TT.scr_row; + if (TT.drawn_row<0 || TT.cur_row<0 || TT.scr_row<0) redraw = 3; + else if (abs(scroll)>TT.screen_height/2) redraw = 3; + + tty_jump(0, 0); + if (redraw&2) tty_esc("2J"), tty_esc("H"); //clear screen + else if (scroll>0) printf("\033[%dL", scroll); //scroll up + else if (scroll<0) printf("\033[%dM", -scroll); //scroll down + + //jump until cursor for (; y < TT.screen_height; y++ ) { - tty_jump(0, y); - if (scr_buf == c_r) - break; - if (scr_buf) { - if (scr_buf->line->str_data && scr_buf->line->str_len) { - line = scr_buf->line->str_data; - bytes = scr_buf->line->str_len; - scr_buf = scr_buf->down; - crunch_str(&line, TT.screen_width-1, stdout, "\t", vi_crunch); - if ( *line ) printf("@"); - } else scr_buf = scr_buf->down; - } + if (scr_buf == c_r) break; + scr_buf = scr_buf->down; } - //draw cursor row ///////////////////////////////////////////////////////////// //for long lines line starts to scroll when cursor hits margin @@ -1120,10 +1128,12 @@ static void draw_page() bytes = TT.cur_col; end = line; + + tty_jump(0, y); + tty_esc("2K"); //find cursor position aw = crunch_nstr(&end, 1024, bytes, 0, "\t", vi_crunch); - //if we need to render text that is not inserted to buffer yet if (TT.vi_mode == 2 && il->str_len) { char* iend = il->str_data; //input end @@ -1167,26 +1177,52 @@ static void draw_page() x += crunch_str(&end, TT.screen_width-x, stdout, "\t", vi_crunch); } - tty_jump(0, ++y); if (scr_buf) scr_buf = scr_buf->down; // drawing cursor row ends /////////////////////////////////////////////////////////////////// -//draw until end + //start drawing all other rows that needs update + /////////////////////////////////////////////////////////////////// + y = 0, scr_buf = scr_r; + + //if we moved around in long line might need to redraw everything + if (clip != TT.drawn_col) redraw = 3; + for (; y < TT.screen_height; y++ ) { + int draw_line = 0; + if (scr_buf == c_r) { + scr_buf = scr_buf->down; + continue; + } else if (redraw) draw_line++; + else if (scroll<0 && TT.screen_height-y-1<-scroll) + scroll++, draw_line++; + else if (scroll>0) scroll--, draw_line++; + tty_jump(0, y); - if (scr_buf) { - if (scr_buf->line->str_data && scr_buf->line->str_len) { - line = scr_buf->line->str_data; - bytes = scr_buf->line->str_len; - scr_buf = scr_buf->down; - crunch_str(&line, TT.screen_width-1, stdout, "\t", vi_crunch); - if ( *line ) printf("@"); - } else scr_buf = scr_buf->down; - } else printf("~"); + if (draw_line) { + + tty_esc("2K"); + if (scr_buf) { + if (draw_line && scr_buf->line->str_data && scr_buf->line->str_len) { + line = scr_buf->line->str_data; + bytes = scr_buf->line->str_len; + + aw = crunch_nstr(&line, clip, bytes, 0, "\t", vi_crunch); + crunch_str(&line, TT.screen_width-1, stdout, "\t", vi_crunch); + if ( *line ) printf("@"); + + } + } else if (draw_line) printf("~"); + } + if (scr_buf) scr_buf = scr_buf->down; } + TT.drawn_row = TT.scr_row, TT.drawn_col = clip; + + //finished updating visual area + tty_jump(0, TT.screen_height); + tty_esc("2K"); switch (TT.vi_mode) { case 0: tty_esc("30;44m"); @@ -1214,10 +1250,12 @@ static void draw_page() tty_jump(TT.screen_width-12, TT.screen_height); printf("| %d, %d\n", TT.cur_row, TT.cur_col); + tty_esc("m"); + tty_jump(0, TT.screen_height+1); + tty_esc("2K"); if (!TT.vi_mode) { tty_esc("1m"); - tty_jump(0, TT.screen_height+1); printf("%s", il->str_data); tty_esc("m"); } else tty_jump(cx_scr, cy_scr); @@ -1243,28 +1281,23 @@ static void adjust_screen_buffer() struct linelist *t = text; int c = -1, s = -1, i = 0; //searching cursor and screen line numbers - for (;;) { - i++; + for (;((c == -1) || (s == -1)) && t != 0; i++, t = t->down) { if (t == c_r) c = i; if (t == scr_r) s = i; - - t = t->down; - if ( ((c != -1) && (s != -1)) || t == 0) - break; } //adjust screen buffer so cursor is on drawing area - if (c <= s) scr_r = c_r; //scroll up - else if (c > s) { + if (c <= s) scr_r = c_r, s = c; //scroll up + else { //drawing does not have wrapping so no need to check width - int distance = c - s + 1; + int distance = c-s+1; - if (distance >= (int)TT.screen_height) { - int adj = distance - TT.screen_height; - while (adj--) scr_r = scr_r->down; //scroll down + if (distance > (int)TT.screen_height) { + int adj = distance-TT.screen_height; + for (;adj; adj--) scr_r = scr_r->down, s++; //scroll down } } - TT.cur_row = c; + TT.cur_row = c, TT.scr_row = s; } @@ -1410,7 +1443,6 @@ static int cur_up(int count0, int count1, char* unused) TT.vi_mov_flag |= 0x80000000; check_cursor_bounds(); - adjust_screen_buffer(); return 1; } @@ -1421,7 +1453,6 @@ static int cur_down(int count0, int count1, char* unused) c_r = c_r->down; check_cursor_bounds(); - adjust_screen_buffer(); return 1; } |