11use crate :: {
22 ansi:: { self , EraseMode , Op , OpStr } ,
33 color:: Rgb3 ,
4- display:: { self , TextDisplay , ROWS } ,
4+ display:: { self , TextDisplay , COLUMNS , ROWS } ,
55 CHARACTER_DRAW_CYCLES ,
66} ;
77use alloc:: string:: String ;
88use embedded_graphics:: prelude:: DrawTarget ;
99use esp32c3_hal:: systimer:: SystemTimer ;
10- use esp_println:: println;
1110
1211pub const IROWS : isize = display:: ROWS as isize ;
1312pub const ICOLS : isize = display:: COLUMNS as isize ;
@@ -63,6 +62,18 @@ impl CursorPos {
6362 }
6463}
6564
65+ enum VerticalLocation {
66+ Middle ,
67+ Top ,
68+ Bottom ,
69+ }
70+
71+ enum HorizontalLocation {
72+ Middle ,
73+ Left ,
74+ Right ,
75+ }
76+
6677#[ derive( Debug , Clone , Copy ) ]
6778pub struct Cursor {
6879 pub pos : CursorPos ,
@@ -91,8 +102,20 @@ impl Cursor {
91102 * self
92103 }
93104
94- fn is_at_bottom ( & self ) -> bool {
95- self . pos . row ( ) == ROWS - 1
105+ fn location ( & self ) -> ( VerticalLocation , HorizontalLocation ) {
106+ const BOT : usize = ROWS - 1 ;
107+ const RIGHT : usize = COLUMNS - 1 ;
108+ let vert = match self . pos . row ( ) {
109+ BOT => VerticalLocation :: Bottom ,
110+ 0 => VerticalLocation :: Top ,
111+ _ => VerticalLocation :: Middle ,
112+ } ;
113+ let horz = match self . pos . col ( ) {
114+ RIGHT => HorizontalLocation :: Right ,
115+ 0 => HorizontalLocation :: Left ,
116+ _ => HorizontalLocation :: Middle ,
117+ } ;
118+ ( vert, horz)
96119 }
97120
98121 fn set_highlight ( & self , text : & mut TextDisplay ) {
@@ -216,52 +239,68 @@ impl TextField {
216239 . write ( self . cursor . pos . row ( ) , self . cursor . pos . col ( ) , t) ;
217240 self . move_cursor ( 0 , 1 ) ;
218241 }
219- '\n' => {
220- if self . cursor . is_at_bottom ( ) {
242+ '\n' => match self . cursor . location ( ) {
243+ ( VerticalLocation :: Bottom , _ ) => {
221244 self . cursor . unset_highlight ( & mut self . text ) ;
222245 self . text . scroll_down ( 1 ) ;
223246 self . move_cursor ( 0 , -( self . cursor . pos . col ( ) as isize ) )
224- } else {
225- self . move_cursor ( 1 , -( self . cursor . pos . col ( ) as isize ) )
226247 }
227- }
248+ _ => self . move_cursor ( 1 , -( self . cursor . pos . col ( ) as isize ) ) ,
249+ } ,
228250 '\r' => self . move_cursor ( 0 , -( self . cursor . pos . col ( ) as isize ) ) ,
229251 _ => {
230252 for c in t. escape_default ( ) {
231253 self . text . write ( self . cursor . pos . 0 , self . cursor . pos . 1 , c) ;
232- self . move_cursor ( 0 , 1 ) ;
254+ match self . cursor . location ( ) {
255+ ( _, HorizontalLocation :: Left | HorizontalLocation :: Middle ) => {
256+ self . move_cursor ( 0 , 1 ) ;
257+ }
258+ (
259+ VerticalLocation :: Top | VerticalLocation :: Middle ,
260+ HorizontalLocation :: Right ,
261+ ) => self . move_cursor ( 1 , -( self . cursor . pos . col ( ) as isize ) ) ,
262+ ( VerticalLocation :: Bottom , HorizontalLocation :: Right ) => {
263+ self . cursor . unset_highlight ( & mut self . text ) ;
264+ self . text . scroll_down ( 1 ) ;
265+ self . cursor . set_highlight ( & mut self . text ) ;
266+ self . move_cursor ( 0 , -( self . cursor . pos . col ( ) as isize ) ) ;
267+ }
268+ }
233269 }
234270 }
235271 }
236272 }
237273
238274 fn handle_op ( & mut self , op : Op ) {
239- use core:: cmp:: min;
240- use Op :: * ;
241- match & op {
242- TextOp ( v) => println ! (
243- "TextOp({:?}{}) [{}]" ,
244- & v[ ..min( v. len( ) , 5 ) ] ,
245- if v. len( ) > 5 { "..." } else { "" } ,
246- v. len( )
247- ) ,
248- DecPrivateSet ( v) => {
249- println ! (
250- "DecPrivateSet({:?}{}) [{}]" ,
275+ #[ cfg( feature = "op_log" ) ]
276+ {
277+ use core:: cmp:: min;
278+ use Op :: * ;
279+ match & op {
280+ TextOp ( v) => println ! (
281+ "TextOp({:?}{}) [{}]" ,
251282 & v[ ..min( v. len( ) , 5 ) ] ,
252283 if v. len( ) > 5 { "..." } else { "" } ,
253284 v. len( )
254- )
255- }
256- DecPrivateReset ( v) => {
257- println ! (
258- "DecPrivateReset({:?}{}) [{}]" ,
259- & v[ ..min( v. len( ) , 5 ) ] ,
260- if v. len( ) > 5 { "..." } else { "" } ,
261- v. len( )
262- )
285+ ) ,
286+ DecPrivateSet ( v) => {
287+ println ! (
288+ "DecPrivateSet({:?}{}) [{}]" ,
289+ & v[ ..min( v. len( ) , 5 ) ] ,
290+ if v. len( ) > 5 { "..." } else { "" } ,
291+ v. len( )
292+ )
293+ }
294+ DecPrivateReset ( v) => {
295+ println ! (
296+ "DecPrivateReset({:?}{}) [{}]" ,
297+ & v[ ..min( v. len( ) , 5 ) ] ,
298+ if v. len( ) > 5 { "..." } else { "" } ,
299+ v. len( )
300+ )
301+ }
302+ _ => println ! ( "{:?}" , op) ,
263303 }
264- _ => println ! ( "{:?}" , op) ,
265304 }
266305 match op {
267306 MoveCursorAbs { x, y } => {
@@ -274,7 +313,13 @@ impl TextField {
274313 self . move_cursor ( 0 , x as isize - self . cursor . pos . col ( ) as isize ) ;
275314 }
276315 MoveCursorDelta { dx, dy } => {
277- self . move_cursor ( dy, dx) ;
316+ // Constrain dx and dy so that the result added to the current position
317+ // stays within the window
318+ let x = ( self . cursor . pos . col ( ) as isize + dx) . clamp ( 0 , COLUMNS as isize - 1 )
319+ - self . cursor . pos . col ( ) as isize ;
320+ let y = ( self . cursor . pos . row ( ) as isize + dy) . clamp ( 0 , ROWS as isize - 1 )
321+ - self . cursor . pos . row ( ) as isize ;
322+ self . move_cursor ( y, x) ;
278323 }
279324 MoveCursorBeginningAndLine { dy } => {
280325 self . move_cursor ( dy, -( self . cursor . pos . col ( ) as isize ) ) ;
0 commit comments