@@ -33,6 +33,8 @@ void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self,
33
33
self -> status_x = 0 ;
34
34
self -> status_y = 0 ;
35
35
self -> first_row = 0 ;
36
+ self -> vt_scroll_top = 0 ;
37
+ self -> vt_scroll_end = self -> scroll_area -> height_in_tiles - 1 ;
36
38
common_hal_displayio_tilegrid_set_all_tiles (self -> scroll_area , 0 );
37
39
if (self -> status_bar ) {
38
40
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,
42
44
}
43
45
44
46
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
+
45
49
// Make sure the terminal is initialized before we do anything with it.
46
50
if (self -> scroll_area == NULL ) {
47
51
return len ;
@@ -114,7 +118,7 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
114
118
}
115
119
} else if (c == 0x1b ) {
116
120
// Handle commands of the form [ESC].<digits><command-char> where . is not yet known.
117
- uint8_t vt_args [3 ] = {0 , -1 , -1 };
121
+ int16_t vt_args [3 ] = {0 , 0 , 0 };
118
122
uint8_t j = 1 ;
119
123
#if CIRCUITPY_TERMINALIO_VT100
120
124
uint8_t n_args = 1 ;
@@ -158,8 +162,8 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
158
162
#endif
159
163
} else {
160
164
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 ;
163
167
#if CIRCUITPY_TERMINALIO_VT100
164
168
if (vt_args [0 ] == 1 ) {
165
169
clr_start = 0 ;
@@ -188,9 +192,6 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
188
192
if (vt_args [0 ] > 0 ) {
189
193
vt_args [0 ]-- ;
190
194
}
191
- if (vt_args [1 ] == -1 ) {
192
- vt_args [1 ] = 0 ;
193
- }
194
195
if (vt_args [1 ] > 0 ) {
195
196
vt_args [1 ]-- ;
196
197
}
@@ -200,7 +201,7 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
200
201
if (vt_args [1 ] >= self -> scroll_area -> width_in_tiles ) {
201
202
vt_args [1 ] = self -> scroll_area -> width_in_tiles - 1 ;
202
203
}
203
- vt_args [0 ] = (vt_args [0 ] + self -> scroll_area -> top_left_y ) % self -> scroll_area -> height_in_tiles ;
204
+ vt_args [0 ] = SCRNMOD (vt_args [0 ]) ;
204
205
self -> cursor_x = vt_args [1 ];
205
206
self -> cursor_y = vt_args [0 ];
206
207
start_y = self -> cursor_y ;
@@ -215,43 +216,58 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
215
216
common_hal_displayio_palette_set_color (terminal_palette , 1 , 0xffffff );
216
217
}
217
218
}
219
+ } else if (c == 'r' ) {
220
+ if (vt_args [0 ] < vt_args [1 ] && vt_args [0 ] >= 1 && vt_args [1 ] <= self -> scroll_area -> height_in_tiles ) {
221
+ self -> vt_scroll_top = vt_args [0 ] - 1 ;
222
+ self -> vt_scroll_end = vt_args [1 ] - 1 ;
223
+ } else {
224
+ self -> vt_scroll_top = 0 ;
225
+ self -> vt_scroll_end = self -> scroll_area -> height_in_tiles - 1 ;
226
+ }
227
+ self -> cursor_x = 0 ;
228
+ self -> cursor_y = self -> scroll_area -> top_left_y % self -> scroll_area -> height_in_tiles ;
229
+ start_y = self -> cursor_y ;
218
230
#endif
219
231
}
220
232
i += j + 1 ;
221
233
}
222
234
#if CIRCUITPY_TERMINALIO_VT100
223
235
} else if (i [0 ] == 'M' ) {
224
- if (self -> cursor_y != self -> scroll_area -> top_left_y ) {
236
+ if (self -> cursor_y != SCRNMOD ( self -> vt_scroll_top ) ) {
225
237
if (self -> cursor_y > 0 ) {
226
238
self -> cursor_y = self -> cursor_y - 1 ;
227
239
} else {
228
240
self -> cursor_y = self -> scroll_area -> height_in_tiles - 1 ;
229
241
}
230
242
} else {
231
- if (self -> cursor_y > 0 ) {
232
- common_hal_displayio_tilegrid_set_top_left (self -> scroll_area , 0 , self -> cursor_y - 1 );
243
+ if (self -> vt_scroll_top != 0 || self -> vt_scroll_end != self -> scroll_area -> height_in_tiles ) {
244
+ // Scroll range defined, manually move tiles to perform scroll
245
+ for (int16_t irow = self -> vt_scroll_end - 1 ; irow >= self -> vt_scroll_top ; irow -- ) {
246
+ for (int16_t icol = 0 ; icol < self -> scroll_area -> width_in_tiles ; icol ++ ) {
247
+ 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 )));
248
+ }
249
+ }
250
+ for (int16_t icol = 0 ; icol < self -> scroll_area -> width_in_tiles ; icol ++ ) {
251
+ common_hal_displayio_tilegrid_set_tile (self -> scroll_area , icol , self -> cursor_y , 0 );
252
+ }
233
253
} 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 );
254
+ // Full screen scroll, just set new top_y pointer and clear row
255
+ if (self -> cursor_y > 0 ) {
256
+ common_hal_displayio_tilegrid_set_top_left (self -> scroll_area , 0 , self -> cursor_y - 1 );
257
+ } else {
258
+ common_hal_displayio_tilegrid_set_top_left (self -> scroll_area , 0 , self -> scroll_area -> height_in_tiles - 1 );
259
+ }
260
+ for (uint16_t icol = 0 ; icol < self -> scroll_area -> width_in_tiles ; icol ++ ) {
261
+ common_hal_displayio_tilegrid_set_tile (self -> scroll_area , icol , self -> scroll_area -> top_left_y , 0 );
262
+ }
263
+ self -> cursor_y = self -> scroll_area -> top_left_y ;
238
264
}
239
-
240
265
self -> cursor_x = 0 ;
241
- self -> cursor_y = self -> scroll_area -> top_left_y ;
242
266
}
243
267
start_y = self -> cursor_y ;
244
268
i ++ ;
245
269
} 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 ;
270
+ self -> cursor_y ++ ;
255
271
i ++ ;
256
272
#endif
257
273
} else if (i [0 ] == ']' && c == ';' ) {
@@ -276,12 +292,28 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
276
292
self -> cursor_y %= self -> scroll_area -> height_in_tiles ;
277
293
}
278
294
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 );
295
+ if (((self -> cursor_y + self -> scroll_area -> height_in_tiles ) - 1 ) % self -> scroll_area -> height_in_tiles == SCRNMOD (self -> vt_scroll_end )) {
296
+ #if CIRCUITPY_TERMINALIO_VT100
297
+ if (self -> vt_scroll_top != 0 || self -> vt_scroll_end != self -> scroll_area -> height_in_tiles ) {
298
+ // Scroll range defined, manually move tiles to perform scroll
299
+ self -> cursor_y = SCRNMOD (self -> vt_scroll_end );
300
+
301
+ for (int16_t irow = self -> vt_scroll_top ; irow < self -> vt_scroll_end ; irow ++ ) {
302
+ for (int16_t icol = 0 ; icol < self -> scroll_area -> width_in_tiles ; icol ++ ) {
303
+ 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 )));
304
+ }
305
+ }
306
+ }
307
+ #endif
308
+ if (self -> vt_scroll_top == 0 && self -> vt_scroll_end == self -> scroll_area -> height_in_tiles ) {
309
+ // Full screen scroll, just set new top_y pointer
310
+ 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 );
311
+ }
312
+ // clear the new row in case of scroll up
313
+ for (int16_t icol = 0 ; icol < self -> scroll_area -> width_in_tiles ; icol ++ ) {
314
+ common_hal_displayio_tilegrid_set_tile (self -> scroll_area , icol , self -> cursor_y , 0 );
283
315
}
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 ) ;
316
+ self -> cursor_x = 0 ;
285
317
}
286
318
start_y = self -> cursor_y ;
287
319
}
0 commit comments