From 46eefda07367e63b7ceffeecb2778409f1d4b387 Mon Sep 17 00:00:00 2001 From: Paul LeoNerd Evans Date: Sat, 27 Aug 2011 19:59:02 +0100 Subject: [PATCH] Provide an explicit termkey_canonicalise() function; canonicalise Space/SP in both directions --- t/20canon.c | 51 ++++++++++++++++++++++++++++++++++++++++++ termkey.c | 29 +++++++++++++++++++----- termkey.h.in | 2 ++ termkey_canonicalise.3 | 24 ++++++++++++++++++++ termkey_getkey.3.sh | 2 ++ termkey_strpkey.3 | 2 ++ termkey_waitkey.3.sh | 2 ++ 7 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 t/20canon.c create mode 100644 termkey_canonicalise.3 diff --git a/t/20canon.c b/t/20canon.c new file mode 100644 index 0000000..b407f9f --- /dev/null +++ b/t/20canon.c @@ -0,0 +1,51 @@ +#include "../termkey.h" +#include "taplib.h" + +int main(int argc, char *argv[]) +{ + TermKey *tk; + TermKeyKey key; + char *endp; + +#define CLEAR_KEY do { key.type = -1; key.code.codepoint = -1; key.modifiers = -1; key.utf8[0] = 0; } while(0) + + plan_tests(18); + + tk = termkey_new(0, TERMKEY_FLAG_NOTERMIOS); + + CLEAR_KEY; + endp = termkey_strpkey(tk, " ", &key, 0); + is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for SP/unicode"); + is_int(key.code.codepoint, ' ', "key.code.codepoint for SP/unicode"); + is_int(key.modifiers, 0, "key.modifiers for SP/unicode"); + is_str(key.utf8, " ", "key.utf8 for SP/unicode"); + is_str(endp, "", "consumed entire input for SP/unicode"); + + CLEAR_KEY; + endp = termkey_strpkey(tk, "Space", &key, 0); + is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for Space/unicode"); + is_int(key.code.codepoint, ' ', "key.code.codepoint for Space/unicode"); + is_int(key.modifiers, 0, "key.modifiers for Space/unicode"); + is_str(key.utf8, " ", "key.utf8 for Space/unicode"); + is_str(endp, "", "consumed entire input for Space/unicode"); + + termkey_set_flags(tk, termkey_get_flags(tk) | TERMKEY_FLAG_SPACESYMBOL); + + CLEAR_KEY; + endp = termkey_strpkey(tk, " ", &key, 0); + is_int(key.type, TERMKEY_TYPE_KEYSYM, "key.type for SP/symbol"); + is_int(key.code.sym, TERMKEY_SYM_SPACE, "key.code.codepoint for SP/symbol"); + is_int(key.modifiers, 0, "key.modifiers for SP/symbol"); + is_str(endp, "", "consumed entire input for SP/symbol"); + + CLEAR_KEY; + endp = termkey_strpkey(tk, "Space", &key, 0); + is_int(key.type, TERMKEY_TYPE_KEYSYM, "key.type for Space/symbol"); + is_int(key.code.sym, TERMKEY_SYM_SPACE, "key.code.codepoint for Space/symbol"); + is_int(key.modifiers, 0, "key.modifiers for Space/symbol"); + is_str(endp, "", "consumed entire input for Space/symbol"); + + termkey_destroy(tk); + + return exit_status(); +} diff --git a/termkey.c b/termkey.c index e1969c2..bb1c5f8 100644 --- a/termkey.c +++ b/termkey.c @@ -538,12 +538,6 @@ static void emit_codepoint(TermKey *tk, long codepoint, TermKeyKey *key) key->type = TERMKEY_TYPE_KEYSYM; } } - else if(codepoint == 0x20 && (tk->flags & TERMKEY_FLAG_SPACESYMBOL)) { - // ASCII space - key->type = TERMKEY_TYPE_KEYSYM; - key->code.sym = TERMKEY_SYM_SPACE; - key->modifiers = 0; - } else if(codepoint == 0x7f && !(tk->flags & TERMKEY_FLAG_NOINTERPRET)) { // ASCII DEL key->type = TERMKEY_TYPE_KEYSYM; @@ -569,10 +563,31 @@ static void emit_codepoint(TermKey *tk, long codepoint, TermKeyKey *key) key->modifiers = 0; } + termkey_canonicalise(tk, key); + if(key->type == TERMKEY_TYPE_UNICODE) fill_utf8(key); } +void termkey_canonicalise(TermKey *tk, TermKeyKey *key) +{ + int flags = tk->flags; + + if(flags & TERMKEY_FLAG_SPACESYMBOL) { + if(key->type == TERMKEY_TYPE_UNICODE && key->code.number == 0x20) { + key->type = TERMKEY_TYPE_KEYSYM; + key->code.sym = TERMKEY_SYM_SPACE; + } + } + else { + if(key->type == TERMKEY_TYPE_KEYSYM && key->code.sym == TERMKEY_SYM_SPACE) { + key->type = TERMKEY_TYPE_UNICODE; + key->code.number = 0x20; + fill_utf8(key); + } + } +} + static TermKeyResult peekkey(TermKey *tk, TermKeyKey *key, int force, size_t *nbytep) { int again = 0; @@ -1178,6 +1193,8 @@ char *termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermKeyForm else return NULL; + termkey_canonicalise(tk, key); + return (char *)str; } diff --git a/termkey.h.in b/termkey.h.in index f0bce90..59a4f02 100644 --- a/termkey.h.in +++ b/termkey.h.in @@ -163,6 +163,8 @@ void termkey_set_flags(TermKey *tk, int newflags); int termkey_get_waittime(TermKey *tk); void termkey_set_waittime(TermKey *tk, int msec); +void termkey_canonicalise(TermKey *tk, TermKeyKey *key); + TermKeyResult termkey_getkey(TermKey *tk, TermKeyKey *key); TermKeyResult termkey_getkey_force(TermKey *tk, TermKeyKey *key); TermKeyResult termkey_waitkey(TermKey *tk, TermKeyKey *key); diff --git a/termkey_canonicalise.3 b/termkey_canonicalise.3 new file mode 100644 index 0000000..d208251 --- /dev/null +++ b/termkey_canonicalise.3 @@ -0,0 +1,24 @@ +.TH TERMKEY_CANONICALISE 3 +.SH NAME +termkey_canonicalise \- canonicalise a key event +.SH SYNOPSIS +.nf +.B #include +.sp +.BI "void termkey_canonicalise(TermKey *" tk ", TermKeyKey *" key ); +.fi +.sp +Link with \fI-ltermkey\fP. +.SH DESCRIPTION +\fBtermkey_canonicalise\fP(3) modifies the key event structure given by \fIkey\fP according to the flags set on the given \fItk\fP instance. This operation is performed implicitly by \fBtermkey_getkey\fP(3), \fBtermkey_waitkey\fP(3) and \fBtermkey_strpkey\fP(3), and is also provided explicitly by this function. +.PP +The canonicalisation operation is affected by the following flags: +.TP +.B TERMKEY_FLAG_SPACESYMBOL +If this flag is set then a Unicode space character is represented using the \fBTERMKEY_SYM_SPACE\fP symbol. If this flag is not set, it is represented by the U+0020 Unicode codepoint. +.SH "RETURN VALUE" +\fBtermkey_canonicalise\fP() returns no value. +.SH "SEE ALSO" +.BR termkey_new (3), +.BR termkey_waitkey (3), +.BR termkey_strpkey (3) diff --git a/termkey_getkey.3.sh b/termkey_getkey.3.sh index 55bfca1..022f209 100644 --- a/termkey_getkey.3.sh +++ b/termkey_getkey.3.sh @@ -32,6 +32,8 @@ no bytes are waiting in the buffer. .PP Neither of these functions will block or perform any IO operations on the underlying filehandle. To use the instance in an asynchronous program, see \fBtermkey_advisereadable\fP(3). For a blocking call suitable for use in a synchronous program, use \fBtermkey_waitkey\fP(3) instead of \fBtermkey_getkey\fP(). .PP +Before returning, this function canonicalises the \fIkey\fP structure according to the rules given for \fBtermkey_canonicalise\fP(3). +.PP The \fITermKeyKey\fP structure is defined as follows: .PP .in +4n diff --git a/termkey_strpkey.3 b/termkey_strpkey.3 index 12e2d3a..f9de839 100644 --- a/termkey_strpkey.3 +++ b/termkey_strpkey.3 @@ -24,6 +24,8 @@ If the only modifier is \fBTERMKEY_MOD_CTRL\fP on a plain letter, accept it as " .B TERMKEY_FORMAT_ALTISMETA Use the name "Meta" or the letter "M" instead of "Alt" or "A". .PP +Before returning, this function canonicalises the \fIkey\fP structure according to the rules given for \fBtermkey_canonicalise\fP(3). +.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. diff --git a/termkey_waitkey.3.sh b/termkey_waitkey.3.sh index ee8edaf..754ac21 100644 --- a/termkey_waitkey.3.sh +++ b/termkey_waitkey.3.sh @@ -14,6 +14,8 @@ Link with \fI-ltermkey\fP. .SH DESCRIPTION \fBtermkey_waitkey\fP(3) attempts to retrieve a single keypress event from the buffer, and put it in the structure referred to by \fIkey\fP. If successful it will return \fBTERMKEY_RES_KEY\fP to indicate that the structure now contains a new keypress event. If nothing is in the buffer it will block until one is available. If no events are ready and the input stream is now closed, will return \fBTERMKEY_RES_EOF\fP. .PP +Before returning, this function canonicalises the \fIkey\fP structure according to the rules given for \fBtermkey_canonicalise\fP(3). +.PP For details of the \fITermKeyKey\fP structure, see \fBtermkey_getkey\fP(3). .PP Some keypresses generate multiple bytes from the terminal. Because there may be network or other delays between the terminal and an application using termkey, \fBtermkey_waitkey\fP() will attempt to wait for the remaining bytes to arrive if it detects the start of a multibyte sequence. If no more bytes arrive within a certain time, then the bytes will be reported as they stand, even if this results in interpreting a partially-complete Escape sequence as a literal Escape key followed by some normal letters or other symbols. The amount of time to wait can be set by \fBtermkey_set_waittime\fP(3).