;REMSCRN.ASM
;
;WRITTEN 2/28/86 BY JOHN GOTSCHALL
;
;
;
;
;    GENERIC SCREEN CONTROL STRING FILTER
;    REPLACES OUTBOUND SCREEN COMMAND STRINGS WITH
;    STRINGS THAT PERFORM IDENTICLE FUNCTIONS ON A
;    REMOTE CONSOLE,  THIS PROGRAM WAS DEVELOPED FOR
;    USE IN AN APPLICATION WHERE A BUSINESS HAD A CP/M
;    MACHINE RUNNING DBASE II, THEY DID NOT WANT TO
;    GET A MULTI-USER MACHINE, BUT THEY DID WANT
;    SIMULTANEOUS I/O TO A REMOTE HAZELTINE 1500, SO
;    THAT WHEN ONE TERMINAL WAS NOT IN USE THE OTHER COULD
;    BE USED, VERY SIMILAR IN FUNCTION TO A BYE PROGRAM,
;    WITH THE EXCEPTION THAT THERE WAS NO MODEM INVOLVED.
;    THE REMOTE IN THIS CASE HAD A DIFFERENT SET OF SCREEN COMMAND
;    SEQUENCES THAN THE LOCAL, NECESSITATING CONVERSION
;    OF THE LOCAL'S NATIVE COMMAND STRINGS INTO THE REMOTES
;    NATIVE TONGUE.  THIS MODULE PERFORMS THAT FUNCTION,
;    RATHER NICELY.
;
;    I WROTE THIS LITTLE THING, AND AS IT IS MY VERY FIRST
;    100% SUCCESSFUL ASSEMBLY PROGRAM WITH PRACTICAL APPLICATION,
;    I HAVE MADE IT AVAILABLE TO THE GENERAL PUBLIC AND THUS
;    MAY BE USED BY ANY PERSON FOR NON-PROFIT USE.  IF YOU
;    DO USE IT FOR PROFIT, YOU OWE ME ONE U.S. DOLLAR FOR
;    EVERY PERSON THAT USES IT. (PRETTY CHEAP HUH?, THAT'S NOT
;    ASKING A HECK OF A LOT.)
;
;    IF YOU OWE ME A BUCK SEND IT TO:
;
;     JOHN GOTSCHALL
;     PO BOX 2475
;     SEATTLE  WA  98111
;
;     ANYWAY, IMPLEMENTATION OF THIS CODE SHOULD BE PRETTY
;     OBVIOUS, JUST PATCH THE FIRST TABLE WITH THE VALUES
;     FOR YOUR LOCAL TERMINAL, THEN PLACE THE APPROPRIATE
;     REPLACEMENT VALUES INTO THE SECOND TABLE, WHEN OUTPUTTING
;     TO THE REMOTE, IF THE STRING THAT APPEARS IN THE FIRST
;     FOUR BYTES OF THE FIRST TABLE GETS SENT TO THE LOCAL,
;     THE CONTENTS OF THE FIRST FOUR BYTES OF THE SECOND
;     TABLE WILL BE SENT TO THE REMOTE IN PLACE OF WHAT WAS SENT
;     TO THE LOCAL.  IF YOU ARE USING A BYE PROGRAM, ALL YOU
;     NEED TO DO IS ADD THIS CODE TO YOUR BYE PROGRAM SOURCE
;     CODE (MAKING SURE TO FIX ANY DUPLICATED LABELS), THEN HAVE
;     YOUR BBS PROGRAM POKE THE VALUES FOR THE REMOTE'S
;     COMMAND STRINGS INTO THE SECOND TABLE, THEN YOUR BYE
;     MERGED WITH THIS PROGRAM WILL TAKE CARE OF MAKING
;     SURE THE REMOTE GETS SCREEN CONTROL SEQUENCES THAT IT CAN
;     UNDERSTAND, YET YOUR BBS PROGRAM NEED NOT DO ANYMORE
;     THAN PRETEND THAT YOUR LOCAL AND THE REMOTE HAVE THE
;     SAME SCREEN COMMAND SET.  WORKS PERFECT WITH THE
;     BUILT IN COMMANDS LIKE IN DBASE II AND TURBO PASCAL,
;     IT EVEN WORKED PERFECT WITH WORDSTAR IN MY APPLICATION.
;     WELL, IF YOU HAVE READ ALL OF THIS, I CERTAINLY HOPE YOU
;     CAN MAKE USE OF THIS PROGRAM, AS YOU ALREADY HAVE SOME
;     TIME INTO IT.
;
;     BE FORWARNED, WHILE THIS CODE NEVER USES A STACK,
;     IT WILL, WITHOUT A DOUBT DESTROY THE CONTENTS OF
;     THE CPU REGISTERS, SO SAVE ANYTHING YOU WANT TO KEEP
;     BEFORE CALLING THIS SUBROUTINE!!!!!
;
;     DELIVER OUTBOUND CHARACTERS TO THIS ROUTINE IN BOTH
;     THE A AND C REGISTERS !!
;
;
;=======================================================
;The following section of code filters the output to the remote,
;checking for the presence of screen command sequences, and when
;encountered, replaces the strings that are native to the local
;with strings that are native to the remote.  This is done
;through the use of two look-up tables.  The first of the two
;tables contains all of the sequences that are expected to be
;sent out, and are in code that is native to the local screen.
;the second table is where we patch in the corresponding strings,
;but there they are the strings that the remote will recognize
;as they are native to the remote.
;=======================================================
;
;******************************************************
;There are many calls to a routine labeled 'REMOUT',
;you will not find remout in this listing, whenever this
;code calls remout, it thinks that it is delivering a
;single character to the remote...  all waiting for status
;for the remote must take place in remout, your version
;of bye should already have a routine to output characters
;to the remote.....  THAT routine is the one that this code
;refers to when it calls remout.  The character to be sent to the
;renote from this code will be found in the C register whenever remout
;is called.
;********************************************************
;
;
;THE FOLLOWING TWO TABLES ARE 60 BYTES LONG, THEY ARE
;ORGANIZED SO THERE ARE 15 STRINGS OF 4 BYTES.  THE FIRST
;TABLE IS SCANNED PRIOR TO ANY OUTPUT TO THE REMOTE, IF
;THE CURRENT OUTBOUND CHARACTER MATCHES ANY OF THE CHARACTERS
;IN THE FIRST POSITIONS OF THE FIRST TABLE, THE CHARACTER IS
;BUFFERED, WHEN THE NEXT CHARACTER COMES THROUGH, A TEST IS
;MADE TO FIND ANY WHOLE MATCHING STRINGS, IF THERE IS A
;POSSIBILITY OF A MATCH ON THE THIRD CHARACTER, THE SECOND
;CHARACTER IS BUFFERED, AND THE ROUTINE WAITS UNTIL THE
;THIRD CHARACTER COMES THROUGH, IT THEN TESTS TO SEE IF
;THERE IS A POSSIBILITY OF A COMPLETE MATCH.  ON CHARACTERS
;2, AND 3, CHECKS ARE MADE FOR BOTH PENDING MATCHES, AND
;COMPLETE MATCHES, ANY COMPLETE MATCHES WIN AND ARE IMMEDIATLY
;CONVERTED TO THE REMOTE'S COMMAND SET, AND ARE IMMEDIATLY SENT OUT
;TO THE REMOTE.
;
;IF THERE IS A MATCH IN ANY OF THE STRINGS IN THE FIRST TABLE
;THE STRING IS REPLACED WITH THE CONTENTS OF THE SAME POSITIONS
;IN THE SECOND TABLE...  ANY STRINGS MAY BE PUT IN ANY LOCATIONS,
;WITH THE EXCEPTION THAT THE LAST STRING OF 4 IN EACH TABLE IS
;RESERVED FOR THE CURSOR POSITIONING LEAD IN STRINGS, THE
;FOLLOWING THREE BYTES ARE FOR THE X AND Y COORDINATES AND
;THERE IS A FLAG THAT DENOTES WHICH COORDINATE COMES FIRST.
;
;THE MAXIMUM LENGTH FOR ANY COMMAND STRING IS FOUR BYTES!
;
INSTNG  EQU     $+OFFSET
       DB      01BH,045H,01BH,048H     ;CLEAR AND HOME CURSOR
       DB      01BH,05AH,0,0           ;CLEAR TO EOL
       DB      01BH,04AH,0,0           ;CLEAR TO EOS
       DB      27,69,0,0               ;ANOTHER STRING THAT IS CL & HME
       DB      01BH,048H,01BH,045H     ;YET ANOTHER CL & HOME STRING
       DB      01BH,'K',0,0            ;IF LESS THAN 4 BYTES LONG,
       DB      0,0,0,0                 ;LEAVE 0'S TO FILL THE EXTRAS,
       DB      0,0,0,0                 ;THE ZEROS WON'T BE SENT OUT
       DB      0,0,0,0
       DB      0,0,0,0
       DB      0,0,0,0
       DB      0,0,0,0
       DB      0,0,0,0
       DB      0,0,0,0
       DB      27,70,0,0       ;**LEAD-IN** CHARACTERS FOR THE
                               ;LOCAL CONSOLE'S CURSOR POSITIONING
                               ;STRING, IF LESS THAN 4 BYTES LONG,
                               ;LEAVE A '0' TO FILL THE EXTRAS
;
ICCC    EQU     $+OFFSET
       DB      2       ;WHICH COORDINATE CARRIES THE COLUMN DATA?
                       ;THE FIRST OR THE SECOND
;
ICCO    EQU     $+OFFSET
       DB      32      ;VALUE OF COLUMN OFFSET FOR LOCAL
;
ICRO    EQU     $+OFFSET
       DB      32      ;VALUE OF ROW OFFSET FOR LOCAL
;
;
OUTSTNG EQU     $+OFFSET
       DB      07EH,01CH,0A0H,0        ;REPLACEMENT COMMAND STRINGS
       DB      07EH,0FH,0,0            ;THAT ARE TO BE INSERTED IN THE
       DB      07EH,018H,0,0           ;DATA FLOW TO THE REMOTE IN
       DB      07EH,01CH,0A0H,0        ;IN PLACE OF THE COMMAND STRINGS
       DB      07EH,01CH,0A0H,0        ;FOUND IN THE ABOVE TABLE.  THE
       DB      07EH,0FH,0,0            ;STRINGS IN THE TABLE ABOVE MUST
       DB      0,0,0,0                 ;MATCH THE STRINGS THAT WILL BE
       DB      0,0,0,0                 ;SENT TO THE LOCAL CONSOLE, WHILE
       DB      0,0,0,0                 ;THESE MUST CARRY THE STRINGS FOR
       DB      0,0,0,0                 ;THE SAME FUNCTIONS, BUT IN THE
       DB      0,0,0,0                 ;REMOTE'S NATIVE TONGUE.
       DB      0,0,0,0                 ;IF LESS THAN 4 BYTES LONG,
       DB      0,0,0,0                 ;LEAVE 0'S TO FILL THE EXTRAS,
       DB      0,0,0,0                 ;THE ZEROS WON'T BE SENT OUT
       DB      07EH,011H,0,0   ;**LEAD-IN** CHARACTERS FOR THE
                               ;REMOTE CONSOLE'S CURSOR POSITIONING
                               ;STRING, IF LESS THAN 4 BYTES LONG,
                               ;LEAVE 0'S TO FILL THE EXTRAS,
;                               ;THE ZEROS WON'T BE SENT OUT
;
OCCC    EQU     $+OFFSET
       DB      1       ;POSITION IN CURSOR POSITIONING
                       ;STRING THAT CARRIES THE COLUMN
                       ;FOR REMOTE
;
OCCO    EQU     $+OFFSET
       DB      0       ;VALUE OF COLUMN OFFSET FOR REMOTE
;
OCRO    EQU     $+OFFSET
       DB      0       ;VALUE OF ROW OFFSET FOR REMOTE
;
;
;MOVE (HL) TO (DE) LENGTH IN (B)
;
;THE FOLLOWING IS COMMENTED OUT, THIS ROUTINE IS DUPLICATED EXACTLY
;IN MY VERSION OF BYE.COM, SO I DON'T NEED THIS AGAIN, BUT IF YOUR
;VERSION OF BYE.COM DOES NOT HAVE THIS ROUTINE IN IT, USE THIS ONE
;OR IF YOU MAKE AN OVERLAY OF THIS FILE YOU WILL NEED IT
;
;
;MOVE   EQU     $+OFFSET
;       MOV     A,M     ;GET A BYTE
;       STAX    D       ;PUT IT IN NEW HOME
;       INX     D       ;BUMP POINTERS
;       INX     H
;       DCR     B       ;DEC BYTE COUNT
;       JNZ     MOVE    ;IF MORE, DO IT
;       RET             ;IF NOT, RETURN
;
;**************************************************
;**************************************************
;*  MAIN PROGRAM SECTION, THIS IS THE PART THAT   *
;*  DOES ALL THE FILTERING OF CURSOR COMMAND      *
;*  SEQUENCES.......                              *
;**************************************************
;
;
;the call to vconout below calls the routine that is already
;in my version of bye.  I replaced the call for vconout in
;my version of bye with a call for 'OUTPUT' below, so that the
;program comes here just prior to outputing to the local.
;
OUTPUT  EQU     $+OFFSET
       CALL    STRT            ;STORE CHAR IN FIRST EMPTY BUFFER LOC
       CALL    VCONOUT         ;SEND IT TO THE LOCAL
;
MT1     EQU     $+OFFSET
       LDA     CLCF            ;POINT TO CURSOR LOCATION COMMAND FLG
       CPI     1               ;ARE WE AWAITING A CURSOR COMMAND?
       JZ      CPF             ;YES, GOTO CURSOR POS.FILTER
MT2     EQU     $+OFFSET
       LDA     MTSTR           ;POINT TO MATCHSTRING
       CPI     01H             ;IS IT A 1?
       JZ      MMF             ;THERE WAS A PRIVIOUS MATCH, AND NOT A CURSOR
                               ;COMMAND, SO
                               ;LETS TAKE THIS CHAR TO THE MAIN
                               ;MATCH FINDER
MT3     EQU     $+OFFSET
       JMP     QCHK            ;NOTHING MATCHED LAST TIME
                               ;WE OUTPUTTED, AND WER'E NOT LOOKIN
                               ;FOR A CURSOR COORDINATE, SO LET'S JUST
                               ;QUICKLY SCAN FOR A FIRST
                               ;CHAR MATCH
;
QCHK    EQU     $+OFFSET
       LXI     H,BUFLOC        ;GET THE ADDRESS OF THE BUFFER
       SHLD    BUFPTR          ;PUT IT IN THE BUFFERPOINTER
       LXI     H,INSTNG        ;GET THE ADDRESS OF INSTING
       SHLD    INSPTR          ;PUT IT IN THE POINTER
       MOV     B,C             ;SAVE THE CHAR IN B
       MVI     A,0
       STA     COUNT
       STA     COUNT1
       LXI     H,INSTNG        ;POINT TO THE BEGINNING OF THE INSTING
QCHCK1  EQU     $+OFFSET
       MOV     A,M             ;GET THE CONTENTS
       CMP     C               ;IS IT THE SAME AS OUR CHAR?
       JZ      ST1MT           ;IT'S A MATCH
QCHK2   EQU     $+OFFSET
       INX     H       ;BUMP
       INX     H       ;UP TO THE
       INX     H       ;BEGINNING OF THE NEXT
       INX     H       ;STRING OF FOUR BYTES
       LDA     COUNT
       INR     A
       STA     COUNT   ;KEEP TRACK OF WHICH GROUP OF FOUR WERE' ON
       CPI     0FH     ;PAST 15 YET?, IF SO, THEN THERE IS NO POSSIBLE
       JZ      DONE    ;MATCH SO GO DUMP THE CHARACTER FROM THE BUFFER
       JMP     QCHCK1
ST1MT   EQU     $+OFFSET
       LXI     H,MTSTR ;THERE IS A MATCH IN ONE OF THE FIRST
       MVI     A,1     ;POSITIONS OF THE INSTRING LINES
       MOV     M,A     ;LEAVE NOTE OF THIS IN THE MTSTR GROUP.
       RET             ;TO CP/M, WE'LL SEND OUT THIS CHAR LATER..
;
;
;###########################
;
; MMF (MAIN MATCH FINDER,
;  ROUTINE CHECKS ENTIRE INSTRING, COMPARES TO THE CONTENTS OF THE
;  BUFFER TO THE INSTNG TABLE, MAKES NOTATION TO SHOW POSSIBLE
;  PENDING MATCHES, OR PARTIAL BUT IMPOSSIBLE MATCHES, AND MAKES
;  THE FINAL DECISION ON WHETHER OR NOT THERE IS A MATCH OF
;  AN ENTIRE STRING.
;
;
;
MMF     EQU     $+OFFSET
       LXI     H,INSTNG        ;GET ADDRESS OF INSTNG INTO (D,E)
       SHLD    INSPTR          ;RESET POINTER
       LXI     H,BUFLOC        ;POINT TO FIRST BUFFER POSITION
       SHLD    BUFPTR          ;RESET BUFPTR
       MVI     A,0             ;GET A 0
       STA     POSMTCH         ;RESET POSSIBLE MATCH FLAG
       STA     COUNT           ;RESET COUNT FLAG
       STA     COUNT1
ENT     EQU     $+OFFSET
       LDA     COUNT1          ;REACHED END OF INSTNG?
       CPI     15
       JZ      ANT1            ;YEP...GO AND CHECK FOR A PENDING MATCH...
                               ;IT MAY BE THAT WE NEED TO WAIT FOR MORE
                               ;CHARACTERS TO COME THROUGH...
       LHLD    BUFPTR          ;POINT TO THE CURRENT BUFFER ADDRESS
;
;COME INTO ENT1 WITH THE CURRENT BUFFER ADDR IN HL
;
ENT1    EQU     $+OFFSET
       MOV     A,M             ;GET VALUE OF CHAR AT BUFFER
       LHLD    INSPTR          ;POINT TO TABLE
       CMP     M               ;DOES BUFFER CHAR MATCH TABLE CHAR?
       JNZ     ENT7            ;NOPE...
ENT2    EQU     $+OFFSET
       LDA     COUNT           ;IF WE ARE AT THE FIRST OF 4,
       CPI     0               ;COUNT WILL BE 0
       JNZ     ENT6            ;NOPE...
ENT3    EQU     $+OFFSET
       MVI     A,1             ;SINCE THERE IS A MATCH IN THE
       STA     POSMTCH         ;FIRST OF 4 IN THE TABLE, MAKE
                               ;A NOTE OF IT
ENT4    EQU     $+OFFSET
       LXI     H,MTSTR         ;POINT TO MATCHSTRING
       LDA     COUNT           ;ALSO MAKE NOTE IN THE MATCHSTRING
       MOV     B,A             ;ADD COUNT TO MATCHSTR LOCATION
ENT4A   EQU     $+OFFSET
       MOV     A,B             ;MAKE SURE WE STILL HAVE IT
       CPI     0               ;MATCHING LOCATIONS YET?
       JZ      ENT4B           ;YEP
       INX     H               ;BUMP POINTER
       DCR     B               ;COUNTDOWN
       JMP     ENT4A
ENT4B   EQU     $+OFFSET
       MVI     A,1             ;GET A ONE
       MOV     M,A             ;PUT THE FLAG INTO THE MATCHSTRING
ENT5    EQU     $+OFFSET
       LDA     COUNT           ;CECK TO SEE IF THIS IS THE
       CPI     3               ;4TH CHAR IN THE STRING
       JNZ     ENT8            ;NOPE, GO DO SOME MORE....
       JMP     WHM             ;WE HAVE A FULL MATCH FOR A WHOLE
                               ;STRING OF FOUR !!!!!!!
ENT6    EQU     $+OFFSET
       LDA     POSMTCH         ;IS THERE A POSSIBLE MATCH?
       CPI     1               ;
       JZ      ENT4
       JMP     ENT8
ENT7    EQU     $+OFFSET
       LXI     H,POSMTCH       ;POINT TO POSMTCH
       MVI     A,0             ;GET A 0
       MOV     M,A             ;RESET POSMTCH
ENT8    EQU     $+OFFSET
       LHLD    BUFPTR          ;GET THE ADDRESS IN THE BUFFER POINTER
       INX     H               ;INCREMENT IT
       SHLD    BUFPTR          ;PUT IT BACK
       LHLD    INSPTR          ;GET THE ADDRESS IN THE INSTRING POINTER
       INX     H               ;INCREMENT IT
       SHLD    INSPTR          ;PUT IT BACK
       LDA     COUNT           ;GET THE COUNT
       INR     A               ;INCREMENT IT
       STA     COUNT           ;PUT IT BACK
ENT9    EQU     $+OFFSET
       LDA     COUNT           ;MAKE SURE WE HAVE THE COUNT
       CPI     4               ;PAST THE 4TH CHAR YET?
       JNZ     ENT             ;NOPE , GO DO MORE
ENT10   EQU     $+OFFSET
       MVI     A,0             ;WE'RE AT HE 4TH, SO
       STA     COUNT           ;RESET COUNT
       LDA     COUNT1          ;WERE LOOKING AT THE NEXT
       INR     A               ;STRING IN THE TABLE, SO
       STA     COUNT1          ;MAKE NOTE OF THAT
       LXI     H,BUFLOC        ;ALSO, ON THE NEXT PASS,
       SHLD    BUFPTR          ;WE WANT TO POINT TO
                               ;THE FIRST CHAR IN THE BUFFER
       JMP     ENT
;################################################
;
;END OF MATCH FINDER, IF THERE WAS NO EXACT MATCH,
;WE MAY JUST NOT HAVE ALL THE CHARACTERS YET, SO NOW WE CHECK TO
;SEE IF ANY PARTIAL MATCH IS A POSSIBLE MATCH
;
ANT1    EQU     $+OFFSET
       LXI     H,MTSTR         ;POINT TO THE FIRST POS OF MTSTR
       MOV     A,M             ;GET THE CONTENTS
       CPI     1               ;IS IT A ONE?
       JNZ     DONE            ;NOPE, GO EMPTY BUFFER TO REMOTE,
                               ;THERE IS NO CHANCE OF A MATCH..
ANT2    EQU     $+OFFSET
       INX     H               ;POINT TO NEXT LOCATION IN MTSTR
       MOV     A,M             ;IS IT A ONE?
       CPI     1               ;NOPE,
       JNZ     BZ              ;GO CHECK BUFFER STRING
ANT3    EQU     $+OFFSET
       INX     H               ;POINT TO NEXT LOCATION
       MOV     A,M             ;GET CONTENTS
       CPI     1
       JNZ     BZ1             ;GO CHECK BUFFER STRING
       JMP     BZ2
BZ      EQU     $+OFFSET
       LXI     H,BUFLOC                ;POINT TO BUFFER
       INX     H               ;POINT TO 2ND CHAR
       MOV     A,M             ;GET THE CHAR
       CPI     0               ;IS THE POSITION IN THE BUFFER EMPTY?
       RZ                      ;YES, THEN RETURN TO CP/M, LEAVE ALL AS IT
                               ;IS, THERE MAY BE MORE CHARACTERS NEEDE TO
                               ;MAKE A MATCHING STRING
       JMP     DONE            ;THERE IS NO POSSIBILITY OF A MATCH,
                               ;SO GO DUMP THE BUFFER
BZ1     EQU     $+OFFSET
       LXI     H,BUFLOC                ;POINT TO THE
       INX     H               ;3RD CHAR IN BUFFER
       INX     H               ;THERE WE ARE.....
       MOV     A,M             ;GET THE CHAR, IS IT EMPTY?
       CPI     0
       RZ                      ;YEP, SAME AS IN BZ....
       JMP     DONE
BZ2     EQU     $+OFFSET
       LXI     H,BUFLOC        ;SAME AS BZ & BZ1,
       INX     H
       INX     H
       INX     H               ;BUT CHECK THE LAST CHAR IN BUFFER
       MOV     A,M             ;GET THE CHAR..
       CPI     0               ;IS THE POSITION EMPTY?
       RZ                      ;STILL EMPTY,GO TO CP/M AND TO IT AGIN,
       JMP     DONE            ;BUFFER IS FULL AND NO MATCHES, SO GO EMPTY
                               ;THE BUFFER.
;*****************************************
;END OF MAIN MATCH FINDER.....
;****************************************
;
;
;
;****************************************
;THIS IS WHERE WE GO WHEN WE HAVE A MATCH
;WE NEED TO SEND OUT THE STRING THAT CORRESPONDS TO
;THE STRING THAT MATCHED IN THE TABLE, IF IT WAS THE
;CURSOR POSITIONING STRING, WE WILL HAVE TO HANDLE THAT HERE ALSO.
;
WHM     EQU     $+OFFSET
       LXI     H,BUFLOC        ;POINT TO BUFFER
       XCHG                    ;MOVE TO DE
WHM1    EQU     $+OFFSET
       LXI     H,COUNT1
       MOV     B,M             ;PUT THE VALUE INTO B:
       LXI     H,OUTSTNG       ;GET THE ADDRESS OF THE TABLE
WHM2    EQU     $+OFFSET
       MOV     A,B             ;PUT B INTO A
       CPI     0               ;POINTING TO THE CORRECT SUBSTRING?
       JZ      WHM3            ;YEP
       INX     H               ;MOVE POINTER UP
       INX     H               ;BYE FOUR, THUS
       INX     H               ;POINTING AT
       INX     H               ;THE NEXT SUBSTRING IN THE OUTSTNG
       DCR     B               ;BUMP B DOWN
       JMP     WHM2            ;LOOP SOME MORE
WHM3    EQU     $+OFFSET
       MVI     B,4             ;4 BYTES TO MOVE
       CALL    MOVE            ;MOVE THE CONTENTS TO THE BUFFER
;******************************
;DONE MOVING THE NEW STRING INTO THE BUFFER, NOW LET'S
;SEE IF IT IS A CURSOR POSITIONING STRING....
;
       LDA     COUNT1          ;GET THE TABLE STRING POINTER
       CPI     14              ;IS IT A CURSOR COMMAND?
       JNZ     DONE            ;NOPE, SO GO EMPTY BUFFER & RESET ALL
       MV
I       A,1             ;GET A 1
       STA     CLCF            ;SET CURSOR COMMAND FLAG TO TRUE
       JMP     DONE            ;GO EMPTY THE BUFFER TO THE REMOTE....
;********************************
;SINCE WE JUST SET THE CLCF, WE WILL COME HERE ON
;THE NEXT 2 CONSOLE OUTPUT CALLS....
;OUR VALUE IS IN THE BUFFER, BUT IF THE SECOND BUFFER POSITION
;IS EMPTY, THEN WE NEED ONE MORE CHARACTER...
;ALSO, SINCE ONE OR BOTH OF OUR CURSOR AND ROW VALUES
;MAY BE A 0, WE'LL DUMP THE BUFFER HERE INSTEAD OF USING
;THE 'DONE ' ROUTINE....
;WE ARE COUNTING ON GETTING AN OFFSET OF >0 FROM THE LOCAL
;FOR THE FIRST POSITION...
CPF     EQU     $+OFFSET
       LXI     H,BUFLOC        ;POINT TO THE BUFFER'S
       INX     H               ;SECOND POSITION
       MOV     A,M             ;GET THE CHAR
       CPI     0               ;IS THERE A CHAR THERE?
       RZ                      ;NOPE, GOTO CP/M AND AWAIT ANOTHER
CPF1    EQU     $+OFFSET        ;NOW WE HAVE THE TWO CHARACTERS WE WANT
       LXI     H,OCCC          ;POINT TO THE FIRST BUFFER LOCATION
       MOV     B,M             ;GET THE VALUE INTO B
       LDA     ICCC            ;GET THE OTHER ONE
       CMP     B               ;DO THEY MATCH?
       JZ      CPF2            ;YEP,DON'T NEED TO REVERSE THE BUFFER CONTENTS
       LDA     BUFLOC          ;GET THE FIRST CHAR
       MOV     B,A             ;SAVE IT IN B
       LDA     BUFLOC+1        ;GET THE NEXT ONE
       STA     BUFLOC          ;PUT IT WHERE THE FIRST ONE WAS
       MOV     A,B             ;GET THE ONE THAT WAS THE FIRST
       STA     BUFLOC+1        ;AND PUT IT IN THE SECOND POSITION
;
;NOW MODIFY THE X,Y COORDINATE VALUES
;BY STRIPPING THEM OF THEIR ORIGINAL OFFSET(S)
;
CPF2    EQU     $+OFFSET
       LXI     H,ICCO          ;POINT TO VAL OF LOCAL OFFSET
       LDA     BUFLOC          ;GET THE FIRST CHAR
       SUB     M               ;SUBTRACT THE OFFSET
       STA     BUFLOC          ;PUT IT BACK
       LXI     H,ICRO          ;POINT TO VAL OF 2ND LOCAL OFFSET
       LDA     BUFLOC+1        ;GET 2ND VAL FROM BUFFER
       SUB     M               ;SUBTRACT THE OFFSET
       STA     BUFLOC  +1      ;PUT IT BACK
;
;NOW ADD THE NEW OFFSETS TO THEM
;
CPF3    EQU     $+OFFSET
       LXI     H,OCCO          ;POINT TO THE OUTSTNG VALUE
       LDA     BUFLOC          ;GET THE VALUE OF THE 1ST CHAR
       ADD     M               ;ADD THE NEW OFFSET
       STA     BUFLOC
       LXI     H,OCRO          ;POINT TO THE OTHER ONE
       LDA     BUFLOC+1        ;GET THE SECOND VAL FROM BUFFER
       ADD     M               ;ADD THE NEW OFFSET
       STA     BUFLOC+1        ;PUT IT BACK
       LDA     BUFLOC          ;GET 1ST CHAR
       MOV     C,A             ;PUT IT IN C
       CALL    REMOUT          ;SEND IT OUT
       LDA     BUFLOC+1        ;GET SECOND
       MOV     C,A             ;PUT IT IN C
       CALL    REMOUT          ;SEND IT OUT
       MVI     A,0             ;NOW KILL THE CHARS IN THE BUFFER
       STA     BUFLOC
       STA     BUFLOC+1
       CALL    DONE2           ;USE DONE'S ROUTINES TO CLEAR THINGS
INIT9   EQU     $+OFFSET
       LXI     H,CLCF          ;POINT TO THE FIRST OF THE FLAGS AND BUFFERS
       LXI     B,BUFPTR-CLCF   ;# OF VARIABLES TO CLEAR
       MVI     A,0             ;GET A ZERO
INIT10  EQU     $+OFFSET
       MOV     M,A             ;PUT IT IN THE VAR OR FLAG
       DCX     B               ;BUMP COUNTER
       MOV     B,A
       CPI     0
       RZ                      ;ALLDONE, BACK TO CP/M
       INX     H               ;POINT TO NEXT BYTE
       MVI     A,0             ;GET THE ZERO BACK
       JMP     INIT10
;********************************************
;DONE OUTPUTTING ANYTHING THAT COMES ALONG, CONVERTED AS NECESSARY
;******************************************
;
;COME HERE WITH A NEW CHARACTER, BEFORE OUTPUTING IT TO
;THE LOCAL
;
STRT    EQU     $+OFFSET
       MVI     A,0
       STA     COUNT           ;ZERO THE COUNTER
       LXI     H,BUFLOC        ;POINT TO THE BUFFER
STRT1   EQU     $+OFFSET
       MOV     A,M             ;GET THE CONTENTS
       CPI     0               ;IS THERE A 0 THERE?
       JZ      STRT2           ;YES, BUFFER IS EMPTY
       LDA     COUNT           ;NO? THEN HOW MANY CHAR IN IT?
       INR     A               ;LETS LOOK AT THEM AND COUNT
       STA     COUNT           ;THE CHARACTERS
       CPI     6               ;BETTER NOT BE MORE THAN 6
       JZ      ERRXIT          ;OOPS, GOT A PROBLEM
       INX     H               ;POINT TO NEXT POSITION
       JMP     STRT1           ;MORE CHARS TO CHECK
STRT2   EQU     $+OFFSET
       MOV     M,C             ;PUT OUTBOUND CHAR INTO BUFFER
       RET
;**************************************
;
;DONE... THIS IS WERE WE END UP WHEN WE WANT TO DUMP THE BUFFER TO
;        THE REMOTE.....
;
DONE    EQU     $+OFFSET
       MVI     B,0             ;SET COUNT TO 0
       LXI     H,BUFLOC        ;POINT TO THE BUFFER
DONE1   EQU     $+OFFSET
       MOV     A,M             ;GET THE CHAR
       CPI     0               ;IS IT A 0?
       JZ      DONE2           ;RETURN IF 0
       MOV     C,M             ;NOT A 0 SO GET THE CHAR
       CALL    REMOUT          ;GO OUTPUT IT
       MVI     A,0
       MOV     M,A             ;KILL THE BUFFER CHAR
       INX     H               ;POINT TO NEXT CHAR
       JMP     DONE1
DONE2   EQU     $+OFFSET
       LXI     H,POSMTCH       ;POINT TO POSMTCH FLAG
       MOV     M,A             ;PUT A ZERO THERE
       LXI     H,MTSTR         ;POINT TO MATCH STR
       MVI     B,5             ;SET COUNT
DONE3   EQU     $+OFFSET
       MOV     M,A             ;ZERO THE MTSTR ALSO
       DCR     B
       CMP     B               ;IS B A 0 YET?
       JZ      DONE4           ;ALL DONE
       INX     H               ;POINT TO NEXT
       MVI     A,0             ;GET A 0
       JMP     DONE3           ;
DONE4   EQU     $+OFFSET
       RET
;
CLCF    EQU     $+OFFSET
       DB      0
POSMTCH EQU     $+OFFSET
       DB      0
OSPTR   EQU     $+OFFSET
       DB      0,0
INSPTR  EQU     $+OFFSET
       DB      0,0
MTSTR   EQU     $+OFFSET
       DB      0,0,0,0,0,0
COUNT   EQU     $+OFFSET
       DB      0
COUNT1  EQU     $+OFFSET
       DB      0
BUFLOC  EQU     $+OFFSET        ;LOCATION OF OUTBOUND BUFFERED STRING
       DB      0,0,0,0,0,0,0
BUFPTR  EQU     $+OFFSET
       DB      0,0
;==========================================================
;END OF SCREEN COMMAND STRING FILTER SECTION.
;==========================================================