aboutsummaryrefslogtreecommitdiff
path: root/vterm-module.c
diff options
context:
space:
mode:
authorjixiufeng <jixiufeng@luojilab.com>2018-11-10 19:27:57 +0800
committerjixiufeng <jixiufeng@luojilab.com>2018-11-10 19:27:57 +0800
commita9a3375b78390dcd2c82bfcf97bcc4bb2ef12bbd (patch)
tree792184afe7f483eee4a99fc8a512339c371c5449 /vterm-module.c
parent122b4834edf3c8f332fcf763d3489d5def5fcb1f (diff)
replace refresh_row with refresh_lines
Diffstat (limited to 'vterm-module.c')
-rw-r--r--vterm-module.c169
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"));