	PAGE 85
	.Z80
	.COMMENT #
VTPATCH.MAC enthaelt einen Ausgabe-Patch fuer XMODEM im VT100-Betrieb.

24.03.86	A.Herrmann
01.09.86	Uebersetzung der <Esc>[J - Sequenz debugged
09.09.86	<Esc><,=,> , <Esc>(x , <Esc>)x und <Esc>[2J hinzugenommen
01.04.87	<Esc>[?...h,l und <Esc>[t;br hinzugenommen

Achtung: Zum Testen mit VT.MAC ist .PHASE 310H durch ASEG und ORG 103H
	und die Equation OUTPUT EQU 2080H durch OUTPUT EQU DISPLA zu ersetzen. 
	(Die Routine OUTPUT existiert nur in XMODEM bei 2080h.)
	Ferner kann die Uebersetzung der Kontrollsequenzen durch Setzen des
	Display Flags DISFLG unterdrueckt werden. Stattdessen werden dann die
	ankommenden Codes als ASCII-Kombinationen dargestellt.
	Wird bei TMESSG der sofortige Ruecksprung RET durch NOP ersetzt, 
	erscheint Diagnose-Output des Uebersetzers auf dem Bildschirm. 

VTPATCH uebersetzt die folgenden VT100-Kontrollsequenzen in Steuercodes 
fuer den VIDEO80-Treiber. Wenn kein VIDEO80 Code angegeben ist, wird der
Input ignoriert. 

  VT100       -->  VIDEO80      Bedeutung  (n=ASCII-Integer)
-----------------------------------------------------------------------
  <Esc>[nA    -->  Ctrl/K       Cursor up  (Default n=1)
  <Esc>[nB    -->  Ctrl/J       Cursor down
  <Esc>[nC    -->  Ctrl/I       Cursor forward
  <Esc>[nD    -->  Ctrl/H       Cursor backward
  <Esc>[l;cH  -->  <Esc>Fyx     Cursor position (Default l,c=0)
  <Esc>[l;cf  -->  dito
  <Esc>[t;br  -->  <Esc>C t b	Set window top and bottom line

  <Esc>[1m   -->   <Esc>R       Bold (Dim)
  <Esc>[4m   -->   <Esc>R       Underline (Dim)
  <Esc>[7m   -->   <Esc>R       Reverse (Dim)
  <Esc>[0m   -->   <Esc>S       All attributes off (Dim off)
  <Esc>[m    -->   dito

  <Esc>[nL   -->   <Esc>\       Insert line
  <Esc>[nM   -->   <Esc>]       Delete line
  <Esc>[0K   -->   <Esc>Z       Erase end of line
  <Esc>[K    -->   dito
  <Esc>[0J   -->   <Esc>[       Erase end of screen
  <Esc>[J    -->   dito

  <Esc>[?..h -->		Terminal mode control (on switches)
  <Esc>[?..l -->		Terminal mode control (off switches)

  <Esc>(x    -->		Change G0 char set (Ignored for all x)
  <Esc>)x    -->		Change G1 char set (Ignored for all x)

  <Esc>=     -->		Keypad mode on
  <Esc>>     -->		Keypad mode off
  <Esc><     -->		ANSI mode on
  <Esc>M     -->   <Esc>\       Reverse index (benutzt im VAX-Editor EDT)

Sobald eine nicht aufgefuehrte Sequenz erkannt wird, wird die Uebersetzung
abgebrochen. Das "ungehoerige" Zeichen und darauffolgende Zeichen werden 
unveraendert ausgegeben.

VTPATCH wird mit ZSID bei 310H in den XMODEM-File XM.COM gepatcht.
Die Routine erwartet die Ausgabezeichen im Akku A und kann anstelle der
Ausgabe-Routine bei 2080H in XMODEM aufgerufen werden.
Alle Registerwerte werden eingangs gerettet und vor dem Ruecksprung wieder 
restauriert.

Fuer die Benutzung des numerischen Tastenfeldes im VT100-"Keypad application
mode" wurde eine UMTAST-Datei XMKEYP.COM angelegt. Diese enthaelt die ANSI-
Sequenzen fuer die 8-Bit-Codes, welche DINTAST in der Betriebsart 7 ("80", 
Umschalten mit Ctrl/Lock 7) bei den betreffenden Tasten ausgibt.
XMKEYP.COM ruft als Autoload-File XM.COM.
#
	ENTRY VT100
	.PHASE 310H
;ASEG		;nur fuer
;ORG 310H	;Testzwecke mit VT.MAC

VT100:	JP START

; GLOBAL ADDRESSES

BDOS	EQU 0005H	;BDOS JUMP ADDRESS
OUTPUT	EQU 2080H	;XMODEM OUTPUT ROUTINE
;OUTPUT	EQU DISPLA	;nur fuer Testzwecke mit VT.MAC

; VARIABLES AND CONSTANTS

CTRLC	EQU 03H
CTRLH	EQU 08H
CTRLI	EQU 09H
CTRLJ	EQU 0AH
CTRLK	EQU 0BH
ESC	EQU 1BH		;ESCAPE
LBR	EQU '['		;SEQUENCE INTRODUCER
LP	EQU '('		;ANOTHER ONE
RP	EQU ')'		;AND YET ANOTHER ONE
DELIM	EQU ';'		;PARAMETER DELIMITER

DISFLG:	DB 0		;DISPLAY FLAG (NORMALLY=0)
INIFLG:	DB 0		;0 = INIT PARSER
CHAR:	DB 0		;CHAR TO BE TRANSLATED
PAR1:	DB 0		;1ST PARAMETER
PAR2:	DB 0		;2ND PARAMETER
STATUS:	DB 0		;CURRENT PARSER STATUS

TEXT	EQU 0
ESCAPE	EQU 1
LEFTBR	EQU 2
LEFTPA	EQU 3
RIGHTP	EQU 4
PARAM1	EQU 5
PARAM2	EQU 6
QUESTM	EQU 7

JPSTA:	DW STTEXT	;STATUS JUMP TABLE 
	DW STESCA	;(STATUS JUMPS ARE CALCULATED,
	DW STLEFT	;NOT COMPARED!)
	DW STLFTP
	DW STRGHT
	DW STPAR1
	DW STPAR2

; INPUT CHARS AND JUMP ADDRESSES
;(REMEMBER: TABLES OF JUMP ADDRESSES HAVE TO BE IN
; REVERSE ORDER OF THE CORRESPONDING TABLES OF CHARS !)

FCODES:	
F2CODE:	DB 'fHr'	;TRANSL.INTO 2 CHARS w/ 2 PARS.
F2LEN1	EQU $-F2CODE
F2COD2:	DB 'LM'		;w/ PAR1>=1
	DB 'K'		;w/ PAR1 =0
	DB 'J'		;w/ PAR1 = empty, 0, or 2
F2LEN2	EQU $-F2COD2
	DB 'm'		;w/ PAR1 =0,1,4,7
F2LEN	EQU $-F2CODE

F1CODE:	DB 'ABCD'	;TRANSL.INTO 1 CONTROL CHAR
F1LEN	EQU $-F1CODE

FCDLEN	EQU $-FCODES

JPTR2:	DW TRANSM	;m
	DW TRANJ	;J
	DW TRANK	;K
	DW TRANM	;M
	DW TRANL	;L
	DW TRANSR	;r
	DW TRANH	;H
	DW TRANSF	;f

SMPARS:	DB 0		;AND ALL OTHERS: ATTRIBUTES OFF
	DB 1		;ATTRIBUTES OFF (FOR BOLD)
	DB 4		;ATTRIBUTES OFF (FOR UNDERLINE)
	DB 7		;DIM (FOR REVERSE VIDEO)
SMPLEN	EQU $-SMPARS

; REPLACEMENT CHARACTERS
;(REMEMBER: TABLES OF REPLACEMENT CHARS HAVE TO BE IN
; REVERSE ORDER OF CORRESPONDING TABLES OF CHARS !)

REPLSM:	DB 'R'		;FOR '7'
	DB 'R'		;FOR '4'
	DB 'R'		;FOR '1'
	DB 'S'		;FOR '0'
REPLF1:	DB CTRLH	;FOR 'D'
	DB CTRLI	;FOR 'C'
	DB CTRLJ	;FOR 'B'
	DB CTRLK	;FOR 'A'
REPLF2:	DB '['		;FOR 'J'
	DB 'Z'		;FOR 'K'
	DB ']'		;FOR 'M'
	DB '\'		;FOR 'L'
;------------------------------------------
;	SOME SUBROUTINES
;------------------------------------------
INITVT:	CPL
	LD (INIFLG),A
	LD A,TEXT	;STATUS=TEXT
	LD (STATUS),A
	RET

COMPJP:	ADD HL,BC	;COMPUTE JUMP ADDRESS IN HL
	ADD HL,BC
	LD E,(HL)
	INC HL
	LD D,(HL)
	EX DE,HL
	RET

MULT10:	ADD A,A		;A*10 = A*8 + A*2
	PUSH BC
	LD B,A
	ADD A,A
	ADD A,A
	ADD A,B
	POP BC
	RET
;------------------------------------------
;	MAIN ROUTINE
;------------------------------------------
START:	PUSH AF
	PUSH BC
	PUSH DE
	PUSH HL
	LD (CHAR),A	;SAVE CHAR

	LD A,(INIFLG)	;INIT. PARSER ?
	OR A
	CALL Z,INITVT
	
	LD A,(DISFLG)	;IF THIS FLAG IS SET
	OR A		;INCOMING CHARS WON'T
	JP Z,STAT	;BE INTERPRETED BUT
	LD A,(CHAR)
	CALL DISPLA	;ONLY DISPLAYED
	JP EXIT

STAT:	LD A,(STATUS)
	LD B,0
	LD C,A
	LD HL,JPSTA
	CALL COMPJP	;COMPUTE JUMP ADDRESS
	LD A,(CHAR)
	JP (HL)

STTEXT:	CP ESC		;= "Esc" ?
	JP NZ,OUTCH
	LD A,ESCAPE
	JP SEXIT

STESCA:	CP LBR		;= "[" ?
	JP NZ,STESCB
	XOR A
	LD (PAR1),A
	LD (PAR2),A
	LD A,LEFTBR
	JP SEXIT
STESCB:	CP LP		;= "(" ?
	JP NZ,STESCC
	LD A,LEFTPA
	JP SEXIT
STESCC:	CP RP		;= ")" ?
	JP NZ,STESC1
	LD A,RIGHTP
	JP SEXIT
STESC1:	CP 'M'		;= "M" ?
	JP NZ,STESC2
	LD A,'\'	;-> INSERT LINE
STESC:	CALL TROUT	;OUTPUT ESCAPE SEQUENCE
	JP TEXIT
STESC2:	CP '<'		;IGNORE ALL OF THE FOLLOWING
	JP Z,TEXIT
	CP '='
	JP Z,TEXIT
	CP '>'
	JP Z,TEXIT
	JP OUTCH	;ELSE JUST SHOW IT

STLEFT:	CP DELIM	;= ";" ?
	JR NZ,STLEF1
	LD A,PARAM2
	JP SEXIT
STLEF1:	CP '9'+1	;= DIGIT ?
	JP NC,STLEF2
	CP '0'
	JP C,STLEF2
	SUB 30H
	LD (PAR1),A	;PAR1=A
	LD A,PARAM1
	JP SEXIT
STLEF2:	CP '?'		;= "?" ?
	JP Z,EXIT	;YES, IGNORE IT
	CP 'h'		;= "h" ?
	JR Z,TEXIT	;YES, NO TRANSLATION.
	CP 'l'		;= "l" ?
	JR Z,TEXIT	;YES, NO TRANSLATION.

	LD HL,FCODES	;=FCODE ?
	LD BC,FCDLEN
	CPIR
	JP NZ,OUTCH
	DEC HL
	LD A,(HL)
	CALL TRANS	;YES, TRANSLATE IT.
	JP TEXIT

STPAR1:	CP DELIM	;= ";" ?
	JR NZ,STPA11
	LD A,PARAM2
	JP SEXIT
STPA11:	CP '9'+1	;= DIGIT ?
	JP NC,STPA12
	CP '0'
	JP C,STPA12
	SUB 30H
	LD B,A
	LD A,(PAR1)
	CALL MULT10	;PAR1=PAR1*10+A
	ADD A,B
	LD (PAR1),A
	JP EXIT
STPA12:	JP STLEF2	;= FCODE ?

STPAR2:	CP '9'+1	;= DIGIT ?
	JP NC,STPA21
	CP '0'
	JP C,STPA21
	SUB 30H
	LD B,A
	LD A,(PAR2)
	CALL MULT10	;PAR2=PAR2*10+A
	ADD A,B
	LD (PAR2),A
	JP EXIT
STPA21:	LD HL,F2CODE	;= 2-PAR.FCODE ?
	LD BC,F2LEN1
	CPIR
	JP NZ,OUTCH
	DEC HL
	LD A,(HL)
	CALL TRANS	;YES, TRANSLATE IT.
	JP TEXIT
STLFTP:
STRGHT:	JP TEXIT	;IGNORE THIS

OUTCH:	CALL OUTPUT
TEXIT:	LD A,TEXT
SEXIT:	LD (STATUS),A
EXIT:	POP HL
	POP DE
	POP BC
	POP AF
	RET		;BACK TO CALLING PROGRAM

;------------------------------------------
;	OUTPUT OF TRANSLATION SEQUENCE
;------------------------------------------
TRANS:	CALL TMESSG	;DIAGNOSTIC MESSAGE
	LD HL,F1CODE	;= F1CODE ?
	LD BC,F1LEN
	CPIR
	JP NZ,TRAN2
TRAN1:	LD HL,REPLF1	;YES.
	ADD HL,BC	;COMPUTE ADDRESS OF REPL CHAR
	LD A,(PAR1)	;TRANSLATE AT LEAST ONCE
	OR A
	JP NZ,F1LOOP
	INC A
	LD (PAR1),A
F1LOOP:	LD A,(HL)	;GET REPLACEMENT CHAR
	PUSH HL
	CALL OUTPUT
	POP HL
	LD A,(PAR1)	;CHECK 1ST PARAMETER
	DEC A		;IF OUTPUT
	LD (PAR1),A	;HAS TO BE
	JP NZ,F1LOOP	;REPEATED
	JP TREXIT

TRAN2:	LD HL,F2CODE	;= F2CODE ?
	LD BC,F2LEN
	CPIR
	JP NZ,TREXIT
	LD HL,JPTR2
	CALL COMPJP
	JP (HL)

TRANSM:	LD A,(PAR1)
	LD HL,SMPARS
	LD BC,SMPLEN
	CPIR
	JP Z,TRASM1	;PARAMETER FOUND?
	LD BC,SMPLEN-1	;NO, ATTRIBUTES OFF.
TRASM1:	LD A,ESC	;YES,
	PUSH BC
	CALL OUTPUT	;OUTPUT ESCAPE CHAR,
	POP BC
	LD HL,REPLSM
	ADD HL,BC	;COMPUTE ADDRESS,
	LD A,(HL)	;GET, AND
	CALL OUTPUT	;OUTPUT REPLACEMENT CHAR
	JP TREXIT

TRANJ:	LD A,(PAR1)	;PAR1 = 0 ?
	OR A
	JP NZ,TRAN2J
	LD A,'['	;ERASE TO END OF SCREEN
	JP TRANXJ
TRAN2J:	CP 2		;PAR1 = 2 ?
	JP NZ,TREXIT
	LD A,'I'	;ERASE ENTIRE SCREEN
TRANXJ:	CALL TROUT
	JP TREXIT

TRANK:	LD A,(PAR1)	;DEFINED ONLY FOR PAR1=0
	OR A
	JP NZ,TREXIT
TRANL:
TRANM:	LD A,(CHAR)
	LD HL,F2COD2
	LD BC,F2LEN2
	CPIR
	LD HL,REPLF2
	ADD HL,BC	;COMPUTE ADDRESS OF REPL CHAR
	LD A,(PAR1)	;TRANSLATE AT LEAST ONCE
	OR A
	JP NZ,TRANM1
	INC A
	LD (PAR1),A
TRANM1:	PUSH HL
	LD A,(HL)
	CALL TROUT	;OUTPUT ESC SEQUENCE
	POP HL
	LD A,(PAR1)	;DECREMENT PAR1
	DEC A		;AND CHECK
	LD (PAR1),A	;IF SEQUENCE HAS TO BE
	JP NZ,TRANM1	;REPEATED
	JP TREXIT

TRANSR:	LD A,ESC	;SET WINDOW
	CALL OUTPUT
	LD A,'C'	;FOR 'r'
	CALL OUTPUT
	LD A,0		;LEFT COLUMN = 0 (1.COLUMN)
	CALL OUTCOD
	LD A,(PAR1)	;TOP LINE NO. CODED
	OR A		; DEFAULT OUTPUT = 0 (1.LINE)
	JR Z,TRASR1
	DEC A		;(MY SCREEN LINE NUMBERS START WITH 0)
TRASR1:	CALL OUTCOD
	LD A,79		;RIGHT COLUMN = 79 (80.COLUMN)
	CALL OUTCOD
	LD A,(PAR2)	;BOTTOM LINE NO. CODED
	OR A		; DEFAULT OUTPUT = 23 (24.LINE)
	JR NZ,TRASR2
	LD A,24
TRASR2:	DEC A
	CALL OUTCOD
	JP TREXIT

TRANSF:
TRANH:	LD A,ESC	;CURSOR POSITIONING
	CALL OUTPUT
	LD A,'F'	;FOR 'f' or 'H'
	CALL OUTPUT
	LD A,(PAR1)	;LINE NO. CODED
	OR A
	JR Z,TRANH1
	DEC A		;BEGINNING WITH 0
TRANH1:	CALL OUTCOD
	LD A,(PAR2)	;COLUMN NO. CODED
	OR A
	JR Z,TRANH2
	DEC A		;BEGINNING WITH 0
TRANH2:	CALL OUTCOD
	JP TREXIT

TREXIT: RET

OUTCOD:	ADD A,20H	;SCREEN CONTROL CODE OUTPUT
	CALL OUTPUT
	RET

TROUT:	PUSH AF		;OUTPUT TRANSLATION ESCAPE SEQUENCE
	LD A,ESC
	CALL OUTPUT	;OUTPUT ESCAPE CHAR,
	POP AF
	CALL OUTPUT	;OUTPUT REPLACEMENT CHAR
	RET

TMESSG: RET		;FOR A DIAGNOSTIC MESSAGE REPLACE "RET" BY "NOP"
;	PUSH AF		;OUTPUT A MESSAGE
;	LD DE,TRMSG1
;	LD C,9
;	CALL BDOS
;	POP AF
;	PUSH AF
;	LD C,2
;	LD E,A
;	CALL BDOS
;	LD DE,TRMSG2
;	LD C,9
;	CALL BDOS
;	POP AF
;	RET
;TRMSG1:	DB 0DH,0AH
;	DB '(VT:$'
;TRMSG2:	DB ')'
;	DB 0DH,0AH
;	DB '$'
;------------------------------------------
; DISPLAY INCOMING CHARACTER
; (ONLY IF DISFLG IS NOT 0)
;------------------------------------------
DISPLA:	
	CP ESC
	JP NZ,DISPL1
	LD DE,ESCMSG
	LD C,9
	CALL BDOS
	RET
ESCMSG:	DB '<Esc>$'
DISPL1:
	CP 20H
	JP NC,DISPCH
	ADD A,40H
	PUSH AF
	LD A,'^'
	CALL DISPCH
	POP AF
DISPCH:	LD C,2
	LD E,A
	CALL BDOS
	RET
;------------------------------------------
	.DEPHASE
	END
