@@ -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
+ uint16_t vt_args [3 ] = {0 , -1 , -1 };
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 ;
@@ -200,7 +204,7 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
200
204
if (vt_args [1 ] >= self -> scroll_area -> width_in_tiles ) {
201
205
vt_args [1 ] = self -> scroll_area -> width_in_tiles - 1 ;
202
206
}
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 ]) ;
204
208
self -> cursor_x = vt_args [1 ];
205
209
self -> cursor_y = vt_args [0 ];
206
210
start_y = self -> cursor_y ;
@@ -215,39 +219,77 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
215
219
common_hal_displayio_palette_set_color (terminal_palette , 1 , 0xffffff );
216
220
}
217
221
}
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 ;
218
233
#endif
219
234
}
220
235
i += j + 1 ;
221
236
}
222
237
#if CIRCUITPY_TERMINALIO_VT100
223
238
} 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 ) ) {
225
240
if (self -> cursor_y > 0 ) {
226
241
self -> cursor_y = self -> cursor_y - 1 ;
227
242
} else {
228
243
self -> cursor_y = self -> scroll_area -> height_in_tiles - 1 ;
229
244
}
230
245
} 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
+ }
233
256
} 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 ;
238
267
}
239
-
240
268
self -> cursor_x = 0 ;
241
- self -> cursor_y = self -> scroll_area -> top_left_y ;
242
269
}
243
270
start_y = self -> cursor_y ;
244
271
i ++ ;
245
272
} 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
+ }
251
293
}
252
294
self -> cursor_x = 0 ;
253
295
}
@@ -276,12 +318,28 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
276
318
self -> cursor_y %= self -> scroll_area -> height_in_tiles ;
277
319
}
278
320
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 );
283
341
}
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 ;
285
343
}
286
344
start_y = self -> cursor_y ;
287
345
}
0 commit comments