; ; PROGRAM: PRINT III (PRINT) ; VERSION: 2.0 ; DATE: 18 May 84 ; AUTHOR: RICHARD CONN ; PREVIOUS VERSIONS: 1.3 (17 May 83) ; PREVIOUS VERSIONS: 1.2 (26 Apr 83), 1.1 (26 Apr 83), 1.0 (22 Apr 83) ; VERS equ 20 z3env SET 0f400h FALSE equ 0 TRUE equ NOT FALSE timeok equ FALSE ;TRUE to enable TIME feature, FALSE to disable ; ; PRINT is THE file print utility for ZCPR3. Installable by Z3INS, ; PRINT provides a wide range of options for the user. First, PRINT allows ; the user to employ wild cards and file name lists (lists of files separated ; by commas, like: file1,file2,file3,...). Second, PRINT 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 ; ; ; BASIC SYSLIB ROUTINES NEEDED BY PRINT ; ESIZE EQU 16 ; SIZE OF DIR ENTRY (FROM SYSLIB DIRF ROUTINE) EXT DIRQS ; DIRECTORY PROCESSOR EXT DIRPACK ; PACK DIRECTORY EXT Z3INIT ; INIT BUFFERS EXT ZFNAME ; FILE NAME PROCESSOR EXT Z3LOG ; LOG INTO DIR EXT GETPRT ; GET PRINTER DATA EXT INITFCB ; INIT FCB EXT RETUD ; RETURN CURRENT USER/DISK EXT PUTUD ; SAVE CURRENT USER/DISK EXT GETUD ; RESTORE CURRENT USER/DISK EXT EPRINT ; 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 ; ; Environment Definition ; if z3env ne 0 ; ; External ZCPR3 Environment Descriptor ; jmp start db 'Z3ENV' ;This is a ZCPR3 Utility db 1 ;External Environment Descriptor z3eadr: dw z3env start: lhld z3eadr ;pt to ZCPR3 environment ; else ; ; Internal ZCPR3 Environment Descriptor ; MACLIB Z3BASE.LIB MACLIB SYSENV.LIB z3eadr: jmp start SYSENV start: lxi h,z3eadr ;pt to ZCPR3 environment endif ; ; Start of Program -- Initialize ZCPR3 Environment ; call z3init ;initialize the ZCPR3 Env and the VLIB Env jmp startp ; ; Special Buffer Area ; LWIDTH: DB 0 ; WIDTH OF LINE LTPP: DB 0 ; LINES OF TEXT PER PAGE LSPP: DB 0 ; LINES TO SKIP PER PAGE LFF: DB 0 ; FORM FEED FLAG (0=NO) ; ; NOTE: LTPP + LSPP + 2 (HEADER SIZE) = TOTAL LINES PER PAGE ON PRINTER ; 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 2 ; PTR TO BUFFER FOR HEADING ; if timeok TIMEBF: DS 2 ; PTR TO 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 ; STARTP: LXI H,0 ; GET STACK PTR DAD SP SHLD STACK ; SAVE IT CALL CODEND ; DETERMINE FREE SPACE SHLD CMDLNE ; SAVE PTR TO COMMAND LINE LXI D,100H ; BUFFER SIZE DAD D SHLD HBUF ; BUFFER FOR HEADING ; IF TIMEOK DAD D SHLD TIMEBF ; BUFFER FOR TIME DATA ENDIF ; DAD D SHLD DIRBUF ; PTR TO DIR BUFFER SPHL ; SET TOP OF STACK CALL PUTUD ; SAVE CURRENT USER/DISK AWAY CALL GETPRT ; GET PRINTER DATA MOV A,M ; GET PRINTER WIDTH STA LWIDTH INX H INX H MOV A,M ; GET NUMBER OF LINES OF TEXT STA LTPP MOV B,A ; ... IN B DCX H MOV A,M ; GET NUMBER OF LINES ON PAGE SUI 2 SUB B ; ADJUST FOR PAGING DATA STA LSPP ; NUMBER OF LINES TO SKIP PER PAGE INX H INX H MOV A,M ; GET FORM FEED FLAG STA LFF LHLD CMDLNE ; PT TO COMMAND LINE SAVE AREA LXI D,TBUFF+1 ; SAVE COMMAND LINE XCHG MVI B,80H ; SIZE OF BUFFER CALL MOVEB ; ; **** Banner of Program ; CALL EPRINT 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 EPRINT db cr,lf,' PRINT file1,file2,...,filen o...' DB cr,lf,'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 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 and ^X skips to next ' db 'file' DB 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 ; 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 ; ; SKIP TO OPTION CHAR ; CALL SBLANK ; ; 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 push h lhld hbuf ;pt to heading mov m,a ;set no heading pop h ; if timeok call time ;get time string xchg lhld timebf ;store in buffer xchg 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: xchg lhld hbuf ;pt to heading buffer xchg 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: SHLD NEXTCH ; SAVE PTR TO NEXT CHAR LHLD DIRBUF ; RESET STACK SPHL CALL GETUD ; RESET USER IF NECESSARY LXI D,FCB ; PT TO FCB IN DE, PT TO FIRST CHAR OF FILE NAME IN HL MVI A,0 ; SELECT DIR BEFORE DU LHLD NEXTCH ; GET PTR TO NEXT CHAR CALL ZFNAME ; EXTRACT FILE NAME INTO FCB, AND GET DISK AND USER SHLD NEXTCH ; SAVE PTR TO DELIMITER WHICH ENDED SCAN ; ; LOAD DIRECTORY AND PERFORM FUNCTION ; FCT: LXI D,FCB ; PT TO FCB CALL Z3LOG ; LOG INTO IT LXI D,FCB ; PT TO FCB CALL INITFCB ; INIT THE FCB LHLD DIRBUF ; PT TO DIR BUFFER AREA MVI A,11000000B ; SELECT SYS AND NON-SYS FILES CALL DIRQS ; LOAD DIR, SELECT FILES, PACK, AND ALPHABETIZE ; ; DETERMINE BEGINNING OF SCRATCH AREA (SCRATCH) AND SIZE 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 ZCPR3 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 SHLD NFPTR MOV H,B MOV L,C SHLD NFCNT LHLD NFPTR ; PT TO FILE CALL FUNCTION ; PERFORM FUNCTION FCTLNXT: LHLD DIRBUF ; RESET STACK SPHL LHLD NFCNT ; RESET FILE COUNT MOV B,H MOV C,L LHLD NFPTR ; RESET FILE PTR 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 EPRINT DB CR,LF,'** PRINT 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 eprint db cr,lf,'--- PRINT File Inspect Mode ---' db cr,lf,' Option Function' db cr,lf,' Y (def) Select File' db cr,lf,' N Don''t Select File' db cr,lf,' Q Select Rest of Files' db cr,lf,' S Skip Rest of Files' db cr,lf,0 ichk2: call eprint db cr,lf,'Select ',0 call prfn ;print file name call eprint db ' -- (Y/N/Q/S)? ',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 eprint 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 eprint 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 eprint db cr,lf,'File: ',0 call prfn ;print file name call eprint db ' -- Set Top of Form ',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 eprint 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 eprint db cr,lf,'File ',0 xchg ;HL pts to FCB call prfn ;print file name call eprint 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 mvi b,3 ;see if CR is one of next 3 chars push h eolt2: inx h ;pt to next mov a,m ;get char cpi cr jz eolt2a ;yes, it is dcr b ;count down jnz eolt2 pop h ;restore HL jmp eolt3 eolt2a: pop h ;restore HL ret ;allow to continue eolt3: 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 call proffs ;print offset if any lda lnumfl ;printing line numbers? ora a ;0=no rz call lprint ;print blank for line number 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 lff ;form feed done? ora a ;0=no lda lspp ;number of lines to skip per page cz lineskp ;skip lines if no previous FF jmp fctlnxt ;continue with next file ; ; Skip out rest of page ; Form Feed Function ; page: lda lff ;form feed in use ora a ;0=no jnz prout0 ;process top of new page if form feed in use 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 lda lff ;form feed available? ora a ;0=no jnz lines2 lines1: call lcrlf ;new line dcr b ;count down jnz lines1 ret lines2: call lcrlf ;new line mvi a,ff ;output form feed to printer jmp lout ; ; 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 ; push h lhld hbuf ;pt to heading buffer mov a,m ;print heading? pop h 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 lhld timebf ;pt to time stamp call lpstr ;print ret ; endif ; ; Print Header ; prhdg: lda skipfl ;skipping? ora a rnz call prdash ;print separator lhld 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 EPRINT 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 ; CMDLNE: DS 2 ; PTR TO COMMAND LINE STRING DIRBUF: DS 2 ; PTR TO DIRECTORY BUFFER NFPTR: DS 2 ; PTR TO NEXT FILE NFCNT: DS 2 ; NEXT FILE COUNT NEXTCH: DS 2 ; PTR TO NEXT CHAR IN MULTIFILE COMMAND LINE SCRATCH: DS 2 ; ADDRESS OF FIRST FREE BYTE BCNT: DS 1 ; NUMBER OF PAGES IN SCRATCH AREA ; ; 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 ; STACK: DS 2 ; OLD STACK PTR END