Merge branch 'text-reflow-fixes'

This commit is contained in:
Daniel Eklöf 2020-02-15 19:00:18 +01:00
commit a089d6264d
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
5 changed files with 53 additions and 56 deletions

1
grid.c
View file

@ -28,6 +28,7 @@ grid_row_alloc(int cols, bool initialize)
{ {
struct row *row = malloc(sizeof(*row)); struct row *row = malloc(sizeof(*row));
row->dirty = false; row->dirty = false;
row->linebreak = false;
if (initialize) { if (initialize) {
row->cells = calloc(cols, sizeof(row->cells[0])); row->cells = calloc(cols, sizeof(row->cells[0]));

View file

@ -16,8 +16,10 @@
#define LOG_MODULE "render" #define LOG_MODULE "render"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "log.h" #include "log.h"
#include "shm.h" #include "config.h"
#include "grid.h" #include "grid.h"
#include "selection.h"
#include "shm.h"
#define min(x, y) ((x) < (y) ? (x) : (y)) #define min(x, y) ((x) < (y) ? (x) : (y))
#define max(x, y) ((x) > (y) ? (x) : (y)) #define max(x, y) ((x) > (y) ? (x) : (y))
@ -981,7 +983,6 @@ reflow(struct terminal *term, struct row **new_grid, int new_cols, int new_rows,
assert(new_row == NULL); assert(new_row == NULL);
new_row = grid_row_alloc(new_cols, true); new_row = grid_row_alloc(new_cols, true);
new_row->dirty = true;
new_grid[new_row_idx] = new_row; new_grid[new_row_idx] = new_row;
/* Start at the beginning of the old grid's scrollback. That is, /* Start at the beginning of the old grid's scrollback. That is,
@ -1009,20 +1010,33 @@ reflow(struct terminal *term, struct row **new_grid, int new_cols, int new_rows,
/* Walk current line of the old grid */ /* Walk current line of the old grid */
for (int c = 0; c < old_cols; c++) { for (int c = 0; c < old_cols; c++) {
const struct cell *old_cell = &old_row->cells[c]; if (old_row->cells[c].wc == 0) {
if (old_cell->wc == 0) {
empty_count++; empty_count++;
continue; continue;
} }
assert(old_cell->wc != 0); int old_cols_left = old_cols - c;
int cols_needed = empty_count + old_cols_left;
/* Non-empty cell. Emit preceeding string of empty cells, int new_cols_left = new_cols - new_col_idx;
* and possibly line break for current cell */ if (new_cols_left < cols_needed && new_cols_left >= old_cols_left)
empty_count = max(0, empty_count - (cols_needed - new_cols_left));
for (int i = 0; i < empty_count + 1; i++) { for (int i = 0; i < empty_count + 1; i++) {
const struct cell *old_cell = &old_row->cells[c - empty_count + i];
/* Out of columns on current row in new grid? */
if (new_col_idx >= new_cols) { if (new_col_idx >= new_cols) {
/*
* If last cell on last row and first cell on new
* row are non-empty, wrap the line, otherwise
* insert a hard line break.
*/
if (new_row->cells[new_cols - 1].wc == 0 ||
old_cell->wc == 0)
{
new_row->linebreak = true;
}
new_col_idx = 0; new_col_idx = 0;
new_row_idx = (new_row_idx + 1) & (new_rows - 1); new_row_idx = (new_row_idx + 1) & (new_rows - 1);
@ -1030,38 +1044,27 @@ reflow(struct terminal *term, struct row **new_grid, int new_cols, int new_rows,
if (new_row == NULL) { if (new_row == NULL) {
new_row = grid_row_alloc(new_cols, true); new_row = grid_row_alloc(new_cols, true);
new_grid[new_row_idx] = new_row; new_grid[new_row_idx] = new_row;
} else } else {
memset(new_row->cells, 0, new_cols * sizeof(new_row->cells[0])); memset(new_row->cells, 0, new_cols * sizeof(new_row->cells[0]));
new_row->linebreak = false;
new_row->dirty = true; }
} }
assert(new_row != NULL);
assert(new_col_idx >= 0);
assert(new_col_idx < new_cols);
new_row->cells[new_col_idx] = *old_cell;
new_row->cells[new_col_idx].attrs.clean = 1;
new_col_idx++; new_col_idx++;
} }
empty_count = 0; empty_count = 0;
new_col_idx--;
assert(new_row != NULL);
assert(new_col_idx >= 0);
assert(new_col_idx < new_cols);
/* Copy current cell */
new_row->cells[new_col_idx].attrs.clean = 1;
new_row->cells[new_col_idx++] = *old_cell;
} }
/* if (old_row->linebreak) {
* If last cell of the old grid's line is empty, then we new_row->linebreak = true;
* insert a linebreak in the new grid's line too. Unless, the
* *entire* old line was empty.
*/
if (empty_count < old_cols &&
//r < old_rows - 1 &&
(old_row->cells[old_cols - 1].wc == 0 ||
old_row->cells[old_cols - 1].attrs.linefeed))
{
new_col_idx = 0; new_col_idx = 0;
new_row_idx = (new_row_idx + 1) & (new_rows - 1); new_row_idx = (new_row_idx + 1) & (new_rows - 1);
@ -1069,10 +1072,10 @@ reflow(struct terminal *term, struct row **new_grid, int new_cols, int new_rows,
if (new_row == NULL) { if (new_row == NULL) {
new_row = grid_row_alloc(new_cols, true); new_row = grid_row_alloc(new_cols, true);
new_grid[new_row_idx] = new_row; new_grid[new_row_idx] = new_row;
} else } else {
memset(new_row->cells, 0, new_cols * sizeof(new_row->cells[0])); memset(new_row->cells, 0, new_cols * sizeof(new_row->cells[0]));
new_row->linebreak = false;
new_row->dirty = true; }
} }
} }
@ -1108,6 +1111,8 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
if (!force && width == term->width && height == term->height && scale == term->scale) if (!force && width == term->width && height == term->height && scale == term->scale)
return; return;
selection_cancel(term);
/* Cancel an application initiated "Synchronized Update" */ /* Cancel an application initiated "Synchronized Update" */
term_disable_app_sync_updates(term); term_disable_app_sync_updates(term);
@ -1153,8 +1158,8 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
/* Reset offset such that the last copied row ends up at the /* Reset offset such that the last copied row ends up at the
* bottom of the screen */ * bottom of the screen */
term->normal.offset = last_normal_row - new_rows; term->normal.offset = last_normal_row - new_rows + 1;
term->alt.offset = last_alt_row - new_rows; term->alt.offset = last_alt_row - new_rows + 1;
/* Can't have negative offsets, so wrap 'em */ /* Can't have negative offsets, so wrap 'em */
while (term->normal.offset < 0) while (term->normal.offset < 0)
@ -1168,6 +1173,7 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
while (alt[term->alt.offset] == NULL) while (alt[term->alt.offset] == NULL)
term->alt.offset = (term->alt.offset + 1) & (new_alt_grid_rows - 1); term->alt.offset = (term->alt.offset + 1) & (new_alt_grid_rows - 1);
/* TODO: try to keep old view */
term->normal.view = term->normal.offset; term->normal.view = term->normal.offset;
term->alt.view = term->alt.offset; term->alt.view = term->alt.offset;
@ -1237,21 +1243,14 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
while (cursor_row < 0) while (cursor_row < 0)
cursor_row += term->grid->num_rows; cursor_row += term->grid->num_rows;
/* Heuristic to prevent a new prompt from being printed a new line */ assert(cursor_row >= 0);
bool do_linefeed = false; assert(cursor_row < term->rows);
if (term->cursor.point.col > 0)
cursor_row--;
else if (cursor_row >= term->rows)
do_linefeed = true;
term_cursor_to( term_cursor_to(
term, term,
min(max(cursor_row, 0), term->rows - 1), cursor_row,
min(term->cursor.point.col, term->cols - 1)); min(term->cursor.point.col, term->cols - 1));
if (do_linefeed)
term_linefeed(term);
term->render.last_cursor.cell = NULL; term->render.last_cursor.cell = NULL;
tll_free(term->normal.scroll_damage); tll_free(term->normal.scroll_damage);
tll_free(term->alt.scroll_damage); tll_free(term->alt.scroll_damage);

View file

@ -213,7 +213,7 @@ extract_one(struct terminal *term, struct row *row, struct cell *cell,
if (ctx->last_row != NULL && row != ctx->last_row && if (ctx->last_row != NULL && row != ctx->last_row &&
((term->selection.kind == SELECTION_NORMAL && ((term->selection.kind == SELECTION_NORMAL &&
(ctx->last_cell->wc == 0 || ctx->last_cell->attrs.linefeed)) || ctx->last_row->linebreak) ||
term->selection.kind == SELECTION_BLOCK)) term->selection.kind == SELECTION_BLOCK))
{ {
/* Last cell was the last column in the selection */ /* Last cell was the last column in the selection */

View file

@ -1090,8 +1090,8 @@ term_reset(struct terminal *term, bool hard)
term->normal.offset = term->normal.view = 0; term->normal.offset = term->normal.view = 0;
term->alt.offset = term->alt.view = 0; term->alt.offset = term->alt.view = 0;
for (size_t i = 0; i < term->rows; i++) { for (size_t i = 0; i < term->rows; i++) {
memset(grid_row_and_alloc(&term->normal, i)->cells, 0, term->cols * sizeof(struct cell)); term->normal.rows[i] = grid_row_alloc(term->cols, true);
memset(grid_row_and_alloc(&term->alt, i)->cells, 0, term->cols * sizeof(struct cell)); term->alt.rows[i] = grid_row_alloc(term->cols, true);
} }
for (size_t i = term->rows; i < term->normal.num_rows; i++) { for (size_t i = term->rows; i < term->normal.num_rows; i++) {
grid_row_free(term->normal.rows[i]); grid_row_free(term->normal.rows[i]);
@ -1253,6 +1253,7 @@ static inline void
erase_line(struct terminal *term, struct row *row) erase_line(struct terminal *term, struct row *row)
{ {
erase_cell_range(term, row, 0, term->cols - 1); erase_cell_range(term, row, 0, term->cols - 1);
row->linebreak = false;
} }
void void
@ -1498,17 +1499,13 @@ term_scroll_reverse(struct terminal *term, int rows)
void void
term_formfeed(struct terminal *term) term_formfeed(struct terminal *term)
{ {
int col = term->cursor.point.col;
if (!term->cursor.lcf)
col--;
if (col >= 0)
term->grid->cur_row->cells[col].attrs.linefeed = 1;
term_cursor_left(term, term->cursor.point.col); term_cursor_left(term, term->cursor.point.col);
} }
void void
term_linefeed(struct terminal *term) term_linefeed(struct terminal *term)
{ {
term->grid->cur_row->linebreak = true;
if (term->cursor.point.row == term->scroll_region.end - 1) if (term->cursor.point.row == term->scroll_region.end - 1)
term_scroll(term, 1); term_scroll(term, 1);
else else

View file

@ -42,8 +42,7 @@ struct attributes {
uint32_t have_fg:1; uint32_t have_fg:1;
uint32_t have_bg:1; uint32_t have_bg:1;
uint32_t selected:2; uint32_t selected:2;
uint32_t linefeed:1; uint32_t reserved:3;
uint32_t reserved:2;
uint32_t bg:24; uint32_t bg:24;
}; };
static_assert(sizeof(struct attributes) == 8, "bad size"); static_assert(sizeof(struct attributes) == 8, "bad size");
@ -84,6 +83,7 @@ struct damage {
struct row { struct row {
struct cell *cells; struct cell *cells;
bool dirty; bool dirty;
bool linebreak;
}; };
struct grid { struct grid {