Skip to content

Commit bc36b94

Browse files
authored
Merge pull request #10108 from RetiredWizard/vtscroll
Add basic VT100 scrolling
2 parents 6e7baea + 7cbe3b5 commit bc36b94

File tree

4 files changed

+128
-63
lines changed

4 files changed

+128
-63
lines changed

ports/atmel-samd/mpconfigport.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ CIRCUITPY_ZLIB = 0
5959

6060
# Turn off a few more things that don't fit in 192kB
6161

62+
CIRCUITPY_TERMINALIO_VT100 = 0
63+
6264
ifeq ($(INTERNAL_FLASH_FILESYSTEM),1)
6365
CIRCUITPY_ONEWIREIO ?= 0
6466
CIRCUITPY_SAFEMODE_PY ?= 0

py/circuitpy_mpconfig.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,9 @@ CFLAGS += -DCIRCUITPY_SYS=$(CIRCUITPY_SYS)
552552
CIRCUITPY_TERMINALIO ?= $(CIRCUITPY_DISPLAYIO)
553553
CFLAGS += -DCIRCUITPY_TERMINALIO=$(CIRCUITPY_TERMINALIO)
554554

555+
CIRCUITPY_TERMINALIO_VT100 ?= $(CIRCUITPY_TERMINALIO)
556+
CFLAGS += -DCIRCUITPY_TERMINALIO_VT100=$(CIRCUITPY_TERMINALIO_VT100)
557+
555558
CIRCUITPY_FONTIO ?= $(call enable-if-all,$(CIRCUITPY_DISPLAYIO) $(CIRCUITPY_TERMINALIO))
556559
CFLAGS += -DCIRCUITPY_FONTIO=$(CIRCUITPY_FONTIO)
557560

shared-bindings/terminalio/Terminal.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,18 @@
3030
//|
3131
//| VT100 control sequences:
3232
//| * ``ESC [ K`` - Clear the remainder of the line
33+
//| * ``ESC [ 0 K`` - Clear the remainder of the line
34+
//| * ``ESC [ 1 K`` - Clear start of the line to cursor
35+
//| * ``ESC [ 2 K`` - Clear the entire line
3336
//| * ``ESC [ #### D`` - Move the cursor to the left by ####
3437
//| * ``ESC [ 2 J`` - Erase the entire display
3538
//| * ``ESC [ nnnn ; mmmm H`` - Move the cursor to mmmm, nnnn.
36-
//| * ``ESC [ nn m`` - Set the terminal display attributes.
37-
//| * ``ESC [ nn ; nn m`` - Set the terminal display attributes.
39+
//| * ``ESC [ H`` - Move the cursor to 0,0.
40+
//| * ``ESC M`` - Move the cursor up one line, scrolling if necessary.
41+
//| * ``ESC D`` - Move the cursor down one line, scrolling if necessary.
42+
//| * ``ESC [ ## m`` - Set the terminal display attributes.
43+
//| * ``ESC [ ## ; ## m`` - Set the terminal display attributes.
44+
//| * ``ESC [ ## ; ## ; ## m`` - Set the terminal display attributes.
3845
//|
3946
//| Supported Display attributes:
4047
//| 0 - Reset all attributes

shared-module/terminalio/Terminal.c

Lines changed: 114 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
4747
return len;
4848
}
4949

50+
#if CIRCUITPY_TERMINALIO_VT100
5051
uint32_t _select_color(uint16_t ascii_color) {
5152
uint32_t color_value = 0;
5253
if ((ascii_color & 1) > 0) {
@@ -63,6 +64,8 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
6364
}
6465

6566
displayio_palette_t *terminal_palette = self->scroll_area->pixel_shader;
67+
#endif
68+
6669
const byte *i = data;
6770
uint16_t start_y = self->cursor_y;
6871
while (i < data + len) {
@@ -111,99 +114,149 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
111114
}
112115
} else if (c == 0x1b) {
113116
// Handle commands of the form [ESC].<digits><command-char> where . is not yet known.
114-
uint16_t n = 0;
117+
uint8_t vt_args[3] = {0, -1, -1};
115118
uint8_t j = 1;
119+
#if CIRCUITPY_TERMINALIO_VT100
120+
uint8_t n_args = 1;
121+
#endif
116122
for (; j < 6; j++) {
117123
if ('0' <= i[j] && i[j] <= '9') {
118-
n = n * 10 + (i[j] - '0');
124+
vt_args[0] = vt_args[0] * 10 + (i[j] - '0');
119125
} else {
120126
c = i[j];
121127
break;
122128
}
123129
}
124130
if (i[0] == '[') {
125-
if (i[1] == 'K') {
126-
// Clear the rest of the line.
127-
for (uint16_t k = self->cursor_x; k < self->scroll_area->width_in_tiles; k++) {
128-
common_hal_displayio_tilegrid_set_tile(self->scroll_area, k, self->cursor_y, 0);
131+
for (uint8_t i_args = 1; i_args < 3 && c == ';'; i_args++) {
132+
vt_args[i_args] = 0;
133+
for (++j; j < 12; j++) {
134+
if ('0' <= i[j] && i[j] <= '9') {
135+
vt_args[i_args] = vt_args[i_args] * 10 + (i[j] - '0');
136+
#if CIRCUITPY_TERMINALIO_VT100
137+
n_args = i_args + 1;
138+
#endif
139+
} else {
140+
c = i[j];
141+
break;
142+
}
143+
}
144+
}
145+
if (c == '?') {
146+
#if CIRCUITPY_TERMINALIO_VT100
147+
if (i[2] == '2' && i[3] == '5') {
148+
// cursor visibility commands
149+
if (i[4] == 'h') {
150+
// make cursor visible
151+
// not implemented yet
152+
} else if (i[4] == 'l') {
153+
// make cursor invisible
154+
// not implemented yet
155+
}
129156
}
130-
i += 2;
157+
i += 5;
158+
#endif
131159
} else {
132-
if (c == 'D') {
133-
if (n > self->cursor_x) {
160+
if (c == 'K') {
161+
uint8_t clr_start = self->cursor_x;
162+
uint8_t clr_end = self->scroll_area->width_in_tiles;
163+
#if CIRCUITPY_TERMINALIO_VT100
164+
if (vt_args[0] == 1) {
165+
clr_start = 0;
166+
clr_end = self->cursor_x;
167+
} else if (vt_args[0] == 2) {
168+
clr_start = 0;
169+
}
170+
#endif
171+
// Clear the (start/rest/all) of the line.
172+
for (uint16_t k = clr_start; k < clr_end; k++) {
173+
common_hal_displayio_tilegrid_set_tile(self->scroll_area, k, self->cursor_y, 0);
174+
}
175+
} else if (c == 'D') {
176+
if (vt_args[0] > self->cursor_x) {
134177
self->cursor_x = 0;
135178
} else {
136-
self->cursor_x -= n;
179+
self->cursor_x -= vt_args[0];
137180
}
138-
}
139-
if (c == 'J') {
140-
if (n == 2) {
181+
} else if (c == 'J') {
182+
if (vt_args[0] == 2) {
141183
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, 0);
142184
self->cursor_x = self->cursor_y = start_y = 0;
143-
n = 0;
144185
common_hal_displayio_tilegrid_set_all_tiles(self->scroll_area, 0);
145186
}
146-
}
147-
if (c == 'm') {
148-
if ((n >= 40 && n <= 47) || (n >= 30 && n <= 37)) {
149-
common_hal_displayio_palette_set_color(terminal_palette, 1 - (n / 40), _select_color(n % 10));
187+
} else if (c == 'H') {
188+
if (vt_args[0] > 0) {
189+
vt_args[0]--;
150190
}
151-
if (n == 0) {
152-
common_hal_displayio_palette_set_color(terminal_palette, 0, 0x000000);
153-
common_hal_displayio_palette_set_color(terminal_palette, 1, 0xffffff);
191+
if (vt_args[1] == -1) {
192+
vt_args[1] = 0;
154193
}
155-
}
156-
if (c == ';') {
157-
uint16_t m = 0;
158-
for (++j; j < 9; j++) {
159-
if ('0' <= i[j] && i[j] <= '9') {
160-
m = m * 10 + (i[j] - '0');
161-
} else {
162-
c = i[j];
163-
break;
164-
}
194+
if (vt_args[1] > 0) {
195+
vt_args[1]--;
165196
}
166-
if (c == 'H') {
167-
if (n > 0) {
168-
n--;
169-
}
170-
if (m > 0) {
171-
m--;
172-
}
173-
if (n >= self->scroll_area->height_in_tiles) {
174-
n = self->scroll_area->height_in_tiles - 1;
175-
}
176-
if (m >= self->scroll_area->width_in_tiles) {
177-
m = self->scroll_area->width_in_tiles - 1;
178-
}
179-
n = (n + self->scroll_area->top_left_y) % self->scroll_area->height_in_tiles;
180-
self->cursor_x = m;
181-
self->cursor_y = n;
182-
start_y = self->cursor_y;
197+
if (vt_args[0] >= self->scroll_area->height_in_tiles) {
198+
vt_args[0] = self->scroll_area->height_in_tiles - 1;
183199
}
184-
if (c == 'm') {
185-
if ((n >= 40 && n <= 47) || (n >= 30 && n <= 37)) {
186-
common_hal_displayio_palette_set_color(terminal_palette, 1 - (n / 40), _select_color(n % 10));
187-
}
188-
if (n == 0) {
189-
common_hal_displayio_palette_set_color(terminal_palette, 0, 0x000000);
190-
common_hal_displayio_palette_set_color(terminal_palette, 1, 0xffffff);
191-
}
192-
if ((m >= 40 && m <= 47) || (m >= 30 && m <= 37)) {
193-
common_hal_displayio_palette_set_color(terminal_palette, 1 - (m / 40), _select_color(m % 10));
200+
if (vt_args[1] >= self->scroll_area->width_in_tiles) {
201+
vt_args[1] = self->scroll_area->width_in_tiles - 1;
202+
}
203+
vt_args[0] = (vt_args[0] + self->scroll_area->top_left_y) % self->scroll_area->height_in_tiles;
204+
self->cursor_x = vt_args[1];
205+
self->cursor_y = vt_args[0];
206+
start_y = self->cursor_y;
207+
#if CIRCUITPY_TERMINALIO_VT100
208+
} else if (c == 'm') {
209+
for (uint8_t i_args = 0; i_args < n_args; i_args++) {
210+
if ((vt_args[i_args] >= 40 && vt_args[i_args] <= 47) || (vt_args[i_args] >= 30 && vt_args[i_args] <= 37)) {
211+
common_hal_displayio_palette_set_color(terminal_palette, 1 - (vt_args[i_args] / 40), _select_color(vt_args[i_args] % 10));
194212
}
195-
if (m == 0) {
213+
if (vt_args[i_args] == 0) {
196214
common_hal_displayio_palette_set_color(terminal_palette, 0, 0x000000);
197215
common_hal_displayio_palette_set_color(terminal_palette, 1, 0xffffff);
198216
}
199217
}
218+
#endif
200219
}
201220
i += j + 1;
202-
continue;
203221
}
222+
#if CIRCUITPY_TERMINALIO_VT100
223+
} else if (i[0] == 'M') {
224+
if (self->cursor_y != self->scroll_area->top_left_y) {
225+
if (self->cursor_y > 0) {
226+
self->cursor_y = self->cursor_y - 1;
227+
} else {
228+
self->cursor_y = self->scroll_area->height_in_tiles - 1;
229+
}
230+
} else {
231+
if (self->cursor_y > 0) {
232+
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, self->cursor_y - 1);
233+
} else {
234+
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, self->scroll_area->height_in_tiles - 1);
235+
}
236+
for (uint8_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
237+
common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->scroll_area->top_left_y, 0);
238+
}
239+
240+
self->cursor_x = 0;
241+
self->cursor_y = self->scroll_area->top_left_y;
242+
}
243+
start_y = self->cursor_y;
244+
i++;
245+
} else if (i[0] == 'D') {
246+
self->cursor_y = (self->cursor_y + 1) % self->scroll_area->height_in_tiles;
247+
if (self->cursor_y == self->scroll_area->top_left_y) {
248+
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, (self->cursor_y + 1) % self->scroll_area->height_in_tiles);
249+
for (uint8_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
250+
common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->cursor_y, 0);
251+
}
252+
self->cursor_x = 0;
253+
}
254+
start_y = self->cursor_y;
255+
i++;
256+
#endif
204257
} else if (i[0] == ']' && c == ';') {
205258
self->in_osc_command = true;
206-
self->osc_command = n;
259+
self->osc_command = vt_args[0];
207260
i += j + 1;
208261
}
209262
}

0 commit comments

Comments
 (0)