Skip to content

Commit 8c5c624

Browse files
committed
Add VT100 ranged scroll
1 parent bc36b94 commit 8c5c624

File tree

3 files changed

+85
-23
lines changed

3 files changed

+85
-23
lines changed

shared-bindings/terminalio/Terminal.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
//| * ``ESC [ H`` - Move the cursor to 0,0.
4040
//| * ``ESC M`` - Move the cursor up one line, scrolling if necessary.
4141
//| * ``ESC D`` - Move the cursor down one line, scrolling if necessary.
42+
//| * ``ESC [ r`` - Disable scrolling range (set to fullscreen).
43+
//| * ``ESC [ nnnn ; mmmm r`` - Set scrolling range between rows nnnn and mmmm.
4244
//| * ``ESC [ ## m`` - Set the terminal display attributes.
4345
//| * ``ESC [ ## ; ## m`` - Set the terminal display attributes.
4446
//| * ``ESC [ ## ; ## ; ## m`` - Set the terminal display attributes.

shared-module/terminalio/Terminal.c

Lines changed: 81 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self,
3333
self->status_x = 0;
3434
self->status_y = 0;
3535
self->first_row = 0;
36+
self->vt_scroll_top = 0;
37+
self->vt_scroll_end = self->scroll_area->height_in_tiles - 1;
3638
common_hal_displayio_tilegrid_set_all_tiles(self->scroll_area, 0);
3739
if (self->status_bar) {
3840
common_hal_displayio_tilegrid_set_all_tiles(self->status_bar, 0);
@@ -42,6 +44,8 @@ void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self,
4244
}
4345

4446
size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, const byte *data, size_t len, int *errcode) {
47+
#define scrnmod(x) (((x) + (self->scroll_area->top_left_y)) % (self->scroll_area->height_in_tiles))
48+
4549
// Make sure the terminal is initialized before we do anything with it.
4650
if (self->scroll_area == NULL) {
4751
return len;
@@ -114,7 +118,7 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
114118
}
115119
} else if (c == 0x1b) {
116120
// Handle commands of the form [ESC].<digits><command-char> where . is not yet known.
117-
uint8_t vt_args[3] = {0, -1, -1};
121+
uint16_t vt_args[3] = {0, -1, -1};
118122
uint8_t j = 1;
119123
#if CIRCUITPY_TERMINALIO_VT100
120124
uint8_t n_args = 1;
@@ -158,8 +162,8 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
158162
#endif
159163
} else {
160164
if (c == 'K') {
161-
uint8_t clr_start = self->cursor_x;
162-
uint8_t clr_end = self->scroll_area->width_in_tiles;
165+
int16_t clr_start = self->cursor_x;
166+
int16_t clr_end = self->scroll_area->width_in_tiles;
163167
#if CIRCUITPY_TERMINALIO_VT100
164168
if (vt_args[0] == 1) {
165169
clr_start = 0;
@@ -200,7 +204,7 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
200204
if (vt_args[1] >= self->scroll_area->width_in_tiles) {
201205
vt_args[1] = self->scroll_area->width_in_tiles - 1;
202206
}
203-
vt_args[0] = (vt_args[0] + self->scroll_area->top_left_y) % self->scroll_area->height_in_tiles;
207+
vt_args[0] = scrnmod(vt_args[0]);
204208
self->cursor_x = vt_args[1];
205209
self->cursor_y = vt_args[0];
206210
start_y = self->cursor_y;
@@ -215,39 +219,77 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
215219
common_hal_displayio_palette_set_color(terminal_palette, 1, 0xffffff);
216220
}
217221
}
222+
} else if (c == 'r') {
223+
if (vt_args[0] < vt_args[1] && vt_args[0] >= 1 && vt_args[1] <= self->scroll_area->height_in_tiles) {
224+
self->vt_scroll_top = vt_args[0] - 1;
225+
self->vt_scroll_end = vt_args[1] - 1;
226+
} else {
227+
self->vt_scroll_top = 0;
228+
self->vt_scroll_end = self->scroll_area->height_in_tiles - 1;
229+
}
230+
self->cursor_x = 0;
231+
self->cursor_y = self->scroll_area->top_left_y % self->scroll_area->height_in_tiles;
232+
start_y = self->cursor_y;
218233
#endif
219234
}
220235
i += j + 1;
221236
}
222237
#if CIRCUITPY_TERMINALIO_VT100
223238
} else if (i[0] == 'M') {
224-
if (self->cursor_y != self->scroll_area->top_left_y) {
239+
if (self->cursor_y != scrnmod(self->vt_scroll_top)) {
225240
if (self->cursor_y > 0) {
226241
self->cursor_y = self->cursor_y - 1;
227242
} else {
228243
self->cursor_y = self->scroll_area->height_in_tiles - 1;
229244
}
230245
} else {
231-
if (self->cursor_y > 0) {
232-
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, self->cursor_y - 1);
246+
if (self->vt_scroll_top != 0 || self->vt_scroll_end != self->scroll_area->height_in_tiles) {
247+
// Scroll range defined, manually move tiles to perform scroll
248+
for (int16_t irow = self->vt_scroll_end - 1; irow >= self->vt_scroll_top; irow--) {
249+
for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
250+
common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, scrnmod(irow + 1), common_hal_displayio_tilegrid_get_tile(self->scroll_area, icol, scrnmod(irow)));
251+
}
252+
}
253+
for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
254+
common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->cursor_y, 0);
255+
}
233256
} 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);
257+
// Full screen scroll, just set new top_y pointer and clear row
258+
if (self->cursor_y > 0) {
259+
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, self->cursor_y - 1);
260+
} else {
261+
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, self->scroll_area->height_in_tiles - 1);
262+
}
263+
for (uint16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
264+
common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->scroll_area->top_left_y, 0);
265+
}
266+
self->cursor_y = self->scroll_area->top_left_y;
238267
}
239-
240268
self->cursor_x = 0;
241-
self->cursor_y = self->scroll_area->top_left_y;
242269
}
243270
start_y = self->cursor_y;
244271
i++;
245272
} 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);
273+
if (self->cursor_y != scrnmod(self->vt_scroll_end)) {
274+
self->cursor_y = (self->cursor_y + 1) % self->scroll_area->height_in_tiles;
275+
} else {
276+
if (self->vt_scroll_top != 0 || self->vt_scroll_end != self->scroll_area->height_in_tiles) {
277+
// Scroll range defined, manually move tiles to perform scroll
278+
for (int16_t irow = self->vt_scroll_top; irow < self->vt_scroll_end; irow++) {
279+
for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
280+
common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, scrnmod(irow), common_hal_displayio_tilegrid_get_tile(self->scroll_area, icol, scrnmod(irow + 1)));
281+
}
282+
}
283+
for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
284+
common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->cursor_y, 0);
285+
}
286+
} else {
287+
// Full screen scroll, just set new top_y pointer and clear row
288+
self->cursor_y = (self->cursor_y + 1) % self->scroll_area->height_in_tiles;
289+
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, (self->cursor_y + 1) % self->scroll_area->height_in_tiles);
290+
for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
291+
common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->cursor_y, 0);
292+
}
251293
}
252294
self->cursor_x = 0;
253295
}
@@ -276,12 +318,28 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
276318
self->cursor_y %= self->scroll_area->height_in_tiles;
277319
}
278320
if (self->cursor_y != start_y) {
279-
// clear the new row in case of scroll up
280-
if (self->cursor_y == self->scroll_area->top_left_y) {
281-
for (uint16_t j = 0; j < self->scroll_area->width_in_tiles; j++) {
282-
common_hal_displayio_tilegrid_set_tile(self->scroll_area, j, self->cursor_y, 0);
321+
if (((self->cursor_y + self->scroll_area->height_in_tiles) - 1) % self->scroll_area->height_in_tiles == scrnmod(self->vt_scroll_end)) {
322+
#if CIRCUITPY_TERMINALIO_VT100
323+
if (self->vt_scroll_top != 0 || self->vt_scroll_end != self->scroll_area->height_in_tiles) {
324+
// Scroll range defined, manually move tiles to perform scroll
325+
self->cursor_y = scrnmod(self->vt_scroll_end);
326+
327+
for (int16_t irow = self->vt_scroll_top; irow < self->vt_scroll_end; irow++) {
328+
for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
329+
common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, scrnmod(irow), common_hal_displayio_tilegrid_get_tile(self->scroll_area, icol, scrnmod(irow + 1)));
330+
}
331+
}
332+
}
333+
#endif
334+
if (self->vt_scroll_top == 0 && self->vt_scroll_end == self->scroll_area->height_in_tiles) {
335+
// Full screen scroll, just set new top_y pointer
336+
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, (self->cursor_y + self->scroll_area->height_in_tiles + 1) % self->scroll_area->height_in_tiles);
337+
}
338+
// clear the new row in case of scroll up
339+
for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
340+
common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->cursor_y, 0);
283341
}
284-
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, (self->cursor_y + self->scroll_area->height_in_tiles + 1) % self->scroll_area->height_in_tiles);
342+
self->cursor_x = 0;
285343
}
286344
start_y = self->cursor_y;
287345
}

shared-module/terminalio/Terminal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ typedef struct {
2323
uint16_t status_x;
2424
uint16_t status_y;
2525
uint16_t first_row;
26+
uint16_t vt_scroll_top;
27+
uint16_t vt_scroll_end;
2628
uint16_t osc_command;
2729
bool in_osc_command;
2830
} terminalio_terminal_obj_t;

0 commit comments

Comments
 (0)