You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

117 lines
2.7 KiB

/*
* keyd - A key remapping daemon.
*
* © 2019 Raheman Vaiya (see also: LICENSE).
*/
#include <string.h>
#include "macro.h"
#include "keys.h"
#include "error.h"
#include "unicode.h"
#include "string.h"
static int parse(struct macro *macro, char *s)
{
#define ADD_ENTRY(t, d) do { \
if (macro->sz >= MAX_MACRO_SIZE) { \
err("maxium macro size (%d) exceeded", MAX_MACRO_SIZE); \
return 1; \
} \
macro->entries[macro->sz].type = t; \
macro->entries[macro->sz].data = d; \
macro->sz++; \
} while(0)
char *tok;
macro->sz = 0;
for (tok = strtok(s, " "); tok; tok = strtok(NULL, " ")) {
uint8_t code, mods;
size_t len = strlen(tok);
if (!parse_key_sequence(tok, &code, &mods)) {
ADD_ENTRY(MACRO_KEYSEQUENCE, (mods << 8) | code);
} else if (strchr(tok, '+')) {
char *saveptr;
char *key;
for (key = strtok_r(tok, "+", &saveptr); key; key = strtok_r(NULL, "+", &saveptr)) {
size_t len = strlen(key);
if (len > 1 && key[len-2] == 'm' && key[len-1] == 's')
ADD_ENTRY(MACRO_TIMEOUT, atoi(key));
else if (!parse_key_sequence(key, &code, &mods))
ADD_ENTRY(MACRO_HOLD, code);
else {
err("%s is not a valid key", key);
return -1;
}
}
ADD_ENTRY(MACRO_RELEASE, 0);
} else if (len > 1 && tok[len-2] == 'm' && tok[len-1] == 's') {
ADD_ENTRY(MACRO_TIMEOUT, atoi(tok));
} else {
uint32_t codepoint;
int chrsz;
while ((chrsz=utf8_read_char(tok, &codepoint))) {
int i;
int xcode;
if (chrsz == 1 && codepoint < 128) {
for (i = 0; i < 256; i++) {
const char *name = keycode_table[i].name;
const char *shiftname = keycode_table[i].shifted_name;
if (name && name[0] == tok[0] && name[1] == 0) {
ADD_ENTRY(MACRO_KEYSEQUENCE, i);
break;
}
if (shiftname && shiftname[0] == tok[0] && shiftname[1] == 0) {
ADD_ENTRY(MACRO_KEYSEQUENCE, (MOD_SHIFT << 8) | i);
break;
}
}
} else if ((xcode = lookup_xcompose_code(codepoint)) > 0)
ADD_ENTRY(MACRO_UNICODE, xcode);
tok += chrsz;
}
}
}
return 0;
}
/* Returns:
* 0 on success
* -1 in the case of an invalid macro expression
* >0 for all other errors
*/
int parse_macro(const char *exp, struct macro *macro)
{
char s[MAX_MACROEXP_LEN+1];
int len = strlen(exp);
if (len > MAX_MACROEXP_LEN) {
err("macro exceeds maximum macro length (%d)", MAX_MACROEXP_LEN);
return -1;
}
strcpy(s, exp);
str_escape(s);
len = strlen(s);
if (!parse_key_sequence(s, NULL, NULL) || utf8_strlen(s) == 1) {
return parse(macro, s);
} else if (!strncmp(s, "macro(", 6) && s[len-1] == ')') {
s[len-1] = 0;
return parse(macro, s+6);
} else {
err("invalid macro");
return -1;
}
}