;******************************************************************************* ;* Module : READLN.SUB ;* Programmer: Tony Papadimitriou <tonyp@acm.org> ;* Purpose : Read a text line (with or w/out echo) from getc macro input ;* Language : Motorola/Freescale/NXP HC08/9S08 Assembly Language (aspisys.com/ASM8) ;* Status : FREEWARE Copyright (c) 2021 by Tony Papadimitriou <tonyp@acm.org> ;* Original : http://www.aspisys.com/code/hc08/readln.html ;* Note(s) : Use: #Include readln.sub ;* History : 10.12.09 v1.00 Original ;* : 16.06.17 BugFix: Added missing TSTA instruction to check length ;* : Added echo option via the putc macro ;* : Added backspace recognition in echo mode only ;* : Added Escape recognition in echo mode only ;* : 16.08.01 Minor optimization in Readln proc [-1 byte] ;* : Removed redundant BEQ in Readln proc [-2 bytes] ;* : Minor optimization in Readln proc Done@@ [-4 bytes] ;* : 21.09.09 Minor optimization by Readln proc Cont@@ [-2 bytes] ;* : Simplified CCR[C] checks in Readln proc [-3 bytes] ;******************************************************************************* #ifmain ;----------------------------------------------------------------------- #ListOff #Uses mcu.inc #ListOn getc macro #if :index = 1 ... \@~macro~\@ macro is a stub mexit #endif !... endm putc macro #if :index = 1 ... \@~macro~\@ macro is a stub mexit #endif !... endm #endif ;------------------------------------------------------------------------ ?_OBJECT_? ;******************************************************************************* ; Purpose: Read a CR terminated line (LFs ignored) ; Input : HX -> buffer for received string ; : A = maximum buffer size (including NUL terminator) ; : CCR[C] = 0: no echo and no editing allowed ; : CCR[C] = 1: with echo and editing allowed ; Output : A = number of characters read ; : (HX -> Buffer) is filled with input data ; Note(s): A terminator character (CR) is required to exit the routine ; : If length is zero, you just wait for a CR without saving ; : If more characters arrive than buffer can hold, they are truncated Readln macro [Buffer][,MaxLength][,echo] #ifb ~@~ call ~0~ mexit #endif mdef 3,clc ;;default is no echo #ifnoparm ~3~ = clc mset 3,sec #endif #ifparm ~1~ #ifb ~2~ #push #spauto :sp pshhx @@lea ~1~ ~3~ call ~0~ pulhx #pull mexit #endif #endif #ifparm ~2~ #ifb ~1~ #push #spauto :sp psha lda ~2~ ~3~ call ~0~ pula #pull mexit #endif #endif #push #spauto :sp push lda ~2~ @@lea ~1~ ~3~ call ~0~ pull #pull endm ;------------------------------------------------------------------------------- #spauto Readln proc pshhx .buf@@ #ais psha len@@ tpa and #CCR_C_ ;we only care for CCR[C] flag psha ccr@@ lda len@@,sp psha remain@@ ;chars remaining (max characters to read) beq Save?@@ ;if zero, wait for terminator ;-------------------------------------- bra Cont@@ Loop@@ @getc ;read a character cbeqa #LF,Loop@@ ;LFs are ignored cbeqa #CR,Done@@ ;on CR terminator, exit ;-------------------------------------- ;the remaining checks apply only in echo mode tst ccr@@,sp ;is echo enabled? beq Save?@@ ;no, skip next checks cbeqa #BS,Backspace@@ ;on BS, if in echo mode, delete last character cbeqa #ESC,ClearLine@@ ;on ESC, if in echo mode, clear the whole line ;-------------------------------------- Save?@@ tst remain@@,sp ;a possible BS puts us back in the game beq Loop@@ ;if zero, only terminator will work cmpa #' ' ;nothing below space is accepted blo Loop@@ sta ,x ;anything else save in buffer tst ccr@@,sp ;is echo enabled? beq MakeAsciz@@ ;no, skip echo @putc ;echo character MakeAsciz@@ aix #1 ;point to next buffer position Cont@@ clr ,x ;make it ASCIZ string dec remain@@,sp ;one less char to receive bra Loop@@ ;-------------------------------------- ClearLine@@ lda len@@,sp ;delete all characters bra BS_Loop@@ Backspace@@ lda #1 ;delete just one character BS_Loop@@ psha lda remain@@,sp ;get remaining length inca ;if incremented, check ... cmpa len@@,sp ;are we at the beginning? bhs BS_Cont@@ ;yes, ignore backspace ;-------------------------------------- ;erase previous character lda #BS @putc lda #' ' @putc lda #BS @putc ;-------------------------------------- inc remain@@,sp ;un-count deleted character aix #-1 ;back up buffer position clr ,x ;make it ASCIZ string BS_Cont@@ pula dbnza BS_Loop@@ ;repeat requested number of times bra Loop@@ ;go get another character ;-------------------------------------- Done@@ tsx lda len@@,spx ;original string length sub remain@@,spx ;subtract remaining length deca ;do NOT count end-of-line ;-------------------------------------- ;A = number of characters read ais #:ais ;de-allocate temporaries pulhx rtc #sp ;******************************************************************************* #Exit ;******************************************************************************* @EndStats buffer @var 80 Start proc @rsp ldhx #buffer lda #::buffer sec call Readln bra * @vector Vreset,Start