-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.c
More file actions
125 lines (106 loc) · 4.19 KB
/
Copy pathparser.c
File metadata and controls
125 lines (106 loc) · 4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include "parser.h"
typedef enum{
STATE_NORMAL,
STATE_ESC,
STATE_CSI,
STATE_OSC
} ParserState;
ParserState current_state = STATE_NORMAL;
int params[16];
int param_count = 0;
int current_param = 0;
int has_digit = 0; // tracks if the user actually typed a number
void parse_byte(char c, TermCallbacks *cb){
if(!cb) return; // safety check for null pointer
switch (current_state) {
case STATE_NORMAL:
if (c == '\x1b') {
current_state = STATE_ESC;
} else {
if(cb->print) cb->print((uint32_t)c); // send the character to the callback
}
break;
case STATE_ESC:
if (c == '[') {
current_state = STATE_CSI;
param_count = 0;
current_param = 0;
has_digit = 0;
}
else if (c == ']') {
current_state = STATE_OSC;
}
else {
// If it's a different escape sequence, ignore and reset
current_state = STATE_NORMAL;
}
break;
case STATE_CSI:
if (isdigit(c)) {
// Build the number (e.g., '3' then '4' -> 34)
current_param = (current_param * 10) + (c - '0');
has_digit = 1;
}
else if (c == ';') {
// Parameter is done, save it to the array
params[param_count++] = has_digit ? current_param : 0;
current_param = 0;
has_digit = 0;
}
else if (c >= 0x40 && c <= 0x7E) {
// We hit a letter! The sequence is finished.
// Save the very last parameter
if (has_digit) {
params[param_count++] = current_param;
} else if (param_count == 0 && c == 'm') {
// Edge case: bash sometimes sends just "ESC[m"
// which implicitly means "ESC[0m" (Reset)
params[param_count++] = 0;
}
if(c == 'm'){
if(cb->sgr) cb->sgr(params, param_count); // send SGR event to callback
}
else if(c == 'H' || c == 'f'){
// Safely extract row and col, defaulting to 1 if missing or zero
int row = (param_count > 0 && params[0] > 0) ? params[0] : 1;
int col = (param_count > 1 && params[1] > 0) ? params[1] : 1;
if(cb->cursor_move) cb->cursor_move(row, col);
}
else if (c == 'A') {
int n = (param_count > 0 && params[0] > 0) ? params[0] : 1;
if(cb->cursor_up) cb->cursor_up(n);
}
else if (c == 'B') {
int n = (param_count > 0 && params[0] > 0) ? params[0] : 1;
if(cb->cursor_down) cb->cursor_down(n);
}
else if (c == 'C') {
int n = (param_count > 0 && params[0] > 0) ? params[0] : 1;
if(cb->cursor_right) cb->cursor_right(n);
}
else if (c == 'D') {
int n = (param_count > 0 && params[0] > 0) ? params[0] : 1;
if(cb->cursor_left) cb->cursor_left(n);
}
else if(c == 'J'){
// Default to mode 0 if no parameters were given
int mode = (param_count > 0) ? params[0] : 0;
if(cb->erase_display) cb->erase_display(mode);
}
else if(c == 'K'){
int mode = (param_count > 0) ? params[0] : 0;
if(cb->erase_line) cb->erase_line(mode);
}
current_state = STATE_NORMAL; // reset for next text
}
break;
case STATE_OSC:
if (c == '\x07') { // BEL character
current_state = STATE_NORMAL; // reset for next text
}
break;
}
}