Refactor keymap.c - slstatus - status monitor
 (HTM) git clone git://git.suckless.org/slstatus
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit f17f39d0a2e2898177dbcf5daf67284956005b9b
 (DIR) parent 13d77cd268bade5e9ee9c07d9b94ca7c733cbe3d
 (HTM) Author: Laslo Hunhold <dev@frign.de>
       Date:   Wed, 23 May 2018 15:29:37 +0200
       
       Refactor keymap.c
       
        - Get rid of camel-casing
        - Don't use all-caps for variable names
        - use LEN()-macro
        - use strncmp() rather than strstr() for prefix-checking
        - clean up the tokenizer-loop and don't use copies
        - make the loop more readable by separating different breaking
          conditions
        - stricter error-checking and cleanup
        - store the layout directly with bprintf rather than having
          a separate buffer
       
       Diffstat:
         M components/keymap.c                 |     101 ++++++++++++++-----------------
       
       1 file changed, 45 insertions(+), 56 deletions(-)
       ---
 (DIR) diff --git a/components/keymap.c b/components/keymap.c
       @@ -7,21 +7,15 @@
        
        #include "../util.h"
        
       -#define LAYOUT_MAX 256
       -
       -/* Given a token (sym) from the xkb_symbols string
       - * check whether it is a valid layout/variant. The
       - * EXCLUDES array contains invalid layouts/variants
       - * that are part of the xkb rules config.
       - */
        static int
       -IsLayoutOrVariant(char *sym)
       +valid_layout_or_variant(char *sym)
        {
       -        static const char* EXCLUDES[] = { "evdev", "inet", "pc", "base" };
       -
                size_t i;
       -        for (i = 0; i < sizeof(EXCLUDES)/sizeof(EXCLUDES[0]); ++i) {
       -                if (strstr(sym, EXCLUDES[i])) {
       +        /* invalid symbols from xkb rules config */
       +        static const char *invalid[] = { "evdev", "inet", "pc", "base" };
       +
       +        for (i = 0; i < LEN(invalid); i++) {
       +                if (!strncmp(sym, invalid[i], strlen(invalid[i]))) {
                                return 0;
                        }
                }
       @@ -29,70 +23,65 @@ IsLayoutOrVariant(char *sym)
                return 1;
        }
        
       -static void
       -GetKeyLayout(char *syms, char layout[], int groupNum)
       +static char *
       +get_layout(char *syms, int grp_num)
        {
       -        char *token, *copy, *delims;
       -        int group;
       -
       -        delims = "+:";
       -        group = 0;
       -        copy = strdup(syms);
       -        token = strtok(copy, delims);
       -        while (token != NULL && group <= groupNum) {
       -                /* Ignore :2,:3,:4 which represent additional layout
       -                  * groups
       -                  */
       -                if (IsLayoutOrVariant(token)
       -                    && !(strlen(token) == 1 && isdigit(token[0]))) {
       -                        strncpy (layout, token, LAYOUT_MAX);
       -                        group++;
       +        char *tok, *layout;
       +        int grp;
       +
       +        layout = NULL;
       +        tok = strtok(syms, "+:");
       +        for (grp = 0; tok && grp <= grp_num; tok = strtok(NULL, "+:")) {
       +                if (!valid_layout_or_variant(tok)) {
       +                        continue;
       +                } else if (strlen(tok) == 1 && isdigit(tok[0])) {
       +                        /* ignore :2, :3, :4 (additional layout groups) */
       +                        continue;
                        }
       -
       -                token = strtok(NULL,delims);
       +                layout = tok;
       +                grp++;
                }
        
       -        free(copy);
       +        return layout;
        }
        
        const char *
        keymap(void)
        {
       -        static char layout[LAYOUT_MAX];
       -
                Display *dpy;
       -        char *symbols = NULL;
       -        XkbDescRec* desc = NULL;
       +        XkbDescRec *desc;
       +        XkbStateRec state;
       +        char *symbols, *layout;
        
       -        memset(layout, '\0', LAYOUT_MAX);
       +        layout = NULL;
        
                if (!(dpy = XOpenDisplay(NULL))) {
                        warn("XOpenDisplay: Failed to open display");
                        return NULL;
                }
       -
       -        ;
                if (!(desc = XkbAllocKeyboard())) {
       -                warn("XkbAllocKeyboard: failed to allocate keyboard");
       -                XCloseDisplay(dpy);
       -                return NULL;
       +                warn("XkbAllocKeyboard: Failed to allocate keyboard");
       +                goto end;
                }
       -
       -        XkbGetNames(dpy, XkbSymbolsNameMask, desc);
       -        if (desc->names) {
       -                XkbStateRec state;
       -                XkbGetState(dpy, XkbUseCoreKbd, &state);
       -
       -                symbols = XGetAtomName(dpy, desc->names->symbols);
       -                GetKeyLayout(symbols, layout, state.group);
       -                XFree(symbols);
       -        } else {
       -                warn("XkbGetNames: failed to retrieve symbols for keys");
       -                return NULL;
       +        if (XkbGetNames(dpy, XkbSymbolsNameMask, desc)) {
       +                warn("XkbGetNames: Failed to retrieve key symbols");
       +                goto end;
                }
       -
       +        if (XkbGetState(dpy, XkbUseCoreKbd, &state)) {
       +                warn("XkbGetState: Failed to retrieve keyboard state");
       +                goto end;
       +        }
       +        if (!(symbols = XGetAtomName(dpy, desc->names->symbols))) {
       +                warn("XGetAtomName: Failed to get atom name");
       +                goto end;
       +        }
       +        layout = (char *)bprintf("%s", get_layout(symbols, state.group));
       +        XFree(symbols);
       +end:
                XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1);
       -        XCloseDisplay(dpy);
       +        if (XCloseDisplay(dpy)) {
       +                warn("XCloseDisplay: Failed to close display");
       +        }
        
                return layout;
        }