=== modified file 't/12strpkey.c' --- t/12strpkey.c 2011-04-01 12:49:20 +0000 +++ t/12strpkey.c 2011-04-01 09:48:15 +0000 @@ -5,77 +5,88 @@ { TermKey *tk; TermKeyKey key; + TermKeyResult res; #define CLEAR_KEY do { key.type = -1; key.code.codepoint = -1; key.modifiers = -1; key.utf8[0] = 0; } while(0) - plan_tests(38); + plan_tests(48); tk = termkey_new(0, TERMKEY_FLAG_NOTERMIOS); CLEAR_KEY; - termkey_strpkey(tk, "A", &key, 0); + res = termkey_strpkey(tk, "A", &key, 0); + is_int(res, TERMKEY_RES_KEY, "result for unicode/A/0"); is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/A/0"); - is_int(key.code.codepoint, 'A', "key.code.codepoint for unicode/A/0"); + is_int(key.code.codepoint, 'A', "key.code.codepoint for unicode/A/0"); is_int(key.modifiers, 0, "key.modifiers for unicode/A/0"); is_str(key.utf8, "A", "key.utf8 for unicode/A/0"); CLEAR_KEY; - termkey_strpkey(tk, "C-b", &key, 0); + res = termkey_strpkey(tk, "C-b", &key, 0); + is_int(res, TERMKEY_RES_KEY, "result for unicode/b/CTRL"); is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/b/CTRL"); - is_int(key.code.codepoint, 'b', "key.code.codepoint for unicode/b/CTRL"); + is_int(key.code.codepoint, 'b', "key.code.codepoint for unicode/b/CTRL"); is_int(key.modifiers, TERMKEY_KEYMOD_CTRL, "key.modifiers for unicode/b/CTRL"); is_str(key.utf8, "b", "key.utf8 for unicode/b/CTRL"); CLEAR_KEY; - termkey_strpkey(tk, "Ctrl-b", &key, TERMKEY_FORMAT_LONGMOD); + res = termkey_strpkey(tk, "Ctrl-b", &key, TERMKEY_FORMAT_LONGMOD); + is_int(res, TERMKEY_RES_KEY, "result for unicode/b/CTRL longmod"); is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/b/CTRL longmod"); - is_int(key.code.codepoint, 'b', "key.code.codepoint for unicode/b/CTRL longmod"); + is_int(key.code.codepoint, 'b', "key.code.codepoint for unicode/b/CTRL longmod"); is_int(key.modifiers, TERMKEY_KEYMOD_CTRL, "key.modifiers for unicode/b/CTRL longmod"); is_str(key.utf8, "b", "key.utf8 for unicode/b/CTRL longmod"); CLEAR_KEY; - termkey_strpkey(tk, "^B", &key, TERMKEY_FORMAT_CARETCTRL); + res = termkey_strpkey(tk, "^B", &key, TERMKEY_FORMAT_CARETCTRL); + is_int(res, TERMKEY_RES_KEY, "result for unicode/b/CTRL caretctrl"); is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/b/CTRL caretctrl"); - is_int(key.code.codepoint, 'b', "key.code.codepoint for unicode/b/CTRL caretctrl"); + is_int(key.code.codepoint, 'b', "key.code.codepoint for unicode/b/CTRL caretctrl"); is_int(key.modifiers, TERMKEY_KEYMOD_CTRL, "key.modifiers for unicode/b/CTRL caretctrl"); is_str(key.utf8, "b", "key.utf8 for unicode/b/CTRL caretctrl"); CLEAR_KEY; - termkey_strpkey(tk, "A-c", &key, 0); + res = termkey_strpkey(tk, "A-c", &key, 0); + is_int(res, TERMKEY_RES_KEY, "result for unicode/c/ALT"); is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/c/ALT"); - is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT"); + is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT"); is_int(key.modifiers, TERMKEY_KEYMOD_ALT, "key.modifiers for unicode/c/ALT"); is_str(key.utf8, "c", "key.utf8 for unicode/c/ALT"); CLEAR_KEY; - termkey_strpkey(tk, "Alt-c", &key, TERMKEY_FORMAT_LONGMOD); + res = termkey_strpkey(tk, "Alt-c", &key, TERMKEY_FORMAT_LONGMOD); + is_int(res, TERMKEY_RES_KEY, "result for unicode/c/ALT longmod"); is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/c/ALT longmod"); - is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT longmod"); + is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT longmod"); is_int(key.modifiers, TERMKEY_KEYMOD_ALT, "key.modifiers for unicode/c/ALT longmod"); is_str(key.utf8, "c", "key.utf8 for unicode/c/ALT longmod"); CLEAR_KEY; - termkey_strpkey(tk, "M-c", &key, TERMKEY_FORMAT_ALTISMETA); + res = termkey_strpkey(tk, "M-c", &key, TERMKEY_FORMAT_ALTISMETA); + is_int(res, TERMKEY_RES_KEY, "result for unicode/c/ALT altismeta"); is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/c/ALT altismeta"); - is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT altismeta"); + is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT altismeta"); is_int(key.modifiers, TERMKEY_KEYMOD_ALT, "key.modifiers for unicode/c/ALT altismeta"); is_str(key.utf8, "c", "key.utf8 for unicode/c/ALT altismeta"); CLEAR_KEY; - termkey_strpkey(tk, "Meta-c", &key, TERMKEY_FORMAT_ALTISMETA|TERMKEY_FORMAT_LONGMOD); + res = termkey_strpkey(tk, "Meta-c", &key, TERMKEY_FORMAT_ALTISMETA|TERMKEY_FORMAT_LONGMOD); + is_int(res, TERMKEY_RES_KEY, "result for unicode/c/ALT altismeta+longmod"); is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/c/ALT altismeta+longmod"); - is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT altismeta+longmod"); + is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT altismeta+longmod"); is_int(key.modifiers, TERMKEY_KEYMOD_ALT, "key.modifiers for unicode/c/ALT altismeta+longmod"); is_str(key.utf8, "c", "key.utf8 for unicode/c/ALT altismeta+longmod"); CLEAR_KEY; - termkey_strpkey(tk, "Up", &key, 0); + res = termkey_strpkey(tk, "Up", &key, 0); + is_int(res, TERMKEY_RES_KEY, "result for sym/Up/0"); is_int(key.type, TERMKEY_TYPE_KEYSYM, "key.type for sym/Up/0"); is_int(key.code.sym, TERMKEY_SYM_UP, "key.code.codepoint for sym/Up/0"); is_int(key.modifiers, 0, "key.modifiers for sym/Up/0"); CLEAR_KEY; - termkey_strpkey(tk, "F5", &key, 0); + res = termkey_strpkey(tk, "F5", &key, 0); + is_int(res, TERMKEY_RES_KEY, "result for func/5/0"); is_int(key.type, TERMKEY_TYPE_FUNCTION, "key.type for func/5/0"); is_int(key.code.number, 5, "key.code.number for func/5/0"); is_int(key.modifiers, 0, "key.modifiers for func/5/0"); === modified file 'termkey.c' --- termkey.c 2011-04-01 12:49:20 +0000 +++ termkey.c 2011-04-01 12:26:54 +0000 @@ -1080,7 +1080,7 @@ return pos; } -char *termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermKeyFormat format) +TermKeyResult termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermKeyFormat format) { struct modnames *mods = &modnames[!!(format & TERMKEY_FORMAT_LONGMOD) + !!(format & TERMKEY_FORMAT_ALTISMETA) * 2]; @@ -1088,19 +1088,22 @@ key->modifiers = 0; if((format & TERMKEY_FORMAT_CARETCTRL) && str[0] == '^' && str[1]) { - str = termkey_strpkey(tk, str+1, key, format & ~TERMKEY_FORMAT_CARETCTRL); + TermKeyResult res = termkey_strpkey(tk, str+1, key, format & ~TERMKEY_FORMAT_CARETCTRL); - if(!str || - key->type != TERMKEY_TYPE_UNICODE || - key->code.codepoint < '@' || key->code.codepoint > '_' || - key->modifiers != 0) - return NULL; + if(res != TERMKEY_RES_KEY) + return res; + if(key->type != TERMKEY_TYPE_UNICODE) + return TERMKEY_RES_NONE; + if(key->code.codepoint < '@' || key->code.codepoint > '_') + return TERMKEY_RES_NONE; + if(key->modifiers != 0) + return TERMKEY_RES_NONE; if(key->code.codepoint >= 'A' && key->code.codepoint <= 'Z') key->code.codepoint += 0x20; key->modifiers = TERMKEY_KEYMOD_CTRL; fill_utf8(key); - return (char *)str; + return res; } const char *hyphen; @@ -1122,25 +1125,22 @@ } size_t nbytes; - char *endstr; if(parse_utf8((unsigned char *)str, strlen(str), &key->code.codepoint, &nbytes) == TERMKEY_RES_KEY && nbytes == strlen(str)) { key->type = TERMKEY_TYPE_UNICODE; fill_utf8(key); - str += nbytes; } - else if((endstr = termkey_lookup_keyname(tk, str, &key->code.sym))) { + else if((key->code.sym = termkey_keyname2sym(tk, str)) != TERMKEY_SYM_UNKNOWN) { key->type = TERMKEY_TYPE_KEYSYM; - str = endstr; } - else if(sscanf(str, "F%d%n", &key->code.number, &nbytes) == 1) { + else if(sscanf(str, "F%d", &key->code.number) == 1) { key->type = TERMKEY_TYPE_FUNCTION; - str += nbytes; } // TODO: Consider mouse events? - else - return NULL; + else { + return TERMKEY_RES_NONE; + } - return (char *)str; + return TERMKEY_RES_KEY; } === modified file 'termkey.h.in' --- termkey.h.in 2011-04-01 12:49:20 +0000 +++ termkey.h.in 2011-04-01 12:26:54 +0000 @@ -190,8 +190,8 @@ #define TERMKEY_FORMAT_VIM (TERMKEY_FORMAT_ALTISMETA|TERMKEY_FORMAT_WRAPBRACKET) -size_t termkey_strfkey(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, TermKeyFormat format); -char *termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermKeyFormat format); +size_t termkey_strfkey(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, TermKeyFormat format); +TermKeyResult termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermKeyFormat format); // Old name for termkey_strfkey() size_t termkey_snprint_key(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, TermKeyFormat format); === modified file 'termkey_strpkey.3' --- termkey_strpkey.3 2011-04-01 12:49:20 +0000 +++ termkey_strpkey.3 2011-04-01 10:11:50 +0000 @@ -5,7 +5,7 @@ .nf .B #include .sp -.BI "char *termkey_strpkey(TermKey *" tk ", const char *" str ", +.BI "size_t termkey_strpkey(TermKey *" tk ", const char *" str ", .BI " TermKeyKey " key ", TermKeyFormat " format ); .fi .sp @@ -26,7 +26,13 @@ .PP The \fBTERMKEY_FORMAT_WRAPBRACKET\fP and \fBTERMKEY_FORMAT_MOUSE_POS\fP options are currently not supported by \fBtermkey_strpkey\fP(). When returning a \fBTERMKEY_TYPE_UNICODE\fP key structure, this function will fill in the \fIutf8\fP member. .SH "RETURN VALUE" -After a successful parse, \fBtermkey_strpkey\fP() returns a pointer to the first character of the input it did not consume. If the input string contains more characters then this will point at the first character beyond. If the entire input string was consumed, then this will point at a null byte. If \fBtermkey_strpkey\fP() fails to parse, it returns \fBNULL\fP. After a failed parse, the \fIkey\fP structure may contain partial or invalid results. The structure will only be valid if the function returns a non-\fBNULL\fP result. +\fBtermkey_strpkey\fP() returns one of the following constants: +.TP +.B TERMKEY_RES_KEY +A key structure was successfully parsed. +.TP +.B TERMKEY_RES_NONE +No key was recognised in the string buffer. .SH "SEE ALSO" .BR termkey_new (3), .BR termkey_strfkey (3)