source: mainline/uspace/srv/hid/output/proto/vt100.c@ e7dc3a4

ticket/834-toolchain-update
Last change on this file since e7dc3a4 was ead72f2, checked in by Jiri Svoboda <jiri@…>, 4 years ago

Fix mapping of blue color on ECMA/VT-100

Don't wanna be seeing red when playing Tetris

  • Property mode set to 100644
File size: 6.0 KB
Line 
1/*
2 * Copyright (c) 2021 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 output
31 * @{
32 */
33
34#include <inttypes.h>
35#include <errno.h>
36#include <stddef.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <io/color.h>
40#include <types/common.h>
41#include "vt100.h"
42
43#define MAX_CONTROL 20
44
45typedef enum {
46 CI_BLACK = 0,
47 CI_RED = 1,
48 CI_GREEN = 2,
49 CI_BROWN = 3,
50 CI_BLUE = 4,
51 CI_MAGENTA = 5,
52 CI_CYAN = 6,
53 CI_WHITE = 7
54} sgr_color_index_t;
55
56typedef enum {
57 SGR_RESET = 0,
58 SGR_BOLD = 1,
59 SGR_UNDERLINE = 4,
60 SGR_BLINK = 5,
61 SGR_REVERSE = 7,
62 SGR_FGCOLOR = 30,
63 SGR_BGCOLOR = 40
64} sgr_command_t;
65
66static sgr_color_index_t color_map[] = {
67 [COLOR_BLACK] = CI_BLACK,
68 [COLOR_BLUE] = CI_BLUE,
69 [COLOR_GREEN] = CI_GREEN,
70 [COLOR_CYAN] = CI_CYAN,
71 [COLOR_RED] = CI_RED,
72 [COLOR_MAGENTA] = CI_MAGENTA,
73 [COLOR_YELLOW] = CI_BROWN,
74 [COLOR_WHITE] = CI_WHITE
75};
76
77/** ECMA-48 Set Graphics Rendition. */
78static void vt100_sgr(vt100_state_t *state, unsigned int mode)
79{
80 char control[MAX_CONTROL];
81
82 snprintf(control, MAX_CONTROL, "\033[%um", mode);
83 state->control_puts(control);
84}
85
86static void vt100_set_pos(vt100_state_t *state, sysarg_t col, sysarg_t row)
87{
88 char control[MAX_CONTROL];
89
90 snprintf(control, MAX_CONTROL, "\033[%" PRIun ";%" PRIun "f",
91 row + 1, col + 1);
92 state->control_puts(control);
93}
94
95static void vt100_set_sgr(vt100_state_t *state, char_attrs_t attrs)
96{
97 switch (attrs.type) {
98 case CHAR_ATTR_STYLE:
99 switch (attrs.val.style) {
100 case STYLE_NORMAL:
101 vt100_sgr(state, SGR_RESET);
102 vt100_sgr(state, SGR_BGCOLOR + CI_WHITE);
103 vt100_sgr(state, SGR_FGCOLOR + CI_BLACK);
104 break;
105 case STYLE_EMPHASIS:
106 vt100_sgr(state, SGR_RESET);
107 vt100_sgr(state, SGR_BGCOLOR + CI_WHITE);
108 vt100_sgr(state, SGR_FGCOLOR + CI_RED);
109 vt100_sgr(state, SGR_BOLD);
110 break;
111 case STYLE_INVERTED:
112 vt100_sgr(state, SGR_RESET);
113 vt100_sgr(state, SGR_BGCOLOR + CI_BLACK);
114 vt100_sgr(state, SGR_FGCOLOR + CI_WHITE);
115 break;
116 case STYLE_SELECTED:
117 vt100_sgr(state, SGR_RESET);
118 vt100_sgr(state, SGR_BGCOLOR + CI_RED);
119 vt100_sgr(state, SGR_FGCOLOR + CI_WHITE);
120 break;
121 }
122 break;
123 case CHAR_ATTR_INDEX:
124 vt100_sgr(state, SGR_RESET);
125 vt100_sgr(state, SGR_BGCOLOR + color_map[attrs.val.index.bgcolor & 7]);
126 vt100_sgr(state, SGR_FGCOLOR + color_map[attrs.val.index.fgcolor & 7]);
127
128 if (attrs.val.index.attr & CATTR_BRIGHT)
129 vt100_sgr(state, SGR_BOLD);
130
131 break;
132 case CHAR_ATTR_RGB:
133 vt100_sgr(state, SGR_RESET);
134
135 if (attrs.val.rgb.bgcolor <= attrs.val.rgb.fgcolor)
136 vt100_sgr(state, SGR_REVERSE);
137
138 break;
139 }
140}
141
142vt100_state_t *vt100_state_create(sysarg_t cols, sysarg_t rows,
143 vt100_putuchar_t putuchar_fn, vt100_control_puts_t control_puts_fn,
144 vt100_flush_t flush_fn)
145{
146 vt100_state_t *state = malloc(sizeof(vt100_state_t));
147 if (state == NULL)
148 return NULL;
149
150 state->putuchar = putuchar_fn;
151 state->control_puts = control_puts_fn;
152 state->flush = flush_fn;
153
154 state->cols = cols;
155 state->rows = rows;
156
157 state->cur_col = (sysarg_t) -1;
158 state->cur_row = (sysarg_t) -1;
159
160 state->cur_attrs.type = CHAR_ATTR_STYLE;
161 state->cur_attrs.val.style = STYLE_NORMAL;
162
163 /* Initialize graphic rendition attributes */
164 vt100_sgr(state, SGR_RESET);
165 vt100_sgr(state, SGR_FGCOLOR + CI_BLACK);
166 vt100_sgr(state, SGR_BGCOLOR + CI_WHITE);
167 state->control_puts("\033[2J");
168 state->control_puts("\033[?25l");
169
170 return state;
171}
172
173void vt100_state_destroy(vt100_state_t *state)
174{
175 free(state);
176}
177
178void vt100_get_dimensions(vt100_state_t *state, sysarg_t *cols,
179 sysarg_t *rows)
180{
181 *cols = state->cols;
182 *rows = state->rows;
183}
184
185errno_t vt100_yield(vt100_state_t *state)
186{
187 return EOK;
188}
189
190errno_t vt100_claim(vt100_state_t *state)
191{
192 return EOK;
193}
194
195void vt100_goto(vt100_state_t *state, sysarg_t col, sysarg_t row)
196{
197 if ((col >= state->cols) || (row >= state->rows))
198 return;
199
200 if ((col != state->cur_col) || (row != state->cur_row)) {
201 vt100_set_pos(state, col, row);
202 state->cur_col = col;
203 state->cur_row = row;
204 }
205}
206
207void vt100_set_attr(vt100_state_t *state, char_attrs_t attrs)
208{
209 if (!attrs_same(state->cur_attrs, attrs)) {
210 vt100_set_sgr(state, attrs);
211 state->cur_attrs = attrs;
212 }
213}
214
215void vt100_cursor_visibility(vt100_state_t *state, bool visible)
216{
217 if (visible)
218 state->control_puts("\033[?25h");
219 else
220 state->control_puts("\033[?25l");
221}
222
223void vt100_putuchar(vt100_state_t *state, char32_t ch)
224{
225 state->putuchar(ch == 0 ? ' ' : ch);
226 state->cur_col++;
227
228 if (state->cur_col >= state->cols) {
229 state->cur_row += state->cur_col / state->cols;
230 state->cur_col %= state->cols;
231 }
232}
233
234void vt100_flush(vt100_state_t *state)
235{
236 state->flush();
237}
238
239/** @}
240 */
Note: See TracBrowser for help on using the repository browser.