summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-13 14:27:58 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-13 14:27:58 +0300
commit5ab6b560e8528c27ba934b90f94b1828b7771e27 (patch)
tree409c2a2e864529ccda0ff3e3b75b0280279e2a33 /src
parent7633ab2c60b40bd5aa67ef391b2a0d149685742f (diff)
Encapsulate stream queue context and consolidate forwarding wrappers
- Create struct stream_emit_ctx packing stream queue arguments into 1 cache line - Reduce emit_stream_bulk_wrapped from 13 parameters to 3 - Reduce flush_stream_queue from 10 parameters to 1 - Extract stream_queue_finish to eliminate duplicated cleanup in kernel instantiations - Replace EMIT_STREAM_ROW macros with typed inline functions - Move pending_wrap clearing directly into term_screen_erase, insert, delete, and scroll - Remove sc_erase_display, sc_erase_line, sc_insert_chars, and sc_delete_chars wrappers - Consolidate term_row and remove duplicated row_fill_gap helper
Diffstat (limited to 'src')
-rw-r--r--src/core.c439
-rw-r--r--src/core.h28
-rw-r--r--src/escape.c8
-rw-r--r--src/fastcsi.c12
-rw-r--r--src/screen.c7
-rw-r--r--src/screen.h23
6 files changed, 249 insertions, 268 deletions
diff --git a/src/core.c b/src/core.c
index 5d50db9..fcd73d0 100644
--- a/src/core.c
+++ b/src/core.c
@@ -91,7 +91,7 @@ void term_sc_print_glyph(struct term *t, uint32_t cp, int width, uint16_t flags)
int right = t->lr_margin_mode ? t->right_margin : cols - 1;
if (TERM_EXPECT(width == 2 && cols > 1 && cx == right && t->autowrap, 0)) {
- row_fill_gap(t, p, row, cx);
+ term_row_fill_gap(srow, cx);
clear_wide_edges(row, cx, right + 1, srow->len);
row[cx] = (struct cell){ ' ', TERM_COLOR_FG, TERM_COLOR_BG, CELL_WRAP_PAD, 0 };
srow->len = (uint16_t)cols;
@@ -113,7 +113,7 @@ void term_sc_print_glyph(struct term *t, uint32_t cp, int width, uint16_t flags)
} else {
flags &= ~CELL_WIDE;
}
- row_fill_gap(t, p, row, cx);
+ term_row_fill_gap(srow, cx);
if (TERM_EXPECT(t->insert_mode, 0)) {
if (cx == srow->len)
row[cx] = (struct cell){ ' ', TERM_COLOR_FG, TERM_COLOR_BG, 0, 0 };
@@ -333,13 +333,11 @@ void term_sc_tab(struct term *t, int n)
void term_sc_scroll_region(struct term *t, int top, int bottom, int n, bool down)
{
- t->pending_wrap = false;
term_screen_scroll_region(t, top, bottom, n, down, false);
}
void term_sc_scroll(struct term *t, int n, bool down)
{
- t->pending_wrap = false;
term_screen_scroll_region(t, t->scroll_top, t->scroll_bottom, n, down, true);
}
@@ -587,67 +585,100 @@ static void flush_orig_rows(struct term *t, struct screen *s,
}
}
-static void flush_stream_queue(struct term *t, struct screen *s,
- struct hist_ascii_line *q, int *q_count, int q_cap,
- int *orig_y, int *orig_rem, size_t *flushed_scrolled,
- const struct pen_attr *attr, bool def_pen)
+struct stream_emit_ctx {
+ struct term *term;
+ struct screen *screen;
+ struct hist_ascii_line *q;
+ const struct pen_attr *attr;
+ size_t flushed_scrolled;
+ int q_cap;
+ int q_count;
+ int orig_y;
+ int orig_rem;
+ int cols;
+ bool def_pen;
+};
+
+static void flush_stream_queue(struct stream_emit_ctx *ctx)
{
- if (*orig_rem > 0)
- flush_orig_rows(t, s, orig_y, orig_rem, *orig_rem);
- int flush_n = *q_count - q_cap;
- (void)def_pen;
- term_hist_push_ascii_lines(&t->hist, q, flush_n, attr);
- if (q_cap > 0) {
- if (flush_n >= q_cap)
- memcpy(q, q + flush_n, (size_t)q_cap * sizeof(q[0]));
+ if (ctx->orig_rem > 0)
+ flush_orig_rows(ctx->term, ctx->screen, &ctx->orig_y, &ctx->orig_rem, ctx->orig_rem);
+ int flush_n = ctx->q_count - ctx->q_cap;
+ (void)ctx->def_pen;
+ term_hist_push_ascii_lines(&ctx->term->hist, ctx->q, flush_n, ctx->attr);
+ if (ctx->q_cap > 0) {
+ if (flush_n >= ctx->q_cap)
+ memcpy(ctx->q, ctx->q + flush_n, (size_t)ctx->q_cap * sizeof(ctx->q[0]));
else
- memmove(q, q + flush_n, (size_t)q_cap * sizeof(q[0]));
+ memmove(ctx->q, ctx->q + flush_n, (size_t)ctx->q_cap * sizeof(ctx->q[0]));
}
- *q_count = q_cap;
- *flushed_scrolled += (size_t)flush_n;
+ ctx->q_count = ctx->q_cap;
+ ctx->flushed_scrolled += (size_t)flush_n;
}
-static inline void emit_stream_bulk_wrapped(struct term *t, struct screen *s,
- const char *src, int bulk_lines, int cols,
- const struct pen_attr *attr, bool def_pen,
- struct hist_ascii_line *q, int q_cap,
- int *q_count, int *orig_y, int *orig_rem,
- size_t *flushed_scrolled)
+static inline void emit_stream_bulk_wrapped(struct stream_emit_ctx *ctx,
+ const char *src, int bulk_lines)
{
+ struct term *t = ctx->term;
+ struct screen *s = ctx->screen;
+ int cols = ctx->cols;
if (TERM_EXPECT(t->pending_wrap, 0)) {
row_set_wrapped(screen_get_row(s, s->rows - 1), true);
t->pending_wrap = false;
t->cursor_x = 0;
term_screen_scroll_up(t);
}
- if (bulk_lines < q_cap) {
+ if (bulk_lines < ctx->q_cap) {
const char *p = src;
for (int r = 0; r < bulk_lines; r++, p += cols) {
- if (*q_count == 256) {
- flush_stream_queue(t, s, q, q_count, q_cap, orig_y, orig_rem,
- flushed_scrolled, attr, def_pen);
+ if (ctx->q_count == 256) {
+ flush_stream_queue(ctx);
}
- q[(*q_count)++] = (struct hist_ascii_line){ p, (uint16_t)cols, 1 };
+ ctx->q[ctx->q_count++] = (struct hist_ascii_line){ p, (uint16_t)cols, 1 };
}
return;
}
- if (*orig_rem > 0)
- flush_orig_rows(t, s, orig_y, orig_rem, *orig_rem);
- if (*q_count > 0) {
- term_hist_push_ascii_lines(&t->hist, q, *q_count, attr);
- *flushed_scrolled += (size_t)*q_count;
- *q_count = 0;
+ if (ctx->orig_rem > 0)
+ flush_orig_rows(t, s, &ctx->orig_y, &ctx->orig_rem, ctx->orig_rem);
+ if (ctx->q_count > 0) {
+ term_hist_push_ascii_lines(&t->hist, ctx->q, ctx->q_count, ctx->attr);
+ ctx->flushed_scrolled += (size_t)ctx->q_count;
+ ctx->q_count = 0;
}
- int hist_rows = bulk_lines - q_cap;
+ int hist_rows = bulk_lines - ctx->q_cap;
if (hist_rows > 0) {
- term_hist_push_ascii(&t->hist, src, hist_rows * cols, attr, true);
- *flushed_scrolled += (size_t)hist_rows;
+ term_hist_push_ascii(&t->hist, src, hist_rows * cols, ctx->attr, true);
+ ctx->flushed_scrolled += (size_t)hist_rows;
}
const char *sp = src + (size_t)hist_rows * (size_t)cols;
- for (int r = 0; r < q_cap; r++, sp += cols)
- q[r] = (struct hist_ascii_line){ sp, (uint16_t)cols, 1 };
- *q_count = q_cap;
+ for (int r = 0; r < ctx->q_cap; r++, sp += cols)
+ ctx->q[r] = (struct hist_ascii_line){ sp, (uint16_t)cols, 1 };
+ ctx->q_count = ctx->q_cap;
+}
+
+static inline TERM_ALWAYS_INLINE void emit_stream_row_fast(struct stream_emit_ctx *ctx,
+ const char *row_ptr,
+ int row_len, bool row_wrapped)
+{
+ if (TERM_EXPECT(ctx->q_count == 256, 0))
+ flush_stream_queue(ctx);
+ ctx->q[ctx->q_count++] = (struct hist_ascii_line){
+ row_ptr, (uint16_t)row_len, (uint8_t)row_wrapped
+ };
+}
+
+static inline TERM_ALWAYS_INLINE void emit_stream_row(struct stream_emit_ctx *ctx,
+ const char *row_ptr,
+ int row_len, bool row_wrapped)
+{
+ if (TERM_EXPECT(ctx->term->pending_wrap, 0)) {
+ row_set_wrapped(screen_get_row(ctx->screen, ctx->screen->rows - 1), true);
+ ctx->term->pending_wrap = false;
+ ctx->term->cursor_x = 0;
+ term_screen_scroll_up(ctx->term);
+ }
+ emit_stream_row_fast(ctx, row_ptr, row_len, row_wrapped);
}
static TERM_NOINLINE size_t stream_ascii_wrapped(struct term *t, const char *buf, size_t len)
@@ -877,6 +908,140 @@ static inline uint64_t line_masks(const char *buf, uint64_t *nl)
return controls;
}
+static void stream_queue_finish(struct stream_emit_ctx *ctx)
+{
+ int cols = ctx->cols;
+ size_t queued_rows = 0;
+ for (int j = 0; j < ctx->q_count; j++)
+ queued_rows += ctx->q[j].wrapped ? 1 : rows_narrow(ctx->q[j].len, cols);
+ size_t loop_scrolled = ctx->flushed_scrolled + queued_rows;
+ if (loop_scrolled == 0)
+ return;
+
+ struct term *t = ctx->term;
+ struct screen *s = ctx->screen;
+ int rows = s->rows;
+
+ int push_orig = queued_rows < (size_t)ctx->orig_rem ? (int)queued_rows : ctx->orig_rem;
+ if (push_orig > 0)
+ flush_orig_rows(t, s, &ctx->orig_y, &ctx->orig_rem, push_orig);
+
+ int needed = rows - 1 - ctx->orig_rem;
+ int tail_rows = 0;
+ int k = ctx->q_count;
+ while (k > 0 && tail_rows < needed) {
+ k--;
+ struct hist_ascii_line pr = ctx->q[k];
+ int r = (pr.wrapped || pr.len == 0) ? 1 : (int)rows_narrow(pr.len, cols);
+ tail_rows += r;
+ }
+
+ int flush_n = k;
+ if (flush_n > 0) {
+ term_hist_push_ascii_lines(&t->hist, ctx->q, flush_n, ctx->attr);
+ }
+
+ int skip_rows = tail_rows - needed;
+ if (skip_rows > 0) {
+ struct hist_ascii_line pr = ctx->q[k];
+ int skip_bytes = skip_rows * cols;
+ if (skip_bytes > (int)pr.len) skip_bytes = (int)pr.len;
+ term_hist_push_ascii(&t->hist, pr.ptr, skip_bytes, ctx->attr, true);
+ }
+
+ if (ctx->orig_rem == 0) {
+ s->top = 0;
+ } else {
+ s->top += tail_rows;
+ if (s->top >= rows)
+ s->top -= rows;
+ }
+ /* Rows that stay on the screen become text rows. A row that
+ * continues the row above starts from its pen. */
+ int cur_y = ctx->orig_rem;
+ bool prev_wrapped = false;
+ for (int j = k; j < ctx->q_count && cur_y < rows - 1; j++) {
+ struct hist_ascii_line pr = ctx->q[j];
+ int p_len = pr.len;
+ const char *p_ptr = pr.ptr;
+
+ if (p_len == 0) {
+ int p = phys_row(t, cur_y);
+ struct srow *dst = &s->slot[p];
+ dst->uid = ++t->next_row_uid;
+ dst->version++;
+ uint8_t tail_padded = (dst->kind == ROW_CELLS && dst->len == 0)
+ ? (dst->flags & RF_TAIL_PADDED) : 0;
+ dst->kind = ROW_CELLS;
+ dst->len = 0;
+ dst->flags = tail_padded;
+ prev_wrapped = false;
+ cur_y++;
+ continue;
+ }
+
+ int off_in_line = 0;
+ if (j == k && skip_rows > 0) {
+ off_in_line = skip_rows * cols;
+ prev_wrapped = true;
+ }
+
+ while (off_in_line < p_len && cur_y < rows - 1) {
+ int chunk = p_len - off_in_line;
+ bool row_wraps = false;
+ if (chunk > cols) {
+ chunk = cols;
+ row_wraps = true;
+ } else if (pr.wrapped && off_in_line + chunk == p_len) {
+ row_wraps = true;
+ }
+
+ int p = phys_row(t, cur_y);
+ struct srow *dst = &s->slot[p];
+ dst->uid = ++t->next_row_uid;
+ dst->version++;
+
+ struct pen_attr start = prev_wrapped ? *ctx->attr : pen_attr_default();
+ dst->kind = ROW_TEXT;
+ dst->len = 0;
+ dst->flags = row_wraps ? RF_WRAPPED : 0;
+ text_row_start(&dst->text, &start);
+ dst->text.text = dst->ascii;
+ text_append(dst, (const uint8_t *)(p_ptr + off_in_line),
+ chunk, chunk, chunk, HLINE_NARROW,
+ ctx->attr->fg, ctx->attr->bg, pen_sl(ctx->attr));
+
+ prev_wrapped = row_wraps;
+ off_in_line += chunk;
+ cur_y++;
+ }
+ }
+ while (cur_y < rows - 1) {
+ int p = phys_row(t, cur_y);
+ struct srow *dst = &s->slot[p];
+ dst->uid = ++t->next_row_uid;
+ dst->version++;
+ dst->kind = ROW_CELLS;
+ dst->len = 0;
+ dst->flags = 0;
+ cur_y++;
+ }
+ int bot_p = phys_row(t, rows - 1);
+ struct srow *bot = &s->slot[bot_p];
+ uint8_t bot_tail = (bot->kind == ROW_CELLS && bot->len == 0)
+ ? (bot->flags & RF_TAIL_PADDED) : 0;
+ bot->uid = ++t->next_row_uid;
+ bot->version++;
+ bot->kind = ROW_CELLS;
+ bot->len = 0;
+ bot->flags = bot_tail;
+ if (t->prompt_y > 0) {
+ t->prompt_y = (size_t)t->prompt_y > loop_scrolled
+ ? t->prompt_y - (int)loop_scrolled : 0;
+ }
+ clamp_selection_after_scroll(t);
+}
+
/* One body for every level. isa is a constant in each copy below, so each
* copy keeps only its own kernels. */
static inline TERM_ALWAYS_INLINE size_t bulk_ascii_lines_body(struct term *t, const char *buf,
@@ -894,7 +1059,6 @@ static inline TERM_ALWAYS_INLINE size_t bulk_ascii_lines_body(struct term *t, co
bool autowrap = t->autowrap;
bool lnm = term_lnm(t);
int last_char = (int)t->last_char;
- size_t flushed_scrolled = 0;
struct pen_attr attr = {
.fg = t->cur_fg,
@@ -909,29 +1073,19 @@ static inline TERM_ALWAYS_INLINE size_t bulk_ascii_lines_body(struct term *t, co
return 0;
struct hist_ascii_line q[256];
- int q_cap = rows - 1;
- int q_count = 0;
- int orig_y = 0;
- int orig_rem = q_cap;
-
-#define EMIT_STREAM_ROW_FAST(row_ptr, row_len, row_wrapped) do { \
- if (TERM_EXPECT(q_count == 256, 0)) \
- flush_stream_queue(t, s, q, &q_count, q_cap, &orig_y, &orig_rem, \
- &flushed_scrolled, &attr, def_pen); \
- q[q_count++] = (struct hist_ascii_line){ \
- (row_ptr), (uint16_t)(row_len), (uint8_t)(row_wrapped) \
- }; \
-} while (0)
-
-#define EMIT_STREAM_ROW(row_ptr, row_len, row_wrapped) do { \
- if (TERM_EXPECT(t->pending_wrap, 0)) { \
- row_set_wrapped(screen_get_row(s, rows - 1), true); \
- t->pending_wrap = false; \
- t->cursor_x = 0; \
- term_screen_scroll_up(t); \
- } \
- EMIT_STREAM_ROW_FAST(row_ptr, row_len, row_wrapped); \
-} while (0)
+ struct stream_emit_ctx ctx = {
+ .term = t,
+ .screen = s,
+ .q = q,
+ .attr = &attr,
+ .flushed_scrolled = 0,
+ .q_cap = rows - 1,
+ .q_count = 0,
+ .orig_y = 0,
+ .orig_rem = rows - 1,
+ .cols = cols,
+ .def_pen = def_pen,
+ };
while (i < len) {
/* Scan each block once. Keep the unfinished line in the input buffer. */
@@ -953,7 +1107,7 @@ static inline TERM_ALWAYS_INLINE size_t bulk_ascii_lines_body(struct term *t, co
goto narrow_done;
if (end > i)
last_char = (unsigned char)buf[end - 1];
- EMIT_STREAM_ROW_FAST(buf + i, (int)(end - i), false);
+ emit_stream_row_fast(&ctx, buf + i, (int)(end - i), false);
i = end + 1;
nl &= nl - 1;
}
@@ -979,9 +1133,7 @@ narrow_done:
int bulk_lines = run / cols - (run % cols == 0);
if (bulk_lines > 0 && autowrap && (i + run == len || ((unsigned char)buf[i + run] >= 0x20 && (unsigned char)buf[i + run] < 0x7f) || (run % cols == 0))) {
- emit_stream_bulk_wrapped(t, s, buf + i, bulk_lines, cols, &attr, def_pen,
- q, q_cap, &q_count, &orig_y, &orig_rem,
- &flushed_scrolled);
+ emit_stream_bulk_wrapped(&ctx, buf + i, bulk_lines);
size_t write_cells = (size_t)bulk_lines * (size_t)cols;
last_char = (unsigned char)buf[i + write_cells - 1];
i += write_cells;
@@ -998,7 +1150,7 @@ narrow_done:
if (eol > 0) {
last_char = (unsigned char)buf[i + limit - 1];
- EMIT_STREAM_ROW_FAST(buf + i, limit, false);
+ emit_stream_row_fast(&ctx, buf + i, limit, false);
i += (size_t)(limit + eol);
continue;
}
@@ -1008,7 +1160,7 @@ narrow_done:
(unsigned char)buf[i + limit - 1]);
if (!wrapped) break;
last_char = (unsigned char)buf[i + limit - 1];
- EMIT_STREAM_ROW_FAST(buf + i, limit, true);
+ emit_stream_row_fast(&ctx, buf + i, limit, true);
i += (size_t)limit;
continue;
}
@@ -1030,7 +1182,7 @@ narrow_done:
if (p1 > 0)
last_char = (unsigned char)buf[i + p1 - 1];
- EMIT_STREAM_ROW_FAST(buf + i, p1, false);
+ emit_stream_row_fast(&ctx, buf + i, p1, false);
int next_start = p1 + eol1;
int last_consumed = next_start;
@@ -1051,7 +1203,7 @@ narrow_done:
if (eol2 > 0) {
if (rel_p2 > 0)
last_char = (unsigned char)buf[i + p2 - 1];
- EMIT_STREAM_ROW_FAST(buf + i + next_start, rel_p2, false);
+ emit_stream_row_fast(&ctx, buf + i + next_start, rel_p2, false);
int next_start2 = p2 + eol2;
last_consumed = next_start2;
@@ -1072,7 +1224,7 @@ narrow_done:
if (eol3 > 0) {
if (rel_p3 > 0)
last_char = (unsigned char)buf[i + p3 - 1];
- EMIT_STREAM_ROW_FAST(buf + i + next_start2, rel_p3, false);
+ emit_stream_row_fast(&ctx, buf + i + next_start2, rel_p3, false);
last_consumed = p3 + eol3;
}
@@ -1101,7 +1253,7 @@ narrow_done:
if (TERM_EXPECT(eol > 0, 1)) {
if (run > 0)
last_char = (unsigned char)buf[i + run - 1];
- EMIT_STREAM_ROW(buf + i, run, false);
+ emit_stream_row(&ctx, buf + i, run, false);
i += (size_t)(run + eol);
continue;
}
@@ -1109,7 +1261,7 @@ narrow_done:
if (!run) {
int neol = newline_bytes(buf + i, len - i);
if (neol == 2 || (neol == 1 && lnm)) {
- EMIT_STREAM_ROW(buf + i, 0, false);
+ emit_stream_row(&ctx, buf + i, 0, false);
i += (size_t)neol;
continue;
}
@@ -1128,150 +1280,23 @@ narrow_done:
((unsigned char)buf[i + full] >= 0x20 &&
(unsigned char)buf[i + full] < 0x7f) ||
full % cols == 0)) {
- emit_stream_bulk_wrapped(t, s, buf + i, bulk_lines, cols, &attr, def_pen,
- q, q_cap, &q_count, &orig_y, &orig_rem,
- &flushed_scrolled);
+ emit_stream_bulk_wrapped(&ctx, buf + i, bulk_lines);
size_t write_cells = (size_t)bulk_lines * (size_t)cols;
last_char = (unsigned char)buf[i + write_cells - 1];
i += write_cells;
continue;
}
last_char = (unsigned char)buf[i + run - 1];
- EMIT_STREAM_ROW(buf + i, run, true);
+ emit_stream_row(&ctx, buf + i, run, true);
i += (size_t)run;
}
-#undef EMIT_STREAM_ROW
-#undef EMIT_STREAM_ROW_FAST
#if defined(TERM_KERNEL_AVX512)
done:
#endif
if (i == 0)
return 0;
- size_t queued_rows = 0;
- for (int j = 0; j < q_count; j++)
- queued_rows += q[j].wrapped ? 1 : rows_narrow(q[j].len, cols);
- size_t loop_scrolled = flushed_scrolled + queued_rows;
- if (loop_scrolled > 0) {
- int push_orig = queued_rows < (size_t)orig_rem ? (int)queued_rows : orig_rem;
- if (push_orig > 0)
- flush_orig_rows(t, s, &orig_y, &orig_rem, push_orig);
-
- int needed = rows - 1 - orig_rem;
- int tail_rows = 0;
- int k = q_count;
- while (k > 0 && tail_rows < needed) {
- k--;
- struct hist_ascii_line pr = q[k];
- int r = (pr.wrapped || pr.len == 0) ? 1 : (int)rows_narrow(pr.len, cols);
- tail_rows += r;
- }
-
- int flush_n = k;
- if (flush_n > 0) {
- term_hist_push_ascii_lines(&t->hist, q, flush_n, &attr);
- }
-
- int skip_rows = tail_rows - needed;
- if (skip_rows > 0) {
- struct hist_ascii_line pr = q[k];
- int skip_bytes = skip_rows * cols;
- if (skip_bytes > (int)pr.len) skip_bytes = (int)pr.len;
- term_hist_push_ascii(&t->hist, pr.ptr, skip_bytes, &attr, true);
- }
-
- if (orig_rem == 0) {
- s->top = 0;
- } else {
- s->top += tail_rows;
- if (s->top >= rows)
- s->top -= rows;
- }
- /* Rows that stay on the screen become text rows. A row that
- * continues the row above starts from its pen. */
- int cur_y = orig_rem;
- bool prev_wrapped = false;
- for (int j = k; j < q_count && cur_y < rows - 1; j++) {
- struct hist_ascii_line pr = q[j];
- int p_len = pr.len;
- const char *p_ptr = pr.ptr;
-
- if (p_len == 0) {
- int p = phys_row(t, cur_y);
- struct srow *dst = &s->slot[p];
- dst->uid = ++t->next_row_uid;
- dst->version++;
- uint8_t tail_padded = (dst->kind == ROW_CELLS && dst->len == 0)
- ? (dst->flags & RF_TAIL_PADDED) : 0;
- dst->kind = ROW_CELLS;
- dst->len = 0;
- dst->flags = tail_padded;
- prev_wrapped = false;
- cur_y++;
- continue;
- }
-
- int off_in_line = 0;
- if (j == k && skip_rows > 0) {
- off_in_line = skip_rows * cols;
- prev_wrapped = true;
- }
-
- while (off_in_line < p_len && cur_y < rows - 1) {
- int chunk = p_len - off_in_line;
- bool row_wraps = false;
- if (chunk > cols) {
- chunk = cols;
- row_wraps = true;
- } else if (pr.wrapped && off_in_line + chunk == p_len) {
- row_wraps = true;
- }
-
- int p = phys_row(t, cur_y);
- struct srow *dst = &s->slot[p];
- dst->uid = ++t->next_row_uid;
- dst->version++;
-
- struct pen_attr start = prev_wrapped ? attr : pen_attr_default();
- dst->kind = ROW_TEXT;
- dst->len = 0;
- dst->flags = row_wraps ? RF_WRAPPED : 0;
- text_row_start(&dst->text, &start);
- dst->text.text = dst->ascii;
- text_append(dst, (const uint8_t *)(p_ptr + off_in_line),
- chunk, chunk, chunk, HLINE_NARROW,
- attr.fg, attr.bg, pen_sl(&attr));
-
- prev_wrapped = row_wraps;
- off_in_line += chunk;
- cur_y++;
- }
- }
- while (cur_y < rows - 1) {
- int p = phys_row(t, cur_y);
- struct srow *dst = &s->slot[p];
- dst->uid = ++t->next_row_uid;
- dst->version++;
- dst->kind = ROW_CELLS;
- dst->len = 0;
- dst->flags = 0;
- cur_y++;
- }
- int bot_p = phys_row(t, rows - 1);
- struct srow *bot = &s->slot[bot_p];
- uint8_t bot_tail = (bot->kind == ROW_CELLS && bot->len == 0)
- ? (bot->flags & RF_TAIL_PADDED) : 0;
- bot->uid = ++t->next_row_uid;
- bot->version++;
- bot->kind = ROW_CELLS;
- bot->len = 0;
- bot->flags = bot_tail;
- if (t->prompt_y > 0) {
- t->prompt_y = (size_t)t->prompt_y > loop_scrolled
- ? t->prompt_y - (int)loop_scrolled : 0;
- }
- clamp_selection_after_scroll(t);
- }
+ stream_queue_finish(&ctx);
t->last_char = (uint32_t)last_char;
t->cursor_x = 0;
diff --git a/src/core.h b/src/core.h
index 2460938..beec4e0 100644
--- a/src/core.h
+++ b/src/core.h
@@ -103,34 +103,6 @@ static inline void sc_erase_span(struct term *t, int y, int from, int to)
t->scr.slot[p].version++;
}
-/* Erase display mode 0, 1, 2, or 3. */
-static inline void sc_erase_display(struct term *t, int mode)
-{
- t->pending_wrap = false;
- term_screen_erase(t, mode);
-}
-
-/* Erase line mode 0, 1, or 2. */
-static inline void sc_erase_line(struct term *t, int mode)
-{
- t->pending_wrap = false;
- term_screen_erase_line(t, mode);
-}
-
-/* Insert n blank characters at cursor. */
-static inline void sc_insert_chars(struct term *t, int n)
-{
- t->pending_wrap = false;
- term_screen_insert_chars(t, n);
-}
-
-/* Delete n characters at cursor. */
-static inline void sc_delete_chars(struct term *t, int n)
-{
- t->pending_wrap = false;
- term_screen_delete_chars(t, n);
-}
-
/* Scroll margins: top to bottom, n lines up or down. */
void term_sc_scroll_region(struct term *t, int top, int bottom, int n, bool down);
diff --git a/src/escape.c b/src/escape.c
index 9576e8e..fc254af 100644
--- a/src/escape.c
+++ b/src/escape.c
@@ -746,7 +746,7 @@ static inline TERM_ALWAYS_INLINE void dispatch_csi(struct term *t, const struct
}
break;
case 'J':
- sc_erase_display(t, csi->params[0]);
+ term_screen_erase(t, csi->params[0]);
break;
case 'X': {
int n = csi_count(csi);
@@ -759,13 +759,13 @@ static inline TERM_ALWAYS_INLINE void dispatch_csi(struct term *t, const struct
t->decsace = (uint8_t)csi->params[0];
break;
case 'K':
- sc_erase_line(t, csi->params[0]);
+ term_screen_erase_line(t, csi->params[0]);
break;
case 'P':
- sc_delete_chars(t, csi_count(csi));
+ term_screen_delete_chars(t, csi_count(csi));
break;
case '@':
- sc_insert_chars(t, csi_count(csi));
+ term_screen_insert_chars(t, csi_count(csi));
break;
case 'c': {
if (csi->prefix == '>')
diff --git a/src/fastcsi.c b/src/fastcsi.c
index d8983dc..74d4800 100644
--- a/src/fastcsi.c
+++ b/src/fastcsi.c
@@ -169,13 +169,13 @@ int term_try_fast_csi(struct term *t, const char *buf, size_t rem)
(p[0] >= '0' && p[0] <= '3' && p + 1 < end && p[1] == 'J')) {
t->cur_fg = fg;
t->cur_bg = bg;
- sc_erase_display(t, p[0] == 'J' ? 0 : p[0] - '0');
+ term_screen_erase(t, p[0] == 'J' ? 0 : p[0] - '0');
p += p[0] == 'J' ? 1 : 2;
} else if (p[0] == 'K' ||
(p[0] >= '0' && p[0] <= '2' && p + 1 < end && p[1] == 'K')) {
t->cur_fg = fg;
t->cur_bg = bg;
- sc_erase_line(t, p[0] == 'K' ? 0 : p[0] - '0');
+ term_screen_erase_line(t, p[0] == 'K' ? 0 : p[0] - '0');
p += p[0] == 'K' ? 1 : 2;
} else if (!t->origin_mode && !t->lr_margin_mode &&
((*p >= '0' && *p <= '9') || *p == ';' ||
@@ -279,13 +279,13 @@ int term_try_fast_csi(struct term *t, const char *buf, size_t rem)
case 'J':
t->cur_fg = fg;
t->cur_bg = bg;
- sc_erase_display(t, pv[0]);
+ term_screen_erase(t, pv[0]);
p = q + 1;
break;
case 'K':
t->cur_fg = fg;
t->cur_bg = bg;
- sc_erase_line(t, pv[0]);
+ term_screen_erase_line(t, pv[0]);
p = q + 1;
break;
case 'X':
@@ -298,13 +298,13 @@ int term_try_fast_csi(struct term *t, const char *buf, size_t rem)
case 'P':
t->cur_fg = fg;
t->cur_bg = bg;
- sc_delete_chars(t, n);
+ term_screen_delete_chars(t, n);
p = q + 1;
break;
case '@':
t->cur_fg = fg;
t->cur_bg = bg;
- sc_insert_chars(t, n);
+ term_screen_insert_chars(t, n);
p = q + 1;
break;
case 's':
diff --git a/src/screen.c b/src/screen.c
index afd9b4a..d0f573c 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -324,9 +324,9 @@ void term_screen_erase_line(struct term *t, int mode)
void term_screen_delete_chars(struct term *t, int n)
{
+ t->pending_wrap = false;
if (t->cursor_x >= t->cols)
return;
- t->pending_wrap = false;
int x = t->cursor_x;
int cols = t->cols;
if (n > cols - x)
@@ -365,9 +365,9 @@ void term_screen_delete_chars(struct term *t, int n)
void term_screen_insert_chars(struct term *t, int n)
{
+ t->pending_wrap = false;
if (t->cursor_x >= t->cols)
return;
- t->pending_wrap = false;
int x = t->cursor_x;
int cols = t->cols;
if (n > cols - x)
@@ -407,6 +407,7 @@ void term_screen_insert_chars(struct term *t, int n)
void term_screen_erase_all(struct term *t)
{
+ t->pending_wrap = false;
struct screen *s = &t->scr;
bool pristine = using_default_colors(t);
for (int y = 0; y < s->rows; y++) {
@@ -544,6 +545,7 @@ static inline bool srow_has_text(const struct srow *r, int cols)
void term_screen_erase(struct term *t, int mode)
{
+ t->pending_wrap = false;
if (mode == 3) {
term_hist_clear(&t->hist);
term_hist_view_clear(&t->view);
@@ -667,6 +669,7 @@ static void rotate_and_clear_srows(struct term *t, struct srow *base, int height
void term_screen_scroll_region(struct term *t, int top, int bottom, int count,
bool down, bool history)
{
+ t->pending_wrap = false;
if (count <= 0 || top > bottom || top < 0 || bottom >= t->rows)
return;
int height = bottom - top + 1;
diff --git a/src/screen.h b/src/screen.h
index 50e18c6..8498e9d 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -161,15 +161,7 @@ static inline struct srow *screen_row_at(const struct screen *s, int y)
static inline struct srow *term_row(const struct term *t, int y)
{
- int p = t->scr.top + y;
- struct srow *row = &t->scr.slot[p >= t->scr.rows ? p - t->scr.rows : p];
- srow_materialize_text(row);
- return row;
-}
-
-static inline struct srow *term_screen_row(const struct term *t, int y)
-{
- return term_row(t, y);
+ return screen_get_row(&t->scr, y);
}
/* Write the cells of a text row to out: its text, then its fill blanks.
@@ -361,17 +353,6 @@ static inline void mark_row_blank(struct term *t, int p, uint32_t fg, uint32_t b
(void)bg;
}
-static inline void row_fill_gap(struct term *t, int p, struct cell *row, int x)
-{
- struct screen *s = term_active_screen(t);
- struct srow *r = &s->slot[p];
- if (x > r->len) {
- if (!(r->flags & RF_TAIL_PADDED))
- fill_cells(row + r->len, x - r->len, TERM_COLOR_FG, TERM_COLOR_BG);
- r->len = (uint16_t)x;
- }
-}
-
static inline void term_row_fill_gap(struct srow *row, int x)
{
if (x > row->len) {
@@ -413,7 +394,7 @@ static inline void erase_span(struct term *t, int p, int from, int to)
row_set_wrapped(row, false);
if (!pristine) {
- row_fill_gap(t, p, cells, from);
+ term_row_fill_gap(row, from);
fill_cells(cells + from, to - from, t->cur_fg, t->cur_bg);
if (to > len) {
row->len = (uint16_t)to;