diff options
author | Phil Jones <philj56@gmail.com> | 2022-10-05 14:35:12 +0100 |
---|---|---|
committer | Phil Jones <philj56@gmail.com> | 2022-10-05 14:35:12 +0100 |
commit | 4f13d9c88e8a00ccb9ba8d5380db2f93d3f67908 (patch) | |
tree | 91506378e4d30edad5178238267d9a3132dcf146 /src | |
parent | 803b0d14b7ac8ea03105613fa25849d460073357 (diff) |
Add options to hide input for passwords etc.
Diffstat (limited to 'src')
-rw-r--r-- | src/config.c | 34 | ||||
-rw-r--r-- | src/entry.h | 3 | ||||
-rw-r--r-- | src/entry_backend/harfbuzz.c | 9 | ||||
-rw-r--r-- | src/entry_backend/pango.c | 17 | ||||
-rw-r--r-- | src/main.c | 5 |
5 files changed, 66 insertions, 2 deletions
diff --git a/src/config.c b/src/config.c index fb00fd6..59b8012 100644 --- a/src/config.c +++ b/src/config.c @@ -33,6 +33,7 @@ static uint32_t fixup_percentage(uint32_t value, uint32_t base, bool is_percent, static uint32_t parse_anchor(const char *filename, size_t lineno, const char *str, bool *err); static bool parse_bool(const char *filename, size_t lineno, const char *str, bool *err); +static wchar_t parse_wchar(const char *filename, size_t lineno, const char *str, bool *err); static struct color parse_color(const char *filename, size_t lineno, const char *str, bool *err); static uint32_t parse_uint32(const char *filename, size_t lineno, const char *str, bool *err); static int32_t parse_int32(const char *filename, size_t lineno, const char *str, bool *err); @@ -357,6 +358,22 @@ bool parse_option(struct tofi *tofi, const char *filename, size_t lineno, const tofi->fuzzy_match = parse_bool(filename, lineno, value, &err); } else if (strcasecmp(option, "require-match") == 0) { tofi->require_match = parse_bool(filename, lineno, value, &err); + } else if (strcasecmp(option, "hide-input") == 0) { + tofi->window.entry.hide_input = parse_bool(filename, lineno, value, &err); + } else if (strcasecmp(option, "hidden-character") == 0) { + /* Unicode handling is ugly. */ + wchar_t wc = parse_wchar(filename, lineno, value, &err); + size_t buf_len = N_ELEM(tofi->window.entry.hidden_character_mb) + 1; + char *buf = xmalloc(buf_len); + size_t char_len = snprintf(buf, buf_len, "%lc", wc); + if (char_len >= buf_len) { + PARSE_ERROR(filename, lineno, "Character \"%lc\" is too large.\n", value); + err = true; + } else { + memcpy(tofi->window.entry.hidden_character_mb, buf, char_len); + tofi->window.entry.hidden_character_mb_length = char_len; + } + free(buf); } else if (strcasecmp(option, "drun-launch") == 0) { tofi->drun_launch = parse_bool(filename, lineno, value, &err); } else if (strcasecmp(option, "drun-print-exec") == 0) { @@ -507,6 +524,23 @@ bool parse_bool(const char *filename, size_t lineno, const char *str, bool *err) return false; } +wchar_t parse_wchar(const char *filename, size_t lineno, const char *str, bool *err) +{ + size_t len = strlen(str); + wchar_t ch; + size_t ret = mbrtowc(&ch, str, len, NULL); + if (ret == (size_t)-2) { + return 0; + } else if (ret != len) { + PARSE_ERROR(filename, lineno, "Failed to parse \"%s\" as a character.\n", str); + if (err) { + *err = true; + } + return 0; + } + return ch; +} + uint32_t parse_anchor(const char *filename, size_t lineno, const char *str, bool *err) { if(strcasecmp(str, "top-left") == 0) { diff --git a/src/entry.h b/src/entry.h index 46ec65f..6b547e0 100644 --- a/src/entry.h +++ b/src/entry.h @@ -49,6 +49,9 @@ struct entry { /* Options */ bool drun; bool horizontal; + bool hide_input; + char hidden_character_mb[4]; + uint32_t hidden_character_mb_length; uint32_t num_results; uint32_t num_results_drawn; uint32_t last_num_results_drawn; diff --git a/src/entry_backend/harfbuzz.c b/src/entry_backend/harfbuzz.c index 2834d9d..c5fc07e 100644 --- a/src/entry_backend/harfbuzz.c +++ b/src/entry_backend/harfbuzz.c @@ -230,7 +230,14 @@ void entry_backend_harfbuzz_update(struct entry *entry) /* Render the entry text */ hb_buffer_clear_contents(buffer); setup_hb_buffer(buffer); - hb_buffer_add_utf8(buffer, entry->input_mb, -1, 0, -1); + if (entry->hide_input) { + size_t char_len = N_ELEM(entry->hidden_character_mb); + for (size_t i = 0; i < entry->input_length; i++) { + hb_buffer_add_utf8(buffer, entry->hidden_character_mb, char_len, 0, char_len); + } + } else { + hb_buffer_add_utf8(buffer, entry->input_mb, -1, 0, -1); + } hb_shape(entry->harfbuzz.hb_font, buffer, NULL, 0); extents = render_hb_buffer(cr, buffer); extents.x_advance = MAX(extents.x_advance, entry->input_width); diff --git a/src/entry_backend/pango.c b/src/entry_backend/pango.c index d4737a1..01fc153 100644 --- a/src/entry_backend/pango.c +++ b/src/entry_backend/pango.c @@ -85,7 +85,22 @@ void entry_backend_pango_update(struct entry *entry) cairo_translate(cr, entry->prompt_padding, 0); /* Render the entry text */ - pango_layout_set_text(layout, entry->input_mb, -1); + if (entry->hide_input) { + /* + * Pango needs to be passed the whole text at once, so we need + * to manually replicate the replacement character in a buffer. + */ + static char buf[sizeof(entry->input_mb)]; + uint32_t char_len = entry->hidden_character_mb_length; + for (size_t i = 0; i < entry->input_length; i++) { + for (size_t j = 0; j < char_len; j++) { + buf[i * char_len + j] = entry->hidden_character_mb[j]; + } + } + pango_layout_set_text(layout, buf, -1); + } else { + pango_layout_set_text(layout, entry->input_mb, -1); + } pango_cairo_update_layout(cr, layout); pango_cairo_show_layout(cr, layout); pango_layout_get_pixel_extents(entry->pango.layout, &ink_rect, &logical_rect); @@ -814,6 +814,8 @@ static void usage() " --history <true|false> Sort results by number of usages.\n" " --fuzzy-match <true|false> Use fuzzy matching for searching.\n" " --require-match <true|false> Require a match for selection.\n" +" --hide-input <true|false> Hide sensitive input such as passwords.\n" +" --hidden-character <char> Replacement character for hidden input.\n" " --drun-launch <true|false> Launch apps directly in drun mode.\n" " --drun-print-exec <true|false> Print a command line in drun mode.\n" " This is now always the case,\n" @@ -864,6 +866,8 @@ const struct option long_options[] = { {"history", required_argument, NULL, 0}, {"fuzzy-match", required_argument, NULL, 0}, {"require-match", required_argument, NULL, 0}, + {"hide-input", required_argument, NULL, 0}, + {"hidden-character", required_argument, NULL, 0}, {"drun-launch", required_argument, NULL, 0}, {"drun-print-exec", required_argument, NULL, 0}, {"hint-font", required_argument, NULL, 0}, @@ -1007,6 +1011,7 @@ int main(int argc, char *argv[]) .font_name = "Sans", .font_size = 24, .prompt_text = "run: ", + .hidden_character_mb = "*", .padding_top = 8, .padding_bottom = 8, .padding_left = 8, |