Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add VT100 ranged scroll #10110

Merged
merged 7 commits into from
Mar 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ports/atmel-samd/boards/openbook_m4/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ CIRCUITPY_KEYPAD = 1
CIRCUITPY_SYNTHIO = 0
CIRCUITPY_JPEGIO = 0
CIRCUITPY_FLOPPYIO = 0
CIRCUITPY_TERMINALIO_VT100 = 0
1 change: 1 addition & 0 deletions ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ LONGINT_IMPL = MPZ
CIRCUITPY_SPITARGET = 0
CIRCUITPY_SYNTHIO = 0
CIRCUITPY_JPEGIO = 0
CIRCUITPY_TERMINALIO_VT100 = 0
2 changes: 2 additions & 0 deletions shared-bindings/terminalio/Terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
//| * ``ESC [ H`` - Move the cursor to 0,0.
//| * ``ESC M`` - Move the cursor up one line, scrolling if necessary.
//| * ``ESC D`` - Move the cursor down one line, scrolling if necessary.
//| * ``ESC [ r`` - Disable scrolling range (set to fullscreen).
//| * ``ESC [ nnnn ; mmmm r`` - Set scrolling range between rows nnnn and mmmm.
//| * ``ESC [ ## m`` - Set the terminal display attributes.
//| * ``ESC [ ## ; ## m`` - Set the terminal display attributes.
//| * ``ESC [ ## ; ## ; ## m`` - Set the terminal display attributes.
Expand Down
92 changes: 62 additions & 30 deletions shared-module/terminalio/Terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self,
self->status_x = 0;
self->status_y = 0;
self->first_row = 0;
self->vt_scroll_top = 0;
self->vt_scroll_end = self->scroll_area->height_in_tiles - 1;
common_hal_displayio_tilegrid_set_all_tiles(self->scroll_area, 0);
if (self->status_bar) {
common_hal_displayio_tilegrid_set_all_tiles(self->status_bar, 0);
Expand All @@ -42,6 +44,8 @@ void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self,
}

size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, const byte *data, size_t len, int *errcode) {
#define SCRNMOD(x) (((x) + (self->scroll_area->top_left_y)) % (self->scroll_area->height_in_tiles))

// Make sure the terminal is initialized before we do anything with it.
if (self->scroll_area == NULL) {
return len;
Expand Down Expand Up @@ -114,7 +118,7 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
}
} else if (c == 0x1b) {
// Handle commands of the form [ESC].<digits><command-char> where . is not yet known.
uint8_t vt_args[3] = {0, -1, -1};
int16_t vt_args[3] = {0, 0, 0};
uint8_t j = 1;
#if CIRCUITPY_TERMINALIO_VT100
uint8_t n_args = 1;
Expand Down Expand Up @@ -158,8 +162,8 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
#endif
} else {
if (c == 'K') {
uint8_t clr_start = self->cursor_x;
uint8_t clr_end = self->scroll_area->width_in_tiles;
int16_t clr_start = self->cursor_x;
int16_t clr_end = self->scroll_area->width_in_tiles;
#if CIRCUITPY_TERMINALIO_VT100
if (vt_args[0] == 1) {
clr_start = 0;
Expand Down Expand Up @@ -188,9 +192,6 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
if (vt_args[0] > 0) {
vt_args[0]--;
}
if (vt_args[1] == -1) {
vt_args[1] = 0;
}
if (vt_args[1] > 0) {
vt_args[1]--;
}
Expand All @@ -200,7 +201,7 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
if (vt_args[1] >= self->scroll_area->width_in_tiles) {
vt_args[1] = self->scroll_area->width_in_tiles - 1;
}
vt_args[0] = (vt_args[0] + self->scroll_area->top_left_y) % self->scroll_area->height_in_tiles;
vt_args[0] = SCRNMOD(vt_args[0]);
self->cursor_x = vt_args[1];
self->cursor_y = vt_args[0];
start_y = self->cursor_y;
Expand All @@ -215,43 +216,58 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
common_hal_displayio_palette_set_color(terminal_palette, 1, 0xffffff);
}
}
} else if (c == 'r') {
if (vt_args[0] < vt_args[1] && vt_args[0] >= 1 && vt_args[1] <= self->scroll_area->height_in_tiles) {
self->vt_scroll_top = vt_args[0] - 1;
self->vt_scroll_end = vt_args[1] - 1;
} else {
self->vt_scroll_top = 0;
self->vt_scroll_end = self->scroll_area->height_in_tiles - 1;
}
self->cursor_x = 0;
self->cursor_y = self->scroll_area->top_left_y % self->scroll_area->height_in_tiles;
start_y = self->cursor_y;
#endif
}
i += j + 1;
}
#if CIRCUITPY_TERMINALIO_VT100
} else if (i[0] == 'M') {
if (self->cursor_y != self->scroll_area->top_left_y) {
if (self->cursor_y != SCRNMOD(self->vt_scroll_top)) {
if (self->cursor_y > 0) {
self->cursor_y = self->cursor_y - 1;
} else {
self->cursor_y = self->scroll_area->height_in_tiles - 1;
}
} else {
if (self->cursor_y > 0) {
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, self->cursor_y - 1);
if (self->vt_scroll_top != 0 || self->vt_scroll_end != self->scroll_area->height_in_tiles) {
// Scroll range defined, manually move tiles to perform scroll
for (int16_t irow = self->vt_scroll_end - 1; irow >= self->vt_scroll_top; irow--) {
for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
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)));
}
}
for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->cursor_y, 0);
}
} else {
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, self->scroll_area->height_in_tiles - 1);
}
for (uint8_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->scroll_area->top_left_y, 0);
// Full screen scroll, just set new top_y pointer and clear row
if (self->cursor_y > 0) {
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, self->cursor_y - 1);
} else {
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, self->scroll_area->height_in_tiles - 1);
}
for (uint16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->scroll_area->top_left_y, 0);
}
self->cursor_y = self->scroll_area->top_left_y;
}

self->cursor_x = 0;
self->cursor_y = self->scroll_area->top_left_y;
}
start_y = self->cursor_y;
i++;
} else if (i[0] == 'D') {
self->cursor_y = (self->cursor_y + 1) % self->scroll_area->height_in_tiles;
if (self->cursor_y == self->scroll_area->top_left_y) {
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, (self->cursor_y + 1) % self->scroll_area->height_in_tiles);
for (uint8_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->cursor_y, 0);
}
self->cursor_x = 0;
}
start_y = self->cursor_y;
self->cursor_y++;
i++;
#endif
} else if (i[0] == ']' && c == ';') {
Expand All @@ -276,12 +292,28 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
self->cursor_y %= self->scroll_area->height_in_tiles;
}
if (self->cursor_y != start_y) {
// clear the new row in case of scroll up
if (self->cursor_y == self->scroll_area->top_left_y) {
for (uint16_t j = 0; j < self->scroll_area->width_in_tiles; j++) {
common_hal_displayio_tilegrid_set_tile(self->scroll_area, j, self->cursor_y, 0);
if (((self->cursor_y + self->scroll_area->height_in_tiles) - 1) % self->scroll_area->height_in_tiles == SCRNMOD(self->vt_scroll_end)) {
#if CIRCUITPY_TERMINALIO_VT100
if (self->vt_scroll_top != 0 || self->vt_scroll_end != self->scroll_area->height_in_tiles) {
// Scroll range defined, manually move tiles to perform scroll
self->cursor_y = SCRNMOD(self->vt_scroll_end);

for (int16_t irow = self->vt_scroll_top; irow < self->vt_scroll_end; irow++) {
for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
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)));
}
}
}
#endif
if (self->vt_scroll_top == 0 && self->vt_scroll_end == self->scroll_area->height_in_tiles) {
// Full screen scroll, just set new top_y pointer
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);
}
// clear the new row in case of scroll up
for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) {
common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->cursor_y, 0);
}
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);
self->cursor_x = 0;
}
start_y = self->cursor_y;
}
Expand Down
2 changes: 2 additions & 0 deletions shared-module/terminalio/Terminal.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ typedef struct {
uint16_t status_x;
uint16_t status_y;
uint16_t first_row;
uint16_t vt_scroll_top;
uint16_t vt_scroll_end;
uint16_t osc_command;
bool in_osc_command;
} terminalio_terminal_obj_t;
Expand Down