From b630bf7a5f5ec85317db04f770ffc90664ac28f0 Mon Sep 17 00:00:00 2001 From: Přemysl Janouch Date: Tue, 23 Sep 2014 01:38:08 +0200 Subject: WIP: Is mine now (^3^) Seriously though, I've got some issues with how this thing is designed, as well as with its formatting, and when you add the fact that the original author wants to merge this thing into his bigger library that also handles terminal output, which I'll kindly leave to ncurses, it kind of makes sense for me to do this. Manpages have been removed as they are going to become obsolete and they're rather difficult to maintain. If anything, there will be Doxygen-generated documentation. The plan is to throw away any direct UTF-8 support and support all uni- and multibyte character encodings. However some unrelated refactoring is about to come first. --- .bzrignore | 10 - LICENSE | 7 +- demo-async.c | 83 +- demo-glib.c | 86 +- demo.c | 231 ++-- driver-csi.c | 1116 +++++++-------- driver-ti.c | 973 ++++++------- man/also | 9 - man/termkey.7 | 145 -- man/termkey_advisereadable.3 | 33 - man/termkey_canonicalise.3 | 22 - man/termkey_get_buffer_remaining.3 | 23 - man/termkey_get_fd.3 | 19 - man/termkey_get_keyname.3 | 20 - man/termkey_getkey.3.sh | 56 - man/termkey_interpret_csi.3 | 28 - man/termkey_interpret_modereport.3 | 26 - man/termkey_interpret_mouse.3 | 41 - man/termkey_interpret_position.3 | 26 - man/termkey_keycmp.3 | 22 - man/termkey_keyname2sym.3 | 22 - man/termkey_lookup_keyname.3 | 23 - man/termkey_new.3 | 48 - man/termkey_push_bytes.3 | 23 - man/termkey_set_buffer_size.3 | 22 - man/termkey_set_canonflags.3 | 21 - man/termkey_set_flags.3 | 21 - man/termkey_set_waittime.3 | 22 - man/termkey_start.3 | 25 - man/termkey_strfkey.3 | 59 - man/termkey_strpkey.3 | 45 - man/termkey_waitkey.3.sh | 45 - termkey-internal.h | 156 ++- termkey.c | 2626 +++++++++++++++++++----------------- termkey.h.in | 416 +++--- 35 files changed, 2975 insertions(+), 3575 deletions(-) delete mode 100644 .bzrignore delete mode 100644 man/also delete mode 100644 man/termkey.7 delete mode 100644 man/termkey_advisereadable.3 delete mode 100644 man/termkey_canonicalise.3 delete mode 100644 man/termkey_get_buffer_remaining.3 delete mode 100644 man/termkey_get_fd.3 delete mode 100644 man/termkey_get_keyname.3 delete mode 100644 man/termkey_getkey.3.sh delete mode 100644 man/termkey_interpret_csi.3 delete mode 100644 man/termkey_interpret_modereport.3 delete mode 100644 man/termkey_interpret_mouse.3 delete mode 100644 man/termkey_interpret_position.3 delete mode 100644 man/termkey_keycmp.3 delete mode 100644 man/termkey_keyname2sym.3 delete mode 100644 man/termkey_lookup_keyname.3 delete mode 100644 man/termkey_new.3 delete mode 100644 man/termkey_push_bytes.3 delete mode 100644 man/termkey_set_buffer_size.3 delete mode 100644 man/termkey_set_canonflags.3 delete mode 100644 man/termkey_set_flags.3 delete mode 100644 man/termkey_set_waittime.3 delete mode 100644 man/termkey_start.3 delete mode 100644 man/termkey_strfkey.3 delete mode 100644 man/termkey_strpkey.3 delete mode 100644 man/termkey_waitkey.3.sh diff --git a/.bzrignore b/.bzrignore deleted file mode 100644 index 030eb3c..0000000 --- a/.bzrignore +++ /dev/null @@ -1,10 +0,0 @@ -termkey.h -demo -demo-async -demo-glib -termkey_getkey.3 -termkey_waitkey.3 -*.lo -*.la -.libs -t/*.t diff --git a/LICENSE b/LICENSE index ee03032..93afa4f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,8 +1,5 @@ - - -The MIT License - -Copyright (c) 2007-2011 Paul Evans +Copyright (c) 2007-2014 Paul Evans +Copyright (c) 2014 Přemysl Janouch Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/demo-async.c b/demo-async.c index 9d398a7..51bc1b3 100644 --- a/demo-async.c +++ b/demo-async.c @@ -6,59 +6,62 @@ #include "termkey.h" -static void on_key(TermKey *tk, TermKeyKey *key) +static void +on_key (termkey_t *tk, termkey_key_t *key) { - char buffer[50]; - termkey_strfkey(tk, buffer, sizeof buffer, key, TERMKEY_FORMAT_VIM); - printf("%s\n", buffer); + char buffer[50]; + termkey_strfkey (tk, buffer, sizeof buffer, key, TERMKEY_FORMAT_VIM); + printf ("%s\n", buffer); } -int main(int argc, char *argv[]) +int +main (int argc, char *argv[]) { - TERMKEY_CHECK_VERSION; + TERMKEY_CHECK_VERSION; - TermKey *tk = termkey_new(0, 0); + termkey_t *tk = termkey_new (0, 0); - if(!tk) { - fprintf(stderr, "Cannot allocate termkey instance\n"); - exit(1); - } + if (!tk) + { + fprintf (stderr, "Cannot allocate termkey instance\n"); + exit (1); + } - struct pollfd fd; + struct pollfd fd; + fd.fd = 0; /* the file descriptor we passed to termkey_new() */ + fd.events = POLLIN; - fd.fd = 0; /* the file descriptor we passed to termkey_new() */ - fd.events = POLLIN; + termkey_result_t ret; + termkey_key_t key; - TermKeyResult ret; - TermKeyKey key; + int running = 1; + int nextwait = -1; - int running = 1; - int nextwait = -1; + while (running) + { + if (poll (&fd, 1, nextwait) == 0) + // Timed out + if (termkey_getkey_force (tk, &key) == TERMKEY_RES_KEY) + on_key (tk, &key); - while(running) { - if(poll(&fd, 1, nextwait) == 0) { - // Timed out - if(termkey_getkey_force(tk, &key) == TERMKEY_RES_KEY) - on_key(tk, &key); - } + if (fd.revents & (POLLIN | POLLHUP | POLLERR)) + termkey_advisereadable (tk); - if(fd.revents & (POLLIN|POLLHUP|POLLERR)) - termkey_advisereadable(tk); + while ((ret = termkey_getkey (tk, &key)) == TERMKEY_RES_KEY) + { + on_key (tk, &key); - while((ret = termkey_getkey(tk, &key)) == TERMKEY_RES_KEY) { - on_key(tk, &key); + if (key.type == TERMKEY_TYPE_UNICODE + && key.modifiers & TERMKEY_KEYMOD_CTRL + && (key.code.codepoint == 'C' || key.code.codepoint == 'c')) + running = 0; + } - if(key.type == TERMKEY_TYPE_UNICODE && - key.modifiers & TERMKEY_KEYMOD_CTRL && - (key.code.codepoint == 'C' || key.code.codepoint == 'c')) - running = 0; - } + if (ret == TERMKEY_RES_AGAIN) + nextwait = termkey_get_waittime (tk); + else + nextwait = -1; + } - if(ret == TERMKEY_RES_AGAIN) - nextwait = termkey_get_waittime(tk); - else - nextwait = -1; - } - - termkey_destroy(tk); + termkey_destroy (tk); } diff --git a/demo-glib.c b/demo-glib.c index 7dc8d87..00f5aa2 100644 --- a/demo-glib.c +++ b/demo-glib.c @@ -3,63 +3,63 @@ #include "termkey.h" -static TermKey *tk; +static termkey_t *tk; static int timeout_id; -static void on_key(TermKey *tk, TermKeyKey *key) +static void +on_key (termkey_t *tk, termkey_key_t *key) { - char buffer[50]; - termkey_strfkey(tk, buffer, sizeof buffer, key, TERMKEY_FORMAT_VIM); - printf("%s\n", buffer); + char buffer[50]; + termkey_strfkey (tk, buffer, sizeof buffer, key, TERMKEY_FORMAT_VIM); + printf ("%s\n", buffer); } -static gboolean key_timer(gpointer data) +static gboolean +key_timer (gpointer data) { - TermKeyKey key; - - if(termkey_getkey_force(tk, &key) == TERMKEY_RES_KEY) - on_key(tk, &key); - - return FALSE; + termkey_key_t key; + if (termkey_getkey_force (tk, &key) == TERMKEY_RES_KEY) + on_key (tk, &key); + return FALSE; } -static gboolean stdin_io(GIOChannel *source, GIOCondition condition, gpointer data) +static gboolean +stdin_io (GIOChannel *source, GIOCondition condition, gpointer data) { - if(condition && G_IO_IN) { - if(timeout_id) - g_source_remove(timeout_id); + if (condition && G_IO_IN) + { + if (timeout_id) + g_source_remove (timeout_id); - termkey_advisereadable(tk); + termkey_advisereadable (tk); - TermKeyResult ret; - TermKeyKey key; - while((ret = termkey_getkey(tk, &key)) == TERMKEY_RES_KEY) { - on_key(tk, &key); - } + termkey_result_t ret; + termkey_key_t key; + while ((ret = termkey_getkey (tk, &key)) == TERMKEY_RES_KEY) + on_key (tk, &key); - if(ret == TERMKEY_RES_AGAIN) - timeout_id = g_timeout_add(termkey_get_waittime(tk), key_timer, NULL); - } + if (ret == TERMKEY_RES_AGAIN) + timeout_id = g_timeout_add + (termkey_get_waittime (tk), key_timer, NULL); + } - return TRUE; + return TRUE; } -int main(int argc, char *argv[]) +int +main (int argc, char *argv[]) { - TERMKEY_CHECK_VERSION; - - tk = termkey_new(0, 0); - - if(!tk) { - fprintf(stderr, "Cannot allocate termkey instance\n"); - exit(1); - } - - GMainLoop *loop = g_main_loop_new(NULL, FALSE); - - g_io_add_watch(g_io_channel_unix_new(0), G_IO_IN, stdin_io, NULL); - - g_main_loop_run(loop); - - termkey_destroy(tk); + TERMKEY_CHECK_VERSION; + + tk = termkey_new (0, 0); + if (!tk) + { + fprintf (stderr, "Cannot allocate termkey instance\n"); + exit (1); + } + + GMainLoop *loop = g_main_loop_new (NULL, FALSE); + g_io_add_watch (g_io_channel_unix_new (0), G_IO_IN, stdin_io, NULL); + g_main_loop_run (loop); + termkey_destroy (tk); } diff --git a/demo.c b/demo.c index 3ff68e0..c53eb0b 100644 --- a/demo.c +++ b/demo.c @@ -7,112 +7,129 @@ #include "termkey.h" -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { - TERMKEY_CHECK_VERSION; - - int mouse = 0; - int mouse_proto = 0; - TermKeyFormat format = TERMKEY_FORMAT_VIM; - - char buffer[50]; - TermKey *tk; - - int opt; - while((opt = getopt(argc, argv, "m::p:")) != -1) { - switch(opt) { - case 'm': - if(optarg) - mouse = atoi(optarg); - else - mouse = 1000; - - break; - - case 'p': - mouse_proto = atoi(optarg); - break; - - default: - fprintf(stderr, "Usage: %s [-m]\n", argv[0]); - return 1; - } - } - - tk = termkey_new(0, TERMKEY_FLAG_SPACESYMBOL|TERMKEY_FLAG_CTRLC); - - if(!tk) { - fprintf(stderr, "Cannot allocate termkey instance\n"); - exit(1); - } - - if(termkey_get_flags(tk) & TERMKEY_FLAG_UTF8) - printf("Termkey in UTF-8 mode\n"); - else if(termkey_get_flags(tk) & TERMKEY_FLAG_RAW) - printf("Termkey in RAW mode\n"); - - TermKeyResult ret; - TermKeyKey key; - - if(mouse) { - printf("\033[?%dhMouse mode active\n", mouse); - if(mouse_proto) - printf("\033[?%dh", mouse_proto); - } - - while((ret = termkey_waitkey(tk, &key)) != TERMKEY_RES_EOF) { - if(ret == TERMKEY_RES_KEY) { - termkey_strfkey(tk, buffer, sizeof buffer, &key, format); - if(key.type == TERMKEY_TYPE_MOUSE) { - int line, col; - termkey_interpret_mouse(tk, &key, NULL, NULL, &line, &col); - printf("%s at line=%d, col=%d\n", buffer, line, col); - } - else if(key.type == TERMKEY_TYPE_POSITION) { - int line, col; - termkey_interpret_position(tk, &key, &line, &col); - printf("Cursor position report at line=%d, col=%d\n", line, col); - } - else if(key.type == TERMKEY_TYPE_MODEREPORT) { - int initial, mode, value; - termkey_interpret_modereport(tk, &key, &initial, &mode, &value); - printf("Mode report %s mode %d = %d\n", initial ? "DEC" : "ANSI", mode, value); - } - else if(key.type == TERMKEY_TYPE_UNKNOWN_CSI) { - long args[16]; - size_t nargs = 16; - unsigned long command; - termkey_interpret_csi(tk, &key, args, &nargs, &command); - printf("Unrecognised CSI %c %ld;%ld %c%c\n", (char)(command >> 8), args[0], args[1], (char)(command >> 16), (char)command); - } - else { - printf("Key %s\n", buffer); - } - - if(key.type == TERMKEY_TYPE_UNICODE && - key.modifiers & TERMKEY_KEYMOD_CTRL && - (key.code.codepoint == 'C' || key.code.codepoint == 'c')) - break; - - if(key.type == TERMKEY_TYPE_UNICODE && - key.modifiers == 0 && - key.code.codepoint == '?') { - // printf("\033[?6n"); // DECDSR 6 == request cursor position - printf("\033[?1$p"); // DECRQM == request mode, DEC origin mode - fflush(stdout); - } - } - else if(ret == TERMKEY_RES_ERROR) { - if(errno != EINTR) { - perror("termkey_waitkey"); - break; - } - printf("Interrupted by signal\n"); - } - } - - if(mouse) - printf("\033[?%dlMouse mode deactivated\n", mouse); - - termkey_destroy(tk); + TERMKEY_CHECK_VERSION; + + int mouse = 0; + int mouse_proto = 0; + termkey_format_t format = TERMKEY_FORMAT_VIM; + + char buffer[50]; + termkey_t *tk; + + int opt; + while ((opt = getopt (argc, argv, "m::p:")) != -1) + { + switch (opt) + { + case 'm': + if (optarg) + mouse = atoi (optarg); + else + mouse = 1000; + break; + + case 'p': + mouse_proto = atoi (optarg); + break; + + default: + fprintf (stderr, "Usage: %s [-m]\n", argv[0]); + return 1; + } + } + + tk = termkey_new (0, TERMKEY_FLAG_SPACESYMBOL | TERMKEY_FLAG_CTRLC); + + if (!tk) + { + fprintf (stderr, "Cannot allocate termkey instance\n"); + exit (1); + } + + if (termkey_get_flags (tk) & TERMKEY_FLAG_UTF8) + printf ("Termkey in UTF-8 mode\n"); + else if (termkey_get_flags (tk) & TERMKEY_FLAG_RAW) + printf ("Termkey in RAW mode\n"); + + termkey_result_t ret; + termkey_key_t key; + + if (mouse) + { + printf ("\033[?%dhMouse mode active\n", mouse); + if (mouse_proto) + printf ("\033[?%dh", mouse_proto); + } + + while ((ret = termkey_waitkey (tk, &key)) != TERMKEY_RES_EOF) + { + if (ret == TERMKEY_RES_KEY) + { + termkey_strfkey (tk, buffer, sizeof buffer, &key, format); + if (key.type == TERMKEY_TYPE_MOUSE) + { + int line, col; + termkey_interpret_mouse (tk, &key, NULL, NULL, &line, &col); + printf ("%s at line=%d, col=%d\n", buffer, line, col); + } + else if (key.type == TERMKEY_TYPE_POSITION) + { + int line, col; + termkey_interpret_position (tk, &key, &line, &col); + printf ("Cursor position report at line=%d, col=%d\n", + line, col); + } + else if (key.type == TERMKEY_TYPE_MODEREPORT) + { + int initial, mode, value; + termkey_interpret_modereport + (tk, &key, &initial, &mode, &value); + printf ("Mode report %s mode %d = %d\n", + initial ? "DEC" : "ANSI", mode, value); + } + else if (key.type == TERMKEY_TYPE_UNKNOWN_CSI) + { + long args[16]; + size_t nargs = 16; + unsigned long command; + termkey_interpret_csi (tk, &key, args, &nargs, &command); + printf ("Unrecognised CSI %c %ld;%ld %c%c\n", + (char) (command >> 8), args[0], args[1], + (char) (command >> 16), (char) command); + } + else + printf ("Key %s\n", buffer); + + if (key.type == TERMKEY_TYPE_UNICODE + && key.modifiers & TERMKEY_KEYMOD_CTRL + && (key.code.codepoint == 'C' || key.code.codepoint == 'c')) + break; + + if (key.type == TERMKEY_TYPE_UNICODE + && key.modifiers == 0 + && key.code.codepoint == '?') + { + // printf("\033[?6n"); // DECDSR 6 == request cursor position + printf ("\033[?1$p"); // DECRQM == request mode, DEC origin mode + fflush (stdout); + } + } + else if (ret == TERMKEY_RES_ERROR) + { + if (errno != EINTR) + { + perror("termkey_waitkey"); + break; + } + printf ("Interrupted by signal\n"); + } + } + + if (mouse) + printf ("\033[?%dlMouse mode deactivated\n", mouse); + + termkey_destroy (tk); } diff --git a/driver-csi.c b/driver-csi.c index 45e6dcf..c2b2673 100644 --- a/driver-csi.c +++ b/driver-csi.c @@ -9,12 +9,15 @@ static int keyinfo_initialised = 0; static struct keyinfo ss3s[64]; static char ss3_kpalts[64]; -typedef struct { - TermKey *tk; -} TermKeyCsi; +typedef struct +{ + termkey_t *tk; +} +termkey_csi_t; -typedef TermKeyResult CsiHandler(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args); -static CsiHandler *csi_handlers[64]; +typedef termkey_result_t (*csi_handler_fn) + (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args); +static csi_handler_fn csi_handlers[64]; /* * Handler for CSI/SS3 cmd keys @@ -22,137 +25,148 @@ static CsiHandler *csi_handlers[64]; static struct keyinfo csi_ss3s[64]; -static TermKeyResult handle_csi_ss3_full(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args) +static termkey_result_t +handle_csi_ss3_full (termkey_t *tk, + termkey_key_t *key, int cmd, long *arg, int args) { - if(args > 1 && arg[1] != -1) - key->modifiers = arg[1] - 1; - else - key->modifiers = 0; - - key->type = csi_ss3s[cmd - 0x40].type; - key->code.sym = csi_ss3s[cmd - 0x40].sym; - key->modifiers &= ~(csi_ss3s[cmd - 0x40].modifier_mask); - key->modifiers |= csi_ss3s[cmd - 0x40].modifier_set; - - if(key->code.sym == TERMKEY_SYM_UNKNOWN) - return TERMKEY_RES_NONE; - - return TERMKEY_RES_KEY; + if (args > 1 && arg[1] != -1) + key->modifiers = arg[1] - 1; + else + key->modifiers = 0; + + key->type = csi_ss3s[cmd - 0x40].type; + key->code.sym = csi_ss3s[cmd - 0x40].sym; + key->modifiers &= ~(csi_ss3s[cmd - 0x40].modifier_mask); + key->modifiers |= csi_ss3s[cmd - 0x40].modifier_set; + + if (key->code.sym == TERMKEY_SYM_UNKNOWN) + return TERMKEY_RES_NONE; + return TERMKEY_RES_KEY; } -static void register_csi_ss3_full(TermKeyType type, TermKeySym sym, int modifier_set, int modifier_mask, unsigned char cmd) +static void +register_csi_ss3_full (termkey_type_t type, termkey_sym_t sym, + int modifier_set, int modifier_mask, unsigned char cmd) { - if(cmd < 0x40 || cmd >= 0x80) { - return; - } + if (cmd < 0x40 || cmd >= 0x80) + return; - csi_ss3s[cmd - 0x40].type = type; - csi_ss3s[cmd - 0x40].sym = sym; - csi_ss3s[cmd - 0x40].modifier_set = modifier_set; - csi_ss3s[cmd - 0x40].modifier_mask = modifier_mask; + csi_ss3s[cmd - 0x40].type = type; + csi_ss3s[cmd - 0x40].sym = sym; + csi_ss3s[cmd - 0x40].modifier_set = modifier_set; + csi_ss3s[cmd - 0x40].modifier_mask = modifier_mask; - csi_handlers[cmd - 0x40] = &handle_csi_ss3_full; + csi_handlers[cmd - 0x40] = &handle_csi_ss3_full; } -static void register_csi_ss3(TermKeyType type, TermKeySym sym, unsigned char cmd) +static void +register_csi_ss3 (termkey_type_t type, termkey_sym_t sym, unsigned char cmd) { - register_csi_ss3_full(type, sym, 0, 0, cmd); + register_csi_ss3_full (type, sym, 0, 0, cmd); } /* * Handler for SS3 keys with kpad alternate representations */ -static void register_ss3kpalt(TermKeyType type, TermKeySym sym, unsigned char cmd, char kpalt) +static void +register_ss3kpalt (termkey_type_t type, termkey_sym_t sym, + unsigned char cmd, char kpalt) { - if(cmd < 0x40 || cmd >= 0x80) { - return; - } - - ss3s[cmd - 0x40].type = type; - ss3s[cmd - 0x40].sym = sym; - ss3s[cmd - 0x40].modifier_set = 0; - ss3s[cmd - 0x40].modifier_mask = 0; - ss3_kpalts[cmd - 0x40] = kpalt; + if (cmd < 0x40 || cmd >= 0x80) + return; + + ss3s[cmd - 0x40].type = type; + ss3s[cmd - 0x40].sym = sym; + ss3s[cmd - 0x40].modifier_set = 0; + ss3s[cmd - 0x40].modifier_mask = 0; + + ss3_kpalts[cmd - 0x40] = kpalt; } /* * Handler for CSI number ~ function keys */ -static struct keyinfo csifuncs[35]; /* This value must be increased if more CSI function keys are added */ -#define NCSIFUNCS (sizeof(csifuncs)/sizeof(csifuncs[0])) +/* This value must be increased if more CSI function keys are added */ +static struct keyinfo csifuncs[35]; +#define NCSIFUNCS (sizeof csifuncs / sizeof csifuncs[0]) -static TermKeyResult handle_csifunc(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args) +static termkey_result_t +handle_csifunc (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args) { - if(args > 1 && arg[1] != -1) - key->modifiers = arg[1] - 1; - else - key->modifiers = 0; - - key->type = TERMKEY_TYPE_KEYSYM; - - if(arg[0] == 27) { - int mod = key->modifiers; - (*tk->method.emit_codepoint)(tk, arg[2], key); - key->modifiers |= mod; - } - else if(arg[0] >= 0 && arg[0] < NCSIFUNCS) { - key->type = csifuncs[arg[0]].type; - key->code.sym = csifuncs[arg[0]].sym; - key->modifiers &= ~(csifuncs[arg[0]].modifier_mask); - key->modifiers |= csifuncs[arg[0]].modifier_set; - } - else - key->code.sym = TERMKEY_SYM_UNKNOWN; - - if(key->code.sym == TERMKEY_SYM_UNKNOWN) { + if (args > 1 && arg[1] != -1) + key->modifiers = arg[1] - 1; + else + key->modifiers = 0; + key->type = TERMKEY_TYPE_KEYSYM; + + if (arg[0] == 27) + { + int mod = key->modifiers; + (*tk->method.emit_codepoint) (tk, arg[2], key); + key->modifiers |= mod; + } + else if (arg[0] >= 0 && arg[0] < NCSIFUNCS) + { + key->type = csifuncs[arg[0]].type; + key->code.sym = csifuncs[arg[0]].sym; + key->modifiers &= ~(csifuncs[arg[0]].modifier_mask); + key->modifiers |= csifuncs[arg[0]].modifier_set; + } + else + key->code.sym = TERMKEY_SYM_UNKNOWN; + + if (key->code.sym == TERMKEY_SYM_UNKNOWN) + { #ifdef DEBUG - fprintf(stderr, "CSI: Unknown function key %ld\n", arg[0]); + fprintf (stderr, "CSI: Unknown function key %ld\n", arg[0]); #endif - return TERMKEY_RES_NONE; - } + return TERMKEY_RES_NONE; + } - return TERMKEY_RES_KEY; + return TERMKEY_RES_KEY; } -static void register_csifunc(TermKeyType type, TermKeySym sym, int number) +static void +register_csifunc (termkey_type_t type, termkey_sym_t sym, int number) { - if(number >= NCSIFUNCS) { - return; - } + if (number >= NCSIFUNCS) + return; - csifuncs[number].type = type; - csifuncs[number].sym = sym; - csifuncs[number].modifier_set = 0; - csifuncs[number].modifier_mask = 0; + csifuncs[number].type = type; + csifuncs[number].sym = sym; + csifuncs[number].modifier_set = 0; + csifuncs[number].modifier_mask = 0; - csi_handlers['~' - 0x40] = &handle_csifunc; + csi_handlers['~' - 0x40] = &handle_csifunc; } /* * Handler for CSI u extended Unicode keys */ -static TermKeyResult handle_csi_u(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args) +static termkey_result_t +handle_csi_u (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args) { - switch(cmd) { - case 'u': { - if(args > 1 && arg[1] != -1) - key->modifiers = arg[1] - 1; - else - key->modifiers = 0; - - int mod = key->modifiers; - key->type = TERMKEY_TYPE_KEYSYM; - (*tk->method.emit_codepoint)(tk, arg[0], key); - key->modifiers |= mod; - - return TERMKEY_RES_KEY; - } - default: - return TERMKEY_RES_NONE; - } + switch (cmd) + { + case 'u': + { + if (args > 1 && arg[1] != -1) + key->modifiers = arg[1] - 1; + else + key->modifiers = 0; + + int mod = key->modifiers; + key->type = TERMKEY_TYPE_KEYSYM; + (*tk->method.emit_codepoint) (tk, arg[0], key); + key->modifiers |= mod; + return TERMKEY_RES_KEY; + } + default: + return TERMKEY_RES_NONE; + } } /* @@ -160,100 +174,101 @@ static TermKeyResult handle_csi_u(TermKey *tk, TermKeyKey *key, int cmd, long *a * Note: This does not handle X10 encoding */ -static TermKeyResult handle_csi_m(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args) +static termkey_result_t +handle_csi_m (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args) { - int initial = cmd >> 8; - cmd &= 0xff; - - switch(cmd) { - case 'M': - case 'm': - break; - default: - return TERMKEY_RES_NONE; - } - - if(!initial && args >= 3) { // rxvt protocol - key->type = TERMKEY_TYPE_MOUSE; - key->code.mouse[0] = arg[0]; - - key->modifiers = (key->code.mouse[0] & 0x1c) >> 2; - key->code.mouse[0] &= ~0x1c; - - termkey_key_set_linecol(key, arg[1], arg[2]); - - return TERMKEY_RES_KEY; - } - - if(initial == '<' && args >= 3) { // SGR protocol - key->type = TERMKEY_TYPE_MOUSE; - key->code.mouse[0] = arg[0]; - - key->modifiers = (key->code.mouse[0] & 0x1c) >> 2; - key->code.mouse[0] &= ~0x1c; - - termkey_key_set_linecol(key, arg[1], arg[2]); - - if(cmd == 'm') // release - key->code.mouse[3] |= 0x80; - - return TERMKEY_RES_KEY; - } - - return TERMKEY_RES_NONE; + int initial = cmd >> 8; + cmd &= 0xff; + + switch (cmd) + { + case 'M': + case 'm': + break; + default: + return TERMKEY_RES_NONE; + } + + if (!initial && args >= 3) + { + // rxvt protocol + key->type = TERMKEY_TYPE_MOUSE; + key->code.mouse[0] = arg[0]; + + key->modifiers = (key->code.mouse[0] & 0x1c) >> 2; + key->code.mouse[0] &= ~0x1c; + + termkey_key_set_linecol (key, arg[1], arg[2]); + return TERMKEY_RES_KEY; + } + + if (initial == '<' && args >= 3) + { + // SGR protocol + key->type = TERMKEY_TYPE_MOUSE; + key->code.mouse[0] = arg[0]; + + key->modifiers = (key->code.mouse[0] & 0x1c) >> 2; + key->code.mouse[0] &= ~0x1c; + + termkey_key_set_linecol (key, arg[1], arg[2]); + + if (cmd == 'm') // release + key->code.mouse[3] |= 0x80; + return TERMKEY_RES_KEY; + } + return TERMKEY_RES_NONE; } -TermKeyResult termkey_interpret_mouse(TermKey *tk, const TermKeyKey *key, TermKeyMouseEvent *event, int *button, int *line, int *col) +termkey_result_t +termkey_interpret_mouse (termkey_t *tk, const termkey_key_t *key, + termkey_mouse_event_t *event, int *button, int *line, int *col) { - if(key->type != TERMKEY_TYPE_MOUSE) - return TERMKEY_RES_NONE; - - if(button) - *button = 0; - - termkey_key_get_linecol(key, line, col); - - if(!event) - return TERMKEY_RES_KEY; - - int btn = 0; - - int code = key->code.mouse[0]; - - int drag = code & 0x20; - - code &= ~0x3c; - - switch(code) { - case 0: - case 1: - case 2: - *event = drag ? TERMKEY_MOUSE_DRAG : TERMKEY_MOUSE_PRESS; - btn = code + 1; - break; - - case 3: - *event = TERMKEY_MOUSE_RELEASE; - // no button hint - break; - - case 64: - case 65: - *event = drag ? TERMKEY_MOUSE_DRAG : TERMKEY_MOUSE_PRESS; - btn = code + 4 - 64; - break; - - default: - *event = TERMKEY_MOUSE_UNKNOWN; - } - - if(button) - *button = btn; - - if(key->code.mouse[3] & 0x80) - *event = TERMKEY_MOUSE_RELEASE; - - return TERMKEY_RES_KEY; + if (key->type != TERMKEY_TYPE_MOUSE) + return TERMKEY_RES_NONE; + + if (button) + *button = 0; + + termkey_key_get_linecol (key, line, col); + + if (!event) + return TERMKEY_RES_KEY; + + int btn = 0; + int code = key->code.mouse[0]; + int drag = code & 0x20; + code &= ~0x3c; + + switch (code) + { + case 0: + case 1: + case 2: + *event = drag ? TERMKEY_MOUSE_DRAG : TERMKEY_MOUSE_PRESS; + btn = code + 1; + break; + + case 3: + *event = TERMKEY_MOUSE_RELEASE; + // no button hint + break; + + case 64: + case 65: + *event = drag ? TERMKEY_MOUSE_DRAG : TERMKEY_MOUSE_PRESS; + btn = code + 4 - 64; + break; + + default: + *event = TERMKEY_MOUSE_UNKNOWN; + } + + if (button) + *button = btn; + if (key->code.mouse[3] & 0x80) + *event = TERMKEY_MOUSE_RELEASE; + return TERMKEY_RES_KEY; } /* @@ -261,413 +276,432 @@ TermKeyResult termkey_interpret_mouse(TermKey *tk, const TermKeyKey *key, TermKe * A plain CSI R with no arguments is probably actually */ -static TermKeyResult handle_csi_R(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args) +static termkey_result_t +handle_csi_R (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args) { - switch(cmd) { - case 'R'|'?'<<8: - if(args < 2) - return TERMKEY_RES_NONE; - - key->type = TERMKEY_TYPE_POSITION; - termkey_key_set_linecol(key, arg[1], arg[0]); - return TERMKEY_RES_KEY; - - default: - return handle_csi_ss3_full(tk, key, cmd, arg, args); - } + switch (cmd) + { + case 'R' | '?' << 8: + if (args < 2) + return TERMKEY_RES_NONE; + + key->type = TERMKEY_TYPE_POSITION; + termkey_key_set_linecol (key, arg[1], arg[0]); + return TERMKEY_RES_KEY; + + default: + return handle_csi_ss3_full (tk, key, cmd, arg, args); + } } -TermKeyResult termkey_interpret_position(TermKey *tk, const TermKeyKey *key, int *line, int *col) +termkey_result_t +termkey_interpret_position (termkey_t *tk, + const termkey_key_t *key, int *line, int *col) { - if(key->type != TERMKEY_TYPE_POSITION) - return TERMKEY_RES_NONE; - - termkey_key_get_linecol(key, line, col); + if (key->type != TERMKEY_TYPE_POSITION) + return TERMKEY_RES_NONE; - return TERMKEY_RES_KEY; + termkey_key_get_linecol (key, line, col); + return TERMKEY_RES_KEY; } /* * Handler for CSI $y mode status reports */ -static TermKeyResult handle_csi_y(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args) +static termkey_result_t +handle_csi_y (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args) { - switch(cmd) { - case 'y'|'$'<<16: - case 'y'|'$'<<16 | '?'<<8: - if(args < 2) - return TERMKEY_RES_NONE; - - key->type = TERMKEY_TYPE_MODEREPORT; - key->code.mouse[0] = (cmd >> 8); - key->code.mouse[1] = arg[0] >> 8; - key->code.mouse[2] = arg[0] & 0xff; - key->code.mouse[3] = arg[1]; - return TERMKEY_RES_KEY; - - default: - return TERMKEY_RES_NONE; - } + switch (cmd) + { + case 'y' | '$' << 16: + case 'y' | '$' << 16 | '?' << 8: + if (args < 2) + return TERMKEY_RES_NONE; + + key->type = TERMKEY_TYPE_MODEREPORT; + key->code.mouse[0] = (cmd >> 8); + key->code.mouse[1] = arg[0] >> 8; + key->code.mouse[2] = arg[0] & 0xff; + key->code.mouse[3] = arg[1]; + return TERMKEY_RES_KEY; + + default: + return TERMKEY_RES_NONE; + } } -TermKeyResult termkey_interpret_modereport(TermKey *tk, const TermKeyKey *key, int *initial, int *mode, int *value) +termkey_result_t +termkey_interpret_modereport (termkey_t *tk, + const termkey_key_t *key, int *initial, int *mode, int *value) { - if(key->type != TERMKEY_TYPE_MODEREPORT) - return TERMKEY_RES_NONE; - - if(initial) - *initial = key->code.mouse[0]; - - if(mode) - *mode = (key->code.mouse[1] << 8) | key->code.mouse[2]; - - if(value) - *value = key->code.mouse[3]; - - return TERMKEY_RES_KEY; + if (key->type != TERMKEY_TYPE_MODEREPORT) + return TERMKEY_RES_NONE; + + if (initial) + *initial = key->code.mouse[0]; + if (mode) + *mode = (key->code.mouse[1] << 8) | key->code.mouse[2]; + if (value) + *value = key->code.mouse[3]; + return TERMKEY_RES_KEY; } #define CHARAT(i) (tk->buffer[tk->buffstart + (i)]) -static TermKeyResult parse_csi(TermKey *tk, size_t introlen, size_t *csi_len, long args[], size_t *nargs, unsigned long *commandp) +static termkey_result_t +parse_csi (termkey_t *tk, size_t introlen, size_t *csi_len, + long args[], size_t *nargs, unsigned long *commandp) { - size_t csi_end = introlen; - - while(csi_end < tk->buffcount) { - if(CHARAT(csi_end) >= 0x40 && CHARAT(csi_end) < 0x80) - break; - csi_end++; - } - - if(csi_end >= tk->buffcount) - return TERMKEY_RES_AGAIN; - - unsigned char cmd = CHARAT(csi_end); - *commandp = cmd; - - char present = 0; - int argi = 0; - - size_t p = introlen; - - // See if there is an initial byte - if(CHARAT(p) >= '<' && CHARAT(p) <= '?') { - *commandp |= (CHARAT(p) << 8); - p++; - } - - // Now attempt to parse out up number;number;... separated values - while(p < csi_end) { - unsigned char c = CHARAT(p); - - if(c >= '0' && c <= '9') { - if(!present) { - args[argi] = c - '0'; - present = 1; - } - else { - args[argi] = (args[argi] * 10) + c - '0'; - } - } - else if(c == ';') { - if(!present) - args[argi] = -1; - present = 0; - argi++; - - if(argi > 16) - break; - } - else if(c >= 0x20 && c <= 0x2f) { - *commandp |= c << 16; - break; - } - - p++; - } - - if(present) - argi++; - - *nargs = argi; - *csi_len = csi_end + 1; - - return TERMKEY_RES_KEY; + size_t csi_end = introlen; + while (csi_end < tk->buffcount) + { + if (CHARAT (csi_end) >= 0x40 && CHARAT (csi_end) < 0x80) + break; + csi_end++; + } + + if (csi_end >= tk->buffcount) + return TERMKEY_RES_AGAIN; + + unsigned char cmd = CHARAT (csi_end); + *commandp = cmd; + + char present = 0; + int argi = 0; + + size_t p = introlen; + + // See if there is an initial byte + if (CHARAT (p) >= '<' && CHARAT (p) <= '?') + { + *commandp |= (CHARAT (p) << 8); + p++; + } + + // Now attempt to parse out up number;number;... separated values + for (; p < csi_end; p++) + { + unsigned char c = CHARAT (p); + if (c >= '0' && c <= '9') + { + if (!present) + { + args[argi] = c - '0'; + present = 1; + } + else + args[argi] = (args[argi] * 10) + c - '0'; + } + else if (c == ';') + { + if (!present) + args[argi] = -1; + present = 0; + argi++; + + if (argi > 16) + break; + } + else if (c >= 0x20 && c <= 0x2f) + { + *commandp |= c << 16; + break; + } + } + + if (present) + argi++; + + *nargs = argi; + *csi_len = csi_end + 1; + return TERMKEY_RES_KEY; } -TermKeyResult termkey_interpret_csi(TermKey *tk, const TermKeyKey *key, long args[], size_t *nargs, unsigned long *cmd) +termkey_result_t +termkey_interpret_csi (termkey_t *tk, const termkey_key_t *key, + long args[], size_t *nargs, unsigned long *cmd) { - size_t dummy; + if (tk->hightide == 0) + return TERMKEY_RES_NONE; + if (key->type != TERMKEY_TYPE_UNKNOWN_CSI) + return TERMKEY_RES_NONE; - if(tk->hightide == 0) - return TERMKEY_RES_NONE; - if(key->type != TERMKEY_TYPE_UNKNOWN_CSI) - return TERMKEY_RES_NONE; - - return parse_csi(tk, 0, &dummy, args, nargs, cmd); + size_t dummy; + return parse_csi (tk, 0, &dummy, args, nargs, cmd); } -static int register_keys(void) +static int +register_keys (void) { - int i; - - for(i = 0; i < 64; i++) { - csi_ss3s[i].sym = TERMKEY_SYM_UNKNOWN; - ss3s[i].sym = TERMKEY_SYM_UNKNOWN; - ss3_kpalts[i] = 0; - } - - for(i = 0; i < NCSIFUNCS; i++) - csifuncs[i].sym = TERMKEY_SYM_UNKNOWN; - - register_csi_ss3(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UP, 'A'); - register_csi_ss3(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DOWN, 'B'); - register_csi_ss3(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RIGHT, 'C'); - register_csi_ss3(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_LEFT, 'D'); - register_csi_ss3(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 'E'); - register_csi_ss3(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_END, 'F'); - register_csi_ss3(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HOME, 'H'); - register_csi_ss3(TERMKEY_TYPE_FUNCTION, 1, 'P'); - register_csi_ss3(TERMKEY_TYPE_FUNCTION, 2, 'Q'); - register_csi_ss3(TERMKEY_TYPE_FUNCTION, 3, 'R'); - register_csi_ss3(TERMKEY_TYPE_FUNCTION, 4, 'S'); - - register_csi_ss3_full(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_TAB, TERMKEY_KEYMOD_SHIFT, TERMKEY_KEYMOD_SHIFT, 'Z'); - - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPENTER, 'M', 0); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPEQUALS, 'X', '='); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPMULT, 'j', '*'); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPPLUS, 'k', '+'); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPCOMMA, 'l', ','); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPMINUS, 'm', '-'); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPPERIOD, 'n', '.'); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPDIV, 'o', '/'); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP0, 'p', '0'); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP1, 'q', '1'); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP2, 'r', '2'); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP3, 's', '3'); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP4, 't', '4'); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP5, 'u', '5'); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP6, 'v', '6'); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP7, 'w', '7'); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP8, 'x', '8'); - register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP9, 'y', '9'); - - register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_FIND, 1); - register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_INSERT, 2); - register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DELETE, 3); - register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SELECT, 4); - register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 5); - register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 6); - register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HOME, 7); - register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_END, 8); - - register_csifunc(TERMKEY_TYPE_FUNCTION, 1, 11); - register_csifunc(TERMKEY_TYPE_FUNCTION, 2, 12); - register_csifunc(TERMKEY_TYPE_FUNCTION, 3, 13); - register_csifunc(TERMKEY_TYPE_FUNCTION, 4, 14); - register_csifunc(TERMKEY_TYPE_FUNCTION, 5, 15); - register_csifunc(TERMKEY_TYPE_FUNCTION, 6, 17); - register_csifunc(TERMKEY_TYPE_FUNCTION, 7, 18); - register_csifunc(TERMKEY_TYPE_FUNCTION, 8, 19); - register_csifunc(TERMKEY_TYPE_FUNCTION, 9, 20); - register_csifunc(TERMKEY_TYPE_FUNCTION, 10, 21); - register_csifunc(TERMKEY_TYPE_FUNCTION, 11, 23); - register_csifunc(TERMKEY_TYPE_FUNCTION, 12, 24); - register_csifunc(TERMKEY_TYPE_FUNCTION, 13, 25); - register_csifunc(TERMKEY_TYPE_FUNCTION, 14, 26); - register_csifunc(TERMKEY_TYPE_FUNCTION, 15, 28); - register_csifunc(TERMKEY_TYPE_FUNCTION, 16, 29); - register_csifunc(TERMKEY_TYPE_FUNCTION, 17, 31); - register_csifunc(TERMKEY_TYPE_FUNCTION, 18, 32); - register_csifunc(TERMKEY_TYPE_FUNCTION, 19, 33); - register_csifunc(TERMKEY_TYPE_FUNCTION, 20, 34); - - csi_handlers['u' - 0x40] = &handle_csi_u; - - csi_handlers['M' - 0x40] = &handle_csi_m; - csi_handlers['m' - 0x40] = &handle_csi_m; - - csi_handlers['R' - 0x40] = &handle_csi_R; - - csi_handlers['y' - 0x40] = &handle_csi_y; - - keyinfo_initialised = 1; - return 1; + int i; + for (i = 0; i < 64; i++) + { + csi_ss3s[i].sym = TERMKEY_SYM_UNKNOWN; + ss3s[i].sym = TERMKEY_SYM_UNKNOWN; + ss3_kpalts[i] = 0; + } + for (i = 0; i < NCSIFUNCS; i++) + csifuncs[i].sym = TERMKEY_SYM_UNKNOWN; + + register_csi_ss3 (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UP, 'A'); + register_csi_ss3 (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DOWN, 'B'); + register_csi_ss3 (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RIGHT, 'C'); + register_csi_ss3 (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_LEFT, 'D'); + register_csi_ss3 (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 'E'); + register_csi_ss3 (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_END, 'F'); + register_csi_ss3 (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HOME, 'H'); + register_csi_ss3 (TERMKEY_TYPE_FUNCTION, 1, 'P'); + register_csi_ss3 (TERMKEY_TYPE_FUNCTION, 2, 'Q'); + register_csi_ss3 (TERMKEY_TYPE_FUNCTION, 3, 'R'); + register_csi_ss3 (TERMKEY_TYPE_FUNCTION, 4, 'S'); + + register_csi_ss3_full (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_TAB, + TERMKEY_KEYMOD_SHIFT, TERMKEY_KEYMOD_SHIFT, 'Z'); + + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPENTER, 'M', 0); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPEQUALS, 'X', '='); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPMULT, 'j', '*'); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPPLUS, 'k', '+'); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPCOMMA, 'l', ','); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPMINUS, 'm', '-'); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPPERIOD, 'n', '.'); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPDIV, 'o', '/'); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP0, 'p', '0'); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP1, 'q', '1'); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP2, 'r', '2'); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP3, 's', '3'); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP4, 't', '4'); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP5, 'u', '5'); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP6, 'v', '6'); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP7, 'w', '7'); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP8, 'x', '8'); + register_ss3kpalt (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP9, 'y', '9'); + + register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_FIND, 1); + register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_INSERT, 2); + register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DELETE, 3); + register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SELECT, 4); + register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 5); + register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 6); + register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HOME, 7); + register_csifunc (TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_END, 8); + + register_csifunc (TERMKEY_TYPE_FUNCTION, 1, 11); + register_csifunc (TERMKEY_TYPE_FUNCTION, 2, 12); + register_csifunc (TERMKEY_TYPE_FUNCTION, 3, 13); + register_csifunc (TERMKEY_TYPE_FUNCTION, 4, 14); + register_csifunc (TERMKEY_TYPE_FUNCTION, 5, 15); + register_csifunc (TERMKEY_TYPE_FUNCTION, 6, 17); + register_csifunc (TERMKEY_TYPE_FUNCTION, 7, 18); + register_csifunc (TERMKEY_TYPE_FUNCTION, 8, 19); + register_csifunc (TERMKEY_TYPE_FUNCTION, 9, 20); + register_csifunc (TERMKEY_TYPE_FUNCTION, 10, 21); + register_csifunc (TERMKEY_TYPE_FUNCTION, 11, 23); + register_csifunc (TERMKEY_TYPE_FUNCTION, 12, 24); + register_csifunc (TERMKEY_TYPE_FUNCTION, 13, 25); + register_csifunc (TERMKEY_TYPE_FUNCTION, 14, 26); + register_csifunc (TERMKEY_TYPE_FUNCTION, 15, 28); + register_csifunc (TERMKEY_TYPE_FUNCTION, 16, 29); + register_csifunc (TERMKEY_TYPE_FUNCTION, 17, 31); + register_csifunc (TERMKEY_TYPE_FUNCTION, 18, 32); + register_csifunc (TERMKEY_TYPE_FUNCTION, 19, 33); + register_csifunc (TERMKEY_TYPE_FUNCTION, 20, 34); + + csi_handlers['u' - 0x40] = &handle_csi_u; + + csi_handlers['M' - 0x40] = &handle_csi_m; + csi_handlers['m' - 0x40] = &handle_csi_m; + + csi_handlers['R' - 0x40] = &handle_csi_R; + + csi_handlers['y' - 0x40] = &handle_csi_y; + + keyinfo_initialised = 1; + return 1; } -static void *new_driver(TermKey *tk, const char *term) +static void * +new_driver (termkey_t *tk, const char *term) { - if(!keyinfo_initialised) - if(!register_keys()) - return NULL; - - TermKeyCsi *csi = malloc(sizeof *csi); - if(!csi) - return NULL; + if (!keyinfo_initialised && !register_keys ()) + return NULL; - csi->tk = tk; + termkey_csi_t *csi = malloc (sizeof *csi); + if (!csi) + return NULL; - return csi; + csi->tk = tk; + return csi; } -static void free_driver(void *info) +static void +free_driver (void *info) { - TermKeyCsi *csi = info; - - free(csi); + termkey_csi_t *csi = info; + free (csi); } -static TermKeyResult peekkey_csi(TermKey *tk, TermKeyCsi *csi, size_t introlen, TermKeyKey *key, int force, size_t *nbytep) +static termkey_result_t +peekkey_csi (termkey_t *tk, termkey_csi_t *csi, + size_t introlen, termkey_key_t *key, int force, size_t *nbytep) { - size_t csi_len; - size_t args = 16; - long arg[16]; - unsigned long cmd; - - TermKeyResult ret = parse_csi(tk, introlen, &csi_len, arg, &args, &cmd); - - if(ret == TERMKEY_RES_AGAIN) { - if(!force) - return TERMKEY_RES_AGAIN; - - (*tk->method.emit_codepoint)(tk, '[', key); - key->modifiers |= TERMKEY_KEYMOD_ALT; - *nbytep = introlen; - return TERMKEY_RES_KEY; - } - - if(cmd == 'M' && args < 3) { // Mouse in X10 encoding consumes the next 3 bytes also - tk->buffstart += csi_len; - tk->buffcount -= csi_len; - - TermKeyResult mouse_result = (*tk->method.peekkey_mouse)(tk, key, nbytep); - - tk->buffstart -= csi_len; - tk->buffcount += csi_len; - - if(mouse_result == TERMKEY_RES_KEY) - *nbytep += csi_len; - - return mouse_result; - } - - TermKeyResult result = TERMKEY_RES_NONE; - - // We know from the logic above that cmd must be >= 0x40 and < 0x80 - if(csi_handlers[(cmd & 0xff) - 0x40]) - result = (*csi_handlers[(cmd & 0xff) - 0x40])(tk, key, cmd, arg, args); - - if(result == TERMKEY_RES_NONE) { + size_t csi_len; + size_t args = 16; + long arg[16]; + unsigned long cmd; + + termkey_result_t ret = parse_csi (tk, introlen, &csi_len, arg, &args, &cmd); + if (ret == TERMKEY_RES_AGAIN) + { + if (!force) + return TERMKEY_RES_AGAIN; + + (*tk->method.emit_codepoint) (tk, '[', key); + key->modifiers |= TERMKEY_KEYMOD_ALT; + *nbytep = introlen; + return TERMKEY_RES_KEY; + } + + // Mouse in X10 encoding consumes the next 3 bytes also + if (cmd == 'M' && args < 3) + { + tk->buffstart += csi_len; + tk->buffcount -= csi_len; + + termkey_result_t mouse_result = + (*tk->method.peekkey_mouse) (tk, key, nbytep); + + tk->buffstart -= csi_len; + tk->buffcount += csi_len; + + if (mouse_result == TERMKEY_RES_KEY) + *nbytep += csi_len; + return mouse_result; + } + + termkey_result_t result = TERMKEY_RES_NONE; + + // We know from the logic above that cmd must be >= 0x40 and < 0x80 + if (csi_handlers[(cmd & 0xff) - 0x40]) + result = (*csi_handlers[(cmd & 0xff) - 0x40]) (tk, key, cmd, arg, args); + + if (result == TERMKEY_RES_NONE) + { #ifdef DEBUG - switch(args) { - case 1: - fprintf(stderr, "CSI: Unknown arg1=%ld cmd=%c\n", arg[0], (char)cmd); - break; - case 2: - fprintf(stderr, "CSI: Unknown arg1=%ld arg2=%ld cmd=%c\n", arg[0], arg[1], (char)cmd); - break; - case 3: - fprintf(stderr, "CSI: Unknown arg1=%ld arg2=%ld arg3=%ld cmd=%c\n", arg[0], arg[1], arg[2], (char)cmd); - break; - default: - fprintf(stderr, "CSI: Unknown arg1=%ld arg2=%ld arg3=%ld ... args=%d cmd=%c\n", arg[0], arg[1], arg[2], args, (char)cmd); - break; - } + switch (args) + { + case 1: + fprintf (stderr, "CSI: Unknown arg1=%ld cmd=%c\n", arg[0], (char)cmd); + break; + case 2: + fprintf (stderr, "CSI: Unknown arg1=%ld arg2=%ld cmd=%c\n", arg[0], arg[1], (char) cmd); + break; + case 3: + fprintf (stderr, "CSI: Unknown arg1=%ld arg2=%ld arg3=%ld cmd=%c\n", arg[0], arg[1], arg[2], (char) cmd); + break; + default: + fprintf (stderr, "CSI: Unknown arg1=%ld arg2=%ld arg3=%ld ... args=%d cmd=%c\n", arg[0], arg[1], arg[2], args, (char) cmd); + break; + } #endif - key->type = TERMKEY_TYPE_UNKNOWN_CSI; - key->code.number = cmd; + key->type = TERMKEY_TYPE_UNKNOWN_CSI; + key->code.number = cmd; - tk->hightide = csi_len - introlen; - *nbytep = introlen; // Do not yet eat the data bytes - return TERMKEY_RES_KEY; - } + tk->hightide = csi_len - introlen; + *nbytep = introlen; // Do not yet eat the data bytes + return TERMKEY_RES_KEY; + } - *nbytep = csi_len; - return result; + *nbytep = csi_len; + return result; } -static TermKeyResult peekkey_ss3(TermKey *tk, TermKeyCsi *csi, size_t introlen, TermKeyKey *key, int force, size_t *nbytep) +static termkey_result_t +peekkey_ss3 (termkey_t *tk, termkey_csi_t *csi, size_t introlen, + termkey_key_t *key, int force, size_t *nbytep) { - if(tk->buffcount < introlen + 1) { - if(!force) - return TERMKEY_RES_AGAIN; - - (*tk->method.emit_codepoint)(tk, 'O', key); - key->modifiers |= TERMKEY_KEYMOD_ALT; - *nbytep = tk->buffcount; - return TERMKEY_RES_KEY; - } - - unsigned char cmd = CHARAT(introlen); - - if(cmd < 0x40 || cmd >= 0x80) - return TERMKEY_RES_NONE; - - key->type = csi_ss3s[cmd - 0x40].type; - key->code.sym = csi_ss3s[cmd - 0x40].sym; - key->modifiers = csi_ss3s[cmd - 0x40].modifier_set; - - if(key->code.sym == TERMKEY_SYM_UNKNOWN) { - if(tk->flags & TERMKEY_FLAG_CONVERTKP && ss3_kpalts[cmd - 0x40]) { - key->type = TERMKEY_TYPE_UNICODE; - key->code.codepoint = ss3_kpalts[cmd - 0x40]; - key->modifiers = 0; - - key->utf8[0] = key->code.codepoint; - key->utf8[1] = 0; - } - else { - key->type = ss3s[cmd - 0x40].type; - key->code.sym = ss3s[cmd - 0x40].sym; - key->modifiers = ss3s[cmd - 0x40].modifier_set; - } - } - - if(key->code.sym == TERMKEY_SYM_UNKNOWN) { + if (tk->buffcount < introlen + 1) + { + if (!force) + return TERMKEY_RES_AGAIN; + + (*tk->method.emit_codepoint) (tk, 'O', key); + key->modifiers |= TERMKEY_KEYMOD_ALT; + *nbytep = tk->buffcount; + return TERMKEY_RES_KEY; + } + + unsigned char cmd = CHARAT (introlen); + + if (cmd < 0x40 || cmd >= 0x80) + return TERMKEY_RES_NONE; + + key->type = csi_ss3s[cmd - 0x40].type; + key->code.sym = csi_ss3s[cmd - 0x40].sym; + key->modifiers = csi_ss3s[cmd - 0x40].modifier_set; + + if (key->code.sym == TERMKEY_SYM_UNKNOWN) + { + if (tk->flags & TERMKEY_FLAG_CONVERTKP && ss3_kpalts[cmd - 0x40]) + { + key->type = TERMKEY_TYPE_UNICODE; + key->code.codepoint = ss3_kpalts[cmd - 0x40]; + key->modifiers = 0; + + key->utf8[0] = key->code.codepoint; + key->utf8[1] = 0; + } + else + { + key->type = ss3s[cmd - 0x40].type; + key->code.sym = ss3s[cmd - 0x40].sym; + key->modifiers = ss3s[cmd - 0x40].modifier_set; + } + } + + if (key->code.sym == TERMKEY_SYM_UNKNOWN) + { #ifdef DEBUG - fprintf(stderr, "CSI: Unknown SS3 %c (0x%02x)\n", (char)cmd, cmd); + fprintf (stderr, "CSI: Unknown SS3 %c (0x%02x)\n", (char) cmd, cmd); #endif - return TERMKEY_RES_NONE; - } - - *nbytep = introlen + 1; + return TERMKEY_RES_NONE; + } - return TERMKEY_RES_KEY; + *nbytep = introlen + 1; + return TERMKEY_RES_KEY; } -static TermKeyResult peekkey(TermKey *tk, void *info, TermKeyKey *key, int force, size_t *nbytep) +static termkey_result_t +peekkey (termkey_t *tk, void *info, + termkey_key_t *key, int force, size_t *nbytep) { - if(tk->buffcount == 0) - return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE; - - TermKeyCsi *csi = info; - - // Now we're sure at least 1 byte is valid - unsigned char b0 = CHARAT(0); - - if(b0 == 0x1b && tk->buffcount > 1 && CHARAT(1) == '[') { - return peekkey_csi(tk, csi, 2, key, force, nbytep); - } - else if(b0 == 0x1b && tk->buffcount > 1 && CHARAT(1) == 'O') { - return peekkey_ss3(tk, csi, 2, key, force, nbytep); - } - else if(b0 == 0x8f) { - return peekkey_ss3(tk, csi, 1, key, force, nbytep); - } - else if(b0 == 0x9b) { - return peekkey_csi(tk, csi, 1, key, force, nbytep); - } - else - return TERMKEY_RES_NONE; + if (tk->buffcount == 0) + return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE; + + termkey_csi_t *csi = info; + + // Now we're sure at least 1 byte is valid + unsigned char b0 = CHARAT (0); + + if (b0 == 0x1b && tk->buffcount > 1 && CHARAT (1) == '[') + return peekkey_csi (tk, csi, 2, key, force, nbytep); + if (b0 == 0x1b && tk->buffcount > 1 && CHARAT (1) == 'O') + return peekkey_ss3 (tk, csi, 2, key, force, nbytep); + if (b0 == 0x8f) + return peekkey_ss3 (tk, csi, 1, key, force, nbytep); + if (b0 == 0x9b) + return peekkey_csi (tk, csi, 1, key, force, nbytep); + else + return TERMKEY_RES_NONE; } -struct TermKeyDriver termkey_driver_csi = { - .name = "CSI", +termkey_driver_t termkey_driver_csi = +{ + .name = "CSI", - .new_driver = new_driver, - .free_driver = free_driver, + .new_driver = new_driver, + .free_driver = free_driver, - .peekkey = peekkey, + .peekkey = peekkey, }; diff --git a/driver-ti.c b/driver-ti.c index d827bdf..ab76c25 100644 --- a/driver-ti.c +++ b/driver-ti.c @@ -9,9 +9,6 @@ #else # include # include - -/* curses.h has just poluted our namespace. We want this back */ -# undef buttons #endif #include @@ -27,563 +24,607 @@ * vector to store an extent map after the database is loaded. */ -typedef enum { - TYPE_KEY, - TYPE_ARR, - TYPE_MOUSE, -} trie_nodetype; - -struct trie_node { - trie_nodetype type; -}; - -struct trie_node_key { - trie_nodetype type; - struct keyinfo key; -}; - -struct trie_node_arr { - trie_nodetype type; - unsigned char min, max; /* INCLUSIVE endpoints of the extent range */ - struct trie_node *arr[]; /* dynamic size at allocation time */ -}; - -typedef struct { - TermKey *tk; +typedef enum +{ + TYPE_KEY, + TYPE_ARRAY, + TYPE_MOUSE, +} +trie_nodetype_t; - struct trie_node *root; +typedef struct trie_node +{ + trie_nodetype_t type; +} +trie_node_t; - char *start_string; - char *stop_string; -} TermKeyTI; +typedef struct trie_node_key +{ + trie_nodetype_t type; + keyinfo_t key; +} +trie_node_key_t; -static int funcname2keysym(const char *funcname, TermKeyType *typep, TermKeySym *symp, int *modmask, int *modsetp); -static int insert_seq(TermKeyTI *ti, const char *seq, struct trie_node *node); +typedef struct trie_node_array +{ + trie_nodetype_t type; + unsigned char min, max; /* INCLUSIVE endpoints of the extent range */ + trie_node_t *arr[]; /* dynamic size at allocation time */ +} +trie_node_array_t; -static struct trie_node *new_node_key(TermKeyType type, TermKeySym sym, int modmask, int modset) +typedef struct { - struct trie_node_key *n = malloc(sizeof(*n)); - if(!n) - return NULL; + termkey_t *tk; + trie_node_t *root; - n->type = TYPE_KEY; + char *start_string; + char *stop_string; +} +termkey_ti_t; - n->key.type = type; - n->key.sym = sym; - n->key.modifier_mask = modmask; - n->key.modifier_set = modset; +static int funcname2keysym (const char *funcname, termkey_type_t *typep, + termkey_sym_t *symp, int *modmask, int *modsetp); +static int insert_seq (termkey_ti_t *ti, const char *seq, trie_node_t *node); - return (struct trie_node*)n; +static trie_node_t * +new_node_key (termkey_type_t type, termkey_sym_t sym, int modmask, int modset) +{ + trie_node_key_t *n = malloc (sizeof *n); + if (!n) + return NULL; + + n->type = TYPE_KEY; + n->key.type = type; + n->key.sym = sym; + n->key.modifier_mask = modmask; + n->key.modifier_set = modset; + return (trie_node_t *) n; } -static struct trie_node *new_node_arr(unsigned char min, unsigned char max) +static trie_node_t * +new_node_arr (unsigned char min, unsigned char max) { - struct trie_node_arr *n = malloc(sizeof(*n) + ((int)max-min+1) * sizeof(n->arr[0])); - if(!n) - return NULL; + trie_node_array_t *n = malloc (sizeof *n + + ((int) max - min + 1) * sizeof n->arr[0]); + if (!n) + return NULL; - n->type = TYPE_ARR; - n->min = min; n->max = max; + n->type = TYPE_ARRAY; + n->min = min; + n->max = max; - int i; - for(i = min; i <= max; i++) - n->arr[i-min] = NULL; + int i; + for (i = min; i <= max; i++) + n->arr[i - min] = NULL; - return (struct trie_node*)n; + return (trie_node_t *) n; } -static struct trie_node *lookup_next(struct trie_node *n, unsigned char b) +static trie_node_t * +lookup_next (trie_node_t *n, unsigned char b) { - switch(n->type) { - case TYPE_KEY: - case TYPE_MOUSE: - fprintf(stderr, "ABORT: lookup_next within a TYPE_KEY node\n"); - abort(); - case TYPE_ARR: - { - struct trie_node_arr *nar = (struct trie_node_arr*)n; - if(b < nar->min || b > nar->max) - return NULL; - return nar->arr[b - nar->min]; - } - } - - return NULL; // Never reached but keeps compiler happy + switch (n->type) + { + case TYPE_KEY: + case TYPE_MOUSE: + // FIXME + fprintf (stderr, "ABORT: lookup_next within a TYPE_KEY node\n"); + abort (); + case TYPE_ARRAY: + { + trie_node_array_t *nar = (trie_node_array_t *) n; + if (b < nar->min || b > nar->max) + return NULL; + return nar->arr[b - nar->min]; + } + } + + return NULL; // Never reached but keeps compiler happy } -static void free_trie(struct trie_node *n) +static void +free_trie (trie_node_t *n) { - switch(n->type) { - case TYPE_KEY: - case TYPE_MOUSE: - break; - case TYPE_ARR: - { - struct trie_node_arr *nar = (struct trie_node_arr*)n; - int i; - for(i = nar->min; i <= nar->max; i++) - if(nar->arr[i - nar->min]) - free_trie(nar->arr[i - nar->min]); - break; - } - } - - free(n); + switch (n->type) + { + case TYPE_KEY: + case TYPE_MOUSE: + break; + case TYPE_ARRAY: + { + trie_node_array_t *nar = (trie_node_array_t *) n; + int i; + for (i = nar->min; i <= nar->max; i++) + if (nar->arr[i - nar->min]) + free_trie (nar->arr[i - nar->min]); + } + } + free (n); } -static struct trie_node *compress_trie(struct trie_node *n) +static trie_node_t * +compress_trie (struct trie_node *n) { - if(!n) - return NULL; - - switch(n->type) { - case TYPE_KEY: - case TYPE_MOUSE: - return n; - case TYPE_ARR: - { - struct trie_node_arr *nar = (struct trie_node_arr*)n; - unsigned char min, max; - // Find the real bounds - for(min = 0; !nar->arr[min]; min++) - ; - for(max = 0xff; !nar->arr[max]; max--) - ; - - struct trie_node_arr *new = (struct trie_node_arr*)new_node_arr(min, max); - int i; - for(i = min; i <= max; i++) - new->arr[i - min] = compress_trie(nar->arr[i]); - - free(nar); - return (struct trie_node*)new; - } - } - - return n; + if (!n) + return NULL; + + switch (n->type) + { + case TYPE_KEY: + case TYPE_MOUSE: + return n; + case TYPE_ARRAY: + { + trie_node_array_t *nar = (trie_node_array_t *) n; + // Find the real bounds + unsigned char min, max; + for (min = 0; !nar->arr[min]; min++) + ; + for (max = 0xff; !nar->arr[max]; max--) + ; + + trie_node_array_t *new = (trie_node_array_t *) new_node_arr (min, max); + int i; + for (i = min; i <= max; i++) + new->arr[i - min] = compress_trie (nar->arr[i]); + + free (nar); + return (trie_node_t *) new; + } + } + return n; } -static int load_terminfo(TermKeyTI *ti, const char *term) +static int +load_terminfo (termkey_ti_t *ti, const char *term) { - int i; + int i; #ifdef HAVE_UNIBILIUM - unibi_term *unibi = unibi_from_term(term); - if(!unibi) - return 0; + unibi_term *unibi = unibi_from_term (term); + if (!unibi) + return 0; #else - int err; + int err; - /* Have to cast away the const. But it's OK - we know terminfo won't really - * modify term */ - if(setupterm((char*)term, 1, &err) != OK) - return 0; + /* Have to cast away the const. But it's OK - we know terminfo won't really + * modify term */ + if (setupterm ((char *) term, 1, &err) != OK) + return 0; #endif #ifdef HAVE_UNIBILIUM - for(i = unibi_string_begin_+1; i < unibi_string_end_; i++) + for (i = unibi_string_begin_ + 1; i < unibi_string_end_; i++) #else - for(i = 0; strfnames[i]; i++) + for (i = 0; strfnames[i]; i++) #endif - { - // Only care about the key_* constants + { + // Only care about the key_* constants #ifdef HAVE_UNIBILIUM - const char *name = unibi_name_str(i); + const char *name = unibi_name_str (i); #else - const char *name = strfnames[i]; + const char *name = strfnames[i]; #endif - if(strncmp(name, "key_", 4) != 0) - continue; + if (strncmp (name, "key_", 4) != 0) + continue; #ifdef HAVE_UNIBILIUM - const char *value = unibi_get_str(unibi, i); + const char *value = unibi_get_str (unibi, i); #else - const char *value = tigetstr(strnames[i]); + const char *value = tigetstr (strnames[i]); #endif - if(!value || value == (char*)-1) - continue; - - struct trie_node *node = NULL; - - if(strcmp(name + 4, "mouse") == 0) { - node = malloc(sizeof(*node)); - if(!node) - return 0; - - node->type = TYPE_MOUSE; - } - else { - TermKeyType type; - TermKeySym sym; - int mask = 0; - int set = 0; - - if(!funcname2keysym(name + 4, &type, &sym, &mask, &set)) - continue; - - if(sym == TERMKEY_SYM_NONE) - continue; - - node = new_node_key(type, sym, mask, set); - } - - if(node) - if(!insert_seq(ti, value, node)) { - free(node); - return 0; - } - } - - /* Take copies of these terminfo strings, in case we build multiple termkey - * instances for multiple different termtypes, and it's different by the - * time we want to use it - */ + if (!value || value == (char*) -1) + continue; + + struct trie_node *node = NULL; + if (strcmp (name + 4, "mouse") == 0) + { + node = malloc (sizeof *node); + if (!node) + return 0; + + node->type = TYPE_MOUSE; + } + else + { + termkey_type_t type; + termkey_sym_t sym; + int mask = 0; + int set = 0; + + if (!funcname2keysym (name + 4, &type, &sym, &mask, &set)) + continue; + + if (sym == TERMKEY_SYM_NONE) + continue; + + node = new_node_key (type, sym, mask, set); + } + + if (node && !insert_seq (ti, value, node)) + { + free(node); + return 0; + } + } + + /* Take copies of these terminfo strings, in case we build multiple termkey + * instances for multiple different termtypes, and it's different by the + * time we want to use it + */ #ifdef HAVE_UNIBILIUM - const char *keypad_xmit = unibi_get_str(unibi, unibi_pkey_xmit); + const char *keypad_xmit = unibi_get_str (unibi, unibi_pkey_xmit); #endif - if(keypad_xmit) - ti->start_string = strdup(keypad_xmit); - else - ti->start_string = NULL; + if (keypad_xmit) + ti->start_string = strdup (keypad_xmit); + else + ti->start_string = NULL; #ifdef HAVE_UNIBILIUM - const char *keypad_local = unibi_get_str(unibi, unibi_pkey_local); + const char *keypad_local = unibi_get_str (unibi, unibi_pkey_local); #endif - if(keypad_local) - ti->stop_string = strdup(keypad_local); - else - ti->stop_string = NULL; + if (keypad_local) + ti->stop_string = strdup (keypad_local); + else + ti->stop_string = NULL; #ifdef HAVE_UNIBILIUM - unibi_destroy(unibi); + unibi_destroy (unibi); #endif - return 1; + return 1; } -static void *new_driver(TermKey *tk, const char *term) +static void * +new_driver (termkey_t *tk, const char *term) { - TermKeyTI *ti = malloc(sizeof *ti); - if(!ti) - return NULL; - - ti->tk = tk; + termkey_ti_t *ti = malloc (sizeof *ti); + if (!ti) + return NULL; - ti->root = new_node_arr(0, 0xff); - if(!ti->root) - goto abort_free_ti; + ti->tk = tk; + ti->root = new_node_arr (0, 0xff); + if (!ti->root) + goto abort_free_ti; - if(!load_terminfo(ti, term)) - goto abort_free_trie; + if (!load_terminfo (ti, term)) + goto abort_free_trie; - ti->root = compress_trie(ti->root); - - return ti; + ti->root = compress_trie (ti->root); + return ti; abort_free_trie: - free_trie(ti->root); + free_trie(ti->root); abort_free_ti: - free(ti); + free(ti); - return NULL; + return NULL; } -static int start_driver(TermKey *tk, void *info) +static int +start_driver (termkey_t *tk, void *info) { - TermKeyTI *ti = info; - struct stat statbuf; - char *start_string = ti->start_string; - size_t len; - - if(tk->fd == -1 || !start_string) - return 1; - - /* The terminfo database will contain keys in application cursor key mode. - * We may need to enable that mode - */ - - /* There's no point trying to write() to a pipe */ - if(fstat(tk->fd, &statbuf) == -1) - return 0; - - if(S_ISFIFO(statbuf.st_mode)) - return 1; - - // Can't call putp or tputs because they suck and don't give us fd control - len = strlen(start_string); - while(len) { - size_t written = write(tk->fd, start_string, len); - if(written == -1) - return 0; - start_string += written; - len -= written; - } - return 1; + termkey_ti_t *ti = info; + struct stat statbuf; + char *start_string = ti->start_string; + size_t len; + + if (tk->fd == -1 || !start_string) + return 1; + + /* The terminfo database will contain keys in application cursor key mode. + * We may need to enable that mode + */ + + // FIXME: isatty() should suffice + /* There's no point trying to write() to a pipe */ + if (fstat (tk->fd, &statbuf) == -1) + return 0; + + if (S_ISFIFO (statbuf.st_mode)) + return 1; + + // Can't call putp or tputs because they suck and don't give us fd control + len = strlen (start_string); + while (len) + { + size_t written = write (tk->fd, start_string, len); + if (written == -1) + return 0; + start_string += written; + len -= written; + } + return 1; } -static int stop_driver(TermKey *tk, void *info) +// XXX: this is the same as above only with a different string +static int +stop_driver (termkey_t *tk, void *info) { - TermKeyTI *ti = info; - struct stat statbuf; - char *stop_string = ti->stop_string; - size_t len; - - if(tk->fd == -1 || !stop_string) - return 1; - - /* There's no point trying to write() to a pipe */ - if(fstat(tk->fd, &statbuf) == -1) - return 0; - - if(S_ISFIFO(statbuf.st_mode)) - return 1; - - /* The terminfo database will contain keys in application cursor key mode. - * We may need to enable that mode - */ - - // Can't call putp or tputs because they suck and don't give us fd control - len = strlen(stop_string); - while(len) { - size_t written = write(tk->fd, stop_string, len); - if(written == -1) - return 0; - stop_string += written; - len -= written; - } - return 1; + termkey_ti_t *ti = info; + struct stat statbuf; + char *stop_string = ti->stop_string; + size_t len; + + if (tk->fd == -1 || !stop_string) + return 1; + + /* There's no point trying to write() to a pipe */ + if (fstat (tk->fd, &statbuf) == -1) + return 0; + + if (S_ISFIFO (statbuf.st_mode)) + return 1; + + /* The terminfo database will contain keys in application cursor key mode. + * We may need to enable that mode + */ + + // Can't call putp or tputs because they suck and don't give us fd control + len = strlen (stop_string); + while (len) + { + size_t written = write (tk->fd, stop_string, len); + if (written == -1) + return 0; + stop_string += written; + len -= written; + } + return 1; } -static void free_driver(void *info) +static void +free_driver (void *info) { - TermKeyTI *ti = info; - - free_trie(ti->root); - - if(ti->start_string) - free(ti->start_string); - - if(ti->stop_string) - free(ti->stop_string); - - free(ti); + termkey_ti_t *ti = info; + free_trie (ti->root); + free (ti->start_string); + free (ti->stop_string); + free (ti); } #define CHARAT(i) (tk->buffer[tk->buffstart + (i)]) -static TermKeyResult peekkey(TermKey *tk, void *info, TermKeyKey *key, int force, size_t *nbytep) +static termkey_result_t +peekkey (termkey_t *tk, void *info, + termkey_key_t *key, int force, size_t *nbytep) { - TermKeyTI *ti = info; - - if(tk->buffcount == 0) - return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE; - - struct trie_node *p = ti->root; - - unsigned int pos = 0; - while(pos < tk->buffcount) { - p = lookup_next(p, CHARAT(pos)); - if(!p) - break; - - pos++; - - if(p->type == TYPE_KEY) { - struct trie_node_key *nk = (struct trie_node_key*)p; - key->type = nk->key.type; - key->code.sym = nk->key.sym; - key->modifiers = nk->key.modifier_set; - *nbytep = pos; - return TERMKEY_RES_KEY; - } - else if(p->type == TYPE_MOUSE) { - tk->buffstart += pos; - tk->buffcount -= pos; - - TermKeyResult mouse_result = (*tk->method.peekkey_mouse)(tk, key, nbytep); - - tk->buffstart -= pos; - tk->buffcount += pos; - - if(mouse_result == TERMKEY_RES_KEY) - *nbytep += pos; - - return mouse_result; - } - } - - // If p is not NULL then we hadn't walked off the end yet, so we have a - // partial match - if(p && !force) - return TERMKEY_RES_AGAIN; - - return TERMKEY_RES_NONE; + termkey_ti_t *ti = info; + + if (tk->buffcount == 0) + return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE; + + trie_node_t *p = ti->root; + unsigned int pos = 0; + while (pos < tk->buffcount) + { + p = lookup_next (p, CHARAT (pos)); + if (!p) + break; + + pos++; + + if (p->type == TYPE_KEY) + { + trie_node_key_t *nk = (trie_node_key_t *) p; + key->type = nk->key.type; + key->code.sym = nk->key.sym; + key->modifiers = nk->key.modifier_set; + *nbytep = pos; + return TERMKEY_RES_KEY; + } + else if (p->type == TYPE_MOUSE) + { + tk->buffstart += pos; + tk->buffcount -= pos; + + termkey_result_t mouse_result = + (*tk->method.peekkey_mouse) (tk, key, nbytep); + + tk->buffstart -= pos; + tk->buffcount += pos; + + if (mouse_result == TERMKEY_RES_KEY) + *nbytep += pos; + + return mouse_result; + } + } + + // If p is not NULL then we hadn't walked off the end yet, so we have a + // partial match + if (p && !force) + return TERMKEY_RES_AGAIN; + + return TERMKEY_RES_NONE; } -static struct { - const char *funcname; - TermKeyType type; - TermKeySym sym; - int mods; -} funcs[] = +static struct +{ + const char *funcname; + termkey_type_t type; + termkey_sym_t sym; + int mods; +} +funcs[] = { - /* THIS LIST MUST REMAIN SORTED! */ - { "backspace", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BACKSPACE, 0 }, - { "begin", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 0 }, - { "beg", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 0 }, - { "btab", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_TAB, TERMKEY_KEYMOD_SHIFT }, - { "cancel", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CANCEL, 0 }, - { "clear", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CLEAR, 0 }, - { "close", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CLOSE, 0 }, - { "command", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_COMMAND, 0 }, - { "copy", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_COPY, 0 }, - { "dc", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DELETE, 0 }, - { "down", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DOWN, 0 }, - { "end", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_END, 0 }, - { "enter", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_ENTER, 0 }, - { "exit", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_EXIT, 0 }, - { "find", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_FIND, 0 }, - { "help", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HELP, 0 }, - { "home", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HOME, 0 }, - { "ic", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_INSERT, 0 }, - { "left", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_LEFT, 0 }, - { "mark", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MARK, 0 }, - { "message", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MESSAGE, 0 }, - { "mouse", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_NONE, 0 }, - { "move", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MOVE, 0 }, - { "next", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 0 }, // Not quite, but it's the best we can do - { "npage", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 0 }, - { "open", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPEN, 0 }, - { "options", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPTIONS, 0 }, - { "ppage", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 0 }, - { "previous", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 0 }, // Not quite, but it's the best we can do - { "print", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PRINT, 0 }, - { "redo", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REDO, 0 }, - { "reference", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REFERENCE, 0 }, - { "refresh", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REFRESH, 0 }, - { "replace", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REPLACE, 0 }, - { "restart", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RESTART, 0 }, - { "resume", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RESUME, 0 }, - { "right", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RIGHT, 0 }, - { "save", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SAVE, 0 }, - { "select", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SELECT, 0 }, - { "suspend", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SUSPEND, 0 }, - { "undo", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UNDO, 0 }, - { "up", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UP, 0 }, - { NULL }, + /* THIS LIST MUST REMAIN SORTED! */ + { "backspace", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BACKSPACE, 0 }, + { "begin", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 0 }, + { "beg", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 0 }, + { "btab", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_TAB, TERMKEY_KEYMOD_SHIFT }, + { "cancel", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CANCEL, 0 }, + { "clear", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CLEAR, 0 }, + { "close", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CLOSE, 0 }, + { "command", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_COMMAND, 0 }, + { "copy", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_COPY, 0 }, + { "dc", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DELETE, 0 }, + { "down", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DOWN, 0 }, + { "end", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_END, 0 }, + { "enter", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_ENTER, 0 }, + { "exit", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_EXIT, 0 }, + { "find", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_FIND, 0 }, + { "help", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HELP, 0 }, + { "home", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HOME, 0 }, + { "ic", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_INSERT, 0 }, + { "left", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_LEFT, 0 }, + { "mark", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MARK, 0 }, + { "message", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MESSAGE, 0 }, + { "mouse", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_NONE, 0 }, + { "move", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MOVE, 0 }, + // Not quite, but it's the best we can do + { "next", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 0 }, + { "npage", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 0 }, + { "open", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPEN, 0 }, + { "options", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPTIONS, 0 }, + { "ppage", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 0 }, + // Not quite, but it's the best we can do + { "previous", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 0 }, + { "print", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PRINT, 0 }, + { "redo", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REDO, 0 }, + { "reference", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REFERENCE, 0 }, + { "refresh", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REFRESH, 0 }, + { "replace", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REPLACE, 0 }, + { "restart", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RESTART, 0 }, + { "resume", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RESUME, 0 }, + { "right", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RIGHT, 0 }, + { "save", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SAVE, 0 }, + { "select", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SELECT, 0 }, + { "suspend", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SUSPEND, 0 }, + { "undo", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UNDO, 0 }, + { "up", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UP, 0 }, + { NULL }, }; -static int funcname2keysym(const char *funcname, TermKeyType *typep, TermKeySym *symp, int *modmaskp, int *modsetp) +static int +funcname2keysym (const char *funcname, + termkey_type_t *typep, termkey_sym_t *symp, int *modmaskp, int *modsetp) { - // Binary search - - int start = 0; - int end = sizeof(funcs)/sizeof(funcs[0]); // is "one past" the end of the range - - while(1) { - int i = (start+end) / 2; - int cmp = strcmp(funcname, funcs[i].funcname); - - if(cmp == 0) { - *typep = funcs[i].type; - *symp = funcs[i].sym; - *modmaskp = funcs[i].mods; - *modsetp = funcs[i].mods; - return 1; - } - else if(end == start + 1) - // That was our last choice and it wasn't it - not found - break; - else if(cmp > 0) - start = i; - else - end = i; - } - - if(funcname[0] == 'f' && isdigit(funcname[1])) { - *typep = TERMKEY_TYPE_FUNCTION; - *symp = atoi(funcname + 1); - return 1; - } - - // Last-ditch attempt; maybe it's a shift key? - if(funcname[0] == 's' && funcname2keysym(funcname + 1, typep, symp, modmaskp, modsetp)) { - *modmaskp |= TERMKEY_KEYMOD_SHIFT; - *modsetp |= TERMKEY_KEYMOD_SHIFT; - return 1; - } + // Binary search + + int start = 0; + int end = sizeof funcs / sizeof funcs[0]; + // is "one past" the end of the range + + // XXX: bsearch()? + while (1) + { + int i = (start + end) / 2; + int cmp = strcmp (funcname, funcs[i].funcname); + + if (cmp == 0) + { + *typep = funcs[i].type; + *symp = funcs[i].sym; + *modmaskp = funcs[i].mods; + *modsetp = funcs[i].mods; + return 1; + } + else if (end == start + 1) + // That was our last choice and it wasn't it - not found + break; + else if (cmp > 0) + start = i; + else + end = i; + } + + if (funcname[0] == 'f' && isdigit (funcname[1])) + { + *typep = TERMKEY_TYPE_FUNCTION; + // FIXME + *symp = atoi (funcname + 1); + return 1; + } + + // Last-ditch attempt; maybe it's a shift key? + if (funcname[0] == 's' && funcname2keysym + (funcname + 1, typep, symp, modmaskp, modsetp)) + { + *modmaskp |= TERMKEY_KEYMOD_SHIFT; + *modsetp |= TERMKEY_KEYMOD_SHIFT; + return 1; + } #ifdef DEBUG - fprintf(stderr, "TODO: Need to convert funcname %s to a type/sym\n", funcname); + fprintf (stderr, "TODO: Need to convert funcname %s to a type/sym\n", funcname); #endif - return 0; + return 0; } -static int insert_seq(TermKeyTI *ti, const char *seq, struct trie_node *node) +static int +insert_seq (termkey_ti_t *ti, const char *seq, trie_node_t *node) { - int pos = 0; - struct trie_node *p = ti->root; - - // Unsigned because we'll be using it as an array subscript - unsigned char b; - - while((b = seq[pos])) { - struct trie_node *next = lookup_next(p, b); - if(!next) - break; - p = next; - pos++; - } - - while((b = seq[pos])) { - struct trie_node *next; - if(seq[pos+1]) - // Intermediate node - next = new_node_arr(0, 0xff); - else - // Final key node - next = node; - - if(!next) - return 0; - - switch(p->type) { - case TYPE_ARR: - { - struct trie_node_arr *nar = (struct trie_node_arr*)p; - if(b < nar->min || b > nar->max) { - fprintf(stderr, "ASSERT FAIL: Trie insert at 0x%02x is outside of extent bounds (0x%02x..0x%02x)\n", - b, nar->min, nar->max); - abort(); - } - nar->arr[b - nar->min] = next; - p = next; - break; - } - case TYPE_KEY: - case TYPE_MOUSE: - fprintf(stderr, "ASSERT FAIL: Tried to insert child node in TYPE_KEY\n"); - abort(); - } - - pos++; - } - - return 1; + int pos = 0; + trie_node_t *p = ti->root; + + // Unsigned because we'll be using it as an array subscript + unsigned char b; + + while ((b = seq[pos])) + { + trie_node_t *next = lookup_next (p, b); + if (!next) + break; + p = next; + pos++; + } + + while ((b = seq[pos])) + { + trie_node_t *next; + if (seq[pos+1]) + // Intermediate node + next = new_node_arr (0, 0xff); + else + // Final key node + next = node; + + if (!next) + return 0; + + switch (p->type) + { + case TYPE_ARRAY: + { + trie_node_array_t *nar = (trie_node_array_t *) p; + if (b < nar->min || b > nar->max) + { + // FIXME + fprintf (stderr, "ASSERT FAIL: Trie insert at 0x%02x is outside of extent bounds (0x%02x..0x%02x)\n", + b, nar->min, nar->max); + abort (); + } + nar->arr[b - nar->min] = next; + p = next; + break; + } + case TYPE_KEY: + case TYPE_MOUSE: + // FIXME + fprintf (stderr, "ASSERT FAIL: Tried to insert child node in TYPE_KEY\n"); + abort (); + } + + pos++; + } + return 1; } -struct TermKeyDriver termkey_driver_ti = { - .name = "terminfo", +termkey_driver_t termkey_driver_ti = +{ + .name = "terminfo", - .new_driver = new_driver, - .free_driver = free_driver, + .new_driver = new_driver, + .free_driver = free_driver, - .start_driver = start_driver, - .stop_driver = stop_driver, + .start_driver = start_driver, + .stop_driver = stop_driver, - .peekkey = peekkey, + .peekkey = peekkey, }; diff --git a/man/also b/man/also deleted file mode 100644 index 611ca45..0000000 --- a/man/also +++ /dev/null @@ -1,9 +0,0 @@ -termkey_destroy.3 = termkey_new.3 -termkey_new_abstract.3 = termkey_new.3 -termkey_get_flags.3 = termkey_set_flags.3 -termkey_get_canonflags.3 = termkey_set_canonflags.3 -termkey_get_buffer_size.3 = termkey_set_buffer_size.3 -termkey_get_waittime.3 = termkey_set_waittime.3 -termkey_getkey_force.3 = termkey_getkey.3 -termkey_stop.3 = termkey_start.3 -termkey_is_started.3 = termkey_start.3 diff --git a/man/termkey.7 b/man/termkey.7 deleted file mode 100644 index deae880..0000000 --- a/man/termkey.7 +++ /dev/null @@ -1,145 +0,0 @@ -.TH TERMKEY 7 -.SH NAME -termkey \- terminal keypress reading library -.SH DESCRIPTION -\fBtermkey\fP is a library that allows programs to read and interpret keypress and other events from a terminal. It understands encoding schemes used by terminals to encode keypresses, and -.SM UTF-8 , -allowing it to return events representing key events. -.PP -\fBtermkey\fP operates in a pseudo object-oriented fashion. It provides one function, \fBtermkey_new\fP(3), that returns a pointer to a newly-allocated structure. All other functions take this pointer as their first argument. A typical use of this library would consist of a call to \fBtermkey_new\fP() to construct a new instance to represent the \fIstdin\fP stream, then use the \fBtermkey_waitkey\fP(3) function to wait for and interpret key press events. The \fBtermkey_destroy\fP(3) function can be used to deallocate resources used by the instance if the program has finished using it. -.SS Reading Events -Each instance of a \fBtermkey\fP structure may be used in one of three ways by the program. It may be used synchronously, blocking to wait for keypresses from a filehandle. It may be used asynchronously, returning keypresses if they are available, while co-operating with a non-blocking program. Or it may be used abstractly, interpreting key press bytes fed to it directly by the containing program. -.PP -To obtain the next key event synchronously, a program may call \fBtermkey_waitkey\fP(3). This will either return an event from its internal buffer, or block until a key is available, returning it when it is ready. It behaves similarly to \fBgetc\fP(3), \fBfgetc\fP(3), or similar, except that it understands and returns entire key press events, rather than single bytes. -.PP -To work with an asynchronous program, two other functions are used. \fBtermkey_advisereadable\fP(3) informs a \fBtermkey\fP instance that more bytes of input may be available from its file handle, so it should call \fBread\fP(2) to obtain them. The program can then call \fBtermkey_getkey\fP(3) to extract key press events out of the internal buffer, in a way similar to \fBtermkey_waitkey\fP(). -.PP -Finally, bytes of input can be fed into the \fBtermkey\fP instance directly, by calling \fBtermkey_push_bytes\fP(3). This may be useful if the bytes have already been read from the terminal by the application, or even in situations that don't directly involve a terminal filehandle. Because of these situations, it is possible to construct a \fBtermkey\fP instance not associated with a file handle, by passing -1 as the file descriptor. -.PP -A \fBtermkey\fP instance contains a buffer of pending bytes that have been read but not yet consumed by \fBtermkey_getkey\fP(3). \fBtermkey_get_buffer_remaining\fP(3) returns the number of bytes of buffer space currently free in the instance. \fBtermkey_set_buffer_size\fP(3) and \fBtermkey_get_buffer_size\fP(3) can be used to control and return the total size of this buffer. -.SS Key Events -Key events are stored in structures. Each structure holds details of one key event. This structure is defined as follows. -.PP -.in +4n -.nf -typedef struct { - TermKeyType type; - union { - long codepoint; /* TERMKEY_TYPE_UNICODE */ - int number; /* TERMKEY_TYPE_FUNCTION */ - TermKeySym sym; /* TERMKEY_TYPE_KEYSYM */ - } code; - int modifiers; - char utf8[7]; -} TermKeyKey; -.fi -.in -.PP -The \fItype\fP field indicates the type of event, and determines which of the members of the \fIcode\fP union is valid. It will be one of the following constants: -.TP -.B TERMKEY_TYPE_UNICODE -a Unicode codepoint. This value indicates that \fIcode.codepoint\fP is valid, and will contain the codepoint number of the keypress. In Unicode mode (if the \fBTERMKEY_FLAG_UTF8\fP bit is set) this will be its Unicode character number. In raw byte mode, this will contain a single 8-bit byte. -.TP -.B TERMKEY_TYPE_FUNCTION -a numbered function key. This value indicates that \fIcode.number\fP is valid, and contains the number of the numbered function key. -.TP -.B TERMKEY_TYPE_KEYSYM -a symbolic key. This value indicates that \fIcode.sym\fP is valid, and contains the symbolic key value. -.TP -.B TERMKEY_TYPE_MOUSE -a mouse button press, release, or movement. The \fIcode\fP structure should be considered opaque; \fBtermkey_interpret_mouse\fP(3) may be used to interpret it. -.TP -.B TERMKEY_TYPE_POSITION -a cursor position report. The \fIcode\fP structure should be considered opaque; \fBtermkey_interpret_position\fP(3) may be used to interpret it. -.TP -.B TERMKEY_TYPE_MODEREPORT -an ANSI or DEC mode value report. The \fIcode\fP structure should be considered opaque; \fBtermkey_interpret_modereport\fP(3) may be used to interpret it. -.TP -.B TERMKEY_TYPE_UNKNOWN_CSI -an unrecognised CSI sequence. The \fIcode\fP structure should be considered opaque; \fBtermkey_interpret_csi\fP(3) may be used to interpret it. -.PP -The \fImodifiers\fP bitmask is composed of a bitwise-or of the constants \fBTERMKEY_KEYMOD_SHIFT\fP, \fBTERMKEY_KEYMOD_CTRL\fP and \fBTERMKEY_KEYMOD_ALT\fP. -.PP -The \fIutf8\fP field is only set on events whose \fItype\fP is \fBTERMKEY_TYPE_UNICODE\fP. It should not be read for other events. -.PP -Key events that represent special keys (\fItype\fP is \fBTERMKEY_TYPE_KEYSYM\fP) have with them as symbolic value that identifies the special key, in \fIcode.sym\fP. \fBtermkey_get_keyname\fP(3) may be used to turn this symbolic value into a string, and \fBtermkey_lookup_keyname\fP(3) may be used to turn string names into symbolic values. -.PP -A pair of functions are also provided to convert between key events and strings. \fBtermkey_strfkey\fP(3) converts a key event into a string, and \fBtermkey_strpkey\fP(3) parses a string turning it into a key event. -.PP -Key events may be compared for equallity or ordering by using \fBtermkey_keycmp\fP(3). -.SS Control Flags -Details of the behaviour of a \fBtermkey\fP instance are controlled by two bitmasks of flags. \fBtermkey_set_flags\fP(3) and \fBtermkey_get_flags\fP(3) set or return the flags used to control the general behaviour, and \fBtermkey_set_canonflags\fP(3) and \fBtermkey_get_canonflags\fP(3) set or return the flags that control the key value canonicalisation behaviour performed by \fBtermkey_canonicalise\fP(3). -.PP -The following control flags are recognised. -.TP -.B TERMKEY_FLAG_NOINTERPRET -Do not attempt to interpret \fIC0\fP codes into keysyms. Instead report them as plain \fICtrl-letter\fP events. -.TP -.B TERMKEY_FLAG_CONVERTKP -Convert xterm's alternative keypad symbols into the plain -.SM ASCII -codes they would represent. -.TP -.B TERMKEY_FLAG_RAW -Ignore locale settings; do not attempt to recombine -.SM UTF-8 -sequences. Instead report only raw values. -.TP -.B TERMKEY_FLAG_UTF8 -Ignore locale settings; force -.SM UTF-8 -recombining on. This flag overrides \fBTERMKEY_FLAG_RAW\fP. -.TP -.B TERMKEY_FLAG_NOTERMIOS -Even if the terminal file descriptor \fIfd\fP represents a -.SM TTY -device, do not call the \fBtcsetattr\fP(3) \fBtermios\fP function on it to set it to canonical input mode. -.TP -.B TERMKEY_FLAG_SPACESYMBOL -Report space as being a symbolic key rather than a Unicode codepoint. Setting or clearing this flag in fact sets or clears the \fBTERMKEY_CANON_SPACESYMBOL\fP canonicalisation flag. -.TP -.B TERMKEY_FLAG_CTRLC -Disable the \fBSIGINT\fP behaviour of \fICtrl-C\fP. If this flag is provided, then \fICtrl-C\fP will be available as a normal keypress, rather than sending the process group a \fBSIGINT\fP. This flag only takes effect without \fBTERMKEY_FLAG_NOTERMIOS\fP; with it, none of the signal keys are disabled anyway. -.TP -.B TERMKEY_FLAG_EINTR -Without this flag, IO operations are retried when interrupted by a signal (\fBEINTR\fP). With this flag the \fBTERMKEY_RES_ERROR\fP result is returned instead. -.PP -The following canonicalisation flags are recognised. -.TP -.B TERMKEY_CANON_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 \f(CWU+0020\fP Unicode codepoint. -.TP -.B TERMKEY_CANON_DELBS -If this flag is set then an -.SM ASCII -.SM DEL -character is represented by the \fBTERMKEY_SYM_BACKSPACE\fP symbol. If not, it is represented by \fBTERMKEY_SYM_DEL\fP. An -.SM ASCII -.SM BS -character is always represented by \fBTERMKEY_SYM_BACKSPACE\fP, regardless of this flag. -.SS Multi-byte Events -Special keys, mouse events, and -.SM UTF-8 -encoded Unicode text, are all represented by more than one byte. If the start of a multi-byte sequence is seen by \fBtermkey_waitkey\fP() it will wait a short time to see if the remainder of the sequence arrives. If the sequence remains unfinished after this timeout, it will be returned in its incomplete state. Partial escape sequences are returned as an Escape key (\fBTERMKEY_SYM_ESCAPE\fP) followed by the text contained in the sequence. Partial -.SM UTF-8 -sequences are returned as the Unicode replacement character, \f(CWU+FFFD\fP. -.PP -The amount of time that the \fBtermkey\fP instance will wait is set by \fBtermkey_set_waittime\fP(3), and is returned by \fBtermkey_get_waittime\fP(3). Initially it will be set to 50 miliseconds. -.SS Mouse Events -The \fBTERMKEY_TYPE_MOUSE\fP event type indicates a mouse event. The \fIcode\fP field of the event structure should be considered opaque, though \fImodifiers\fP will be valid. In order to obtain the details of the mouse event, call \fBtermkey_interpret_mouse\fP(3) passing the event structure and pointers to integers to store the result in. -.PP -\fBtermkey\fP recognises three mouse protocols: the original -.SM X10 -protocol (\f(CWCSI M\fP followed by three bytes), -.SM SGR -encoding (\f(CWCSI < ... M\fP, as requested by \f(CWCSI ? 1006 h\fP), and rxvt encoding (\f(CWCSI ... M\fP, as requested by \f(CWCSI ? 1015 h\fP). Which encoding is in use is inferred automatically by \fBtermkey\fP, and does not need to be specified explicitly. -.SS Position Events -The \fBTERMKEY_TYPE_POSITION\fP event type indicates a cursor position report. This is typically sent by a terminal in response to the Report Cursor Position command (\f(CWCSI ? 6 n\fP). The event bytes are opaque, but can be obtained by calling \fBtermkey_interpret_position\fP(3) passing the event structure and pointers to integers to store the result in. Note that only a DEC CPR sequence (\f(CWCSI ? R\fP) is recognised, and not the non-DEC prefixed \f(CWCSI R\fP because the latter could be interpreted as the \f(CWF3\fP function key instead. -.SS Mode Reports -The \fBTERMKEY_TYPE_MODEREPORT\fP event type indicates an ANSI or DEC mode report. This is typically sent by a terminal in response to the Request Mode command (\f(CWCSI $p\fP or \f(CWCSI ? $p\fP). The event bytes are opaque, but can be obtained by calling \fBtermkey_interpret_modereport\fP(3) passing the event structure and pointers to integers to store the result in. -.SS Unrecognised CSIs -The \fBTERMKEY_TYPE_UNKNOWN_CSI\fP event type indicates a CSI sequence that the \fBtermkey\fP does not recognise. It will have been extracted from the stream, but is available to the application to inspect by calling \fBtermkey_interpret_csi\fP(3). It is important that if the application wishes to inspect this sequence it is done immediately, before any other IO operations on the \fBtermkey\fP instance (specifically, before calling \fBtermkey_waitkey\fP() or \fBtermkey_getkey\fP() again), otherwise the buffer space consumed by the sequence will be overwritten. Other types of key event do not suffer this limitation as the \fBTermKeyKey\fP structure is sufficient to contain all the information required. -.SH "SEE ALSO" -.BR termkey_new (3), -.BR termkey_waitkey (3), -.BR termkey_getkey (3) diff --git a/man/termkey_advisereadable.3 b/man/termkey_advisereadable.3 deleted file mode 100644 index 2c02c41..0000000 --- a/man/termkey_advisereadable.3 +++ /dev/null @@ -1,33 +0,0 @@ -.TH TERMKEY_ADVISEREADABLE 3 -.SH NAME -termkey_advisereadable \- read more bytes from the underlying terminal -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "TermKeyResult termkey_advisereadable(TermKey *" tk ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_advisereadable\fP() informs the \fBtermkey\fP(7) instance that new input may be available on the underlying file descriptor and so it should call \fBread\fP(2) to obtain it. If at least one more byte was read it will return \fBTERMKEY_RES_AGAIN\fP to indicate it may be useful to call \fBtermkey_getkey\fP(3) again. If no more input was read then \fBTERMKEY_RES_NONE\fP is returned. If there was no buffer space remaining, then \fBTERMKEY_RES_ERROR\fP is returned with \fIerrno\fP set to \fBENOMEM\fP. If no filehandle is associated with this instance, \fBTERMKEY_RES_ERROR\fP is returned with \fIerrno\fP set to \fBEBADF\fP. -.PP -This function, along with \fBtermkey_getkey\fP(3) make it possible to use the termkey instance in an asynchronous program. To provide bytes without using a readable file handle, use \fBtermkey_push_bytes\fP(3). -.PP -For synchronous usage, \fBtermkey_waitkey\fP(3) performs the input blocking task. -.SH "RETURN VALUE" -\fBtermkey_advisereadable\fP() returns one of the following constants: -.TP -.B TERMKEY_RES_AGAIN -At least one byte was read. -.TP -.B TERMKEY_RES_NONE -No nore bytes were read. -.TP -.B TERMKEY_RES_ERROR -An IO error occured. \fIerrno\fP will be preserved. If the error is \fBEINTR\fP then this will only be returned if \fBTERMKEY_FLAG_EINTR\fP flag is not set; if it is then the IO operation will be retried instead. -.SH "SEE ALSO" -.BR termkey_getkey (3), -.BR termkey_waitkey (3), -.BR termkey_set_waittime (3), -.BR termkey (7) diff --git a/man/termkey_canonicalise.3 b/man/termkey_canonicalise.3 deleted file mode 100644 index 47fb21f..0000000 --- a/man/termkey_canonicalise.3 +++ /dev/null @@ -1,22 +0,0 @@ -.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 canonicalisation flags set on the given \fBtermkey\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 -See \fBtermkey\fP(7) for a list of canonicalisation flags. -.SH "RETURN VALUE" -\fBtermkey_canonicalise\fP() returns no value. -.SH "SEE ALSO" -.BR termkey_set_canonflags (3), -.BR termkey_waitkey (3), -.BR termkey_strpkey (3), -.BR termkey (7) diff --git a/man/termkey_get_buffer_remaining.3 b/man/termkey_get_buffer_remaining.3 deleted file mode 100644 index d207865..0000000 --- a/man/termkey_get_buffer_remaining.3 +++ /dev/null @@ -1,23 +0,0 @@ -.TH TERMKEY_GET_BUFFER_REMAINING 3 -.SH NAME -termkey_get_buffer_remaining \- returns the free buffer space -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "size_t termkey_get_buffer_remaining(TermKey *" tk "); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_get_buffer_remaining\fP() returns the number of bytes of buffer space currently free in the \fBtermkey\fP(7) instance. These bytes are free to use by \fBtermkey_push_bytes\fP(3), or may be filled by \fBtermkey_advisereadable\fP(3). -.PP -.SH "RETURN VALUE" -\fBtermkey_get_buffer_remaining\fP() returns a size in bytes. -.SH "SEE ALSO" -.BR termkey_push_bytes (3), -.BR termkey_advisereadable (3), -.BR termkey_set_buffer_size (3), -.BR termkey_get_buffer_size (3), -.BR termkey_getkey (3), -.BR termkey (7) diff --git a/man/termkey_get_fd.3 b/man/termkey_get_fd.3 deleted file mode 100644 index 86b60b6..0000000 --- a/man/termkey_get_fd.3 +++ /dev/null @@ -1,19 +0,0 @@ -.TH TERMKEY_GET_FD 3 -.SH NAME -termkey_get_fd \- obtain the file descriptor for the terminal -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "int termkey_get_fd(TermKey *" tk ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_get_fd\fP() returns the file descriptor that the \fBtermkey\fP(7) instance is using to read bytes from. -.SH "RETURN VALUE" -\fBtermkey_get_fd\fP() returns the current file descriptor, or -1 if no file descriptor is associated with this instance. -.SH "SEE ALSO" -.BR termkey_new (3), -.BR termkey_get_flags (3), -.BR termkey (7) diff --git a/man/termkey_get_keyname.3 b/man/termkey_get_keyname.3 deleted file mode 100644 index 14f1426..0000000 --- a/man/termkey_get_keyname.3 +++ /dev/null @@ -1,20 +0,0 @@ -.TH TERMKEY_GET_KEYNAME 3 -.SH NAME -termkey_get_keyname \- return a string name for a symbolic key -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "const char *termkey_get_keyname(TermKey *" tk ", TermKeySym " sym ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_get_keyname\fP() returns a human-readable string name for the symbolic key value given by \fIsym\fP. The returned string is owned by the \fBtermkey\fP(7) instance \fItk\fP so should not be modified or freed. The returned pointer is guaranteed to be valid until the instance is released using \fBtermkey_destroy\fP(3). This function is the inverse of \fBtermkey_keyname2sym\fP(3). -.SH "RETURN VALUE" -\fBtermkey_get_key\fP() returns a pointer to a string. -.SH "SEE ALSO" -.BR termkey_lookup_keyname (3), -.BR termkey_keyname2sym (3), -.BR termkey_strfkey (3), -.BR termkey (7) diff --git a/man/termkey_getkey.3.sh b/man/termkey_getkey.3.sh deleted file mode 100644 index 32d296d..0000000 --- a/man/termkey_getkey.3.sh +++ /dev/null @@ -1,56 +0,0 @@ -# vim:ft=nroff -cat < -.sp -.BI "TermKeyResult termkey_getkey(TermKey *" tk ", TermKeyKey *" key ); -.BI "TermKeyResult termkey_getkey_force(TermKey *" tk ", TermKeyKey *" key ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_getkey\fP() attempts to retrieve a single keypress event from the \fBtermkey\fP(7) instance buffer, and put it in the structure referred to by \fIkey\fP. It returns one of the following values: -.in -.TP -.B TERMKEY_RES_KEY -a complete keypress was removed from the buffer, and has been placed in the \fIkey\fP structure. -.TP -.B TERMKEY_RES_AGAIN -a partial keypress event was found in the buffer, but it does not yet contain all the bytes required. An indication of what \fBtermkey_getkey_force\fP() would return has been placed in the \fIkey\fP structure. -.TP -.B TERMKEY_RES_NONE -no bytes are waiting in the buffer. -.TP -.B TERMKEY_RES_EOF - no bytes are ready and the input stream is now closed. -.TP -.B TERMKEY_RES_ERROR -called with terminal IO stopped, due to \fBtermkey_stop\fP(3). In this case \fIerrno\fP will be set to \fBEINVAL\fP. -.PP -\fBtermkey_getkey_force\fP() is similar to \fBtermkey_getkey\fP() but will not return \fBTERMKEY_RES_AGAIN\fP if a partial match is found. Instead, it will force an interpretation of the bytes, even if this means interpreting the start of an Escape-prefixed multi-byte sequence as a literal \fIEscape\fP key followed by normal letters. -.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(). For providing input without a readable filehandle, use \fBtermkey_push_bytes\fP(3). -.PP -Before returning, this function canonicalises the \fIkey\fP structure according to the rules given for \fBtermkey_canonicalise\fP(3). -.SH "RETURN VALUE" -\fBtermkey_getkey\fP() returns an enumeration of one of \fBTERMKEY_RES_KEY\fP, \fBTEMRKEY_RES_AGAIN\fP, \fBTERMKEY_RES_NONE\fP, \fBTERMKEY_RES_EOF\fP or \fBTERMKEY_RES_ERROR\fP. \fBtermkey_getkey_force\fP() returns one of the above, except for \fBTERMKEY_RES_AGAIN\fP. -.SH EXAMPLE -The following example program prints details of every keypress until the user presses \fICtrl-C\fP. It demonstrates how to use the \fBtermkey\fP instance in a typical \fBpoll\fP(2)-driven asynchronous program, which may include mixed IO with other file handles. -.PP -.in +4n -.nf -EOF -sed "s/\\\\/\\\\\\\\/g" demo-async.c -cat < -.sp -.BI "TermKeyResult termkey_interpret_csi(TermKey *" tk ", const TermKeyKey *" key ", " -.BI " long *" args "[], size_t *" nargs ", unsigned long *" cmd ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_interpret_csi\fP() fills in variables in the passed pointers according to the unrecognised CSI sequence event found in \fIkey\fP. It should be called if \fBtermkey_getkey\fP(3) or similar have returned a key event with the type of \fBTERMKEY_TYPE_UNKNOWN_CSI\fP. Note that it is important to call this function as soon as possible after obtaining a \fBTERMKEY_TYPE_CSI\fP key event; specifically, before calling \fBtermkey_getkey\fP() or \fBtermkey_waitkey\fP() again, as a subsequent call will overwrite the buffer space currently containing this sequence. -.PP -The \fIargs\fP array will be filled with the numerical arguments of the CSI sequence. The number of elements available in this array should be given as the initial value of the value pointed to by \fInargs\fP, which will be adjusted to give the number of arguments actually found when the function returns. The \fIcmd\fP variable will contain the CSI command value. If a leading byte was found (such as '\f(CW?\fP') then it will be bitwise-ored with the command value, shifted up by 8 bits. If an intermediate byte was found (such as '\f(CW$\fP') then it will be bitwise-ored with the command value, shifted up by 16 bits. -.nf -.sp - *cmd = command | (initial << 8) | (intermediate << 16); -.fi -.SH "RETURN VALUE" -If passed a \fIkey\fP event of the type \fBTERMKEY_TYPE_UNKNOWN_CSI\fP, this function will return \fBTERMKEY_RES_KEY\fP and will affect the variables whose pointers were passed in, as described above. -.PP -For other event types it will return \fBTERMKEY_RES_NONE\fP, and its effects on any variables whose pointers were passed in, are undefined. -.SH "SEE ALSO" -.BR termkey_waitkey (3), -.BR termkey_getkey (3), -.BR termkey (7) diff --git a/man/termkey_interpret_modereport.3 b/man/termkey_interpret_modereport.3 deleted file mode 100644 index d778655..0000000 --- a/man/termkey_interpret_modereport.3 +++ /dev/null @@ -1,26 +0,0 @@ -.TH TERMKEY_INTERPRET_MODEREPORT 3 -.SH NAME -termkey_interpret_modereport \- interpret opaque mode report data -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "TermKeyResult termkey_interpret_modereport(TermKey *" tk ", const TermKeyKey *" key ", " -.BI " int *" initial ", int *" mode ", int *" value ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_interpret_modereport\fP() fills in variables in the passed pointers according to the mode report event found in \fIkey\fP. It should be called if \fBtermkey_getkey\fP(3) or similar have returned a key event with the type of \fBTERMKEY_TYPE_MODEREPORT\fP. -.PP -Any pointer may instead be given as \fBNULL\fP to not return that value. -.PP -The \fIinitial\fP variable will be filled with 0 for an ANSI mode report, or \f(CW'?'\fP for a DEC mode report. The \fImode\fP variable will be filled with the number of the mode, and \fIvalue\fP will be filled with the value from the report. -.SH "RETURN VALUE" -If passed a \fIkey\fP event of the type \fBTERMKEY_TYPE_MODEREPORT\fP, this function will return \fBTERMKEY_RES_KEY\fP and will affect the variables whose pointers were passed in, as described above. -.PP -For other event types it will return \fBTERMKEY_RES_NONE\fP, and its effects on any variables whose pointers were passed in, are undefined. -.SH "SEE ALSO" -.BR termkey_waitkey (3), -.BR termkey_getkey (3), -.BR termkey (7) diff --git a/man/termkey_interpret_mouse.3 b/man/termkey_interpret_mouse.3 deleted file mode 100644 index dbc0c74..0000000 --- a/man/termkey_interpret_mouse.3 +++ /dev/null @@ -1,41 +0,0 @@ -.TH TERMKEY_INTERPRET_MOUSE 3 -.SH NAME -termkey_interpret_mouse \- interpret opaque mouse event data -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "TermKeyResult termkey_interpret_mouse(TermKey *" tk ", const TermKeyKey *" key ", " -.BI " TermKeyMouseEvent *" ev ", int *" button ", int *" line ", int *" col ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_interpret_mouse\fP() fills in variables in the passed pointers according to the mouse event found in \fIkey\fP. It should be called if \fBtermkey_getkey\fP(3) or similar have returned a key event with the type of \fBTERMKEY_TYPE_MOUSE\fP. -.PP -Any pointer may instead be given as \fBNULL\fP to not return that value. -.PP -The \fIev\fP variable will take one of the following values: -.in -.TP -.B TERMKEY_MOUSE_UNKNOWN -an unknown mouse event. -.TP -.B TERMKEY_MOUSE_PRESS -a mouse button was pressed; \fIbutton\fP will contain its number. -.TP -.B TERMKEY_MOUSE_DRAG -the mouse was moved while holding a button; \fIbutton\fP will contain its number. -.TP -.B TERMKEY_MOUSE_RELEASE -a mouse button was released, or the mouse was moved while no button was pressed. If known, \fIbutton\fP will contain the number of the button released. Not all terminals can report this, so it may be 0 instead. -.PP -The \fIline\fP and \fIcol\fP variables will be filled in with the mouse position, indexed from 1. Note that due to the limited number of bytes in the \fBTermKeyKey\fP structure, the line and column numbers are limited to 2047 and 4095 respectively. -.SH "RETURN VALUE" -If passed a \fIkey\fP event of the type \fBTERMKEY_TYPE_MOUSE\fP, this function will return \fBTERMKEY_RES_KEY\fP and will affect the variables whose pointers were passed in, as described above. -.PP -For other event types it will return \fBTERMKEY_RES_NONE\fP, and its effects on any variables whose pointers were passed in, are undefined. -.SH "SEE ALSO" -.BR termkey_waitkey (3), -.BR termkey_getkey (3), -.BR termkey (7) diff --git a/man/termkey_interpret_position.3 b/man/termkey_interpret_position.3 deleted file mode 100644 index e4fb091..0000000 --- a/man/termkey_interpret_position.3 +++ /dev/null @@ -1,26 +0,0 @@ -.TH TERMKEY_INTERPRET_POSITION 3 -.SH NAME -termkey_interpret_position \- interpret opaque cursor position event data -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "TermKeyResult termkey_interpret_position(TermKey *" tk ", const TermKeyKey *" key ", " -.BI " int *" line ", int *" col ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_interpret_position\fP() fills in variables in the passed pointers according to the cursor position report event found in \fIkey\fP. It should be called if \fBtermkey_getkey\fP(3) or similar have returned a key event with the type of \fBTERMKEY_TYPE_POSITION\fP. -.PP -Any pointer may instead be given as \fBNULL\fP to not return that value. -.PP -The \fIline\fP and \fIcol\fP variables will be filled in with the cursor position, indexed from 1. Note that due to the limited number of bytes in the \fBTermKeyKey\fP structure, the line and column numbers are limited to 2047 and 4095 respectively. -.SH "RETURN VALUE" -If passed a \fIkey\fP event of the type \fBTERMKEY_TYPE_POSITION\fP, this function will return \fBTERMKEY_RES_KEY\fP and will affect the variables whose pointers were passed in, as described above. -.PP -For other event types it will return \fBTERMKEY_RES_NONE\fP, and its effects on any variables whose pointers were passed in, are undefined. -.SH "SEE ALSO" -.BR termkey_waitkey (3), -.BR termkey_getkey (3), -.BR termkey (7) diff --git a/man/termkey_keycmp.3 b/man/termkey_keycmp.3 deleted file mode 100644 index 9001815..0000000 --- a/man/termkey_keycmp.3 +++ /dev/null @@ -1,22 +0,0 @@ -.TH TERMKEY_KEYCMP 3 -.SH NAME -termkey_keycmp \- compare two key events -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "int termkey_keycmp(TermKey *" tk ", const TermKeyKey *" key1 ", -.BI " const TermKeyKey *" key2 ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_keycmp\fP() compares two key structures and applies a total ordering, returning a value that is negative, zero, or positive, to indicate if the given structures are increasing, identical, or decreasing. Before comparison, copies of both referenced structures are taken, and canonicalised according to the rules for \fBtermkey_canonicalise\fP(3). -.PP -Two structures of differing type are ordered \fBTERMKEY_TYPE_UNICODE\fP, \fBTERMKEY_TYPE_KEYSYM\fP, \fBTERMKEY_TYPE_FUNCTION\fP, \fBTERMKEY_TYPE_MOUSE\fP. Unicode structures are ordered by codepoint, keysym structures are ordered by keysym number, function structures are ordered by function key number, and mouse structures are ordered opaquely by an unspecified but consistent ordering. Within these values, keys different in modifier bits are ordered by the modifiers. -.SH "RETURN VALUE" -\fBtermkey_keycmp\fP() returns an integer greater than, equal to, or less than zero to indicate the relation between the two given key structures. -.SH "SEE ALSO" -.BR termkey_strpkey (3), -.BR termkey_canonicalise (3), -.BR termkey (7) diff --git a/man/termkey_keyname2sym.3 b/man/termkey_keyname2sym.3 deleted file mode 100644 index cd75140..0000000 --- a/man/termkey_keyname2sym.3 +++ /dev/null @@ -1,22 +0,0 @@ -.TH TERMKEY_KEYNAME2SYM 3 -.SH NAME -termkey_keyname2sym \- look up a symbolic key value for a string name -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "TermKeySym termkey_keyname2sym(TermKey *" tk ", const char *" keyname ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_keyname2sym\fP() looks up the symbolic key value represented by the given string name. This is a case-sensitive comparison. If the given name is not found, \fBTERMKEY_SYM_UNKNOWN\fP is returned instead. This function is the inverse of \fBtermkey_get_keyname\fP(3), and is a more specific form of \fBtermkey_lookup_keyname\fP(3) which only recognises names as complete strings. -.PP -Because the key names are stored in an array indexed by the symbol number, this function has to perform a linear search of the names. Use of this function should be restricted to converting key names into symbolic values during a program's initialisation, so that efficient comparisons can be done while it is running. -.SH "RETURN VALUE" -\fBtermkey_keyname2sym\fP() returns a symbolic key constant, or \fBTERMKEY_SYM_UNKNOWN\fP. -.SH "SEE ALSO" -.BR termkey_get_keyname (3), -.BR termkey_lookup_keyname (3), -.BR termkey_strpkey (3), -.BR termkey (7) diff --git a/man/termkey_lookup_keyname.3 b/man/termkey_lookup_keyname.3 deleted file mode 100644 index 4525a95..0000000 --- a/man/termkey_lookup_keyname.3 +++ /dev/null @@ -1,23 +0,0 @@ -.TH TERMKEY_LOOKUP_KEYNAME 3 -.SH NAME -termkey_lookup_keyname \- look up a symbolic key value for a string name -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "char *termkey_lookup_keyname(TermKey *" tk ", const char *" keyname ", -.BI " TermKeySym *" sym "); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_lookup_keyname\fP() looks up the symbolic key value represented by the given string name. This is a case-sensitive comparison. The symbolic value is written to the variable addressed by \fIsym\fP. This function is a more general form of \fBtermkey_keyname2sym\fP(3) because it can recognise a symbolic key name within a longer string, returning a pointer to the remainder of the input after the key name. -.PP -Because the key names are stored in an array indexed by the symbol number, this function has to perform a linear search of the names. Use of this function should be restricted to converting key names into symbolic values during a program's initialisation, so that efficient comparisons can be done while it is running. -.SH "RETURN VALUE" -\fBtermkey_lookup_keyname\fP() returns a pointer to the first character after a recognised name, or \fBNULL\fP if the string does not begin with the name of a recognised symbolic key. -.SH "SEE ALSO" -.BR termkey_get_keyname (3), -.BR termkey_keyname2sym (3), -.BR termkey_strpkey (3), -.BR termkey (7) diff --git a/man/termkey_new.3 b/man/termkey_new.3 deleted file mode 100644 index 02e6774..0000000 --- a/man/termkey_new.3 +++ /dev/null @@ -1,48 +0,0 @@ -.TH TERMKEY_NEW 3 -.SH NAME -termkey_new, termkey_destroy \- create or destroy new termkey instance -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "TERMKEY_CHECK_VERSION;" -.BI "TermKey *termkey_new(int " fd ", int " flags ); -.BI "TermKey *termkey_new_abstract(const char *" term ", int " flags ); -.BI "void termkey_destroy(TermKey *" tk ); -.fi -.sp -Link with \fI\-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_new\fP() creates a new \fBtermkey\fP(7) instance connected to the file handle opened by \fIfd\fP using the \fIflags\fP. The \fITermKey\fP structure should be considered opaque; its contents are not intended for use outside of the library. -.PP -\fBtermkey_new_abstract\fP() creates a new \fBtermkey\fP() instance with no file handle associated. As this is usually done for handling other sources of terminal byte input, it also takes a string indicating the termtype to use. -.PP -\fBtermkey_destroy\fP() destroys the given instance and releases any resources controlled by it. It will not close the underlying filehandle given as the \fIfd\fP argument to \fBtermkey_new\fP(). -.PP -The constructor attempts to detect if the current locale is -.SM UTF-8 -aware or not, and sets either the \fBTERMKEY_FLAG_UTF8\fP or \fBTERMKEY_FLAG_RAW\fP flag. One of these two bits will always be in effect. The current flags in effect can be obtained by \fBtermkey_get_flags\fP(3). -.PP -If a file handle is provided, the terminfo driver may send a string to initialise or set the state of the terminal before \fBtermkey_new\fP() returns. This will not be done if no file handle is provided, or if the file handle is a pipe (\fBS_ISFIFO\fP()). In this case it will be the caller's responsibility to ensure the terminal is in the correct mode. Once initialised, the terminal can be stopped by \fBtermkey_stop\fP(3), and started again by \fBtermkey_start\fP(3). -.SH VERSION CHECK MACRO -Before calling any functions in the \fBtermkey\fP library, an application should use the \fBTERMKEY_CHECK_VERSION\fP macro to check that the loaded version of the library is compatible with the version it was compiled against. This should be done early on, ideally just after entering its \fBmain\fP() function. -.SH "RETURN VALUE" -If successful, \fBtermkey_new\fP() returns a pointer to the new instance. On failure, \fBNULL\fP is returned with \fIerrno\fP set to indicate the failure. \fBtermkey_destroy\fP() returns no value. -.SH ERRORS -.TP -.B ENOENT -No driver was able to recognise the given terminal type. -.TP -.B ENOMEM -A call to \fBmalloc\fP(3) failed to allocate memory. -.PP -Additionally, \fBtermkey_new\fP() may fail if \fBfstat\fP(2) or \fBwrite\fP(2) fails on the given file handle. -.SH "SEE ALSO" -.BR termkey_waitkey (3), -.BR termkey_advisereadable (3), -.BR termkey_getkey (3), -.BR termkey_get_flags (3), -.BR termkey_get_fd (3), -.BR termkey_get_buffer_remaining (3), -.BR termkey_get_buffer_size (3), -.BR termkey (7) diff --git a/man/termkey_push_bytes.3 b/man/termkey_push_bytes.3 deleted file mode 100644 index 3761034..0000000 --- a/man/termkey_push_bytes.3 +++ /dev/null @@ -1,23 +0,0 @@ -.TH TERMKEY_PUSH_BYTES 3 -.SH NAME -termkey_push_bytes \- supply more bytes to the input buffer -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "size_t termkey_push_bytes(TermKey *" tk ", const char *" bytes ", size_t " len "); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_push_bytes\fP() allows more bytes of input to be supplied directly into the input buffer of the \fBtermkey\fP(7) instance. If there was no buffer space remaining then -1 is returned with \fIerrno\fP set to \fBENOMEM\fP. -.PP -This function, along with \fBtermkey_getkey\fP(3), makes it possible to use the \fBtermkey\fP instance with a source of bytes other than from reading a filehandle. -.PP -For synchronous usage, \fBtermkey_waitkey\fP(3) performs the input blocking task. For use against a regular stream filehandle that supports \fBread\fP(2), see \fBtermkey_advisereadable\fP(3). -.SH "RETURN VALUE" -\fBtermkey_push_bytes\fP() the number of bytes consumed from the input (which may be smaller than the length provided, if the buffer runs out of space) or -1 cast to \fBsize_t\fP if an error occurs, in which case \fIerrno\fP is set accordingly. -.SH "SEE ALSO" -.BR termkey_getkey (3), -.BR termkey_advisereadable (3), -.BR termkey (7) diff --git a/man/termkey_set_buffer_size.3 b/man/termkey_set_buffer_size.3 deleted file mode 100644 index b3023fb..0000000 --- a/man/termkey_set_buffer_size.3 +++ /dev/null @@ -1,22 +0,0 @@ -.TH TERMKEY_SET_BUFFER_SIZE 3 -.SH NAME -termkey_set_buffer_size, termkey_get_buffer_size \- control the buffer size -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "int termkey_set_buffer_size(TermKey *" tk ", size_t " size ); -.BI "size_t termkey_get_buffer_size(TermKey *" tk ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_set_buffer_size\fP() changes the size of the buffer space in the \fBtermkey\fP(7) instance to that given by \fIsize\fP. Any bytes pending in the buffer will be preserved when resizing, though they will be truncated if the new size is smaller than the total number of bytes in the buffer. -.PP -\fBtermkey_get_buffer_size\fP() returns the size of the buffer set by the last call to \fBtermkey_set_buffer_size\fP(), or the default initial size of 256 bytes. -.SH "RETURN VALUE" -\fBtermkey_set_buffer_size\fP() returns a true value, or zero if an error occurs. \fBtermkey_get_buffer_size\fP() returns the current buffer size in bytes. -.SH "SEE ALSO" -.BR termkey_new (3), -.BR termkey_get_buffer_remaining (3), -.BR termkey (7) diff --git a/man/termkey_set_canonflags.3 b/man/termkey_set_canonflags.3 deleted file mode 100644 index 027bd37..0000000 --- a/man/termkey_set_canonflags.3 +++ /dev/null @@ -1,21 +0,0 @@ -.TH TERMKEY_SET_CANONFLAGS 3 -.SH NAME -termkey_set_canonflags, termkey_get_canonflags \- control the canonicalisation flags -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "void termkey_set_canonflags(TermKey *" tk ", int " newflags ); -.BI "int termkey_get_canonflags(TermKey *" tk ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_set_canonflags\fP() changes the set of canonicalisation flags in the \fBtermkey\fP(7) instance to those given by \fInewflags\fP. For detail on the available flags and their meaning, see the \fBtermkey\fP manpage. -.PP -\fBtermkey_get_canonflags\fP() returns the value set by the last call to \fBtermkey_set_canonflags\fP(). -.SH "RETURN VALUE" -\fBtermkey_set_canonflags\fP() returns no value. \fBtermkey_get_canonflags\fP() returns the current canonicalisation flags. -.SH "SEE ALSO" -.BR termkey_canonicalise (3), -.BR termkey (7) diff --git a/man/termkey_set_flags.3 b/man/termkey_set_flags.3 deleted file mode 100644 index 10bdcac..0000000 --- a/man/termkey_set_flags.3 +++ /dev/null @@ -1,21 +0,0 @@ -.TH TERMKEY_SET_FLAGS 3 -.SH NAME -termkey_set_flags, termkey_get_flags \- control the operational flags -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "void termkey_set_flags(TermKey *" tk ", int " newflags ); -.BI "int termkey_get_flags(TermKey *" tk ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_set_flags\fP() changes the set of operation flags in the \fBtermkey\fP(7) instance to those given by \fInewflags\fP. -.PP -\fBtermkey_get_flags\fP() returns the value set by the last call to \fBtermkey_set_flags\fP(), or the value given to the constructor. -.SH "RETURN VALUE" -\fBtermkey_set_flags\fP() returns no value. \fBtermkey_get_flags\fP() returns the current operational flags. -.SH "SEE ALSO" -.BR termkey_new (3), -.BR termkey (7) diff --git a/man/termkey_set_waittime.3 b/man/termkey_set_waittime.3 deleted file mode 100644 index 972c03f..0000000 --- a/man/termkey_set_waittime.3 +++ /dev/null @@ -1,22 +0,0 @@ -.TH TERMKEY_SET_WAITTIME 3 -.SH NAME -termkey_set_waittime, termkey_get_waittime \- control the wait time for multibyte sequences -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "void termkey_set_waittime(TermKey *" tk ", int " msec ); -.BI "int termkey_get_waittime(TermKey *" tk ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_set_waittime\fP() sets the number of miliseconds that \fBtermkey_waitkey\fP(3) will wait for the remaining bytes of a multibyte sequence if it detects the start of a partially-complete one. -.PP -\fBtermkey_get_waittime\fP() returns the value set by the last call to \fBtermkey_set_waittime\fP(), or the default value if a different has not been set. -.SH "RETURN VALUE" -\fBtermkey_set_waittime\fP() returns no value. \fBtermkey_get_waittime\fP() returns the current wait time in miliseconds. -.SH "SEE ALSO" -.BR termkey_getkey (3), -.BR termkey_waitkey (3), -.BR termkey (7) diff --git a/man/termkey_start.3 b/man/termkey_start.3 deleted file mode 100644 index 1de0edf..0000000 --- a/man/termkey_start.3 +++ /dev/null @@ -1,25 +0,0 @@ -.TH TERMKEY_START 3 -.SH NAME -termkey_start, termkey_stop, termkey_is_started \- enable or disable terminal operations -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "int termkey_start(TermKey *" tk ); -.BI "int termkey_stop(TermKey *" tk ); -.sp -.BI "int termkey_is_started(TermKey *" tk ); -.fi -.sp -Link with \fI\-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_start\fP() enables the terminal IO operations of the given \fBtermkey\fP(7) instance, including sending a terminal control sequence and setting the \fBtermios\fP(3) modes required. -.PP -\fBtermkey_stop\fP() disables terminal IO operations, by reversing the steps taken by \fBtermkey_start\fP(). A newly-constructed \fBtermkey\fP instance will have terminal IO enabled already. -.PP -\fBtermkey_is_started\fP() enquires whether terminal IO is currently enabled. -.SH "RETURN VALUE" -If successful, \fBtermkey_start\fP() and \fBtermkey_stop\fP() return a true value. On failure, zero is returned with \fIerrno\fP set to indicate the failure. \fBtermkey_is_started\fP() returns true or false to indicate whether terminal IO is currently enabled. -.SH "SEE ALSO" -.BR termkey_new (3), -.BR termkey (7) diff --git a/man/termkey_strfkey.3 b/man/termkey_strfkey.3 deleted file mode 100644 index 68b301e..0000000 --- a/man/termkey_strfkey.3 +++ /dev/null @@ -1,59 +0,0 @@ -.TH TERMKEY_STRFKEY 3 -.SH NAME -termkey_strfkey \- format a string representing a key event -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "size_t termkey_strfkey(TermKey *" tk ", char *" buffer ", size_t " len ", -.BI " TermKeyKey *" key ", TermKeyFormat " format ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_strfkey\fP() formats a string buffer to contain a human-readable representation of a key event. It fills the \fIbuffer\fP in a way analogous to the \fBsnprintf\fP(3) or \fBstrftime\fP(3) standard library functions. This function used to be called \fBtermkey_snprint_key\fP() but was renamed after version 0.6. -.PP -The \fIformat\fP argument specifies the format of the output, as a bitmask of the following constants: -.TP -.B TERMKEY_FORMAT_LONGMOD -Print full modifier names e.g. "\f(CWShift-\fP" instead of abbreviating to "\f(CWS-\fP". -.TP -.B TERMKEY_FORMAT_CARETCTRL -If the only modifier is \fBTERMKEY_MOD_CTRL\fP on a plain letter, render it as "\f(CW^X\fP" rather than "\f(CWCtrl-X\fP". -.TP -.B TERMKEY_FORMAT_ALTISMETA -Use the name "\f(CWMeta\fP" or the letter "\f(CWM\fP" instead of "\f(CWAlt\fP" or "\f(CWA\fP". -.TP -.B TERMKEY_FORMAT_WRAPBRACKET -If the key event is a special key instead of unmodified Unicode, wrap it in "\f(CW\fP". -.TP -.B TERMKEY_FORMAT_SPACEMOD -Use spaces instead of hyphens to separate the modifier name(s) from the base key name. -.TP -.B TERMKEY_FORMAT_LOWERMOD -Use lowercase for the modifier name. -.TP -.B TERMKEY_FORMAT_LOWERSPACE -Use lowercase with spaces in for the key name instead of camelCase (for example "\f(CWpage down\fP" instead of "\f(CWPageDown\fP"). -.TP -.B TERMKEY_FORMAT_MOUSE_POS -If the event is a mouse event, include the position rendered as "\f(CW@ (col,line)\fP". -.PP -The following shortcuts are provided for common combinations of format bits: -.TP -.B TERMKEY_FORMAT_VIM -Shortcut to set \fBALTISMETA\fP and \fBWRAPBRACKET\fP, to give an output close to the format the \fIvim\fP editor uses. -.TP -.B TERMKEY_FORMAT_URWID -Shortcut to set \fBALTISMETA\fP, \fBLONGMOD\fP, \fBLOWERMOD\fP, \fBSPACEMOD\fP and \fBLOWERSPACE\fP, to give an output close to the format the \fIurwid\fP python library uses. -.PP -When formatting a \fBTERMKEY_TYPE_UNICODE\fP key structure, this function uses the \fIutf8\fP member. If this member contains an empty string (i.e. its first character is 0) then this member will be prefilled by the function from the \fIcode.number\fP member. This can be convenient when the key structure is being constructed programatically by user code. -.SH "RETURN VALUE" -\fBtermkey_strfkey\fP() returns the number of characters written to \fIbuffer\fP. -.SH "SEE ALSO" -.BR termkey_new (3), -.BR termkey_getkey (3), -.BR termkey_waitkey (3), -.BR termkey_get_keyname (3), -.BR termkey_strpkey (3), -.BR termkey (7) diff --git a/man/termkey_strpkey.3 b/man/termkey_strpkey.3 deleted file mode 100644 index fd90e0e..0000000 --- a/man/termkey_strpkey.3 +++ /dev/null @@ -1,45 +0,0 @@ -.TH TERMKEY_STRPKEY 3 -.SH NAME -termkey_strpkey \- parse a string representing a key event -.SH SYNOPSIS -.nf -.B #include -.sp -.BI "char *termkey_strpkey(TermKey *" tk ", const char *" str ", -.BI " TermKeyKey *" key ", TermKeyFormat " format ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_strpkey\fP(3) parses a string buffer containing a human-readable representation of a key event. It fills the \fIkey\fP structure from the results of this parsing, similar to the \fBstrptime\fP(3) standard library function. -.PP -The \fIformat\fP argument specifies the format expected in the string, as a bitmask of the following constants: -.TP -.B TERMKEY_FORMAT_LONGMOD -Expect full modifier names e.g. "\f(CWShift-\fP" instead of abbreviating to "\f(CWS-\fP". -.TP -.B TERMKEY_FORMAT_CARETCTRL -If the only modifier is \fBTERMKEY_MOD_CTRL\fP on a plain letter, accept it as "\f(CW^X\fP" rather than "\f(CWCtrl-X\fP". -.TP -.B TERMKEY_FORMAT_ALTISMETA -Expect the name "\f(CWMeta\fP" or the letter "\f(CWM\fP" instead of "\f(CWAlt\fP" or "\f(CWA\fP". -.TP -.B TERMKEY_FORMAT_SPACEMOD -Expect spaces instead of hyphens to separate the modifer name(s) from the base key name. -.TP -.B TERMKEY_FORMAT_LOWERMOD -Expect lowercase for the modifier name. -.TP -.B TERMKEY_FORMAT_LOWERSPACE -Expect lowercase with spaces in for the key name instead of camelCase (for example "\f(CWpage down\fP" instead of "\f(CWPageDown\fP"). -.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. -.SH "SEE ALSO" -.BR termkey_new (3), -.BR termkey_strfkey (3), -.BR termkey_keycmp (3), -.BR termkey (7) diff --git a/man/termkey_waitkey.3.sh b/man/termkey_waitkey.3.sh deleted file mode 100644 index 7f11228..0000000 --- a/man/termkey_waitkey.3.sh +++ /dev/null @@ -1,45 +0,0 @@ -# vim:ft=nroff -cat < -.sp -.BI "TermKeyResult termkey_waitkey(TermKey *" tk ", TermKeyKey *" key ); -.fi -.sp -Link with \fI-ltermkey\fP. -.SH DESCRIPTION -\fBtermkey_waitkey\fP() attempts to retrieve a single keypress event from the \fBtermkey\fP(7) instance 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. If no filehandle is associated with this instance, \fBTERMKEY_RES_ERROR\fP is returned with \fIerrno\fP set to \fBEBADF\fP. -.PP -Before returning, this function canonicalises the \fIkey\fP structure according to the rules given for \fBtermkey_canonicalise\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 \fBtermkey\fP, \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). -.SH "RETURN VALUE" -\fBtermkey_waitkey\fP() returns one of the following constants: -.TP -.B TERMKEY_RES_KEY -A key event as been provided. -.TP -.B TERMKEY_RES_EOF -No key events are ready and the terminal has been closed, so no more will arrive. -.TP -.B TERMKEY_RES_ERROR -An IO error occured. \fIerrno\fP will be preserved. If the error is \fBEINTR\fP then this will only be returned if \fBTERMKEY_FLAG_EINTR\fP flag is not set; if it is then the IO operation will be retried instead. If this is called with terminal IO stopped, due to \fBtermkey_stop\fP(3) then \fIerrno\fP will be set to \fBEINVAL\fP. -.SH EXAMPLE -The following example program prints details of every keypress until the user presses \fICtrl-C\fP. -.PP -.in +4n -.nf -EOF -sed "s/\\\\/\\\\\\\\/g" demo.c -cat < #include -struct TermKeyDriver +typedef struct termkey_driver termkey_driver_t; +struct termkey_driver { - const char *name; - void *(*new_driver)(TermKey *tk, const char *term); - void (*free_driver)(void *info); - int (*start_driver)(TermKey *tk, void *info); - int (*stop_driver)(TermKey *tk, void *info); - TermKeyResult (*peekkey)(TermKey *tk, void *info, TermKeyKey *key, int force, size_t *nbytes); + const char *name; + void *(*new_driver) (termkey_t *tk, const char *term); + void (*free_driver) (void *info); + int (*start_driver) (termkey_t *tk, void *info); + int (*stop_driver) (termkey_t *tk, void *info); + termkey_result_t (*peekkey) (termkey_t *tk, + void *info, termkey_key_t *key, int force, size_t *nbytes); }; -struct keyinfo { - TermKeyType type; - TermKeySym sym; - int modifier_mask; - int modifier_set; +typedef struct keyinfo keyinfo_t; +struct keyinfo +{ + termkey_type_t type; + termkey_sym_t sym; + int modifier_mask; + int modifier_set; }; -struct TermKeyDriverNode; -struct TermKeyDriverNode { - struct TermKeyDriver *driver; - void *info; - struct TermKeyDriverNode *next; +typedef struct termkey_driver_node termkey_driver_node_t; +struct termkey_driver_node +{ + termkey_driver_t *driver; + void *info; + termkey_driver_node_t *next; }; -struct TermKey { - int fd; - int flags; - int canonflags; - unsigned char *buffer; - size_t buffstart; // First offset in buffer - size_t buffcount; // NUMBER of entires valid in buffer - size_t buffsize; // Total malloc'ed size - size_t hightide; /* Position beyond buffstart at which peekkey() should next start - * normally 0, but see also termkey_interpret_csi */ - - struct termios restore_termios; - char restore_termios_valid; - - int waittime; // msec - - char is_closed; - char is_started; - - int nkeynames; - const char **keynames; - - // There are 32 C0 codes - struct keyinfo c0[32]; - - struct TermKeyDriverNode *drivers; - - // Now some "protected" methods for the driver to call but which we don't - // want exported as real symbols in the library - struct { - void (*emit_codepoint)(TermKey *tk, long codepoint, TermKeyKey *key); - TermKeyResult (*peekkey_simple)(TermKey *tk, TermKeyKey *key, int force, size_t *nbytes); - TermKeyResult (*peekkey_mouse)(TermKey *tk, TermKeyKey *key, size_t *nbytes); - } method; +struct termkey +{ + int fd; + int flags; + int canonflags; + unsigned char *buffer; + size_t buffstart; // First offset in buffer + size_t buffcount; // NUMBER of entires valid in buffer + size_t buffsize; // Total malloc'ed size + + // Position beyond buffstart at which peekkey() should next start + // normally 0, but see also termkey_interpret_csi(). + size_t hightide; + + struct termios restore_termios; + char restore_termios_valid; + + int waittime; // msec + + char is_closed; + char is_started; + + int nkeynames; + const char **keynames; + + // There are 32 C0 codes + keyinfo_t c0[32]; + + termkey_driver_node_t *drivers; + + // Now some "protected" methods for the driver to call but which we don't + // want exported as real symbols in the library + struct + { + void (*emit_codepoint) (termkey_t *tk, + long codepoint, termkey_key_t *key); + termkey_result_t (*peekkey_simple) (termkey_t *tk, + termkey_key_t *key, int force, size_t *nbytes); + termkey_result_t (*peekkey_mouse) (termkey_t *tk, + termkey_key_t *key, size_t *nbytes); + } + method; }; -static inline void termkey_key_get_linecol(const TermKeyKey *key, int *line, int *col) +static inline void +termkey_key_get_linecol (const termkey_key_t *key, int *line, int *col) { - if(col) - *col = (unsigned char)key->code.mouse[1] | ((unsigned char)key->code.mouse[3] & 0x0f) << 8; + if (col) + *col = (unsigned char) key->code.mouse[1] + | ((unsigned char) key->code.mouse[3] & 0x0f) << 8; - if(line) - *line = (unsigned char)key->code.mouse[2] | ((unsigned char)key->code.mouse[3] & 0x70) << 4; + if (line) + *line = (unsigned char) key->code.mouse[2] + | ((unsigned char) key->code.mouse[3] & 0x70) << 4; } -static inline void termkey_key_set_linecol(TermKeyKey *key, int line, int col) +static inline void +termkey_key_set_linecol (termkey_key_t *key, int line, int col) { - if(line > 0xfff) - line = 0xfff; + if (line > 0xfff) + line = 0xfff; - if(col > 0x7ff) - col = 0x7ff; + if (col > 0x7ff) + col = 0x7ff; - key->code.mouse[1] = (line & 0x0ff); - key->code.mouse[2] = (col & 0x0ff); - key->code.mouse[3] = (line & 0xf00) >> 8 | (col & 0x300) >> 4; + key->code.mouse[1] = (line & 0x0ff); + key->code.mouse[2] = (col & 0x0ff); + key->code.mouse[3] = (line & 0xf00) >> 8 | (col & 0x300) >> 4; } -extern struct TermKeyDriver termkey_driver_csi; -extern struct TermKeyDriver termkey_driver_ti; +extern termkey_driver_t termkey_driver_csi; +extern termkey_driver_t termkey_driver_ti; + +#endif // ! TERMKEY_INTERNAL_H -#endif diff --git a/termkey.c b/termkey.c index db084cc..55ab6d9 100644 --- a/termkey.c +++ b/termkey.c @@ -10,105 +10,113 @@ #include -#define strcaseeq(a,b) (strcasecmp(a,b) == 0) - -void termkey_check_version(int major, int minor) +void +termkey_check_version (int major, int minor) { - if(major != TERMKEY_VERSION_MAJOR) { - fprintf(stderr, "libtermkey major version mismatch; %d (wants) != %d (library)\n", - major, TERMKEY_VERSION_MAJOR); - exit(1); - } - - if(minor > TERMKEY_VERSION_MINOR) { - fprintf(stderr, "libtermkey minor version mismatch; %d (wants) > %d (library)\n", - minor, TERMKEY_VERSION_MINOR); - exit(1); - } - - // Happy + if (major != TERMKEY_VERSION_MAJOR) + { + fprintf (stderr, "libtermkey major version mismatch; %d (wants) != %d (library)\n", + major, TERMKEY_VERSION_MAJOR); + exit (1); + } + + if (minor > TERMKEY_VERSION_MINOR) + { + fprintf (stderr, "libtermkey minor version mismatch; %d (wants) > %d (library)\n", + minor, TERMKEY_VERSION_MINOR); + exit (1); + } + + // Happy } -static struct TermKeyDriver *drivers[] = { - &termkey_driver_ti, - &termkey_driver_csi, - NULL, +static termkey_driver_t *drivers[] = +{ + &termkey_driver_ti, + &termkey_driver_csi, + NULL, }; // Forwards for the "protected" methods -// static void eat_bytes(TermKey *tk, size_t count); -static void emit_codepoint(TermKey *tk, long codepoint, TermKeyKey *key); -static TermKeyResult peekkey_simple(TermKey *tk, TermKeyKey *key, int force, size_t *nbytes); -static TermKeyResult peekkey_mouse(TermKey *tk, TermKeyKey *key, size_t *nbytes); - -static TermKeySym register_c0(TermKey *tk, TermKeySym sym, unsigned char ctrl, const char *name); -static TermKeySym register_c0_full(TermKey *tk, TermKeySym sym, int modifier_set, int modifier_mask, unsigned char ctrl, const char *name); - -static struct { - TermKeySym sym; - const char *name; -} keynames[] = { - { TERMKEY_SYM_NONE, "NONE" }, - { TERMKEY_SYM_BACKSPACE, "Backspace" }, - { TERMKEY_SYM_TAB, "Tab" }, - { TERMKEY_SYM_ENTER, "Enter" }, - { TERMKEY_SYM_ESCAPE, "Escape" }, - { TERMKEY_SYM_SPACE, "Space" }, - { TERMKEY_SYM_DEL, "DEL" }, - { TERMKEY_SYM_UP, "Up" }, - { TERMKEY_SYM_DOWN, "Down" }, - { TERMKEY_SYM_LEFT, "Left" }, - { TERMKEY_SYM_RIGHT, "Right" }, - { TERMKEY_SYM_BEGIN, "Begin" }, - { TERMKEY_SYM_FIND, "Find" }, - { TERMKEY_SYM_INSERT, "Insert" }, - { TERMKEY_SYM_DELETE, "Delete" }, - { TERMKEY_SYM_SELECT, "Select" }, - { TERMKEY_SYM_PAGEUP, "PageUp" }, - { TERMKEY_SYM_PAGEDOWN, "PageDown" }, - { TERMKEY_SYM_HOME, "Home" }, - { TERMKEY_SYM_END, "End" }, - { TERMKEY_SYM_CANCEL, "Cancel" }, - { TERMKEY_SYM_CLEAR, "Clear" }, - { TERMKEY_SYM_CLOSE, "Close" }, - { TERMKEY_SYM_COMMAND, "Command" }, - { TERMKEY_SYM_COPY, "Copy" }, - { TERMKEY_SYM_EXIT, "Exit" }, - { TERMKEY_SYM_HELP, "Help" }, - { TERMKEY_SYM_MARK, "Mark" }, - { TERMKEY_SYM_MESSAGE, "Message" }, - { TERMKEY_SYM_MOVE, "Move" }, - { TERMKEY_SYM_OPEN, "Open" }, - { TERMKEY_SYM_OPTIONS, "Options" }, - { TERMKEY_SYM_PRINT, "Print" }, - { TERMKEY_SYM_REDO, "Redo" }, - { TERMKEY_SYM_REFERENCE, "Reference" }, - { TERMKEY_SYM_REFRESH, "Refresh" }, - { TERMKEY_SYM_REPLACE, "Replace" }, - { TERMKEY_SYM_RESTART, "Restart" }, - { TERMKEY_SYM_RESUME, "Resume" }, - { TERMKEY_SYM_SAVE, "Save" }, - { TERMKEY_SYM_SUSPEND, "Suspend" }, - { TERMKEY_SYM_UNDO, "Undo" }, - { TERMKEY_SYM_KP0, "KP0" }, - { TERMKEY_SYM_KP1, "KP1" }, - { TERMKEY_SYM_KP2, "KP2" }, - { TERMKEY_SYM_KP3, "KP3" }, - { TERMKEY_SYM_KP4, "KP4" }, - { TERMKEY_SYM_KP5, "KP5" }, - { TERMKEY_SYM_KP6, "KP6" }, - { TERMKEY_SYM_KP7, "KP7" }, - { TERMKEY_SYM_KP8, "KP8" }, - { TERMKEY_SYM_KP9, "KP9" }, - { TERMKEY_SYM_KPENTER, "KPEnter" }, - { TERMKEY_SYM_KPPLUS, "KPPlus" }, - { TERMKEY_SYM_KPMINUS, "KPMinus" }, - { TERMKEY_SYM_KPMULT, "KPMult" }, - { TERMKEY_SYM_KPDIV, "KPDiv" }, - { TERMKEY_SYM_KPCOMMA, "KPComma" }, - { TERMKEY_SYM_KPPERIOD, "KPPeriod" }, - { TERMKEY_SYM_KPEQUALS, "KPEquals" }, - { 0, NULL }, +static void emit_codepoint (termkey_t *tk, long codepoint, termkey_key_t *key); +static termkey_result_t peekkey_simple (termkey_t *tk, + termkey_key_t *key, int force, size_t *nbytes); +static termkey_result_t peekkey_mouse (termkey_t *tk, + termkey_key_t *key, size_t *nbytes); + +static termkey_sym_t register_c0 (termkey_t *tk, termkey_sym_t sym, + unsigned char ctrl, const char *name); +static termkey_sym_t register_c0_full (termkey_t *tk, termkey_sym_t sym, + int modifier_set, int modifier_mask, unsigned char ctrl, const char *name); + +static struct +{ + termkey_sym_t sym; + const char *name; +} +keynames[] = +{ + { TERMKEY_SYM_NONE, "NONE" }, + { TERMKEY_SYM_BACKSPACE, "Backspace" }, + { TERMKEY_SYM_TAB, "Tab" }, + { TERMKEY_SYM_ENTER, "Enter" }, + { TERMKEY_SYM_ESCAPE, "Escape" }, + { TERMKEY_SYM_SPACE, "Space" }, + { TERMKEY_SYM_DEL, "DEL" }, + { TERMKEY_SYM_UP, "Up" }, + { TERMKEY_SYM_DOWN, "Down" }, + { TERMKEY_SYM_LEFT, "Left" }, + { TERMKEY_SYM_RIGHT, "Right" }, + { TERMKEY_SYM_BEGIN, "Begin" }, + { TERMKEY_SYM_FIND, "Find" }, + { TERMKEY_SYM_INSERT, "Insert" }, + { TERMKEY_SYM_DELETE, "Delete" }, + { TERMKEY_SYM_SELECT, "Select" }, + { TERMKEY_SYM_PAGEUP, "PageUp" }, + { TERMKEY_SYM_PAGEDOWN, "PageDown" }, + { TERMKEY_SYM_HOME, "Home" }, + { TERMKEY_SYM_END, "End" }, + { TERMKEY_SYM_CANCEL, "Cancel" }, + { TERMKEY_SYM_CLEAR, "Clear" }, + { TERMKEY_SYM_CLOSE, "Close" }, + { TERMKEY_SYM_COMMAND, "Command" }, + { TERMKEY_SYM_COPY, "Copy" }, + { TERMKEY_SYM_EXIT, "Exit" }, + { TERMKEY_SYM_HELP, "Help" }, + { TERMKEY_SYM_MARK, "Mark" }, + { TERMKEY_SYM_MESSAGE, "Message" }, + { TERMKEY_SYM_MOVE, "Move" }, + { TERMKEY_SYM_OPEN, "Open" }, + { TERMKEY_SYM_OPTIONS, "Options" }, + { TERMKEY_SYM_PRINT, "Print" }, + { TERMKEY_SYM_REDO, "Redo" }, + { TERMKEY_SYM_REFERENCE, "Reference" }, + { TERMKEY_SYM_REFRESH, "Refresh" }, + { TERMKEY_SYM_REPLACE, "Replace" }, + { TERMKEY_SYM_RESTART, "Restart" }, + { TERMKEY_SYM_RESUME, "Resume" }, + { TERMKEY_SYM_SAVE, "Save" }, + { TERMKEY_SYM_SUSPEND, "Suspend" }, + { TERMKEY_SYM_UNDO, "Undo" }, + { TERMKEY_SYM_KP0, "KP0" }, + { TERMKEY_SYM_KP1, "KP1" }, + { TERMKEY_SYM_KP2, "KP2" }, + { TERMKEY_SYM_KP3, "KP3" }, + { TERMKEY_SYM_KP4, "KP4" }, + { TERMKEY_SYM_KP5, "KP5" }, + { TERMKEY_SYM_KP6, "KP6" }, + { TERMKEY_SYM_KP7, "KP7" }, + { TERMKEY_SYM_KP8, "KP8" }, + { TERMKEY_SYM_KP9, "KP9" }, + { TERMKEY_SYM_KPENTER, "KPEnter" }, + { TERMKEY_SYM_KPPLUS, "KPPlus" }, + { TERMKEY_SYM_KPMINUS, "KPMinus" }, + { TERMKEY_SYM_KPMULT, "KPMult" }, + { TERMKEY_SYM_KPDIV, "KPDiv" }, + { TERMKEY_SYM_KPCOMMA, "KPComma" }, + { TERMKEY_SYM_KPPERIOD, "KPPeriod" }, + { TERMKEY_SYM_KPEQUALS, "KPEquals" }, + { 0, NULL }, }; #define CHARAT(i) (tk->buffer[tk->buffstart + (i)]) @@ -116,112 +124,125 @@ static struct { #ifdef DEBUG /* Some internal deubgging functions */ -static void print_buffer(TermKey *tk) +static void +print_buffer (termkey_t *tk) { - int i; - for(i = 0; i < tk->buffcount && i < 20; i++) - fprintf(stderr, "%02x ", CHARAT(i)); - if(tk->buffcount > 20) - fprintf(stderr, "..."); + int i; + for (i = 0; i < tk->buffcount && i < 20; i++) + fprintf (stderr, "%02x ", CHARAT (i)); + if (tk->buffcount > 20) + fprintf (stderr, "..."); } -static void print_key(TermKey *tk, TermKeyKey *key) +static void +print_key (termkey_t *tk, termkey_key_t *key) { - switch(key->type) { - case TERMKEY_TYPE_UNICODE: - fprintf(stderr, "Unicode codepoint=U+%04lx utf8='%s'", key->code.codepoint, key->utf8); - break; - case TERMKEY_TYPE_FUNCTION: - fprintf(stderr, "Function F%d", key->code.number); - break; - case TERMKEY_TYPE_KEYSYM: - fprintf(stderr, "Keysym sym=%d(%s)", key->code.sym, termkey_get_keyname(tk, key->code.sym)); - break; - case TERMKEY_TYPE_MOUSE: - { - TermKeyMouseEvent ev; - int button, line, col; - termkey_interpret_mouse(tk, key, &ev, &button, &line, &col); - fprintf(stderr, "Mouse ev=%d button=%d pos=(%d,%d)\n", ev, button, line, col); - } - break; - case TERMKEY_TYPE_POSITION: - { - int line, col; - termkey_interpret_position(tk, key, &line, &col); - fprintf(stderr, "Position report pos=(%d,%d)\n", line, col); - } - break; - case TERMKEY_TYPE_MODEREPORT: - { - int initial, mode, value; - termkey_interpret_modereport(tk, key, &initial, &mode, &value); - fprintf(stderr, "Mode report mode=%s %d val=%d\n", initial == '?' ? "DEC" : "ANSI", mode, value); - } - break; - case TERMKEY_TYPE_UNKNOWN_CSI: - fprintf(stderr, "unknown CSI\n"); - break; - } - - int m = key->modifiers; - fprintf(stderr, " mod=%s%s%s+%02x", - (m & TERMKEY_KEYMOD_CTRL ? "C" : ""), - (m & TERMKEY_KEYMOD_ALT ? "A" : ""), - (m & TERMKEY_KEYMOD_SHIFT ? "S" : ""), - m & ~(TERMKEY_KEYMOD_CTRL|TERMKEY_KEYMOD_ALT|TERMKEY_KEYMOD_SHIFT)); + switch (key->type) + { + case TERMKEY_TYPE_UNICODE: + fprintf (stderr, "Unicode codepoint=U+%04lx utf8='%s'", + key->code.codepoint, key->utf8); + break; + case TERMKEY_TYPE_FUNCTION: + fprintf (stderr, "Function F%d", key->code.number); + break; + case TERMKEY_TYPE_KEYSYM: + fprintf (stderr, "Keysym sym=%d(%s)", + key->code.sym, termkey_get_keyname (tk, key->code.sym)); + break; + case TERMKEY_TYPE_MOUSE: + { + termkey_mouse_event_t ev; + int button, line, col; + termkey_interpret_mouse (tk, key, &ev, &button, &line, &col); + fprintf (stderr, "Mouse ev=%d button=%d pos=(%d,%d)\n", + ev, button, line, col); + break; + } + case TERMKEY_TYPE_POSITION: + { + int line, col; + termkey_interpret_position (tk, key, &line, &col); + fprintf (stderr, "Position report pos=(%d,%d)\n", line, col); + break; + } + case TERMKEY_TYPE_MODEREPORT: + { + int initial, mode, value; + termkey_interpret_modereport (tk, key, &initial, &mode, &value); + fprintf (stderr, "Mode report mode=%s %d val=%d\n", + initial == '?' ? "DEC" : "ANSI", mode, value); + break; + } + case TERMKEY_TYPE_UNKNOWN_CSI: + fprintf (stderr, "unknown CSI\n"); + } + + int m = key->modifiers; + fprintf (stderr, " mod=%s%s%s+%02x", + (m & TERMKEY_KEYMOD_CTRL ? "C" : ""), + (m & TERMKEY_KEYMOD_ALT ? "A" : ""), + (m & TERMKEY_KEYMOD_SHIFT ? "S" : ""), + m & ~(TERMKEY_KEYMOD_CTRL | TERMKEY_KEYMOD_ALT | TERMKEY_KEYMOD_SHIFT)); } -static const char *res2str(TermKeyResult res) +static const char * +res2str (termkey_result_t res) { - static char errorbuffer[256]; - - switch(res) { - case TERMKEY_RES_KEY: - return "TERMKEY_RES_KEY"; - case TERMKEY_RES_EOF: - return "TERMKEY_RES_EOF"; - case TERMKEY_RES_AGAIN: - return "TERMKEY_RES_AGAIN"; - case TERMKEY_RES_NONE: - return "TERMKEY_RES_NONE"; - case TERMKEY_RES_ERROR: - snprintf(errorbuffer, sizeof errorbuffer, "TERMKEY_RES_ERROR(errno=%d)\n", errno); - return (const char*)errorbuffer; - } - - return "unknown"; + static char errorbuffer[256]; + + switch (res) + { + case TERMKEY_RES_KEY: + return "TERMKEY_RES_KEY"; + case TERMKEY_RES_EOF: + return "TERMKEY_RES_EOF"; + case TERMKEY_RES_AGAIN: + return "TERMKEY_RES_AGAIN"; + case TERMKEY_RES_NONE: + return "TERMKEY_RES_NONE"; + case TERMKEY_RES_ERROR: + snprintf (errorbuffer, sizeof errorbuffer, + "TERMKEY_RES_ERROR(errno=%d)\n", errno); + return (const char*) errorbuffer; + } + + return "unknown"; } #endif /* Similar to snprintf(str, size, "%s", src) except it turns CamelCase into * space separated values */ -static int snprint_cameltospaces(char *str, size_t size, const char *src) +static int +snprint_cameltospaces (char *str, size_t size, const char *src) { - int prev_lower = 0; - size_t l = 0; - while(*src && l < size - 1) { - if(isupper(*src) && prev_lower) { - if(str) - str[l++] = ' '; - if(l >= size - 1) - break; - } - prev_lower = islower(*src); - str[l++] = tolower(*src++); - } - str[l] = 0; - /* For consistency with snprintf, return the number of bytes that would have - * been written, excluding '\0' */ - while(*src) { - if(isupper(*src) && prev_lower) { - l++; - } - prev_lower = islower(*src); - src++; l++; - } - return l; + int prev_lower = 0; + size_t l = 0; + while (*src && l < size - 1) + { + if (isupper (*src) && prev_lower) + { + if (str) + str[l++] = ' '; + if (l >= size - 1) + break; + } + prev_lower = islower (*src); + str[l++] = tolower (*src++); + } + str[l] = 0; + + /* For consistency with snprintf, return the number of bytes that would have + * been written, excluding '\0' */ + for (; *src; src++) + { + if (isupper (*src) && prev_lower) + l++; + prev_lower = islower (*src); + l++; + } + return l; } /* Similar to strcmp(str, strcamel, n) except that: @@ -229,1286 +250,1393 @@ static int snprint_cameltospaces(char *str, size_t size, const char *src) * it takes char**s and updates them * n counts bytes of strcamel, not str */ -static int strpncmp_camel(const char **strp, const char **strcamelp, size_t n) +static int +strpncmp_camel (const char **strp, const char **strcamelp, size_t n) { - const char *str = *strp, *strcamel = *strcamelp; - int prev_lower = 0; - - for( ; (*str || *strcamel) && n; n--) { - char b = tolower(*strcamel); - if(isupper(*strcamel) && prev_lower) { - if(*str != ' ') - break; - str++; - if(*str != b) - break; - } - else - if(*str != b) - break; - - prev_lower = islower(*strcamel); - - str++; - strcamel++; - } - - *strp = str; - *strcamelp = strcamel; - return *str - *strcamel; + const char *str = *strp, *strcamel = *strcamelp; + int prev_lower = 0; + + for (; (*str || *strcamel) && n; n--) + { + char b = tolower (*strcamel); + if (isupper (*strcamel) && prev_lower) + { + if (*str != ' ') + break; + str++; + if (*str != b) + break; + } + else if (*str != b) + break; + + prev_lower = islower (*strcamel); + + str++; + strcamel++; + } + + *strp = str; + *strcamelp = strcamel; + return *str - *strcamel; } -static TermKey *termkey_alloc(void) +static termkey_t * +termkey_alloc (void) { - TermKey *tk = malloc(sizeof(TermKey)); - if(!tk) - return NULL; - - /* Default all the object fields but don't allocate anything */ + termkey_t *tk = malloc (sizeof *tk); + if (!tk) + return NULL; - tk->fd = -1; - tk->flags = 0; - tk->canonflags = 0; + /* Default all the object fields but don't allocate anything */ - tk->buffer = NULL; - tk->buffstart = 0; - tk->buffcount = 0; - tk->buffsize = 256; /* bytes */ - tk->hightide = 0; + tk->fd = -1; + tk->flags = 0; + tk->canonflags = 0; - tk->restore_termios_valid = 0; + tk->buffer = NULL; + tk->buffstart = 0; + tk->buffcount = 0; + tk->buffsize = 256; /* bytes */ + tk->hightide = 0; - tk->waittime = 50; /* msec */ + tk->restore_termios_valid = 0; - tk->is_closed = 0; - tk->is_started = 0; + tk->waittime = 50; /* msec */ - tk->nkeynames = 64; - tk->keynames = NULL; + tk->is_closed = 0; + tk->is_started = 0; - for(int i = 0; i < 32; i++) - tk->c0[i].sym = TERMKEY_SYM_NONE; + tk->nkeynames = 64; + tk->keynames = NULL; - tk->drivers = NULL; + for (int i = 0; i < 32; i++) + tk->c0[i].sym = TERMKEY_SYM_NONE; - tk->method.emit_codepoint = &emit_codepoint; - tk->method.peekkey_simple = &peekkey_simple; - tk->method.peekkey_mouse = &peekkey_mouse; + tk->drivers = NULL; - return tk; + tk->method.emit_codepoint = &emit_codepoint; + tk->method.peekkey_simple = &peekkey_simple; + tk->method.peekkey_mouse = &peekkey_mouse; + return tk; } -static int termkey_init(TermKey *tk, const char *term) +static int +termkey_init (termkey_t *tk, const char *term) { - tk->buffer = malloc(tk->buffsize); - if(!tk->buffer) - return 0; - - tk->keynames = malloc(sizeof(tk->keynames[0]) * tk->nkeynames); - if(!tk->keynames) - goto abort_free_buffer; - - int i; - for(i = 0; i < tk->nkeynames; i++) - tk->keynames[i] = NULL; - - for(i = 0; keynames[i].name; i++) - if(termkey_register_keyname(tk, keynames[i].sym, keynames[i].name) == -1) - goto abort_free_keynames; - - register_c0(tk, TERMKEY_SYM_BACKSPACE, 0x08, NULL); - register_c0(tk, TERMKEY_SYM_TAB, 0x09, NULL); - register_c0(tk, TERMKEY_SYM_ENTER, 0x0d, NULL); - register_c0(tk, TERMKEY_SYM_ESCAPE, 0x1b, NULL); - - struct TermKeyDriverNode *tail = NULL; - - for(i = 0; drivers[i]; i++) { - void *info = (*drivers[i]->new_driver)(tk, term); - if(!info) - continue; + tk->buffer = malloc (tk->buffsize); + if (!tk->buffer) + return 0; + + tk->keynames = malloc (sizeof tk->keynames[0] * tk->nkeynames); + if (!tk->keynames) + goto abort_free_buffer; + + int i; + for (i = 0; i < tk->nkeynames; i++) + tk->keynames[i] = NULL; + for (i = 0; keynames[i].name; i++) + if (termkey_register_keyname (tk, + keynames[i].sym, keynames[i].name) == -1) + goto abort_free_keynames; + + register_c0 (tk, TERMKEY_SYM_BACKSPACE, 0x08, NULL); + register_c0 (tk, TERMKEY_SYM_TAB, 0x09, NULL); + register_c0 (tk, TERMKEY_SYM_ENTER, 0x0d, NULL); + register_c0 (tk, TERMKEY_SYM_ESCAPE, 0x1b, NULL); + + termkey_driver_node_t *tail = NULL; + for (i = 0; drivers[i]; i++) + { + void *info = (*drivers[i]->new_driver) (tk, term); + if (!info) + continue; #ifdef DEBUG - fprintf(stderr, "Loading the %s driver...\n", drivers[i]->name); + fprintf (stderr, "Loading the %s driver...\n", drivers[i]->name); #endif - struct TermKeyDriverNode *thisdrv = malloc(sizeof(*thisdrv)); - if(!thisdrv) - goto abort_free_drivers; + termkey_driver_node_t *thisdrv = malloc (sizeof *thisdrv); + if (!thisdrv) + goto abort_free_drivers; - thisdrv->driver = drivers[i]; - thisdrv->info = info; - thisdrv->next = NULL; + thisdrv->driver = drivers[i]; + thisdrv->info = info; + thisdrv->next = NULL; - if(!tail) - tk->drivers = thisdrv; - else - tail->next = thisdrv; + if (!tail) + tk->drivers = thisdrv; + else + tail->next = thisdrv; - tail = thisdrv; + tail = thisdrv; #ifdef DEBUG - fprintf(stderr, "Loaded %s driver\n", drivers[i]->name); + fprintf (stderr, "Loaded %s driver\n", drivers[i]->name); #endif - } - - if(!tk->drivers) { - errno = ENOENT; - goto abort_free_keynames; - } + } - return 1; + if (!tk->drivers) + { + errno = ENOENT; + goto abort_free_keynames; + } + return 1; abort_free_drivers: - for(struct TermKeyDriverNode *p = tk->drivers; p; ) { - (*p->driver->free_driver)(p->info); - struct TermKeyDriverNode *next = p->next; - free(p); - p = next; - } + for (termkey_driver_node_t *p = tk->drivers; p; ) + { + (*p->driver->free_driver) (p->info); + termkey_driver_node_t *next = p->next; + free (p); + p = next; + } abort_free_keynames: - free(tk->keynames); + free (tk->keynames); abort_free_buffer: - free(tk->buffer); - - return 0; + free (tk->buffer); + return 0; } -TermKey *termkey_new(int fd, int flags) +termkey_t * +termkey_new (int fd, int flags) { - TermKey *tk = termkey_alloc(); - if(!tk) - return NULL; + termkey_t *tk = termkey_alloc (); + if (!tk) + return NULL; - tk->fd = fd; + tk->fd = fd; - if(!(flags & (TERMKEY_FLAG_RAW|TERMKEY_FLAG_UTF8))) { - char *e; + if (!(flags & (TERMKEY_FLAG_RAW | TERMKEY_FLAG_UTF8))) + { + char *e; - /* Most OSes will set .UTF-8. Some will set .utf8. Try to be fairly - * generous in parsing these - */ - if(((e = getenv("LANG")) || (e = getenv("LC_MESSAGES")) || (e = getenv("LC_ALL"))) && - (e = strchr(e, '.')) && e++ && - (strcaseeq(e, "UTF-8") || strcaseeq(e, "UTF8"))) - flags |= TERMKEY_FLAG_UTF8; - else - flags |= TERMKEY_FLAG_RAW; - } + /* Most OSes will set .UTF-8. Some will set .utf8. Try to be fairly + * generous in parsing these + */ + if (((e = getenv("LANG")) || (e = getenv("LC_CTYPE")) + || (e = getenv("LC_ALL"))) && (e = strchr(e, '.')) && e++ && + (!strcasecmp(e, "UTF-8") || !strcasecmp(e, "UTF8"))) + flags |= TERMKEY_FLAG_UTF8; + else + flags |= TERMKEY_FLAG_RAW; + } - termkey_set_flags(tk, flags); + termkey_set_flags (tk, flags); - const char *term = getenv("TERM"); + const char *term = getenv ("TERM"); - if(!termkey_init(tk, term)) - goto abort; + if (!termkey_init (tk, term)) + goto abort; - if(!termkey_start(tk)) - goto abort; + if (!termkey_start (tk)) + goto abort; - return tk; + return tk; abort: - free(tk); - return NULL; + free (tk); + return NULL; } -TermKey *termkey_new_abstract(const char *term, int flags) +termkey_t * +termkey_new_abstract (const char *term, int flags) { - TermKey *tk = termkey_alloc(); - if(!tk) - return NULL; - - tk->fd = -1; - - termkey_set_flags(tk, flags); - - if(!termkey_init(tk, term)) { - free(tk); - return NULL; - } - - termkey_start(tk); - - return tk; + termkey_t *tk = termkey_alloc (); + if (!tk) + return NULL; + + tk->fd = -1; + termkey_set_flags (tk, flags); + if (!termkey_init (tk, term)) + { + free (tk); + return NULL; + } + + termkey_start (tk); + return tk; } -void termkey_free(TermKey *tk) +void +termkey_free (termkey_t *tk) { - free(tk->buffer); tk->buffer = NULL; - free(tk->keynames); tk->keynames = NULL; - - struct TermKeyDriverNode *p; - for(p = tk->drivers; p; ) { - (*p->driver->free_driver)(p->info); - struct TermKeyDriverNode *next = p->next; - free(p); - p = next; - } - - free(tk); + free (tk->buffer); tk->buffer = NULL; + free (tk->keynames); tk->keynames = NULL; + + termkey_driver_node_t *p; + for (p = tk->drivers; p; ) + { + (*p->driver->free_driver) (p->info); + termkey_driver_node_t *next = p->next; + free (p); + p = next; + } + free (tk); } -void termkey_destroy(TermKey *tk) +void +termkey_destroy (termkey_t *tk) { - if(tk->is_started) - termkey_stop(tk); + if (tk->is_started) + termkey_stop (tk); - termkey_free(tk); + termkey_free (tk); } -int termkey_start(TermKey *tk) +int +termkey_start (termkey_t *tk) { - if(tk->is_started) - return 1; - - if(tk->fd != -1 && !(tk->flags & TERMKEY_FLAG_NOTERMIOS)) { - struct termios termios; - if(tcgetattr(tk->fd, &termios) == 0) { - tk->restore_termios = termios; - tk->restore_termios_valid = 1; - - termios.c_iflag &= ~(IXON|INLCR|ICRNL); - termios.c_lflag &= ~(ICANON|ECHO); - termios.c_cc[VMIN] = 1; - termios.c_cc[VTIME] = 0; - - if(tk->flags & TERMKEY_FLAG_CTRLC) - /* want no signal keys at all, so just disable ISIG */ - termios.c_lflag &= ~ISIG; - else { - /* Disable Ctrl-\==VQUIT and Ctrl-D==VSUSP but leave Ctrl-C as SIGINT */ - termios.c_cc[VQUIT] = _POSIX_VDISABLE; - termios.c_cc[VSUSP] = _POSIX_VDISABLE; - /* Some OSes have Ctrl-Y==VDSUSP */ + if (tk->is_started) + return 1; + + if (tk->fd != -1 && !(tk->flags & TERMKEY_FLAG_NOTERMIOS)) + { + struct termios termios; + if (tcgetattr (tk->fd, &termios) == 0) + { + tk->restore_termios = termios; + tk->restore_termios_valid = 1; + + termios.c_iflag &= ~(IXON|INLCR|ICRNL); + termios.c_lflag &= ~(ICANON|ECHO); + termios.c_cc[VMIN] = 1; + termios.c_cc[VTIME] = 0; + + if (tk->flags & TERMKEY_FLAG_CTRLC) + /* want no signal keys at all, so just disable ISIG */ + termios.c_lflag &= ~ISIG; + else + { + /* Disable ^\ == VQUIT and ^D == VSUSP but leave ^C as SIGINT */ + termios.c_cc[VQUIT] = _POSIX_VDISABLE; + termios.c_cc[VSUSP] = _POSIX_VDISABLE; + /* Some OSes have ^Y == VDSUSP */ #ifdef VDSUSP - termios.c_cc[VDSUSP] = _POSIX_VDISABLE; + termios.c_cc[VDSUSP] = _POSIX_VDISABLE; #endif - } + } #ifdef DEBUG - fprintf(stderr, "Setting termios(3) flags\n"); + fprintf (stderr, "Setting termios(3) flags\n"); #endif - tcsetattr(tk->fd, TCSANOW, &termios); - } - } + tcsetattr (tk->fd, TCSANOW, &termios); + } + } - struct TermKeyDriverNode *p; - for(p = tk->drivers; p; p = p->next) - if(p->driver->start_driver) - if(!(*p->driver->start_driver)(tk, p->info)) - return 0; + termkey_driver_node_t *p; + for (p = tk->drivers; p; p = p->next) + if (p->driver->start_driver) + if (!(*p->driver->start_driver) (tk, p->info)) + return 0; #ifdef DEBUG - fprintf(stderr, "Drivers started; termkey instance %p is ready\n", tk); + fprintf (stderr, "Drivers started; termkey instance %p is ready\n", tk); #endif - tk->is_started = 1; - return 1; + tk->is_started = 1; + return 1; } -int termkey_stop(TermKey *tk) +int +termkey_stop (termkey_t *tk) { - if(!tk->is_started) - return 1; + if (!tk->is_started) + return 1; - struct TermKeyDriverNode *p; - for(p = tk->drivers; p; p = p->next) - if(p->driver->stop_driver) - (*p->driver->stop_driver)(tk, p->info); + struct termkey_driver_node *p; + for (p = tk->drivers; p; p = p->next) + if (p->driver->stop_driver) + (*p->driver->stop_driver) (tk, p->info); - if(tk->restore_termios_valid) - tcsetattr(tk->fd, TCSANOW, &tk->restore_termios); + if (tk->restore_termios_valid) + tcsetattr (tk->fd, TCSANOW, &tk->restore_termios); - tk->is_started = 0; - - return 1; + tk->is_started = 0; + return 1; } -int termkey_is_started(TermKey *tk) +int +termkey_is_started (termkey_t *tk) { - return tk->is_started; + return tk->is_started; } -int termkey_get_fd(TermKey *tk) +int +termkey_get_fd (termkey_t *tk) { - return tk->fd; + return tk->fd; } -int termkey_get_flags(TermKey *tk) +int +termkey_get_flags (termkey_t *tk) { - return tk->flags; + return tk->flags; } -void termkey_set_flags(TermKey *tk, int newflags) +void +termkey_set_flags (termkey_t *tk, int newflags) { - tk->flags = newflags; - - if(tk->flags & TERMKEY_FLAG_SPACESYMBOL) - tk->canonflags |= TERMKEY_CANON_SPACESYMBOL; - else - tk->canonflags &= ~TERMKEY_CANON_SPACESYMBOL; + tk->flags = newflags; + if (tk->flags & TERMKEY_FLAG_SPACESYMBOL) + tk->canonflags |= TERMKEY_CANON_SPACESYMBOL; + else + tk->canonflags &= ~TERMKEY_CANON_SPACESYMBOL; } -void termkey_set_waittime(TermKey *tk, int msec) +void +termkey_set_waittime (termkey_t *tk, int msec) { - tk->waittime = msec; + tk->waittime = msec; } -int termkey_get_waittime(TermKey *tk) +int +termkey_get_waittime (termkey_t *tk) { - return tk->waittime; + return tk->waittime; } -int termkey_get_canonflags(TermKey *tk) +int +termkey_get_canonflags (termkey_t *tk) { - return tk->canonflags; + return tk->canonflags; } -void termkey_set_canonflags(TermKey *tk, int flags) +void +termkey_set_canonflags (termkey_t *tk, int flags) { - tk->canonflags = flags; - - if(tk->canonflags & TERMKEY_CANON_SPACESYMBOL) - tk->flags |= TERMKEY_FLAG_SPACESYMBOL; - else - tk->flags &= ~TERMKEY_FLAG_SPACESYMBOL; + tk->canonflags = flags; + if(tk->canonflags & TERMKEY_CANON_SPACESYMBOL) + tk->flags |= TERMKEY_FLAG_SPACESYMBOL; + else + tk->flags &= ~TERMKEY_FLAG_SPACESYMBOL; } -size_t termkey_get_buffer_size(TermKey *tk) +size_t +termkey_get_buffer_size (termkey_t *tk) { - return tk->buffsize; + return tk->buffsize; } -int termkey_set_buffer_size(TermKey *tk, size_t size) +int +termkey_set_buffer_size (termkey_t *tk, size_t size) { - unsigned char *buffer = realloc(tk->buffer, size); - if(!buffer) - return 0; + unsigned char *buffer = realloc (tk->buffer, size); + if (!buffer) + return 0; - tk->buffer = buffer; - tk->buffsize = size; - - return 1; + tk->buffer = buffer; + tk->buffsize = size; + return 1; } -size_t termkey_get_buffer_remaining(TermKey *tk) +size_t +termkey_get_buffer_remaining (termkey_t *tk) { - /* Return the total number of free bytes in the buffer, because that's what - * is available to the user. */ - return tk->buffsize - tk->buffcount; + /* Return the total number of free bytes in the buffer, because that's what + * is available to the user. */ + return tk->buffsize - tk->buffcount; } -static void eat_bytes(TermKey *tk, size_t count) +static void +eat_bytes (termkey_t *tk, size_t count) { - if(count >= tk->buffcount) { - tk->buffstart = 0; - tk->buffcount = 0; - return; - } - - tk->buffstart += count; - tk->buffcount -= count; + if (count >= tk->buffcount) + { + tk->buffstart = 0; + tk->buffcount = 0; + return; + } + + tk->buffstart += count; + tk->buffcount -= count; } -static inline unsigned int utf8_seqlen(long codepoint) +static inline unsigned int +utf8_seqlen (long codepoint) { - if(codepoint < 0x0000080) return 1; - if(codepoint < 0x0000800) return 2; - if(codepoint < 0x0010000) return 3; - if(codepoint < 0x0200000) return 4; - if(codepoint < 0x4000000) return 5; - return 6; + if (codepoint < 0x0000080) return 1; + if (codepoint < 0x0000800) return 2; + if (codepoint < 0x0010000) return 3; + if (codepoint < 0x0200000) return 4; + if (codepoint < 0x4000000) return 5; + return 6; } -static void fill_utf8(TermKeyKey *key) +static void +fill_utf8 (termkey_key_t *key) { - long codepoint = key->code.codepoint; - int nbytes = utf8_seqlen(codepoint); - - key->utf8[nbytes] = 0; - - // This is easier done backwards - int b = nbytes; - while(b > 1) { - b--; - key->utf8[b] = 0x80 | (codepoint & 0x3f); - codepoint >>= 6; - } - - switch(nbytes) { - case 1: key->utf8[0] = (codepoint & 0x7f); break; - case 2: key->utf8[0] = 0xc0 | (codepoint & 0x1f); break; - case 3: key->utf8[0] = 0xe0 | (codepoint & 0x0f); break; - case 4: key->utf8[0] = 0xf0 | (codepoint & 0x07); break; - case 5: key->utf8[0] = 0xf8 | (codepoint & 0x03); break; - case 6: key->utf8[0] = 0xfc | (codepoint & 0x01); break; - } + long codepoint = key->code.codepoint; + int nbytes = utf8_seqlen (codepoint); + + key->utf8[nbytes] = 0; + + // This is easier done backwards + int b = nbytes; + while (b > 1) + { + b--; + key->utf8[b] = 0x80 | (codepoint & 0x3f); + codepoint >>= 6; + } + + switch (nbytes) + { + case 1: key->utf8[0] = (codepoint & 0x7f); break; + case 2: key->utf8[0] = 0xc0 | (codepoint & 0x1f); break; + case 3: key->utf8[0] = 0xe0 | (codepoint & 0x0f); break; + case 4: key->utf8[0] = 0xf0 | (codepoint & 0x07); break; + case 5: key->utf8[0] = 0xf8 | (codepoint & 0x03); break; + case 6: key->utf8[0] = 0xfc | (codepoint & 0x01); break; + } } #define UTF8_INVALID 0xFFFD -static TermKeyResult parse_utf8(const unsigned char *bytes, size_t len, long *cp, size_t *nbytep) +static termkey_result_t +parse_utf8 (const unsigned char *bytes, size_t len, long *cp, size_t *nbytep) { - unsigned int nbytes; - - unsigned char b0 = bytes[0]; - - if(b0 < 0x80) { - // Single byte ASCII - *cp = b0; - *nbytep = 1; - return TERMKEY_RES_KEY; - } - else if(b0 < 0xc0) { - // Starts with a continuation byte - that's not right - *cp = UTF8_INVALID; - *nbytep = 1; - return TERMKEY_RES_KEY; - } - else if(b0 < 0xe0) { - nbytes = 2; - *cp = b0 & 0x1f; - } - else if(b0 < 0xf0) { - nbytes = 3; - *cp = b0 & 0x0f; - } - else if(b0 < 0xf8) { - nbytes = 4; - *cp = b0 & 0x07; - } - else if(b0 < 0xfc) { - nbytes = 5; - *cp = b0 & 0x03; - } - else if(b0 < 0xfe) { - nbytes = 6; - *cp = b0 & 0x01; - } - else { - *cp = UTF8_INVALID; - *nbytep = 1; - return TERMKEY_RES_KEY; - } - - for(unsigned int b = 1; b < nbytes; b++) { - unsigned char cb; - - if(b >= len) - return TERMKEY_RES_AGAIN; - - cb = bytes[b]; - if(cb < 0x80 || cb >= 0xc0) { - *cp = UTF8_INVALID; - *nbytep = b; - return TERMKEY_RES_KEY; - } - - *cp <<= 6; - *cp |= cb & 0x3f; - } - - // Check for overlong sequences - if(nbytes > utf8_seqlen(*cp)) - *cp = UTF8_INVALID; - - // Check for UTF-16 surrogates or invalid *cps - if((*cp >= 0xD800 && *cp <= 0xDFFF) || - *cp == 0xFFFE || - *cp == 0xFFFF) - *cp = UTF8_INVALID; - - *nbytep = nbytes; - return TERMKEY_RES_KEY; + unsigned int nbytes; + unsigned char b0 = bytes[0]; + + if (b0 < 0x80) + { + // Single byte ASCII + *cp = b0; + *nbytep = 1; + return TERMKEY_RES_KEY; + } + else if (b0 < 0xc0) + { + // Starts with a continuation byte - that's not right + *cp = UTF8_INVALID; + *nbytep = 1; + return TERMKEY_RES_KEY; + } + else if (b0 < 0xe0) + { + nbytes = 2; + *cp = b0 & 0x1f; + } + else if (b0 < 0xf0) + { + nbytes = 3; + *cp = b0 & 0x0f; + } + else if (b0 < 0xf8) + { + nbytes = 4; + *cp = b0 & 0x07; + } + else if (b0 < 0xfc) + { + nbytes = 5; + *cp = b0 & 0x03; + } + else if (b0 < 0xfe) + { + nbytes = 6; + *cp = b0 & 0x01; + } + else + { + *cp = UTF8_INVALID; + *nbytep = 1; + return TERMKEY_RES_KEY; + } + + for (unsigned int b = 1; b < nbytes; b++) + { + if (b >= len) + return TERMKEY_RES_AGAIN; + + unsigned char cb = bytes[b]; + if (cb < 0x80 || cb >= 0xc0) + { + *cp = UTF8_INVALID; + *nbytep = b; + return TERMKEY_RES_KEY; + } + + *cp <<= 6; + *cp |= cb & 0x3f; + } + + // Check for overlong sequences + if (nbytes > utf8_seqlen (*cp)) + *cp = UTF8_INVALID; + + // Check for UTF-16 surrogates or invalid *cps + if ((*cp >= 0xD800 && *cp <= 0xDFFF) || *cp == 0xFFFE || *cp == 0xFFFF) + *cp = UTF8_INVALID; + + *nbytep = nbytes; + return TERMKEY_RES_KEY; } -static void emit_codepoint(TermKey *tk, long codepoint, TermKeyKey *key) +static void +emit_codepoint (termkey_t *tk, long codepoint, termkey_key_t *key) { - if(codepoint < 0x20) { - // C0 range - key->code.codepoint = 0; - key->modifiers = 0; - - if(!(tk->flags & TERMKEY_FLAG_NOINTERPRET) && tk->c0[codepoint].sym != TERMKEY_SYM_UNKNOWN) { - key->code.sym = tk->c0[codepoint].sym; - key->modifiers |= tk->c0[codepoint].modifier_set; - } - - if(!key->code.sym) { - key->type = TERMKEY_TYPE_UNICODE; - /* Generically modified Unicode ought not report the SHIFT state, or else - * we get into complicationg trying to report Shift-; vs : and so on... - * In order to be able to represent Ctrl-Shift-A as CTRL modified - * unicode A, we need to call Ctrl-A simply 'a', lowercase - */ - if(codepoint+0x40 >= 'A' && codepoint+0x40 <= 'Z') - // it's a letter - use lowecase instead - key->code.codepoint = codepoint + 0x60; - else - key->code.codepoint = codepoint + 0x40; - key->modifiers = TERMKEY_KEYMOD_CTRL; - } - else { - key->type = TERMKEY_TYPE_KEYSYM; - } - } - else if(codepoint == 0x7f && !(tk->flags & TERMKEY_FLAG_NOINTERPRET)) { - // ASCII DEL - key->type = TERMKEY_TYPE_KEYSYM; - key->code.sym = TERMKEY_SYM_DEL; - key->modifiers = 0; - } - else if(codepoint >= 0x20 && codepoint < 0x80) { - // ASCII lowbyte range - key->type = TERMKEY_TYPE_UNICODE; - key->code.codepoint = codepoint; - key->modifiers = 0; - } - else if(codepoint >= 0x80 && codepoint < 0xa0) { - // UTF-8 never starts with a C1 byte. So we can be sure of these - key->type = TERMKEY_TYPE_UNICODE; - key->code.codepoint = codepoint - 0x40; - key->modifiers = TERMKEY_KEYMOD_CTRL|TERMKEY_KEYMOD_ALT; - } - else { - // UTF-8 codepoint - key->type = TERMKEY_TYPE_UNICODE; - key->code.codepoint = codepoint; - key->modifiers = 0; - } - - termkey_canonicalise(tk, key); - - if(key->type == TERMKEY_TYPE_UNICODE) - fill_utf8(key); + if (codepoint < 0x20) + { + // C0 range + key->code.codepoint = 0; + key->modifiers = 0; + + if (!(tk->flags & TERMKEY_FLAG_NOINTERPRET) + && tk->c0[codepoint].sym != TERMKEY_SYM_UNKNOWN) + { + key->code.sym = tk->c0[codepoint].sym; + key->modifiers |= tk->c0[codepoint].modifier_set; + } + + if (!key->code.sym) + { + key->type = TERMKEY_TYPE_UNICODE; + /* Generically modified Unicode ought not report the SHIFT state, or else + * we get into complicationg trying to report Shift-; vs : and so on... + * In order to be able to represent Ctrl-Shift-A as CTRL modified + * unicode A, we need to call Ctrl-A simply 'a', lowercase + */ + if (codepoint + 0x40 >= 'A' && codepoint + 0x40 <= 'Z') + // it's a letter - use lowecase instead + key->code.codepoint = codepoint + 0x60; + else + key->code.codepoint = codepoint + 0x40; + key->modifiers = TERMKEY_KEYMOD_CTRL; + } + else + key->type = TERMKEY_TYPE_KEYSYM; + } + else if (codepoint == 0x7f && !(tk->flags & TERMKEY_FLAG_NOINTERPRET)) + { + // ASCII DEL + key->type = TERMKEY_TYPE_KEYSYM; + key->code.sym = TERMKEY_SYM_DEL; + key->modifiers = 0; + } + else if (codepoint >= 0x20 && codepoint < 0x80) + { + // ASCII lowbyte range + key->type = TERMKEY_TYPE_UNICODE; + key->code.codepoint = codepoint; + key->modifiers = 0; + } + else if (codepoint >= 0x80 && codepoint < 0xa0) + { + // UTF-8 never starts with a C1 byte. So we can be sure of these + key->type = TERMKEY_TYPE_UNICODE; + key->code.codepoint = codepoint - 0x40; + key->modifiers = TERMKEY_KEYMOD_CTRL | TERMKEY_KEYMOD_ALT; + } + else + { + // UTF-8 codepoint + key->type = TERMKEY_TYPE_UNICODE; + key->code.codepoint = codepoint; + key->modifiers = 0; + } + + termkey_canonicalise (tk, key); + + if (key->type == TERMKEY_TYPE_UNICODE) + fill_utf8 (key); } -void termkey_canonicalise(TermKey *tk, TermKeyKey *key) +void +termkey_canonicalise (termkey_t *tk, termkey_key_t *key) { - int flags = tk->canonflags; - - if(flags & TERMKEY_CANON_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); - } - } - - if(flags & TERMKEY_CANON_DELBS) { - if(key->type == TERMKEY_TYPE_KEYSYM && key->code.sym == TERMKEY_SYM_DEL) { - key->code.sym = TERMKEY_SYM_BACKSPACE; - } - } + int flags = tk->canonflags; + + if (flags & TERMKEY_CANON_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); + } + } + + if (flags & TERMKEY_CANON_DELBS) + if (key->type == TERMKEY_TYPE_KEYSYM + && key->code.sym == TERMKEY_SYM_DEL) + key->code.sym = TERMKEY_SYM_BACKSPACE; } -static TermKeyResult peekkey(TermKey *tk, TermKeyKey *key, int force, size_t *nbytep) +static termkey_result_t +peekkey (termkey_t *tk, termkey_key_t *key, int force, size_t *nbytep) { - int again = 0; + int again = 0; - if(!tk->is_started) { - errno = EINVAL; - return TERMKEY_RES_ERROR; - } + if (!tk->is_started) + { + errno = EINVAL; + return TERMKEY_RES_ERROR; + } #ifdef DEBUG - fprintf(stderr, "getkey(force=%d): buffer ", force); - print_buffer(tk); - fprintf(stderr, "\n"); + fprintf (stderr, "getkey(force=%d): buffer ", force); + print_buffer (tk); + fprintf (stderr, "\n"); #endif - if(tk->hightide) { - tk->buffstart += tk->hightide; - tk->buffcount -= tk->hightide; - tk->hightide = 0; - } + if (tk->hightide) + { + tk->buffstart += tk->hightide; + tk->buffcount -= tk->hightide; + tk->hightide = 0; + } - TermKeyResult ret; - struct TermKeyDriverNode *p; - for(p = tk->drivers; p; p = p->next) { - ret = (p->driver->peekkey)(tk, p->info, key, force, nbytep); + termkey_result_t ret; + termkey_driver_node_t *p; + for (p = tk->drivers; p; p = p->next) + { + ret = (p->driver->peekkey) (tk, p->info, key, force, nbytep); #ifdef DEBUG - fprintf(stderr, "Driver %s yields %s\n", p->driver->name, res2str(ret)); + fprintf (stderr, "Driver %s yields %s\n", + p->driver->name, res2str (ret)); #endif - switch(ret) { - case TERMKEY_RES_KEY: + switch (ret) + { + case TERMKEY_RES_KEY: + { #ifdef DEBUG - print_key(tk, key); fprintf(stderr, "\n"); + print_key (tk, key); fprintf (stderr, "\n"); #endif - // Slide the data down to stop it running away - { - size_t halfsize = tk->buffsize / 2; - - if(tk->buffstart > halfsize) { - memcpy(tk->buffer, tk->buffer + halfsize, halfsize); - tk->buffstart -= halfsize; - } - } - - /* fallthrough */ - case TERMKEY_RES_EOF: - case TERMKEY_RES_ERROR: - return ret; - - case TERMKEY_RES_AGAIN: - if(!force) - again = 1; - - /* fallthrough */ - case TERMKEY_RES_NONE: - break; - } - } - - if(again) - return TERMKEY_RES_AGAIN; - - ret = peekkey_simple(tk, key, force, nbytep); + // Slide the data down to stop it running away + size_t halfsize = tk->buffsize / 2; + if (tk->buffstart > halfsize) + { + memcpy (tk->buffer, tk->buffer + halfsize, halfsize); + tk->buffstart -= halfsize; + } + + /* fallthrough */ + } + case TERMKEY_RES_EOF: + case TERMKEY_RES_ERROR: + return ret; + + case TERMKEY_RES_AGAIN: + if (!force) + again = 1; + case TERMKEY_RES_NONE: + break; + } + } + + if (again) + return TERMKEY_RES_AGAIN; + + ret = peekkey_simple (tk, key, force, nbytep); #ifdef DEBUG - fprintf(stderr, "getkey_simple(force=%d) yields %s\n", force, res2str(ret)); - if(ret == TERMKEY_RES_KEY) { - print_key(tk, key); fprintf(stderr, "\n"); - } + fprintf (stderr, "getkey_simple(force=%d) yields %s\n", + force, res2str (ret)); + if (ret == TERMKEY_RES_KEY) + { + print_key (tk, key); + fprintf (stderr, "\n"); + } #endif - return ret; + return ret; } -static TermKeyResult peekkey_simple(TermKey *tk, TermKeyKey *key, int force, size_t *nbytep) +static termkey_result_t +peekkey_simple (termkey_t *tk, termkey_key_t *key, int force, size_t *nbytep) { - if(tk->buffcount == 0) - return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE; - - unsigned char b0 = CHARAT(0); - - if(b0 == 0x1b) { - // Escape-prefixed value? Might therefore be Alt+key - if(tk->buffcount == 1) { - // This might be an press, or it may want to be part of a longer - // sequence - if(!force) - return TERMKEY_RES_AGAIN; - - (*tk->method.emit_codepoint)(tk, b0, key); - *nbytep = 1; - return TERMKEY_RES_KEY; - } - - // Try another key there - tk->buffstart++; - tk->buffcount--; - - // Run the full driver - TermKeyResult metakey_result = peekkey(tk, key, force, nbytep); - - tk->buffstart--; - tk->buffcount++; - - switch(metakey_result) { - case TERMKEY_RES_KEY: - key->modifiers |= TERMKEY_KEYMOD_ALT; - (*nbytep)++; - break; - - case TERMKEY_RES_NONE: - case TERMKEY_RES_EOF: - case TERMKEY_RES_AGAIN: - case TERMKEY_RES_ERROR: - break; - } - - return metakey_result; - } - else if(b0 < 0xa0) { - // Single byte C0, G0 or C1 - C1 is never UTF-8 initial byte - (*tk->method.emit_codepoint)(tk, b0, key); - *nbytep = 1; - return TERMKEY_RES_KEY; - } - else if(tk->flags & TERMKEY_FLAG_UTF8) { - // Some UTF-8 - long codepoint; - TermKeyResult res = parse_utf8(tk->buffer + tk->buffstart, tk->buffcount, &codepoint, nbytep); - - if(res == TERMKEY_RES_AGAIN && force) { - /* There weren't enough bytes for a complete UTF-8 sequence but caller - * demands an answer. About the best thing we can do here is eat as many - * bytes as we have, and emit a UTF8_INVALID. If the remaining bytes - * arrive later, they'll be invalid too. - */ - codepoint = UTF8_INVALID; - *nbytep = tk->buffcount; - res = TERMKEY_RES_KEY; - } - - key->type = TERMKEY_TYPE_UNICODE; - key->modifiers = 0; - (*tk->method.emit_codepoint)(tk, codepoint, key); - return res; - } - else { - // Non UTF-8 case - just report the raw byte - key->type = TERMKEY_TYPE_UNICODE; - key->code.codepoint = b0; - key->modifiers = 0; - - key->utf8[0] = key->code.codepoint; - key->utf8[1] = 0; - - *nbytep = 1; - - return TERMKEY_RES_KEY; - } + if (tk->buffcount == 0) + return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE; + + unsigned char b0 = CHARAT(0); + if (b0 == 0x1b) + { + // Escape-prefixed value? Might therefore be Alt+key + if (tk->buffcount == 1) + { + // This might be an press, or it may want to be part of a longer + // sequence + if (!force) + return TERMKEY_RES_AGAIN; + + (*tk->method.emit_codepoint) (tk, b0, key); + *nbytep = 1; + return TERMKEY_RES_KEY; + } + + // Try another key there + tk->buffstart++; + tk->buffcount--; + + // Run the full driver + termkey_result_t metakey_result = peekkey (tk, key, force, nbytep); + + tk->buffstart--; + tk->buffcount++; + + switch (metakey_result) + { + case TERMKEY_RES_KEY: + key->modifiers |= TERMKEY_KEYMOD_ALT; + (*nbytep)++; + break; + + case TERMKEY_RES_NONE: + case TERMKEY_RES_EOF: + case TERMKEY_RES_AGAIN: + case TERMKEY_RES_ERROR: + break; + } + + return metakey_result; + } + else if (b0 < 0xa0) + { + // Single byte C0, G0 or C1 - C1 is never UTF-8 initial byte + (*tk->method.emit_codepoint) (tk, b0, key); + *nbytep = 1; + return TERMKEY_RES_KEY; + } + else if (tk->flags & TERMKEY_FLAG_UTF8) + { + // Some UTF-8 + long codepoint; + termkey_result_t res = parse_utf8 + (tk->buffer + tk->buffstart, tk->buffcount, &codepoint, nbytep); + + if (res == TERMKEY_RES_AGAIN && force) + { + /* There weren't enough bytes for a complete UTF-8 sequence but caller + * demands an answer. About the best thing we can do here is eat as many + * bytes as we have, and emit a UTF8_INVALID. If the remaining bytes + * arrive later, they'll be invalid too. + */ + codepoint = UTF8_INVALID; + *nbytep = tk->buffcount; + res = TERMKEY_RES_KEY; + } + + key->type = TERMKEY_TYPE_UNICODE; + key->modifiers = 0; + (*tk->method.emit_codepoint) (tk, codepoint, key); + return res; + } + else + { + // Non UTF-8 case - just report the raw byte + key->type = TERMKEY_TYPE_UNICODE; + key->code.codepoint = b0; + key->modifiers = 0; + + key->utf8[0] = key->code.codepoint; + key->utf8[1] = 0; + + *nbytep = 1; + return TERMKEY_RES_KEY; + } } -static TermKeyResult peekkey_mouse(TermKey *tk, TermKeyKey *key, size_t *nbytep) +static termkey_result_t +peekkey_mouse (termkey_t *tk, termkey_key_t *key, size_t *nbytep) { - if(tk->buffcount < 3) - return TERMKEY_RES_AGAIN; + if (tk->buffcount < 3) + return TERMKEY_RES_AGAIN; - key->type = TERMKEY_TYPE_MOUSE; - key->code.mouse[0] = CHARAT(0) - 0x20; - key->code.mouse[1] = CHARAT(1) - 0x20; - key->code.mouse[2] = CHARAT(2) - 0x20; - key->code.mouse[3] = 0; + key->type = TERMKEY_TYPE_MOUSE; + key->code.mouse[0] = CHARAT (0) - 0x20; + key->code.mouse[1] = CHARAT (1) - 0x20; + key->code.mouse[2] = CHARAT (2) - 0x20; + key->code.mouse[3] = 0; - key->modifiers = (key->code.mouse[0] & 0x1c) >> 2; - key->code.mouse[0] &= ~0x1c; + key->modifiers = (key->code.mouse[0] & 0x1c) >> 2; + key->code.mouse[0] &= ~0x1c; - *nbytep = 3; - return TERMKEY_RES_KEY; + *nbytep = 3; + return TERMKEY_RES_KEY; } -TermKeyResult termkey_getkey(TermKey *tk, TermKeyKey *key) +termkey_result_t +termkey_getkey (termkey_t *tk, termkey_key_t *key) { - size_t nbytes = 0; - TermKeyResult ret = peekkey(tk, key, 0, &nbytes); + size_t nbytes = 0; + termkey_result_t ret = peekkey (tk, key, 0, &nbytes); - if(ret == TERMKEY_RES_KEY) - eat_bytes(tk, nbytes); + if (ret == TERMKEY_RES_KEY) + eat_bytes (tk, nbytes); - if(ret == TERMKEY_RES_AGAIN) - /* Call peekkey() again in force mode to obtain whatever it can */ - (void)peekkey(tk, key, 1, &nbytes); - /* Don't eat it yet though */ + if(ret == TERMKEY_RES_AGAIN) + /* Call peekkey() again in force mode to obtain whatever it can */ + (void) peekkey (tk, key, 1, &nbytes); + /* Don't eat it yet though */ - return ret; + return ret; } -TermKeyResult termkey_getkey_force(TermKey *tk, TermKeyKey *key) +termkey_result_t +termkey_getkey_force (termkey_t *tk, termkey_key_t *key) { - size_t nbytes = 0; - TermKeyResult ret = peekkey(tk, key, 1, &nbytes); + size_t nbytes = 0; + termkey_result_t ret = peekkey (tk, key, 1, &nbytes); - if(ret == TERMKEY_RES_KEY) - eat_bytes(tk, nbytes); + if (ret == TERMKEY_RES_KEY) + eat_bytes (tk, nbytes); - return ret; + return ret; } -TermKeyResult termkey_waitkey(TermKey *tk, TermKeyKey *key) +termkey_result_t +termkey_waitkey (termkey_t *tk, termkey_key_t *key) { - if(tk->fd == -1) { - errno = EBADF; - return TERMKEY_RES_ERROR; - } - - while(1) { - TermKeyResult ret = termkey_getkey(tk, key); - - switch(ret) { - case TERMKEY_RES_KEY: - case TERMKEY_RES_EOF: - case TERMKEY_RES_ERROR: - return ret; - - case TERMKEY_RES_NONE: - ret = termkey_advisereadable(tk); - if(ret == TERMKEY_RES_ERROR) - return ret; - break; - - case TERMKEY_RES_AGAIN: - { - if(tk->is_closed) - // We're closed now. Never going to get more bytes so just go with - // what we have - return termkey_getkey_force(tk, key); - - struct pollfd fd; - + if (tk->fd == -1) + { + errno = EBADF; + return TERMKEY_RES_ERROR; + } + + while (1) + { + termkey_result_t ret = termkey_getkey (tk, key); + + switch (ret) + { + case TERMKEY_RES_KEY: + case TERMKEY_RES_EOF: + case TERMKEY_RES_ERROR: + return ret; + + case TERMKEY_RES_NONE: + ret = termkey_advisereadable (tk); + if (ret == TERMKEY_RES_ERROR) + return ret; + break; + + case TERMKEY_RES_AGAIN: + { + if (tk->is_closed) + // We're closed now. Never going to get more bytes + // so just go with what we have + return termkey_getkey_force (tk, key); + + struct pollfd fd; retry: - fd.fd = tk->fd; - fd.events = POLLIN; - - int pollret = poll(&fd, 1, tk->waittime); - if(pollret == -1) { - if(errno == EINTR && !(tk->flags & TERMKEY_FLAG_EINTR)) - goto retry; - - return TERMKEY_RES_ERROR; - } - - if(fd.revents & (POLLIN|POLLHUP|POLLERR)) - ret = termkey_advisereadable(tk); - else - ret = TERMKEY_RES_NONE; - - if(ret == TERMKEY_RES_ERROR) - return ret; - if(ret == TERMKEY_RES_NONE) - return termkey_getkey_force(tk, key); - } - break; - } - } - - /* UNREACHABLE */ + fd.fd = tk->fd; + fd.events = POLLIN; + + int pollret = poll (&fd, 1, tk->waittime); + if (pollret == -1) + { + if (errno == EINTR && !(tk->flags & TERMKEY_FLAG_EINTR)) + goto retry; + + return TERMKEY_RES_ERROR; + } + + if (fd.revents & (POLLIN|POLLHUP|POLLERR)) + ret = termkey_advisereadable (tk); + else + ret = TERMKEY_RES_NONE; + + if (ret == TERMKEY_RES_ERROR) + return ret; + if (ret == TERMKEY_RES_NONE) + return termkey_getkey_force (tk, key); + } + } + } + + /* UNREACHABLE */ } -TermKeyResult termkey_advisereadable(TermKey *tk) +termkey_result_t +termkey_advisereadable (termkey_t *tk) { - ssize_t len; - - if(tk->fd == -1) { - errno = EBADF; - return TERMKEY_RES_ERROR; - } - - if(tk->buffstart) { - memmove(tk->buffer, tk->buffer + tk->buffstart, tk->buffcount); - tk->buffstart = 0; - } - - /* Not expecting it ever to be greater but doesn't hurt to handle that */ - if(tk->buffcount >= tk->buffsize) { - errno = ENOMEM; - return TERMKEY_RES_ERROR; - } - + if (tk->fd == -1) + { + errno = EBADF; + return TERMKEY_RES_ERROR; + } + + if (tk->buffstart) + { + memmove (tk->buffer, tk->buffer + tk->buffstart, tk->buffcount); + tk->buffstart = 0; + } + + /* Not expecting it ever to be greater but doesn't hurt to handle that */ + if (tk->buffcount >= tk->buffsize) + { + errno = ENOMEM; + return TERMKEY_RES_ERROR; + } + + ssize_t len; retry: - len = read(tk->fd, tk->buffer + tk->buffcount, tk->buffsize - tk->buffcount); - - if(len == -1) { - if(errno == EAGAIN) - return TERMKEY_RES_NONE; - else if(errno == EINTR && !(tk->flags & TERMKEY_FLAG_EINTR)) - goto retry; - else - return TERMKEY_RES_ERROR; - } - else if(len < 1) { - tk->is_closed = 1; - return TERMKEY_RES_NONE; - } - else { - tk->buffcount += len; - return TERMKEY_RES_AGAIN; - } + len = read (tk->fd, tk->buffer + tk->buffcount, + tk->buffsize - tk->buffcount); + + if (len == -1) + { + if (errno == EAGAIN) + return TERMKEY_RES_NONE; + if (errno == EINTR && !(tk->flags & TERMKEY_FLAG_EINTR)) + goto retry; + return TERMKEY_RES_ERROR; + } + if (len < 1) + { + tk->is_closed = 1; + return TERMKEY_RES_NONE; + } + tk->buffcount += len; + return TERMKEY_RES_AGAIN; } -size_t termkey_push_bytes(TermKey *tk, const char *bytes, size_t len) +size_t +termkey_push_bytes (termkey_t *tk, const char *bytes, size_t len) { - if(tk->buffstart) { - memmove(tk->buffer, tk->buffer + tk->buffstart, tk->buffcount); - tk->buffstart = 0; - } - - /* Not expecting it ever to be greater but doesn't hurt to handle that */ - if(tk->buffcount >= tk->buffsize) { - errno = ENOMEM; - return (size_t)-1; - } - - if(len > tk->buffsize - tk->buffcount) - len = tk->buffsize - tk->buffcount; - - // memcpy(), not strncpy() in case of null bytes in input - memcpy(tk->buffer + tk->buffcount, bytes, len); - tk->buffcount += len; - - return len; + if (tk->buffstart) + { + memmove (tk->buffer, tk->buffer + tk->buffstart, tk->buffcount); + tk->buffstart = 0; + } + + /* Not expecting it ever to be greater but doesn't hurt to handle that */ + if (tk->buffcount >= tk->buffsize) + { + errno = ENOMEM; + return (size_t)-1; + } + + if (len > tk->buffsize - tk->buffcount) + len = tk->buffsize - tk->buffcount; + + // memcpy(), not strncpy() in case of null bytes in input + memcpy (tk->buffer + tk->buffcount, bytes, len); + tk->buffcount += len; + + return len; } -TermKeySym termkey_register_keyname(TermKey *tk, TermKeySym sym, const char *name) +termkey_sym_t +termkey_register_keyname (termkey_t *tk, termkey_sym_t sym, const char *name) { - if(!sym) - sym = tk->nkeynames; - - if(sym >= tk->nkeynames) { - const char **new_keynames = realloc(tk->keynames, sizeof(new_keynames[0]) * (sym + 1)); - if(!new_keynames) - return -1; + if (!sym) + sym = tk->nkeynames; - tk->keynames = new_keynames; + if (sym >= tk->nkeynames) + { + const char **new_keynames = + realloc (tk->keynames, sizeof new_keynames[0] * (sym + 1)); + if (!new_keynames) + return -1; - // Fill in the hole - for(int i = tk->nkeynames; i < sym; i++) - tk->keynames[i] = NULL; + tk->keynames = new_keynames; - tk->nkeynames = sym + 1; - } + // Fill in the hole + for (int i = tk->nkeynames; i < sym; i++) + tk->keynames[i] = NULL; - tk->keynames[sym] = name; + tk->nkeynames = sym + 1; + } - return sym; + tk->keynames[sym] = name; + return sym; } -const char *termkey_get_keyname(TermKey *tk, TermKeySym sym) +const char * +termkey_get_keyname (termkey_t *tk, termkey_sym_t sym) { - if(sym == TERMKEY_SYM_UNKNOWN) - return "UNKNOWN"; - - if(sym < tk->nkeynames) - return tk->keynames[sym]; - - return "UNKNOWN"; + if (sym == TERMKEY_SYM_UNKNOWN) + return "UNKNOWN"; + if (sym < tk->nkeynames) + return tk->keynames[sym]; + return "UNKNOWN"; } -static const char *termkey_lookup_keyname_format(TermKey *tk, const char *str, TermKeySym *sym, TermKeyFormat format) +static const char * +termkey_lookup_keyname_format (termkey_t *tk, + const char *str, termkey_sym_t *sym, termkey_format_t format) { - /* We store an array, so we can't do better than a linear search. Doesn't - * matter because user won't be calling this too often */ - - for(*sym = 0; *sym < tk->nkeynames; (*sym)++) { - const char *thiskey = tk->keynames[*sym]; - if(!thiskey) - continue; - size_t len = strlen(thiskey); - if(format & TERMKEY_FORMAT_LOWERSPACE) { - const char *thisstr = str; - if(strpncmp_camel(&thisstr, &thiskey, len) == 0) - return thisstr; - } - else { - if(strncmp(str, thiskey, len) == 0) - return (char *)str + len; - } - } - - return NULL; + /* We store an array, so we can't do better than a linear search. Doesn't + * matter because user won't be calling this too often */ + + for (*sym = 0; *sym < tk->nkeynames; (*sym)++) + { + const char *thiskey = tk->keynames[*sym]; + if (!thiskey) + continue; + size_t len = strlen (thiskey); + if (format & TERMKEY_FORMAT_LOWERSPACE) + { + const char *thisstr = str; + if (strpncmp_camel (&thisstr, &thiskey, len) == 0) + return thisstr; + } + else if (!strncmp (str, thiskey, len)) + return (char *) str + len; + } + return NULL; } -const char *termkey_lookup_keyname(TermKey *tk, const char *str, TermKeySym *sym) +const char * +termkey_lookup_keyname (termkey_t *tk, const char *str, termkey_sym_t *sym) { - return termkey_lookup_keyname_format(tk, str, sym, 0); + return termkey_lookup_keyname_format (tk, str, sym, 0); } -TermKeySym termkey_keyname2sym(TermKey *tk, const char *keyname) +termkey_sym_t +termkey_keyname2sym (termkey_t *tk, const char *keyname) { - TermKeySym sym; - const char *endp = termkey_lookup_keyname(tk, keyname, &sym); - if(!endp || endp[0]) - return TERMKEY_SYM_UNKNOWN; - return sym; + termkey_sym_t sym; + const char *endp = termkey_lookup_keyname (tk, keyname, &sym); + if (!endp || endp[0]) + return TERMKEY_SYM_UNKNOWN; + return sym; } -static TermKeySym register_c0(TermKey *tk, TermKeySym sym, unsigned char ctrl, const char *name) +static termkey_sym_t +register_c0 (termkey_t *tk, + termkey_sym_t sym, unsigned char ctrl, const char *name) { - return register_c0_full(tk, sym, 0, 0, ctrl, name); + return register_c0_full (tk, sym, 0, 0, ctrl, name); } -static TermKeySym register_c0_full(TermKey *tk, TermKeySym sym, int modifier_set, int modifier_mask, unsigned char ctrl, const char *name) +static termkey_sym_t +register_c0_full (termkey_t *tk, termkey_sym_t sym, + int modifier_set, int modifier_mask, unsigned char ctrl, const char *name) { - if(ctrl >= 0x20) { - errno = EINVAL; - return -1; - } - - if(name) - sym = termkey_register_keyname(tk, sym, name); - - tk->c0[ctrl].sym = sym; - tk->c0[ctrl].modifier_set = modifier_set; - tk->c0[ctrl].modifier_mask = modifier_mask; - - return sym; + if (ctrl >= 0x20) + { + errno = EINVAL; + return -1; + } + + if (name) + sym = termkey_register_keyname (tk, sym, name); + + tk->c0[ctrl].sym = sym; + tk->c0[ctrl].modifier_set = modifier_set; + tk->c0[ctrl].modifier_mask = modifier_mask; + return sym; } -/* Previous name for this function - * No longer declared in termkey.h but it remains in the compiled library for - * backward-compatibility reasons. - */ -size_t termkey_snprint_key(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, TermKeyFormat format) +static struct modnames { - return termkey_strfkey(tk, buffer, len, key, format); -} - -static struct modnames { - const char *shift, *alt, *ctrl; + const char *shift, *alt, *ctrl; } -modnames[] = { - { "S", "A", "C" }, // 0 - { "Shift", "Alt", "Ctrl" }, // LONGMOD - { "S", "M", "C" }, // ALTISMETA - { "Shift", "Meta", "Ctrl" }, // ALTISMETA+LONGMOD - { "s", "a", "c" }, // LOWERMOD - { "shift", "alt", "ctrl" }, // LOWERMOD+LONGMOD - { "s", "m", "c" }, // LOWERMOD+ALTISMETA - { "shift", "meta", "ctrl" }, // LOWERMOD+ALTISMETA+LONGMOD +modnames[] = +{ + { "S", "A", "C" }, // 0 + { "Shift", "Alt", "Ctrl" }, // LONGMOD + { "S", "M", "C" }, // ALTISMETA + { "Shift", "Meta", "Ctrl" }, // ALTISMETA+LONGMOD + { "s", "a", "c" }, // LOWERMOD + { "shift", "alt", "ctrl" }, // LOWERMOD+LONGMOD + { "s", "m", "c" }, // LOWERMOD+ALTISMETA + { "shift", "meta", "ctrl" }, // LOWERMOD+ALTISMETA+LONGMOD }; -size_t termkey_strfkey(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, TermKeyFormat format) +size_t +termkey_strfkey (termkey_t *tk, char *buffer, size_t len, + termkey_key_t *key, termkey_format_t format) { - size_t pos = 0; - size_t l = 0; - - struct modnames *mods = &modnames[!!(format & TERMKEY_FORMAT_LONGMOD) + - !!(format & TERMKEY_FORMAT_ALTISMETA) * 2 + - !!(format & TERMKEY_FORMAT_LOWERMOD) * 4]; - - int wrapbracket = (format & TERMKEY_FORMAT_WRAPBRACKET) && - (key->type != TERMKEY_TYPE_UNICODE || key->modifiers != 0); - - char sep = (format & TERMKEY_FORMAT_SPACEMOD) ? ' ' : '-'; - - if(format & TERMKEY_FORMAT_CARETCTRL && - key->type == TERMKEY_TYPE_UNICODE && - key->modifiers == TERMKEY_KEYMOD_CTRL) { - long codepoint = key->code.codepoint; - - // Handle some of the special casesfirst - if(codepoint >= 'a' && codepoint <= 'z') { - l = snprintf(buffer + pos, len - pos, wrapbracket ? "<^%c>" : "^%c", (char)codepoint - 0x20); - if(l <= 0) return pos; - pos += l; - return pos; - } - else if((codepoint >= '@' && codepoint < 'A') || - (codepoint > 'Z' && codepoint <= '_')) { - l = snprintf(buffer + pos, len - pos, wrapbracket ? "<^%c>" : "^%c", (char)codepoint); - if(l <= 0) return pos; - pos += l; - return pos; - } - } - - if(wrapbracket) { - l = snprintf(buffer + pos, len - pos, "<"); - if(l <= 0) return pos; - pos += l; - } - - if(key->modifiers & TERMKEY_KEYMOD_ALT) { - l = snprintf(buffer + pos, len - pos, "%s%c", mods->alt, sep); - if(l <= 0) return pos; - pos += l; - } - - if(key->modifiers & TERMKEY_KEYMOD_CTRL) { - l = snprintf(buffer + pos, len - pos, "%s%c", mods->ctrl, sep); - if(l <= 0) return pos; - pos += l; - } - - if(key->modifiers & TERMKEY_KEYMOD_SHIFT) { - l = snprintf(buffer + pos, len - pos, "%s%c", mods->shift, sep); - if(l <= 0) return pos; - pos += l; - } - - switch(key->type) { - case TERMKEY_TYPE_UNICODE: - if(!key->utf8[0]) // In case of user-supplied key structures - fill_utf8(key); - l = snprintf(buffer + pos, len - pos, "%s", key->utf8); - break; - case TERMKEY_TYPE_KEYSYM: - { - const char *name = termkey_get_keyname(tk, key->code.sym); - if(format & TERMKEY_FORMAT_LOWERSPACE) - l = snprint_cameltospaces(buffer + pos, len - pos, name); - else - l = snprintf(buffer + pos, len - pos, "%s", name); - } - break; - case TERMKEY_TYPE_FUNCTION: - l = snprintf(buffer + pos, len - pos, "%c%d", - (format & TERMKEY_FORMAT_LOWERSPACE ? 'f' : 'F'), key->code.number); - break; - case TERMKEY_TYPE_MOUSE: - { - TermKeyMouseEvent ev; - int button; - int line, col; - termkey_interpret_mouse(tk, key, &ev, &button, &line, &col); - - static const char *evnames[] = { "Unknown", "Press", "Drag", "Release" }; - - l = snprintf(buffer + pos, len - pos, "Mouse%s(%d)", - evnames[ev], button); - - if(format & TERMKEY_FORMAT_MOUSE_POS) { - if(l <= 0) return pos; - pos += l; - - l = snprintf(buffer + pos, len - pos, " @ (%u,%u)", col, line); - } - } - break; - case TERMKEY_TYPE_POSITION: - l = snprintf(buffer + pos, len - pos, "Position"); - break; - case TERMKEY_TYPE_MODEREPORT: - { - int initial, mode, value; - termkey_interpret_modereport(tk, key, &initial, &mode, &value); - if(initial) - l = snprintf(buffer + pos, len - pos, "Mode(%c%d=%d)", initial, mode, value); - else - l = snprintf(buffer + pos, len - pos, "Mode(%d=%d)", mode, value); - } - case TERMKEY_TYPE_UNKNOWN_CSI: - l = snprintf(buffer + pos, len - pos, "CSI %c", key->code.number & 0xff); - break; - } - - if(l <= 0) return pos; - pos += l; - - if(wrapbracket) { - l = snprintf(buffer + pos, len - pos, ">"); - if(l <= 0) return pos; - pos += l; - } - - return pos; + size_t pos = 0; + size_t l = 0; + + struct modnames *mods = &modnames[ + !!(format & TERMKEY_FORMAT_LONGMOD) + + !!(format & TERMKEY_FORMAT_ALTISMETA) * 2 + + !!(format & TERMKEY_FORMAT_LOWERMOD) * 4]; + + int wrapbracket = (format & TERMKEY_FORMAT_WRAPBRACKET) && + (key->type != TERMKEY_TYPE_UNICODE || key->modifiers != 0); + + char sep = (format & TERMKEY_FORMAT_SPACEMOD) ? ' ' : '-'; + + if (format & TERMKEY_FORMAT_CARETCTRL && + key->type == TERMKEY_TYPE_UNICODE && + key->modifiers == TERMKEY_KEYMOD_CTRL) + { + long codepoint = key->code.codepoint; + + // Handle some of the special casesfirst + if (codepoint >= 'a' && codepoint <= 'z') + { + l = snprintf (buffer + pos, len - pos, + wrapbracket ? "<^%c>" : "^%c", (char) codepoint - 0x20); + if (l <= 0) + return pos; + pos += l; + return pos; + } + else if ((codepoint >= '@' && codepoint < 'A') || + (codepoint > 'Z' && codepoint <= '_')) + { + l = snprintf (buffer + pos, len - pos, + wrapbracket ? "<^%c>" : "^%c", (char) codepoint); + if(l <= 0) + return pos; + pos += l; + return pos; + } + } + + if (wrapbracket) + { + l = snprintf (buffer + pos, len - pos, "<"); + if (l <= 0) + return pos; + pos += l; + } + + if (key->modifiers & TERMKEY_KEYMOD_ALT) + { + l = snprintf (buffer + pos, len - pos, "%s%c", mods->alt, sep); + if(l <= 0) + return pos; + pos += l; + } + if (key->modifiers & TERMKEY_KEYMOD_CTRL) + { + l = snprintf (buffer + pos, len - pos, "%s%c", mods->ctrl, sep); + if (l <= 0) + return pos; + pos += l; + } + if (key->modifiers & TERMKEY_KEYMOD_SHIFT) + { + l = snprintf (buffer + pos, len - pos, "%s%c", mods->shift, sep); + if (l <= 0) + return pos; + pos += l; + } + + switch (key->type) + { + case TERMKEY_TYPE_UNICODE: + if (!key->utf8[0]) // In case of user-supplied key structures + fill_utf8 (key); + l = snprintf (buffer + pos, len - pos, "%s", key->utf8); + break; + case TERMKEY_TYPE_KEYSYM: + { + const char *name = termkey_get_keyname (tk, key->code.sym); + if (format & TERMKEY_FORMAT_LOWERSPACE) + l = snprint_cameltospaces (buffer + pos, len - pos, name); + else + l = snprintf (buffer + pos, len - pos, "%s", name); + break; + } + case TERMKEY_TYPE_FUNCTION: + l = snprintf (buffer + pos, len - pos, "%c%d", + (format & TERMKEY_FORMAT_LOWERSPACE ? 'f' : 'F'), key->code.number); + break; + case TERMKEY_TYPE_MOUSE: + { + termkey_mouse_event_t ev; + int button; + int line, col; + termkey_interpret_mouse (tk, key, &ev, &button, &line, &col); + + static const char *evnames[] = + { "Unknown", "Press", "Drag", "Release" }; + l = snprintf(buffer + pos, len - pos, + "Mouse%s(%d)", evnames[ev], button); + if (format & TERMKEY_FORMAT_MOUSE_POS) + { + if (l <= 0) + return pos; + pos += l; + l = snprintf (buffer + pos, len - pos, " @ (%u,%u)", col, line); + } + break; + } + case TERMKEY_TYPE_POSITION: + l = snprintf (buffer + pos, len - pos, "Position"); + break; + case TERMKEY_TYPE_MODEREPORT: + { + int initial, mode, value; + termkey_interpret_modereport (tk, key, &initial, &mode, &value); + if (initial) + l = snprintf (buffer + pos, len - pos, + "Mode(%c%d=%d)", initial, mode, value); + else + l = snprintf (buffer + pos, len - pos, + "Mode(%d=%d)", mode, value); + // XXX: should this fall through? + } + case TERMKEY_TYPE_UNKNOWN_CSI: + l = snprintf (buffer + pos, len - pos, + "CSI %c", key->code.number & 0xff); + break; + } + + if (l <= 0) + return pos; + pos += l; + + if (wrapbracket) + { + l = snprintf (buffer + pos, len - pos, ">"); + if (l <= 0) + return pos; + pos += l; + } + return pos; } -const char *termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermKeyFormat format) +const char * +termkey_strpkey (termkey_t *tk, + const char *str, termkey_key_t *key, termkey_format_t format) { - struct modnames *mods = &modnames[!!(format & TERMKEY_FORMAT_LONGMOD) + - !!(format & TERMKEY_FORMAT_ALTISMETA) * 2 + - !!(format & TERMKEY_FORMAT_LOWERMOD) * 4]; - - key->modifiers = 0; - - if((format & TERMKEY_FORMAT_CARETCTRL) && str[0] == '^' && str[1]) { - str = 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(key->code.codepoint >= 'A' && key->code.codepoint <= 'Z') - key->code.codepoint += 0x20; - key->modifiers = TERMKEY_KEYMOD_CTRL; - fill_utf8(key); - return (char *)str; - } - - const char *sep_at; - - while((sep_at = strchr(str, (format & TERMKEY_FORMAT_SPACEMOD) ? ' ' : '-'))) { - size_t n = sep_at - str; - - if(n == strlen(mods->alt) && strncmp(mods->alt, str, n) == 0) - key->modifiers |= TERMKEY_KEYMOD_ALT; - else if(n == strlen(mods->ctrl) && strncmp(mods->ctrl, str, n) == 0) - key->modifiers |= TERMKEY_KEYMOD_CTRL; - else if(n == strlen(mods->shift) && strncmp(mods->shift, str, n) == 0) - key->modifiers |= TERMKEY_KEYMOD_SHIFT; - - else - break; - - str = sep_at + 1; - } - - size_t nbytes; - ssize_t snbytes; - const char *endstr; - - if((endstr = termkey_lookup_keyname_format(tk, str, &key->code.sym, format))) { - key->type = TERMKEY_TYPE_KEYSYM; - str = endstr; - } - else if(sscanf(str, "F%d%zn", &key->code.number, &snbytes) == 1) { - key->type = TERMKEY_TYPE_FUNCTION; - str += snbytes; - } - // Unicode must be last - else if(parse_utf8((unsigned const char *)str, strlen(str), &key->code.codepoint, &nbytes) == TERMKEY_RES_KEY) { - key->type = TERMKEY_TYPE_UNICODE; - fill_utf8(key); - str += nbytes; - } - // TODO: Consider mouse events? - else - return NULL; - - termkey_canonicalise(tk, key); - - return (char *)str; + struct modnames *mods = &modnames[ + !!(format & TERMKEY_FORMAT_LONGMOD) + + !!(format & TERMKEY_FORMAT_ALTISMETA) * 2 + + !!(format & TERMKEY_FORMAT_LOWERMOD) * 4]; + + key->modifiers = 0; + + if ((format & TERMKEY_FORMAT_CARETCTRL) && str[0] == '^' && str[1]) + { + str = 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 (key->code.codepoint >= 'A' && key->code.codepoint <= 'Z') + key->code.codepoint += 0x20; + key->modifiers = TERMKEY_KEYMOD_CTRL; + fill_utf8 (key); + return (char *) str; + } + + const char *sep_at; + while ((sep_at = strchr (str, + (format & TERMKEY_FORMAT_SPACEMOD) ? ' ' : '-'))) + { + size_t n = sep_at - str; + + if (n == strlen (mods->alt) && !strncmp (mods->alt, str, n)) + key->modifiers |= TERMKEY_KEYMOD_ALT; + else if (n == strlen (mods->ctrl) && !strncmp (mods->ctrl, str, n)) + key->modifiers |= TERMKEY_KEYMOD_CTRL; + else if (n == strlen (mods->shift) && !strncmp (mods->shift, str, n)) + key->modifiers |= TERMKEY_KEYMOD_SHIFT; + else + break; + + str = sep_at + 1; + } + + size_t nbytes; + ssize_t snbytes; + const char *endstr; + + if ((endstr = termkey_lookup_keyname_format + (tk, str, &key->code.sym, format))) + { + key->type = TERMKEY_TYPE_KEYSYM; + str = endstr; + } + // FIXME: sscanf + else if (sscanf(str, "F%d%zn", &key->code.number, &snbytes) == 1) + { + key->type = TERMKEY_TYPE_FUNCTION; + str += snbytes; + } + // Unicode must be last + else if (parse_utf8 ((unsigned const char *) str, strlen (str), + &key->code.codepoint, &nbytes) == TERMKEY_RES_KEY) + { + key->type = TERMKEY_TYPE_UNICODE; + fill_utf8 (key); + str += nbytes; + } + // TODO: Consider mouse events? + else + return NULL; + + termkey_canonicalise (tk, key); + return (char *) str; } -int termkey_keycmp(TermKey *tk, const TermKeyKey *key1p, const TermKeyKey *key2p) +int +termkey_keycmp (termkey_t *tk, + const termkey_key_t *key1p, const termkey_key_t *key2p) { - /* Copy the key structs since we'll be modifying them */ - TermKeyKey key1 = *key1p, key2 = *key2p; - - termkey_canonicalise(tk, &key1); - termkey_canonicalise(tk, &key2); - - if(key1.type != key2.type) - return key1.type - key2.type; - - switch(key1.type) { - case TERMKEY_TYPE_UNICODE: - if(key1.code.codepoint != key2.code.codepoint) - return key1.code.codepoint - key2.code.codepoint; - break; - case TERMKEY_TYPE_KEYSYM: - if(key1.code.sym != key2.code.sym) - return key1.code.sym - key2.code.sym; - break; - case TERMKEY_TYPE_FUNCTION: - case TERMKEY_TYPE_UNKNOWN_CSI: - if(key1.code.number != key2.code.number) - return key1.code.number - key2.code.number; - break; - case TERMKEY_TYPE_MOUSE: - { - int cmp = strncmp(key1.code.mouse, key2.code.mouse, 4); - if(cmp != 0) - return cmp; - } - break; - case TERMKEY_TYPE_POSITION: - { - int line1, col1, line2, col2; - termkey_interpret_position(tk, &key1, &line1, &col1); - termkey_interpret_position(tk, &key2, &line2, &col2); - if(line1 != line2) - return line1 - line2; - return col1 - col2; - } - break; - case TERMKEY_TYPE_MODEREPORT: - { - int initial1, initial2, mode1, mode2, value1, value2; - termkey_interpret_modereport(tk, &key1, &initial1, &mode1, &value1); - termkey_interpret_modereport(tk, &key2, &initial2, &mode2, &value2); - if(initial1 != initial2) - return initial1 - initial2; - if(mode1 != mode2) - return mode1 - mode2; - return value1 - value2; - } - } - - return key1.modifiers - key2.modifiers; + /* Copy the key structs since we'll be modifying them */ + termkey_key_t key1 = *key1p, key2 = *key2p; + + termkey_canonicalise (tk, &key1); + termkey_canonicalise (tk, &key2); + + if (key1.type != key2.type) + return key1.type - key2.type; + + switch (key1.type) + { + case TERMKEY_TYPE_UNICODE: + if (key1.code.codepoint != key2.code.codepoint) + return key1.code.codepoint - key2.code.codepoint; + break; + case TERMKEY_TYPE_KEYSYM: + if (key1.code.sym != key2.code.sym) + return key1.code.sym - key2.code.sym; + break; + case TERMKEY_TYPE_FUNCTION: + case TERMKEY_TYPE_UNKNOWN_CSI: + if (key1.code.number != key2.code.number) + return key1.code.number - key2.code.number; + break; + case TERMKEY_TYPE_MOUSE: + { + int cmp = strncmp (key1.code.mouse, key2.code.mouse, 4); + if (cmp != 0) + return cmp; + break; + } + case TERMKEY_TYPE_POSITION: + { + int line1, col1, line2, col2; + termkey_interpret_position (tk, &key1, &line1, &col1); + termkey_interpret_position (tk, &key2, &line2, &col2); + if (line1 != line2) + return line1 - line2; + return col1 - col2; + } + case TERMKEY_TYPE_MODEREPORT: + { + int initial1, initial2, mode1, mode2, value1, value2; + termkey_interpret_modereport (tk, &key1, &initial1, &mode1, &value1); + termkey_interpret_modereport (tk, &key2, &initial2, &mode2, &value2); + if (initial1 != initial2) + return initial1 - initial2; + if (mode1 != mode2) + return mode1 - mode2; + return value1 - value2; + } + } + + return key1.modifiers - key2.modifiers; } + diff --git a/termkey.h.in b/termkey.h.in index 87c5e5b..e621eab 100644 --- a/termkey.h.in +++ b/termkey.h.in @@ -1,240 +1,258 @@ -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef GUARD_TERMKEY_H_ -#define GUARD_TERMKEY_H_ +#ifndef TERMKEY_H +#define TERMKEY_H #include #include +#include #define TERMKEY_VERSION_MAJOR @@VERSION_MAJOR@@ #define TERMKEY_VERSION_MINOR @@VERSION_MINOR@@ #define TERMKEY_CHECK_VERSION \ - termkey_check_version(TERMKEY_VERSION_MAJOR, TERMKEY_VERSION_MINOR) - -typedef enum { - TERMKEY_SYM_UNKNOWN = -1, - TERMKEY_SYM_NONE = 0, - - /* Special names in C0 */ - TERMKEY_SYM_BACKSPACE, - TERMKEY_SYM_TAB, - TERMKEY_SYM_ENTER, - TERMKEY_SYM_ESCAPE, - - /* Special names in G0 */ - TERMKEY_SYM_SPACE, - TERMKEY_SYM_DEL, - - /* Special keys */ - TERMKEY_SYM_UP, - TERMKEY_SYM_DOWN, - TERMKEY_SYM_LEFT, - TERMKEY_SYM_RIGHT, - TERMKEY_SYM_BEGIN, - TERMKEY_SYM_FIND, - TERMKEY_SYM_INSERT, - TERMKEY_SYM_DELETE, - TERMKEY_SYM_SELECT, - TERMKEY_SYM_PAGEUP, - TERMKEY_SYM_PAGEDOWN, - TERMKEY_SYM_HOME, - TERMKEY_SYM_END, - - /* Special keys from terminfo */ - TERMKEY_SYM_CANCEL, - TERMKEY_SYM_CLEAR, - TERMKEY_SYM_CLOSE, - TERMKEY_SYM_COMMAND, - TERMKEY_SYM_COPY, - TERMKEY_SYM_EXIT, - TERMKEY_SYM_HELP, - TERMKEY_SYM_MARK, - TERMKEY_SYM_MESSAGE, - TERMKEY_SYM_MOVE, - TERMKEY_SYM_OPEN, - TERMKEY_SYM_OPTIONS, - TERMKEY_SYM_PRINT, - TERMKEY_SYM_REDO, - TERMKEY_SYM_REFERENCE, - TERMKEY_SYM_REFRESH, - TERMKEY_SYM_REPLACE, - TERMKEY_SYM_RESTART, - TERMKEY_SYM_RESUME, - TERMKEY_SYM_SAVE, - TERMKEY_SYM_SUSPEND, - TERMKEY_SYM_UNDO, - - /* Numeric keypad special keys */ - TERMKEY_SYM_KP0, - TERMKEY_SYM_KP1, - TERMKEY_SYM_KP2, - TERMKEY_SYM_KP3, - TERMKEY_SYM_KP4, - TERMKEY_SYM_KP5, - TERMKEY_SYM_KP6, - TERMKEY_SYM_KP7, - TERMKEY_SYM_KP8, - TERMKEY_SYM_KP9, - TERMKEY_SYM_KPENTER, - TERMKEY_SYM_KPPLUS, - TERMKEY_SYM_KPMINUS, - TERMKEY_SYM_KPMULT, - TERMKEY_SYM_KPDIV, - TERMKEY_SYM_KPCOMMA, - TERMKEY_SYM_KPPERIOD, - TERMKEY_SYM_KPEQUALS, - - /* et cetera ad nauseum */ - TERMKEY_N_SYMS -} TermKeySym; - -typedef enum { - TERMKEY_TYPE_UNICODE, - TERMKEY_TYPE_FUNCTION, - TERMKEY_TYPE_KEYSYM, - TERMKEY_TYPE_MOUSE, - TERMKEY_TYPE_POSITION, - TERMKEY_TYPE_MODEREPORT, - /* add other recognised types here */ - - TERMKEY_TYPE_UNKNOWN_CSI = -1 -} TermKeyType; - -typedef enum { - TERMKEY_RES_NONE, - TERMKEY_RES_KEY, - TERMKEY_RES_EOF, - TERMKEY_RES_AGAIN, - TERMKEY_RES_ERROR -} TermKeyResult; - -typedef enum { - TERMKEY_MOUSE_UNKNOWN, - TERMKEY_MOUSE_PRESS, - TERMKEY_MOUSE_DRAG, - TERMKEY_MOUSE_RELEASE -} TermKeyMouseEvent; - -enum { - TERMKEY_KEYMOD_SHIFT = 1 << 0, - TERMKEY_KEYMOD_ALT = 1 << 1, - TERMKEY_KEYMOD_CTRL = 1 << 2 + termkey_check_version (TERMKEY_VERSION_MAJOR, TERMKEY_VERSION_MINOR) + +typedef enum termkey_sym termkey_sym_t; +enum termkey_sym +{ + TERMKEY_SYM_UNKNOWN = -1, + TERMKEY_SYM_NONE = 0, + + /* Special names in C0 */ + TERMKEY_SYM_BACKSPACE, + TERMKEY_SYM_TAB, + TERMKEY_SYM_ENTER, + TERMKEY_SYM_ESCAPE, + + /* Special names in G0 */ + TERMKEY_SYM_SPACE, + TERMKEY_SYM_DEL, + + /* Special keys */ + TERMKEY_SYM_UP, + TERMKEY_SYM_DOWN, + TERMKEY_SYM_LEFT, + TERMKEY_SYM_RIGHT, + TERMKEY_SYM_BEGIN, + TERMKEY_SYM_FIND, + TERMKEY_SYM_INSERT, + TERMKEY_SYM_DELETE, + TERMKEY_SYM_SELECT, + TERMKEY_SYM_PAGEUP, + TERMKEY_SYM_PAGEDOWN, + TERMKEY_SYM_HOME, + TERMKEY_SYM_END, + + /* Special keys from terminfo */ + TERMKEY_SYM_CANCEL, + TERMKEY_SYM_CLEAR, + TERMKEY_SYM_CLOSE, + TERMKEY_SYM_COMMAND, + TERMKEY_SYM_COPY, + TERMKEY_SYM_EXIT, + TERMKEY_SYM_HELP, + TERMKEY_SYM_MARK, + TERMKEY_SYM_MESSAGE, + TERMKEY_SYM_MOVE, + TERMKEY_SYM_OPEN, + TERMKEY_SYM_OPTIONS, + TERMKEY_SYM_PRINT, + TERMKEY_SYM_REDO, + TERMKEY_SYM_REFERENCE, + TERMKEY_SYM_REFRESH, + TERMKEY_SYM_REPLACE, + TERMKEY_SYM_RESTART, + TERMKEY_SYM_RESUME, + TERMKEY_SYM_SAVE, + TERMKEY_SYM_SUSPEND, + TERMKEY_SYM_UNDO, + + /* Numeric keypad special keys */ + TERMKEY_SYM_KP0, + TERMKEY_SYM_KP1, + TERMKEY_SYM_KP2, + TERMKEY_SYM_KP3, + TERMKEY_SYM_KP4, + TERMKEY_SYM_KP5, + TERMKEY_SYM_KP6, + TERMKEY_SYM_KP7, + TERMKEY_SYM_KP8, + TERMKEY_SYM_KP9, + TERMKEY_SYM_KPENTER, + TERMKEY_SYM_KPPLUS, + TERMKEY_SYM_KPMINUS, + TERMKEY_SYM_KPMULT, + TERMKEY_SYM_KPDIV, + TERMKEY_SYM_KPCOMMA, + TERMKEY_SYM_KPPERIOD, + TERMKEY_SYM_KPEQUALS, + + TERMKEY_N_SYMS }; -typedef struct { - TermKeyType type; - union { - long codepoint; /* TERMKEY_TYPE_UNICODE */ - int number; /* TERMKEY_TYPE_FUNCTION */ - TermKeySym sym; /* TERMKEY_TYPE_KEYSYM */ - char mouse[4]; /* TERMKEY_TYPE_MOUSE */ - /* opaque. see termkey_interpret_mouse */ - } code; - - int modifiers; - - /* Any Unicode character can be UTF-8 encoded in no more than 6 bytes, plus - * terminating NUL */ - char utf8[7]; -} TermKeyKey; - -typedef struct TermKey TermKey; - -enum { - TERMKEY_FLAG_NOINTERPRET = 1 << 0, /* Do not interpret C0//DEL codes if possible */ - TERMKEY_FLAG_CONVERTKP = 1 << 1, /* Convert KP codes to regular keypresses */ - TERMKEY_FLAG_RAW = 1 << 2, /* Input is raw bytes, not UTF-8 */ - TERMKEY_FLAG_UTF8 = 1 << 3, /* Input is definitely UTF-8 */ - TERMKEY_FLAG_NOTERMIOS = 1 << 4, /* Do not make initial termios calls on construction */ - TERMKEY_FLAG_SPACESYMBOL = 1 << 5, /* Sets TERMKEY_CANON_SPACESYMBOL */ - TERMKEY_FLAG_CTRLC = 1 << 6, /* Allow Ctrl-C to be read as normal, disabling SIGINT */ - TERMKEY_FLAG_EINTR = 1 << 7 /* Return ERROR on signal (EINTR) rather than retry */ +typedef enum termkey_type termkey_type_t; +enum termkey_type +{ + TERMKEY_TYPE_UNICODE, + TERMKEY_TYPE_FUNCTION, + TERMKEY_TYPE_KEYSYM, + TERMKEY_TYPE_MOUSE, + TERMKEY_TYPE_POSITION, + TERMKEY_TYPE_MODEREPORT, + /* add other recognised types here */ + + TERMKEY_TYPE_UNKNOWN_CSI = -1 }; -enum { - TERMKEY_CANON_SPACESYMBOL = 1 << 0, /* Space is symbolic rather than Unicode */ - TERMKEY_CANON_DELBS = 1 << 1 /* Del is converted to Backspace */ +typedef enum termkey_result termkey_result_t; +enum termkey_result +{ + TERMKEY_RES_NONE, + TERMKEY_RES_KEY, + TERMKEY_RES_EOF, + TERMKEY_RES_AGAIN, + TERMKEY_RES_ERROR }; -void termkey_check_version(int major, int minor); +typedef enum termkey_mouse_event termkey_mouse_event_t; +enum termkey_mouse_event +{ + TERMKEY_MOUSE_UNKNOWN, + TERMKEY_MOUSE_PRESS, + TERMKEY_MOUSE_DRAG, + TERMKEY_MOUSE_RELEASE +}; -TermKey *termkey_new(int fd, int flags); -TermKey *termkey_new_abstract(const char *term, int flags); -void termkey_free(TermKey *tk); -void termkey_destroy(TermKey *tk); +enum +{ + TERMKEY_KEYMOD_SHIFT = 1 << 0, + TERMKEY_KEYMOD_ALT = 1 << 1, + TERMKEY_KEYMOD_CTRL = 1 << 2 +}; -int termkey_start(TermKey *tk); -int termkey_stop(TermKey *tk); -int termkey_is_started(TermKey *tk); +typedef struct termkey_key termkey_key_t; +struct termkey_key +{ + termkey_type_t type; + union + { + long codepoint; /* TERMKEY_TYPE_UNICODE */ + int number; /* TERMKEY_TYPE_FUNCTION */ + termkey_sym_t sym; /* TERMKEY_TYPE_KEYSYM */ + char mouse[4]; /* TERMKEY_TYPE_MOUSE */ + /* opaque, see termkey_interpret_mouse() */ + } code; + + int modifiers; + + /* The raw multibyte sequence for the key */ + char utf8[MB_LEN_MAX + 1]; +}; -int termkey_get_fd(TermKey *tk); +typedef struct termkey termkey_t; + +enum +{ + TERMKEY_FLAG_NOINTERPRET = 1 << 0, /* Do not interpret C0//DEL codes if possible */ + TERMKEY_FLAG_CONVERTKP = 1 << 1, /* Convert KP codes to regular keypresses */ + TERMKEY_FLAG_RAW = 1 << 2, /* Input is raw bytes, not UTF-8 */ + TERMKEY_FLAG_UTF8 = 1 << 3, /* Input is definitely UTF-8 */ + TERMKEY_FLAG_NOTERMIOS = 1 << 4, /* Do not make initial termios calls on construction */ + TERMKEY_FLAG_SPACESYMBOL = 1 << 5, /* Sets TERMKEY_CANON_SPACESYMBOL */ + TERMKEY_FLAG_CTRLC = 1 << 6, /* Allow Ctrl-C to be read as normal, disabling SIGINT */ + TERMKEY_FLAG_EINTR = 1 << 7 /* Return ERROR on signal (EINTR) rather than retry */ +}; -int termkey_get_flags(TermKey *tk); -void termkey_set_flags(TermKey *tk, int newflags); +enum +{ + TERMKEY_CANON_SPACESYMBOL = 1 << 0, /* Space is symbolic rather than Unicode */ + TERMKEY_CANON_DELBS = 1 << 1 /* Del is converted to Backspace */ +}; + +void termkey_check_version (int major, int minor); -int termkey_get_waittime(TermKey *tk); -void termkey_set_waittime(TermKey *tk, int msec); +termkey_t *termkey_new (int fd, int flags); +termkey_t *termkey_new_abstract (const char *term, int flags); +void termkey_free (termkey_t *tk); +void termkey_destroy (termkey_t *tk); -int termkey_get_canonflags(TermKey *tk); -void termkey_set_canonflags(TermKey *tk, int); +int termkey_start (termkey_t *tk); +int termkey_stop (termkey_t *tk); +int termkey_is_started (termkey_t *tk); -size_t termkey_get_buffer_size(TermKey *tk); -int termkey_set_buffer_size(TermKey *tk, size_t size); +int termkey_get_fd (termkey_t *tk); -size_t termkey_get_buffer_remaining(TermKey *tk); +int termkey_get_flags (termkey_t *tk); +void termkey_set_flags (termkey_t *tk, int newflags); -void termkey_canonicalise(TermKey *tk, TermKeyKey *key); +int termkey_get_waittime (termkey_t *tk); +void termkey_set_waittime (termkey_t *tk, int msec); -TermKeyResult termkey_getkey(TermKey *tk, TermKeyKey *key); -TermKeyResult termkey_getkey_force(TermKey *tk, TermKeyKey *key); -TermKeyResult termkey_waitkey(TermKey *tk, TermKeyKey *key); +int termkey_get_canonflags (termkey_t *tk); +void termkey_set_canonflags (termkey_t *tk, int flags); -TermKeyResult termkey_advisereadable(TermKey *tk); +size_t termkey_get_buffer_size (termkey_t *tk); +int termkey_set_buffer_size (termkey_t *tk, size_t size); -size_t termkey_push_bytes(TermKey *tk, const char *bytes, size_t len); +size_t termkey_get_buffer_remaining (termkey_t *tk); -TermKeySym termkey_register_keyname(TermKey *tk, TermKeySym sym, const char *name); -const char *termkey_get_keyname(TermKey *tk, TermKeySym sym); -const char *termkey_lookup_keyname(TermKey *tk, const char *str, TermKeySym *sym); +void termkey_canonicalise (termkey_t *tk, termkey_key_t *key); -TermKeySym termkey_keyname2sym(TermKey *tk, const char *keyname); +termkey_result_t termkey_getkey (termkey_t *tk, termkey_key_t *key); +termkey_result_t termkey_getkey_force (termkey_t *tk, termkey_key_t *key); +termkey_result_t termkey_waitkey (termkey_t *tk, termkey_key_t *key); -TermKeyResult termkey_interpret_mouse(TermKey *tk, const TermKeyKey *key, TermKeyMouseEvent *event, int *button, int *line, int *col); +termkey_result_t termkey_advisereadable (termkey_t *tk); -TermKeyResult termkey_interpret_position(TermKey *tk, const TermKeyKey *key, int *line, int *col); +size_t termkey_push_bytes (termkey_t *tk, const char *bytes, size_t len); -TermKeyResult termkey_interpret_modereport(TermKey *tk, const TermKeyKey *key, int *initial, int *mode, int *value); +termkey_sym_t termkey_register_keyname (termkey_t *tk, + termkey_sym_t sym, const char *name); +const char *termkey_get_keyname (termkey_t *tk, termkey_sym_t sym); +const char *termkey_lookup_keyname (termkey_t *tk, + const char *str, termkey_sym_t *sym); -TermKeyResult termkey_interpret_csi(TermKey *tk, const TermKeyKey *key, long args[], size_t *nargs, unsigned long *cmd); +termkey_sym_t termkey_keyname2sym (termkey_t *tk, const char *keyname); -typedef enum { - TERMKEY_FORMAT_LONGMOD = 1 << 0, /* Shift-... instead of S-... */ - TERMKEY_FORMAT_CARETCTRL = 1 << 1, /* ^X instead of C-X */ - TERMKEY_FORMAT_ALTISMETA = 1 << 2, /* Meta- or M- instead of Alt- or A- */ - TERMKEY_FORMAT_WRAPBRACKET = 1 << 3, /* Wrap special keys in brackets like */ - TERMKEY_FORMAT_SPACEMOD = 1 << 4, /* M Foo instead of M-Foo */ - TERMKEY_FORMAT_LOWERMOD = 1 << 5, /* meta or m instead of Meta or M */ - TERMKEY_FORMAT_LOWERSPACE = 1 << 6, /* page down instead of PageDown */ +termkey_result_t termkey_interpret_mouse (termkey_t *tk, + const termkey_key_t *key, termkey_mouse_event_t *event, + int *button, int *line, int *col); +termkey_result_t termkey_interpret_position (termkey_t *tk, + const termkey_key_t *key, int *line, int *col); +termkey_result_t termkey_interpret_modereport (termkey_t *tk, + const termkey_key_t *key, int *initial, int *mode, int *value); +termkey_result_t termkey_interpret_csi (termkey_t *tk, + const termkey_key_t *key, long args[], size_t *nargs, unsigned long *cmd); - TERMKEY_FORMAT_MOUSE_POS = 1 << 8 /* Include mouse position if relevant; @ col,line */ -} TermKeyFormat; +typedef enum termkey_format termkey_format_t; +enum termkey_format +{ + TERMKEY_FORMAT_LONGMOD = 1 << 0, /* Shift-... instead of S-... */ + TERMKEY_FORMAT_CARETCTRL = 1 << 1, /* ^X instead of C-X */ + TERMKEY_FORMAT_ALTISMETA = 1 << 2, /* Meta- or M- instead of Alt- or A- */ + TERMKEY_FORMAT_WRAPBRACKET = 1 << 3, /* Wrap special keys in brackets like */ + TERMKEY_FORMAT_SPACEMOD = 1 << 4, /* M Foo instead of M-Foo */ + TERMKEY_FORMAT_LOWERMOD = 1 << 5, /* meta or m instead of Meta or M */ + TERMKEY_FORMAT_LOWERSPACE = 1 << 6, /* page down instead of PageDown */ + + TERMKEY_FORMAT_MOUSE_POS = 1 << 8 /* Include mouse position if relevant; @ col,line */ +}; /* Some useful combinations */ -#define TERMKEY_FORMAT_VIM (TermKeyFormat)(TERMKEY_FORMAT_ALTISMETA|TERMKEY_FORMAT_WRAPBRACKET) -#define TERMKEY_FORMAT_URWID (TermKeyFormat)(TERMKEY_FORMAT_LONGMOD|TERMKEY_FORMAT_ALTISMETA| \ - TERMKEY_FORMAT_LOWERMOD|TERMKEY_FORMAT_SPACEMOD|TERMKEY_FORMAT_LOWERSPACE) +#define TERMKEY_FORMAT_VIM (termkey_format_t) \ + (TERMKEY_FORMAT_ALTISMETA | TERMKEY_FORMAT_WRAPBRACKET) +#define TERMKEY_FORMAT_URWID (termkey_format_t) \ + (TERMKEY_FORMAT_LONGMOD | TERMKEY_FORMAT_ALTISMETA | \ + TERMKEY_FORMAT_LOWERMOD | TERMKEY_FORMAT_SPACEMOD | \ + TERMKEY_FORMAT_LOWERSPACE) -size_t termkey_strfkey(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, TermKeyFormat format); -const char *termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermKeyFormat format); +size_t termkey_strfkey (termkey_t *tk, char *buffer, size_t len, + termkey_key_t *key, termkey_format_t format); +const char *termkey_strpkey (termkey_t *tk, const char *str, + termkey_key_t *key, termkey_format_t format); -int termkey_keycmp(TermKey *tk, const TermKeyKey *key1, const TermKeyKey *key2); +int termkey_keycmp (termkey_t *tk, + const termkey_key_t *key1, const termkey_key_t *key2); -#endif +#endif // ! TERMKEY_H -#ifdef __cplusplus -} -#endif -- cgit v1.2.3-70-g09d2