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
This commit is contained in:
Laslo Hunhold 2018-05-23 15:29:37 +02:00 committed by Aaron Marcher
parent 13d77cd268
commit f17f39d0a2
1 changed files with 44 additions and 55 deletions

View File

@ -7,21 +7,15 @@
#include "../util.h" #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 static int
IsLayoutOrVariant(char *sym) valid_layout_or_variant(char *sym)
{ {
static const char* EXCLUDES[] = { "evdev", "inet", "pc", "base" };
size_t i; size_t i;
for (i = 0; i < sizeof(EXCLUDES)/sizeof(EXCLUDES[0]); ++i) { /* invalid symbols from xkb rules config */
if (strstr(sym, EXCLUDES[i])) { 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; return 0;
} }
} }
@ -29,70 +23,65 @@ IsLayoutOrVariant(char *sym)
return 1; return 1;
} }
static void static char *
GetKeyLayout(char *syms, char layout[], int groupNum) get_layout(char *syms, int grp_num)
{ {
char *token, *copy, *delims; char *tok, *layout;
int group; int grp;
delims = "+:"; layout = NULL;
group = 0; tok = strtok(syms, "+:");
copy = strdup(syms); for (grp = 0; tok && grp <= grp_num; tok = strtok(NULL, "+:")) {
token = strtok(copy, delims); if (!valid_layout_or_variant(tok)) {
while (token != NULL && group <= groupNum) { continue;
/* Ignore :2,:3,:4 which represent additional layout } else if (strlen(tok) == 1 && isdigit(tok[0])) {
* groups /* ignore :2, :3, :4 (additional layout groups) */
*/ continue;
if (IsLayoutOrVariant(token)
&& !(strlen(token) == 1 && isdigit(token[0]))) {
strncpy (layout, token, LAYOUT_MAX);
group++;
} }
layout = tok;
token = strtok(NULL,delims); grp++;
} }
free(copy); return layout;
} }
const char * const char *
keymap(void) keymap(void)
{ {
static char layout[LAYOUT_MAX];
Display *dpy; Display *dpy;
char *symbols = NULL; XkbDescRec *desc;
XkbDescRec* desc = NULL; XkbStateRec state;
char *symbols, *layout;
memset(layout, '\0', LAYOUT_MAX); layout = NULL;
if (!(dpy = XOpenDisplay(NULL))) { if (!(dpy = XOpenDisplay(NULL))) {
warn("XOpenDisplay: Failed to open display"); warn("XOpenDisplay: Failed to open display");
return NULL; return NULL;
} }
;
if (!(desc = XkbAllocKeyboard())) { if (!(desc = XkbAllocKeyboard())) {
warn("XkbAllocKeyboard: failed to allocate keyboard"); warn("XkbAllocKeyboard: Failed to allocate keyboard");
XCloseDisplay(dpy); goto end;
return NULL;
} }
if (XkbGetNames(dpy, XkbSymbolsNameMask, desc)) {
XkbGetNames(dpy, XkbSymbolsNameMask, desc); warn("XkbGetNames: Failed to retrieve key symbols");
if (desc->names) { goto end;
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 (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); XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1);
XCloseDisplay(dpy); if (XCloseDisplay(dpy)) {
warn("XCloseDisplay: Failed to close display");
}
return layout; return layout;
} }