port dmenu password patch - wmenu - 🔧 fork of wmenu
 (HTM) git clone git@git.drkhsh.at/wmenu.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 9e9284666c9fcf3278ad17f98a247658db8b2269
 (DIR) parent 6ad7a303ef2ff130b84cfa718ace423a3101dbbb
 (HTM) Author: sewn <sewn@disroot.org>
       Date:   Sun, 10 Mar 2024 18:00:48 +0300
       
       port dmenu password patch
       
       Diffstat:
         M docs/wmenu.1.scd                    |       6 +++++-
         M menu.c                              |      14 +++++++++++---
         M menu.h                              |       2 ++
         M render.c                            |      21 +++++++++++++++++++--
       
       4 files changed, 37 insertions(+), 6 deletions(-)
       ---
 (DIR) diff --git a/docs/wmenu.1.scd b/docs/wmenu.1.scd
       @@ -6,7 +6,7 @@ wmenu - dynamic menu for Wayland
        
        # SYNOPSIS
        
       -*wmenu* [-biv] \
       +*wmenu* [-biPv] \
          [-f _font_] \
          [-l _lines_] \
          [-o _output_] \
       @@ -30,6 +30,10 @@ to those matching the tokens in the input.
        *-i*
                wmenu matches menu items case insensitively.
        
       +*-P*
       +        wmenu will not directly display the keyboard input, but instead replace it
       +        with asterisks. All data from stdin will be ignored.
       +
        *-v*
                prints version information to stdout, then exits.
        
 (DIR) diff --git a/menu.c b/menu.c
       @@ -89,11 +89,11 @@ static bool parse_color(const char *color, uint32_t *result) {
        // Parse menu options from command line arguments.
        void menu_getopts(struct menu *menu, int argc, char *argv[]) {
                const char *usage =
       -                "Usage: wmenu [-biv] [-f font] [-l lines] [-o output] [-p prompt]\n"
       +                "Usage: wmenu [-biPv] [-f font] [-l lines] [-o output] [-p prompt]\n"
                        "\t[-N color] [-n color] [-M color] [-m color] [-S color] [-s color]\n";
        
                int opt;
       -        while ((opt = getopt(argc, argv, "bhivf:l:o:p:N:n:M:m:S:s:")) != -1) {
       +        while ((opt = getopt(argc, argv, "bhiPvf:l:o:p:N:n:M:m:S:s:")) != -1) {
                        switch (opt) {
                        case 'b':
                                menu->bottom = true;
       @@ -101,6 +101,9 @@ void menu_getopts(struct menu *menu, int argc, char *argv[]) {
                        case 'i':
                                menu->strncmp = strncasecmp;
                                break;
       +                case 'P':
       +                        menu->passwd = true;
       +                        break;
                        case 'v':
                                puts("wmenu " VERSION);
                                exit(EXIT_SUCCESS);
       @@ -335,8 +338,13 @@ static void match_items(struct menu *menu) {
        
        // Read menu items from standard input.
        void read_menu_items(struct menu *menu) {
       -        char buf[sizeof menu->input];
       +        if (menu->passwd) {
       +                // Don't read standard input in password mode
       +                calc_widths(menu);
       +                return;
       +        }
        
       +        char buf[sizeof menu->input];
                struct item **next = &menu->items;
                while (fgets(buf, sizeof buf, stdin)) {
                        char *p = strchr(buf, '\n');
 (DIR) diff --git a/menu.h b/menu.h
       @@ -53,6 +53,8 @@ struct menu {
                bool bottom;
                // The function used to match menu items
                int (*strncmp)(const char *, const char *, size_t);
       +        // Whether the input is a password
       +        bool passwd;
                // The font used to display the menu
                char *font;
                // The number of lines to list items vertically
 (DIR) diff --git a/render.c b/render.c
       @@ -1,4 +1,7 @@
       +#define _POSIX_C_SOURCE 200809L
        #include <cairo/cairo.h>
       +#include <stdlib.h>
       +#include <string.h>
        
        #include "render.h"
        
       @@ -72,8 +75,22 @@ static void render_prompt(struct menu *menu, cairo_t *cairo) {
        
        // Renders the input text.
        static void render_input(struct menu *menu, cairo_t *cairo) {
       -        render_text(menu, cairo, menu->input, menu->promptw, 0, 0,
       -                0, menu->normalfg, menu->padding, menu->padding);
       +        char *censort = NULL;
       +
       +        if (menu->passwd) {
       +                censort = calloc(1, sizeof(menu->input));
       +                if (!censort) {
       +                        return;
       +                }
       +                memset(censort, '*', strlen(menu->input));
       +        }
       +
       +        render_text(menu, cairo, menu->passwd ? censort : menu->input,
       +                menu->promptw, 0, 0, 0, menu->normalfg, menu->padding, menu->padding);
       +
       +        if (censort) {
       +                free(censort);
       +        }
        }
        
        // Renders a cursor for the input field.