diff options
| author | jixiufeng <jixiufeng@luojilab.com> | 2018-11-10 19:27:57 +0800 |
|---|---|---|
| committer | jixiufeng <jixiufeng@luojilab.com> | 2018-11-10 19:27:57 +0800 |
| commit | a9a3375b78390dcd2c82bfcf97bcc4bb2ef12bbd (patch) | |
| tree | 792184afe7f483eee4a99fc8a512339c371c5449 /vterm-module.c | |
| parent | 122b4834edf3c8f332fcf763d3489d5def5fcb1f (diff) | |
replace refresh_row with refresh_lines
Diffstat (limited to 'vterm-module.c')
| -rw-r--r-- | vterm-module.c | 169 |
1 files changed, 82 insertions, 87 deletions
diff --git a/vterm-module.c b/vterm-module.c index 1b6d630..f44f3c7 100644 --- a/vterm-module.c +++ b/vterm-module.c @@ -138,58 +138,57 @@ static size_t get_col_offset(Term *term, int row, int end_col) { return offset; } -static size_t refresh_row(Term *term, emacs_env *env, int row, int end_col, - bool append_newline) { - int j; - char *ptr = term->textbuf; +static void refresh_lines(Term *term, emacs_env *env, int start_row, + int end_row, int end_col) { + if (end_row < start_row) { + return; + } + int i, j; + + char buffer[((end_row - start_row + 1) * end_col) * 4]; int length = 0; VTermScreenCell cell; VTermScreenCell lastCell; - fetch_cell(term, row, 0, &lastCell); - - for (j = 0; j < end_col; j++) { - VTermPos pos = {.row = row, .col = j}; - fetch_cell(term, row, j, &cell); - - if (!compare_cells(&cell, &lastCell)) { - ptr[length] = '\0'; - emacs_value text = render_text(env, ptr, length, &lastCell); - insert(env, text); - ptr += length; - length = 0; - } + fetch_cell(term, start_row, 0, &lastCell); - lastCell = cell; - if (cell.chars[0] == 0) { - ptr[length] = ' '; - length++; - } else { - unsigned char bytes[4]; - size_t count = codepoint_to_utf8(cell.chars[0], bytes); - int k; - for (k = 0; k < count; k++) { - ptr[length] = bytes[k]; + int offset = 0; + for (i = start_row; i < end_row; i++) { + for (j = 0; j < end_col; j++) { + fetch_cell(term, i, j, &cell); + + if (!compare_cells(&cell, &lastCell)) { + emacs_value text = render_text(env, buffer, length, &lastCell); + insert(env, text); + length = 0; + } + + lastCell = cell; + if (cell.chars[0] == 0) { + buffer[length] = ' '; length++; + } else { + unsigned char bytes[4]; + size_t count = codepoint_to_utf8(cell.chars[0], bytes); + for (int k = 0; k < count; k++) { + buffer[length] = bytes[k]; + length++; + } } - } - if (cell.width > 1) { - int w = cell.width - 1; - j = j + w; + if (cell.width > 1) { + int w = cell.width - 1; + offset += w; + j = j + w; + } } + + buffer[length] = '\n'; + length++; } - if (length > 0) { - emacs_value text = render_text(env, ptr, length, &lastCell); - insert(env, text); - ptr += length; - } - if (append_newline) { - *ptr = '\n'; - ptr += 1; - insert(env, env->make_string(env, "\n", 1)); - } - *ptr = 0; - return ptr - term->textbuf; + emacs_value text = render_text(env, buffer, length, &lastCell); + insert(env, text); + + return; } // Refresh the screen (visible part of the buffer when the terminal is @@ -197,33 +196,26 @@ static size_t refresh_row(Term *term, emacs_env *env, int row, int end_col, static void refresh_screen(Term *term, emacs_env *env) { int height; int width; + + /* if (term->invalid_end < term->invalid_start) { */ + /* goto end; */ + /* } */ + vterm_get_size(term->vt, &height, &width); - // Term height may have decreased before `invalid_end` reflects it. /* refresh full screen now */ /* TODO: only refresh invalid lines */ term->invalid_start = 0; term->invalid_end = height; + // Term height may have decreased before `invalid_end` reflects it. int line_start = row_to_linenr(term, term->invalid_start); - goto_line(env, line_start - 1); - int liner; - int r; - for (r = term->invalid_start; r < term->invalid_end; r++) { - liner = row_to_linenr(term, r); - int buffer_lnum = env->extract_integer(env, buffer_line_number(env)); - if (liner > buffer_lnum) { - goto_line(env, buffer_lnum); /* maybe should goto end of buffer */ - int i; - for (i = 0; i < liner - buffer_lnum; i++) { - insert(env, env->make_string(env, "\n", 1)); - } - } - delete_lines(env, liner, 1, false); - goto_line(env, liner); - refresh_row(term, env, r, width, false); - } - term->invalid_start = INT_MAX; - term->invalid_end = -1; + goto_line(env, line_start); + delete_lines(env, line_start, term->invalid_end - term->invalid_start, true); + refresh_lines(term, env, term->invalid_start, term->invalid_end, width); + + /* end: */ + /* term->invalid_start = INT_MAX; */ + /* term->invalid_end = -1; */ } // Refresh the scrollback of an invalidated terminal. @@ -232,31 +224,30 @@ static void refresh_scrollback(Term *term, emacs_env *env) { int buffer_lnum; vterm_get_size(term->vt, &height, &width); - while (term->sb_pending > 0) { + if (term->sb_pending > 0) { // This means that either the window height has decreased or the screen // became full and libvterm had to push all rows up. Convert the first // pending scrollback row into a string and append it just above the visible // section of the buffer buffer_lnum = env->extract_integer(env, buffer_line_number(env)); - if ((buffer_lnum - height) >= (int)term->sb_size) { - // scrollback full, delete lines at the top - delete_lines(env, 1, 1, true); - /* insert(env,env->make_string(env, "\n", 1)); */ + int del_cnt = buffer_lnum - height - (int)term->sb_size + term->sb_pending; + if (del_cnt > 0) { + delete_lines(env, 1, del_cnt, true); + buffer_lnum = env->extract_integer(env, buffer_line_number(env)); } - buffer_lnum = env->extract_integer(env, buffer_line_number(env)); int buf_index = buffer_lnum - height + 1; goto_line(env, buf_index); - size_t length = refresh_row(term, env, -term->sb_pending, width, true); - term->sb_pending--; + refresh_lines(term, env, -term->sb_pending, 0, width); + term->sb_pending = 0; } - // Remove extra lines at the bottom int max_line_count = (int)term->sb_current + height; buffer_lnum = env->extract_integer(env, buffer_line_number(env)); // Remove extra lines at the bottom if (buffer_lnum > max_line_count) { - delete_lines(env, max_line_count, buffer_lnum - max_line_count, true); + delete_lines(env, max_line_count + 1, buffer_lnum - max_line_count + 1, + true); } } @@ -274,7 +265,6 @@ static void adjust_topline(Term *term, emacs_env *env, long added) { size_t offset = get_col_offset(term, pos.row, pos.col); forward_char(env, env->make_integer(env, pos.col - offset)); - bool following = buffer_lnum == cursor_lnum + added; // cursor at end? emacs_value window = get_buffer_window(env); @@ -283,7 +273,8 @@ static void adjust_topline(Term *term, emacs_env *env, long added) { if (swindow == window) { if (following) { // "Follow" the terminal output - recenter(env, env->make_integer(env, -1)); /* make current line at the screen bottom */ + recenter(env, env->make_integer( + env, -1)); /* make current line at the screen bottom */ } else { recenter(env, env->make_integer(env, pos.row)); } @@ -291,12 +282,18 @@ static void adjust_topline(Term *term, emacs_env *env, long added) { } static void term_redraw(Term *term, emacs_env *env) { - long ml_before = env->extract_integer(env, buffer_line_number(env)); + /* if (term->is_invalidated) { */ + toggle_cursor_blinking(env, term->cursor_blinking); + toggle_cursor(env, term->cursor_visible); + long bufline_before = env->extract_integer(env, buffer_line_number(env)); + /* refresh_size(term, env); */ refresh_scrollback(term, env); refresh_screen(term, env); - long ml_added = - env->extract_integer(env, buffer_line_number(env)) - ml_before; - adjust_topline(term, env, ml_added); + long line_added = + env->extract_integer(env, buffer_line_number(env)) - bufline_before; + adjust_topline(term, env, line_added); + /* } */ + /* term->is_invalidated = false; */ } static VTermScreenCallbacks vterm_screen_callbacks = { @@ -538,7 +535,7 @@ static emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, term->sb_pending = 0; term->sb_buffer = malloc(sizeof(ScrollbackLine *) * term->sb_size); term->invalid_start = 0; - term->invalid_end = cols; + term->invalid_end = rows; return env->make_user_ptr(env, term_finalize, term); } @@ -547,9 +544,6 @@ static emacs_value Fvterm_update(emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data) { Term *term = env->get_user_ptr(env, args[0]); - toggle_cursor_blinking(env, term->cursor_blinking); - toggle_cursor(env, term->cursor_visible); - // Process keys if (nargs > 1) { ptrdiff_t len = string_bytes(env, args[1]); @@ -643,12 +637,13 @@ int emacs_module_init(struct emacs_runtime *ert) { Fdelete_lines = env->make_global_ref(env, env->intern(env, "vterm--delete-lines")); Frecenter = env->make_global_ref(env, env->intern(env, "recenter")); - Fforward_char = - env->make_global_ref(env, env->intern(env, "forward-char")); + Fforward_char = env->make_global_ref(env, env->intern(env, "forward-char")); Fblink_cursor_mode = env->make_global_ref(env, env->intern(env, "blink-cursor-mode")); - Fget_buffer_window = env->make_global_ref(env, env->intern(env, "get-buffer-window")); - Fselected_window = env->make_global_ref(env, env->intern(env, "selected-window")); + Fget_buffer_window = + env->make_global_ref(env, env->intern(env, "get-buffer-window")); + Fselected_window = + env->make_global_ref(env, env->intern(env, "selected-window")); // Faces Qterm = env->make_global_ref(env, env->intern(env, "vterm")); |
