From 54e2b0b005347810571a44b1ad64f9c14cf56e92 Mon Sep 17 00:00:00 2001 From: Max Hollmann Date: Wed, 15 Jul 2020 09:53:13 +0200 Subject: [PATCH 1/8] limit font size to non-negative values --- terminal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terminal.c b/terminal.c index 40bfbc90..84c9d459 100644 --- a/terminal.c +++ b/terminal.c @@ -1430,7 +1430,7 @@ term_font_size_adjust(struct terminal *term, double amount) old_pt_size = term->font_sizes[i].px_size * 72. / dpi; } - term->font_sizes[i].pt_size = old_pt_size + amount; + term->font_sizes[i].pt_size = fmax(old_pt_size + amount, 0); term->font_sizes[i].px_size = -1; } From 5ae45c3b45e13104ce344940d37f5848cc88d9e2 Mon Sep 17 00:00:00 2001 From: Max Hollmann Date: Wed, 15 Jul 2020 11:05:22 +0200 Subject: [PATCH 2/8] added font-size limitting to changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fb27893..b06dc6bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -105,6 +105,8 @@ * A multi-column character that does not fit on the current line is now printed on the next line, instead of only printing half the character. +* Font size can no longer be reduced to negative values + (https://codeberg.org/dnkl/foot/issues/38). ### Security From 6183f7f64a10465b429f70c713102ced2e0517bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 16 Jul 2020 07:41:51 +0200 Subject: [PATCH 3/8] vt: utf8: handle multi-column spacer values correctly when combining --- vt.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/vt.c b/vt.c index 618611c6..feac9040 100644 --- a/vt.c +++ b/vt.c @@ -540,15 +540,12 @@ action_utf8_print(struct terminal *term, wchar_t wc) if (!term->grid->cursor.lcf) base_col--; + while (row->cells[base_col].wc == CELL_MULT_COL_SPACER && base_col > 0) + base_col--; + assert(base_col >= 0 && base_col < term->cols); wchar_t base = row->cells[base_col].wc; - /* Handle double-column glyphs */ - if (base == 0 && base_col > 0) { - base_col--; - base = row->cells[base_col].wc; - } - const struct composed *composed = (base >= CELL_COMB_CHARS_LO && base < (CELL_COMB_CHARS_LO + term->composed_count)) From 9508804b18270ab47c750dc61a16384297c06aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 16 Jul 2020 08:01:37 +0200 Subject: [PATCH 4/8] vt: ignore 0x7f (DEL) in ground state This ensures *all* bytes mapped to action_print() have wcwidth == 1. DEL has wcwidth == -1, and would thus have been ignored by term_print() anwyway. --- vt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vt.c b/vt.c index feac9040..148f2aae 100644 --- a/vt.c +++ b/vt.c @@ -223,6 +223,8 @@ action_print(struct terminal *term, uint8_t c) L'│', L'≤', L'≥', L'π', L'≠', L'£', L'·', /* x - ~ */ }; + assert(wcwidth(c) == 1); + if (unlikely(term->charsets.set[term->charsets.selected] == CHARSET_GRAPHIC) && c >= 0x60 && c <= 0x7e) { @@ -739,7 +741,8 @@ state_ground_switch(struct terminal *term, uint8_t data) case 0x19: case 0x1c ... 0x1f: action_execute(term, data); return STATE_GROUND; - case 0x20 ... 0x7f: action_print(term, data); return STATE_GROUND; + /* modified from 0x20..0x7f to 0x20..0x7e, since 0x7f is DEL, which is a zero-width character */ + case 0x20 ... 0x7e: action_print(term, data); return STATE_GROUND; case 0xc2 ... 0xdf: action_utf8_21(term, data); return STATE_UTF8_21; case 0xe0 ... 0xef: action_utf8_31(term, data); return STATE_UTF8_31; From 6f2cffd8c0949c2dfa1499c5d0c2594eb645ac26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 16 Jul 2020 08:04:12 +0200 Subject: [PATCH 5/8] vt: never call term_print() with a width <= 0 --- terminal.c | 3 +-- vt.c | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/terminal.c b/terminal.c index 84c9d459..554aa8b2 100644 --- a/terminal.c +++ b/terminal.c @@ -2401,8 +2401,7 @@ print_spacer(struct terminal *term, int col) void term_print(struct terminal *term, wchar_t wc, int width) { - if (unlikely(width <= 0)) - return; + assert(width > 0); print_linewrap(term); print_insert(term, width); diff --git a/vt.c b/vt.c index 148f2aae..f25f26be 100644 --- a/vt.c +++ b/vt.c @@ -663,7 +663,8 @@ action_utf8_print(struct terminal *term, wchar_t wc) } } - term_print(term, wc, width); + if (width > 0) + term_print(term, wc, width); } static void From 47d6dd0eeef6b3153a3989c76044f2cb091b12d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 16 Jul 2020 08:06:37 +0200 Subject: [PATCH 6/8] csi: never call term_print() with width <= 0 --- csi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/csi.c b/csi.c index fc6db974..fe102ada 100644 --- a/csi.c +++ b/csi.c @@ -338,8 +338,10 @@ csi_dispatch(struct terminal *term, uint8_t final) LOG_DBG("REP: '%C' %d times", term->vt.last_printed, count); const int width = wcwidth(term->vt.last_printed); - for (int i = 0; i < count; i++) - term_print(term, term->vt.last_printed, width); + if (width > 0) { + for (int i = 0; i < count; i++) + term_print(term, term->vt.last_printed, width); + } } break; From 674f0dd0fc56252d7c274eb9207f260a8e05ca2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 16 Jul 2020 08:10:56 +0200 Subject: [PATCH 7/8] sixel: verify list order: fix assertion when two sixels are on the same row Two sixel may in fact exist on the same row, assuming their columns don't overlap. --- sixel.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/sixel.c b/sixel.c index 7d4b3d38..7dab1fcc 100644 --- a/sixel.c +++ b/sixel.c @@ -113,13 +113,33 @@ verify_sixel_list_order(const struct terminal *term) { #if defined(_DEBUG) int prev_row = INT_MAX; + int prev_col = -1; + int prev_col_count = 0; tll_foreach(term->grid->sixel_images, it) { int row = rebase_row(term, it->item.pos.row + it->item.rows - 1); - assert(row < prev_row); - if (row >= prev_row) + int col = it->item.pos.col; + int col_count = it->item.cols; + + assert(row <= prev_row); + if (row > prev_row) return false; + + if (row == prev_row) { + /* Allowed to be on the same row only if their columns + * don't overlap */ + + assert(col + col_count <= prev_col || + prev_col + prev_col_count <= col); + + if (!(col + col_count <= prev_col || + prev_col + prev_col_count <= col)) + return false; + } + prev_row = row; + prev_col = col; + prev_col_count = col_count; } #endif return true; From 7f6ed98a8366d0c270aff592c6d5782f99385a6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 16 Jul 2020 08:47:37 +0200 Subject: [PATCH 8/8] term: line-wrap: don't move cursor outside the grid Remove assertion that row be less than the scrolling region end. The cursor may in fact be *inside* the margin. Inside the margin, content never scrolls, but we must make sure we don't move the cursor outside the grid. --- terminal.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/terminal.c b/terminal.c index 554aa8b2..450b885b 100644 --- a/terminal.c +++ b/terminal.c @@ -2355,12 +2355,15 @@ print_linewrap(struct terminal *term) } term->grid->cursor.lcf = false; - if (term->grid->cursor.point.row == term->scroll_region.end - 1) + + const int row = term->grid->cursor.point.row; + + if (row == term->scroll_region.end - 1) term_scroll(term, 1); else { - assert(term->grid->cursor.point.row < term->scroll_region.end - 1); - term->grid->cursor.point.row++; - term->grid->cur_row = grid_row(term->grid, term->grid->cursor.point.row); + const int new_row = min(row + 1, term->rows - 1); + term->grid->cursor.point.row = new_row; + term->grid->cur_row = grid_row(term->grid, new_row); } term->grid->cursor.point.col = 0;