;;; -*- TI-Asm -*- ;;; ;;; Mimas - Assembly language IDE for the TI-83 Plus ;;; ;;; Copyright (C) 2010 Benjamin Moody ;;; ;;; This program is free software: you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License as ;;; published by the Free Software Foundation; either version 3 of the ;;; License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;; General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program. If not, see . ;; EditTextLine: ;; ;; Allow user to edit text in the current edit buffer. This routine ;; returns when the user presses a key that is not recognized as a ;; text editing command. ;; ;; Input: ;; - Edit buffer contains text to be edited ;; - (textEditXStart) = X coordinate to place left edge of edit box ;; - (textEditXEnd) = X coordinate to place right edge of edit box ;; - (penRow), (penCol) = current cursor position ;; - editVarName, (iy + asm_Flag3) = 1 to allow typing only legal ;; variable name characters ;; ;; Output: ;; - A = keypress value ;; - editTextChanged, (iy + asm_Flag3) = 1 if text has been modified ;; ;; Destroys: ;; - AF, BC, DE, HL EditTextLine: ld a,(penRow) dec a ld e,a ld hl,(textEditXStart) ld a,h sub l inc a ld b,a ld a,l ld c,9 call FillRectangle EditTextLine_Redisplay: ld hl,(textEditXStart) inc l ld a,h sub l ld b,a ld a,l ld de,(penRow) ld c,7 call ClearRectangle call DispTextHead call DispTextTail call XBufCpy EditTextLine_Loop: call GetKeyCursor cp kClear jr z,EditTextLine_Clear res editClearPressed,(iy + asm_Flag3) cp kVarx ret z SWITCH_BEGIN SWITCH_CASE kLeft, EditTextLine_Left SWITCH_CASE kRight, EditTextLine_Right SWITCH_CASE kBOL, EditTextLineStart SWITCH_CASE kEOL, EditTextLine_EOL SWITCH_CASE kDel, EditTextLine_Del ; SWITCH_CASE kClear, EditTextLine_Clear SWITCH_CASE kBackspace, EditTextLine_Backspace SWITCH_CASE kColon, EditTextLine_Colon SWITCH_CASE kRecall, EditTextLine_Rcl SWITCH_END call CheckAsmEditShortcuts cp EchoStart ret c call KeyToChar jr nz,EditTextLine_Loop EditTextLine_Insert: bit editVarName,(iy + asm_Flag3) jr z,EditTextLine_InsertOK cp '0' jr c,EditTextLine_Loop cp '9'+1 jr c,EditTextLine_InsertOK call IsFileNameStartChar jr c,EditTextLine_Loop EditTextLine_InsertOK: call TextEditInsertChar jr EditTextLine_Redisplay EditTextLineStart: call TextEditBOL jr EditTextLine EditTextLine_Left: call TextEditLeft jr EditTextLine_MaybeRedisplay EditTextLine_Right: call TextEditRight EditTextLine_MaybeRedisplay: jr c,EditTextLine_Loop EditTextLine_Redisplay_: jr EditTextLine_Redisplay EditTextLine_EOL: call TextEditEOL jr EditTextLine_MaybeRedisplay EditTextLine_Del: call TextBufAtEOB jr nz,EditTextLine_Del_OK EditTextLine_QuitIfMostlyEmpty: call TextBufMostlyEmpty ret z EditTextLine_Loop_: jr EditTextLine_Loop EditTextLine_Del_OK: call TextEditDeleteNext jr EditTextLine_Redisplay_ EditTextLine_Clear: ; call TextBufAtEOB ; jr nz,EditTextLine_ClearRight ; call TextBufMostlyEmpty ; ret z ; call TextBufClear ; jr EditTextLineStart ; EditTextLine_ClearRight: ; call TextBufClearTail ; jr EditTextLine_Redisplay_ call TextBufMostlyEmpty ret z call TextBufAtEOB jr nz,EditTextLine_ClearRight bit editClearPressed,(iy + asm_Flag3) ld hl,cutBuffer call nz,TextBufInsertString ld de,(editTop) ld hl,(editCursor) call SaveToCutBuffer call TextBufClear jr EditTextLineStart EditTextLine_Colon: call TextBufHeadMostlyEmpty ld a,Lsemicolon jr z,EditTextLine_Insert ld hl,(editCursor) call FindWordStart inc hl call TextBufHeadMostlyEmptyUpToAddr ld a,':' jr nz,EditTextLine_Insert ;; delete leading spaces ex de,hl ld hl,(editCursor) or a sbc hl,de jr z,EditTextLine_Insert ld b,h ld c,l ld hl,(editTop) ex de,hl ldir ld (editCursor),de ld a,':' call TextBufInsertChar EditTextLine_MoveCursorCurrent: call TextEditMoveCursorCurrent EditTextLine_Redisplay__: jr EditTextLine_Redisplay_ EditTextLine_Backspace: call TextBufAtBOB jr z,EditTextLine_QuitIfMostlyEmpty call TextEditLeft jr EditTextLine_Del_OK EditTextLine_Rcl: ld hl,cutBuffer call TextBufInsertString jr EditTextLine_MoveCursorCurrent EditTextLine_ClearRight: ld de,(editTail) ld hl,(editBtm) call SaveToCutBuffer call TextBufClearTail set editClearPressed,(iy + asm_Flag3) jr EditTextLine_Redisplay__ ;; CheckAsmEditShortcuts: ;; ;; Check if A is an instruction shortcut key; if so, insert the ;; corresponding mnemonic if appropriate. ;; ;; Input: ;; - A = keycode ;; ;; Output: ;; - A = 0 if a shortcut ;; ;; Destroys: ;; - F, BC, DE, HL ;; - OP1 CheckAsmEditShortcuts: bit editAsmShortcuts,(iy + asm_Flag3) ret z call TextBufMostlyEmpty ret nz ld hl,shortcutKeyTable ld bc,numShortcutKeys cpir ret nz ld c,numShortcutKeys - 1 add hl,bc ld e,(hl) ld hl,(editTop) ld (editCursor),hl call TextBufInsertNormalMnemonic call TextEditMoveCursorCurrent set shiftAlpha,(iy + shiftFlags) xor a ret ;; DispTextHead: ;; ;; Display the edit-buffer text to the left of the cursor. ;; ;; Destroys: ;; - AF, BC, DE, HL DispTextHead: push ix ld a,(textEditXStart) inc a ld c,a ld a,(penCol) ld b,a ; push bc ; ld de,(penRow) ; sub c ; ld b,a ; ld a,c ; ld c,7 ; call ClearRectangle ; pop bc inc c ld hl,(editCursor) jr DispTextHead_Begin DispTextHead_Loop: push bc call PutCharBitmap pop bc pop hl DispTextHead_Begin: ld de,(editTop) scf sbc hl,de jr c,DispTextHead_StartOfBuffer add hl,de ld a,(hl) push hl push bc BCALL _LoadPattern pop bc ld a,b sub (hl) ld b,a cp c jp p,DispTextHead_Loop ld a,c sub 2 ld hl,textEditScrollLeftBitmap DispTextHead_FinishClip: call PutCharBitmap pop hl pop ix ret DispTextHead_StartOfBuffer: dec c dec c DispTextHead_FinishNoClip: ld a,(penRow) ld e,a ld a,c ld c,7 pop ix ld b,1 jq_ FillRectangle ;; DispTextTail: ;; ;; Display the edit-buffer text to the right of the cursor. ;; ;; Destroys: ;; - AF, BC, DE, HL ;; - sFont_record DispTextTail: push ix ld a,(penCol) ld b,a ld a,(textEditXEnd) ld c,a ; push bc ; ld de,(penRow) ; sub b ; ld c,a ; ld a,b ; ld b,c ; ld c,7 ; call ClearRectangle ; pop bc ld hl,(editTail) jr DispTextTail_Begin DispTextTail_Loop: sub (hl) push bc call PutCharBitmap pop bc pop hl inc hl DispTextTail_Begin: ld de,(editBtm) or a sbc hl,de jr nc,DispTextHead_FinishNoClip add hl,de ld a,(hl) push hl push bc BCALL _LoadPattern pop bc ld a,b add a,(hl) ld b,a cp c jr c,DispTextTail_Loop ld a,c sub 3 ld hl,textEditScrollRightBitmap jr DispTextHead_FinishClip ;; TextEditEOL: ;; ;; Move the cursor to the end of the line. ;; ;; Output: ;; - Carry flag clear if display needs to be redrawn ;; ;; Destroys: ;; - AF, HL TextEditEOL: call TextBufForwardChar ret c call MoveEditCursorRight jr c,TextEditEOL call TextBufEOB ld a,(textEditXEnd) sub 8 ld (penCol),a or a ret ;; TextEditBOL: ;; ;; Move the cursor to the start of the line. ;; ;; Destroys: ;; - AF, B, HL TextEditBOL: ld a,(textEditXStart) add a,3 ld (penCol),a call TextBufBOB call TextBufPeekNextChar cp SFourSpaces ret nz ;; fall through ;; TextEditRight: ;; ;; Move the cursor right. If already at end of buffer, do nothing. ;; ;; Output: ;; - Carry flag clear if display needs to be redrawn ;; ;; Destroys: ;; - AF, B, HL TextEditRight: call TextBufForwardChar ret c MoveEditCursorRight: call SFont_Len_A ld hl,penCol ld a,(hl) add a,b ld (hl),a ld a,(textEditXEnd) sub 8 MoveEditCursorRight_AtEOB: cp (hl) ccf ret c ld (hl),a ret ;; TextEditInsertChar: ;; ;; Insert a character in the text editor. If buffer is full, do nothing. ;; ;; Input: ;; - A = character ;; ;; Destroys: ;; - AF, B, HL TextEditInsertChar: call TextBufInsertChar ret c jr MoveEditCursorRight ;; TextEditLeft: ;; ;; Move the cursor left. If already at start of buffer, do nothing. ;; ;; Output: ;; - Carry flag clear if display needs to be redrawn ;; ;; Destroys: ;; - AF, B, HL TextEditLeft: call TextBufBackwardChar ret c MoveEditCursorLeft: call SFont_Len_A ld hl,penCol ld a,(hl) sub b ld (hl),a ld a,(textEditXStart) add a,2 call TextBufAtBOB jr z,MoveEditCursorLeft_AtBOB add a,2 MoveEditCursorLeft_AtBOB: cp (hl) scf ret m inc a ld (hl),a or a ret ;; TextEditDeleteNext: ;; ;; Delete the character following the cursor. If already at end of ;; buffer, do nothing. ;; ;; Output: ;; - Carry flag clear if tail needs to be redrawn ;; ;; Destroys: ;; - AF, HL TextEditDeleteNext: call TextBufForwardChar ret c ;; fall through ;; TextBufDeletePrevChar: ;; ;; Delete the character in the buffer before the insertion point. ;; ;; Output: ;; - Carry flag set if already at start of buffer ;; ;; Destroys: ;; - F TextBufDeletePrevChar: set editTextChanged,(iy + asm_Flag3) TextBufDeletePrevCharNF: push hl push de ld hl,(editCursor) ld de,(editTop) scf sbc hl,de jr c,TextBufDeletePrevChar_Done add hl,de ld (editCursor),hl TextBufDeletePrevChar_Done: pop de pop hl ret ;; TextEditMoveCursor: ;; ;; Move text buffer cursor to a specified position, and update penCol ;; appropriately by moving "rightwards" from the start of the buffer. ;; ;; Input: ;; - DE = target cursor address ;; ;; Destroys: ;; - AF, B, HL TextEditMoveCursorCurrent: ld de,(editCursor) TextEditMoveCursor: call TextEditBOL TextEditMoveCursor_Loop: ld hl,(editCursor) or a sbc hl,de ret nc call TextEditRight call TextBufAtEOB jr nz,TextEditMoveCursor_Loop ret ;; TextBufClear: ;; ;; Clear the edit buffer. ;; ;; Destroys: ;; - HL TextBufClear: ld hl,(editTop) ld (editCursor),hl TextBufClearTail: set editTextChanged,(iy + asm_Flag3) ld hl,(editBtm) ld (editTail),hl ret ;; TextBufAtBOB: ;; ;; Check if we are currently at the beginning of the edit buffer. ;; ;; Output: ;; - Zero flag set if we are currently at the start of the buffer ;; ;; Destroys: ;; - F TextBufAtBOB: push hl push de BCALL _IsAtTop pop de pop hl ret ;; TextBufAtEOB: ;; ;; Check if we are currently at the end of the edit buffer. ;; ;; Output: ;; - Zero flag set if we are currently at the end of the buffer ;; ;; Destroys: ;; - F TextBufAtEOB: push bc ld b,a call TextBufPeekNextChar ld a,b pop bc ret ;; TextBufMostlyEmpty: ;; ;; Check if the edit buffer is empty or contains only space ;; characters. ;; ;; Output: ;; - Zero flag set if buffer is mostly empty ;; ;; Destroys: ;; - F TextBufMostlyEmpty: push hl push de push bc ld b,a call TextBufHeadMostlyEmpty call z,TextBufTailMostlyEmpty ld a,b pop bc pop de pop hl ret ;; TextBufHeadMostlyEmpty: ;; ;; Check if the head of the edit buffer is empty or contains only ;; space characters. ;; ;; Output: ;; - Zero flag set if buffer head is mostly empty ;; ;; Destroys: ;; - AF, DE, HL TextBufHeadMostlyEmpty: ld hl,(editCursor) TextBufHeadMostlyEmptyUpToAddr: ld de,(editTop) or a TextBufHeadMostlyEmpty_Loop: sbc hl,de add hl,de ret z ret c ld a,(de) inc de call IsSpaceChar jr z,TextBufHeadMostlyEmpty_Loop ret ;; TextBufTailMostlyEmpty: ;; ;; Check if the tail of the edit buffer is empty or contains only ;; space characters. ;; ;; Output: ;; - Zero flag set if buffer tail is mostly empty ;; ;; Destroys: ;; - AF, DE, HL TextBufTailMostlyEmpty: ld de,(editTail) ld hl,(editBtm) jr TextBufHeadMostlyEmpty_Loop ;; TextBufPeekNextChar: ;; ;; Get the character following the current insertion point. Zero ;; indicates end of buffer. ;; ;; Output: ;; - A = character ;; - Zero flag set if at end of buffer ;; ;; Destroys: ;; - F TextBufPeekNextChar: push hl push de ld hl,(editTail) ld de,(editBtm) ld a,(hl) or a sbc hl,de pop de pop hl ret nz xor a ret ;; TextBufForwardChar: ;; ;; Move forward one character in the edit buffer. ;; ;; Output: ;; - A = character skipped over ;; - Carry flag set if at end of buffer ;; ;; Destroys: ;; - F TextBufForwardChar: push hl push de ld hl,(editTail) ld de,(editBtm) or a sbc hl,de add hl,de ccf jr c,TextBufForwardChar_Done ld de,(editCursor) ld a,(hl) ldi inc bc ld (editCursor),de ld (editTail),hl TextBufForwardChar_Done: pop de pop hl ret ;; TextBufBackwardChar: ;; ;; Move backward one character in the edit buffer. ;; ;; Output: ;; - A = character skipped over ;; - Carry flag set if at start of buffer ;; ;; Destroys: ;; - F TextBufBackwardChar: push hl push de ld hl,(editCursor) ld de,(editTop) scf sbc hl,de jr c,TextBufForwardChar_Done add hl,de ld (editCursor),hl ld de,(editTail) dec de ld (editTail),de ld a,(hl) ld (de),a jr TextBufForwardChar_Done ;; TextBufToZTStr: ;; ;; Convert text buffer into a contiguous, zero-terminated string. ;; This assumes there is an extra byte at (editBtm) if ;; necessary. ;; ;; Output: ;; - HL = start of text buffer ;; ;; Destroys: ;; - F TextBufToZTStr: call TextBufEOB ld hl,(editCursor) ld (hl),0 ld hl,(editTop) ret ;; TextBufEOB: ;; ;; Move the insertion point to the end of the edit buffer. ;; ;; Destroys: ;; - F TextBufEOB: push hl push de push bc BCALL _BufToBtm TextBufEOB_Done: pop bc pop de pop hl ret ;; TextBufBOB: ;; ;; Move the insertion point to the start of the edit buffer. ;; ;; Destroys: ;; - F TextBufBOB: push hl push de push bc BCALL _BufToTop jr TextBufEOB_Done ;; TextBufInsertSymbolString: ;; ;; Insert a constant symbol string from page 1 into the edit buffer. ;; ;; Input: ;; - HL = address of symbol string (RAM or page 1) ;; ;; Output: ;; - Carry flag set if buffer full ;; ;; Destroys: ;; - AF, DE, HL ;; - OP1-OP3 TextBufInsertSymbolString: ld de,OP1 push de push bc call UnpackSymbolString pop bc pop hl jr TextBufInsertString ;; TextBufInsertNormalMnemonic: ;; ;; Insert a normal instruction mnemonic, with spaces before and after ;; it. ;; ;; Input: ;; - E = byte offset (from normalMnemonics) to mnemonic string ;; ;; Destroys: ;; - AF, B, DE, HL ;; - OP1 TextBufInsertNormalMnemonic: ld d,0 ld hl,normalMnemonics add hl,de ;; fall through ;; TextBufInsertMnemonic: ;; ;; Insert an instruction mnemonic, with spaces before and after it. ;; ;; Input: ;; - HL = address of mnemonic string (ASCII characters with bit 7 set, ;; terminated by a byte without bit 7 set) ;; ;; Destroys: ;; - AF, B, DE, HL ;; - OP1 TextBufInsertMnemonic: ld a,SFourSpaces call TextBufInsertChar ; ld b,5 ; TextBufInsertMnemonic_Loop: ; dec b ; jr nz,TextBufInsertMnemonic_BNot0 ; inc b ; TextBufInsertMnemonic_BNot0: ; ld a,(hl) ; and 7Fh ; call TextBufInsertChar ; cp (hl) ; inc hl ; jr nz,TextBufInsertMnemonic_Loop ; ld a,SFourSpaces ; TextBufInsertMnemonic_PadLoop: ; call TextBufInsertChar ; djnz TextBufInsertMnemonic_PadLoop ; ret ld de,OP1 call Extract_pMStr ;; fall through ;; TextBufInsertString: ;; ;; Insert a zero-terminated string into the edit buffer. ;; ;; Input: ;; - HL = address of string ;; ;; Output: ;; - Carry flag set if buffer full ;; ;; Destroys: ;; - AF TextBufInsertString: ld a,(hl) inc hl or a ret z call TextBufInsertChar jr nc,TextBufInsertString ret ;; TextBufInsertQuotedChar: ;; ;; Insert a character into the edit buffer, adding a backslash if ;; necessary for literal character/string syntax. ;; ;; Input: ;; - A = character ;; ;; Destroys: ;; - AF TextBufInsertQuotedChar: SWITCH_BEGIN SWITCH_CASE 0, TextBufInsertQuotedChar_Backslash0 SWITCH_CASE Lquote, TextBufInsertQuotedChar_Backslash SWITCH_CASE Lapostrophe, TextBufInsertQuotedChar_Backslash SWITCH_CASE Lbackslash, TextBufInsertQuotedChar_Backslash SWITCH_CASE Lenter, TextBufInsertQuotedChar_BackslashXX SWITCH_END cp LblockArrow jr c,TextBufInsertChar TextBufInsertQuotedChar_BackslashXX: push af ld a,Lbackslash call TextBufInsertChar ld a,'x' call TextBufInsertChar pop af jr TextBufInsertHex8 TextBufInsertQuotedChar_Backslash0: ld a,'0' TextBufInsertQuotedChar_Backslash: push af ld a,Lbackslash call TextBufInsertChar pop af jr TextBufInsertChar ;; TextBufInsertBin8: ;; ;; Insert eight binary digits into the edit buffer. ;; ;; Input: ;; - A = byte value ;; ;; Output: ;; - Carry flag set if buffer full ;; ;; Destroys: ;; - AF TextBufInsertBin8: push bc ld c,a ld b,8 TextBufInsertBin8_Loop: sla c ld a,'0'/2 rla call TextBufInsertChar djnz TextBufInsertBin8_Loop pop bc ret ;; TextBufInsertHex8: ;; ;; Insert two hexadecimal digits into the edit buffer. ;; ;; Input: ;; - A = byte value ;; ;; Output: ;; - Carry flag set if buffer full ;; ;; Destroys: ;; - AF TextBufInsertHex8: push af call HexHToASCII call TextBufInsertChar pop af call HexLToASCII ;; fall through ;; TextBufInsertChar: ;; ;; Insert a character into the edit buffer. ;; ;; Input: ;; - A = character ;; ;; Output: ;; - Carry flag set if buffer full ;; ;; Destroys: ;; - F TextBufInsertChar: set editTextChanged,(iy + asm_Flag3) TextBufInsertCharNF: push hl push de ld hl,(editTail) ld de,(editCursor) scf sbc hl,de jr c,TextBufInsertChar_Error ld (de),a inc de ld (editCursor),de TextBufInsertChar_Error: pop de pop hl ret ;; FindWordStart: ;; ;; Search backwards from a given address to find the beginning of the ;; word, if any. ;; ;; Input: ;; - HL = address of a character ;; ;; Output: ;; - HL = address of most recent non-word character before the given ;; address ;; ;; Destroys: ;; - AF FindWordStart: dec hl ld a,(hl) call IsWordChar jr nc,FindWordStart cp '.' jr z,FindWordStart ret ;; SaveToCutBuffer: ;; ;; Save the text in the given region to the cut buffer. If the given ;; region is empty, leave the cut buffer untouched. ;; ;; Input: ;; - DE = start of region to save ;; - HL = end of region to save ;; ;; Destroys: ;; - AF, BC, DE, HL SaveToCutBuffer: xor a sbc hl,de ret z ld b,h ld c,l ex de,hl ld de,cutBuffer ldir ld (de),a ret