*   
*   
*     OUTPUT FILTER #1
*      CHARACTER IS IN B
*   
OF1 LDA LEDFG
 ORA A
 JZ OF13  TRANSLATE THIS CHARACTER?
*   
 XRA A  CLEAR LEAD IN FLAG
 STA LEDFG
 MOV A,B
 CPI '&'  &&=&
 JZ OF2  JUST PRINT IT
*   
 MVI A,-64
 ADD B  TRANSLATE CHARACTER TO CTRL-CHARACTER
 MOV B,A
 JMP OF2  PRINT CHARACTER
*   
OF13 MOV A,B
 CPI '&'  LEAD IN CHARACTER?
 JNZ OF2  NO, PRINT CHARACTER
 STA LEDFG
 RET
*   
*   
*     OUTPUT FILTER #2
*      ALIAS "CHOUT"
*       CHARACTER IS IN B
*   
 IF SOLOS
XSYOUT EQU $
 ENDF
OF2 EQU $
 IF PTDOS
 MOV A,B  ACCA FOR PTDOS
 ENDF
 CALL SYSOT  SEND IT OUT
 MOV A,B
 SUI CR
 JZ OF21
 MOV A,B
 CPI ' '
 RC .  NO PHEAD INC FOR CTRL-CHARACTERS
 LDA PHEAD
 INR A
*   
OF21 STA PHEAD
 RET
*   
CHOUT EQU OF2
*   
*   
*     CARRIAGE RETURN
*     IF NEEDED
*   
CCRLF LDA PHEAD
 ORA A
 RZ 
*   
*     CARRIAGE RETURN
*     ALWAYS
*   
CRLF MVI B,CR
 CALL CHOUT
 MVI B,LF
 JMP CHOUT
*   
*     CHECK IF PANIC CHARACTER HAS BEEN HIT
*   
 IF SOLOS
XSYT2 EQU $
 ENDF
PCHECK CALL SYSTS
 RZ 
*   
*   
*     INPUT FILTER #3
*      MASKS OFF PARITY AND CHECKS FOR ESCAPE
*       CHARACTER RETURNED IN A
*   
PCHK1 EQU $
IF3 EQU $
 IF PTDOS
 CALL SYSIN
 ENDF
 ANI 7FH  DIRTY LITTLE BIT!
 CPI ESC
 RNZ
*   
*     CHECK TO SEE IF PANIC HAPPENED DURING RUN
*   
 PUSH B
 PUSH D
 PUSH H  INCASE OF STOP SO CCONT CAN CONTINUE
 LDA DIRF
 ORA A
 JZ STOP1  MUST HAVE BEEN RUN
 MVI B,'\'  MUST HAVE BEEN INPUT (OR LIST)
 CALL CHOUT
 CALL CRLF
 JMP CMND1  ABORT
*   
*   
*    SPEED CONTROL CHECKING
*   
 IF SOLOS
XSYT6 EQU $
SPDCK CALL SYSTS
 RZ .
 ANI 7FH
 CPI ' '
 JNZ SPD1  WAIT IF SPACE BAR
XSYT3 EQU $
SPD0 CALL SYSTS
 JZ SPD0
SPD1 CPI '1'
 JC PCHK1
 CPI '9'+1
 JNC PCHK1
*   
*  1-9 IS SPEED CONTROL
*   
 SUI '0'
 MOV B,A
 XRA A
SPED STC .
 RAL .
 DCR B
 JNZ SPED
 RAR .
 JMP SETDS  SET DISPLAY SPEED
 ENDF
*   
*   
*     INPUT FILTER #1
*      CHARACTER IS IN A AND B
*   
IF1 LDA CTLFG  GET CTRL-CHARACTER FLAG
 ORA A
 JZ IF12  NO CTRL-CHARACTER EXPANSION
 MOV B,A
 XRA A
 MOV C,A  ZERRO DISPATCH FLAG
 STA CTLFG  CLEAR CTRL-CHARACTER EXPANTION FLAG
 MOV A,B
 RET .  NOTE: CARRY IS CLEAR
*   
IF12 CALL IF2  GET CHARACTER
*   
 MVI C,SCHRZ  SPECIAL CHARACTER TABLE SIZE (IN ENTRIES)
 LXI H,SCHRT  ADDR OF SPECIAL CHARACTER TABLE
SCTS CMP M  A=M?
 INX H  POINT TO ADDR OF ROUTINE
 STC .  INCASE OF MATCH
 RZ .  A=M, CARRY<>0 MEANS DISPATCH
 INX H
 INX H
 DCR C
 JNZ SCTS  SPECIAL CHARACTRER TABLE SEARCH
*   
 CPI ' '  CTRL-CHARACTER?
 RNC .  NO, RETURN CARRY IS 0
*   
 ADI 64  CONVERT TO NON-CTRL-CHARACTER
 STA CTLFG  SAVE FOR EXPANTION
 MVI A,'&'
 MOV B,A
 RET .  NOTE:  CARRY IS 0
*   
*   
*     INPUT FILTER #2
*      CHARACTER IN A AND B
*   
IF2 PUSH H
IF20 LXI H,ITIMCONST
 IF SOLOS
XSYT4 EQU $
 ENDF
IF21 CALL SYSTS
 JNZ IF22  THERE IS A CHARACTER
*   
 LDA DIRF
 ORA A
 JNZ IF21  NO TIMING IN DIRECT MODE
*   
 DCX H  TICK...TOCK
 MOV A,H
 ORA L
 JNZ IF21
 LHLD ITIM  GET INPUT TIME LIMIT
 MOV A,H
 ORA L
 JZ IF20  NOT ACTIVE
 DCX H
 SHLD ITIM  UPDATE TIME LIMIT
 MOV A,H
 ORA L
 JZ IF23  TIME'S UP SINKER...SINKER
 JMP IF20  NOT YET
*   
IF22 CALL IF3  MASK AND TEST FOR ESCAPES
 MOV B,A
 POP H
 RET
*   
IF23 MVI A,CR  THIS IS WHAT YOU GET FOR TAKING SO LONG
 MOV B,A
 POP H
 RET
*   
*   
*     INPUT A LINE FROM THE TERMINAL
*   
PCR EQU $
 IF SOLOS
 XCHG .  TERMINATE AT END OF LINE (DE)
 ENDF
 IF PTDOS
PCR0 CALL HDCMP  OUTPUT TEXT TI'LL HL = DE
 JZ PLF
 MOV B,M
 PUSH H
 PUSH D
 CALL OF2
 POP D
 POP H
 INX H
 JMP PCR0
 ENDF
PLF MVI M,CR  TERMINATE AT PRESENT POSITION (HL)
 INR C  THERE IS ALWAYS ROOM FOR A CR!  (THIS WON'T BE CORRECT!)
*   
 MOV B,A
 LDA TOPT  GET OLD PHEAD
 ADD C
 STA PHEAD
*   
 LDA DIRF
 ORA A
 MOV A,B
 RNZ .  NO TIME/COUNT CLEAR IF IN DIRECT MODE
 LXI H,0
 SHLD ITIM  THIS ZEROS ITIM
 SHLD ITIM+1  THIS ZEROS ICNT
 RET .  RETURN C HAS LINE LENGTH
*   
INL0 CALL CRLF  ENTRY THAT RE-GETS A LINE
*   
*  THIS IS THE ENTRY TO GET A LINE
*   
INLINE EQU $
 LDA PHEAD
 STA TOPT  SAVE PHEAD
 IF SOLOS
 CALL READR  GET VDM ADDRESS TO 'VDMAD'
 ENDF
INL9 LXI H,IBUF1  READ CHARACTRERS INTO IBUF
 MOV D,H  HL=PRESENT POSITION, DE=LAST CHARACTER POSITION
 MOV E,L  INITIALY SAME AT FIRST
 XRA A
 MOV C,A  C COUNTS THE NUMBER OF CHARACTERS IN THE LINE
*   
INL1 LDA DIRF
 ORA A
 JNZ INL1B  NO COUNT LIMIT IN DIRECT MODE
*   
 LDA ICNT  GET INPUT COUNT LIMIT
 ORA A  SET?
 JZ INL1B  NO, CONTINUE
 CMP C  EQUAL?
 JZ PCR  COUNT'S UP....SNIKER...SINKER
*   
INL1B PUSH H  GET NEXT CHARACTER
 PUSH B
 PUSH D
 CALL IF1  GET CHARACTER
 POP D
 POP B
 MOV B,A
 JC INLSD  SPECIAL DISPATCH
 POP H
*   
 LDA INSFG  TEST INSERT FLAG
 ORA A
 JNZ INSRT  INSERT ON
*   
 CALL HDCMP  CMP HL-DE
 JNZ INL2  DIDN'T PASS DE (POINTER NEXT EMPTY CELL)
 MOV A,C
 CPI LINMAX-2
 JNC INL1  GREATER THAN OR EQU TO, DONT KEEP IT
 INX D
 INR C
*   
INL2 MOV M,B  PUT IN BUFFER
 CALL OF2  PRINT IT
 INX H
 JMP INL1  NEXT CHARACTER
*   
*   
*     DISPATCH TO A SPECIAL CHARACTER HANDLER
*   
INLSD CALL LHLI  GET ROUTINE ADDRESS TO HL
 XTHL .  SAVED HL TO HL, ROUTINE ADDRESS TO STACK
 RET .  GOTO ROUTINE  (NOT A CALL)
*   
*     PROCESS BACK SPACEING
*   
PBS CALL HDCMP  AT END OF LINE?
 JNZ PBS0  JMP IF IN MIDDLE
 XRA A  A=0
 CMP C  IS C = 0 ?
 JZ INL9  YES, LINE IS EMPTY
 DCX H
 DCX D  BACK UP BOTH POINTERS
 DCR C
PBS9 MVI B,05FH  THIS GOES BACK ON THE SOLOS VDM DRIVER
 CALL OF2  PRINT IT
 JMP INL1  CONTINUE
*   
PBS0 DCR C  ONE LESS CHARACTER
 JZ INL9  LINE NOW EMPTY
 IF PTDOS
 DCX H  BACKUP ONE CHARACTER
 ENDF
 PUSH H
*   
PBS1 INX H  SHIFT IT ALL DOWN
 MOV A,M
 DCX H
 MOV M,A
 INX H
 CALL HDCMP
 JNZ PBS1
 DCX D  EOL ADDR
 POP H  CHR POINTER
 IF PTDOS
 JMP PBS9  DO BACKSPACE ON VDM
 ENDF
 IF SOLOS
 JMP INL1  NEXT CHARACTER
 ENDF
 IF SOLOS
*   
*     PROCESS LEFT CURSOR MOVEMENT
*   
PLFT PUSH D
 LXI D,IBUF1
 CALL HDCMP  ALL THE WAY LEFT ALREADY?
 POP D
 JZ INL1  YES, IGNORE
 DCX H
 ENDF
*   
PCKEY MVI A,80H  TURN ON HIGH BIT FOR SOLOS
 ORA B
 MOV B,A
*   
PECHO CALL OF2  PRINT CHARACTER
 JMP INL1  CONTINUE
*   
*     PROCESS RIGHT MOVEMENT
*   
PRIT CALL HDCMP
 JNC INL1  ALREADY ALL THE WAY OVER!
 IF PTDOS
 MOV B,M  GET CHARACTER FROM BUFFER
 ENDF
 INX H  MOVE
 IF SOLOS
 JMP PCKEY
 ENDF
 IF PTDOS
 JMP PECHO
 ENDF
*   
*     PROCESS INSERT MODE ON/OFF
*   
PIOFF XRA A  INSERT MODE OFF
PION STA INSFG  SET INSERT FLAG
 JMP INL1  CONTINUE
*   
*     INSERT MODE
*   
INSRT MOV A,C
 CPI LINMAX-2  DOES IT FIT?
 JNC INL1  NO, IGNORE COMMAND
 INR C
 INX H
 INX D
 PUSH B  SAVE CHARACTER (IN B)
 IF SOLOS
 MVI B,KRIGHT  MOVE CURSOR RIGHT ONE
 ENDF
 CALL OF2  IF PTDOS, ECHO CHR; ELSE MOVE CURSOR
 POP B
 PUSH H
 DCX H
*   
INST1 MOV A,M  SHIFT CHARACTERS UP
 MOV M,B
 MOV B,A
 CALL HDCMP  DONE?
 INX H
 JC INST1  NO, KEEP LOOPING
*   
INST2 EQU $
 IF SOLOS
 LHLD XOPORT
 MOV A,M  TEST FOR NON-VDM OUTPUT PORT
 ORA A
 JNZ INST4  NOT ON VDM, DON'T CHANGE SCREEN
*   
 PUSH D  SAVE POINTER TO END OF BUFFER
 PUSH B  SAVE CHARACTER COUNT AND INPUT CHARACTER
 LXI D,IBUF1  BUFFER POINTER
 LHLD VDMAD  SCREEN POINTER
 MOV A,C  CHARACTER COUNT TO MOVE
 CPI 63+1
 JC INST3
 MVI C,63  MOVE A MAX OF 63 CHARACTERS
*   
INST3 XCHG
 MOV B,M  CHARACTER FROM IBUF1
 XCHG
 MOV A,M  CHARACTER FROM SCREEN
 ANI 80H  EXTRACT "CURSOR" BIT
 ORA B  ADD "CURSOR" BIT TO B
 MOV M,A  CHARACTER TO VDM SCREN
 INX H
 INX D
 DCR C  DONE?
 JNZ INST3
*   
 MOV A,M  FORCE LAST CHARACTER TO BLANK
 ANI 80H  PRESERVE "CURSOR" BIT
 ORI 20H  MAKE LAST CHARACTER BLANK
 MOV M,A
*   
 POP B
 POP D
INST4 EQU $
 ENDF
 POP H
 JMP INL1  DONE INSERTING/DELETING, CONTINUE
 IF SOLOS
*   
*   
*     READ VDM SCREEN ADDRESS
*   
READR XRA A
 STA INSFG  INIT INSFG TO OFF
 MVI B,KESC
 CALL ZOUT
 MVI B,4  THE PROPER CODE TO GET ADDRESS
 CALL ZOUT
 MOV H,B
 MOV L,C
 SHLD VDMAD  SAVE ADDRESS
 RET
*   
*  OUTPUT TO PORT ZERO (VDM)
*   
ZOUT XRA A
XAOUT EQU $
 JMP AOUT  OUTPUT AND RETURN
*   
 ENDF
*   
*   
*   
*   
*   
*     SPECIAL CHARACTER TABLE
*   
SCHRT DB CR
 DW PCR
 DB BS
 DW PBS
 DB KRIGHT
 DW PRIT
 DB KCAN
 DW INL0
 IF SOLOS
 DB KLEFT
 DW PLFT
 ENDF
 DB KION
 DW PION
 DB KIOFF
 DW PIOFF
 DB KLF
 DW PLF
SCHRZ EQU $-SCHRT/3  TABLE LENTH IN ENTRIES
*   
*   
*   
*     I/O RELATED RAM
*   
 IF SOLOS
VDMAD DS 2  VDM ADDRESS
XOPORT DS 2
XIPORT DS 2
 ENDF
ITIM DS 2  INPUT TIME LIMIT
ICNT DS 1  INPUT COUNT LIMIT
LINLEN DS 1  LENGTH OF A LINE
TWIDTH DB 14  WIDTH OF A COMMA TAB FIELD
PHEAD DS 1  PRINTER HEAD POSITION
*   
 DS 1  FOR THE '!'
OBUF DS WMAX+1  FOR NUMERIC CONVERTIONS
EOBUF DS 1  FOR THE '"'
*   
IBCNT DS 1  CURRENT LINE LENGTH (OF INCOMMING LINE)
IBLN DS 2  CURRENT LINE NUMBER (OF INCOMMING LINE)
IBUF DS LINMAX/2  THE I/O BUFFER
IBUF1 DS LINMAX
*   
*   
*    STACK DEFINITION
*   
STKTOP DS SSIZE  THE STACK
CMNDSP EQU STKTOP+SSIZE-1  ADDR OF TOP OF STACK
CSPM1 EQU CMNDSP-1
SPCMND EQU CMNDSP/256*256
TSTKA DS 2  TOP OF ARG STACK POINTER
SPTR DS 2  STACK SAVE FOR 'CONTINUE'
*   
*   

