From 6b116865f64dd1d5b6fe5ba1c859aaec7c6f208b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 28 Mar 2021 14:29:55 +0200 Subject: [PATCH 01/41] =?UTF-8?q?changelog:=20add=20new=20=E2=80=98unrelea?= =?UTF-8?q?sed=E2=80=99=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c6dfcb6..fa54bdb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Changelog +* [Unreleased](#unreleased) * [1.7.1](#1-7-1) * [1.7.0](#1-7-0) * [1.6.4](#1-6-4) @@ -24,6 +25,16 @@ * [1.2.0](#1-2-0) +## Unreleased +### Added +### Changed +### Deprecated +### Removed +### Fixed +### Security +### Contributors + + ## 1.7.1 ### Changed From 0ed40958c7638f1e53a83a3b61cd8e0c99e4fb02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 28 Mar 2021 17:24:35 +0200 Subject: [PATCH 02/41] =?UTF-8?q?install:=20add=20=E2=80=98ninja=20test?= =?UTF-8?q?=E2=80=99=20to=20all=20build=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While we don’t (yet) have any unit tests for foot, users can build foot with e.g. fcft and/or tllist as sub-projects. *They* have tests, and when doing PGO builds, those test binaries *must* be executed, or we get link failures in the final build. --- INSTALL.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/INSTALL.md b/INSTALL.md index 9fa651e1..1d0459bc 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -200,6 +200,7 @@ Then, tell meson we want to _generate_ profiling data, and build: ```sh meson configure -Db_pgo=generate ninja +ninja test ``` Next, we need to actually generate the profiling data. @@ -303,6 +304,7 @@ Next, tell meson to _use_ the profile data we just generated, and rebuild: ```sh meson configure -Db_pgo=use ninja +ninja test ``` Continue reading in [Running the new build](#running-the-new-build) @@ -313,6 +315,7 @@ Continue reading in [Running the new build](#running-the-new-build) ```sh meson --buildtype=debug ../.. ninja +ninja test ``` From 3abde17b9ebf6f1b1dabdef3c6690d7b9ed3f6b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 28 Mar 2021 21:01:22 +0200 Subject: [PATCH 03/41] term: free vt.osc8.uri when destroying a terminal Free vt.osc8.uri in term_destroy(), in the off chance, that the client application emitted an un-terminated OSC-8 URI. --- terminal.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/terminal.c b/terminal.c index 1984562f..47c0e1ff 100644 --- a/terminal.c +++ b/terminal.c @@ -1430,6 +1430,7 @@ term_destroy(struct terminal *term) mtx_unlock(&term->render.workers.lock); free(term->vt.osc.data); + free(term->vt.osc8.uri); grid_free(&term->normal); grid_free(&term->alt); @@ -1679,6 +1680,7 @@ term_reset(struct terminal *term, bool hard) free(term->vt.osc.data); memset(&term->vt, 0, sizeof(term->vt)); term->vt.state = 0; /* GROUND */ + term->vt.osc8.begin = (struct coord){-1, -1}; free(term->vt.osc8.uri); term->vt.osc8.uri = NULL; From 0720b3177a629378804423d8face2b511cda41e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 29 Mar 2021 20:11:32 +0200 Subject: [PATCH 04/41] revert: input: do not include consumed modifiers in the set sent to the client There were two issues with it: * Not all applications decode the sequence into a set of modifiers + key, but use a fixed sequence -> combo mapping, that we broke. * There were unforeseen issues with e.g. F1-12, where the modifier were removed from combos like Ctrl+F12, or Alt+F12. The reason is simple; XKB tells us that Ctrl, or Alt, is a consumed modifier. Now, _why_ it thinks that is a different story. This reverts 6cd72bdee6c2b11f7cab15df9afb0ed92a7f8ba0 Closes #425 --- CHANGELOG.md | 5 +++++ input.c | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa54bdb8..40706868 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,11 @@ ### Deprecated ### Removed ### Fixed + +* Reverted _"Consumed modifiers are no longer sent to the client + application"_ (https://codeberg.org/dnkl/foot/issues/425). + + ### Security ### Contributors diff --git a/input.c b/input.c index 9a26e778..320b1679 100644 --- a/input.c +++ b/input.c @@ -1026,10 +1026,10 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, */ enum modifier keymap_mods = MOD_NONE; - keymap_mods |= mods & ~consumed & shift ? MOD_SHIFT : MOD_NONE; - keymap_mods |= mods & ~consumed & alt ? MOD_ALT : MOD_NONE; - keymap_mods |= mods & ~consumed & ctrl ? MOD_CTRL : MOD_NONE; - keymap_mods |= mods & ~consumed & meta ? MOD_META : MOD_NONE; + keymap_mods |= seat->kbd.shift ? MOD_SHIFT : MOD_NONE; + keymap_mods |= seat->kbd.alt ? MOD_ALT : MOD_NONE; + keymap_mods |= seat->kbd.ctrl ? MOD_CTRL : MOD_NONE; + keymap_mods |= seat->kbd.meta ? MOD_META : MOD_NONE; const struct key_data *keymap; if (sym == XKB_KEY_Escape && keymap_mods == MOD_NONE && term->modify_escape_key) { @@ -1113,7 +1113,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, } else { - if (mods & ~consumed & alt) { + if (mods & alt) { /* * When the alt modifier is pressed, we do one out of three things: * From 6e782271ff433d76e192a43739eb01f175bd1995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 30 Mar 2021 11:08:03 +0200 Subject: [PATCH 05/41] sixel: fix double free caused by bad free() in sixel_colors_set() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sixel_color_set() is called when the number of (sixel) color registers is changed. It frees the current palette, and changes the “palette size” variable. Originally, we only had a single palette. This is the one free:d by sixel_color_set(). Later, we added support for private vs. shared palettes. With this change, we now have one palette that is “never” free:d (the shared one), and a private palette that is always free:d after a sixel has been emitted. ‘sixel.palette’ is a pointer to the palette currently in use, and should only be accessed **while emitting a sixel**. This is the pointer sixel_color_set() free:d. So for example, if ‘sixel.palette’ pointed to the shared palette, we’d free the shared palette. But, we didn’t reset ‘sixel.shared_palette’, causing a double free later on. Closes #427 --- CHANGELOG.md | 3 +++ sixel.c | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40706868..16b5f9c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,9 @@ * Reverted _"Consumed modifiers are no longer sent to the client application"_ (https://codeberg.org/dnkl/foot/issues/425). +* Crash caused by a double free originating in `XTSMGRAPHICS` - set + number of color registers + (https://codeberg.org/dnkl/foot/issues/427). ### Security diff --git a/sixel.c b/sixel.c index cac60493..903fe8e4 100644 --- a/sixel.c +++ b/sixel.c @@ -1344,8 +1344,10 @@ sixel_colors_set(struct terminal *term, unsigned count) unsigned new_palette_size = min(max(2, count), SIXEL_MAX_COLORS); LOG_DBG("sixel palette size set to %u", new_palette_size); - free(term->sixel.palette); - term->sixel.palette = NULL; + free(term->sixel.private_palette); + free(term->sixel.shared_palette); + term->sixel.private_palette = NULL; + term->sixel.shared_palette = NULL; term->sixel.palette_size = new_palette_size; sixel_colors_report_current(term); From 5dbeb5ce274df5649b2e475a7b181c03c26b38b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 5 Apr 2021 14:33:44 +0200 Subject: [PATCH 06/41] config: parse_key_binding_section(): use provided action-map MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don’t call has_key_binding_collisions() with ‘binding_action_map’ unconditionally; use the provided ‘action_map’ instead. This fixes wrong error messages for key combo collisions in key binding sections other than the regular “key-bindings”. --- CHANGELOG.md | 2 ++ config.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16b5f9c3..970c070b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,8 @@ * Crash caused by a double free originating in `XTSMGRAPHICS` - set number of color registers (https://codeberg.org/dnkl/foot/issues/427). +* Wrong action referenced in error message for key binding collisions + (https://codeberg.org/dnkl/foot/issues/432). ### Security diff --git a/config.c b/config.c index ab0236bb..0112b9e4 100644 --- a/config.c +++ b/config.c @@ -1393,7 +1393,7 @@ parse_key_binding_section( if (!parse_key_combos( conf, value, &key_combos, section, key, path, lineno) || has_key_binding_collisions( - conf, action, binding_action_map, bindings, &key_combos, + conf, action, action_map, bindings, &key_combos, path, lineno)) { free(pipe_argv); From 6e293337a9ce223ac4b70d39776e744fa15938bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 5 Apr 2021 14:37:42 +0200 Subject: [PATCH 07/41] doc: foot.ini: fix default value for delete-next-word --- doc/foot.ini.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index ac815b23..dcf644ef 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -593,7 +593,7 @@ scrollback search mode. The syntax is exactly the same as the regular Deletes the **character after** the cursor. Default: _Delete_. *delete-next-word* - Deletes the **word after** the cursor. Default: _Mod1+b + Deletes the **word after** the cursor. Default: _Mod1+d Control+Delete_. *extend-to-word-boundary* From 937ee8a5092fc38b5bb547b6981045eeade3b1f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 5 Apr 2021 14:50:21 +0200 Subject: [PATCH 08/41] config: make {search,url}_binding_action_map[] function local MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensures we don’t accidentally reference them from places we shouldn’t. Unfortunately, binding_action_map[] (for “normal” key bindings) cannot easily be made function local since it is used when parsing both key- and mouse bindings (i.e. it’s used in multiple functions). --- config.c | 68 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/config.c b/config.c index 0112b9e4..6da5b68d 100644 --- a/config.c +++ b/config.c @@ -91,40 +91,6 @@ static const char *const binding_action_map[] = { static_assert(ALEN(binding_action_map) == BIND_ACTION_COUNT, "binding action map size mismatch"); -static const char *const search_binding_action_map[] = { - [BIND_ACTION_SEARCH_NONE] = NULL, - [BIND_ACTION_SEARCH_CANCEL] = "cancel", - [BIND_ACTION_SEARCH_COMMIT] = "commit", - [BIND_ACTION_SEARCH_FIND_PREV] = "find-prev", - [BIND_ACTION_SEARCH_FIND_NEXT] = "find-next", - [BIND_ACTION_SEARCH_EDIT_LEFT] = "cursor-left", - [BIND_ACTION_SEARCH_EDIT_LEFT_WORD] = "cursor-left-word", - [BIND_ACTION_SEARCH_EDIT_RIGHT] = "cursor-right", - [BIND_ACTION_SEARCH_EDIT_RIGHT_WORD] = "cursor-right-word", - [BIND_ACTION_SEARCH_EDIT_HOME] = "cursor-home", - [BIND_ACTION_SEARCH_EDIT_END] = "cursor-end", - [BIND_ACTION_SEARCH_DELETE_PREV] = "delete-prev", - [BIND_ACTION_SEARCH_DELETE_PREV_WORD] = "delete-prev-word", - [BIND_ACTION_SEARCH_DELETE_NEXT] = "delete-next", - [BIND_ACTION_SEARCH_DELETE_NEXT_WORD] = "delete-next-word", - [BIND_ACTION_SEARCH_EXTEND_WORD] = "extend-to-word-boundary", - [BIND_ACTION_SEARCH_EXTEND_WORD_WS] = "extend-to-next-whitespace", - [BIND_ACTION_SEARCH_CLIPBOARD_PASTE] = "clipboard-paste", - [BIND_ACTION_SEARCH_PRIMARY_PASTE] = "primary-paste", -}; - -static_assert(ALEN(search_binding_action_map) == BIND_ACTION_SEARCH_COUNT, - "search binding action map size mismatch"); - -static const char *const url_binding_action_map[] = { - [BIND_ACTION_URL_NONE] = NULL, - [BIND_ACTION_URL_CANCEL] = "cancel", - [BIND_ACTION_URL_TOGGLE_URL_ON_JUMP_LABEL] = "toggle-url-visible", -}; - -static_assert(ALEN(url_binding_action_map) == BIND_ACTION_URL_COUNT, - "URL binding action map size mismatch"); - #define LOG_AND_NOTIFY_ERR(...) \ do { \ LOG_ERR(__VA_ARGS__); \ @@ -1462,6 +1428,31 @@ parse_section_search_bindings( const char *key, const char *value, struct config *conf, const char *path, unsigned lineno) { + static const char *const search_binding_action_map[] = { + [BIND_ACTION_SEARCH_NONE] = NULL, + [BIND_ACTION_SEARCH_CANCEL] = "cancel", + [BIND_ACTION_SEARCH_COMMIT] = "commit", + [BIND_ACTION_SEARCH_FIND_PREV] = "find-prev", + [BIND_ACTION_SEARCH_FIND_NEXT] = "find-next", + [BIND_ACTION_SEARCH_EDIT_LEFT] = "cursor-left", + [BIND_ACTION_SEARCH_EDIT_LEFT_WORD] = "cursor-left-word", + [BIND_ACTION_SEARCH_EDIT_RIGHT] = "cursor-right", + [BIND_ACTION_SEARCH_EDIT_RIGHT_WORD] = "cursor-right-word", + [BIND_ACTION_SEARCH_EDIT_HOME] = "cursor-home", + [BIND_ACTION_SEARCH_EDIT_END] = "cursor-end", + [BIND_ACTION_SEARCH_DELETE_PREV] = "delete-prev", + [BIND_ACTION_SEARCH_DELETE_PREV_WORD] = "delete-prev-word", + [BIND_ACTION_SEARCH_DELETE_NEXT] = "delete-next", + [BIND_ACTION_SEARCH_DELETE_NEXT_WORD] = "delete-next-word", + [BIND_ACTION_SEARCH_EXTEND_WORD] = "extend-to-word-boundary", + [BIND_ACTION_SEARCH_EXTEND_WORD_WS] = "extend-to-next-whitespace", + [BIND_ACTION_SEARCH_CLIPBOARD_PASTE] = "clipboard-paste", + [BIND_ACTION_SEARCH_PRIMARY_PASTE] = "primary-paste", + }; + + static_assert(ALEN(search_binding_action_map) == BIND_ACTION_SEARCH_COUNT, + "search binding action map size mismatch"); + return parse_key_binding_section( "search-bindings", key, value, BIND_ACTION_SEARCH_COUNT, search_binding_action_map, &conf->bindings.search, conf, path, lineno); @@ -1472,6 +1463,15 @@ parse_section_url_bindings( const char *key, const char *value, struct config *conf, const char *path, unsigned lineno) { + static const char *const url_binding_action_map[] = { + [BIND_ACTION_URL_NONE] = NULL, + [BIND_ACTION_URL_CANCEL] = "cancel", + [BIND_ACTION_URL_TOGGLE_URL_ON_JUMP_LABEL] = "toggle-url-visible", + }; + + static_assert(ALEN(url_binding_action_map) == BIND_ACTION_URL_COUNT, + "URL binding action map size mismatch"); + return parse_key_binding_section( "url-bindings", key, value, BIND_ACTION_URL_COUNT, url_binding_action_map, &conf->bindings.url, conf, path, lineno); From 4aae54e3e7ed4909592ad43594cc4da8a844d3f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 5 Apr 2021 21:06:48 +0200 Subject: [PATCH 09/41] osc: verify OSC 4/104 color index is valid Closes #434 --- CHANGELOG.md | 3 +++ osc.c | 12 +++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 970c070b..caadf51b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,9 @@ when output scaling was enabled (https://codeberg.org/dnkl/foot/issues/409). * Empty sixels resulted in non-empty images. +* OSC-4/104 out-of-bounds accesses to the color table. This was the + reason pywal turned foot windows transparent + (https://codeberg.org/dnkl/foot/issues/434). ## 1.7.0 diff --git a/osc.c b/osc.c index bf97db52..68783701 100644 --- a/osc.c +++ b/osc.c @@ -575,6 +575,11 @@ osc_dispatch(struct terminal *term) idx += c - '0'; } + if (idx >= ALEN(term->colors.table)) { + LOG_WARN("invalid OSC 4 color index: %u", idx); + break; + } + /* Client queried for current value */ if (strlen(s_color) == 1 && s_color[0] == '?') { uint32_t color = term->colors.table[idx]; @@ -698,7 +703,7 @@ osc_dispatch(struct terminal *term) if (strlen(string) == 0) { LOG_DBG("resetting all colors"); - for (size_t i = 0; i < 256; i++) { + for (size_t i = 0; i < ALEN(term->colors.table); i++) { update_color_in_grids( term, term->colors.table[i], term->colors.default_table[i]); term->colors.table[i] = term->colors.default_table[i]; @@ -717,6 +722,11 @@ osc_dispatch(struct terminal *term) idx += c - '0'; } + if (idx >= ALEN(term->colors.table)) { + LOG_WARN("invalid OSC 104 color index: %u", idx); + continue; + } + LOG_DBG("resetting color #%u", idx); update_color_in_grids( term, term->colors.table[idx], term->colors.default_table[idx]); From 4a2ff28850385254a7d91bd9643cebe20ac630ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 5 Apr 2021 22:07:58 +0200 Subject: [PATCH 10/41] =?UTF-8?q?changelog:=20move=20OSC-4/104=20fix=20fro?= =?UTF-8?q?m=201.7.1=20to=20=E2=80=98unreleased=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index caadf51b..9f0ed40f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,9 @@ (https://codeberg.org/dnkl/foot/issues/427). * Wrong action referenced in error message for key binding collisions (https://codeberg.org/dnkl/foot/issues/432). +* OSC-4/104 out-of-bounds accesses to the color table. This was the + reason pywal turned foot windows transparent + (https://codeberg.org/dnkl/foot/issues/434). ### Security @@ -71,9 +74,6 @@ when output scaling was enabled (https://codeberg.org/dnkl/foot/issues/409). * Empty sixels resulted in non-empty images. -* OSC-4/104 out-of-bounds accesses to the color table. This was the - reason pywal turned foot windows transparent - (https://codeberg.org/dnkl/foot/issues/434). ## 1.7.0 From 407189978ee0a8bcdc78d5eab6a04ea25526e531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 7 Apr 2021 08:04:24 +0200 Subject: [PATCH 11/41] wayland: {xdg_,}output_*(): free old strings before assigning new ones MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Defensive programming; output_geometry() etc are typically only called once for an output instance. But let’s ensure we’re not leaking memory if it’s called more than once. --- wayland.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wayland.c b/wayland.c index edc9b482..8985e119 100644 --- a/wayland.c +++ b/wayland.c @@ -359,6 +359,10 @@ output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, int32_t transform) { struct monitor *mon = data; + + free(mon->make); + free(mon->model); + mon->dim.mm.width = physical_width; mon->dim.mm.height = physical_height; mon->inch = sqrt(pow(mon->dim.mm.width, 2) + pow(mon->dim.mm.height, 2)) * 0.03937008; @@ -366,6 +370,7 @@ output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, mon->model = model != NULL ? xstrdup(model) : NULL; mon->subpixel = subpixel; mon->transform = transform; + output_update_ppi(mon); } @@ -434,6 +439,7 @@ xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, const char *name) { struct monitor *mon = data; + free(mon->name); mon->name = name != NULL ? xstrdup(name) : NULL; } @@ -442,6 +448,7 @@ xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, const char *description) { struct monitor *mon = data; + free(mon->description); mon->description = description != NULL ? xstrdup(description) : NULL; } From 292a7c5686d04160b4417ed5d57a9410ebf492cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 7 Apr 2021 08:07:43 +0200 Subject: [PATCH 12/41] =?UTF-8?q?config/terminal:=20refactor:=20remove=20?= =?UTF-8?q?=E2=80=9Cdefault=5F*=E2=80=9D=20color=20members=20from=20termin?= =?UTF-8?q?al=20struct?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Access the original colors in the configuration instead. --- config.c | 57 ++++++++++++++++++++++++++++++++++++------------------ config.h | 3 +-- osc.c | 16 +++++++-------- render.c | 16 +++++++-------- terminal.c | 51 ++++++------------------------------------------ terminal.h | 4 ---- 6 files changed, 61 insertions(+), 86 deletions(-) diff --git a/config.c b/config.c index 6da5b68d..8809163c 100644 --- a/config.c +++ b/config.c @@ -857,22 +857,22 @@ parse_section_colors(const char *key, const char *value, struct config *conf, if (strcmp(key, "foreground") == 0) color = &conf->colors.fg; else if (strcmp(key, "background") == 0) color = &conf->colors.bg; - else if (strcmp(key, "regular0") == 0) color = &conf->colors.regular[0]; - else if (strcmp(key, "regular1") == 0) color = &conf->colors.regular[1]; - else if (strcmp(key, "regular2") == 0) color = &conf->colors.regular[2]; - else if (strcmp(key, "regular3") == 0) color = &conf->colors.regular[3]; - else if (strcmp(key, "regular4") == 0) color = &conf->colors.regular[4]; - else if (strcmp(key, "regular5") == 0) color = &conf->colors.regular[5]; - else if (strcmp(key, "regular6") == 0) color = &conf->colors.regular[6]; - else if (strcmp(key, "regular7") == 0) color = &conf->colors.regular[7]; - else if (strcmp(key, "bright0") == 0) color = &conf->colors.bright[0]; - else if (strcmp(key, "bright1") == 0) color = &conf->colors.bright[1]; - else if (strcmp(key, "bright2") == 0) color = &conf->colors.bright[2]; - else if (strcmp(key, "bright3") == 0) color = &conf->colors.bright[3]; - else if (strcmp(key, "bright4") == 0) color = &conf->colors.bright[4]; - else if (strcmp(key, "bright5") == 0) color = &conf->colors.bright[5]; - else if (strcmp(key, "bright6") == 0) color = &conf->colors.bright[6]; - else if (strcmp(key, "bright7") == 0) color = &conf->colors.bright[7]; + else if (strcmp(key, "regular0") == 0) color = &conf->colors.table[0]; + else if (strcmp(key, "regular1") == 0) color = &conf->colors.table[1]; + else if (strcmp(key, "regular2") == 0) color = &conf->colors.table[2]; + else if (strcmp(key, "regular3") == 0) color = &conf->colors.table[3]; + else if (strcmp(key, "regular4") == 0) color = &conf->colors.table[4]; + else if (strcmp(key, "regular5") == 0) color = &conf->colors.table[5]; + else if (strcmp(key, "regular6") == 0) color = &conf->colors.table[6]; + else if (strcmp(key, "regular7") == 0) color = &conf->colors.table[7]; + else if (strcmp(key, "bright0") == 0) color = &conf->colors.table[8 + 0]; + else if (strcmp(key, "bright1") == 0) color = &conf->colors.table[8 + 1]; + else if (strcmp(key, "bright2") == 0) color = &conf->colors.table[8 + 2]; + else if (strcmp(key, "bright3") == 0) color = &conf->colors.table[8 + 3]; + else if (strcmp(key, "bright4") == 0) color = &conf->colors.table[8 + 4]; + else if (strcmp(key, "bright5") == 0) color = &conf->colors.table[8 + 5]; + else if (strcmp(key, "bright6") == 0) color = &conf->colors.table[8 + 6]; + else if (strcmp(key, "bright7") == 0) color = &conf->colors.table[8 + 7]; else if (strcmp(key, "selection-foreground") == 0) color = &conf->colors.selection_fg; else if (strcmp(key, "selection-background") == 0) color = &conf->colors.selection_bg; @@ -2211,7 +2211,7 @@ config_load(struct config *conf, const char *conf_path, .colors = { .fg = default_foreground, .bg = default_background, - .regular = { + .table = { default_regular[0], default_regular[1], default_regular[2], @@ -2220,8 +2220,7 @@ config_load(struct config *conf, const char *conf_path, default_regular[5], default_regular[6], default_regular[7], - }, - .bright = { + default_bright[0], default_bright[1], default_bright[2], @@ -2287,6 +2286,26 @@ config_load(struct config *conf, const char *conf_path, .notifications = tll_init(), }; + /* Initialize the color cube */ + { + /* First 16 entries correspond to the "regular" and "bright" + * colors, and have already been initialized */ + + /* Then follows 216 RGB shades */ + for (size_t r = 0; r < 6; r++) { + for (size_t g = 0; g < 6; g++) { + for (size_t b = 0; b < 6; b++) { + conf->colors.table[16 + r * 6 * 6 + g * 6 + b] + = r * 51 << 16 | g * 51 << 8 | b * 51; + } + } + } + + /* And finally 24 shades of gray */ + for (size_t i = 0; i < 24; i++) + conf->colors.table[232 + i] = i * 11 << 16 | i * 11 << 8 | i * 11; + } + conf->notify.raw_cmd = xstrdup( "notify-send -a foot -i foot ${title} ${body}"); tokenize_cmdline(conf->notify.raw_cmd, &conf->notify.argv); diff --git a/config.h b/config.h index f8c7aaf0..696c57b6 100644 --- a/config.h +++ b/config.h @@ -123,8 +123,7 @@ struct config { struct { uint32_t fg; uint32_t bg; - uint32_t regular[8]; - uint32_t bright[8]; + uint32_t table[256]; uint16_t alpha; uint32_t selection_fg; uint32_t selection_bg; diff --git a/osc.c b/osc.c index 68783701..524269ef 100644 --- a/osc.c +++ b/osc.c @@ -705,8 +705,8 @@ osc_dispatch(struct terminal *term) LOG_DBG("resetting all colors"); for (size_t i = 0; i < ALEN(term->colors.table); i++) { update_color_in_grids( - term, term->colors.table[i], term->colors.default_table[i]); - term->colors.table[i] = term->colors.default_table[i]; + term, term->colors.table[i], term->conf->colors.table[i]); + term->colors.table[i] = term->conf->colors.table[i]; } } @@ -729,8 +729,8 @@ osc_dispatch(struct terminal *term) LOG_DBG("resetting color #%u", idx); update_color_in_grids( - term, term->colors.table[idx], term->colors.default_table[idx]); - term->colors.table[idx] = term->colors.default_table[idx]; + term, term->colors.table[idx], term->conf->colors.table[idx]); + term->colors.table[idx] = term->conf->colors.table[idx]; } } @@ -741,14 +741,14 @@ osc_dispatch(struct terminal *term) break; case 110: /* Reset default text foreground color */ - LOG_DBG("resetting foreground"); - term->colors.fg = term->colors.default_fg; + LOG_DBG("resetting foreground color"); + term->colors.fg = term->conf->colors.fg; term_damage_view(term); break; case 111: /* Reset default text background color */ - LOG_DBG("resetting background"); - term->colors.bg = term->colors.default_bg; + LOG_DBG("resetting background color"); + term->colors.bg = term->conf->colors.bg; term_damage_view(term); term_damage_margins(term); break; diff --git a/render.c b/render.c index b857e360..a0c0696e 100644 --- a/render.c +++ b/render.c @@ -1450,7 +1450,7 @@ render_csd_title(struct terminal *term) struct buffer *buf = shm_get_buffer( term->wl->shm, info.width, info.height, cookie, false, 1); - uint32_t _color = term->colors.default_fg; + uint32_t _color = term->conf->colors.fg; uint16_t alpha = 0xffff; if (term->conf->csd.color.title_set) { @@ -1493,7 +1493,7 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx) static void render_csd_button_minimize(struct terminal *term, struct buffer *buf) { - pixman_color_t color = color_hex_to_pixman(term->colors.default_bg); + pixman_color_t color = color_hex_to_pixman(term->conf->colors.bg); pixman_image_t *src = pixman_image_create_solid_fill(&color); const int max_height = buf->height / 2; @@ -1538,7 +1538,7 @@ static void render_csd_button_maximize_maximized( struct terminal *term, struct buffer *buf) { - pixman_color_t color = color_hex_to_pixman(term->colors.default_bg); + pixman_color_t color = color_hex_to_pixman(term->conf->colors.bg); pixman_image_t *src = pixman_image_create_solid_fill(&color); const int max_height = buf->height / 3; @@ -1566,7 +1566,7 @@ static void render_csd_button_maximize_window( struct terminal *term, struct buffer *buf) { - pixman_color_t color = color_hex_to_pixman(term->colors.default_bg); + pixman_color_t color = color_hex_to_pixman(term->conf->colors.bg); pixman_image_t *src = pixman_image_create_solid_fill(&color); const int max_height = buf->height / 2; @@ -1620,7 +1620,7 @@ render_csd_button_maximize(struct terminal *term, struct buffer *buf) static void render_csd_button_close(struct terminal *term, struct buffer *buf) { - pixman_color_t color = color_hex_to_pixman(term->colors.default_bg); + pixman_color_t color = color_hex_to_pixman(term->conf->colors.bg); pixman_image_t *src = pixman_image_create_solid_fill(&color); const int max_height = buf->height / 3; @@ -1665,21 +1665,21 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx) switch (surf_idx) { case CSD_SURF_MINIMIZE: - _color = term->colors.default_table[4]; /* blue */ + _color = term->conf->colors.table[4]; /* blue */ is_set = term->conf->csd.color.minimize_set; conf_color = &term->conf->csd.color.minimize; is_active = term->active_surface == TERM_SURF_BUTTON_MINIMIZE; break; case CSD_SURF_MAXIMIZE: - _color = term->colors.default_table[2]; /* green */ + _color = term->conf->colors.table[2]; /* green */ is_set = term->conf->csd.color.maximize_set; conf_color = &term->conf->csd.color.maximize; is_active = term->active_surface == TERM_SURF_BUTTON_MAXIMIZE; break; case CSD_SURF_CLOSE: - _color = term->colors.default_table[1]; /* red */ + _color = term->conf->colors.table[1]; /* red */ is_set = term->conf->csd.color.close_set; conf_color = &term->conf->csd.color.close; is_active = term->active_surface == TERM_SURF_BUTTON_CLOSE; diff --git a/terminal.c b/terminal.c index 47c0e1ff..b55a63a9 100644 --- a/terminal.c +++ b/terminal.c @@ -544,25 +544,6 @@ fdm_app_sync_updates_timeout( return true; } -static void -initialize_color_cube(struct terminal *term) -{ - /* First 16 entries have already been initialized from conf */ - for (size_t r = 0; r < 6; r++) { - for (size_t g = 0; g < 6; g++) { - for (size_t b = 0; b < 6; b++) { - term->colors.default_table[16 + r * 6 * 6 + g * 6 + b] - = r * 51 << 16 | g * 51 << 8 | b * 51; - } - } - } - - for (size_t i = 0; i < 24; i++) - term->colors.default_table[232 + i] = i * 11 << 16 | i * 11 << 8 | i * 11; - - memcpy(term->colors.table, term->colors.default_table, sizeof(term->colors.table)); -} - static bool initialize_render_workers(struct terminal *term) { @@ -1100,27 +1081,6 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .colors = { .fg = conf->colors.fg, .bg = conf->colors.bg, - .default_fg = conf->colors.fg, - .default_bg = conf->colors.bg, - .default_table = { - conf->colors.regular[0], - conf->colors.regular[1], - conf->colors.regular[2], - conf->colors.regular[3], - conf->colors.regular[4], - conf->colors.regular[5], - conf->colors.regular[6], - conf->colors.regular[7], - - conf->colors.bright[0], - conf->colors.bright[1], - conf->colors.bright[2], - conf->colors.bright[3], - conf->colors.bright[4], - conf->colors.bright[5], - conf->colors.bright[6], - conf->colors.bright[7], - }, .alpha = conf->colors.alpha, }, .origin = ORIGIN_ABSOLUTE, @@ -1215,7 +1175,8 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, term->scale = it->item.scale; } - initialize_color_cube(term); + memcpy(term->colors.table, term->conf->colors.table, + sizeof(term->colors.table)); /* Initialize the Wayland window backend */ if ((term->window = wayl_win_init(term)) == NULL) @@ -1714,10 +1675,10 @@ term_reset(struct terminal *term, bool hard) term->flash.active = false; term->blink.state = BLINK_ON; fdm_del(term->fdm, term->blink.fd); term->blink.fd = -1; - term->colors.fg = term->colors.default_fg; - term->colors.bg = term->colors.default_bg; - for (size_t i = 0; i < 256; i++) - term->colors.table[i] = term->colors.default_table[i]; + term->colors.fg = term->conf->colors.fg; + term->colors.bg = term->conf->colors.bg; + memcpy(term->colors.table, term->conf->colors.table, + sizeof(term->colors.table)); term->origin = ORIGIN_ABSOLUTE; term->normal.cursor.lcf = false; term->alt.cursor.lcf = false; diff --git a/terminal.h b/terminal.h index ce808ce8..7b463d22 100644 --- a/terminal.h +++ b/terminal.h @@ -407,10 +407,6 @@ struct terminal { uint32_t bg; uint32_t table[256]; uint16_t alpha; - - uint32_t default_fg; - uint32_t default_bg; - uint32_t default_table[256]; } colors; enum cursor_style cursor_style; From 8d06278a292f726c76ab023adea09ee74e82ec60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 7 Apr 2021 19:07:43 +0200 Subject: [PATCH 13/41] sixel: sixel_fini(): free image data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Normally, this data is always free:d indirectly, when the sixel image that took over ownership is destroyed. But let’s play it safe. --- sixel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sixel.c b/sixel.c index 903fe8e4..f4d917f4 100644 --- a/sixel.c +++ b/sixel.c @@ -28,6 +28,7 @@ get_bg(const struct terminal *term) void sixel_fini(struct terminal *term) { + free(term->sixel.image.data); free(term->sixel.private_palette); free(term->sixel.shared_palette); } From 7b0d2522ee204b83bbf4598528bc76fa503d3794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 7 Apr 2021 19:08:29 +0200 Subject: [PATCH 14/41] sixel: unhook: tighten up the condition needed for us to free image data pre-maturely --- sixel.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sixel.c b/sixel.c index f4d917f4..0e8c58d5 100644 --- a/sixel.c +++ b/sixel.c @@ -727,11 +727,6 @@ sixel_unhook(struct terminal *term) term->sixel.image.height = term->sixel.max_non_empty_row_no + 1; } - if (term->sixel.image.height == 0 || term->sixel.image.width == 0) { - /* We won’t be emitting any sixels - free backing image */ - free(term->sixel.image.data); - } - int pixel_row_idx = 0; int pixel_rows_left = term->sixel.image.height; const int stride = term->sixel.image.width * sizeof(uint32_t); @@ -766,6 +761,11 @@ sixel_unhook(struct terminal *term) int start_row = do_scroll ? term->grid->cursor.point.row : 0; const int start_col = do_scroll ? term->grid->cursor.point.col : 0; + if (pixel_rows_left == 0 || rows_avail == 0) { + /* We won’t be emitting any sixels - free backing image */ + free(term->sixel.image.data); + } + /* We do not allow sixels to cross the scrollback wrap-around, as * this makes intersection calculations much more complicated */ while (pixel_rows_left > 0 && rows_avail > 0) { From 275b62371fc674993d3eb066cf2932468f91bc62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 7 Apr 2021 19:52:46 +0200 Subject: [PATCH 15/41] ci: build on alpine/latest, not edge --- .builds/alpine-x64.yml | 3 +-- .gitlab-ci.yml | 11 +++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.builds/alpine-x64.yml b/.builds/alpine-x64.yml index be5bb0d3..3884e66b 100644 --- a/.builds/alpine-x64.yml +++ b/.builds/alpine-x64.yml @@ -1,5 +1,4 @@ - -image: alpine/edge +image: alpine/latest packages: - musl-dev - eudev-libs diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index add26132..3037cd03 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,7 +5,6 @@ variables: GIT_SUBMODULE_STRATEGY: normal before_script: - - echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories - apk update - apk add musl-dev linux-headers meson ninja gcc scdoc ncurses - apk add libxkbcommon-dev pixman-dev freetype-dev fontconfig-dev harfbuzz-dev @@ -15,7 +14,7 @@ before_script: - apk add ttf-hack font-noto-emoji debug-x64: - image: alpine:edge + image: alpine:latest stage: build script: - mkdir -p bld/debug @@ -28,7 +27,7 @@ debug-x64: junit: bld/debug/meson-logs/testlog.junit.xml release-x64: - image: alpine:edge + image: alpine:latest stage: build script: - mkdir -p bld/release @@ -41,7 +40,7 @@ release-x64: junit: bld/release/meson-logs/testlog.junit.xml debug-x86: - image: i386/alpine:edge + image: i386/alpine:latest stage: build script: - mkdir -p bld/debug @@ -54,7 +53,7 @@ debug-x86: junit: bld/debug/meson-logs/testlog.junit.xml release-x86: - image: i386/alpine:edge + image: i386/alpine:latest stage: build script: - mkdir -p bld/release @@ -67,7 +66,7 @@ release-x86: junit: bld/release/meson-logs/testlog.junit.xml codespell: - image: alpine:edge + image: alpine:latest stage: build script: - apk add python3 From f42e42246fe7aba57cabc89ac5a439d03bde06b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 7 Apr 2021 19:09:31 +0200 Subject: [PATCH 16/41] terminal: drain PTY when client terminates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is done by: * Not limiting the number of times we try to read from the PTY when we’ve have POLLHUP * Not requiring the entire the previous read to have filled our buffer. * Not erroring out on EIO. --- CHANGELOG.md | 1 + terminal.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f0ed40f..46af71bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ * OSC-4/104 out-of-bounds accesses to the color table. This was the reason pywal turned foot windows transparent (https://codeberg.org/dnkl/foot/issues/434). +* PTY not being drained when the client application terminates. ### Security diff --git a/terminal.c b/terminal.c index b55a63a9..c6b4705c 100644 --- a/terminal.c +++ b/terminal.c @@ -230,15 +230,20 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data) uint8_t buf[24 * 1024]; ssize_t count = sizeof(buf); - const size_t max_iterations = 10; + const size_t max_iterations = !hup ? 10 : (size_t)-1ll; - for (size_t i = 0; i < max_iterations && pollin && count == sizeof(buf); i++) { + for (size_t i = 0; i < max_iterations && pollin; i++) { xassert(pollin); count = read(term->ptmx, buf, sizeof(buf)); if (count < 0) { - if (errno == EAGAIN) - return true; + if (errno == EAGAIN || errno == EIO) { + /* + * EAGAIN: no more to read - FDM will trigger us again + * EIO: assume PTY was closed - we already have, or will get, a EPOLLHUP + */ + break; + } LOG_ERRNO("failed to read from pseudo terminal"); return false; From 1023f9a6e928f0a40ea70c754c4ca4286633d1b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 5 Apr 2021 22:05:50 +0200 Subject: [PATCH 17/41] osc: add support for URxvt extension to include alpha in OSC-11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are two variants, either using a ‘[percent]’ prefix for legacy colors, or using ‘rgba:r/g/b/a’ instead of ‘rgb:r/g/b’. Closes #436 --- CHANGELOG.md | 5 +++ osc.c | 124 +++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 105 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46af71bd..ff80e2f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,11 @@ ## Unreleased ### Added + +* Support for URxvt OSC-11 extension to set background alpha + (https://codeberg.org/dnkl/foot/issues/436). + + ### Changed ### Deprecated ### Removed diff --git a/osc.c b/osc.c index 524269ef..eade736a 100644 --- a/osc.c +++ b/osc.c @@ -261,8 +261,30 @@ osc_flash(struct terminal *term) } static bool -parse_legacy_color(const char *string, uint32_t *color) +parse_legacy_color(const char *string, uint32_t *color, bool *_have_alpha, + uint16_t *_alpha) { + bool have_alpha = false; + uint16_t alpha = 0xffff; + + if (string[0] == '[') { + /* e.g. \E]11;[0.5]#00ff00 */ + const char *start = &string[1]; + const char *end = strchr(string, ']'); + if (end == NULL) + return false; + + char *_end; + double percent = strtod(start, &_end); + if (_end != end) + return false; + + have_alpha = true; + alpha = 0xffff * percent; + + string = end + 1; + } + if (string[0] != '#') return false; @@ -299,31 +321,53 @@ parse_legacy_color(const char *string, uint32_t *color) uint8_t g = 256 * (rgb[1] / 65536.); uint8_t b = 256 * (rgb[2] / 65536.); - LOG_DBG("legacy: %02x%02x%02x", r, g, b); + LOG_DBG("legacy: %02x%02x%02x (alpha=%04x)", r, g, b, + have_alpha ? alpha : 0xffff); + *color = r << 16 | g << 8 | b; + + if (_have_alpha != NULL) + *_have_alpha = have_alpha; + if (_alpha != NULL) + *_alpha = alpha; return true; } static bool -parse_rgb(const char *string, uint32_t *color) +parse_rgb(const char *string, uint32_t *color, bool *_have_alpha, + uint16_t *_alpha) { size_t len = strlen(string); + bool have_alpha = len >= 4 && strncmp(string, "rgba", 4) == 0; - /* Verify we have the minimum required length (for "rgb:x/x/x") */ - if (len < 3 /* 'rgb' */ + 1 /* ':' */ + 2 /* '/' */ + 3 * 1 /* 3 * 'x' */) - return false; + /* Verify we have the minimum required length (for "") */ + if (have_alpha) { + /* rgba:x/x/x/x */ + if (len < 4 /* 'rgba' */ + 1 /* ':' */ + 3 /* '/' */ + 4 * 1 /* 4 * 'x' */) + return false; + } else { + /* rgb:x/x/x */ + if (len < 3 /* 'rgb' */ + 1 /* ':' */ + 2 /* '/' */ + 3 * 1 /* 3 * 'x' */) + return false; + } - /* Verify prefix is "rgb:" */ - if (string[0] != 'r' || string[1] != 'g' || string[2] != 'b' || string[3] != ':') - return false; + /* Verify prefix is “rgb:” or “rgba:” */ + if (have_alpha) { + if (strncmp(string, "rgba:", 5) != 0) + return false; + string += 5; + len -= 5; + } else { + if (strncmp(string, "rgb:", 4) != 0) + return false; + string += 4; + len -= 4; + } - string += 4; - len -= 4; + int rgb[4]; + int digits[4]; - int rgb[3]; - int digits[3]; - - for (size_t i = 0; i < 3; i++) { + for (size_t i = 0; i < (have_alpha ? 4 : 3); i++) { for (rgb[i] = 0, digits[i] = 0; len > 0 && *string != '/'; len--, string++, digits[i]++) @@ -338,7 +382,7 @@ parse_rgb(const char *string, uint32_t *color) c >= 'a' && c <= 'f' ? c - 'a' + 10 : c - 'A' + 10; } - if (i >= 2) + if (i >= (have_alpha ? 3 : 2)) break; if (len == 0 || *string != '/') @@ -351,7 +395,20 @@ parse_rgb(const char *string, uint32_t *color) uint8_t g = 256 * (rgb[1] / (double)(1 << (4 * digits[1]))); uint8_t b = 256 * (rgb[2] / (double)(1 << (4 * digits[2]))); - LOG_DBG("rgb: %02x%02x%02x", r, g, b); + uint16_t alpha; + if (have_alpha) + alpha = 65536 * (rgb[3] / (double)(1 << (4 * digits[3]))); + + if (have_alpha) + LOG_DBG("rgba: %02x%02x%02x (alpha=%04x)", r, g, b, alpha); + else + LOG_DBG("rgb: %02x%02x%02x", r, g, b); + + if (_have_alpha != NULL) + *_have_alpha = have_alpha; + if (_alpha != NULL) + *_alpha = alpha; + *color = r << 16 | g << 8 | b; return true; } @@ -595,9 +652,9 @@ osc_dispatch(struct terminal *term) else { uint32_t color; - bool color_is_valid = s_color[0] == '#' - ? parse_legacy_color(s_color, &color) - : parse_rgb(s_color, &color); + bool color_is_valid = s_color[0] == '#' || s_color[0] == '[' + ? parse_legacy_color(s_color, &color, NULL, NULL) + : parse_rgb(s_color, &color, NULL, NULL); if (!color_is_valid) continue; @@ -647,15 +704,29 @@ osc_dispatch(struct terminal *term) } uint32_t color; - if (string[0] == '#' ? !parse_legacy_color(string, &color) : !parse_rgb(string, &color)) + bool have_alpha = false; + uint16_t alpha = 0xffff; + + if (string[0] == '#' || string[0] == '[' + ? !parse_legacy_color(string, &color, &have_alpha, &alpha) + : !parse_rgb(string, &color, &have_alpha, &alpha)) + { break; + } LOG_DBG("change color definition for %s to %06x", param == 10 ? "foreground" : "background", color); switch (param) { - case 10: term->colors.fg = color; break; - case 11: term->colors.bg = color; break; + case 10: + term->colors.fg = color; + break; + + case 11: + term->colors.bg = color; + if (have_alpha) + term->colors.alpha = alpha; + break; } term_damage_view(term); @@ -678,8 +749,13 @@ osc_dispatch(struct terminal *term) } uint32_t color; - if (string[0] == '#' ? !parse_legacy_color(string, &color) : !parse_rgb(string, &color)) + + if (string[0] == '#' || string[0] == '[' + ? !parse_legacy_color(string, &color, NULL, NULL) + : !parse_rgb(string, &color, NULL, NULL)) + { break; + } LOG_DBG("change cursor color to %06x", color); From 8adb52e63a9ac280b30e8af628d0f7ed250e6bd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 5 Apr 2021 22:31:09 +0200 Subject: [PATCH 18/41] =?UTF-8?q?osc:=20parse=5Frgb():=20ensure=20?= =?UTF-8?q?=E2=80=98alpha=E2=80=99=20has=20been=20initialized?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- osc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osc.c b/osc.c index eade736a..99803236 100644 --- a/osc.c +++ b/osc.c @@ -395,7 +395,7 @@ parse_rgb(const char *string, uint32_t *color, bool *_have_alpha, uint8_t g = 256 * (rgb[1] / (double)(1 << (4 * digits[1]))); uint8_t b = 256 * (rgb[2] / (double)(1 << (4 * digits[2]))); - uint16_t alpha; + uint16_t alpha = 0xffff; if (have_alpha) alpha = 65536 * (rgb[3] / (double)(1 << (4 * digits[3]))); From 7fc3b1858652e7d1f910ca81cf501fe23516b40a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 7 Apr 2021 08:00:39 +0200 Subject: [PATCH 19/41] osc: parse_legacy_color(): the alpha component is not a floating point number When using the urxvt extension of the XParseColor format, the alpha component is not a floating point number, but a decimal number in the range 0-100. --- osc.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/osc.c b/osc.c index 99803236..0aa75247 100644 --- a/osc.c +++ b/osc.c @@ -268,19 +268,18 @@ parse_legacy_color(const char *string, uint32_t *color, bool *_have_alpha, uint16_t alpha = 0xffff; if (string[0] == '[') { - /* e.g. \E]11;[0.5]#00ff00 */ + /* e.g. \E]11;[50]#00ff00 */ const char *start = &string[1]; - const char *end = strchr(string, ']'); - if (end == NULL) - return false; - char *_end; - double percent = strtod(start, &_end); - if (_end != end) + errno = 0; + char *end; + unsigned long percent = strtoul(start, &end, 10); + + if (errno != 0 || *end != ']') return false; have_alpha = true; - alpha = 0xffff * percent; + alpha = (0xffff * min(percent, 100) + 50) / 100; string = end + 1; } From 220fdc173ed77e25ea20fd551f2cdcb9db29b259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 7 Apr 2021 08:01:55 +0200 Subject: [PATCH 20/41] =?UTF-8?q?changelog:=20tweak=20wording=20for=20URxv?= =?UTF-8?q?t=E2=80=99s=20XParseColor=20extension?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff80e2f2..54e012f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,7 @@ ## Unreleased ### Added -* Support for URxvt OSC-11 extension to set background alpha +* URxvt OSC-11 extension to set background alpha (https://codeberg.org/dnkl/foot/issues/436). From 660b771396a5a537c8cd4100f4e1f1965cdd429c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 7 Apr 2021 08:02:21 +0200 Subject: [PATCH 21/41] =?UTF-8?q?changelog:=20don=E2=80=99t=20use=20a=20hy?= =?UTF-8?q?phen=20between=20=E2=80=98OSC=E2=80=99=20and=20the=20number?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54e012f7..2a40e6a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,7 +44,7 @@ (https://codeberg.org/dnkl/foot/issues/427). * Wrong action referenced in error message for key binding collisions (https://codeberg.org/dnkl/foot/issues/432). -* OSC-4/104 out-of-bounds accesses to the color table. This was the +* OSC 4/104 out-of-bounds accesses to the color table. This was the reason pywal turned foot windows transparent (https://codeberg.org/dnkl/foot/issues/434). * PTY not being drained when the client application terminates. From 713a53fa3e92a13d8223de97cd1c4c90eff3954d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 7 Apr 2021 08:10:56 +0200 Subject: [PATCH 22/41] doc: foot-ctlseq: mention that we support transparency in OSC 11 --- doc/foot-ctlseqs.7.scd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/foot-ctlseqs.7.scd b/doc/foot-ctlseqs.7.scd index 3c32442e..210e3269 100644 --- a/doc/foot-ctlseqs.7.scd +++ b/doc/foot-ctlseqs.7.scd @@ -583,7 +583,9 @@ All _OSC_ sequences begin with *\\E]*, sometimes abbreviated _OSC_. | \\E] 11 ; _spec_ \\E\\ : xterm : Change the default background color to _spec_, a color in - *XParseColor* format. + XParseColor format. Foot implements URxvt's transparency extension; + e.g. _spec_=*[75]#ff00ff* or _spec_=*rgba:ff/00/ff/bf* (pink with + 75% alpha). | \\E] 12 ; _spec_ \\E\\ : xterm : Change cursor color to _spec_, a color in *XParseColor* format. From e853098f4608d5fa457bc873bb4fcfb23d6c2396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 7 Apr 2021 19:04:25 +0200 Subject: [PATCH 23/41] osc: reset background alpha when resetting the background color --- osc.c | 1 + terminal.c | 1 + 2 files changed, 2 insertions(+) diff --git a/osc.c b/osc.c index 0aa75247..157272d9 100644 --- a/osc.c +++ b/osc.c @@ -824,6 +824,7 @@ osc_dispatch(struct terminal *term) case 111: /* Reset default text background color */ LOG_DBG("resetting background color"); term->colors.bg = term->conf->colors.bg; + term->colors.alpha = term->conf->colors.alpha; term_damage_view(term); term_damage_margins(term); break; diff --git a/terminal.c b/terminal.c index c6b4705c..fd206090 100644 --- a/terminal.c +++ b/terminal.c @@ -1682,6 +1682,7 @@ term_reset(struct terminal *term, bool hard) fdm_del(term->fdm, term->blink.fd); term->blink.fd = -1; term->colors.fg = term->conf->colors.fg; term->colors.bg = term->conf->colors.bg; + term->colors.alpha = term->conf->colors.alpha; memcpy(term->colors.table, term->conf->colors.table, sizeof(term->colors.table)); term->origin = ORIGIN_ABSOLUTE; From d620a7b3b43320985ac788851ee464826ff8f713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 7 Apr 2021 08:09:40 +0200 Subject: [PATCH 24/41] osc: implement OSC 17+19: change selection background/foreground colors And of course, we also implement the corresponding reset sequences, OSC 117+119. --- CHANGELOG.md | 2 ++ doc/foot-ctlseqs.7.scd | 29 ++++++++++++++++++++++------- osc.c | 34 +++++++++++++++++++++++++++++++--- render.c | 6 +++--- terminal.c | 6 ++++++ terminal.h | 3 +++ 6 files changed, 67 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a40e6a5..422dce6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ * URxvt OSC-11 extension to set background alpha (https://codeberg.org/dnkl/foot/issues/436). +* OSC 17+19 - change selection background/foreground color. +* OSC 117+119 - reset selection background/foreground color. ### Changed diff --git a/doc/foot-ctlseqs.7.scd b/doc/foot-ctlseqs.7.scd index 210e3269..78f5dfc8 100644 --- a/doc/foot-ctlseqs.7.scd +++ b/doc/foot-ctlseqs.7.scd @@ -564,7 +564,7 @@ All _OSC_ sequences begin with *\\E]*, sometimes abbreviated _OSC_. | \\E] 4 ; _c_ ; _spec_ \\E\\ : xterm : Change color number _c_ to _spec_, where _spec_ is a color in - *XParseColor* format. foot only supports RGB colors; either + XParseColor format. foot only supports RGB colors; either *rgb://*, or the legacy format (*#rgb*). | \\E] 7 ; _Uri_ \\E\\ : iTerm2 @@ -579,7 +579,7 @@ All _OSC_ sequences begin with *\\E]*, sometimes abbreviated _OSC_. | \\E] 10 ; _spec_ \\E\\ : xterm : Change the default foreground color to _spec_, a color in - *XParseColor* format. + XParseColor format. | \\E] 11 ; _spec_ \\E\\ : xterm : Change the default background color to _spec_, a color in @@ -588,21 +588,30 @@ All _OSC_ sequences begin with *\\E]*, sometimes abbreviated _OSC_. 75% alpha). | \\E] 12 ; _spec_ \\E\\ : xterm -: Change cursor color to _spec_, a color in *XParseColor* format. +: Change cursor color to _spec_, a color in XParseColor format. +| \\E] 17 ; _spec_ \\E\\ +: xterm +: Change selection background color to _spec_, a color in + XParseColor format. +| \\E] 19 ; _spec_ \\E\\ +: xterm +: Change selection foreground color to _spec_, a color in XParseColor + format. | \\E] 52 ; _Pc_ ; ? \\E\\ : xterm : Send clipboard data. _Pc_ can be either *c*, *s* or *p*. *c* uses the clipboard as source, and *s* and *p* uses the primary selection. The response is *OSC 52 ; Pc ; *, - where _Pc_ indicates the source used. + where _Pc_ denotes the source used. | \\E] 52 ; _Pc_ ; _Pd_ \\E\\ : xterm -: Copy _Pd_ (base64 encoded text) to the clipboard. _Pc_ indicates the +: Copy _Pd_ (base64 encoded text) to the clipboard. _Pc_ denotes the target: *c* targets the clipboard and *s* and *p* the primary selection. -| \\E] 104 [; _c_] \\E\\ +| \\E] 104 ; _c_ \\E\\ : xterm -: Reset color number _c_, or all colors (excluding the default +: Reset color number _c_ (multiple semicolon separated _c_ values may + be provided), or all colors (excluding the default foreground/background colors) if _c_ is omitted. | \\E] 110 \\E\\ : xterm @@ -613,6 +622,12 @@ All _OSC_ sequences begin with *\\E]*, sometimes abbreviated _OSC_. | \\E] 112 \\E\\ : xterm : Reset cursor color +| \\E] 117 \\E\\ +: xterm +: Reset selection background color +| \\E] 119 \\E\\ +: xterm +: Reset selection foreground color | \\E] 555 \\E\\ : foot : Flash the entire terminal (foot extension) diff --git a/osc.c b/osc.c index 157272d9..f5aa86a2 100644 --- a/osc.c +++ b/osc.c @@ -679,8 +679,10 @@ osc_dispatch(struct terminal *term) break; case 10: - case 11: { - /* Set default foreground/background color */ + case 11: + case 17: + case 19: { + /* Set default foreground/background/highlight-bg/highlight-fg color */ /* Client queried for current value */ if (strlen(string) == 1 && string[0] == '?') { @@ -714,7 +716,11 @@ osc_dispatch(struct terminal *term) } LOG_DBG("change color definition for %s to %06x", - param == 10 ? "foreground" : "background", color); + param == 10 ? "foreground" : + param == 11 ? "background" : + param == 17 ? "selection background" : + "selection foreground", + color); switch (param) { case 10: @@ -726,6 +732,16 @@ osc_dispatch(struct terminal *term) if (have_alpha) term->colors.alpha = alpha; break; + + case 17: + term->colors.selection_bg = color; + term->colors.use_custom_selection = true; + break; + + case 19: + term->colors.selection_fg = color; + term->colors.use_custom_selection = true; + break; } term_damage_view(term); @@ -836,6 +852,18 @@ osc_dispatch(struct terminal *term) term_damage_cursor(term); break; + case 117: + LOG_DBG("resetting selection background color"); + term->colors.selection_bg = term->conf->colors.selection_bg; + term->colors.use_custom_selection = term->conf->colors.use_custom.selection; + break; + + case 119: + LOG_DBG("resetting selection foreground color"); + term->colors.selection_fg = term->conf->colors.selection_fg; + term->colors.use_custom_selection = term->conf->colors.use_custom.selection; + break; + case 555: osc_flash(term); break; diff --git a/render.c b/render.c index a0c0696e..cee44e54 100644 --- a/render.c +++ b/render.c @@ -416,9 +416,9 @@ render_cell(struct terminal *term, pixman_image_t *pix, uint32_t _fg = 0; uint32_t _bg = 0; - if (is_selected && term->conf->colors.use_custom.selection) { - _fg = term->conf->colors.selection_fg; - _bg = term->conf->colors.selection_bg; + if (is_selected && term->colors.use_custom_selection) { + _fg = term->colors.selection_fg; + _bg = term->colors.selection_bg; } else { /* Use cell specific color, if set, otherwise the default colors (possible reversed) */ _fg = cell->attrs.have_fg ? cell->attrs.fg : term->colors.fg; diff --git a/terminal.c b/terminal.c index fd206090..c05eb84e 100644 --- a/terminal.c +++ b/terminal.c @@ -1087,6 +1087,9 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .fg = conf->colors.fg, .bg = conf->colors.bg, .alpha = conf->colors.alpha, + .selection_fg = conf->colors.selection_fg, + .selection_bg = conf->colors.selection_bg, + .use_custom_selection = conf->colors.use_custom.selection, }, .origin = ORIGIN_ABSOLUTE, .cursor_style = conf->cursor.style, @@ -1683,6 +1686,9 @@ term_reset(struct terminal *term, bool hard) term->colors.fg = term->conf->colors.fg; term->colors.bg = term->conf->colors.bg; term->colors.alpha = term->conf->colors.alpha; + term->colors.selection_fg = term->conf->colors.selection_fg; + term->colors.selection_bg = term->conf->colors.selection_bg; + term->colors.use_custom_selection = term->conf->colors.use_custom.selection; memcpy(term->colors.table, term->conf->colors.table, sizeof(term->colors.table)); term->origin = ORIGIN_ABSOLUTE; diff --git a/terminal.h b/terminal.h index 7b463d22..3583cf61 100644 --- a/terminal.h +++ b/terminal.h @@ -407,6 +407,9 @@ struct terminal { uint32_t bg; uint32_t table[256]; uint16_t alpha; + uint32_t selection_fg; + uint32_t selection_bg; + bool use_custom_selection; } colors; enum cursor_style cursor_style; From 24e88dd224888c6fa7d621e4871e81b45ea22b50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 8 Apr 2021 12:58:47 +0200 Subject: [PATCH 25/41] =?UTF-8?q?term/vt:=20only=20do=20reverse-wrapping?= =?UTF-8?q?=20(=E2=80=98bw=E2=80=99)=20on=20cub1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Foot currently does reverse-wrapping (‘auto_left_margin’, or ’bw’) on everything that calls ‘term_cursor_left()’. This is wrong; it should only be done for cub1. From man terminfo: auto_left_margin | bw | bw | cub1 wraps from column 0 to last column This patch moves the reverse-wrapping logic from term_cursor_left() to the handling of BS (backspace). Closes #441 --- terminal.c | 41 +++-------------------------------------- vt.c | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 40 deletions(-) diff --git a/terminal.c b/terminal.c index c05eb84e..e55230b4 100644 --- a/terminal.c +++ b/terminal.c @@ -1988,44 +1988,9 @@ term_cursor_home(struct terminal *term) void term_cursor_left(struct terminal *term, int count) { - xassert(count >= 0); - int new_col = term->grid->cursor.point.col - count; - - /* Reverse wrap */ - if (unlikely(new_col < 0)) { - if (likely(term->reverse_wrap && term->auto_margin)) { - - /* Number of rows to reverse wrap through */ - int row_count = (abs(new_col) - 1) / term->cols + 1; - - /* Row number cursor will end up on */ - int new_row_no = term->grid->cursor.point.row - row_count; - - /* New column number */ - new_col = term->cols - ((abs(new_col) - 1) % term->cols + 1); - xassert(new_col >= 0 && new_col < term->cols); - - /* Don't back up past the scroll region */ - /* TODO: should this be allowed? */ - if (new_row_no < term->scroll_region.start) { - new_row_no = term->scroll_region.start; - new_col = 0; - } - - struct row *new_row = grid_row(term->grid, new_row_no); - term->grid->cursor.point.col = new_col; - term->grid->cursor.point.row = new_row_no; - term->grid->cursor.lcf = false; - term->grid->cur_row = new_row; - return; - } - - /* Reverse wrap disabled - don't let cursor move past first column */ - new_col = 0; - } - - xassert(new_col >= 0); - term->grid->cursor.point.col = new_col; + int move_amount = min(term->grid->cursor.point.col, count); + term->grid->cursor.point.col -= move_amount; + xassert(term->grid->cursor.point.col >= 0); term->grid->cursor.lcf = false; } diff --git a/vt.c b/vt.c index af4691ea..d3523efd 100644 --- a/vt.c +++ b/vt.c @@ -142,8 +142,21 @@ action_execute(struct terminal *term, uint8_t c) #else if (term->grid->cursor.lcf) term->grid->cursor.lcf = false; - else - term_cursor_left(term, 1); + else { + /* Reverse wrap */ + if (unlikely(term->grid->cursor.point.col == 0) && + likely(term->reverse_wrap && term->auto_margin)) + { + if (term->grid->cursor.point.row <= term->scroll_region.start) { + /* Don’t wrap past, or inside, the scrolling region(?) */ + } else + term_cursor_to( + term, + term->grid->cursor.point.row - 1, + term->cols - 1); + } else + term_cursor_left(term, 1); + } #endif break; From c005c16504d7b8adf36044564a3e91f1ce3aed40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 8 Apr 2021 13:11:37 +0200 Subject: [PATCH 26/41] changelog: auto_left_margin on cub1 only --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 422dce6c..2e825870 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,8 @@ reason pywal turned foot windows transparent (https://codeberg.org/dnkl/foot/issues/434). * PTY not being drained when the client application terminates. +* `auto_left_margin` not being limited to `cub1` + (https://codeberg.org/dnkl/foot/issues/441). ### Security From 0f792fa1ce0eaf83d053f88d58b84600299a6c94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 8 Apr 2021 13:50:02 +0200 Subject: [PATCH 27/41] changelog: rewrite entry for OSC 17/117/19/119 --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e825870..a30498b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,8 +30,8 @@ * URxvt OSC-11 extension to set background alpha (https://codeberg.org/dnkl/foot/issues/436). -* OSC 17+19 - change selection background/foreground color. -* OSC 117+119 - reset selection background/foreground color. +* OSC 17/117/19/119 - change/reset selection background/foreground + color. ### Changed From 2efd1016ce9174cffbfe2c800038a1f141fd712c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 9 Apr 2021 21:47:57 +0200 Subject: [PATCH 28/41] render: draw underline cursor below text underline This ensures the cursor is visible on cells where the text is underlined. Closes #415 --- CHANGELOG.md | 5 +++++ render.c | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a30498b4..496920dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,11 @@ ### Changed + +* Underline cursor is now rendered below text underline + (https://codeberg.org/dnkl/foot/issues/415). + + ### Deprecated ### Removed ### Fixed diff --git a/render.c b/render.c index cee44e54..ddd685b6 100644 --- a/render.c +++ b/render.c @@ -387,9 +387,10 @@ draw_cursor(const struct terminal *term, const struct cell *cell, if (likely(term->cursor_blink.state == CURSOR_BLINK_ON || !term->kbd_focus)) { + struct fcft_font *font = attrs_to_font(term, &cell->attrs); draw_underline( - term, pix, attrs_to_font(term, &cell->attrs), &cursor_color, - x, y, cols); + term, pix, font, &cursor_color, + x, y + font->underline.thickness, cols); } break; } From ce321e663e6974fd622a36777c67c7a156d01fa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 9 Apr 2021 23:19:20 +0200 Subject: [PATCH 29/41] config: add box-drawings-uses-font-glyphs=no|yes option When disabled, we render box drawing characters ourselves. This is the default. When enabled, we instead use font glyphs. I.e. no special treatment. Closes #430 --- CHANGELOG.md | 2 ++ config.c | 4 ++++ config.h | 2 ++ doc/foot.ini.5.scd | 18 ++++++++++++++++++ foot.ini | 1 + render.c | 4 +++- 6 files changed, 30 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 496920dd..a97e4e53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,8 @@ (https://codeberg.org/dnkl/foot/issues/436). * OSC 17/117/19/119 - change/reset selection background/foreground color. +* `box-drawings-uses-font-glyphs=yes|no` option to `foot.ini` + (https://codeberg.org/dnkl/foot/issues/430). ### Changed diff --git a/config.c b/config.c index 8809163c..653c3f8a 100644 --- a/config.c +++ b/config.c @@ -770,6 +770,9 @@ parse_section_main(const char *key, const char *value, struct config *conf, } } + else if (strcmp(key, "box-drawings-uses-font-glyphs") == 0) + conf->box_drawings_uses_font_glyphs = str_to_bool(value); + else { LOG_AND_NOTIFY_ERR("%s:%u: [default]: %s: invalid key", path, lineno, key); return false; @@ -2198,6 +2201,7 @@ config_load(struct config *conf, const char *conf_path, .letter_spacing = { .pt = 0, .px = 0, }, .horizontal_letter_offset = {.pt = 0, .px = 0, }, .vertical_letter_offset = {.pt = 0, .px = 0, }, + .box_drawings_uses_font_glyphs = false, .dpi_aware = DPI_AWARE_AUTO, /* DPI-aware when scaling-factor == 1 */ .scrollback = { .lines = 1000, diff --git a/config.h b/config.h index 696c57b6..d64c5e98 100644 --- a/config.h +++ b/config.h @@ -99,6 +99,8 @@ struct config { struct pt_or_px horizontal_letter_offset; struct pt_or_px vertical_letter_offset; + bool box_drawings_uses_font_glyphs; + struct { int lines; diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index dcf644ef..a6e4cd30 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -96,6 +96,24 @@ in this order: Default: _0_. +*box-drawings-uses-font-glyphs* + Boolean. When disabled, foot generates box/line drawing characters + itself. The are several advantages to doing this instead of using + font glyphs: + + - No antaliasing effects where e.g. line endpoints appear dimmer. + - Line- and box characters are guaranteed to span the entire cell, + resulting in a gap-less appearance. + - No alignment issues, i.e. lines are centered when they should be. + - Many fonts lack some, or all, of the line- and box drawing + characters, causing fallback fonts to be used, which results + in out-of-place (for example, badly sized) looking glyphs. + + When enabled, box/line drawing characters are rendered using font + glyphs. This may result in a more uniform look, in some use cases. + + Default: _no_. + *dpi-aware* *auto*, *yes*, or *no*. When set to *yes*, fonts are sized using the monitor's DPI, making a font of a given size have the same diff --git a/foot.ini b/foot.ini index 0c2d3f5b..a194a145 100644 --- a/foot.ini +++ b/foot.ini @@ -12,6 +12,7 @@ # letter-spacing=0 # horizontal-letter-offset=0 # vertical-letter-offset=0 +# box-drawings-uses-font-glyphs=no # dpi-aware=yes # initial-window-size-pixels=700x500 # Or, diff --git a/render.c b/render.c index ddd685b6..71cec0b7 100644 --- a/render.c +++ b/render.c @@ -466,7 +466,9 @@ render_cell(struct terminal *term, pixman_image_t *pix, } if (unlikely((base >= 0x2500 && base <= 0x259f) || - (base >= 0x1fb00 && base <= 0x1fb3b))) { + (base >= 0x1fb00 && base <= 0x1fb3b)) && + likely(!term->conf->box_drawings_uses_font_glyphs)) + { /* Box drawing characters */ size_t idx = base >= 0x1fb00 ? base - 0x1fb00 + 160 : base - 0x2500; xassert(idx < ALEN(term->box_drawing)); From 39d65bf0831db2710c5dc800ec2f346ff33c7678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 9 Apr 2021 23:54:36 +0200 Subject: [PATCH 30/41] doc: foot.ini: codespell: antaliasing -> antialiasing --- doc/foot.ini.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index a6e4cd30..90dfde13 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -101,7 +101,7 @@ in this order: itself. The are several advantages to doing this instead of using font glyphs: - - No antaliasing effects where e.g. line endpoints appear dimmer. + - No antialiasing effects where e.g. line endpoints appear dimmer. - Line- and box characters are guaranteed to span the entire cell, resulting in a gap-less appearance. - No alignment issues, i.e. lines are centered when they should be. From 4325d5a4ab478e6b0f0a6b436fb9a131a6e2385a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 10 Apr 2021 11:24:23 +0200 Subject: [PATCH 31/41] doc: foot.ini: re-phrase the box-drawings-uses-font-glyphs section --- doc/foot.ini.5.scd | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index 90dfde13..675f9bf8 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -101,13 +101,14 @@ in this order: itself. The are several advantages to doing this instead of using font glyphs: - - No antialiasing effects where e.g. line endpoints appear dimmer. + - No antialiasing effects where e.g. line endpoints appear + dimmed down, or blurred. - Line- and box characters are guaranteed to span the entire cell, resulting in a gap-less appearance. - No alignment issues, i.e. lines are centered when they should be. - Many fonts lack some, or all, of the line- and box drawing characters, causing fallback fonts to be used, which results - in out-of-place (for example, badly sized) looking glyphs. + in out-of-place looking glyphs (for example, badly sized). When enabled, box/line drawing characters are rendered using font glyphs. This may result in a more uniform look, in some use cases. From 8561fdb0047f307e9c2a7a0b64dbc9e6d8d080a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 10 Apr 2021 13:16:39 +0200 Subject: [PATCH 32/41] =?UTF-8?q?render:=20don=E2=80=99t=20let=20URL=20jum?= =?UTF-8?q?p=20label=20sub-surfaces=20extend=20outside=20window=20geometry?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have no guarantee that sub-surfaces extending outside the window geometry are rendered correctly (if at all). For example, both Sway and River will render the window border on top of the sub-surface. Future versions of Sway may clip the sub-surface. Since jump-labels are positioned slightly above, and to the left of the URLs first character, having a label on either the top row, or on the first column, will likely position it outside the window. This is handled by simply setting x/y to 0 (or, to -margin, since the label coordinate is later offsetted with the window margins). Second, if the label is very long, it may extend outside the window. This is very unusual for labels only showing the key, and not the URL itself, but could happen in this case too, if e.g. the user has configured double-width key characters. This is handled by calculating its maximum width, and then truncating the label. Although very unlikely, it is possible for a label to also extend outside the window’s vertical size. This could happen for very small font sizes, where the label’s own margins are large, relative to the font size. This case is currently not handled. Closes #443 --- CHANGELOG.md | 2 ++ render.c | 85 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 60 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a97e4e53..b1244531 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,8 @@ * Underline cursor is now rendered below text underline (https://codeberg.org/dnkl/foot/issues/415). +* Foot now tries much harder to keep URL jump labels inside the window + geometry (https://codeberg.org/dnkl/foot/issues/443). ### Deprecated diff --git a/render.c b/render.c index 71cec0b7..944d24b2 100644 --- a/render.c +++ b/render.c @@ -2632,6 +2632,26 @@ render_urls(struct terminal *term) continue; } + int col = pos->col; + int row = pos->row - term->grid->view; + while (row < 0) + row += term->grid->num_rows; + row &= (term->grid->num_rows - 1); + + /* Position label slightly above and to the left */ + int x = col * term->cell_width - 15 * term->cell_width / 10; + int y = row * term->cell_height - 5 * term->cell_height / 10; + + /* Don’t position it outside our window */ + if (x < -term->margins.left) + x = -term->margins.left; + if (y < -term->margins.top) + y = -term->margins.top; + + /* Maximum width of label, in pixels */ + const int max_width = + term->width - term->margins.left - term->margins.right - x; + const size_t key_len = wcslen(key); size_t url_len = mbstowcs(NULL, url->url, 0); @@ -2641,32 +2661,59 @@ render_urls(struct terminal *term) wchar_t url_wchars[url_len + 1]; mbstowcs(url_wchars, url->url, url_len + 1); + /* Format label, not yet subject to any size limitations */ size_t chars = key_len + (show_url ? (2 + url_len) : 0); - - const size_t max_chars = 50; - chars = min(chars, max_chars); - - wchar_t label[chars + 2]; - label[chars] = L'…'; - label[chars + 1] = L'\0'; + wchar_t label[chars + 1]; + label[chars] = L'\0'; if (show_url) swprintf(label, chars + 1, L"%ls: %ls", key, url_wchars); else - wcsncpy(label, key, chars + 1); + wcsncpy(label, key, chars); + /* Upper case the key characters */ for (size_t i = 0; i < wcslen(key); i++) label[i] = towupper(label[i]); + /* Blank already entered key characters */ for (size_t i = 0; i < entered_key_len; i++) label[i] = L' '; - size_t len = wcslen(label); - int cols = wcswidth(label, len); - + /* + * Don’t extend outside our window + * + * Truncate label so that it doesn’t extend outside our + * window. + * + * Do it in a way such that we don’t cut the label in the + * middle of a double-width character. + */ const int scale = term->scale; const int x_margin = 2 * scale; const int y_margin = 1 * scale; + const int max_cols = max_width / term->cell_width; + + int cols = 0; + + for (size_t i = 0; i <= wcslen(label); i++) { + int _cols = wcswidth(label, i); + + if (_cols == (size_t)-1) + continue; + + if (_cols >= max_cols) { + if (i > 0) + label[i - 1] = L'…'; + label[i] = L'\0'; + cols = max_cols; + break; + } + cols = _cols; + } + + if (cols == 0) + continue; + const int width = (2 * x_margin + cols * term->cell_width + scale - 1) / scale * scale; const int height = @@ -2675,22 +2722,6 @@ render_urls(struct terminal *term) struct buffer *buf = shm_get_buffer( term->wl->shm, width, height, shm_cookie_url(url), false, 1); - int col = pos->col; - int row = pos->row - term->grid->view; - while (row < 0) - row += term->grid->num_rows; - row &= (term->grid->num_rows - 1); - - int x = col * term->cell_width - 15 * term->cell_width / 10; - int y = row * term->cell_height - 5 * term->cell_height / 10; - - if (x < 0) - x = 0; -#if 0 - if (y < 0) - y += 15 * term->cell_height / 10; -#endif - wl_subsurface_set_position( sub_surf, (term->margins.left + x) / term->scale, From f62ac3d6831f69b8811e340227452cc540e368b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 14 Apr 2021 11:09:02 +0200 Subject: [PATCH 33/41] render: no need to blend fully opaque sixel images - just blit them --- render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render.c b/render.c index 944d24b2..495c12a6 100644 --- a/render.c +++ b/render.c @@ -935,7 +935,7 @@ render_sixel_chunk(struct terminal *term, pixman_image_t *pix, const struct sixe //LOG_DBG("sixel chunk: %dx%d %dx%d", x, y, width, height); pixman_image_composite32( - PIXMAN_OP_OVER, + sixel->opaque ? PIXMAN_OP_SRC : PIXMAN_OP_OVER, sixel->pix, NULL, pix, From e85c19d54628923d99761e1017779a3b3c806a61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 17 Apr 2021 22:11:14 +0200 Subject: [PATCH 34/41] =?UTF-8?q?term:=20attributes=20struct:=20use=20?= =?UTF-8?q?=E2=80=98bool=E2=80=99=20instead=20of=20=E2=80=98uint32=5Ft?= =?UTF-8?q?=E2=80=99=20for=201-bit=20members?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- terminal.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/terminal.h b/terminal.h index 3583cf61..d8b1bf31 100644 --- a/terminal.h +++ b/terminal.h @@ -26,25 +26,25 @@ * Note that the members are laid out optimized for x86 */ struct attributes { - uint32_t bold:1; - uint32_t dim:1; - uint32_t italic:1; - uint32_t underline:1; - uint32_t strikethrough:1; - uint32_t blink:1; - uint32_t conceal:1; - uint32_t reverse:1; + bool bold:1; + bool dim:1; + bool italic:1; + bool underline:1; + bool strikethrough:1; + bool blink:1; + bool conceal:1; + bool reverse:1; uint32_t fg:24; - uint32_t clean:1; - uint32_t have_fg:1; - uint32_t have_bg:1; + bool clean:1; + bool have_fg:1; + bool have_bg:1; uint32_t selected:2; - uint32_t url:1; + bool url:1; uint32_t reserved:2; uint32_t bg:24; }; -static_assert(sizeof(struct attributes) == 8, "bad size"); +static_assert(sizeof(struct attributes) == 8, "VT attribute struct too large"); #define CELL_COMB_CHARS_LO 0x40000000ul #define CELL_COMB_CHARS_HI 0x400ffffful From 98db408e1a85dce809a9bde5caf11120b0710122 Mon Sep 17 00:00:00 2001 From: Oleh Hushchenkov Date: Sun, 18 Apr 2021 13:56:56 +0300 Subject: [PATCH 35/41] term: stop reading on eof --- terminal.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/terminal.c b/terminal.c index e55230b4..ef33d975 100644 --- a/terminal.c +++ b/terminal.c @@ -247,6 +247,11 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data) LOG_ERRNO("failed to read from pseudo terminal"); return false; + } else if (count == 0) { + /* + * Reached end-of-file + */ + break; } vt_from_slave(term, buf, count); From a2251a399ce669b8f0e2f2b52b4600217b115ff8 Mon Sep 17 00:00:00 2001 From: Oleh Hushchenkov Date: Sun, 18 Apr 2021 14:05:28 +0300 Subject: [PATCH 36/41] Fix comment --- terminal.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/terminal.c b/terminal.c index ef33d975..bcb8a868 100644 --- a/terminal.c +++ b/terminal.c @@ -248,9 +248,7 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data) LOG_ERRNO("failed to read from pseudo terminal"); return false; } else if (count == 0) { - /* - * Reached end-of-file - */ + /* Reached end-of-file */ break; } From 11e8ff9dc5a4afe3f4cbcd8042c43511288d8713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 17 Apr 2021 21:02:02 +0200 Subject: [PATCH 37/41] render: brighten: use corresponding bright palette color for base 8 colors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When brightening one of the 8 base (“regular”) colors, use the corresponding bright palette color, instead of increasing the luminance. Closes #449 --- CHANGELOG.md | 3 +++ render.c | 13 +++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1244531..0da8880d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,9 @@ (https://codeberg.org/dnkl/foot/issues/415). * Foot now tries much harder to keep URL jump labels inside the window geometry (https://codeberg.org/dnkl/foot/issues/443). +* `bold-text-in-bright` now uses the corresponding bright palette + color when the color to brighten matches one of the base 8 colors + (https://codeberg.org/dnkl/foot/issues/449). ### Deprecated diff --git a/render.c b/render.c index 495c12a6..3ca0deeb 100644 --- a/render.c +++ b/render.c @@ -252,8 +252,17 @@ color_dim(uint32_t color) } static inline uint32_t -color_brighten(uint32_t color) +color_brighten(const struct terminal *term, uint32_t color) { + /* + * First try to match the color against the base 8 colors. If we + * find a match, return the corresponding bright color. + */ + for (size_t i = 0; i < 8; i++) { + if (term->colors.table[i] == color) + return term->colors.table[i + 8]; + } + int hue, sat, lum; rgb_to_hsl(color, &hue, &sat, &lum); return hsl_to_rgb(hue, sat, min(100, lum * 1.3)); @@ -435,7 +444,7 @@ render_cell(struct terminal *term, pixman_image_t *pix, if (cell->attrs.dim) _fg = color_dim(_fg); if (term->conf->bold_in_bright && cell->attrs.bold) - _fg = color_brighten(_fg); + _fg = color_brighten(term, _fg); if (cell->attrs.blink && term->blink.state == BLINK_OFF) _fg = color_dim(_fg); From 1df48fcb33f2e6009e7e4055662e441f2f0c3314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 17 Apr 2021 21:57:08 +0200 Subject: [PATCH 38/41] =?UTF-8?q?config:=20bold-text-in-bright:=20add=20?= =?UTF-8?q?=E2=80=98palette-based=E2=80=99=20as=20a=20special=20value?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When ‘bold-text-in-bright’ is set ‘to palette-based’, colors matching one of the 8 regular palette colors are brightened by using the corresponding bright palette color. Other colors, or all colors if ‘bold-text-in-bright’ is set to ‘yes|true’, are brightened by increasing the luminance. --- CHANGELOG.md | 6 ++++-- config.c | 16 +++++++++++++--- config.h | 6 +++++- doc/foot.ini.5.scd | 12 ++++++++++-- render.c | 10 ++++++---- 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0da8880d..e9beff07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,8 +42,10 @@ (https://codeberg.org/dnkl/foot/issues/415). * Foot now tries much harder to keep URL jump labels inside the window geometry (https://codeberg.org/dnkl/foot/issues/443). -* `bold-text-in-bright` now uses the corresponding bright palette - color when the color to brighten matches one of the base 8 colors +* `bold-text-in-bright` may now be set to `palette-based`, in which + case it will use the corresponding bright palette color when the + color to brighten matches one of the base 8 colors, instead of + increasing the luminance (https://codeberg.org/dnkl/foot/issues/449). diff --git a/config.c b/config.c index 653c3f8a..3aed1e7d 100644 --- a/config.c +++ b/config.c @@ -583,8 +583,15 @@ parse_section_main(const char *key, const char *value, struct config *conf, conf->resize_delay_ms = ms; } - else if (strcmp(key, "bold-text-in-bright") == 0) - conf->bold_in_bright = str_to_bool(value); + else if (strcmp(key, "bold-text-in-bright") == 0) { + if (strcmp(value, "palette-based") == 0) { + conf->bold_in_bright.enabled = true; + conf->bold_in_bright.palette_based = true; + } else { + conf->bold_in_bright.enabled = str_to_bool(value); + conf->bold_in_bright.palette_based = false; + } + } else if (strcmp(key, "bell") == 0) { if (strcmp(value, "set-urgency") == 0) @@ -2193,7 +2200,10 @@ config_load(struct config *conf, const char *conf_path, .pad_x = 2, .pad_y = 2, .resize_delay_ms = 100, - .bold_in_bright = false, + .bold_in_bright = { + .enabled = false, + .palette_based = false, + }, .bell_action = BELL_ACTION_NONE, .startup_mode = STARTUP_WINDOWED, .fonts = {tll_init(), tll_init(), tll_init(), tll_init()}, diff --git a/config.h b/config.h index d64c5e98..06184658 100644 --- a/config.h +++ b/config.h @@ -79,7 +79,11 @@ struct config { bool center; uint16_t resize_delay_ms; - bool bold_in_bright; + struct { + bool enabled; + bool palette_based; + } bold_in_bright; + enum { BELL_ACTION_NONE, BELL_ACTION_URGENT, diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index 675f9bf8..4af48307 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -200,8 +200,16 @@ in this order: apply window management rules. Default: _foot_. *bold-text-in-bright* - Boolean. When enabled, bold text is rendered in a brighter color - (in addition to using a bold font). Default: _no_. + Semi-boolean. When enabled, bold text is rendered in a brighter + color (in addition to using a bold font). The color is brightened + by increasing its luminance. + + If set to *palette-based*, rather than a simple *yes|true*, colors + matching one of the 8 regular palette colors will be brightened + using the corresponding bright palette color. Other colors will be + brightened by increasing the luminance. + + Default: _no_. *bell* Action to perform when receiving a *BEL* character. Can be set to diff --git a/render.c b/render.c index 3ca0deeb..5efc7c67 100644 --- a/render.c +++ b/render.c @@ -258,9 +258,11 @@ color_brighten(const struct terminal *term, uint32_t color) * First try to match the color against the base 8 colors. If we * find a match, return the corresponding bright color. */ - for (size_t i = 0; i < 8; i++) { - if (term->colors.table[i] == color) - return term->colors.table[i + 8]; + if (term->conf->bold_in_bright.palette_based) { + for (size_t i = 0; i < 8; i++) { + if (term->colors.table[i] == color) + return term->colors.table[i + 8]; + } } int hue, sat, lum; @@ -443,7 +445,7 @@ render_cell(struct terminal *term, pixman_image_t *pix, if (cell->attrs.dim) _fg = color_dim(_fg); - if (term->conf->bold_in_bright && cell->attrs.bold) + if (term->conf->bold_in_bright.enabled && cell->attrs.bold) _fg = color_brighten(term, _fg); if (cell->attrs.blink && term->blink.state == BLINK_OFF) From 2f8ee9e61d5006bdd24c08f1a3cf710de610634e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 18 Apr 2021 20:11:27 +0200 Subject: [PATCH 39/41] =?UTF-8?q?changelog:=20add=20cglogic=20to=20?= =?UTF-8?q?=E2=80=98contributors=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9beff07..cb19dee3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,8 @@ ### Security ### Contributors +* [cglogic](https://codeberg.org/cglogic) + ## 1.7.1 From 7e2e9d4de82f25515f25811f88c2bf9b28932335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 18 Apr 2021 20:12:26 +0200 Subject: [PATCH 40/41] changelog: prepare for 1.7.2 --- CHANGELOG.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb19dee3..0fe6984a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -* [Unreleased](#unreleased) +* [1.7.2](#1-7-2) * [1.7.1](#1-7-1) * [1.7.0](#1-7-0) * [1.6.4](#1-6-4) @@ -25,7 +25,8 @@ * [1.2.0](#1-2-0) -## Unreleased +## 1.7.2 + ### Added * URxvt OSC-11 extension to set background alpha @@ -49,8 +50,6 @@ (https://codeberg.org/dnkl/foot/issues/449). -### Deprecated -### Removed ### Fixed * Reverted _"Consumed modifiers are no longer sent to the client @@ -68,7 +67,6 @@ (https://codeberg.org/dnkl/foot/issues/441). -### Security ### Contributors * [cglogic](https://codeberg.org/cglogic) From 0d4e61bbe801eb4f0d8618bb7001497f1f2ea834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 18 Apr 2021 20:12:40 +0200 Subject: [PATCH 41/41] meson/pkgbuild: bump version to 1.7.2 --- PKGBUILD | 2 +- meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 43f6a486..6eabe0b5 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,5 +1,5 @@ pkgname=('foot-git' 'foot-terminfo-git') -pkgver=1.7.1 +pkgver=1.7.2 pkgrel=1 arch=('x86_64' 'aarch64') url=https://codeberg.org/dnkl/foot diff --git a/meson.build b/meson.build index b8ba12e8..50cc9eb5 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('foot', 'c', - version: '1.7.1', + version: '1.7.2', license: 'MIT', meson_version: '>=0.53.0', default_options: [