.module Editor ;; Pointer to the start of the variable being edited (size bytes). .var uword VarStartAddress ;; Pointer to the start of the variable's data. .var uword DataStartAddress ;; Pointer to the character sitting under the cursor. .var uword CursorAddress ;; Pointer to the character that appears in the top-left of the editor (top line). .var uword TopOfScreenLineAddress ;; Pointer to the byte after the last character in the variable. EndAddress = iMathPtr2 ;; Pointer to the byte after the largest possible EndAddress value (do not make the variable bigger than this!). MaximumEndAddress = iMathPtr3 .var ubyte[24*10] OldConsole.Buffer .var ubyte OldConsole.Cursor.X .var ubyte OldConsole.Cursor.Y ;; Edit a text variable. ;; Pointer to variable data (size bytes). ;; Pointer to VAT entry. ;; All registers. Edit ld (VarStartAddress),de .bcall _EditProg ld hl,(MaximumEndAddress) ld de,(EndAddress) or a sbc hl,de jr nz,+ .bcall _CloseProg ret ; Out of memory? + ld hl,Console.Buffer ld de,OldConsole.Buffer ld bc,SizeOf(OldConsole.Buffer) ldir ld a,(Console.Cursor.X) ld (OldConsole.Cursor.X),a ld a,(Console.Cursor.Y) ld (OldConsole.Cursor.Y),a ld hl,(EndAddress) ld (hl),'\n' ; EOF marker. inc hl ld (EndAddress),hl ld hl,(VarStartAddress) inc hl inc hl ld (DataStartAddress),hl ld (TopOfScreenLineAddress),hl ld (CursorAddress),hl xor a ld (Cursor.X),a ld (Cursor.Y),a inc a call RepaintAll RestartEditKeyLoop call Console.Cursor.ResetBlink EditKeyLoop call Console.Cursor.GetChar call Console.PutMapNoWriteBuffer push hl call Keypad.GetChar pop hl jr nz,EditKeyLoop push af call Console.RestoreCurrentCharacter pop af InjectKey jp p,NotExtendedKey ; [->] Right cursor key. cp Emerson.Keyboard.KeyCode.Right jr nz,+ call Cursor.MoveRight jr RestartEditKeyLoop + ; [<-] Left cursor key. cp Emerson.Keyboard.KeyCode.Left jr nz,+ call Cursor.MoveLeft jr RestartEditKeyLoop + ; [v] Down cursor key. cp Emerson.Keyboard.KeyCode.Down jr nz,+ call Cursor.MoveDown jr RestartEditKeyLoop + ; [^] Up cursor key. cp Emerson.Keyboard.KeyCode.Up jr nz,+ call Cursor.MoveUp jr RestartEditKeyLoop + ; [Page Down] key. cp Emerson.Keyboard.KeyCode.PageDown jr nz,+ call Cursor.PageDown jr RestartEditKeyLoop + ; [Page Up] key. cp Emerson.Keyboard.KeyCode.PageUp jr nz,+ call Cursor.PageUp jr RestartEditKeyLoop + ; [End] key. cp Emerson.Keyboard.KeyCode.End jr nz,+ call Cursor.MoveEnd jr RestartEditKeyLoop + ; [Home] key. cp Emerson.Keyboard.KeyCode.Home jr nz,+ call Cursor.MoveHome jr RestartEditKeyLoop + cp Emerson.Keyboard.KeyCode.Escape jp z,Quit jp RestartEditKeyLoop ; It's an extended key, but I don't know it... NotExtendedKey ; Translate \r -> \n cp '\r' \ jr nz,+ ld a,'\n' + ; Backspace key. cp '\b' \ jr nz,NotBackspace ld hl,(DataStartAddress) ld de,(CursorAddress) or a sbc hl,de jp z,RestartEditKeyLoop ; Can't backspace from char 0. ld hl,(EndAddress) ld de,(CursorAddress) or a sbc hl,de ld b,h ld c,l ld hl,(CursorAddress) ld de,(CursorAddress) dec de ldir ld hl,(EndAddress) dec hl ld (EndAddress),hl ld ix,(VarStartAddress) ld l,(ix+0) \ ld h,(ix+1) dec hl ld (ix+0),l \ ld (ix+1),h ld a,Emerson.Keyboard.KeyCode.Left cp 128 ; ssf jp InjectKey NotBackspace ; Insert a character. ld hl,(MaximumEndAddress) ld de,(EndAddress) or a sbc hl,de jp z,RestartEditKeyLoop ; Not enough room. ; Enlarge the variable. ld ix,(VarStartAddress) ld e,(ix+0) \ ld d,(ix+1) inc de ld (ix+0),e \ ld (ix+1),d ld de,(EndAddress) inc de ld (EndAddress),de dec de ld h,d ld l,e dec hl ; hl->old last character. ; de->new last character. push hl ld bc,(CursorAddress) or a sbc hl,bc ld b,h ld c,l inc bc pop hl ; bc->length from cursor->end of file. lddr ; Insert the character proper. ld hl,(CursorAddress) ld (hl),a ld a,Emerson.Keyboard.KeyCode.Right cp 128 ; ssf jp InjectKey Quit ld hl,(EndAddress) dec hl ld (EndAddress),hl .bcall _CloseProg ; Restore the original text buffer and cursor position to the display. ld hl,OldConsole.Buffer xor a ld (Console.Cursor.X),a ld (Console.Cursor.Y),a - ld a,(hl) inc hl call Console.PutMap ld a,(Console.Cursor.X) inc a ld (Console.Cursor.X),a cp 24 jr nz,- xor a ld (Console.Cursor.X),a ld a,(Console.Cursor.Y) inc a ld (Console.Cursor.Y),a cp 10 jr nz,- ld a,(OldConsole.Cursor.X) ld (Console.Cursor.X),a ld a,(OldConsole.Cursor.Y) ld (Console.Cursor.Y),a ret ;; Repaints the entire screen. ;; This does not clear the screen first. RepaintAllNoClear xor a ld (Console.Cursor.X),a ld (Console.Cursor.Y),a jr + ;; Repaints the entire screen. ;; This clears the screen first. RepaintAll call Console.Clear + xor a ld (Cursor.IsOnScreen),a ld hl,(TopOfScreenLineAddress) ld de,(CursorAddress) ld bc,(EndAddress) RepaintLoop ld a,(hl) or a push hl sbc hl,de pop hl jr nz,+ push af ld a,1 ld (Cursor.IsOnScreen),a ld a,(Console.Cursor.X) ld (Editor.Cursor.X),a ld a,(Console.Cursor.Y) ld (Editor.Cursor.Y),a pop af + or a push hl sbc hl,bc pop hl jr nz,+ ; End of file. - ld a,' ' call PutChar jr nz,- jr FinishedRepainting + call PutChar inc hl jr nz,RepaintLoop FinishedRepainting ld a,(Editor.Cursor.X) ld (Console.Cursor.X),a ld a,(Editor.Cursor.Y) ld (Console.Cursor.Y),a ret ;; Puts a character on the display. ;; The charcter to write. ;; z if the cursor has just moved off the screen; nz if it's still on it. PutChar cp '\n' jr nz,+ - ld a,' ' call Console.PutMap ld a,(Console.Cursor.X) inc a ld (Console.Cursor.X),a cp 24 jr nz,- xor a ld (Console.Cursor.X),a ld a,(Console.Cursor.Y) inc a cp 10 ret z ld (Console.Cursor.Y),a inc a ret + call Console.PutMap ld a,(Console.Cursor.X) inc a cp 24 jr z,+ ld (Console.Cursor.X),a xor a inc a ret + xor a ld (Console.Cursor.X),a ld a,(Console.Cursor.Y) inc a cp 10 ret z ld (Console.Cursor.Y),a ret ;; Checks whether you are at the end of the file. ;; z if you are; nz if you aren't. ;; f. AtEnd push hl push de ld de,(CursorAddress) ld hl,(EndAddress) scf sbc hl,de pop de pop hl ret ;; Checks whether you are at the start of the file. ;; z if you are; nz if you aren't. ;; f. AtStart push hl push de ld de,(CursorAddress) ld hl,(DataStartAddress) or a sbc hl,de pop de pop hl ret ;; Scrolls the screen up a line. ScrollUp ld hl,(TopOfScreenLineAddress) ld de,(DataStartAddress) ld b,24 - dec hl or a push hl sbc hl,de pop hl jr nz,+ ld (TopOfScreenLineAddress),hl jr FinishedScrollingUp + ld a,(hl) cp '\n' jr z,+ djnz - ld (TopOfScreenLineAddress),hl jr FinishedScrollingUp + ; So, there's an irritating carriage return somewhere along the way. ; Find the start of the previous FULL line. - dec hl ld a,(hl) cp '\n' jr z,+ or a push hl sbc hl,de pop hl jr nz,- dec hl + inc hl ld (TopOfScreenLineAddress),hl ; Find the last 24 character multiple before the final line feed. -- ld b,24 - ld a,(hl) cp '\n' jr z,+ inc hl djnz - ld (TopOfScreenLineAddress),hl jr -- + FinishedScrollingUp ret ;; Scrolls the screen down a line. ScrollDown ld b,24 ld hl,(TopOfScreenLineAddress) - ld a,(hl) inc hl cp '\n' jr z,+ djnz - + ld (TopOfScreenLineAddress),hl ret .module Cursor ;; The X-coordinate of the editor's cursor. .var ubyte X ;; The Y-coordinate of the editor's cursor. .var ubyte Y ;; Zero if the cursor is on screen, false otherwise. .var ubyte IsOnScreen ;; Moves the cursor right one character. ;; Triggers a repaint. ;; All registers. MoveRight ld hl,(CursorAddress) inc hl push hl ld de,(EndAddress) or a sbc hl,de pop hl ret z ld (CursorAddress),hl call RepaintAllNoClear ld a,(Cursor.IsOnScreen) or a ret nz jp ScrollDown ;; Moves the cursor left one character. ;; Triggers a repaint. ;; All registers. MoveLeft ld hl,(CursorAddress) ld de,(DataStartAddress) or a sbc hl,de ret z ld hl,(CursorAddress) dec hl ld (CursorAddress),hl call RepaintAllNoClear ld a,(Cursor.IsOnScreen) or a ret nz jp ScrollUp ;; Moves the cursor to the end of a line. ;; Triggers a repaint. ;; All registers. MoveEnd ld hl,(CursorAddress) ld de,(EndAddress) scf sbc hl,de ret z - ld de,(CursorAddress) ld hl,(EndAddress) scf sbc hl,de jr z,FoundEnd ld a,(de) cp '\n' jr z,FoundEnd inc de ld (CursorAddress),de jr - FoundEnd ;; Scrolls the screen down until the cursor is visible. ScrollDownToCursor - call RepaintAllNoClear ld a,(Cursor.IsOnScreen) or a ret nz call ScrollDown jr - ;; Moves the cursor to the start of a line. ;; Triggers a repaint. ;; All registers. MoveHome ld hl,(CursorAddress) ld de,(DataStartAddress) or a sbc hl,de ret z - ld de,(CursorAddress) ld hl,(DataStartAddress) or a sbc hl,de jr z,FoundHome dec de ld a,(de) cp '\n' jr z,FoundHome ld (CursorAddress),de jr - FoundHome ;; Scrolls the screen up until the cursor is visible. ScrollUpToCursor - call RepaintAllNoClear ld a,(Cursor.IsOnScreen) or a ret nz call ScrollUp jr - ;; Moves the cursor down a line. ;; Triggers a repaint. ;; All registers. MoveDown ld a,(X) ld b,a ld a,24 sub b ld b,a - call AtEnd jr z,FoundLineBelowStart ld hl,(CursorAddress) ld a,(hl) inc hl ld (CursorAddress),hl cp '\n' jr z,FoundLineBelowStart djnz - FoundLineBelowStart ld a,(X) or a jr z,FoundColumnBelowStart ld b,a - call AtEnd jr z,FoundColumnBelowStart ld hl,(CursorAddress) inc hl ld (CursorAddress),hl ld a,(hl) cp '\n' jr z,FoundColumnBelowStart djnz - FoundColumnBelowStart jr ScrollDownToCursor ;; Moves the cursor up a line. ;; Triggers a repaint. ;; All registers. MoveUp ld a,(X) ld c,a or a jr z,+ ld b,a - call AtStart jr z,+ ld hl,(CursorAddress) dec hl ld (CursorAddress),hl djnz - + call AtStart jr z,+ ld hl,(CursorAddress) dec hl ld (CursorAddress),hl + push bc call ScrollUpToCursor pop bc ; At this point, we're at the end of the previous line. ld hl,(CursorAddress) ld a,(X) - cp c jr z,ScrollUpToCursor jr c,ScrollUpToCursor call AtStart jr z,ScrollUpToCursor dec hl dec a ld (CursorAddress),hl jr - ;; Moves down a page of text. PageDown ld b,10 - push bc call MoveDown pop bc djnz - ret ;; Moves up a page of text. PageUp ld b,10 - push bc call MoveUp pop bc djnz - ret .endmodule .endmodule