PatchworkOS  3984a1d
A non-POSIX operating system.
Loading...
Searching...
No Matches
ansi.h
Go to the documentation of this file.
1#pragma once
2
3#include <ctype.h>
5#include <stdbool.h>
6#include <stdint.h>
7#include <string.h>
8
9/**
10 * @brief ANSI.
11 * @defgroup programs_terminal_ansi ANSI
12 * @ingroup programs_terminal
13 *
14 * @{
15 */
16
17/**
18 * @brief The size we use for buffers when parsing ANSI sequences.
19 */
20#define ANSI_MAX_LENGTH 32
21
22/**
23 * @brief ANSI receiving structure.
24 * @struct ansi_receiving_t
25 */
31
32/**
33 * @brief Convert a keycode to an ANSI receiving sequence.
34 *
35 * A receiving sequence is a sequence sent from the terminal and received by processes running in the terminal.
36 *
37 * @param ansi The receiving structure to store the sequence in.
38 * @param kbd The keyboard event to convert.
39 */
41{
42 switch (kbd->code)
43 {
44 case KBD_BACKSPACE:
45 ansi->buffer[0] = '\b';
46 ansi->length = 1;
47 break;
48 case KBD_ENTER:
49 ansi->buffer[0] = '\n';
50 ansi->length = 1;
51 break;
52 case KBD_TAB:
53 ansi->buffer[0] = '\t';
54 ansi->length = 1;
55 break;
56 case KBD_DELETE:
57 ansi->buffer[0] = '\033';
58 ansi->buffer[1] = '[';
59 ansi->buffer[2] = '3';
60 ansi->buffer[3] = '~';
61 ansi->length = 4;
62 break;
63 case KBD_UP:
64 ansi->buffer[0] = '\033';
65 ansi->buffer[1] = '[';
66 ansi->buffer[2] = 'A';
67 ansi->length = 3;
68 break;
69 case KBD_DOWN:
70 ansi->buffer[0] = '\033';
71 ansi->buffer[1] = '[';
72 ansi->buffer[2] = 'B';
73 ansi->length = 3;
74 break;
75 case KBD_RIGHT:
76 ansi->buffer[0] = '\033';
77 ansi->buffer[1] = '[';
78 ansi->buffer[2] = 'C';
79 ansi->length = 3;
80 break;
81 case KBD_LEFT:
82 ansi->buffer[0] = '\033';
83 ansi->buffer[1] = '[';
84 ansi->buffer[2] = 'D';
85 ansi->length = 3;
86 break;
87 case KBD_PAGE_UP:
88 ansi->buffer[0] = '\033';
89 ansi->buffer[1] = '[';
90 ansi->buffer[2] = '5';
91 ansi->buffer[3] = '~';
92 ansi->length = 4;
93 break;
94 case KBD_PAGE_DOWN:
95 ansi->buffer[0] = '\033';
96 ansi->buffer[1] = '[';
97 ansi->buffer[2] = '6';
98 ansi->buffer[3] = '~';
99 ansi->length = 4;
100 ;
101 break;
102 case KBD_HOME:
103 ansi->buffer[0] = '\033';
104 ansi->buffer[1] = '[';
105 ansi->buffer[2] = '7';
106 ansi->buffer[3] = '~';
107 ansi->length = 4;
108 break;
109 case KBD_END:
110 ansi->buffer[0] = '\033';
111 ansi->buffer[1] = '[';
112 ansi->buffer[2] = '8';
113 ansi->buffer[3] = '~';
114 ansi->length = 4;
115 break;
116 case KBD_C:
117 if (kbd->mods & KBD_MOD_CTRL)
118 {
119 ansi->buffer[0] = '\003';
120 ansi->length = 1;
121 break;
122 }
123 default: // Fallthrough
124 if (kbd->ascii >= 32 && kbd->ascii < 126)
125 {
126 ansi->buffer[0] = kbd->ascii;
127 ansi->length = 1;
128 return;
129 }
130 ansi->length = 0;
131 break;
132 }
133}
134
135/**
136 * @brief ANSI sending structure.
137 * @struct ansi_sending_t
138 */
139typedef struct
140{
146 bool ascii;
147 bool extended; ///< The command contains a '?' indicating an extended command.
149
150/**
151 * @brief Initialize an ANSI sending structure.
152 *
153 * @param ansi The sending structure to initialize.
154 */
156{
157 memset(ansi->buffer, 0, sizeof(ansi->buffer));
158 ansi->length = 0;
159 memset(ansi->parameters, 0, sizeof(ansi->parameters));
160 ansi->paramCount = 0;
161 ansi->command = '\0';
162 ansi->ascii = false;
163}
164
165/**
166 * @brief Parse a character for ANSI sending.
167 *
168 * @param ansi The sending structure.
169 * @param chr The character to parse.
170 * @return Whether the sequence is complete or still parsing.
171 */
172static inline bool ansi_sending_parse(ansi_sending_t* ansi, char chr)
173{
174 ansi->buffer[ansi->length++] = chr;
175 ansi->buffer[ansi->length] = '\0';
176
177 if (ansi->length == 1)
178 {
179 switch (ansi->buffer[0])
180 {
181 case '\033':
182 ansi->parameters[0] = 0; // Reset
183 ansi->paramCount = 0;
184 ansi->extended = false;
185 return false;
186 default:
187 ansi->command = ansi->buffer[0];
188 ansi->ascii = true;
189 ansi->extended = false;
190 ansi->length = 0;
191 ansi->paramCount = 0;
192 return true;
193 }
194 }
195
196 if (ansi->length == 2)
197 {
198 if (ansi->buffer[1] == '[')
199 {
200 return false;
201 }
202 else
203 {
205 return false;
206 }
207 }
208
209 if (ansi->length == 3 && ansi->buffer[2] == '?')
210 {
211 ansi->extended = true;
212 return false;
213 }
214
215 if (ansi->length >= ANSI_MAX_LENGTH - 1)
216 {
218 return false;
219 }
220
221 if (isdigit(ansi->buffer[ansi->length - 1]))
222 {
223 ansi->parameters[ansi->paramCount] =
224 ansi->parameters[ansi->paramCount] * 10 + (ansi->buffer[ansi->length - 1] - '0');
225 return false;
226 }
227 else if (ansi->buffer[ansi->length - 1] == ';')
228 {
229 if (ansi->paramCount >= ANSI_MAX_LENGTH - 1)
230 {
232 return false;
233 }
234 ansi->paramCount++;
235 return false;
236 }
237 else
238 {
239 ansi->command = ansi->buffer[ansi->length - 1];
240 ansi->ascii = false;
241 ansi->length = 0;
242 ansi->paramCount++;
243 return true;
244 }
245}
246
247/** @} */
#define isdigit(c)
Definition ctype.h:20
static fd_t kbd
Definition dwm.c:23
@ KBD_MOD_CTRL
Control modifier.
Definition event.h:150
@ KBD_LEFT
Left arrow key.
Definition kbd.h:115
@ KBD_DOWN
Down arrow key.
Definition kbd.h:116
@ KBD_HOME
Home key.
Definition kbd.h:109
@ KBD_TAB
Tab key.
Definition kbd.h:75
@ KBD_BACKSPACE
Backspace key.
Definition kbd.h:74
@ KBD_RIGHT
Right arrow key.
Definition kbd.h:114
@ KBD_ENTER
Enter key.
Definition kbd.h:72
@ KBD_UP
Up arrow key.
Definition kbd.h:117
@ KBD_END
End key.
Definition kbd.h:112
@ KBD_C
Key C.
Definition kbd.h:36
@ KBD_PAGE_DOWN
Page Down key.
Definition kbd.h:113
@ KBD_DELETE
Delete key.
Definition kbd.h:111
@ KBD_PAGE_UP
Page Up key.
Definition kbd.h:110
static bool ansi_sending_parse(ansi_sending_t *ansi, char chr)
Parse a character for ANSI sending.
Definition ansi.h:172
static void ansi_sending_init(ansi_sending_t *ansi)
Initialize an ANSI sending structure.
Definition ansi.h:155
static void ansi_kbd_to_receiving(ansi_receiving_t *ansi, const event_kbd_t *kbd)
Convert a keycode to an ANSI receiving sequence.
Definition ansi.h:40
#define ANSI_MAX_LENGTH
The size we use for buffers when parsing ANSI sequences.
Definition ansi.h:20
static ansi_t ansi
Definition interactive.c:18
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
__UINT32_TYPE__ uint32_t
Definition stdint.h:15
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
_PUBLIC void * memset(void *s, int c, size_t n)
Definition memset.c:4
ANSI receiving structure.
Definition ansi.h:27
uint8_t length
Definition ansi.h:29
ANSI sending structure.
Definition ansi.h:140
bool extended
The command contains a '?' indicating an extended command.
Definition ansi.h:147
bool ascii
Definition ansi.h:146
uint32_t length
Definition ansi.h:142
char command
Definition ansi.h:145
uint32_t paramCount
Definition ansi.h:144
uint8_t length
Definition ansi.h:11
char buffer[ANSI_MAX_LENGTH]
Definition ansi.h:10
Keyboard event.
Definition event.h:161