changeset 18:6a046bd8107f

Add line input routine It seems useful to be able to accept lines from the user. So implement a read line routine that also handles echoing properly. None of this blindly writing the input back out to whatever device it came in on. This is not useful behaviour for read/write files.
author William Astle <lost@l-w.ca>
date Tue, 08 Nov 2022 21:24:55 -0700
parents f86967c0bc73
children 20fa3242c6a5
files src/lwbasic.s
diffstat 1 files changed, 69 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/lwbasic.s	Sun Nov 06 22:09:33 2022 -0700
+++ b/src/lwbasic.s	Tue Nov 08 21:24:55 2022 -0700
@@ -39,6 +39,7 @@
 keyb_alt        equ 0x04                        ; alt pressed
 keyb_ctrl       equ 0x02                        ; ctrl pressed
 keyb_shift      equ 0x01                        ; shift pressed
+linebuffsize    equ 0x100                       ; the line input buffer (256 bytes)
                 ifdef COCO3
 ; GIME INIT0
 GIME_COCO       equ 0x80                        ; Set for coco2 compatible mode (video display)
@@ -193,6 +194,7 @@
 ; Start of memory which has the direct page and other data.
                 org 0
 dpstart         equ *                           ; start of direct page
+readlinenoecho  rmb 1                           ; if nonzero, the readline routine won't echo its input
                 rmb 0x71-*                      ; align RSTFLG/RSTVEC for stock ROM compatibility
 RSTFLG          rmb 1                           ; 0x55 if RSTVEC is valid
 RSTVEC          rmb 2                           ; points to warm start routine (must start with NOP)
@@ -217,6 +219,7 @@
 keyb_buff       rmb keyb_bufflen                ; the keyboard ring buffer
                 rmb 0x200-*                     ; unused
 textscreen      rmb 0x200                       ; the actual text screen (must be on 512 byte alignment)
+linebuff        rmb linebuffsize                ; the line input buffer
                 org 0x8000                      ; the hardware puts the ROMs here; it's not negotiable
 START           orcc #0x50                      ; make sure interrupts are disabled if we come here in an unusual way
                 ifdef COCO3
@@ -795,6 +798,70 @@
 ;
 ; 0: keyboard/screen console
 ;
+; Read a line from the active file into linebuff. The resulting line will be NUL terminated leading to at most
+; linbuffsize-1 character input. The trailing CR/LF will not be included. The input will be echoed if linebuffecho is
+; enabled. Exit with the length of the input line in B.
+readline        ldx #linebuff                   ; point to line input buffer
+                clr ,x                          ; make sure buffer is NUL terminated
+readline0       bsr readchr                     ; read an input character
+                bcs readline1                   ; brif not EOF
+                cmpa #0x0d                      ; CR (carriage return)
+                beq readline1                   ; brif so - return
+                cmpa #0x03                      ; BREAK?
+                bne readline3                   ; brif not
+                coma                            ; set carry for irregular exit
+                skip1
+readline1       clra                            ; clear carry for regular exit
+                pshs cc                         ; save carry state
+                lda readlinenoecho              ; are we echoing?
+                bne readline2                   ; brif not
+                lda #0x0d                       ; echo carriage return + line feed
+                bsr writechr
+readline2       tfr x,d                         ; get end address after input
+                subd #linebuff                  ; subtract start of buffer; D is now length and C is clear
+                clr ,x                          ; make sure line is NUL terminated
+                puls cc,pc                      ; restore BREAK flag (C) and return
+readline3       cmpa #0x08                      ; backspace?
+                bne readline4                   ; brif not
+                cmpx #linebuff                  ; at start of buffer?
+                beq readline0                   ; brif so - do nothing
+                leax -1,x                       ; move back buffer pointer
+                bsr readlinee                   ; write a BS
+                lda #0x20                       ; write a space
+                bsr readlinee
+                lda #0x08                       ; and finally a BS
+                bsr readlinee
+                bra readline0                   ; go process more characters
+readline4       cmpa #0x0c                      ; form feed?
+                bne readline5                   ; brif not
+                bsr readlinee                   ; go echo character if needed
+                bra readline                    ; go restart line entry
+readline5       cmpa #0x20                      ; is it non-printing?
+                blo readline0                   ; brif so - don't store it and continue
+                bsr readlines                   ; stash character in buffer and echo if necessary
+                bra readline0                   ; go get another character
+readlines       cmpx #linebuff+linebuffsize-1   ; is the line buffer full?
+                bhi readlinee0                  ; brif so - don't store character OR echo it
+                sta ,x+                         ; stash character
+readlinee       ldb readlinenoecho              ; are we echoing?
+                bne readlinee0                  ; brif not
+                bsr writechr                    ; echo the character
+readlinee0      rts
+; Write a character to the active file; all registers preserved but C will be set if the output file cannot handle
+; an output character (doesn't exist, etc.)
+writechr        tst filenum                     ; is it screen?
+                beq writechr_scr                ; brif writing to screen
+                orcc #1                         ; unknown device flag
+                rts
+; Handle output to the screen. This is where we convert CR to CRLF
+writechr_scr    jsr console_outchr              ; output the character
+                cmpa #0x0d                      ; was it CR?
+                bne writechr_scr0               ; brif not
+                lda #0x0a                       ; ouptut an LF
+                jsr console_outchr
+                lda #0x0d                       ; restore original value
+writechr_scr0   andcc #0xfe                     ; clear error flag
+                rts
 ; Read a character from the active file and return it in A; in the event that EOF is detected, readeof will be nonzero
 ; and the call will return with carry set.
 readchr         clr fileeof                     ; flag not end of file (and clear carry)
@@ -819,9 +886,8 @@
 prompt          fcn 'OK'
 immediate       ldx #prompt                     ; point to prompt string
                 jsr console_outstrn
-                jsr readchr
-                bra *
-immediate0      
+immediate0      jsr readline                    ; read input line
+                bcs immediate0                  ; brif ended with BREAK
                 ; handle line
                 bra immediate
                 ifndef COCO3