diff options
author | David Walter Seikel | 2014-02-01 15:00:00 +1000 |
---|---|---|
committer | David Walter Seikel | 2014-02-01 15:00:00 +1000 |
commit | f26667d117af5a119471eb531f3ded65b9c1fbc8 (patch) | |
tree | 992b67a657a159371b88ba48537126370312efa3 | |
parent | Smarten up the CSI parser a little. (diff) | |
download | boxes-f26667d117af5a119471eb531f3ded65b9c1fbc8.zip boxes-f26667d117af5a119471eb531f3ded65b9c1fbc8.tar.gz boxes-f26667d117af5a119471eb531f3ded65b9c1fbc8.tar.bz2 boxes-f26667d117af5a119471eb531f3ded65b9c1fbc8.tar.xz |
Better method to tell if it's ordinary characters, and deal with partial reads better.
-rw-r--r-- | boxes.c | 27 | ||||
-rw-r--r-- | dumbsh.c | 25 | ||||
-rw-r--r-- | handlekeys.c | 15 | ||||
-rw-r--r-- | handlekeys.h | 16 |
4 files changed, 46 insertions, 37 deletions
@@ -1662,12 +1662,12 @@ static void handleCSI(long extra, char *command, int *params, int count) | |||
1662 | } | 1662 | } |
1663 | } | 1663 | } |
1664 | 1664 | ||
1665 | 1665 | // Callback for incoming key sequences from the user. | |
1666 | static int handleKeySequence(long extra, char *sequence) | 1666 | static int handleKeySequence(long extra, char *sequence, int isTranslated) |
1667 | { | 1667 | { |
1668 | struct _view *view = (struct _view *) extra; // Though we pretty much stomp on this straight away. | 1668 | struct _view *view = (struct _view *) extra; // Though we pretty much stomp on this straight away. |
1669 | struct keyCommand *commands = currentBox->view->content->context->modes[currentBox->view->mode].keys; | 1669 | struct keyCommand *commands = currentBox->view->content->context->modes[currentBox->view->mode].keys; |
1670 | int j; | 1670 | int j, l = strlen(sequence); |
1671 | 1671 | ||
1672 | // Coz things might change out from under us, find the current view. | 1672 | // Coz things might change out from under us, find the current view. |
1673 | if (commandMode) view = commandLine; | 1673 | if (commandMode) view = commandLine; |
@@ -1676,14 +1676,23 @@ static int handleKeySequence(long extra, char *sequence) | |||
1676 | // Search for a key sequence bound to a command. | 1676 | // Search for a key sequence bound to a command. |
1677 | for (j = 0; commands[j].key; j++) | 1677 | for (j = 0; commands[j].key; j++) |
1678 | { | 1678 | { |
1679 | if (strcmp(commands[j].key, sequence) == 0) | 1679 | if (strncmp(commands[j].key, sequence, l) == 0) |
1680 | { | 1680 | { |
1681 | doCommand(view, commands[j].command); | 1681 | // If it's a partial match, keep accumulating them. |
1682 | return 1; | 1682 | if (strlen(commands[j].key) != l) |
1683 | return 0; | ||
1684 | else | ||
1685 | { | ||
1686 | doCommand(view, commands[j].command); | ||
1687 | return 1; | ||
1688 | } | ||
1683 | } | 1689 | } |
1684 | } | 1690 | } |
1685 | 1691 | ||
1686 | if ((0 == sequence[1]) && isprint(sequence[0])) // See if it's an ordinary key. | 1692 | // See if it's ordinary keys. |
1693 | // NOTE - with vi style ordinary keys can be commands, | ||
1694 | // but they would be found by the command check above first. | ||
1695 | if (!isTranslated) | ||
1687 | { | 1696 | { |
1688 | // TODO - Should check for tabs to, and insert them. | 1697 | // TODO - Should check for tabs to, and insert them. |
1689 | // Though better off having a function for that? | 1698 | // Though better off having a function for that? |
@@ -1691,10 +1700,10 @@ static int handleKeySequence(long extra, char *sequence) | |||
1691 | view->oW = formatLine(view, view->line->line, &(view->output)); | 1700 | view->oW = formatLine(view, view->line->line, &(view->output)); |
1692 | moveCursorRelative(view, strlen(sequence), 0, 0, 0); | 1701 | moveCursorRelative(view, strlen(sequence), 0, 0, 0); |
1693 | updateLine(view); | 1702 | updateLine(view); |
1694 | return 1; | ||
1695 | } | 1703 | } |
1696 | 1704 | ||
1697 | return 0; | 1705 | // Tell handle_keys to drop it, coz we dealt with it, or it's not one of ours. |
1706 | return 1; | ||
1698 | } | 1707 | } |
1699 | 1708 | ||
1700 | 1709 | ||
@@ -188,25 +188,30 @@ static struct keyCommand simpleEmacsKeys[] = | |||
188 | }; | 188 | }; |
189 | 189 | ||
190 | // Callback for incoming key sequences from the user. | 190 | // Callback for incoming key sequences from the user. |
191 | static int handleKeySequence(long extra, char *sequence) | 191 | static int handleKeySequence(long extra, char *sequence, int isTranslated) |
192 | { | 192 | { |
193 | int j; | 193 | int j, l = strlen(sequence); |
194 | 194 | ||
195 | // Search for a key sequence bound to a command. | 195 | // Search for a key sequence bound to a command. |
196 | for (j = 0; j < (sizeof(simpleEmacsKeys) / sizeof(*simpleEmacsKeys)); j++) | 196 | for (j = 0; j < (sizeof(simpleEmacsKeys) / sizeof(*simpleEmacsKeys)); j++) |
197 | { | 197 | { |
198 | if (strcmp(simpleEmacsKeys[j].key, sequence) == 0) | 198 | if (strncmp(simpleEmacsKeys[j].key, sequence, l) == 0) |
199 | { | 199 | { |
200 | if (simpleEmacsKeys[j].handler) simpleEmacsKeys[j].handler(); | 200 | // If it's a partial match, keep accumulating them. |
201 | return 1; | 201 | if (strlen(simpleEmacsKeys[j].key) != l) |
202 | return 0; | ||
203 | else | ||
204 | { | ||
205 | if (simpleEmacsKeys[j].handler) simpleEmacsKeys[j].handler(); | ||
206 | return 1; | ||
207 | } | ||
202 | } | 208 | } |
203 | } | 209 | } |
204 | 210 | ||
205 | // See if it's ordinary keys. | 211 | // See if it's ordinary keys. |
206 | // NOTE - with vi style ordinary keys can be commands, | 212 | // NOTE - with vi style ordinary keys can be commands, |
207 | // but they would be found by the command check above first. | 213 | // but they would be found by the command check above first. |
208 | // So here we just check the first character, and insert it all. | 214 | if (!isTranslated) |
209 | if (isprint(sequence[0])) | ||
210 | { | 215 | { |
211 | if (TT.x < sizeof(toybuf)) | 216 | if (TT.x < sizeof(toybuf)) |
212 | { | 217 | { |
@@ -219,12 +224,10 @@ static int handleKeySequence(long extra, char *sequence) | |||
219 | TT.x += l; | 224 | TT.x += l; |
220 | updateLine(); | 225 | updateLine(); |
221 | } | 226 | } |
222 | return 1; | ||
223 | } | 227 | } |
224 | 228 | ||
225 | // Return 0 if we didn't handle it, handle_keys will just keep on | 229 | // Tell handle_keys to drop it, coz we dealt with it, or it's not one of ours. |
226 | // accumulating sequences and trying again. | 230 | return 1; |
227 | return 0; | ||
228 | } | 231 | } |
229 | 232 | ||
230 | void dumbsh_main(void) | 233 | 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) | |||
177 | } | 177 | } |
178 | 178 | ||
179 | void handle_keys(long extra, | 179 | void handle_keys(long extra, |
180 | int (*handle_sequence)(long extra, char *sequence), | 180 | int (*handle_sequence)(long extra, char *sequence, int isTranslated), |
181 | void (*handle_CSI)(long extra, char *command, int *params, int count)) | 181 | void (*handle_CSI)(long extra, char *command, int *params, int count)) |
182 | { | 182 | { |
183 | fd_set selectFds; | 183 | fd_set selectFds; |
@@ -212,11 +212,6 @@ void handle_keys(long extra, | |||
212 | FD_SET(0, &selectFds); | 212 | FD_SET(0, &selectFds); |
213 | timeOut.tv_sec = 0; timeOut.tv_nsec = 100000000; // One tenth of a second. | 213 | timeOut.tv_sec = 0; timeOut.tv_nsec = 100000000; // One tenth of a second. |
214 | 214 | ||
215 | // TODO - A bit unstable at the moment, something makes it go into | ||
216 | // a horrid CPU eating edit line flicker mode sometimes. And / or vi mode | ||
217 | // can crash on exit (stack smash). | ||
218 | // This might be fixed now. | ||
219 | |||
220 | // We got a "terminal size changed" signal, ask the terminal | 215 | // We got a "terminal size changed" signal, ask the terminal |
221 | // how big it is now. | 216 | // how big it is now. |
222 | if (sigWinch) | 217 | if (sigWinch) |
@@ -253,10 +248,6 @@ void handle_keys(long extra, | |||
253 | } | 248 | } |
254 | else if ((0 < p) && FD_ISSET(0, &selectFds)) | 249 | else if ((0 < p) && FD_ISSET(0, &selectFds)) |
255 | { | 250 | { |
256 | // I am assuming that we get the input atomically, each multibyte key | ||
257 | // fits neatly into one read. | ||
258 | // If that's not true (which is entirely likely), then we have to get | ||
259 | // complicated with circular buffers and stuff, or just one byte at a time. | ||
260 | j = read(0, &buffer[buffIndex], sizeof(buffer) - (buffIndex + 1)); | 251 | j = read(0, &buffer[buffIndex], sizeof(buffer) - (buffIndex + 1)); |
261 | if (j < 0) perror_exit("input error"); | 252 | if (j < 0) perror_exit("input error"); |
262 | else if (j == 0) // End of file. | 253 | else if (j == 0) // End of file. |
@@ -412,10 +403,10 @@ void handle_keys(long extra, | |||
412 | char b[strlen(sequence) + strlen(buffer) + 1]; | 403 | char b[strlen(sequence) + strlen(buffer) + 1]; |
413 | 404 | ||
414 | sprintf(b, "%s%s", sequence, buffer); | 405 | sprintf(b, "%s%s", sequence, buffer); |
415 | if (handle_sequence(extra, b)) | 406 | if (handle_sequence(extra, b, (0 != sequence[0]))) |
416 | { | 407 | { |
417 | sequence[0] = 0; | ||
418 | buffer[0] = buffIndex = 0; | 408 | buffer[0] = buffIndex = 0; |
409 | sequence[0] = 0; | ||
419 | } | 410 | } |
420 | } | 411 | } |
421 | } | 412 | } |
diff --git a/handlekeys.h b/handlekeys.h index 192d96c..9678131 100644 --- a/handlekeys.h +++ b/handlekeys.h | |||
@@ -5,7 +5,7 @@ | |||
5 | 5 | ||
6 | /* An input loop that handles keystrokes and terminal CSI commands. | 6 | /* An input loop that handles keystrokes and terminal CSI commands. |
7 | * | 7 | * |
8 | * Reads stdin, trying to convert raw keystrokes into something more readable. | 8 | * Reads stdin, trying to translate raw keystrokes into something more readable. |
9 | * See the keys[] array at the top of handlekeys.c for what byte sequences get | 9 | * See the keys[] array at the top of handlekeys.c for what byte sequences get |
10 | * translated into what key names. See dumbsh.c for an example of usage. | 10 | * translated into what key names. See dumbsh.c for an example of usage. |
11 | * A 0.1 second delay is used to detect the Esc key being pressed, and not Esc | 11 | * A 0.1 second delay is used to detect the Esc key being pressed, and not Esc |
@@ -27,9 +27,15 @@ | |||
27 | * handle_CSI - a callback to handle terminal CSI commands. | 27 | * handle_CSI - a callback to handle terminal CSI commands. |
28 | * | 28 | * |
29 | * handle_sequence is called when a complete keystroke sequence has been | 29 | * handle_sequence is called when a complete keystroke sequence has been |
30 | * accumulated. It should return 1 if the sequence has been dealt with, | 30 | * accumulated. The sequence argument holds the accumulated keystrokes. |
31 | * otherwise it should return 0, then handle_keys will keep adding more | 31 | * The translated argument flags if any have been translated, otherwise you |
32 | * complete keystroke sequences on the end, and try again later. | 32 | * can assume it's all ordinary characters. |
33 | * | ||
34 | * handle_keys should return 1 if the sequence has been dealt with, or ignored. | ||
35 | * It should return 0, if handle_keys should keep adding more | ||
36 | * translated keystroke sequences on the end, and try again later. | ||
37 | * 0 should really only be used if it's a partial match, and we need more | ||
38 | * keys in the sequence to make a full match. | ||
33 | * | 39 | * |
34 | * handle_CSI is called when a complete terminal CSI command has been | 40 | * handle_CSI is called when a complete terminal CSI command has been |
35 | * detected. The command argument is the full CSI command code, including | 41 | * detected. The command argument is the full CSI command code, including |
@@ -45,7 +51,7 @@ | |||
45 | * get accumulated until fully recognised by the user code. | 51 | * get accumulated until fully recognised by the user code. |
46 | */ | 52 | */ |
47 | void handle_keys(long extra, | 53 | void handle_keys(long extra, |
48 | int (*handle_sequence)(long extra, char *sequence), | 54 | int (*handle_sequence)(long extra, char *sequence, int isTranslated), |
49 | void (*handle_CSI)(long extra, char *command, int *params, int count)); | 55 | void (*handle_CSI)(long extra, char *command, int *params, int count)); |
50 | 56 | ||
51 | 57 | ||