diff --git a/grid.c b/grid.c index 744dd175..a9d155e0 100644 --- a/grid.c +++ b/grid.c @@ -28,6 +28,7 @@ grid_row_alloc(int cols, bool initialize) { struct row *row = malloc(sizeof(*row)); row->dirty = false; + row->linebreak = false; if (initialize) { row->cells = calloc(cols, sizeof(row->cells[0])); diff --git a/render.c b/render.c index 2c48629b..14c534d0 100644 --- a/render.c +++ b/render.c @@ -1009,17 +1009,16 @@ reflow(struct terminal *term, struct row **new_grid, int new_cols, int new_rows, /* Walk current line of the old grid */ for (int c = 0; c < old_cols; c++) { - const struct cell *old_cell = &old_row->cells[c]; - - if (old_cell->wc == 0) { + if (old_row->cells[c].wc == 0) { empty_count++; continue; } - assert(old_cell->wc != 0); - - /* Non-empty cell. Emit preceeding string of empty cells, - * and possibly line break for current cell */ + int old_cols_left = old_cols - c; + int cols_needed = empty_count + old_cols_left; + int new_cols_left = new_cols - new_col_idx; + 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++) { if (new_col_idx >= new_cols) { @@ -1036,32 +1035,30 @@ reflow(struct terminal *term, struct row **new_grid, int new_cols, int new_rows, new_row->dirty = true; } + assert(new_row != NULL); + assert(new_col_idx >= 0); + assert(new_col_idx < new_cols); + + const struct cell *old_cell = &old_row->cells[c - empty_count + i]; + + if (new_col_idx == 0 && new_row_idx > 0 && + (new_grid[new_row_idx - 1]->cells[new_cols - 1].wc == 0 || + old_cell->wc == 0)) + { + new_grid[new_row_idx - 1]->linebreak = true; + } + + new_row->cells[new_col_idx] = *old_cell; + new_row->cells[new_col_idx].attrs.clean = 1; new_col_idx++; } 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 last cell of the old grid's line is empty, then we - * insert a linebreak in the new grid's line too. Unless, the - * *entire* old line was empty. - */ + if (old_row->linebreak) { + new_row->linebreak = true; - 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_row_idx = (new_row_idx + 1) & (new_rows - 1); @@ -1237,19 +1234,12 @@ maybe_resize(struct terminal *term, int width, int height, bool force) while (cursor_row < 0) cursor_row += term->grid->num_rows; - /* Heuristic to prevent a new prompt from being printed a new line */ - bool do_linefeed = false; - if (term->cursor.point.col > 0) - cursor_row--; - else if (cursor_row >= term->rows) - do_linefeed = true; - term_cursor_to( term, min(max(cursor_row, 0), term->rows - 1), min(term->cursor.point.col, term->cols - 1)); - if (do_linefeed) + if (cursor_row >= term->rows) term_linefeed(term); term->render.last_cursor.cell = NULL; diff --git a/selection.c b/selection.c index f1485f45..189119d9 100644 --- a/selection.c +++ b/selection.c @@ -213,7 +213,7 @@ extract_one(struct terminal *term, struct row *row, struct cell *cell, if (ctx->last_row != NULL && row != ctx->last_row && ((term->selection.kind == SELECTION_NORMAL && - (ctx->last_cell->wc == 0 || ctx->last_cell->attrs.linefeed)) || + ctx->last_row->linebreak) || term->selection.kind == SELECTION_BLOCK)) { /* Last cell was the last column in the selection */ diff --git a/terminal.c b/terminal.c index cb52a416..b2fb9233 100644 --- a/terminal.c +++ b/terminal.c @@ -1253,6 +1253,7 @@ static inline void erase_line(struct terminal *term, struct row *row) { erase_cell_range(term, row, 0, term->cols - 1); + row->linebreak = false; } void @@ -1498,17 +1499,13 @@ term_scroll_reverse(struct terminal *term, int rows) void 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); } void term_linefeed(struct terminal *term) { + term->grid->cur_row->linebreak = true; if (term->cursor.point.row == term->scroll_region.end - 1) term_scroll(term, 1); else diff --git a/terminal.h b/terminal.h index 449a1329..1d19c9d7 100644 --- a/terminal.h +++ b/terminal.h @@ -42,8 +42,7 @@ struct attributes { uint32_t have_fg:1; uint32_t have_bg:1; uint32_t selected:2; - uint32_t linefeed:1; - uint32_t reserved:2; + uint32_t reserved:3; uint32_t bg:24; }; static_assert(sizeof(struct attributes) == 8, "bad size"); @@ -84,6 +83,7 @@ struct damage { struct row { struct cell *cells; bool dirty; + bool linebreak; }; struct grid {