aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDavid Walter Seikel2014-02-01 15:00:00 +1000
committerDavid Walter Seikel2014-02-01 15:00:00 +1000
commitf26667d117af5a119471eb531f3ded65b9c1fbc8 (patch)
tree992b67a657a159371b88ba48537126370312efa3
parentSmarten up the CSI parser a little. (diff)
downloadboxes-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.c27
-rw-r--r--dumbsh.c25
-rw-r--r--handlekeys.c15
-rw-r--r--handlekeys.h16
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)
1662 } 1662 }
1663} 1663}
1664 1664
1665 1665// Callback for incoming key sequences from the user.
1666static int handleKeySequence(long extra, char *sequence) 1666static 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
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[] =
188}; 188};
189 189
190// Callback for incoming key sequences from the user. 190// Callback for incoming key sequences from the user.
191static int handleKeySequence(long extra, char *sequence) 191static 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
230void dumbsh_main(void) 233void 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
179void handle_keys(long extra, 179void 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 */
47void handle_keys(long extra, 53void 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