; ; PROGRAM: PRINT III (PRINT3) ; VERSION: 1.3 ; DATE: 17 May 83 ; AUTHOR: RICHARD CONN ; PREVIOUS VERSIONS: 1.2 (26 Apr 83), 1.1 (26 Apr 83), 1.0 (22 Apr 83) ; VERS equ 13 FALSE equ 0 TRUE equ NOT FALSE timeok equ FALSE ;TRUE to enable TIME feature, FALSE to disable ; ; PRINT3 is THE file print utility for ZCPR2. Installable by GENINS, ; PRINT3 provides a wide range of options for the user. First, PRINT3 allows ; the user to employ wild cards and file name lists (lists of files separated ; by commas, like: file1,file2,file3,...). Second, PRINT3 provides the ; following options: ; E Exact Mode ; No heading appears, no line numbering, ; no page numbering, tab expansion, form ; feeds ; F File Name Toggle ; The Heading Line can optionally contain ; the name of the file ; H@head@ Heading Text ; The user may specify the text of the heading ; to appear at the top of every page ; I Inspect Files ; The user approves each file to be printed ; before the printing process begins ; L Toggle Line Numbering ; Each line may or may not begin with a line ; number ; M Multiple Runs Toggle ; The user may or may not be prompted to set ; the Top of Form on his printer; Multiple Runs ; ON means that he will not be prompted ; N Toggle Page Numbering ; The numbering of each page is turned on or ; off ; Onn Offset Each Line ; Move each line in the indicated number of ; characters from the left ; Snnnn Skip to Specified Page ; Printing begins on the indicated page ; T Toggle Time Display ; Time/Date information is optionally included ; in the page header ; ; ; This program is Copyright (c) 1982, 1983 by Richard Conn ; All Rights Reserved ; ; ZCPR2 and its utilities, including this one, are released ; to the public domain. Anyone who wishes to USE them may do so with ; no strings attached. The author assumes no responsibility or ; liability for the use of ZCPR2 and its utilities. ; ; The author, Richard Conn, has sole rights to this program. ; ZCPR2 and its utilities may not be sold without the express, ; written permission of the author. ; ; ; BASIC SYSLIB ROUTINES NEEDED BY TEMPLATE ; ESIZE EQU 16 ; SIZE OF DIR ENTRY (FROM SYSLIB DIRF ROUTINE) EXT DIRFS ; DIRECTORY PROCESSOR EXT DIRPACK ; PACK DIRECTORY EXT ZGPINS ; INIT BUFFERS EXT ZFNAME ; FILE NAME PROCESSOR EXT INITFCB ; INIT FCB EXT RETUD ; RETURN CURRENT USER/DISK EXT PUTUD ; SAVE CURRENT USER/DISK EXT GETUD ; RESTORE CURRENT USER/DISK EXT LOGUD ; LOG INTO USER/DISK EXT PRINT ; PRINT STRING PTED TO BY RET ADR EXT PADC ; PRINT A IN DEC EXT COUT ; CONSOLE OUTPUT ROUTINE EXT CONDIN ; CONDITIONAL INPUT ROUTINE EXT CIN ; CONSOLE INPUT ROUTINE EXT CAPS ; CAPITALIZE ROUTINE EXT CRLF ; NEW LINE ROUTINE EXT CLINE ; COMMAND LINE STRING SAVE ROUTINE EXT CODEND ; CODE END COMPUTATION ROUTINE EXT F$OPEN ; FILE OPEN EXT F$READ ; BLOCK READ EXT F$CLOSE ; FILE CLOSE EXT EVAL10 ; STRING TO BINARY CONVERSION EXT LHLDC ; LST: HL AS DEC OUTPUT EXT LPSTR ; LST: (HL) STRING OUTPUT EXT LPRINT ; LST: STRING OUTPUT EXT LCRLF ; LST: NEW LINE EXT LOUT ; LST: OUTPUT EXT MOVEB ; MOVEB ROUTINE if timeok EXT TIME ; TIME Library Module Routine endif ; ; CP/M EQUATES ; CPM EQU 0 ; WARM BOOT BDOSE EQU CPM+5 ; BDOS ENTRY FCB EQU CPM+5CH ; FCB TBUFF EQU CPM+80H ; INPUT LINE BUFFER DEL EQU 7FH ; CR EQU 13 ; FF EQU 12 ; LF EQU 10 ; CTRLC EQU 'C'-'@' ; ^C CTRLG EQU 'G'-'@' CTRLH EQU 'H'-'@' CTRLI EQU 'I'-'@' CTRLX EQU 'X'-'@' CTRLZ EQU 'Z'-'@' ; ; OTHER EQUATES ; EOLD EQU 0FFH ; END OF LOAD DELIMITER ; ; Branch to Start of Program ; JMP START ; ;****************************************************************** ; ; SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format ; ; This data block precisely defines the data format for ; initial features of a ZCPR2 system which are required for proper ; initialization of the ZCPR2-Specific Routines in SYSLIB. ; ; ; EXTERNAL PATH DATA ; EPAVAIL: DB 0FFH ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES) EPADR: DW 40H ; ADDRESS OF EXTERNAL PATH IF AVAILABLE ; ; INTERNAL PATH DATA ; INTPATH: DB 0,0 ; DISK, USER FOR FIRST PATH ELEMENT ; DISK = 1 FOR A, '$' FOR CURRENT ; USER = NUMBER, '$' FOR CURRENT DB 0,0 DB 0,0 DB 0,0 DB 0,0 DB 0,0 DB 0,0 DB 0,0 ; DISK, USER FOR 8TH PATH ELEMENT DB 0 ; END OF PATH ; ; MULTIPLE COMMAND LINE BUFFER DATA ; MCAVAIL: DB 0FFH ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE? MCADR: DW 0FF00H ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE ; ; DISK/USER LIMITS ; MDISK: DB 4 ; MAXIMUM NUMBER OF DISKS MUSER: DB 31 ; MAXIMUM USER NUMBER ; ; FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK ; DOK: DB 0FFH ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES) UOK: DB 0FFH ; ALLOW USER CHANGE? (0=NO, 0FFH=YES) ; ; PRIVILEGED USER DATA ; PUSER: DB 10 ; BEGINNING OF PRIVILEGED USER AREAS PPASS: DB 'chdir',0 ; PASSWORD FOR MOVING INTO PRIV USER AREAS DS 41-($-PPASS) ; 40 CHARS MAX IN BUFFER + 1 for ending NULL ; ; CURRENT USER/DISK INDICATOR ; CINDIC: DB '$' ; USUAL VALUE (FOR PATH EXPRESSIONS) ; ; DMA ADDRESS FOR DISK TRANSFERS ; DMADR: DW 80H ; TBUFF AREA ; ; NAMED DIRECTORY INFORMATION ; NDRADR: DW 00000H ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY NDNAMES: DB 64 ; MAX NUMBER OF DIRECTORY NAMES DNFILE: DB 'NAMES ' ; NAME OF DISK NAME FILE DB 'DIR' ; TYPE OF DISK NAME FILE ; ; REQUIREMENTS FLAGS ; EPREQD: DB 0FFH ; EXTERNAL PATH? MCREQD: DB 000H ; MULTIPLE COMMAND LINE? MXREQD: DB 0FFH ; MAX USER/DISK? UDREQD: DB 000H ; ALLOW USER/DISK CHANGE? PUREQD: DB 000H ; PRIVILEGED USER? CDREQD: DB 0FFH ; CURRENT INDIC AND DMA? NDREQD: DB 0FFH ; NAMED DIRECTORIES? Z2CLASS: DB 11 ; CLASS 11 DB 'ZCPR2' DS 10 ; RESERVED ; ; END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA ; ;****************************************************************** ; ; ; **** Special Initial Value Area for GENINS ; LWIDTH: DB 132 ; WIDTH OF LINE LTPP: DB 44 ; LINES OF TEXT PER PAGE LSPP: DB 5 ; LINES TO SKIP PER PAGE CWIDTH: DB 80 ; WIDTH OF SCREEN CTPP: DB 22 ; LINES OF TEXT PER SCREEN CSPP: DB 1 ; LINES TO SKIP PER SCREEN ; ; NOTE: LTPP + LSPP + 2 (HEADER SIZE) = TOTAL LINES PER PAGE ON PRINTER ; NOTE: CTPP + CSPP + 1 (FOOTER SIZE) = TOTAL LINES PER SCREEN ON CONSOLE ; DLNUMFL: DB 0 ; LINE NUMBER FLAG (DEFAULT TO NO) DPNUMFL: DB 0FFH ; PAGE NUMBER FLAG (DEFAULT TO YES) DEXACT: DB 0 ; EXACT PRINT FLAG (DEFAULT TO NO) DFNPFL: DB 0FFH ; FILE NAME PRINT FLAG (DEFAULT TO YES) DTIMEPFL: DB 0FFH ; TIME PRINT FLAG (DEFAULT TO YES) DMULTFL: DB 0FFH ; MULTIPLE RUN FLAG (DEFAULT TO YES) DINSPECT: DB 0 ; INSPECT FILES (DEFAULT TO NO) DOFFSET: DB 0 ; INITIAL COLUMN OFFSET (DEFAULT TO NO COLUMNS) ; ; OTHER BUFFERS ; SKIPFL: DB 0 ; SKIP FLAG (DEFAULT TO NO) SKIPNUM: DS 2 ; PAGE NUMBER TO SKIP TO LNUM: DS 2 ; CURRENT LINE NUMBER PNUM: DS 2 ; CURRENT PAGE NUMBER HBUF: DS 100 ; BUFFER FOR HEADING ; if timeok TIMEBF: DS 100 ; BUFFER FOR TIME STAMP endif ; LNUMFL: DB 0 ; LINE NUMBER FLAG (DEFAULT TO NO) PNUMFL: DB 0FFH ; PAGE NUMBER FLAG (DEFAULT TO YES) EXACT: DB 0 ; EXACT PRINT FLAG (DEFAULT TO NO) FNPFL: DB 0FFH ; FILE NAME PRINT FLAG (DEFAULT TO YES) TIMEPFL: DB 0FFH ; TIME PRINT FLAG (DEFAULT TO YES) MULTFL: DB 0FFH ; MULTIPLE RUN FLAG (DEFAULT TO YES) INSPECT: DB 0 ; INSPECT FILES (DEFAULT TO NO) OFFSET: DB 0 ; OFFSET ON PAGE ; ; Start of Program ; START: LXI H,0 ; GET STACK PTR DAD SP SHLD STACK ; SAVE IT LXI SP,STACK ; SET SP CALL PUTUD ; SAVE CURRENT USER/DISK AWAY CALL RETUD ; GET CURRENT USER/DISK MOV A,B ; SAVE DISK STA DISK MOV A,C ; SAVE USER STA USER CALL ZGPINS ; INIT BUFFERS LXI H,TBUFF ; SAVE COMMAND LINE CALL CLINE SHLD CMDLNE ; SAVE PTR ; ; **** Banner of Program ; CALL PRINT DB 'PRINT III, Version ' DB VERS/10+'0','.',(VERS MOD 10)+'0',0 ; ; Check for Help Request ; LDA FCB+1 ; GET FIRST CHAR OF FILE NAME CPI ' ' ; NO FILE SPEC? JZ HELP CPI '/' ; OPTION CAUGHT? JNZ ECONT ; ; **** Print Help Information ; HELP: CALL PRINT DB CR,LF,'PRINT III Command --' db cr,lf,' PRINT III is invoked by the following command line:' db cr,lf,' PRINT file1,file2,...,filen o...' db cr,lf,'where each "filen" is an ambiguous file name and type' db cr,lf,'and "o" is zero or more of the following options:' db cr,lf,' E Exact Print (expand tabs, form feed, no line' db cr,lf,' or page numbers, no heading)' db cr,lf,' F Toggle File Name Display' db cr,lf,' H@head@ Specify Page Heading (@ is any printing char)' db cr,lf,' I Inspect and Select Files First' db cr,lf,' L Toggle Numbering of Each Line' db cr,lf,' M Toggle Multiple Runs (MR=No TOF Msg)' db cr,lf,' N Toggle Numbering of Each Page' db cr,lf,' Onn Offset Printout by nn Characters from Left' db cr,lf,' Snnnn Skip to Specified Page before Printing' ; if timeok db cr,lf,' T Toggle Time Display (if available) in header' endif ; db cr,lf,'Examples:' db cr,lf,' PRINT MYFILE.TXT,*.MAC LH''SAMPLE''' db cr,lf,' -- Number Lines, SAMPLE is Heading' db cr,lf,' PRINT MYFILE.* S25E' db cr,lf,' -- Skip to Page 25, Exact Print' db cr,lf,' At any time, ^C aborts PRINT III and ^X skips to next ' db 'file' DB CR,LF,0 ; ; RETURN TO OS ; RETURN: LHLD STACK ; GET OLD STACK SPHL ; SET IT RET ; ; PROGRAM'S INIT ROUTINE ; ECONT: CALL INIT ; PROG INIT ROUTINE ; ; EXTRACT FLAGS IF PRESENT ; LXI H,0 ; SET FILE COUNT SHLD FILECNT LHLD CMDLNE ; PT TO BUFFER ; ; SKIP TO FILE NAME STRING ; CALL SBLANK ; SKIP OVER BLANKS ; ; SKIP TO END OF FILE NAME STRING ; CALL SNBLANK ; SKIP OVER NON-BLANKS ; ; CHECK FOR LEADING SLASH ON OPTION AND SKIP IT IF SO ; OPT: CPI '/' ; OPTION CHAR? JNZ OPTION INX H ; SKIP SLASH ; ; PROCESS LIST OF OPTIONS ; OPTION: MOV A,M ; GET BYTE ORA A ; DONE? JZ DSPEC INX H ; PT TO NEXT CHAR CPI ' ' ; SKIP OVER SPACES JZ OPTION MOV C,A ; COMMAND IN C LXI D,OPTAB ; PT TO OPTION TABLE OPTL: LDAX D ; GET OPTION LETTER ORA A ; END OF TABLE? JZ HELP ; HELP IF SO CMP C ; MATCH? JZ OPTM ; PROCESS IF SO INX D ; PT TO NEXT ENTRY INX D INX D JMP OPTL ; ; PROCESS OPTION ; OPTM: PUSH H ; SAVE HL ON STACK LXI H,OPTION ; GET RETURN ADDRESS XTHL ; ... ON STACK AND RESTORE HL INX D ; PT TO ADDRESS LDAX D ; GET ADDRESS LOW MOV B,A ; ... IN B INX D LDAX D ; GET ADDRESS HIGH MOV D,A ; ... IN D MOV E,B ; LOW IN E PUSH D ; PUT ADDRESS ON STACK MOV A,C ; COMMAND IN A RET ; "CALL" OPTION ROUTINE ; ; **** PROGRAM INIT ROUTINE ; THIS ROUTINE IS USED BY THE PROGRAM TO PERFORM ANY INITS ; INIT: lxi h,dlnumfl ;copy defaults into buffers lxi d,lnumfl mvi b,8 ;8 bytes call moveb ;do copy xra a ;A=0 sta skipfl ;set no skip sta hbuf ;set no heading ; if timeok call time ;get time string lxi d,timebf ;store in buffer initt: mov a,m ;get byte stax d ;put byte inx h ;pt to next inx d ora a ;done? jnz initt endif ; RET ; ; **** OPTION TABLE ; EACH OPTION IS A CAPITAL LETTER OR SPECIAL CHAR FOLLOWED BY ; AN ADDRESS; THE TABLE IS TERMINATED BY A BINARY ZERO ; OPTAB: db 'E' dw optexact db 'F' dw optfn db 'H' dw opthd db 'I' dw optinsp db 'L' dw optln db 'M' dw optmult db 'N' dw optpn db 'O' dw optoffs db 'S' dw optskip ; if timeok db 'T' dw opttime endif ; DB 0 ; END OF TABLE ; ; Option: E (Toggle exact mode) ; optexact: lda exact ;get flag cma ;flip it sta exact ;put flag ret ; ; Option: F (Toggle file name display) ; optfn: lda fnpfl ;get flag cma ;flip it sta fnpfl ;put flag ret ; ; Option: H (Set Heading) ; opthd: lxi d,hbuf ;pt to heading buffer mov a,m ;get delim ora a ;none? rz mov b,a ;delim in B inx h ;pt to next char opthd1: mov a,m ;get next char ora a ;done? jz opthd3 cmp b ;done by trailing delim? jz opthd2 stax d ;save char inx h ;pt to next inx d jmp opthd1 opthd2: inx h ;skip over delim opthd3: xra a ;store ending 0 stax d ret ; ; Toggle Inspect Option ; optinsp: lda inspect ;flip flag cma sta inspect ret ; ; Set Line Number Flag ; optln: lda lnumfl ;flip flag cma sta lnumfl ret ; ; Set Multiple Run Flag ; optmult: lda multfl ;flip flag cma sta multfl ret ; ; Set Page Numbering Flag ; optpn: lda pnumfl ;flip flag cma sta pnumfl ret ; ; Set Page Offset ; optoffs: call eval10 ;get number mov a,e ;get low-order byte sta offset ;set offset ret ; ; Set Skip Flag and get number ; optskip: mvi a,0ffh ;set flag sta skipfl call eval10 ;get number xchg shld skipnum ;set page number to skip to xchg ;HL pts to next char mov a,d ;see if page number was zero ora e rnz xra a ;if zero, just turn off skip flag sta skipfl ret ; if timeok ; ; Set Time Flag ; opttime: lda timepfl ;flip flag cma sta timepfl ret ; endif ; ; BEGIN MOVING THROUGH FILE NAMES, SEPARATED BY COMMAS ; DSPEC: LHLD CMDLNE ; PT TO FIRST BYTE CALL SBLANK ; SKIP TO NON-BLANK ; ; MAJOR REENTRY POINT WHEN FILE SPECS ARE SEPARATED BY COMMAS ; HL PTS TO FIRST BYTE OF NEXT FILE SPEC ; DSPEC1: LXI SP,STACK ; RESET STACK CALL GETUD ; RESET USER IF NECESSARY LXI D,NTFCB ; PT TO FCB IN DE, PT TO FIRST CHAR OF FILE NAME IN HL CALL ZFNAME ; EXTRACT FILE NAME INTO FCB, AND GET DISK AND USER JZ DERR ; ERROR HANDLER SHLD NEXTCH ; SAVE PTR TO DELIMITER WHICH ENDED SCAN MOV A,B ; SAVE POSSIBLE DRIVE SPEC CPI 0FFH ; CURRENT DISK? JZ DSPEC2 LDA MDISK ; GET MAX DISK NUMBER DCR B ; ADJUST TO WITHIN BOUNDS 0-15 CMP B ; WITHIN BOUNDS? MOV A,B ; GET DISK NUMBER IN A JNC USPEC DERR: CALL PRINT DB CR,LF,'Invalid Disk Specification',0 JMP DRETURN ; ; SET CURRENT DISK ; DSPEC2: LDA DISK ;GET CURRENT DISK MOV B,A ;... IN B ; CHECK FOR USER NUMBER USPEC: MOV A,C ; GET NEW USER NUMBER CPI 0FFH ; DEFAULT USER? JZ USPEC1 CPI '?' ; ALL USERS NOT ALLOWED? JZ UERR LDA MUSER ; GET MAX USER NUMBER CMP C MOV A,C ; USER NUMBER IN A JNC FCT UERR: CALL PRINT DB CR,LF,'Invalid User Number',0 JMP DRETURN USPEC1: LDA USER ;GET CURRENT USER MOV C,A ;... IN C ; ; LOAD DIRECTORY AND PERFORM FUNCTION ; FCT: MOV A,B ; SAVE NEW DISK/USER AWAY STA CDISK ; CURRENT DISK MOV A,C STA CUSER ; CURRENT USER CALL LOGUD ; LOG INTO ACCOUNT CALL CODEND ; PT TO END OF CODE CALL RETUD ; GET USER NUMBER FOR DIRFS MVI A,11000000B ; SELECT SYS AND NON-SYS FILES ORA C ; OR IN USER NUMBER LXI D,NTFCB ; PT TO FCB CALL INITFCB ; INIT THE FCB CALL DIRFS ; LOAD DIR, SELECT FILES, PACK, AND ALPHABETIZE ; ; DETERMINE BEGINNING OF SCRATCH AREA (SCRATCH) AND SZIE IN PAGES (BCNT) ; PUSH H ; SAVE PTR AND COUNT PUSH B LXI D,ESIZE ; SET PTR TO NEXT FREE BLOCK FCTFRE: MOV A,B ; DONE? ORA C JZ FCTFR1 DAD D ; PT TO NEXT DCX B ; COUNT DOWN JMP FCTFRE FCTFR1: INR H ; NEXT PAGE MVI L,0 SHLD SCRATCH ; SET PTR TO SCRATCH AREA XCHG ; PTR IN DE LHLD BDOSE+1 ; COMPUTE BLOCK BUFFER SIZE MOV A,H ; ADJUST FOR ZCPR2 SUI 10 SUB D ; A=SIZE IN BLOCKS STA BCNT ; SET BLOCK COUNT POP B ; RESTORE AND SAVE REGS POP H ; ; ALLOW USER TO INSPECT FILES ; PUSH H PUSH B CALL ICHECK ; CHECK FOR INSPECT OPTION AND INSPECT IF SET POP B ; RESTORE COUNT AND PTR POP H ; ; PERFORM FUNCTION; HL PTS TO FILE AND BC CONTAINS NUMBER OF FILES ; FCTL: MOV A,B ; CHECK FOR COMPLETION (COUNT = 0) ORA C JZ FCTL1 DCX B ; COUNT DOWN LXI SP,STACK ; RESET STACK PUSH B ; SAVE COUNT AND POINTER PUSH H CALL FUNCTION ; PERFORM FUNCTION FCTLNXT: LXI SP,STACK-4 ; RESTORE STACK POP H ; GET PTR AND COUNT POP B LXI D,ESIZE ; PT TO NEXT ENTRY DAD D JMP FCTL ; ; CHECK FOR NEXT FILE SPEC ; FCTL1: CALL GETUD ; RETURN TO HOME USER/DISK LHLD NEXTCH ; GET PTR MOV A,M ; GET DELIM CPI ',' ; ANOTHER FILE? JNZ DRETURN INX H ; PT TO CHAR AFTER COMMA JMP DSPEC1 ; CONTINUE PROCESSING ; ; **** EMERGENCY ABORT ; ABORT: CALL PRINT DB CR,LF,'** PRINT III Abort **',CR,LF,0 CALL GETUD ; RETURN HOME AND FALL THRU TO DRETURN ; ; **** FUNCTION COMPLETE -- CLEANUP AND EXIT ; FILL THIS IN WITH CLEANUP CODE FOR EXIT ; DRETURN: JMP RETURN ; ; **** INSPECT FILES -- THIS ROUTINE IS TO PERFORM A FILE INSPECTION ; ON INPUT, HL PTS TO FIRST 16-BYTE ENTRY AND BC=NUMBER OF ENTRIES ; ICHECK: mov a,b ;any files? ora c rz push h ;save ptrs push b lxi d,esize ;size of entry ichk1: mvi m,0 ;clear MSBytes dad d ;pt to next dcx b ;count down mov a,b ;done? ora c jnz ichk1 pop b ;restore ptrs pop h lda inspect ;inspect? ora a ;0=no rz call print db cr,lf,'PRINT III File Inspect Mode',0 ichk2: call print db cr,lf,'Select ',0 call prfn ;print file name call print db ' -- (Y/N/Q=Select Rest/S=Skip Rest/other=Y)? ' db 0 call cin ;get response call caps ;capitalize call cout ;echo cpi 'Q' ;select rest? jz ichkyr cpi 'S' ;skip rest jz ichknr cpi 'N' ;no to this one? jnz ichk3 mvi m,0ffh ;set NO flag in file FCB ichk3: dad d ;pt to next one dcx b ;count down mov a,b ;done? ora c jnz ichk2 RET ; Check Rest of Files as Selected ichkyr: call print db cr,lf,' Rest of Files Selected',0 ret ; Check Rest of Files as NOT Selected ichknr: mvi m,0ffh ;set NO flag dad d ;pt to next dcx b ;count down mov a,b ;done? ora c jnz ichknr call print db cr,lf,' Rest of Files NOT Selected',0 ret ; ; **** FUNCTION -- MAIN FUNCTION OF TEMPLATE ; ON ENTRY, HL PTS TO NAME OF FILE (16 BYTES) AND USER IS LOGGED INTO ; DIRECTORY CONTAINING INDICATED FILE ; FUNCTION: ; ; FILE PRINT Routine -- Print the File Whose Name is Pointed to by ; HL; we are already logged into the correct directory ; mov a,m ;file selected? ora a ;0=yes rnz lda multfl ;multiple runs? ora a ;0=no jnz fprint ;go right into function call print db cr,lf,'File: ',0 call prfn ;print file name call print db ' -- Please Set Top of Form' db cr,lf,' Strike Any Key When Ready ',0 call cin ;get response cpi ctrlc ;abort? jz abort cpi ctrlx rz fprint: call prinit ;init print buffers call fload ;load buffer initially call prhead ;print heading line lhld scratch ;pt to first char in file shld nxtln ;set pointer to next line fprloop: call prline ;print line of file jnz fprloop ;done if EOF lda ltpp ;check for new page mov b,a lda lcount ;LTPP and Line Count are Equal if New Page cmp b ;equal? jnz fprlp1 call lcrlf ;advance 2 lines call lcrlf fprlp1: call page ;advance to top of next page ret ; ; Init Print Buffers and Print File Name ; prinit: lxi d,tfcb ;set up FCB mvi b,12 ;12 bytes call moveb lxi h,0 ;HL=0 shld lnum ;set line number inx h ;HL=1 shld pnum ;set page number lda ltpp ;set line count sta lcount call print db cr,lf,'Printing File ',0 lxi h,tfcb ;pt to FCB call prfn ;print file name ret ; ; FILE LOAD (FLOAD) Routine -- Initial Load of memory buffer ; fload: lxi d,tfcb ;pt to file fcb call initfcb ;init file's fcb call f$open ;open file for input jz fload1 ;open was OK call print db cr,lf,'File ',0 xchg ;HL pts to FCB call prfn ;print file name call print db ' NOT Found',0 pop d ;clear return address ret ;abort printout of this file ; ; This is an entry point for further memory loads of the file ; fload1: lda bcnt ;get number of blocks to load mov c,a ;... in C lhld scratch ;get address of first block to load into shld nxtblk ;set pointer to next block to load fload2: call rdblk ;read a block (128 bytes) jnz eof ;eof encountered? call rdblk ;read another block (128 bytes) jnz eof ;eof encountered? dcr c ;count down jnz fload2 lhld nxtblk ;pt to next byte to load mvi m,eold ;mark end of load ret eof: lxi d,tfcb ;close file call f$close lhld nxtblk ;ensure ^Z mvi m,ctrlz ret rdblk: lxi d,tfcb ;pt to FCB call f$read ;read next block ora a ;error? rnz lhld nxtblk ;get ptr to next block xchg ; as dest lxi h,tbuff ;ptr to DMA address mvi b,128 ;copy 128 bytes rdblk1: mov a,m ;get byte ani 7fh ;mask out msb stax d ;put byte inx h ;pt to next inx d dcr b ;count down jnz rdblk1 xchg ;new nxtblock shld nxtblk ret ; ; Line Print Routine ; Print Next Line with Optional Disk Load ; Input Parameter is NXTLN, which is the address of the first char ; on the next line ; Output Parameter is Zero Flag, with Z meaning done with print, NZ ; meaning more yet to print ; prline: call proffs ;print offset lhld lnum ;increment line number inx h shld lnum lhld nxtln ;pt to first char of next line mvi c,0 ;init char count mov a,m ;get first char of line cpi ctrlz ;EOF? cnz prlnum ;print line number (optional) prl1: mov a,m ;get char cpi eold ;end of load? jz prload cpi ctrlz ;eof? jz prexit inx h ;pt to next char cpi ctrli ;tab? jz prtab cpi cr ;? jz prcr cpi ff ;form feed? jz prff cpi lf ;end of line? jz prldn cpi ctrlh ;back space? jz prbs cpi ctrlg ;ring bell? jz prbell cpi del ;delete char? jz prl1 ;skip it cpi ' ' ;other control char? jc prl1 ;skip if other control char call prout ;print char inr c ;increment char count call eoltest ;check to see if at end of line and newline if so jmp prl1 ; ; End of Load Reached -- Load More of File from Disk ; prload: push b ;save char count call fload1 ;use load routine pop b ;get char count lhld scratch ;next byte is here jmp prl1 ;continue processing ; ; Tabulate ; prtab: mvi a,' ' ;space call prout inr c ;new char call eoltest ;process EOL mov a,c ;done? ani 7 jnz prtab ;continue tabulation jmp prl1 ;continue processing ; ; Exit with Zero Flag Set if Done ; prexit: xra a ;set zero flag ret ; ; Carriage Return -- Reset Character Count and Continue ; prcr: call prout ;send CR to printer mvi c,0 ;reset char count jmp prl1 ;continue processing ; ; Form Feed -- Advance to Top of Next Page ; prff: call page ;page eject with heading mvi c,0 ;reset char count jmp prl1 ;continue processing ; ; Line Feed -- End of Routine ; prldn: call prout ;echo LF to printer shld nxtln ;set ptr to first char of next line mvi a,0ffh ;set not done ora a ;set flags ret ; ; Backspace on Printer ; prbs: mov a,c ;check for beginning of line ora a jz prl1 ;continue if at BOL mvi a,ctrlh ;backspace call prout dcr c ;back up char position jmp prl1 ;continue ; ; Ring Bell on Printer ; prbell: call prout ;ring the bell jmp prl1 ;continue without advancing char position ; ; Test for End of Line and Process if so ; eoltest: lda offset ;get offset mov b,a ;... in B lda lwidth ;get line width sub b ;compute remaining width sui 4 ;4 chars less for continuation mark mov b,a ;result in B lda lnumfl ;line numbering (lines are 7 chars shorter if so) ora a ;0=no jz eolt1 mov a,b ;reduce by 7 for line numbers sui 7 mov b,a eolt1: mov a,b ;get line width cmp c ;there? rnz ;continue if not mov a,m ;get next char cpi cr ;new line next? rz ;continue if so cpi ctrlh ;backspace next? rz ;continue if so mvi a,' ' ;print continuation chars call prout mvi a,'<' call prout mvi a,'<' call prout mvi a,cr ;new line call prout mvi a,lf call prout mvi c,0 ;reset char position lda skipfl ;skipping? ora a ;0=no rnz lda lnumfl ;printing line numbers? ora a ;0=no rz call lprint db ' : ',0 ret ; ; Output a character to the printer ; A = Character ; prout: mov b,a ;char in B call condin ;check for abort jz prout1 cpi ctrlc ;abort? jz abort cpi ctrlx ;abort this one file? jz cxabort prout1: lda skipfl ;skipping? ora a ;set flags (Z=no skip=print char) mov a,b ;restore char cz lout ;send character to printer cpi lf ;special tests if it is a line feed rnz ;done if non-LF char lda lcount ;decrement line counter dcr a sta lcount rnz ; ; Paging Required ; Skip to top of next page; reset LCOUNT (Lines Left on Page Count); ; print header ; prout0: lda ltpp ;get number of text lines per page sta lcount ;set as new line count push h ;save ptr lhld pnum ;increment page number inx h shld pnum lda lspp ;get number of lines to skip per page call lineskp ;skip lines pop h ;restore ptr mov a,m ;check next character cpi ctrlz ;EOF? jnz prhead ;print 2-line heading if NOT EOF ret ; ; Abort current file with final page eject ; cxabort: lda lcount ;get count of remaining lines call lineskp ;skip lines lda lspp ;number of lines to skip per page call lineskp ;skip lines jmp fctlnxt ;continue with next file ; ; Skip out rest of page ; Form Feed Function ; page: lda lcount ;get count of remaining lines call lineskp ;skip lines jmp prout0 ;process top of new page ; ; Skip out lines on page ; A = number of lines to skip ; lineskp: mov b,a ;line count in B ora a ;any? rz lda skipfl ;skipping? ora a rnz lines1: mvi a,cr ;output new line to printer call lout mvi a,lf call lout dcr b ;count down jnz lines1 ret ; ; Print Line Number (optional) ; prlnum: lda skipfl ;skipping? ora a ;0=no rnz lda lnumfl ;get flag ora a ;0=don't number lines rz push h ;save ptr lhld lnum ;get line number call lhldc ;print line number call lprint ;print separator db ': ',0 pop h ;restore ptr ret ; ; Print 2-line heading and control skipping ; prhead: push h ;save ptr lda skipfl ;currently skipping? ora a ;0=no cnz skiptst ;test for shut off lda exact ;exact says no heading ora a ;0FFH=yes jnz prhead1 call proffs ;print offset lda pnumfl ;number pages? ora a ;0=no cnz prpnum ;print page heading and number lda fnpfl ;print file name? ora a ;0=no cnz prfname ;print file name ; if timeok ;time available? lda timepfl ;print time? ora a ;0=no cnz prtime ;print time endif ; lda hbuf ;print heading? ora a ;0=no cnz prhdg ;print heading prhead1: pop h ;restore ptr prhead2: lda skipfl ;skipping? ora a rnz call lcrlf ;new line jmp lcrlf ; ; Test for completion of skipping ; skiptst: lhld pnum ;get page number xchg ;... in DE lhld skipnum ;get page to skip to mov a,h ;compare them cmp d rnz mov a,l cmp e rnz xra a ;A=0 to stop skipping sta skipfl ;set flag ret ; ; Print Line Offset ; proffs: lda skipfl ;skipping? ora a rnz push b ;save BC lda offset ;get offset ora a ;any? jz proff2 mov c,a ;offset in B proff1: mvi a,' ' ;space over call prout dcr c ;count down jnz proff1 proff2: pop b ret ; ; Print Page Number ; prpnum: lda skipfl ;skipping? ora a rnz call lprint ;print header db 'Page ',0 lhld pnum ;print current page number call lhldc ;print as decimal ret ; ; Print File Name ; prfname: lda skipfl ;skipping? ora a rnz call prdash ;print separator lxi h,tfcb+1 ;pt to first char mvi b,8 ;8 chars call lfn1 mvi a,'.' call lout mvi b,3 ;3 chars call lfn1 ret lfn1: mov a,m ;get char ani 7fh ;mask call lout ;send to printer inx h ;pt to next dcr b ;count down jnz lfn1 ret ; ; Print Separator ; prdash: call lprint db ' -- ',0 ret ; if timeok ; ; Print Time ; prtime: lda skipfl ;skipping? ora a rnz call prdash ;print separator lxi h,timebf ;pt to time stamp call lpstr ;print ret ; endif ; ; Print Header ; prhdg: lda skipfl ;skipping? ora a rnz call prdash ;print separator lxi h,hbuf ;pt to heading call lpstr ;print ret ; ; UTILITIES ; SBLANK -- SKIP BLANKS PTED TO BY HL UNTIL NON-BLANK ENCOUNTERED; HL ; SNBLANK -- SKIP NON-BLANKS PTED TO BY HL UNTIL BLANK OR EOL; HL ; PRFN -- PRINT FILE NAME PTED TO BY HL; AFFECT NOTHING ; ; ; SKIP UNTIL NON-BLANK ; SBLANK: MOV A,M ; LOOK FOR BLANK INX H ; PT TO NEXT CPI ' ' ; BLANK? JZ SBLANK DCX H ; BACK UP RET ; ; SKIP UNTIL BLANK OR EOL ; SNBLANK: MOV A,M ; GET CHAR INX H ; PT TO NEXT CPI ' ' ; BLANK? JZ SNB1 ORA A ; EOL? JNZ SNBLANK SNB1: DCX H ; BACK UP RET ; ; PRINT FILE NAME PTED TO BY HL ; OUTPUT TO CON: ; PRFN: PUSH H ; SAVE REGS PUSH B CALL RETUD ; GET CURRENT USER/DISK MOV A,B ; PRINT DISK ADI 'A' ; LETTER CALL COUT MOV A,C ; PRINT USER CALL PADC CALL PRINT DB ': ',0 INX H ; PT TO FILE NAME MVI B,8 ; PRINT NAME CALL PRNT MVI A,'.' ; DECIMAL CALL COUT MVI B,3 ; PRINT TYPE CALL PRNT POP B ; GET REGS POP H RET ; ; PRINT CHARS PTED TO BY HL FOR B BYTES ; OUTPUT TO CON: ; PRNT: MOV A,M ; GET CHAR CALL COUT INX H ; PT TO NEXT DCR B ; COUNT DOWN JNZ PRNT RET ; ; BUFFERS ; DISK: DS 1 ; HOME DISK NUMBER USER: DS 1 ; HOME USER NUMBER CDISK: DS 1 ; CURRENT DISK NUMBER CUSER: DS 1 ; CURRENT USER NUMBER CMDLNE: DS 2 ; PTR TO COMMAND LINE STRING NEXTCH: DS 2 ; PTR TO NEXT CHAR IN MULTIFILE COMMAND LINE FILECNT: DS 2 ; COUNT OF NUMBER OF FILES RENAMED SCRATCH: DS 2 ; ADDRESS OF FIRST FREE BYTE BCNT: DS 1 ; NUMBER OF PAGES IN SCRATCH AREA NTFCB: DS 36 ; FCB FOR NEW FILE ; ; PRINT3 Buffers ; tfcb: ds 36 ; FCB for current file nxtblk: ds 2 ; pointer to next block to load nxtln: ds 2 ; pointer to next line to read lcount: ds 1 ; count of text lines left on page ; ; Stack ; DS 100 ; STACK AREA STACK: DS 2 ; OLD STACK PTR END