diff options
-rw-r--r-- | boxes.c | 94 | ||||
-rw-r--r-- | dumbsh.c | 119 | ||||
-rw-r--r-- | handlekeys.c | 37 | ||||
-rw-r--r-- | handlekeys.h | 65 | ||||
-rw-r--r-- | showkey.c | 91 |
5 files changed, 240 insertions, 166 deletions
@@ -1651,59 +1651,69 @@ struct CSI CSIcommands[] = | |||
1651 | {"R", termSize} // Parameters are cursor line and column. Note this may be sent at other times, not just during terminal resize. | 1651 | {"R", termSize} // Parameters are cursor line and column. Note this may be sent at other times, not just during terminal resize. |
1652 | }; | 1652 | }; |
1653 | 1653 | ||
1654 | // Callback for incoming CSI commands from the terminal. | ||
1655 | static void handleCSI(long extra, char *command, int *params, int count) | ||
1656 | { | ||
1657 | int j; | ||
1658 | 1654 | ||
1659 | for (j = 0; j < (sizeof(CSIcommands) / sizeof(*CSIcommands)); j++) | 1655 | // Callback for incoming sequences from the terminal. |
1656 | static int handleEvent(long extra, struct keyevent *event) | ||
1657 | { | ||
1658 | switch (event->type) | ||
1660 | { | 1659 | { |
1661 | if (strcmp(CSIcommands[j].code, command) == 0) | 1660 | case HK_CSI : |
1662 | { | 1661 | { |
1663 | CSIcommands[j].func(extra, params, count); | 1662 | int j; |
1663 | |||
1664 | for (j = 0; j < ARRAY_LEN(CSIcommands); j++) | ||
1665 | { | ||
1666 | if (strcmp(CSIcommands[j].code, event->sequence) == 0) | ||
1667 | { | ||
1668 | CSIcommands[j].func(extra, event->params, event->count); | ||
1669 | break; | ||
1670 | } | ||
1671 | } | ||
1664 | break; | 1672 | break; |
1665 | } | 1673 | } |
1666 | } | ||
1667 | } | ||
1668 | 1674 | ||
1669 | // Callback for incoming key sequences from the user. | 1675 | case HK_KEYS : |
1670 | static int handleKeySequence(long extra, char *sequence, int isTranslated) | 1676 | { |
1671 | { | 1677 | struct _view *view = (struct _view *) extra; // Though we pretty much stomp on this straight away. |
1672 | struct _view *view = (struct _view *) extra; // Though we pretty much stomp on this straight away. | 1678 | struct keyCommand *commands = currentBox->view->content->context->modes[currentBox->view->mode].keys; |
1673 | struct keyCommand *commands = currentBox->view->content->context->modes[currentBox->view->mode].keys; | 1679 | int j, l = strlen(event->sequence); |
1674 | int j, l = strlen(sequence); | ||
1675 | 1680 | ||
1676 | // Coz things might change out from under us, find the current view. | 1681 | // Coz things might change out from under us, find the current view. |
1677 | if (commandMode) view = commandLine; | 1682 | if (commandMode) view = commandLine; |
1678 | else view = currentBox->view; | 1683 | else view = currentBox->view; |
1679 | 1684 | ||
1680 | // Search for a key sequence bound to a command. | 1685 | // Search for a key sequence bound to a command. |
1681 | for (j = 0; commands[j].key; j++) | 1686 | for (j = 0; commands[j].key; j++) |
1682 | { | ||
1683 | if (strncmp(commands[j].key, sequence, l) == 0) | ||
1684 | { | ||
1685 | // If it's a partial match, keep accumulating them. | ||
1686 | if (strlen(commands[j].key) != l) | ||
1687 | return 0; | ||
1688 | else | ||
1689 | { | 1687 | { |
1690 | doCommand(view, commands[j].command); | 1688 | if (strncmp(commands[j].key, event->sequence, l) == 0) |
1691 | return 1; | 1689 | { |
1690 | // If it's a partial match, keep accumulating them. | ||
1691 | if (strlen(commands[j].key) != l) | ||
1692 | return 0; | ||
1693 | else | ||
1694 | { | ||
1695 | doCommand(view, commands[j].command); | ||
1696 | return 1; | ||
1697 | } | ||
1698 | } | ||
1692 | } | 1699 | } |
1700 | |||
1701 | // See if it's ordinary keys. | ||
1702 | // NOTE - with vi style ordinary keys can be commands, | ||
1703 | // but they would be found by the command check above first. | ||
1704 | if (!event->isTranslated) | ||
1705 | { | ||
1706 | // TODO - Should check for tabs to, and insert them. | ||
1707 | // Though better off having a function for that? | ||
1708 | mooshStrings(view->line, event->sequence, view->iX, 0, !overWriteMode); | ||
1709 | view->oW = formatLine(view, view->line->line, &(view->output)); | ||
1710 | moveCursorRelative(view, strlen(event->sequence), 0, 0, 0); | ||
1711 | updateLine(view); | ||
1712 | } | ||
1713 | break; | ||
1693 | } | 1714 | } |
1694 | } | ||
1695 | 1715 | ||
1696 | // See if it's ordinary keys. | 1716 | default : break; |
1697 | // NOTE - with vi style ordinary keys can be commands, | ||
1698 | // but they would be found by the command check above first. | ||
1699 | if (!isTranslated) | ||
1700 | { | ||
1701 | // TODO - Should check for tabs to, and insert them. | ||
1702 | // Though better off having a function for that? | ||
1703 | mooshStrings(view->line, sequence, view->iX, 0, !overWriteMode); | ||
1704 | view->oW = formatLine(view, view->line->line, &(view->output)); | ||
1705 | moveCursorRelative(view, strlen(sequence), 0, 0, 0); | ||
1706 | updateLine(view); | ||
1707 | } | 1717 | } |
1708 | 1718 | ||
1709 | // Tell handle_keys to drop it, coz we dealt with it, or it's not one of ours. | 1719 | // Tell handle_keys to drop it, coz we dealt with it, or it's not one of ours. |
@@ -2481,7 +2491,7 @@ void boxes_main(void) | |||
2481 | updateLine(currentBox->view); | 2491 | updateLine(currentBox->view); |
2482 | 2492 | ||
2483 | // Run the main loop. | 2493 | // Run the main loop. |
2484 | handle_keys((long) currentBox->view, handleKeySequence, handleCSI); | 2494 | handle_keys((long) currentBox->view, handleEvent); |
2485 | 2495 | ||
2486 | // TODO - Should remember to turn off mouse reporting when we leave. | 2496 | // TODO - Should remember to turn off mouse reporting when we leave. |
2487 | 2497 | ||
@@ -48,34 +48,6 @@ static void updateLine() | |||
48 | fflush(stdout); | 48 | fflush(stdout); |
49 | } | 49 | } |
50 | 50 | ||
51 | // Callback for incoming CSI commands from the terminal. | ||
52 | static void handleCSI(long extra, char *command, int *params, int count) | ||
53 | { | ||
54 | // Is it a cursor location report? | ||
55 | if (strcmp("R", command) == 0) | ||
56 | { | ||
57 | // Parameters are cursor line and column. | ||
58 | // NOTE - This may be sent at other times, not just during terminal resize. | ||
59 | // We are assuming here that it's a resize. | ||
60 | // The defaults are 1, which get ignored by the heuristic below. | ||
61 | int r = params[0], c = params[1]; | ||
62 | |||
63 | // Check it's not an F3 key variation, coz some of them use | ||
64 | // the same CSI function command. | ||
65 | // This is a heuristic, we are checking against an unusable terminal size. | ||
66 | if ((2 == count) && (8 < r) && (8 < c)) | ||
67 | { | ||
68 | TT.h = r; | ||
69 | TT.w = c; | ||
70 | updateLine(); | ||
71 | } | ||
72 | } | ||
73 | // NOTE - The CSI differs from the sequence callback | ||
74 | // in not having to return anything. CSI sequences include a | ||
75 | // definite terminating byte, so no need for this callback | ||
76 | // to tell handle_keys to keep accumulating. | ||
77 | } | ||
78 | |||
79 | // The various commands. | 51 | // The various commands. |
80 | static void deleteChar() | 52 | static void deleteChar() |
81 | { | 53 | { |
@@ -184,43 +156,76 @@ static struct keyCommand simpleEmacsKeys[] = | |||
184 | {"^P", prevHistory} | 156 | {"^P", prevHistory} |
185 | }; | 157 | }; |
186 | 158 | ||
187 | // Callback for incoming key sequences from the user. | 159 | // Callback for incoming sequences from the terminal. |
188 | static int handleKeySequence(long extra, char *sequence, int isTranslated) | 160 | static int handleEvent(long extra, struct keyevent *event) |
189 | { | 161 | { |
190 | int j, l = strlen(sequence); | 162 | switch (event->type) |
191 | |||
192 | // Search for a key sequence bound to a command. | ||
193 | for (j = 0; j < (sizeof(simpleEmacsKeys) / sizeof(*simpleEmacsKeys)); j++) | ||
194 | { | 163 | { |
195 | if (strncmp(simpleEmacsKeys[j].key, sequence, l) == 0) | 164 | case HK_KEYS : |
196 | { | 165 | { |
197 | // If it's a partial match, keep accumulating them. | 166 | int j, l = strlen(event->sequence); |
198 | if (strlen(simpleEmacsKeys[j].key) != l) | 167 | |
199 | return 0; | 168 | // Search for a key sequence bound to a command. |
200 | else | 169 | for (j = 0; j < ARRAY_LEN(simpleEmacsKeys); j++) |
201 | { | 170 | { |
202 | if (simpleEmacsKeys[j].handler) simpleEmacsKeys[j].handler(); | 171 | if (strncmp(simpleEmacsKeys[j].key, event->sequence, l) == 0) |
203 | return 1; | 172 | { |
173 | // If it's a partial match, keep accumulating them. | ||
174 | if (strlen(simpleEmacsKeys[j].key) != l) | ||
175 | return 0; | ||
176 | else | ||
177 | { | ||
178 | if (simpleEmacsKeys[j].handler) simpleEmacsKeys[j].handler(); | ||
179 | return 1; | ||
180 | } | ||
181 | } | ||
204 | } | 182 | } |
183 | |||
184 | // See if it's ordinary keys. | ||
185 | // NOTE - with vi style ordinary keys can be commands, | ||
186 | // but they would be found by the command check above first. | ||
187 | if (!event->isTranslated) | ||
188 | { | ||
189 | if (TT.x < sizeof(toybuf)) | ||
190 | { | ||
191 | int j, l = strlen(event->sequence); | ||
192 | |||
193 | for (j = strlen(toybuf); j >= TT.x; j--) | ||
194 | toybuf[j + l] = toybuf[j]; | ||
195 | for (j = 0; j < l; j++) | ||
196 | toybuf[TT.x + j] = event->sequence[j]; | ||
197 | TT.x += l; | ||
198 | updateLine(); | ||
199 | } | ||
200 | } | ||
201 | break; | ||
205 | } | 202 | } |
206 | } | ||
207 | 203 | ||
208 | // See if it's ordinary keys. | 204 | case HK_CSI : |
209 | // NOTE - with vi style ordinary keys can be commands, | ||
210 | // but they would be found by the command check above first. | ||
211 | if (!isTranslated) | ||
212 | { | ||
213 | if (TT.x < sizeof(toybuf)) | ||
214 | { | 205 | { |
215 | int j, l = strlen(sequence); | 206 | // Is it a cursor location report? |
216 | 207 | if (strcmp("R", event->sequence) == 0) | |
217 | for (j = strlen(toybuf); j >= TT.x; j--) | 208 | { |
218 | toybuf[j + l] = toybuf[j]; | 209 | // Parameters are cursor line and column. |
219 | for (j = 0; j < l; j++) | 210 | // NOTE - This may be sent at other times, not just during terminal resize. |
220 | toybuf[TT.x + j] = sequence[j]; | 211 | // We are assuming here that it's a resize. |
221 | TT.x += l; | 212 | // The defaults are 1, which get ignored by the heuristic below. |
222 | updateLine(); | 213 | int r = event->params[0], c = event->params[1]; |
214 | |||
215 | // Check it's not an F3 key variation, coz some of them use | ||
216 | // the same CSI function command. | ||
217 | // This is a heuristic, we are checking against an unusable terminal size. | ||
218 | if ((2 == event->count) && (8 < r) && (8 < c)) | ||
219 | { | ||
220 | TT.h = r; | ||
221 | TT.w = c; | ||
222 | updateLine(); | ||
223 | } | ||
224 | break; | ||
225 | } | ||
223 | } | 226 | } |
227 | |||
228 | default : break; | ||
224 | } | 229 | } |
225 | 230 | ||
226 | // Tell handle_keys to drop it, coz we dealt with it, or it's not one of ours. | 231 | // Tell handle_keys to drop it, coz we dealt with it, or it's not one of ours. |
@@ -269,7 +274,7 @@ void dumbsh_main(void) | |||
269 | 274 | ||
270 | // Let's rock! | 275 | // Let's rock! |
271 | updateLine(); | 276 | updateLine(); |
272 | handle_keys(0, handleKeySequence, handleCSI); | 277 | handle_keys(0, handleEvent); |
273 | 278 | ||
274 | // Clean up. | 279 | // Clean up. |
275 | tcsetattr(0, TCSANOW, &oldTermIo); | 280 | tcsetattr(0, TCSANOW, &oldTermIo); |
diff --git a/handlekeys.c b/handlekeys.c index df18088..7501dbd 100644 --- a/handlekeys.c +++ b/handlekeys.c | |||
@@ -176,10 +176,9 @@ static void handleSIGWINCH(int signalNumber) | |||
176 | sigWinch = 1; | 176 | sigWinch = 1; |
177 | } | 177 | } |
178 | 178 | ||
179 | void handle_keys(long extra, | 179 | void handle_keys(long extra, int (*handle_event)(long extra, struct keyevent *event)) |
180 | int (*handle_sequence)(long extra, char *sequence, int isTranslated), | ||
181 | void (*handle_CSI)(long extra, char *command, int *params, int count)) | ||
182 | { | 180 | { |
181 | struct keyevent event; | ||
183 | fd_set selectFds; | 182 | fd_set selectFds; |
184 | struct timespec timeOut; | 183 | struct timespec timeOut; |
185 | struct sigaction sigAction, oldSigAction; | 184 | struct sigaction sigAction, oldSigAction; |
@@ -261,6 +260,12 @@ void handle_keys(long extra, | |||
261 | else | 260 | else |
262 | { | 261 | { |
263 | buffIndex += j; | 262 | buffIndex += j; |
263 | // Send raw keystrokes, mostly for things like showkey. | ||
264 | event.type = HK_RAW; | ||
265 | event.sequence = buffer; | ||
266 | event.isTranslated = 0; | ||
267 | handle_event(extra, &event); | ||
268 | |||
264 | if (sizeof(buffer) < (buffIndex + 1)) // Ran out of buffer. | 269 | if (sizeof(buffer) < (buffIndex + 1)) // Ran out of buffer. |
265 | { | 270 | { |
266 | fprintf(stderr, "Full buffer - %s -> %s\n", buffer, sequence); | 271 | fprintf(stderr, "Full buffer - %s -> %s\n", buffer, sequence); |
@@ -331,9 +336,18 @@ void handle_keys(long extra, | |||
331 | 336 | ||
332 | if ('M' == buffer[1]) | 337 | if ('M' == buffer[1]) |
333 | { | 338 | { |
334 | // TODO - We have a mouse report, which is CSI M ..., where the rest is | 339 | // We have a mouse report, which is CSI M ..., where the rest is |
335 | // binary encoded, more or less. Not fitting into the CSI format. | 340 | // binary encoded, more or less. Not fitting into the CSI format. |
336 | // To make things worse, can't tell how long this will be. | 341 | // To make things worse, can't tell how long this will be. |
342 | // So leave it up to the caller to tell us if they used it. | ||
343 | event.type = HK_MOUSE; | ||
344 | event.sequence = buffer; | ||
345 | event.isTranslated = 0; | ||
346 | if (handle_event(extra, &event)) | ||
347 | { | ||
348 | buffer[0] = buffIndex = 0; | ||
349 | sequence[0] = 0; | ||
350 | } | ||
337 | } | 351 | } |
338 | else | 352 | else |
339 | { | 353 | { |
@@ -389,8 +403,12 @@ void handle_keys(long extra, | |||
389 | t = csFinal + strlen(csFinal) - 1; | 403 | t = csFinal + strlen(csFinal) - 1; |
390 | if (('\x40' <= (*t)) && ((*t) <= '\x7e')) | 404 | if (('\x40' <= (*t)) && ((*t) <= '\x7e')) |
391 | { | 405 | { |
392 | if (handle_CSI) | 406 | event.type = HK_CSI; |
393 | handle_CSI(extra, csFinal, csParams, p); | 407 | event.sequence = csFinal; |
408 | event.isTranslated = 1; | ||
409 | event.count = p; | ||
410 | event.params = csParams; | ||
411 | handle_event(extra, &event); | ||
394 | buffer[0] = buffIndex = 0; | 412 | buffer[0] = buffIndex = 0; |
395 | sequence[0] = 0; | 413 | sequence[0] = 0; |
396 | } | 414 | } |
@@ -398,12 +416,15 @@ void handle_keys(long extra, | |||
398 | } | 416 | } |
399 | 417 | ||
400 | // Pass the result to the callback. | 418 | // Pass the result to the callback. |
401 | if ((handle_sequence) && (sequence[0] || buffer[0])) | 419 | if (sequence[0] || buffer[0]) |
402 | { | 420 | { |
403 | char b[strlen(sequence) + strlen(buffer) + 1]; | 421 | char b[strlen(sequence) + strlen(buffer) + 1]; |
404 | 422 | ||
405 | sprintf(b, "%s%s", sequence, buffer); | 423 | sprintf(b, "%s%s", sequence, buffer); |
406 | if (handle_sequence(extra, b, (0 != sequence[0]))) | 424 | event.type = HK_KEYS; |
425 | event.sequence = b; | ||
426 | event.isTranslated = (0 != sequence[0]); | ||
427 | if (handle_event(extra, &event)) | ||
407 | { | 428 | { |
408 | buffer[0] = buffIndex = 0; | 429 | buffer[0] = buffIndex = 0; |
409 | sequence[0] = 0; | 430 | sequence[0] = 0; |
diff --git a/handlekeys.h b/handlekeys.h index 9678131..868183f 100644 --- a/handlekeys.h +++ b/handlekeys.h | |||
@@ -3,6 +3,21 @@ | |||
3 | * Copyright 2012 David Seikel <won_fang@yahoo.com.au> | 3 | * Copyright 2012 David Seikel <won_fang@yahoo.com.au> |
4 | */ | 4 | */ |
5 | 5 | ||
6 | enum keyeventtype{ | ||
7 | HK_CSI, | ||
8 | HK_KEYS, | ||
9 | HK_MOUSE, | ||
10 | HK_RAW | ||
11 | }; | ||
12 | |||
13 | struct keyevent { | ||
14 | enum keyeventtype type; // The type of this event. | ||
15 | char *sequence; // Either a translated sequence, or raw bytes. | ||
16 | int isTranslated; // Whether or not sequence is translated. | ||
17 | int count; // Number of entries in params. | ||
18 | int *params; // For CSI events, the decoded parameters. | ||
19 | }; | ||
20 | |||
6 | /* An input loop that handles keystrokes and terminal CSI commands. | 21 | /* An input loop that handles keystrokes and terminal CSI commands. |
7 | * | 22 | * |
8 | * Reads stdin, trying to translate raw keystrokes into something more readable. | 23 | * Reads stdin, trying to translate raw keystrokes into something more readable. |
@@ -17,42 +32,44 @@ | |||
17 | * | 32 | * |
18 | * handle_keys also sets up a SIGWINCH handler to catch terminal resizes, | 33 | * handle_keys also sets up a SIGWINCH handler to catch terminal resizes, |
19 | * and sends a request to the terminal to report it's current size when it gets | 34 | * and sends a request to the terminal to report it's current size when it gets |
20 | * a SIGWINCH. This is the main reason for handle_CSI, as those reports are | 35 | * a SIGWINCH. This is the main reason for HK_CSI, as those reports are |
21 | * sent as CSI. It's still up to the user code to recognise and deal with the | 36 | * sent as CSI. It's still up to the user code to recognise and deal with the |
22 | * terminal resize response, but at least it's nicely decoded for you. | 37 | * terminal resize response, but at least it's nicely decoded for you. |
23 | * | 38 | * |
24 | * Arguments - | 39 | * Arguments - |
25 | * extra - arbitrary data that gets passed back to the callbacks. | 40 | * extra - arbitrary data that gets passed back to the callbacks. |
26 | * handle_sequence - a callback to handle keystroke sequences. | 41 | * handle_event - a callback to handle sequences. |
27 | * handle_CSI - a callback to handle terminal CSI commands. | 42 | * |
43 | * handle_event is called when a complete sequence has been accumulated. It is | ||
44 | * passed a keyevent structure. The type member of that structure determines | ||
45 | * what sort of event this is. What's in the rest of the keyevent depends on | ||
46 | * the type - | ||
28 | * | 47 | * |
29 | * handle_sequence is called when a complete keystroke sequence has been | 48 | * HK_CSI |
30 | * accumulated. The sequence argument holds the accumulated keystrokes. | 49 | * sequence is the fully decoded CSI command, including the private and intermediate characters. |
31 | * The translated argument flags if any have been translated, otherwise you | 50 | * isTranslated is 1, since the CSI command has been translated. |
32 | * can assume it's all ordinary characters. | 51 | * count is the count of translated CSI parameters. |
52 | * params is an array of translateted CSI parameters. | ||
53 | * Empty parameters are set to -1, coz -1 parameters are not legal, | ||
54 | * and empty ones should default to something that is command dependant. | ||
33 | * | 55 | * |
34 | * handle_keys should return 1 if the sequence has been dealt with, or ignored. | 56 | * HK_KEYS |
35 | * It should return 0, if handle_keys should keep adding more | 57 | * sequence the keystrokes as ASCII, either translated or not. |
58 | * isTranslated if 0, then sequence is ordinary keys, otherwise | ||
59 | * sequence is the names of keys, from the keys[] array. | ||
60 | * count and params are not used. | ||
61 | * | ||
62 | * For HK_KEYS handle_event should return 1 if the sequence has been dealt with, | ||
63 | * or ignored. It should return 0, if handle_keys should keep adding more | ||
36 | * translated keystroke sequences on the end, and try again later. | 64 | * 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 | 65 | * 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. | 66 | * keys in the sequence to make a full match. |
39 | * | 67 | * |
40 | * handle_CSI is called when a complete terminal CSI command has been | 68 | * HK_MOUSE |
41 | * detected. The command argument is the full CSI command code, including | 69 | * sequence is the raw bytes of the mouse report. The rest are not used. |
42 | * private and intermediate characters. The params argument is the decoded | 70 | * |
43 | * parameters from the command. The count argument is the number of decoded | ||
44 | * parameters. Empty parameters are set to -1, coz -1 parameters are not legal, | ||
45 | * and empty ones should default to something that is command dependant. | ||
46 | * | ||
47 | * NOTE - handle_CSI differs from handle_sequence in not having to | ||
48 | * return anything. CSI sequences include a definite terminating byte, | ||
49 | * so no need for this callback to tell handle_keys to keep accumulating. | ||
50 | * Some applications use a series of keystrokes for things, so they | ||
51 | * get accumulated until fully recognised by the user code. | ||
52 | */ | 71 | */ |
53 | void handle_keys(long extra, | 72 | void handle_keys(long extra, int (*handle_event)(long extra, struct keyevent *event)); |
54 | int (*handle_sequence)(long extra, char *sequence, int isTranslated), | ||
55 | void (*handle_CSI)(long extra, char *command, int *params, int count)); | ||
56 | 73 | ||
57 | 74 | ||
58 | /* Call this when you want handle_keys to return. */ | 75 | /* Call this when you want handle_keys to return. */ |
@@ -34,24 +34,6 @@ GLOBALS( | |||
34 | #define TT this.showkey | 34 | #define TT this.showkey |
35 | 35 | ||
36 | 36 | ||
37 | // Callback for incoming CSI commands from the terminal. | ||
38 | static void handleCSI(long extra, char *command, int *params, int count) | ||
39 | { | ||
40 | int i; | ||
41 | |||
42 | // Is it a cursor location report? | ||
43 | if (strcmp("R", command) == 0) | ||
44 | { | ||
45 | printf("CSI cursor position - line %d, column %d\r\n", params[0], params[1]); | ||
46 | return; | ||
47 | } | ||
48 | |||
49 | printf("CSI command %s - ", command); | ||
50 | for (i = 0; i < count; i++) | ||
51 | printf("%d ", params[i]); | ||
52 | printf("\r\n"); | ||
53 | } | ||
54 | |||
55 | static void quit() | 37 | static void quit() |
56 | { | 38 | { |
57 | printf("Quitting.\r\n"); | 39 | printf("Quitting.\r\n"); |
@@ -64,31 +46,70 @@ static struct keyCommand simpleKeys[] = | |||
64 | {"^C", quit} | 46 | {"^C", quit} |
65 | }; | 47 | }; |
66 | 48 | ||
67 | // Callback for incoming key sequences from the user. | 49 | // Callback for incoming sequences from the terminal. |
68 | static int handleKeySequence(long extra, char *sequence, int isTranslated) | 50 | static int handleEvent(long extra, struct keyevent *event) |
69 | { | 51 | { |
70 | int j, l = strlen(sequence); | 52 | int i; |
71 | |||
72 | if (isTranslated) | ||
73 | printf("TRANSLATED - "); | ||
74 | else | ||
75 | printf("KEY - "); | ||
76 | printf("%s\r\n", sequence); | ||
77 | 53 | ||
78 | // Search for a key sequence bound to a command. | 54 | switch (event->type) |
79 | for (j = 0; j < (sizeof(simpleKeys) / sizeof(*simpleKeys)); j++) | ||
80 | { | 55 | { |
81 | if (strncmp(simpleKeys[j].key, sequence, l) == 0) | 56 | case HK_RAW : |
57 | { | ||
58 | printf("RAW "); | ||
59 | for (i = 0; event->sequence[i]; i++) | ||
60 | { | ||
61 | printf("(%x) ", (int) event->sequence[i]); | ||
62 | if (32 > event->sequence[i]) | ||
63 | printf("^%c, ", (int) event->sequence[i] + 'A' - 1); | ||
64 | else | ||
65 | printf("%c, ", (int) event->sequence[i]); | ||
66 | } | ||
67 | printf("-> "); | ||
68 | break; | ||
69 | } | ||
70 | |||
71 | case HK_KEYS : | ||
82 | { | 72 | { |
83 | // If it's a partial match, keep accumulating them. | 73 | int l = strlen(event->sequence); |
84 | if (strlen(simpleKeys[j].key) != l) | 74 | |
85 | return 0; | 75 | if (event->isTranslated) |
76 | printf("TRANSLATED - "); | ||
86 | else | 77 | else |
78 | printf("KEY - "); | ||
79 | printf("%s\r\n", event->sequence); | ||
80 | |||
81 | // Search for a key sequence bound to a command. | ||
82 | for (i = 0; i < ARRAY_LEN(simpleKeys); i++) | ||
83 | { | ||
84 | if (strncmp(simpleKeys[i].key, event->sequence, l) == 0) | ||
85 | { | ||
86 | // If it's a partial match, keep accumulating them. | ||
87 | if (strlen(simpleKeys[i].key) != l) | ||
88 | return 0; | ||
89 | else | ||
90 | if (simpleKeys[i].handler) simpleKeys[i].handler(); | ||
91 | } | ||
92 | } | ||
93 | break; | ||
94 | } | ||
95 | |||
96 | case HK_CSI : | ||
97 | { | ||
98 | // Is it a cursor location report? | ||
99 | if (strcmp("R", event->sequence) == 0) | ||
87 | { | 100 | { |
88 | if (simpleKeys[j].handler) simpleKeys[j].handler(); | 101 | printf("CSI cursor position - line %d, column %d\r\n", event->params[0], event->params[1]); |
89 | return 1; | 102 | return 1; |
90 | } | 103 | } |
104 | |||
105 | printf("CSI command %s - ", event->sequence); | ||
106 | for (i = 0; i < event->count; i++) | ||
107 | printf("%d ", event->params[i]); | ||
108 | printf("\r\n"); | ||
109 | break; | ||
91 | } | 110 | } |
111 | |||
112 | default : break; | ||
92 | } | 113 | } |
93 | 114 | ||
94 | return 1; | 115 | return 1; |
@@ -117,7 +138,7 @@ void showkey_main(void) | |||
117 | termIo.c_cc[VMIN]=1; | 138 | termIo.c_cc[VMIN]=1; |
118 | tcsetattr(0, TCSANOW, &termIo); | 139 | tcsetattr(0, TCSANOW, &termIo); |
119 | 140 | ||
120 | handle_keys(0, handleKeySequence, handleCSI); | 141 | handle_keys(0, handleEvent); |
121 | 142 | ||
122 | tcsetattr(0, TCSANOW, &oldTermIo); | 143 | tcsetattr(0, TCSANOW, &oldTermIo); |
123 | puts(""); | 144 | puts(""); |