diff options
| author | Lukas Fürmetz <fuermetz@mailbox.org> | 2017-07-26 15:09:18 +0200 |
|---|---|---|
| committer | Lukas Fürmetz <fuermetz@mailbox.org> | 2017-07-26 15:09:18 +0200 |
| commit | afecd203861d582b78629438cca60014c8e6c5dd (patch) | |
| tree | 4b2488315939777ac28016ea95ea1c3794f0dc88 /vterm-module.c | |
| parent | 9d6a1ea521a6c779ec09e16db8a76a2bdf7e5ae8 (diff) | |
Improve performance by rendering consecutive parts of output text
Diffstat (limited to 'vterm-module.c')
| -rw-r--r-- | vterm-module.c | 77 |
1 files changed, 57 insertions, 20 deletions
diff --git a/vterm-module.c b/vterm-module.c index de8b0ce..32f7526 100644 --- a/vterm-module.c +++ b/vterm-module.c @@ -1,6 +1,7 @@ #include "vterm-module.h" #include <fcntl.h> #include <pty.h> +#include <stdbool.h> #include <stdio.h> #include <string.h> #include <sys/ioctl.h> @@ -66,31 +67,33 @@ static emacs_value list(emacs_env *env, emacs_value *elements, ptrdiff_t len) { return env->funcall(env, Flist, len, elements); } -static emacs_value propertize(emacs_env *env, emacs_value string, - emacs_value prop, emacs_value properties) { - emacs_value Fpropertize = env->intern(env, "propertize"); +static void put_text_property(emacs_env *env, emacs_value string, + emacs_value property, emacs_value value) { + emacs_value Fput_text_property = env->intern(env, "put-text-property"); + emacs_value start = env->make_integer(env, 0); + emacs_value end = string_length(env, string); - return env->funcall(env, Fpropertize, 3, - (emacs_value[]){string, prop, properties}); + env->funcall(env, Fput_text_property, 5, + (emacs_value[]){start, end, property, value, string}); } /* * Color must be a string #RGB */ -static emacs_value render_cell(emacs_env *env, VTermScreenCell cell) { - char c = cell.chars[0] == '\0' ? ' ' : cell.chars[0]; - emacs_value character = env->make_string(env, &c, 1); +static emacs_value render_text(emacs_env *env, char *buffer, int len, + VTermScreenCell *cell) { + emacs_value text = env->make_string(env, buffer, len); emacs_value t = env->intern(env, "t"); emacs_value nil = env->intern(env, "nil"); - emacs_value foreground = color_to_rgb_string(env, cell.fg); - emacs_value background = color_to_rgb_string(env, cell.bg); - emacs_value bold = cell.attrs.bold ? t : nil; - emacs_value underline = cell.attrs.underline ? t : nil; - emacs_value italic = cell.attrs.italic ? t : nil; - emacs_value reverse = cell.attrs.reverse ? t : nil; - emacs_value strike = cell.attrs.strike ? t : nil; + emacs_value foreground = color_to_rgb_string(env, cell->fg); + emacs_value background = color_to_rgb_string(env, cell->bg); + emacs_value bold = cell->attrs.bold ? t : nil; + emacs_value underline = cell->attrs.underline ? t : nil; + emacs_value italic = cell->attrs.italic ? t : nil; + emacs_value reverse = cell->attrs.reverse ? t : nil; + emacs_value strike = cell->attrs.strike ? t : nil; // TODO: Blink, font, dwl, dhl is missing emacs_value Qforeground = env->intern(env, ":foreground"); @@ -108,7 +111,9 @@ static emacs_value render_cell(emacs_env *env, VTermScreenCell cell) { Qreverse, reverse, Qstrike, strike}, 14); - return propertize(env, character, Qface, properties); + put_text_property(env, text, Qface, properties); + + return text; } static void byte_to_hex(uint8_t byte, char *hex) { @@ -142,6 +147,22 @@ static void goto_char(emacs_env *env, int pos) { env->funcall(env, Fgoto_char, 1, (emacs_value[]){point}); } +static bool compare_cells(VTermScreenCell *a, VTermScreenCell *b) { + bool equal = true; + equal = equal && (a->fg.red == b->fg.red); + equal = equal && (a->fg.green == b->fg.green); + equal = equal && (a->fg.blue == b->fg.blue); + equal = equal && (a->bg.red == b->bg.red); + equal = equal && (a->bg.green == b->bg.green); + equal = equal && (a->bg.blue == b->bg.blue); + equal = equal && (a->attrs.bold == b->attrs.bold); + equal = equal && (a->attrs.underline == b->attrs.underline); + equal = equal && (a->attrs.italic == b->attrs.italic); + equal = equal && (a->attrs.reverse == b->attrs.reverse); + equal = equal && (a->attrs.strike == b->attrs.strike); + return equal; +} + static void vterm_redraw(VTerm *vt, emacs_env *env) { int i, j; int rows, cols; @@ -150,18 +171,34 @@ static void vterm_redraw(VTerm *vt, emacs_env *env) { erase_buffer(env); + char buffer[rows * cols]; + int length = 0; + VTermScreenCell cell; + VTermScreenCell lastCell; + VTermPos first = {.row = 0, .col = 0}; + vterm_screen_get_cell(screen, first, &lastCell); + for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { VTermPos pos = {.row = i, .col = j}; - VTermScreenCell cell; vterm_screen_get_cell(screen, pos, &cell); - emacs_value character = render_cell(env, cell); - insert(env, character); + if (!compare_cells(&cell, &lastCell)) { + emacs_value text = render_text(env, buffer, length, &lastCell); + insert(env, text); + length = 0; + } + + lastCell = cell; + buffer[length] = cell.chars[0] == '\0' ? ' ' : cell.chars[0]; + length++; } - insert(env, env->make_string(env, "\n", 1)); + buffer[length] = '\n'; + length++; } + emacs_value text = render_text(env, buffer, length, &lastCell); + insert(env, text); VTermState *state = vterm_obtain_state(vt); VTermPos pos; |
