diff options
Diffstat (limited to '')
-rw-r--r-- | dumbsh.c | 119 |
1 files changed, 62 insertions, 57 deletions
@@ -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); |