diff --git a/csi.c b/csi.c index d16f4aa7..6a3477dd 100644 --- a/csi.c +++ b/csi.c @@ -297,7 +297,7 @@ csi_dispatch(struct terminal *term, uint8_t final) if (row > term->grid.rows) row = term->grid.rows; - grid_cursor_to(&term->grid, row - 1, term->grid.cursor.col); + term_cursor_to(term, row - 1, term->grid.cursor.col); break; } @@ -305,20 +305,20 @@ csi_dispatch(struct terminal *term, uint8_t final) return csi_sgr(term); case 'A': - grid_cursor_up(&term->grid, param_get(term, 0, 1)); + term_cursor_up(term, param_get(term, 0, 1)); break; case 'e': case 'B': - grid_cursor_down(&term->grid, param_get(term, 0, 1)); + term_cursor_down(term, param_get(term, 0, 1)); break; case 'C': - grid_cursor_right(&term->grid, param_get(term, 0, 1)); + term_cursor_right(term, param_get(term, 0, 1)); break; case 'D': - grid_cursor_left(&term->grid, param_get(term, 0, 1)); + term_cursor_left(term, param_get(term, 0, 1)); break; case 'G': { @@ -328,7 +328,7 @@ csi_dispatch(struct terminal *term, uint8_t final) if (col > term->grid.cols) col = term->grid.cols; - grid_cursor_to(&term->grid, term->grid.cursor.row, col); + term_cursor_to(term, term->grid.cursor.row, col); break; } @@ -342,7 +342,7 @@ csi_dispatch(struct terminal *term, uint8_t final) if (col > term->grid.cols) col = term->grid.cols; - grid_cursor_to(&term->grid, row - 1, col - 1); + term_cursor_to(term, row - 1, col - 1); break; } @@ -376,7 +376,7 @@ csi_dispatch(struct terminal *term, uint8_t final) return false; } - grid_erase(&term->grid, start, end); + term_erase(term, start, end); break; } @@ -390,23 +390,19 @@ csi_dispatch(struct terminal *term, uint8_t final) case 0: /* From cursor to end of line */ start = term->grid.linear_cursor; - end = grid_cursor_linear( - &term->grid, term->grid.cursor.row, term->grid.cols); + end = term_cursor_linear(term, term->grid.cursor.row, term->grid.cols); break; case 1: /* From start of line to cursor */ - start = grid_cursor_linear( - &term->grid, term->grid.cursor.row, 0); + start = term_cursor_linear(term, term->grid.cursor.row, 0); end = term->grid.linear_cursor; break; case 2: /* Entire line */ - start = grid_cursor_linear( - &term->grid, term->grid.cursor.row, 0); - end = grid_cursor_linear( - &term->grid, term->grid.cursor.row, term->grid.cols); + start = term_cursor_linear(term, term->grid.cursor.row, 0); + end = term_cursor_linear(term, term->grid.cursor.row, term->grid.cols); break; default: @@ -414,7 +410,7 @@ csi_dispatch(struct terminal *term, uint8_t final) return false; } - grid_erase(&term->grid, start, end); + term_erase(term, start, end); break; } @@ -427,8 +423,8 @@ csi_dispatch(struct terminal *term, uint8_t final) param_get(term, 0, 1), term->grid.scroll_region.end - term->grid.cursor.row); - grid_scroll_reverse_partial( - &term->grid, + term_scroll_reverse_partial( + term, (struct scroll_region){ .start = term->grid.cursor.row, .end = term->grid.scroll_region.end}, @@ -445,8 +441,8 @@ csi_dispatch(struct terminal *term, uint8_t final) param_get(term, 0, 1), term->grid.scroll_region.end - term->grid.cursor.row); - grid_scroll_partial( - &term->grid, + term_scroll_partial( + term, (struct scroll_region){ .start = term->grid.cursor.row, .end = term->grid.scroll_region.end}, @@ -459,21 +455,21 @@ csi_dispatch(struct terminal *term, uint8_t final) int count = param_get(term, 0, 1); /* Only delete up to the right margin */ - const int max_end = grid_cursor_linear( - &term->grid, term->grid.cursor.row, term->grid.cols); + const int max_end = term_cursor_linear( + term, term->grid.cursor.row, term->grid.cols); int start = term->grid.linear_cursor; int end = min(start + count, max_end); /* Erase the requested number of characters */ - grid_erase(&term->grid, start, end); + term_erase(term, start, end); /* Move remaining (up til the right margin) characters */ int remaining = max_end - end; memmove(&term->grid.cells[start], &term->grid.cells[end], remaining * sizeof(term->grid.cells[0])); - grid_damage_update(&term->grid, term->grid.linear_cursor, remaining); + term_damage_update(term, term->grid.linear_cursor, remaining); break; } @@ -591,7 +587,7 @@ csi_dispatch(struct terminal *term, uint8_t final) term->grid.alt_saved_cursor.row = term->grid.cursor.row; term->grid.alt_saved_cursor.col = term->grid.cursor.col; - grid_damage_all(&term->grid); + term_damage_all(term); } break; @@ -646,14 +642,14 @@ csi_dispatch(struct terminal *term, uint8_t final) term->grid.cursor.row = term->grid.alt_saved_cursor.row; term->grid.cursor.col = term->grid.alt_saved_cursor.col; - term->grid.linear_cursor = grid_cursor_linear( - &term->grid, term->grid.cursor.row, term->grid.cursor.col); + term->grid.linear_cursor = term_cursor_linear( + term, term->grid.cursor.row, term->grid.cursor.col); /* Should these be restored from saved values? */ term->grid.scroll_region.start = 0; term->grid.scroll_region.end = term->grid.rows; - grid_damage_all(&term->grid); + term_damage_all(term); } break; diff --git a/grid.c b/grid.c index a6ed618b..67f6e57a 100644 --- a/grid.c +++ b/grid.c @@ -6,306 +6,3 @@ #define LOG_MODULE "grid" #define LOG_ENABLE_DBG 1 #include "log.h" - -#define min(x, y) ((x) < (y) ? (x) : (y)) -#define max(x, y) ((x) > (y) ? (x) : (y)) - -static bool -damage_merge_range(struct grid *grid, const struct damage *dmg) -{ - if (tll_length(grid->damage) == 0) - return false; - - struct damage *old = &tll_back(grid->damage); - if (old->type != dmg->type) - return false; - - const int start = dmg->range.start; - const int end = start + dmg->range.length; - - const int prev_start = old->range.start; - const int prev_end = prev_start + old->range.length; - - if ((start >= prev_start && start <= prev_end) || - (end >= prev_start && end <= prev_end) || - (start <= prev_start && end >= prev_end)) - { - /* The two damage ranges intersect */ - int new_start = min(start, prev_start); - int new_end = max(end, prev_end); - - old->range.start = new_start; - old->range.length = new_end - new_start; - - assert(old->range.start >= 0); - assert(old->range.start < grid->rows * grid->cols); - assert(old->range.length >= 0); - assert(old->range.start + old->range.length <= grid->rows * grid->cols); - return true; - } - - return false; -} - -static void -grid_damage_update_or_erase(struct grid *grid, enum damage_type damage_type, - int start, int length) -{ - struct damage dmg = { - .type = damage_type, - .range = {.start = start, .length = length}, - }; - - assert(dmg.range.start >= 0); - assert(dmg.range.start < grid->rows * grid->cols); - assert(dmg.range.length >= 0); - assert(dmg.range.start + dmg.range.length <= grid->rows * grid->cols); - - if (damage_merge_range(grid, &dmg)) - return; - - tll_push_back(grid->damage, dmg); -} - -void -grid_damage_update(struct grid *grid, int start, int length) -{ - grid_damage_update_or_erase(grid, DAMAGE_UPDATE, start, length); -} - -void -grid_damage_erase(struct grid *grid, int start, int length) -{ - grid_damage_update_or_erase(grid, DAMAGE_ERASE, start, length); -} - -void -grid_damage_all(struct grid *grid) -{ - tll_free(grid->damage); - tll_free(grid->scroll_damage); - grid_damage_update(grid, 0, grid->rows * grid->cols); -} - -static void -damage_adjust_after_scroll(struct grid *grid, enum damage_type damage_type, - struct scroll_region region, int lines) -{ - const int adjustment - = lines * grid->cols * (damage_type == DAMAGE_SCROLL_REVERSE ? -1 : 1); - - const int scroll_start = region.start * grid->cols; - const int scroll_end = region.end * grid->cols; - - tll_foreach(grid->damage, it) { - int start = it->item.range.start; - int length = it->item.range.length; - int end = start + length; - - if (start < scroll_start && end > scroll_start) { - /* Start outside, end either inside or on the other side */ - struct damage outside = { - .type = it->item.type, - .range = {.start = start, .length = scroll_start - start}, - }; - - tll_push_back(grid->damage, outside); - start = scroll_start; - length = end - start; - - } - - if (start < scroll_end && end > scroll_end) { - /* End outside, start either inside or on the other side */ - struct damage outside = { - .type = it->item.type, - .range = {.start = scroll_end, .length = length - scroll_end}, - }; - - tll_push_back(grid->damage, outside); - end = scroll_end; - length = end - start; - } - - if (start >= scroll_start && end <= scroll_end) { - /* Completely inside scroll region */ - start -= adjustment; - it->item.range.start = start; - - if (start < scroll_start) { - /* Scrolled up outside scroll region */ - int new_length = length - (scroll_start - start); - assert(new_length < length); - - if (new_length <= 0) - tll_remove(grid->damage, it); - else { - it->item.range.start = scroll_start; - it->item.range.length = new_length; - } - } - - if (start + length > scroll_end) { - /* Scrolled down outside scroll region */ - if (start >= scroll_end) - tll_remove(grid->damage, it); - else { - it->item.range.start = start; - it->item.range.length = scroll_end - start; - } - } - } - } -} - -void -grid_damage_scroll(struct grid *grid, enum damage_type damage_type, - struct scroll_region region, int lines) -{ - damage_adjust_after_scroll(grid, damage_type, region, lines); - - if (tll_length(grid->scroll_damage) > 0) { - struct damage *dmg = &tll_back(grid->scroll_damage); - - if (dmg->type == damage_type && - dmg->scroll.region.start == region.start && - dmg->scroll.region.end == region.end) - { - dmg->scroll.lines += lines; - return; - } - } - struct damage dmg = { - .type = damage_type, - .scroll = {.region = region, .lines = lines}, - }; - tll_push_back(grid->scroll_damage, dmg); -} - -void -grid_erase(struct grid *grid, int start, int end) -{ - assert(end >= start); - memset(&grid->cells[start], 0, (end - start) * sizeof(grid->cells[0])); - grid_damage_erase(grid, start, end - start); -} - -int -grid_cursor_linear(const struct grid *grid, int row, int col) -{ - return row * grid->cols + col; -} - -void -grid_cursor_to(struct grid *grid, int row, int col) -{ - assert(row >= 0); - assert(row < grid->rows); - assert(col >= 0); - assert(col < grid->cols); - - int new_linear = row * grid->cols + col; - assert(new_linear >= 0); - assert(new_linear < grid->rows * grid->cols); - - grid_damage_update(grid, grid->linear_cursor, 1); - grid_damage_update(grid, new_linear, 1); - grid->print_needs_wrap = false; - - grid->linear_cursor = new_linear; - grid->cursor.col = col; - grid->cursor.row = row; -} - -void -grid_cursor_left(struct grid *grid, int count) -{ - int move_amount = min(grid->cursor.col, count); - grid_cursor_to(grid, grid->cursor.row, grid->cursor.col - move_amount); -} - -void -grid_cursor_right(struct grid *grid, int count) -{ - int move_amount = min(grid->cols - grid->cursor.col - 1, count); - grid_cursor_to(grid, grid->cursor.row, grid->cursor.col + move_amount); -} - -void -grid_cursor_up(struct grid *grid, int count) -{ - int move_amount = min(grid->cursor.row, count); - grid_cursor_to(grid, grid->cursor.row - move_amount, grid->cursor.col); -} - -void -grid_cursor_down(struct grid *grid, int count) -{ - int move_amount = min(grid->rows - grid->cursor.row - 1, count); - grid_cursor_to(grid, grid->cursor.row + move_amount, grid->cursor.col); -} - -void -grid_scroll_partial(struct grid *grid, struct scroll_region region, int rows) -{ - if (rows >= region.end - region.start) { - assert(false && "untested"); - return; - } - - int cell_dst = (region.start + 0) * grid->cols; - int cell_src = (region.start + rows) * grid->cols; - int cell_count = (region.end - region.start - rows) * grid->cols; - - LOG_DBG("moving %d lines from row %d to row %d", cell_count / grid->cols, - cell_src / grid->cols, cell_dst / grid->cols); - - const size_t bytes = cell_count * sizeof(grid->cells[0]); - memmove( - &grid->cells[cell_dst], &grid->cells[cell_src], - bytes); - - memset(&grid->cells[(region.end - rows) * grid->cols], 0, - rows * grid->cols * sizeof(grid->cells[0])); - - grid_damage_scroll(grid, DAMAGE_SCROLL, region, rows); -} - -void -grid_scroll(struct grid *grid, int rows) -{ - grid_scroll_partial(grid, grid->scroll_region, rows); -} - -void -grid_scroll_reverse_partial(struct grid *grid, - struct scroll_region region, int rows) -{ - if (rows >= region.end - region.start) { - assert(false && "todo"); - return; - } - - int cell_dst = (region.start + rows) * grid->cols; - int cell_src = (region.start + 0) * grid->cols; - int cell_count = (region.end - region.start - rows) * grid->cols; - - LOG_DBG("moving %d lines from row %d to row %d", cell_count / grid->cols, - cell_src / grid->cols, cell_dst / grid->cols); - - const size_t bytes = cell_count * sizeof(grid->cells[0]); - memmove( - &grid->cells[cell_dst], &grid->cells[cell_src], - bytes); - - memset(&grid->cells[cell_src], 0, - rows * grid->cols * sizeof(grid->cells[0])); - - grid_damage_scroll(grid, DAMAGE_SCROLL_REVERSE, region, rows); -} - -void -grid_scroll_reverse(struct grid *grid, int rows) -{ - grid_scroll_reverse_partial(grid, grid->scroll_region, rows); -} diff --git a/grid.h b/grid.h index 4854582d..580ef343 100644 --- a/grid.h +++ b/grid.h @@ -1,32 +1,3 @@ #pragma once #include "terminal.h" - -void grid_damage_all(struct grid *grid); -void grid_damage_update(struct grid *grid, int start, int length); -void grid_damage_erase(struct grid *grid, int start, int length); -void grid_damage_scroll( - struct grid *grid, enum damage_type damage_type, - struct scroll_region region, int lines); - -void grid_erase(struct grid *grid, int start, int end); - -void grid_cursor_to(struct grid *grid, int row, int col); -void grid_cursor_left(struct grid *grid, int count); -void grid_cursor_right(struct grid *grid, int count); -void grid_cursor_up(struct grid *grid, int count); -void grid_cursor_down(struct grid *grid, int count); - -void grid_scroll(struct grid *grid, int rows); -void grid_scroll_reverse(struct grid *grid, int rows); - -void grid_scroll_partial( - struct grid *grid, struct scroll_region region, int rows); -void grid_scroll_reverse_partial( - struct grid *grid, struct scroll_region region, int rows); - -int grid_cursor_linear(const struct grid *grid, int row, int col); - - -//void grid_cursor_to(struct grid *grid, int pos); -//void grid_cursor_move(struct grid *grid, int cols); diff --git a/main.c b/main.c index 0dea3f64..3e673967 100644 --- a/main.c +++ b/main.c @@ -470,7 +470,7 @@ resize(struct context *c, int width, int height) if (c->term.grid.scroll_region.end == old_rows) c->term.grid.scroll_region.end = c->term.grid.rows; - grid_damage_all(&c->term.grid); + term_damage_all(&c->term); if (!c->frame_is_scheduled) grid_render(c); diff --git a/meson.build b/meson.build index 05b05a10..a997301b 100644 --- a/meson.build +++ b/meson.build @@ -67,7 +67,7 @@ executable( 'osc.c', 'osc.h', 'shm.c', 'shm.h', 'slave.c', 'slave.h', - 'terminal.h', + 'terminal.c', 'terminal.h', 'tllist.h', 'vt.c', 'vt.h', wl_proto_src + wl_proto_headers, diff --git a/terminal.c b/terminal.c new file mode 100644 index 00000000..61e9d04c --- /dev/null +++ b/terminal.c @@ -0,0 +1,311 @@ +#include "terminal.h" + +#include +#include + +#define LOG_MODULE "terminal" +#define LOG_ENABLE_DBG 1 +#include "log.h" + +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define max(x, y) ((x) > (y) ? (x) : (y)) + +static bool +damage_merge_range(struct terminal *term, const struct damage *dmg) +{ + if (tll_length(term->grid.damage) == 0) + return false; + + struct damage *old = &tll_back(term->grid.damage); + if (old->type != dmg->type) + return false; + + const int start = dmg->range.start; + const int end = start + dmg->range.length; + + const int prev_start = old->range.start; + const int prev_end = prev_start + old->range.length; + + if ((start >= prev_start && start <= prev_end) || + (end >= prev_start && end <= prev_end) || + (start <= prev_start && end >= prev_end)) + { + /* The two damage ranges intersect */ + int new_start = min(start, prev_start); + int new_end = max(end, prev_end); + + old->range.start = new_start; + old->range.length = new_end - new_start; + + assert(old->range.start >= 0); + assert(old->range.start < term->grid.rows * term->grid.cols); + assert(old->range.length >= 0); + assert(old->range.start + old->range.length <= term->grid.rows * term->grid.cols); + return true; + } + + return false; +} + +static void +term_damage_update_or_erase(struct terminal *term, enum damage_type damage_type, + int start, int length) +{ + struct damage dmg = { + .type = damage_type, + .range = {.start = start, .length = length}, + }; + + assert(dmg.range.start >= 0); + assert(dmg.range.start < term->grid.rows * term->grid.cols); + assert(dmg.range.length >= 0); + assert(dmg.range.start + dmg.range.length <= term->grid.rows * term->grid.cols); + + if (damage_merge_range(term, &dmg)) + return; + + tll_push_back(term->grid.damage, dmg); +} + +void +term_damage_update(struct terminal *term, int start, int length) +{ + term_damage_update_or_erase(term, DAMAGE_UPDATE, start, length); +} + +void +term_damage_erase(struct terminal *term, int start, int length) +{ + term_damage_update_or_erase(term, DAMAGE_ERASE, start, length); +} + +void +term_damage_all(struct terminal *term) +{ + tll_free(term->grid.damage); + tll_free(term->grid.scroll_damage); + term_damage_update(term, 0, term->grid.rows * term->grid.cols); +} + +static void +damage_adjust_after_scroll(struct terminal *term, enum damage_type damage_type, + struct scroll_region region, int lines) +{ + const int adjustment + = lines * term->grid.cols * (damage_type == DAMAGE_SCROLL_REVERSE ? -1 : 1); + + const int scroll_start = region.start * term->grid.cols; + const int scroll_end = region.end * term->grid.cols; + + tll_foreach(term->grid.damage, it) { + int start = it->item.range.start; + int length = it->item.range.length; + int end = start + length; + + if (start < scroll_start && end > scroll_start) { + /* Start outside, end either inside or on the other side */ + struct damage outside = { + .type = it->item.type, + .range = {.start = start, .length = scroll_start - start}, + }; + + tll_push_back(term->grid.damage, outside); + start = scroll_start; + length = end - start; + + } + + if (start < scroll_end && end > scroll_end) { + /* End outside, start either inside or on the other side */ + struct damage outside = { + .type = it->item.type, + .range = {.start = scroll_end, .length = length - scroll_end}, + }; + + tll_push_back(term->grid.damage, outside); + end = scroll_end; + length = end - start; + } + + if (start >= scroll_start && end <= scroll_end) { + /* Completely inside scroll region */ + start -= adjustment; + it->item.range.start = start; + + if (start < scroll_start) { + /* Scrolled up outside scroll region */ + int new_length = length - (scroll_start - start); + assert(new_length < length); + + if (new_length <= 0) + tll_remove(term->grid.damage, it); + else { + it->item.range.start = scroll_start; + it->item.range.length = new_length; + } + } + + if (start + length > scroll_end) { + /* Scrolled down outside scroll region */ + if (start >= scroll_end) + tll_remove(term->grid.damage, it); + else { + it->item.range.start = start; + it->item.range.length = scroll_end - start; + } + } + } + } +} + +void +term_damage_scroll(struct terminal *term, enum damage_type damage_type, + struct scroll_region region, int lines) +{ + damage_adjust_after_scroll(term, damage_type, region, lines); + + if (tll_length(term->grid.scroll_damage) > 0) { + struct damage *dmg = &tll_back(term->grid.scroll_damage); + + if (dmg->type == damage_type && + dmg->scroll.region.start == region.start && + dmg->scroll.region.end == region.end) + { + dmg->scroll.lines += lines; + return; + } + } + struct damage dmg = { + .type = damage_type, + .scroll = {.region = region, .lines = lines}, + }; + tll_push_back(term->grid.scroll_damage, dmg); +} + +void +term_erase(struct terminal *term, int start, int end) +{ + assert(end >= start); + memset(&term->grid.cells[start], 0, (end - start) * sizeof(term->grid.cells[0])); + term_damage_erase(term, start, end - start); +} + +int +term_cursor_linear(const struct terminal *term, int row, int col) +{ + return row * term->grid.cols + col; +} + +void +term_cursor_to(struct terminal *term, int row, int col) +{ + assert(row >= 0); + assert(row < term->grid.rows); + assert(col >= 0); + assert(col < term->grid.cols); + + int new_linear = row * term->grid.cols + col; + assert(new_linear >= 0); + assert(new_linear < term->grid.rows * term->grid.cols); + + term_damage_update(term, term->grid.linear_cursor, 1); + term_damage_update(term, new_linear, 1); + term->grid.print_needs_wrap = false; + + term->grid.linear_cursor = new_linear; + term->grid.cursor.col = col; + term->grid.cursor.row = row; +} + +void +term_cursor_left(struct terminal *term, int count) +{ + int move_amount = min(term->grid.cursor.col, count); + term_cursor_to(term, term->grid.cursor.row, term->grid.cursor.col - move_amount); +} + +void +term_cursor_right(struct terminal *term, int count) +{ + int move_amount = min(term->grid.cols - term->grid.cursor.col - 1, count); + term_cursor_to(term, term->grid.cursor.row, term->grid.cursor.col + move_amount); +} + +void +term_cursor_up(struct terminal *term, int count) +{ + int move_amount = min(term->grid.cursor.row, count); + term_cursor_to(term, term->grid.cursor.row - move_amount, term->grid.cursor.col); +} + +void +term_cursor_down(struct terminal *term, int count) +{ + int move_amount = min(term->grid.rows - term->grid.cursor.row - 1, count); + term_cursor_to(term, term->grid.cursor.row + move_amount, term->grid.cursor.col); +} + +void +term_scroll_partial(struct terminal *term, struct scroll_region region, int rows) +{ + if (rows >= region.end - region.start) { + assert(false && "untested"); + return; + } + + int cell_dst = (region.start + 0) * term->grid.cols; + int cell_src = (region.start + rows) * term->grid.cols; + int cell_count = (region.end - region.start - rows) * term->grid.cols; + + LOG_DBG("moving %d lines from row %d to row %d", cell_count / term->grid.cols, + cell_src / term->grid.cols, cell_dst / term->grid.cols); + + const size_t bytes = cell_count * sizeof(term->grid.cells[0]); + memmove( + &term->grid.cells[cell_dst], &term->grid.cells[cell_src], + bytes); + + memset(&term->grid.cells[(region.end - rows) * term->grid.cols], 0, + rows * term->grid.cols * sizeof(term->grid.cells[0])); + + term_damage_scroll(term, DAMAGE_SCROLL, region, rows); +} + +void +term_scroll(struct terminal *term, int rows) +{ + term_scroll_partial(term, term->grid.scroll_region, rows); +} + +void +term_scroll_reverse_partial(struct terminal *term, + struct scroll_region region, int rows) +{ + if (rows >= region.end - region.start) { + assert(false && "todo"); + return; + } + + int cell_dst = (region.start + rows) * term->grid.cols; + int cell_src = (region.start + 0) * term->grid.cols; + int cell_count = (region.end - region.start - rows) * term->grid.cols; + + LOG_DBG("moving %d lines from row %d to row %d", cell_count / term->grid.cols, + cell_src / term->grid.cols, cell_dst / term->grid.cols); + + const size_t bytes = cell_count * sizeof(term->grid.cells[0]); + memmove( + &term->grid.cells[cell_dst], &term->grid.cells[cell_src], + bytes); + + memset(&term->grid.cells[cell_src], 0, + rows * term->grid.cols * sizeof(term->grid.cells[0])); + + term_damage_scroll(term, DAMAGE_SCROLL_REVERSE, region, rows); +} + +void +term_scroll_reverse(struct terminal *term, int rows) +{ + term_scroll_reverse_partial(term, term->grid.scroll_region, rows); +} diff --git a/terminal.h b/terminal.h index 86845c2d..1a2fe8af 100644 --- a/terminal.h +++ b/terminal.h @@ -143,10 +143,37 @@ enum keypad_mode { KEYPAD_NUMERICAL, KEYPAD_APPLICATION }; struct terminal { pid_t slave; int ptmx; + enum decckm decckm; enum keypad_mode keypad_mode; bool bracketed_paste; + struct vt vt; struct grid grid; struct kbd kbd; }; + +void term_damage_all(struct terminal *term); +void term_damage_update(struct terminal *term, int start, int length); +void term_damage_erase(struct terminal *term, int start, int length); +void term_damage_scroll( + struct terminal *term, enum damage_type damage_type, + struct scroll_region region, int lines); + +void term_erase(struct terminal *term, int start, int end); + +void term_cursor_to(struct terminal *term, int row, int col); +void term_cursor_left(struct terminal *term, int count); +void term_cursor_right(struct terminal *term, int count); +void term_cursor_up(struct terminal *term, int count); +void term_cursor_down(struct terminal *term, int count); + +void term_scroll(struct terminal *term, int rows); +void term_scroll_reverse(struct terminal *term, int rows); + +void term_scroll_partial( + struct terminal *term, struct scroll_region region, int rows); +void term_scroll_reverse_partial( + struct terminal *term, struct scroll_region region, int rows); + +int term_cursor_linear(const struct terminal *term, int row, int col); diff --git a/vt.c b/vt.c index 9c3ba1aa..842ae3f2 100644 --- a/vt.c +++ b/vt.c @@ -590,7 +590,7 @@ esc_dispatch(struct terminal *term, uint8_t final) case 'M': /* ri - reverse index (scroll reverse) */ - grid_scroll_reverse(&term->grid, 1); + term_scroll_reverse(term, 1); break; case '=': @@ -627,19 +627,19 @@ action(struct terminal *term, enum action action, uint8_t c) case '\n': /* LF - line feed */ if (term->grid.cursor.row == term->grid.scroll_region.end - 1) { - grid_scroll(&term->grid, 1); + term_scroll(term, 1); } else - grid_cursor_down(&term->grid, 1); + term_cursor_down(term, 1); break; case '\r': /* FF - form feed */ - grid_cursor_left(&term->grid, term->grid.cursor.col); + term_cursor_left(term, term->grid.cursor.col); break; case '\b': /* backspace */ - grid_cursor_left(&term->grid, 1); + term_cursor_left(term, 1); break; case '\x07': @@ -651,7 +651,7 @@ action(struct terminal *term, enum action action, uint8_t c) /* HT - horizontal tab */ int col = term->grid.cursor.col; col = (col + 8) / 8 * 8; - grid_cursor_right(&term->grid, col - term->grid.cursor.col); + term_cursor_right(term, col - term->grid.cursor.col); break; } @@ -672,14 +672,14 @@ action(struct terminal *term, enum action action, uint8_t c) case ACTION_PRINT: { if (term->grid.print_needs_wrap) { if (term->grid.cursor.row == term->grid.scroll_region.end - 1) { - grid_scroll(&term->grid, 1); - grid_cursor_to(&term->grid, term->grid.cursor.row, 0); + term_scroll(term, 1); + term_cursor_to(term, term->grid.cursor.row, 0); } else - grid_cursor_to(&term->grid, term->grid.cursor.row + 1, 0); + term_cursor_to(term, term->grid.cursor.row + 1, 0); } struct cell *cell = &term->grid.cells[term->grid.linear_cursor]; - grid_damage_update(&term->grid, term->grid.linear_cursor, 1); + term_damage_update(term, term->grid.linear_cursor, 1); if (term->vt.utf8.idx > 0) { //LOG_DBG("print: UTF8: %.*s", (int)term->vt.utf8.idx, term->vt.utf8.data); @@ -695,7 +695,7 @@ action(struct terminal *term, enum action action, uint8_t c) cell->attrs = term->vt.attrs; if (term->grid.cursor.col < term->grid.cols - 1) - grid_cursor_right(&term->grid, 1); + term_cursor_right(term, 1); else term->grid.print_needs_wrap = true;