source: mainline/uspace/lib/vt/src/vt100.c

Last change on this file was 9d5cea6, checked in by Jiri Svoboda <jiri@…>, 9 months ago

Allow remcons/vt100 to set terminal title

  • Property mode set to 100644
File size: 29.4 KB
Line 
1/*
2 * Copyright (c) 2024 Jiri Svoboda
3 * Copyright (c) 2011 Martin Decky
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup libvt
31 * @{
32 */
33
34#include <ctype.h>
35#include <errno.h>
36#include <io/color.h>
37#include <io/keycode.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <vt/vt100.h>
41
42/** Map console colors to VT100 color indices */
43sgr_color_index_t color_map[] = {
44 [COLOR_BLACK] = CI_BLACK,
45 [COLOR_BLUE] = CI_BLUE,
46 [COLOR_GREEN] = CI_GREEN,
47 [COLOR_CYAN] = CI_CYAN,
48 [COLOR_RED] = CI_RED,
49 [COLOR_MAGENTA] = CI_MAGENTA,
50 [COLOR_YELLOW] = CI_BROWN,
51 [COLOR_WHITE] = CI_WHITE
52};
53
54/** Clear screen.
55 *
56 * @param vt VT instance
57 */
58void vt100_cls(vt100_t *vt)
59{
60 vt->cb->control_puts(vt->arg, "\033[2J");
61}
62
63/** ECMA-48 Set Graphics Rendition.
64 *
65 * @param vt VT instance
66 * @param mode SGR mode number
67 */
68void vt100_sgr(vt100_t *vt, unsigned int mode)
69{
70 char control[MAX_CONTROL];
71
72 snprintf(control, MAX_CONTROL, "\033[%um", mode);
73 vt->cb->control_puts(vt->arg, control);
74}
75
76/** Set Graphics Rendition with 5 arguments.
77 *
78 * @param vt VT instance
79 * @param a1 First argument
80 * @param a2 Second argument
81 * @param a3 Third argument
82 * @param a4 Fourth argument
83 * @param a5 Fifth argument
84 */
85static void vt100_sgr5(vt100_t *vt, unsigned a1, unsigned a2,
86 unsigned a3, unsigned a4, unsigned a5)
87{
88 char control[MAX_CONTROL];
89
90 snprintf(control, MAX_CONTROL, "\033[%u;%u;%u;%u;%um",
91 a1, a2, a3, a4, a5);
92 vt->cb->control_puts(vt->arg, control);
93}
94
95/** Set cussor position.
96 *
97 * @param vt VT instance
98 * @param col Column (starting from 0)
99 * @param row Row (starting from 0)
100 */
101void vt100_set_pos(vt100_t *vt, sysarg_t col, sysarg_t row)
102{
103 char control[MAX_CONTROL];
104
105 snprintf(control, MAX_CONTROL, "\033[%" PRIun ";%" PRIun "f",
106 row + 1, col + 1);
107 vt->cb->control_puts(vt->arg, control);
108}
109
110/** Set graphics rendition based on attributes,
111 *
112 * @param vt VT instance
113 * @param attrs Character attributes
114 */
115void vt100_set_sgr(vt100_t *vt, char_attrs_t attrs)
116{
117 unsigned color;
118
119 switch (attrs.type) {
120 case CHAR_ATTR_STYLE:
121 switch (attrs.val.style) {
122 case STYLE_NORMAL:
123 vt100_sgr(vt, SGR_RESET);
124 vt100_sgr(vt, SGR_BGCOLOR + CI_WHITE);
125 vt100_sgr(vt, SGR_FGCOLOR + CI_BLACK);
126 break;
127 case STYLE_EMPHASIS:
128 vt100_sgr(vt, SGR_RESET);
129 vt100_sgr(vt, SGR_BGCOLOR + CI_WHITE);
130 vt100_sgr(vt, SGR_FGCOLOR + CI_RED);
131 vt100_sgr(vt, SGR_BOLD);
132 break;
133 case STYLE_INVERTED:
134 vt100_sgr(vt, SGR_RESET);
135 vt100_sgr(vt, SGR_BGCOLOR + CI_BLACK);
136 vt100_sgr(vt, SGR_FGCOLOR + CI_WHITE);
137 break;
138 case STYLE_SELECTED:
139 vt100_sgr(vt, SGR_RESET);
140 vt100_sgr(vt, SGR_BGCOLOR + CI_RED);
141 vt100_sgr(vt, SGR_FGCOLOR + CI_WHITE);
142 break;
143 }
144 break;
145 case CHAR_ATTR_INDEX:
146 vt100_sgr(vt, SGR_RESET);
147 vt100_sgr(vt, SGR_BGCOLOR + color_map[attrs.val.index.bgcolor & 7]);
148 vt100_sgr(vt, SGR_FGCOLOR + color_map[attrs.val.index.fgcolor & 7]);
149
150 if (attrs.val.index.attr & CATTR_BRIGHT)
151 vt100_sgr(vt, SGR_BOLD);
152
153 break;
154 case CHAR_ATTR_RGB:
155 if (vt->enable_rgb == true) {
156 vt100_sgr5(vt, 48, 2, RED(attrs.val.rgb.bgcolor),
157 GREEN(attrs.val.rgb.bgcolor),
158 BLUE(attrs.val.rgb.bgcolor));
159 vt100_sgr5(vt, 38, 2, RED(attrs.val.rgb.fgcolor),
160 GREEN(attrs.val.rgb.fgcolor),
161 BLUE(attrs.val.rgb.fgcolor));
162 } else {
163 vt100_sgr(vt, SGR_RESET);
164 color =
165 ((RED(attrs.val.rgb.fgcolor) >= 0x80) ? COLOR_RED : 0) |
166 ((GREEN(attrs.val.rgb.fgcolor) >= 0x80) ? COLOR_GREEN : 0) |
167 ((BLUE(attrs.val.rgb.fgcolor) >= 0x80) ? COLOR_BLUE : 0);
168 vt100_sgr(vt, SGR_FGCOLOR + color_map[color]);
169 color =
170 ((RED(attrs.val.rgb.bgcolor) >= 0x80) ? COLOR_RED : 0) |
171 ((GREEN(attrs.val.rgb.bgcolor) >= 0x80) ? COLOR_GREEN : 0) |
172 ((BLUE(attrs.val.rgb.bgcolor) >= 0x80) ? COLOR_BLUE : 0);
173 vt100_sgr(vt, SGR_BGCOLOR + color_map[color]);
174 }
175 break;
176 }
177}
178
179/** Create VT instance.
180 *
181 * @param arg Argument passed to callback functions
182 * @param cols Number of columns
183 * @param rows Number of rows
184 * @param cb Callback functions
185 *
186 * @return Pointer to new VT instance on success, NULL on failure.
187 */
188vt100_t *vt100_create(void *arg, sysarg_t cols, sysarg_t rows, vt100_cb_t *cb)
189{
190 vt100_t *vt = malloc(sizeof(vt100_t));
191 if (vt == NULL)
192 return NULL;
193
194 vt->cb = cb;
195 vt->arg = arg;
196
197 vt->cols = cols;
198 vt->rows = rows;
199
200 vt->cur_col = (sysarg_t) -1;
201 vt->cur_row = (sysarg_t) -1;
202
203 vt->cur_attrs.type = -1;
204 vt->cur_attrs.val.style = -1;
205
206 vt->state = vts_base;
207 vt->inncnt = 0;
208
209 return vt;
210}
211
212/** Resize VT instance.
213 *
214 * @param vt VT instance
215 * @param cols New number of columns
216 * @param rows New number of rows
217 */
218void vt100_resize(vt100_t *vt, sysarg_t cols, sysarg_t rows)
219{
220 vt->cols = cols;
221 vt->rows = rows;
222
223 if (vt->cur_col > cols - 1)
224 vt->cur_col = cols - 1;
225 if (vt->cur_row > rows - 1)
226 vt->cur_row = rows - 1;
227}
228
229/** Destroy VT instance.
230 *
231 * @param vt VT instance
232 */
233void vt100_destroy(vt100_t *vt)
234{
235 free(vt);
236}
237
238/** Get VT size.
239 *
240 * @param vt VT instance
241 * @param cols Place to store number of columns
242 * @param rows Place to store number of rows
243 */
244void vt100_get_dimensions(vt100_t *vt, sysarg_t *cols,
245 sysarg_t *rows)
246{
247 *cols = vt->cols;
248 *rows = vt->rows;
249}
250
251/** Temporarily yield VT to other users.
252 *
253 * @param vt VT instance
254 * @return EOK on success or an error code
255 */
256errno_t vt100_yield(vt100_t *vt)
257{
258 return EOK;
259}
260
261/** Reclaim VT.
262 *
263 * @param vt VT instance
264 * @return EOK on success or an error code
265 */
266errno_t vt100_claim(vt100_t *vt)
267{
268 return EOK;
269}
270
271/** Go to specified position, if needed.
272 *
273 * @param vt VT instance
274 * @param col Column (starting from 0)
275 * @param row Row (starting from 0)
276 */
277void vt100_goto(vt100_t *vt, sysarg_t col, sysarg_t row)
278{
279 if ((col >= vt->cols) || (row >= vt->rows))
280 return;
281
282 if ((col != vt->cur_col) || (row != vt->cur_row)) {
283 vt100_set_pos(vt, col, row);
284 vt->cur_col = col;
285 vt->cur_row = row;
286 }
287}
288
289/** Set character attributes, if needed.
290 *
291 * @param vt VT instance
292 * @param attrs Attributes
293 */
294void vt100_set_attr(vt100_t *vt, char_attrs_t attrs)
295{
296 if (!attrs_same(vt->cur_attrs, attrs)) {
297 vt100_set_sgr(vt, attrs);
298 vt->cur_attrs = attrs;
299 }
300}
301
302/** Set cursor visibility.
303 *
304 * @param vt VT instance
305 * @param @c true to make cursor visible, @c false to make it invisible
306 */
307void vt100_cursor_visibility(vt100_t *vt, bool visible)
308{
309 if (visible)
310 vt->cb->control_puts(vt->arg, "\033[?25h");
311 else
312 vt->cb->control_puts(vt->arg, "\033[?25l");
313}
314
315/** Set mouse button press/release reporting.
316 *
317 * @param vt VT instance
318 * @param @c true to enable button press/release reporting
319 */
320void vt100_set_button_reporting(vt100_t *vt, bool enable)
321{
322 if (enable) {
323 /* Enable button tracking */
324 vt->cb->control_puts(vt->arg, "\033[?1000h");
325 /* Enable SGR encoding of mouse reports */
326 vt->cb->control_puts(vt->arg, "\033[?1006h");
327 } else {
328 /* Disable button tracking */
329 vt->cb->control_puts(vt->arg, "\033[?1000l");
330 /* Disable SGR encoding of mouse reports */
331 vt->cb->control_puts(vt->arg, "\033[?1006l");
332 }
333}
334
335/** Set terminal title.
336 *
337 * @param vt VT instance
338 * @param title Terminal title
339 */
340void vt100_set_title(vt100_t *vt, const char *title)
341{
342 vt->cb->control_puts(vt->arg, "\033]0;");
343 vt->cb->control_puts(vt->arg, title);
344 vt->cb->control_puts(vt->arg, "\a");
345}
346
347/** Print Unicode character.
348 *
349 * @param vt VT instance
350 * @parma ch Unicode character
351 */
352void vt100_putuchar(vt100_t *vt, char32_t ch)
353{
354 vt->cb->putuchar(vt->arg, ch == 0 ? ' ' : ch);
355 vt->cur_col++;
356
357 if (vt->cur_col >= vt->cols) {
358 vt->cur_row += vt->cur_col / vt->cols;
359 vt->cur_col %= vt->cols;
360 }
361}
362
363/** Flush VT.
364 *
365 * @param vt VT instance
366 */
367void vt100_flush(vt100_t *vt)
368{
369 vt->cb->flush(vt->arg);
370}
371
372/** Recognize a key.
373 *
374 * Generate a key callback and reset decoder state.
375 *
376 * @param vt VT instance
377 * @param mods Key modifiers
378 * @param key Key code
379 * @param c Character
380 */
381static void vt100_key(vt100_t *vt, keymod_t mods, keycode_t key, char c)
382{
383 vt->cb->key(vt->arg, mods, key, c);
384 vt->state = vts_base;
385}
386
387/** Generate position event callback.
388 * *
389 * @param vt VT instance
390 * @param ev Position event
391 */
392static void vt100_pos_event(vt100_t *vt, pos_event_t *ev)
393{
394 vt->cb->pos_event(vt->arg, ev);
395}
396
397/** Clear number decoder state.
398 *
399 * @param vt VT instance
400 */
401static void vt100_clear_innum(vt100_t *vt)
402{
403 unsigned i;
404
405 vt->inncnt = 0;
406 for (i = 0; i < INNUM_MAX; i++)
407 vt->innum[i] = 0;
408}
409
410/** Process input character with prefix 1b.
411 *
412 * @param vt VT instance
413 * @param c Input character
414 */
415static void vt100_rcvd_1b(vt100_t *vt, char c)
416{
417 switch (c) {
418 case 0x1b:
419 vt100_key(vt, 0, KC_ESCAPE, c);
420 break;
421 case 0x60:
422 vt100_key(vt, KM_ALT, KC_BACKTICK, c);
423 break;
424
425 case 0x31:
426 vt100_key(vt, KM_ALT, KC_1, c);
427 break;
428 case 0x32:
429 vt100_key(vt, KM_ALT, KC_2, c);
430 break;
431 case 0x33:
432 vt100_key(vt, KM_ALT, KC_3, c);
433 break;
434 case 0x34:
435 vt100_key(vt, KM_ALT, KC_4, c);
436 break;
437 case 0x35:
438 vt100_key(vt, KM_ALT, KC_5, c);
439 break;
440 case 0x36:
441 vt100_key(vt, KM_ALT, KC_6, c);
442 break;
443 case 0x37:
444 vt100_key(vt, KM_ALT, KC_7, c);
445 break;
446 case 0x38:
447 vt100_key(vt, KM_ALT, KC_8, c);
448 break;
449 case 0x39:
450 vt100_key(vt, KM_ALT, KC_9, c);
451 break;
452 case 0x30:
453 vt100_key(vt, KM_ALT, KC_0, c);
454 break;
455
456 case 0x2d:
457 vt100_key(vt, KM_ALT, KC_MINUS, c);
458 break;
459 case 0x3d:
460 vt100_key(vt, KM_ALT, KC_EQUALS, c);
461 break;
462
463 case 0x71:
464 vt100_key(vt, KM_ALT, KC_Q, c);
465 break;
466 case 0x77:
467 vt100_key(vt, KM_ALT, KC_W, c);
468 break;
469 case 0x65:
470 vt100_key(vt, KM_ALT, KC_E, c);
471 break;
472 case 0x72:
473 vt100_key(vt, KM_ALT, KC_R, c);
474 break;
475 case 0x74:
476 vt100_key(vt, KM_ALT, KC_T, c);
477 break;
478 case 0x79:
479 vt100_key(vt, KM_ALT, KC_Y, c);
480 break;
481 case 0x75:
482 vt100_key(vt, KM_ALT, KC_U, c);
483 break;
484 case 0x69:
485 vt100_key(vt, KM_ALT, KC_I, c);
486 break;
487 case 0x6f:
488 vt100_key(vt, KM_ALT, KC_O, c);
489 break;
490 case 0x70:
491 vt100_key(vt, KM_ALT, KC_P, c);
492 break;
493
494 /* 0x1b, 0x5b is used by other keys/sequences */
495
496 case 0x5d:
497 vt100_key(vt, KM_ALT, KC_RBRACKET, c);
498 break;
499
500 case 0x61:
501 vt100_key(vt, KM_ALT, KC_A, c);
502 break;
503 case 0x73:
504 vt100_key(vt, KM_ALT, KC_S, c);
505 break;
506 case 0x64:
507 vt100_key(vt, KM_ALT, KC_D, c);
508 break;
509 case 0x66:
510 vt100_key(vt, KM_ALT, KC_F, c);
511 break;
512 case 0x67:
513 vt100_key(vt, KM_ALT, KC_G, c);
514 break;
515 case 0x68:
516 vt100_key(vt, KM_ALT, KC_H, c);
517 break;
518 case 0x6a:
519 vt100_key(vt, KM_ALT, KC_J, c);
520 break;
521 case 0x6b:
522 vt100_key(vt, KM_ALT, KC_K, c);
523 break;
524 case 0x6c:
525 vt100_key(vt, KM_ALT, KC_L, c);
526 break;
527
528 case 0x3b:
529 vt100_key(vt, KM_ALT, KC_SEMICOLON, c);
530 break;
531 case 0x27:
532 vt100_key(vt, KM_ALT, KC_QUOTE, c);
533 break;
534 case 0x5c:
535 vt100_key(vt, KM_ALT, KC_BACKSLASH, c);
536 break;
537
538 case 0x7a:
539 vt100_key(vt, KM_ALT, KC_Z, c);
540 break;
541 case 0x78:
542 vt100_key(vt, KM_ALT, KC_X, c);
543 break;
544 case 0x63:
545 vt100_key(vt, KM_ALT, KC_C, c);
546 break;
547 case 0x76:
548 vt100_key(vt, KM_ALT, KC_V, c);
549 break;
550 case 0x62:
551 vt100_key(vt, KM_ALT, KC_B, c);
552 break;
553 case 0x6e:
554 vt100_key(vt, KM_ALT, KC_N, c);
555 break;
556 case 0x6d:
557 vt100_key(vt, KM_ALT, KC_M, c);
558 break;
559
560 case 0x2c:
561 vt100_key(vt, KM_ALT, KC_COMMA, c);
562 break;
563 case 0x2e:
564 vt100_key(vt, KM_ALT, KC_PERIOD, c);
565 break;
566 case 0x2f:
567 vt100_key(vt, KM_ALT, KC_SLASH, c);
568 break;
569
570 case 0x4f:
571 vt->state = vts_1b4f;
572 break;
573 case 0x5b:
574 vt->state = vts_1b5b;
575 break;
576 default:
577 vt->state = vts_base;
578 break;
579 }
580}
581
582/** Process input character with prefix 1b 4f.
583 *
584 * @param vt VT instance
585 * @param c Input character
586 */
587static void vt100_rcvd_1b4f(vt100_t *vt, char c)
588{
589 switch (c) {
590 case 0x50:
591 vt100_key(vt, 0, KC_F1, 0);
592 break;
593 case 0x51:
594 vt100_key(vt, 0, KC_F2, 0);
595 break;
596 case 0x52:
597 vt100_key(vt, 0, KC_F3, 0);
598 break;
599 case 0x53:
600 vt100_key(vt, 0, KC_F4, 0);
601 break;
602 case 0x48:
603 vt100_key(vt, 0, KC_HOME, 0);
604 break;
605 case 0x46:
606 vt100_key(vt, 0, KC_END, 0);
607 break;
608 default:
609 vt->state = vts_base;
610 break;
611 }
612}
613
614/** Process input character with prefix 1b 5b.
615 *
616 * @param vt VT instance
617 * @param c Input character
618 */
619static void vt100_rcvd_1b5b(vt100_t *vt, char c)
620{
621 switch (c) {
622 case 0x31:
623 vt->state = vts_1b5b31;
624 break;
625 case 0x32:
626 vt->state = vts_1b5b32;
627 break;
628 case 0x35:
629 vt->state = vts_1b5b35;
630 break;
631 case 0x33:
632 vt->state = vts_1b5b33;
633 break;
634 case 0x36:
635 vt->state = vts_1b5b36;
636 break;
637 case 0x3c:
638 vt->state = vts_1b5b3c;
639 break;
640 case 0x41:
641 vt100_key(vt, 0, KC_UP, 0);
642 break;
643 case 0x44:
644 vt100_key(vt, 0, KC_LEFT, 0);
645 break;
646 case 0x42:
647 vt100_key(vt, 0, KC_DOWN, 0);
648 break;
649 case 0x43:
650 vt100_key(vt, 0, KC_RIGHT, 0);
651 break;
652 case 0x48:
653 vt100_key(vt, 0, KC_HOME, 0);
654 break;
655 case 0x46:
656 vt100_key(vt, 0, KC_END, 0);
657 break;
658 default:
659 vt->state = vts_base;
660 break;
661 }
662}
663
664/** Process input character with prefix 1b 5b 31.
665 *
666 * @param vt VT instance
667 * @param c Input character
668 */
669static void vt100_rcvd_1b5b31(vt100_t *vt, char c)
670{
671 switch (c) {
672 case 0x35:
673 vt->state = vts_1b5b3135;
674 break;
675 case 0x37:
676 vt->state = vts_1b5b3137;
677 break;
678 case 0x38:
679 vt->state = vts_1b5b3138;
680 break;
681 case 0x39:
682 vt->state = vts_1b5b3139;
683 break;
684 case 0x3b:
685 vt->state = vts_1b5b313b;
686 break;
687 default:
688 vt->state = vts_base;
689 break;
690 }
691}
692
693/** Process input character with prefix 1b 5b 31 35.
694 *
695 * @param vt VT instance
696 * @param c Input character
697 */
698static void vt100_rcvd_1b5b3135(vt100_t *vt, char c)
699{
700 switch (c) {
701 case 0x7e:
702 vt100_key(vt, 0, KC_F5, 0);
703 break;
704 default:
705 vt->state = vts_base;
706 break;
707 }
708}
709
710/** Process input character with prefix 1b 5b 31 37.
711 *
712 * @param vt VT instance
713 * @param c Input character
714 */
715static void vt100_rcvd_1b5b3137(vt100_t *vt, char c)
716{
717 switch (c) {
718 case 0x7e:
719 vt100_key(vt, 0, KC_F6, 0);
720 break;
721 default:
722 vt->state = vts_base;
723 break;
724 }
725}
726
727/** Process input character with prefix 1b 5b 31 38.
728 *
729 * @param vt VT instance
730 * @param c Input character
731 */
732static void vt100_rcvd_1b5b3138(vt100_t *vt, char c)
733{
734 switch (c) {
735 case 0x7e:
736 vt100_key(vt, 0, KC_F7, 0);
737 break;
738 default:
739 vt->state = vts_base;
740 break;
741 }
742}
743
744/** Process input character with prefix 1b 5b 31 39.
745 *
746 * @param vt VT instance
747 * @param c Input character
748 */
749static void vt100_rcvd_1b5b3139(vt100_t *vt, char c)
750{
751 switch (c) {
752 case 0x7e:
753 vt100_key(vt, 0, KC_F8, 0);
754 break;
755 default:
756 vt->state = vts_base;
757 break;
758 }
759}
760
761/** Process input character with prefix 1b 5b 31 3b.
762 *
763 * @param vt VT instance
764 * @param c Input character
765 */
766static void vt100_rcvd_1b5b313b(vt100_t *vt, char c)
767{
768 switch (c) {
769 case 0x32:
770 vt->state = vts_1b5b313b32;
771 break;
772 case 0x33:
773 vt->state = vts_1b5b313b33;
774 break;
775 default:
776 vt->state = vts_base;
777 break;
778 }
779}
780
781/** Process input character with prefix 1b 5b 31 3b 32.
782 *
783 * @param vt VT instance
784 * @param c Input character
785 */
786static void vt100_rcvd_1b5b313b32(vt100_t *vt, char c)
787{
788 switch (c) {
789 case 0x41:
790 vt100_key(vt, KM_SHIFT, KC_UP, 0);
791 break;
792 case 0x44:
793 vt100_key(vt, KM_SHIFT, KC_LEFT, 0);
794 break;
795 case 0x42:
796 vt100_key(vt, KM_SHIFT, KC_DOWN, 0);
797 break;
798 case 0x43:
799 vt100_key(vt, KM_SHIFT, KC_RIGHT, 0);
800 break;
801 case 0x48:
802 vt100_key(vt, KM_SHIFT, KC_HOME, 0);
803 break;
804 case 0x46:
805 vt100_key(vt, KM_SHIFT, KC_END, 0);
806 break;
807 default:
808 vt->state = vts_base;
809 break;
810 }
811}
812
813/** Process input character with prefix 1b 5b 31 3b 33.
814 *
815 * @param vt VT instance
816 * @param c Input character
817 */
818static void vt100_rcvd_1b5b313b33(vt100_t *vt, char c)
819{
820 switch (c) {
821 case 0x41:
822 vt100_key(vt, KM_ALT, KC_UP, 0);
823 break;
824 case 0x44:
825 vt100_key(vt, KM_ALT, KC_LEFT, 0);
826 break;
827 case 0x42:
828 vt100_key(vt, KM_ALT, KC_DOWN, 0);
829 break;
830 case 0x43:
831 vt100_key(vt, KM_ALT, KC_RIGHT, 0);
832 break;
833 case 0x48:
834 vt100_key(vt, KM_ALT, KC_HOME, 0);
835 break;
836 case 0x46:
837 vt100_key(vt, KM_ALT, KC_END, 0);
838 break;
839 default:
840 vt->state = vts_base;
841 break;
842 }
843}
844
845/** Process input character with prefix 1b 5b 32.
846 *
847 * @param vt VT instance
848 * @param c Input character
849 */
850static void vt100_rcvd_1b5b32(vt100_t *vt, char c)
851{
852 switch (c) {
853 case 0x30:
854 vt->state = vts_1b5b3230;
855 break;
856 case 0x31:
857 vt->state = vts_1b5b3231;
858 break;
859 case 0x33:
860 vt->state = vts_1b5b3233;
861 break;
862 case 0x34:
863 vt->state = vts_1b5b3234;
864 break;
865 case 0x35:
866 vt->state = vts_1b5b3235;
867 break;
868 case 0x38:
869 vt->state = vts_1b5b3238;
870 break;
871 case 0x7e:
872 vt100_key(vt, 0, KC_INSERT, 0);
873 break;
874 default:
875 vt->state = vts_base;
876 break;
877 }
878}
879
880/** Process input character with prefix 1b 5b 32 30.
881 *
882 * @param vt VT instance
883 * @param c Input character
884 */
885static void vt100_rcvd_1b5b3230(vt100_t *vt, char c)
886{
887 switch (c) {
888 case 0x7e:
889 vt100_key(vt, 0, KC_F9, 0);
890 break;
891 default:
892 vt->state = vts_base;
893 break;
894 }
895}
896
897/** Process input character with prefix 1b 5b 32 31.
898 *
899 * @param vt VT instance
900 * @param c Input character
901 */
902static void vt100_rcvd_1b5b3231(vt100_t *vt, char c)
903{
904 switch (c) {
905 case 0x7e:
906 vt100_key(vt, 0, KC_F10, 0);
907 break;
908 default:
909 vt->state = vts_base;
910 break;
911 }
912}
913
914/** Process input character with prefix 1b 5b 32 33.
915 *
916 * @param vt VT instance
917 * @param c Input character
918 */
919static void vt100_rcvd_1b5b3233(vt100_t *vt, char c)
920{
921 switch (c) {
922 case 0x7e:
923 vt100_key(vt, 0, KC_F11, 0);
924 break;
925 default:
926 vt->state = vts_base;
927 break;
928 }
929}
930
931/** Process input character with prefix 1b 5b 32 34.
932 *
933 * @param vt VT instance
934 * @param c Input character
935 */
936static void vt100_rcvd_1b5b3234(vt100_t *vt, char c)
937{
938 switch (c) {
939 case 0x7e:
940 vt100_key(vt, 0, KC_F12, 0);
941 break;
942 default:
943 vt->state = vts_base;
944 break;
945 }
946}
947
948/** Process input character with prefix 1b 5b 32 35.
949 *
950 * @param vt VT instance
951 * @param c Input character
952 */
953static void vt100_rcvd_1b5b3235(vt100_t *vt, char c)
954{
955 switch (c) {
956 case 0x7e:
957 vt100_key(vt, 0, KC_PRTSCR, 0);
958 break;
959 default:
960 vt->state = vts_base;
961 break;
962 }
963}
964
965/** Process input character with prefix 1b 5b 32 38.
966 *
967 * @param vt VT instance
968 * @param c Input character
969 */
970static void vt100_rcvd_1b5b3238(vt100_t *vt, char c)
971{
972 switch (c) {
973 case 0x7e:
974 vt100_key(vt, 0, KC_PAUSE, 0);
975 break;
976 default:
977 vt->state = vts_base;
978 break;
979 }
980}
981
982/** Process input character with prefix 1b 5b 35.
983 *
984 * @param vt VT instance
985 * @param c Input character
986 */
987static void vt100_rcvd_1b5b35(vt100_t *vt, char c)
988{
989 switch (c) {
990 case 0x7e:
991 vt100_key(vt, 0, KC_PAGE_UP, 0);
992 break;
993 default:
994 vt->state = vts_base;
995 break;
996 }
997}
998
999/** Process input character with prefix 1b 5b 33.
1000 *
1001 * @param vt VT instance
1002 * @param c Input character
1003 */
1004static void vt100_rcvd_1b5b33(vt100_t *vt, char c)
1005{
1006 switch (c) {
1007 case 0x7e:
1008 vt100_key(vt, 0, KC_DELETE, 0);
1009 break;
1010 default:
1011 vt->state = vts_base;
1012 break;
1013 }
1014}
1015
1016/** Process input character with prefix 1b 5b 36.
1017 *
1018 * @param vt VT instance
1019 * @param c Input character
1020 */
1021static void vt100_rcvd_1b5b36(vt100_t *vt, char c)
1022{
1023 switch (c) {
1024 case 0x7e:
1025 vt100_key(vt, 0, KC_PAGE_DOWN, 0);
1026 break;
1027 default:
1028 vt->state = vts_base;
1029 break;
1030 }
1031}
1032
1033/** Process input character with prefix 1b 5b 3c - mouse report.
1034 *
1035 * @param vt VT instance
1036 * @param c Input character
1037 */
1038static void vt100_rcvd_1b5b3c(vt100_t *vt, char c)
1039{
1040 pos_event_t ev;
1041
1042 if (isdigit(c)) {
1043 /* Decode next base-10 digit */
1044 vt->innum[vt->inncnt] = vt->innum[vt->inncnt] * 10 + (c - '0');
1045 } else if (c == ';') {
1046 /* Move to next parameter */
1047 if (vt->inncnt >= INNUM_MAX - 1) {
1048 vt->state = vts_base;
1049 vt100_clear_innum(vt);
1050 return;
1051 }
1052 ++vt->inncnt;
1053 } else {
1054 switch (c) {
1055 case 'M':
1056 case 'm':
1057 /* Button press / release */
1058 ev.pos_id = 0;
1059 ev.type = (c == 'M') ? POS_PRESS : POS_RELEASE;
1060
1061 /*
1062 * VT reports button 0 = left button,
1063 * 1 = middle, 2 = right.
1064 * pos_event needs 1 = left, 2 = right, 3 = middle,...
1065 * so right and middle need to be reversed.
1066 */
1067 switch (vt->innum[0]) {
1068 case 1:
1069 ev.btn_num = 3;
1070 break;
1071 case 2:
1072 ev.btn_num = 2;
1073 break;
1074 default:
1075 ev.btn_num = 1 + vt->innum[0];
1076 break;
1077 }
1078 ev.hpos = vt->innum[1] - 1;
1079 ev.vpos = vt->innum[2] - 1;
1080 vt100_pos_event(vt, &ev);
1081 break;
1082 }
1083 vt100_clear_innum(vt);
1084 vt->state = vts_base;
1085 }
1086}
1087
1088/** Process input character (base state, no prefix).
1089 *
1090 * @param vt VT instance
1091 * @param c Input character
1092 */
1093static void vt100_rcvd_base(vt100_t *vt, char c)
1094{
1095 switch (c) {
1096 /*
1097 * Not shifted
1098 */
1099 case 0x60:
1100 vt100_key(vt, 0, KC_BACKTICK, c);
1101 break;
1102
1103 case 0x31:
1104 vt100_key(vt, 0, KC_1, c);
1105 break;
1106 case 0x32:
1107 vt100_key(vt, 0, KC_2, c);
1108 break;
1109 case 0x33:
1110 vt100_key(vt, 0, KC_3, c);
1111 break;
1112 case 0x34:
1113 vt100_key(vt, 0, KC_4, c);
1114 break;
1115 case 0x35:
1116 vt100_key(vt, 0, KC_5, c);
1117 break;
1118 case 0x36:
1119 vt100_key(vt, 0, KC_6, c);
1120 break;
1121 case 0x37:
1122 vt100_key(vt, 0, KC_7, c);
1123 break;
1124 case 0x38:
1125 vt100_key(vt, 0, KC_8, c);
1126 break;
1127 case 0x39:
1128 vt100_key(vt, 0, KC_9, c);
1129 break;
1130 case 0x30:
1131 vt100_key(vt, 0, KC_0, c);
1132 break;
1133 case 0x2d:
1134 vt100_key(vt, 0, KC_MINUS, c);
1135 break;
1136 case 0x3d:
1137 vt100_key(vt, 0, KC_EQUALS, c);
1138 break;
1139
1140 case 0x08:
1141 vt100_key(vt, 0, KC_BACKSPACE, c);
1142 break;
1143
1144 case 0x09:
1145 vt100_key(vt, 0, KC_TAB, c);
1146 break;
1147
1148 case 0x71:
1149 vt100_key(vt, 0, KC_Q, c);
1150 break;
1151 case 0x77:
1152 vt100_key(vt, 0, KC_W, c);
1153 break;
1154 case 0x65:
1155 vt100_key(vt, 0, KC_E, c);
1156 break;
1157 case 0x72:
1158 vt100_key(vt, 0, KC_R, c);
1159 break;
1160 case 0x74:
1161 vt100_key(vt, 0, KC_T, c);
1162 break;
1163 case 0x79:
1164 vt100_key(vt, 0, KC_Y, c);
1165 break;
1166 case 0x75:
1167 vt100_key(vt, 0, KC_U, c);
1168 break;
1169 case 0x69:
1170 vt100_key(vt, 0, KC_I, c);
1171 break;
1172 case 0x6f:
1173 vt100_key(vt, 0, KC_O, c);
1174 break;
1175 case 0x70:
1176 vt100_key(vt, 0, KC_P, c);
1177 break;
1178
1179 case 0x5b:
1180 vt100_key(vt, 0, KC_LBRACKET, c);
1181 break;
1182 case 0x5d:
1183 vt100_key(vt, 0, KC_RBRACKET, c);
1184 break;
1185
1186 case 0x61:
1187 vt100_key(vt, 0, KC_A, c);
1188 break;
1189 case 0x73:
1190 vt100_key(vt, 0, KC_S, c);
1191 break;
1192 case 0x64:
1193 vt100_key(vt, 0, KC_D, c);
1194 break;
1195 case 0x66:
1196 vt100_key(vt, 0, KC_F, c);
1197 break;
1198 case 0x67:
1199 vt100_key(vt, 0, KC_G, c);
1200 break;
1201 case 0x68:
1202 vt100_key(vt, 0, KC_H, c);
1203 break;
1204 case 0x6a:
1205 vt100_key(vt, 0, KC_J, c);
1206 break;
1207 case 0x6b:
1208 vt100_key(vt, 0, KC_K, c);
1209 break;
1210 case 0x6c:
1211 vt100_key(vt, 0, KC_L, c);
1212 break;
1213
1214 case 0x3b:
1215 vt100_key(vt, 0, KC_SEMICOLON, c);
1216 break;
1217 case 0x27:
1218 vt100_key(vt, 0, KC_QUOTE, c);
1219 break;
1220 case 0x5c:
1221 vt100_key(vt, 0, KC_BACKSLASH, c);
1222 break;
1223
1224 case 0x7a:
1225 vt100_key(vt, 0, KC_Z, c);
1226 break;
1227 case 0x78:
1228 vt100_key(vt, 0, KC_X, c);
1229 break;
1230 case 0x63:
1231 vt100_key(vt, 0, KC_C, c);
1232 break;
1233 case 0x76:
1234 vt100_key(vt, 0, KC_V, c);
1235 break;
1236 case 0x62:
1237 vt100_key(vt, 0, KC_B, c);
1238 break;
1239 case 0x6e:
1240 vt100_key(vt, 0, KC_N, c);
1241 break;
1242 case 0x6d:
1243 vt100_key(vt, 0, KC_M, c);
1244 break;
1245
1246 case 0x2c:
1247 vt100_key(vt, 0, KC_COMMA, c);
1248 break;
1249 case 0x2e:
1250 vt100_key(vt, 0, KC_PERIOD, c);
1251 break;
1252 case 0x2f:
1253 vt100_key(vt, 0, KC_SLASH, c);
1254 break;
1255
1256 /*
1257 * Shifted
1258 */
1259 case 0x7e:
1260 vt100_key(vt, KM_SHIFT, KC_BACKTICK, c);
1261 break;
1262
1263 case 0x21:
1264 vt100_key(vt, KM_SHIFT, KC_1, c);
1265 break;
1266 case 0x40:
1267 vt100_key(vt, KM_SHIFT, KC_2, c);
1268 break;
1269 case 0x23:
1270 vt100_key(vt, KM_SHIFT, KC_3, c);
1271 break;
1272 case 0x24:
1273 vt100_key(vt, KM_SHIFT, KC_4, c);
1274 break;
1275 case 0x25:
1276 vt100_key(vt, KM_SHIFT, KC_5, c);
1277 break;
1278 case 0x5e:
1279 vt100_key(vt, KM_SHIFT, KC_6, c);
1280 break;
1281 case 0x26:
1282 vt100_key(vt, KM_SHIFT, KC_7, c);
1283 break;
1284 case 0x2a:
1285 vt100_key(vt, KM_SHIFT, KC_8, c);
1286 break;
1287 case 0x28:
1288 vt100_key(vt, KM_SHIFT, KC_9, c);
1289 break;
1290 case 0x29:
1291 vt100_key(vt, KM_SHIFT, KC_0, c);
1292 break;
1293 case 0x5f:
1294 vt100_key(vt, KM_SHIFT, KC_MINUS, c);
1295 break;
1296 case 0x2b:
1297 vt100_key(vt, KM_SHIFT, KC_EQUALS, c);
1298 break;
1299
1300 case 0x51:
1301 vt100_key(vt, KM_SHIFT, KC_Q, c);
1302 break;
1303 case 0x57:
1304 vt100_key(vt, KM_SHIFT, KC_W, c);
1305 break;
1306 case 0x45:
1307 vt100_key(vt, KM_SHIFT, KC_E, c);
1308 break;
1309 case 0x52:
1310 vt100_key(vt, KM_SHIFT, KC_R, c);
1311 break;
1312 case 0x54:
1313 vt100_key(vt, KM_SHIFT, KC_T, c);
1314 break;
1315 case 0x59:
1316 vt100_key(vt, KM_SHIFT, KC_Y, c);
1317 break;
1318 case 0x55:
1319 vt100_key(vt, KM_SHIFT, KC_U, c);
1320 break;
1321 case 0x49:
1322 vt100_key(vt, KM_SHIFT, KC_I, c);
1323 break;
1324 case 0x4f:
1325 vt100_key(vt, KM_SHIFT, KC_O, c);
1326 break;
1327 case 0x50:
1328 vt100_key(vt, KM_SHIFT, KC_P, c);
1329 break;
1330
1331 case 0x7b:
1332 vt100_key(vt, KM_SHIFT, KC_LBRACKET, c);
1333 break;
1334 case 0x7d:
1335 vt100_key(vt, KM_SHIFT, KC_RBRACKET, c);
1336 break;
1337
1338 case 0x41:
1339 vt100_key(vt, KM_SHIFT, KC_A, c);
1340 break;
1341 case 0x53:
1342 vt100_key(vt, KM_SHIFT, KC_S, c);
1343 break;
1344 case 0x44:
1345 vt100_key(vt, KM_SHIFT, KC_D, c);
1346 break;
1347 case 0x46:
1348 vt100_key(vt, KM_SHIFT, KC_F, c);
1349 break;
1350 case 0x47:
1351 vt100_key(vt, KM_SHIFT, KC_G, c);
1352 break;
1353 case 0x48:
1354 vt100_key(vt, KM_SHIFT, KC_H, c);
1355 break;
1356 case 0x4a:
1357 vt100_key(vt, KM_SHIFT, KC_J, c);
1358 break;
1359 case 0x4b:
1360 vt100_key(vt, KM_SHIFT, KC_K, c);
1361 break;
1362 case 0x4c:
1363 vt100_key(vt, KM_SHIFT, KC_L, c);
1364 break;
1365
1366 case 0x3a:
1367 vt100_key(vt, KM_SHIFT, KC_SEMICOLON, c);
1368 break;
1369 case 0x22:
1370 vt100_key(vt, KM_SHIFT, KC_QUOTE, c);
1371 break;
1372 case 0x7c:
1373 vt100_key(vt, KM_SHIFT, KC_BACKSLASH, c);
1374 break;
1375
1376 case 0x5a:
1377 vt100_key(vt, KM_SHIFT, KC_Z, c);
1378 break;
1379 case 0x58:
1380 vt100_key(vt, KM_SHIFT, KC_X, c);
1381 break;
1382 case 0x43:
1383 vt100_key(vt, KM_SHIFT, KC_C, c);
1384 break;
1385 case 0x56:
1386 vt100_key(vt, KM_SHIFT, KC_V, c);
1387 break;
1388 case 0x42:
1389 vt100_key(vt, KM_SHIFT, KC_B, c);
1390 break;
1391 case 0x4e:
1392 vt100_key(vt, KM_SHIFT, KC_N, c);
1393 break;
1394 case 0x4d:
1395 vt100_key(vt, KM_SHIFT, KC_M, c);
1396 break;
1397
1398 case 0x3c:
1399 vt100_key(vt, KM_SHIFT, KC_COMMA, c);
1400 break;
1401 case 0x3e:
1402 vt100_key(vt, KM_SHIFT, KC_PERIOD, c);
1403 break;
1404 case 0x3f:
1405 vt100_key(vt, KM_SHIFT, KC_SLASH, c);
1406 break;
1407
1408 /*
1409 * ...
1410 */
1411 case 0x20:
1412 vt100_key(vt, 0, KC_SPACE, c);
1413 break;
1414 case 0x0a:
1415 vt100_key(vt, 0, KC_ENTER, '\n');
1416 break;
1417 case 0x0d:
1418 vt100_key(vt, 0, KC_ENTER, '\n');
1419 break;
1420
1421 /*
1422 * Ctrl + key
1423 */
1424 case 0x11:
1425 vt100_key(vt, KM_CTRL, KC_Q, c);
1426 break;
1427 case 0x17:
1428 vt100_key(vt, KM_CTRL, KC_W, c);
1429 break;
1430 case 0x05:
1431 vt100_key(vt, KM_CTRL, KC_E, c);
1432 break;
1433 case 0x12:
1434 vt100_key(vt, KM_CTRL, KC_R, c);
1435 break;
1436 case 0x14:
1437 vt100_key(vt, KM_CTRL, KC_T, c);
1438 break;
1439 case 0x19:
1440 vt100_key(vt, KM_CTRL, KC_Y, c);
1441 break;
1442 case 0x15:
1443 vt100_key(vt, KM_CTRL, KC_U, c);
1444 break;
1445 case 0x0f:
1446 vt100_key(vt, KM_CTRL, KC_O, c);
1447 break;
1448 case 0x10:
1449 vt100_key(vt, KM_CTRL, KC_P, c);
1450 break;
1451
1452 case 0x01:
1453 vt100_key(vt, KM_CTRL, KC_A, c);
1454 break;
1455 case 0x13:
1456 vt100_key(vt, KM_CTRL, KC_S, c);
1457 break;
1458 case 0x04:
1459 vt100_key(vt, KM_CTRL, KC_D, c);
1460 break;
1461 case 0x06:
1462 vt100_key(vt, KM_CTRL, KC_F, c);
1463 break;
1464 case 0x07:
1465 vt100_key(vt, KM_CTRL, KC_G, c);
1466 break;
1467 case 0x0b:
1468 vt100_key(vt, KM_CTRL, KC_K, c);
1469 break;
1470 case 0x0c:
1471 vt100_key(vt, KM_CTRL, KC_L, c);
1472 break;
1473
1474 case 0x1a:
1475 vt100_key(vt, KM_CTRL, KC_Z, c);
1476 break;
1477 case 0x18:
1478 vt100_key(vt, KM_CTRL, KC_X, c);
1479 break;
1480 case 0x03:
1481 vt100_key(vt, KM_CTRL, KC_C, c);
1482 break;
1483 case 0x16:
1484 vt100_key(vt, KM_CTRL, KC_V, c);
1485 break;
1486 case 0x02:
1487 vt100_key(vt, KM_CTRL, KC_B, c);
1488 break;
1489 case 0x0e:
1490 vt100_key(vt, KM_CTRL, KC_N, c);
1491 break;
1492
1493 case 0x7f:
1494 vt100_key(vt, 0, KC_BACKSPACE, '\b');
1495 break;
1496
1497 case 0x1b:
1498 vt->state = vts_1b;
1499 break;
1500 }
1501}
1502
1503void vt100_rcvd_char(vt100_t *vt, char c)
1504{
1505 switch (vt->state) {
1506 case vts_base:
1507 vt100_rcvd_base(vt, c);
1508 break;
1509 case vts_1b:
1510 vt100_rcvd_1b(vt, c);
1511 break;
1512 case vts_1b4f:
1513 vt100_rcvd_1b4f(vt, c);
1514 break;
1515 case vts_1b5b:
1516 vt100_rcvd_1b5b(vt, c);
1517 break;
1518 case vts_1b5b31:
1519 vt100_rcvd_1b5b31(vt, c);
1520 break;
1521 case vts_1b5b3135:
1522 vt100_rcvd_1b5b3135(vt, c);
1523 break;
1524 case vts_1b5b3137:
1525 vt100_rcvd_1b5b3137(vt, c);
1526 break;
1527 case vts_1b5b3138:
1528 vt100_rcvd_1b5b3138(vt, c);
1529 break;
1530 case vts_1b5b3139:
1531 vt100_rcvd_1b5b3139(vt, c);
1532 break;
1533 case vts_1b5b313b:
1534 vt100_rcvd_1b5b313b(vt, c);
1535 break;
1536 case vts_1b5b313b32:
1537 vt100_rcvd_1b5b313b32(vt, c);
1538 break;
1539 case vts_1b5b313b33:
1540 vt100_rcvd_1b5b313b33(vt, c);
1541 break;
1542 case vts_1b5b32:
1543 vt100_rcvd_1b5b32(vt, c);
1544 break;
1545 case vts_1b5b3230:
1546 vt100_rcvd_1b5b3230(vt, c);
1547 break;
1548 case vts_1b5b3231:
1549 vt100_rcvd_1b5b3231(vt, c);
1550 break;
1551 case vts_1b5b3233:
1552 vt100_rcvd_1b5b3233(vt, c);
1553 break;
1554 case vts_1b5b3234:
1555 vt100_rcvd_1b5b3234(vt, c);
1556 break;
1557 case vts_1b5b3235:
1558 vt100_rcvd_1b5b3235(vt, c);
1559 break;
1560 case vts_1b5b3238:
1561 vt100_rcvd_1b5b3238(vt, c);
1562 break;
1563 case vts_1b5b35:
1564 vt100_rcvd_1b5b35(vt, c);
1565 break;
1566 case vts_1b5b33:
1567 vt100_rcvd_1b5b33(vt, c);
1568 break;
1569 case vts_1b5b36:
1570 vt100_rcvd_1b5b36(vt, c);
1571 break;
1572 case vts_1b5b3c:
1573 vt100_rcvd_1b5b3c(vt, c);
1574 break;
1575 }
1576}
1577
1578/** @}
1579 */
Note: See TracBrowser for help on using the repository browser.