X-Git-Url: https://git.xinqibao.xyz/slstatus.git/blobdiff_plain/943b42de05cc3328ea74b0d9f527f17e1fcf47e7..b792b7ab69c24bedf8147c734a849ae0c54da1dc:/components/keymap.c?ds=inline

diff --git a/components/keymap.c b/components/keymap.c
index 358a2ca..ddf7a15 100644
--- a/components/keymap.c
+++ b/components/keymap.c
@@ -7,91 +7,81 @@
 
 #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;
 		}
+	}
 
 	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;
 }