Refactor keymap.c
authorLaslo Hunhold <dev@frign.de>
Wed, 23 May 2018 13:29:37 +0000 (15:29 +0200)
committerAaron Marcher <me@drkhsh.at>
Wed, 23 May 2018 17:56:16 +0000 (19:56 +0200)
 - 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

components/keymap.c

index aed408e4a10366bd2e0fcf5653a39d47d32c5363..ddf7a15a891dbf92860e49a720dd9c1fbf8673c4 100644 (file)
@@ -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;
 }