From f26667d117af5a119471eb531f3ded65b9c1fbc8 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Sat, 1 Feb 2014 15:00:00 +1000 Subject: Better method to tell if it's ordinary characters, and deal with partial reads better. --- boxes.c | 27 ++++++++++++++++++--------- dumbsh.c | 25 ++++++++++++++----------- handlekeys.c | 15 +++------------ handlekeys.h | 16 +++++++++++----- 4 files changed, 46 insertions(+), 37 deletions(-) diff --git a/boxes.c b/boxes.c index c2bc226..c0dcffe 100644 --- a/boxes.c +++ b/boxes.c @@ -1662,12 +1662,12 @@ static void handleCSI(long extra, char *command, int *params, int count) } } - -static int handleKeySequence(long extra, char *sequence) +// Callback for incoming key sequences from the user. +static int handleKeySequence(long extra, char *sequence, int isTranslated) { struct _view *view = (struct _view *) extra; // Though we pretty much stomp on this straight away. struct keyCommand *commands = currentBox->view->content->context->modes[currentBox->view->mode].keys; - int j; + int j, l = strlen(sequence); // Coz things might change out from under us, find the current view. if (commandMode) view = commandLine; @@ -1676,14 +1676,23 @@ static int handleKeySequence(long extra, char *sequence) // Search for a key sequence bound to a command. for (j = 0; commands[j].key; j++) { - if (strcmp(commands[j].key, sequence) == 0) + if (strncmp(commands[j].key, sequence, l) == 0) { - doCommand(view, commands[j].command); - return 1; + // If it's a partial match, keep accumulating them. + if (strlen(commands[j].key) != l) + return 0; + else + { + doCommand(view, commands[j].command); + return 1; + } } } - if ((0 == sequence[1]) && isprint(sequence[0])) // See if it's an ordinary key. + // See if it's ordinary keys. + // NOTE - with vi style ordinary keys can be commands, + // but they would be found by the command check above first. + if (!isTranslated) { // TODO - Should check for tabs to, and insert them. // Though better off having a function for that? @@ -1691,10 +1700,10 @@ static int handleKeySequence(long extra, char *sequence) view->oW = formatLine(view, view->line->line, &(view->output)); moveCursorRelative(view, strlen(sequence), 0, 0, 0); updateLine(view); - return 1; } - return 0; + // Tell handle_keys to drop it, coz we dealt with it, or it's not one of ours. + return 1; } diff --git a/dumbsh.c b/dumbsh.c index 875614b..5f2c63e 100644 --- a/dumbsh.c +++ b/dumbsh.c @@ -188,25 +188,30 @@ static struct keyCommand simpleEmacsKeys[] = }; // Callback for incoming key sequences from the user. -static int handleKeySequence(long extra, char *sequence) +static int handleKeySequence(long extra, char *sequence, int isTranslated) { - int j; + int j, l = strlen(sequence); // Search for a key sequence bound to a command. for (j = 0; j < (sizeof(simpleEmacsKeys) / sizeof(*simpleEmacsKeys)); j++) { - if (strcmp(simpleEmacsKeys[j].key, sequence) == 0) + if (strncmp(simpleEmacsKeys[j].key, sequence, l) == 0) { - if (simpleEmacsKeys[j].handler) simpleEmacsKeys[j].handler(); - return 1; + // If it's a partial match, keep accumulating them. + if (strlen(simpleEmacsKeys[j].key) != l) + return 0; + else + { + if (simpleEmacsKeys[j].handler) simpleEmacsKeys[j].handler(); + return 1; + } } } // See if it's ordinary keys. // NOTE - with vi style ordinary keys can be commands, // but they would be found by the command check above first. - // So here we just check the first character, and insert it all. - if (isprint(sequence[0])) + if (!isTranslated) { if (TT.x < sizeof(toybuf)) { @@ -219,12 +224,10 @@ static int handleKeySequence(long extra, char *sequence) TT.x += l; updateLine(); } - return 1; } - // Return 0 if we didn't handle it, handle_keys will just keep on - // accumulating sequences and trying again. - return 0; + // Tell handle_keys to drop it, coz we dealt with it, or it's not one of ours. + return 1; } void dumbsh_main(void) diff --git a/handlekeys.c b/handlekeys.c index f1fe56c..df18088 100644 --- a/handlekeys.c +++ b/handlekeys.c @@ -177,7 +177,7 @@ static void handleSIGWINCH(int signalNumber) } void handle_keys(long extra, - int (*handle_sequence)(long extra, char *sequence), + int (*handle_sequence)(long extra, char *sequence, int isTranslated), void (*handle_CSI)(long extra, char *command, int *params, int count)) { fd_set selectFds; @@ -212,11 +212,6 @@ void handle_keys(long extra, FD_SET(0, &selectFds); timeOut.tv_sec = 0; timeOut.tv_nsec = 100000000; // One tenth of a second. -// TODO - A bit unstable at the moment, something makes it go into -// a horrid CPU eating edit line flicker mode sometimes. And / or vi mode -// can crash on exit (stack smash). -// This might be fixed now. - // We got a "terminal size changed" signal, ask the terminal // how big it is now. if (sigWinch) @@ -253,10 +248,6 @@ void handle_keys(long extra, } else if ((0 < p) && FD_ISSET(0, &selectFds)) { - // I am assuming that we get the input atomically, each multibyte key - // fits neatly into one read. - // If that's not true (which is entirely likely), then we have to get - // complicated with circular buffers and stuff, or just one byte at a time. j = read(0, &buffer[buffIndex], sizeof(buffer) - (buffIndex + 1)); if (j < 0) perror_exit("input error"); else if (j == 0) // End of file. @@ -412,10 +403,10 @@ void handle_keys(long extra, char b[strlen(sequence) + strlen(buffer) + 1]; sprintf(b, "%s%s", sequence, buffer); - if (handle_sequence(extra, b)) + if (handle_sequence(extra, b, (0 != sequence[0]))) { - sequence[0] = 0; buffer[0] = buffIndex = 0; + sequence[0] = 0; } } } diff --git a/handlekeys.h b/handlekeys.h index 192d96c..9678131 100644 --- a/handlekeys.h +++ b/handlekeys.h @@ -5,7 +5,7 @@ /* An input loop that handles keystrokes and terminal CSI commands. * - * Reads stdin, trying to convert raw keystrokes into something more readable. + * Reads stdin, trying to translate raw keystrokes into something more readable. * See the keys[] array at the top of handlekeys.c for what byte sequences get * translated into what key names. See dumbsh.c for an example of usage. * A 0.1 second delay is used to detect the Esc key being pressed, and not Esc @@ -27,9 +27,15 @@ * handle_CSI - a callback to handle terminal CSI commands. * * handle_sequence is called when a complete keystroke sequence has been - * accumulated. It should return 1 if the sequence has been dealt with, - * otherwise it should return 0, then handle_keys will keep adding more - * complete keystroke sequences on the end, and try again later. + * accumulated. The sequence argument holds the accumulated keystrokes. + * The translated argument flags if any have been translated, otherwise you + * can assume it's all ordinary characters. + * + * handle_keys should return 1 if the sequence has been dealt with, or ignored. + * It should return 0, if handle_keys should keep adding more + * translated keystroke sequences on the end, and try again later. + * 0 should really only be used if it's a partial match, and we need more + * keys in the sequence to make a full match. * * handle_CSI is called when a complete terminal CSI command has been * detected. The command argument is the full CSI command code, including @@ -45,7 +51,7 @@ * get accumulated until fully recognised by the user code. */ void handle_keys(long extra, - int (*handle_sequence)(long extra, char *sequence), + int (*handle_sequence)(long extra, char *sequence, int isTranslated), void (*handle_CSI)(long extra, char *command, int *params, int count)); -- cgit v1.1