	TITLE PRINT  Version 2, Maj 1984                    		       

	.COMMENT *

Programmet udskriver en tekstfil til den lokale printer.
Man starter fra CP/M som ved andre transiente kommandoer:

A>PRINT FILNAVN <cr>

Filnavnet skal overholde standard CP/M formatet d:nnnnnnnn.ttt, hvor d er
drive, nnnnnnnn er filnavnet og ttt er filtype.

Programmet kan kun skrive en enkelt fil ud, men er man i tvivl om filnavnet
kan man bruge sp|rgsm}lstegn og stjerner (wildcards) som normalt for CP/M.
Findes der flere filer, der matcher navnet, skrives de allesammen p} sk{rmen
(som ved DIR), og der udskrives en fejlmeddelelse. Finder programmet kun en
fil starter udskrivningen med det samme.

Hvis filen ikke findes p} det valgte drive tester programmet om der er valgt
default drive (dvs. der er ikke angivet drive i filnavnet). Hvis ikke
returnerer programmet til CP/M med en fejlmeddelelse, ellers s|ger det filen
p} det andet drive (den findes jo nok et eller andet sted).

Tekstfilen udskrives med printerens mindste bogstaver (16,5 CPI). Det betyder
at kompileringslister kan udskrives p} A4 h|j, fordi man f}r 132 tegn pr. linie
(mod normalt 80).

Der er 72 linier p} en A4-side, men for at skippe perforeringen foretager
programmet sideskift efter 67 linier. Bem{rk dog, at listefiler fra
M80-assembleren kun har 50 linier pr. side, medmindre andet er specificeret
med PAGE-kommandoen.

	*


	.Z80

BDOS	EQU  0005H	;BDOS ENTRYPOINT
FCB	EQU  5CH	;CP/M DEFAULT FCB
DEFDRV	EQU  0004H	;DEFAULTDRIVE

BELL	EQU  07H	;
HT	EQU  09H	;TABULATOR (HORIZONTAL TAB)
CR	EQU  0DH	;CARRIAGE RETURN
LF	EQU  0AH	;LINEFEED
FF	EQU  0CH	;FORMFEED
EOF	EQU  1AH	;END OF FILE

	SUBTTL HOVEDPROGRAM: S\G FILNAVN I DIRECTORY
	PAGE 67
PRINT:	LD   DE,OPSTARTTEKST
	LD   C,9
	CALL BDOS

;Hvis fcb'ens andet tegn (filnavnets f|rste tegn) er en blank
;er der ikke blevet indtastet et filnavn i kommandolinien, og
;programmet returnerer til CP/M med en fejlmeddelelse.
	LD   A,(FCB+1)
	CP   " "
	LD   DE,INTETFILNAVNTEKST
	JP   Z,FEJLRETUR

;Find f|rste forekomst af det indtastede filnavn.
	CALL FINDFOERSTEFIL
	JR   NC,FUNDET

;Filen findes ikke p} det valgte drive. Test om der er valgt defaultdrive, og
;s|g det andet drive igennem hvis det er tilf{ldet. Programmet kommer typisk
;hertil, n}r brugeren glemmer at angive drive i filnavnet, og drive A er
;default mens tekstfilen ligger p} drive B.
	LD   A,(FCB)		;ER DER VALGT DEFAULTDRIVE?
	OR   A
	LD   DE,INGENFILTEKST
	JP   NZ,FEJLRETUR	;NEJ => GLEM DET OG GIV EN FEJLMEDDELELSE
	LD   HL,FCB		;JA: FIND UD AF HVILKET DRIVE DER ER DEFAULT
	LD   (HL),2		;OG S[T FCB'EN TIL DET ANDET DRIVE.
	LD   A,(DEFDRV)
	OR   A
	JR   Z,SKIP
	LD   (HL),1
	LD   A,"A"
	LD   (DRIVETEGN),A
SKIP:	CALL FINDFOERSTEFIL	;S\G FILEN P] DET ANDET DRIVE
	LD   DE,INGENFILTEKST
	JP   C,FEJLRETUR	;STADIG IKKE FUNDET => UD TIL CP/M MED FEJL
	LD   DE,FUNDETPAAANDETTEKST
	LD   C,9		;MEDDEL AT FILEN ER FUNDET P] DET ANDET DRIVE
	PUSH HL
	CALL BDOS
	POP  HL
	LD   A,1		;FILEN BLEV FUNDET, MEN IKKE P] DET VALGTE
	LD   (ACCEPTFLAG),A	;DRIVE, DERFOR AFVENT ACCEPT F\R UDSKRIVNING.

	PAGE
;F|rste forekomst er fundet. Skriv filnavnet p} sk{rmen og s|g videre i
;directoryet. Findes der flere er det galt, for programmet kan kun
;udskrive en enkelt fil til printeren.
FUNDET:	CALL SKRIVFILNAVN
	CALL FINDNAESTEFIL
	JR   C,IKKEFLEREFILER	;KUN EN MATCH I DIRECTORY => SKRIV FILEN

;For mange filer matcher med det indtastede filnavn. Alle fundne
;filer skrives derfor p} sk{rmen, og der returneres til CP/M med
;en fejlmeddelelse. Brugeren m} herefter starte forfra med en mere
;pr{cis angivelse af filnavnet.
FLEREFILER:			;SKRIV RESTERENDE FILNAVNE
	LD   DE,SKILLETEGN	;ADSKIL FILNAVNE MED "  : "
	LD   C,9
	PUSH HL
	CALL BDOS
	POP  HL
	CALL SKRIVFILNAVN	;SKRIV NAVNET P] N[STE FOREKOMST
	CALL FINDNAESTEFIL
	JR   NC,FLEREFILER	;LOOP S] L[NGE DER FINDES FILER DER MATCHER
	LD   DE,FORMANGEFILERTEKST
	JP   FEJLRETUR		;UD TIL CP/M MED EN FEJLMEDDELELSE

IKKEFLEREFILER:
;Kun een fil fundet der matcher det indtastede filnavn.
;Hvis acceptflaget ikke er sat (=0) udskrives filen med det samme.
;Er flag = 1 afventes accept f|r udskrivning (J/N), fordi filen
;blev fundet p} det andet drive.
	LD   A,(ACCEPTFLAG)	;FLAG = 0 ?
	OR   A
	JP   Z,SKRIVFILTILPRINTER ;JA => UDSKRIV FILEN MED DET SAMME

;Skriv navnet p} filen og afvent accept f|r udskrivningen (J/N)
	LD   HL,FCBBUFFER	;SKRIV FILNAVNET P] SK[RMEN
	CALL SKRIVFILNAVN

	LD   DE,ACCEPTTEKST	;SKRIV LEDETEKST
	LD   C,9
	CALL BDOS
VENTPAAACCEPT:			;VENT P] J ELLER N 
	LD   C,1
	CALL BDOS
	AND  5FH		;LAV EVT. LILLE BOGSTAV STORT
	CP   "J"		;HVIS J => SKRIV FILEN
	JR   Z,SKRIVFILTILPRINTER
	CP   "N"		;HVIS N => UD TIL CP/M
	JR   NZ,VENTPAAACCEPT	;ELLERS => VENT IGEN
	LD   DE,CRLFTEKST

FEJLRETUR:
	LD   C,9		;BDOS RUTINE 10: PRINT MESSAGE
	CALL BDOS		;
	RET			;RETURNER TIL CP/M. CCP ER IKKE BLEVET \DELAGT,
				;S] DET ER IKKE N\DVENDIGT AT VARMSTARTE.

	SUBTTL HOVEDPROGRAM: SKRIV FUNDEN FIL TIL PRINTER
	PAGE
SKRIVFILTILPRINTER:
	LD   SP,PRINTSTAK	;INITIER EGEN STAK

	LD   E,29		;S[T PRINTER TIL LILLE SKRIFT (16,5 CPI)
	LD   C,5
	CALL BDOS

;Indl{s fil fra diskette til lager.
;Indl{sning af tekstfilen sker f|rst til lageret. N}r hele filen er indl{st,
;eller n}r lagerbufferen er fuld, udskrives bufferens indhold til printeren.
;Programmet bruger den maksimale bufferplads, som memory tillader. Bufferen
;starter i lageret umiddelbart efter print-programmet og slutter ved toppen
;af memory (normalt =CC06H, dvs. start af BDOS). Adressen for toppen af memory
;kan hentes fra adresse 0006H, da adresse 0005H indeholder kommandoen
;JP TOPOFMEMORY (normalt JP CC06H).
	LD   DE,FCB		;KALD BDOS OPEN-RUTINE.
	LD   C,15		;DET G]R ALTID GODT, FORDI FILEN LIGE ER
	CALL BDOS		;FUNDET I DIRECTORYET UNDER S\GNINGEN.

	LD   DE,FILBUFFER	;S[T DMA-ADRESSEN TIL AT STARTE UMIDDELBART
				;EFTER PROGRAMMET (F\RSTE LEDIGE PLADS I LAGER)

LAES:	PUSH DE			;S[T DMA-ADRESSE
	LD   C,26		;
	CALL BDOS
	LD   DE,FCB		;L[S N[STE SEKTOR FRA FILEN
	LD   C,20
	CALL BDOS
	POP  DE			;RETABLER DMA-ADRESSE
	OR   A			;VAR DER END OF FILE?
	JR   NZ,AFSLUT		;JA => AFSLUT PROGRAMMET

	LD   HL,128		;T[L DMA-ADRESSEN OP MED +128, S] N[STE SEKTOR
	ADD  HL,DE		;BLIVER INDL[ST UMIDDELBART EFTER DEN
	EX   DE,HL		;FOREG]ENDE
	OR   A			;TEST OM BUFFEREN ER FULD, DVS. OM DMA-ADRESSEN
	LD   HL,(0006H)		;ER H\JERE END MAKSIMUM-ADRESSEN FOR TPA
	LD   BC,128+1		;
	SBC  HL,BC
	SBC  HL,DE
	JR   NC,LAES		;PLADS I BUFFER => FORTS[T INDL[SNING
	LD   A,EOF		;BUFFER FULD: SKRIV BUFFERINDHOLD TIL PRINTER
	LD   (DE),A
	CALL SKRIVFRABUFFER
	LD   DE,FILBUFFER	;FORTS[T INDL[SNING FRA START AF LAGERBUFFER
	JR   LAES

AFSLUT:	LD   A,EOF		;MARKER FILEN MED EOF, UANSET OM DEN ER
	LD   (DE),A		;EOF-M[RKET I FORVEJEN
	CALL SKRIVFRABUFFER	;SKRIV BUFFERENS INDHOLD
	LD   E,30		;S[T PRINTEREN TIL "NORMAL" SKRIFT (10 CPI)
	LD   C,5
	CALL BDOS
	LD   E,FF		;AFSLUT MED ET SIDESKIFT P] PRINTEREN
	LD   C,5
	CALL BDOS
	JP   0000H		;VARMSTART CP/M, FORDI CCP M]SKE ER BLEVET
				;\DELAGT (VED STORE FILER).

	SUBTTL UNDERRUTINER BENYTTET VED FILS\GNING
	PAGE
;Find n{ste forekomst af filnavnet i default-fcb'en (adresse 5CH).
;F|rste gang kaldes SEARCHFIRST, alle efterf|lgende gange kaldes SEARCHNEXT.
;Hvis rutinerne finder en forekomst i directoriet returneres der med NC og
;HL peger p} f|rste byte i det p}g{ldende directoryentry. Hvis der ikke
;findes en match returneres der med C-flaget sat.
FINDFOERSTEFIL:
	LD   DE,FCB	;
	LD   C,17	;BDOS RUTINE 17: SEARCH FIRST
	JR   FIND	;

FINDNAESTEFIL:
	LD   C,18	;BDOS RUTINE 18: SEARCH NEXT

FIND:	CALL BDOS	;
	RRCA		;A * 32 + 80H
	RRCA		;
	SCF		;
	RRA		;
	LD   H,0	;S[T HL TIL AT PEGE P] ENTRY
	LD   L,A	;
	RET		;RETURNER MED STATUS I C-FLAG

;Skriv et filnavn til sk{rm i formatet NNNNNNNNbTTT (12 bytes).
;Ved kald skal HL pege p} starten af den fcb der indeholder filnavnet.
SKRIVFILNAVN:
	LD   B,8	;8 TEGN I FILNAVN
	INC  HL
	CALL SKRIVTEGN
	PUSH HL		;ADSKIL NAVN OG TYPE MED ET BLANKTEGN
	LD   E," "
	LD   C,2
	CALL BDOS
	POP  HL
	LD   B,3	;3 TEGN I FILTYPE
SKRIVTEGN:
	LD   E,(HL)
	RES  7,E
	LD   C,2	;BDOS RUTINE 2: CONSOLE OUTPUT
	PUSH BC
	PUSH HL
	CALL BDOS
	POP  HL
	POP  BC
	INC  HL
	DJNZ SKRIVTEGN
	RET

	SUBTTL UNDERRUTINE BENYTTET VED UDSKRIVNING TIL PRINTER
	PAGE
;Udskriv lagerbufferens indhold til printer
SKRIVFRABUFFER:
	LD   HL,FILBUFFER	;START AF FILBUFFER I LAGERET
PRINTTEGN:
	LD   A,(HL)		;HENT N[STE TEGN FRA FILEN
	CP   EOF		;STOP VED END OF FILE
	RET  Z
	PUSH HL
	CALL PRINTA		;SKRIV TEGNET TIL PRINTEREN
	POP  HL
	INC  HL
	JR   PRINTTEGN

;Udskriv A-registret til printeren. Rutinen udvider tabulatortegn
;til et antal blanktegn frem til n{ste kolonne a' 8 tegn.
;Derfor vedligeholdes en t{ller for, hvilken kolonne printhovedet
;i |jeblikket befinder sig i (PRINTKOLONNE).
;Der er 72 linier p} en A4-side, men for at skippe perforeringen foretager
;rutinen et sideskift n}r der er skrevet mere end 67 linier p} en side.
PRINTA:	CP   " "	;KONTROLTEGN?
	JR   NC,PRA1	;NEJ => SKRIV TEGNET

	CP   HT		;TABULATOR?
	JR   Z,TABULATOR;JA => SKRIV BLANKE FREM TIL N[STE KOLONNE A' 8 TEGN

	LD   HL,PRINTKOLONNE
	LD   (HL),0	;ANDRE KONTROLTEGN BEVIRKER, AT DER STARTES FORFRA P]
			;PRINTLINIEN, SELVOM DET IKKE ALTID BEH\VER AT V[RE
			;TILF[LDET, SPECIELT IKKE VED STYREKARAKTERER TIL
			;PRINTEREN. DET ER IKKE MULIGT AT TAGE H\JDE FOR ALLE
			;SPECIALTILF[LDE.

	CP   FF		;SKIFT SIDE VED FORMFEED
	JR   Z,NYSIDE

	CP   LF		;SKIFT LINIE VED LINEFEED, 
	JR   NZ,PRA2	;ELLERS BARE SKRIV KONTROLTEGNET

	LD   HL,LINIETAELLER
	INC  (HL)
	LD   A,(HL)	;HVIS LINIETAELLEREN BLIVER ST\RRE END 67 SKIFTES
	CP   68		;SIDE, FOR AT SKIPPE PERFORERINGEN
	LD   A,LF
	JR   C,PRA2

NYSIDE:	XOR  A		;SIDESKIFT: NULSTIL LINIET[LLER
	LD   (LINIETAELLER),A
	LD   A,FF
	JR   PRA2

PRA1:	LD   HL,PRINTKOLONNE ;HVIS DET ER F\RSTE TEGN P] LINIEN UDF\RES EN
	INC  (HL)	     ;TABULERING. DET GIVER EN VENSTREMARGIN P] 8 TEGN
	LD   B,(HL)
	DEC  B
	JR   NZ,PRA2
	PUSH AF
	CALL TABULATOR
	POP  AF
	JR   PRA1

PRA2:	LD   E,A	;SKRIV TEGNET TIL PRINTEREN
	LD   C,5	;BDOS RUTINE LIST (SKRIVER E-REGISTER TIL PRINTER)
	CALL BDOS
	RET

TABULATOR:
	LD   A," "	;SKRIV BLANKTEGN FREM TIL N[STE KOLONNE A' 8 TEGN
	CALL PRA1
	LD   A,(PRINTKOLONNE)
	AND  111B	;KOLONNE A' 8 TEGN?
	JR   NZ,TABULATOR ;NEJ => SKRIV ET BLANKTEGN MERE
	RET

	SUBTTL DATAAREALER
	PAGE
	DS   32		;PROGRAMSTAK: 16 NIVEAUER
PRINTSTAK EQU $

PRINTKOLONNE: DB 0
LINIETAELLER: DB 0

OPSTARTTEKST:
 DB "PRINT version 2.0    EDB-skolen i HERLEV   Maj 1984.",CR,LF,LF,"$"

FUNDETPAAANDETTEKST:
 DB BELL,128+4,"Fundet p} "
DRIVETEGN: DB "B   : ",128,"$"

ACCEPTTEKST:
 DB CR,LF,"Skal filen udskrives til printer (J/N)? $"

SKILLETEGN:
 DB "  : $"


;	FEJLTEKSTER:

INTETFILNAVNTEKST:
 DB "Du skal indtaste et filnavn i kommandolinien:",CR,LF
 DB "A>PRINT FILNAVN",CR,LF,"$"

INGENFILTEKST:
 DB "Kan ikke finde filen!",CR,LF,"$"

FORMANGEFILERTEKST:
 DB CR,LF,"Der er for mange filer med det navn!",CR,"$"

CRLFTEKST:
 DB CR,LF,"$"

ACCEPTFLAG:	;FLAGET VISER OM DER SKAL AFVENTES ACCEPT AF DE FUNDNE
	DB   0	;FILER F\R UDSKRIVNING:
		;0: KUN EN FIL P] DET VALGTE DRIVE, UDSKRIV MED DET SAMME
		;1: FILEN FUNDET P] IKKE DEFAULT DRIVE, AFVENT ACCEPT (J/N)

;I denne buffer gemmes fcb'en for f|rst fundne fil.
FCBBUFFER: DS 33,0

FILBUFFER  EQU $ ;RESTEN AF LAGERET BRUGES SOM BUFFER VED INDL[SNING
		 ;AF FILEN FRA DISKETTEN

	SUBTTL

	END  PRINT
P   EOF		;STOP VED END OF FILE
	RET  Z
	PUSH HL