; ; PROGRAM: PHELP ; AUTHOR: Richard Conn ; VERSION: 2.0 ; DATE: 28 Apr 83 ; PREVIOUS VERSIONS: None ; DERIVATION: PHELP 1.2 (12 July 80) ; VERS equ 20 FALSE EQU 0 TRUE EQU NOT FALSE timeok equ FALSE ;TRUE if TIME enabled, FALSE if not ; ; PHELP is used to print out a HLP file. It breaks pages on each ; information section and ignores form feeds, so the data is presented ; in a sequential fashion. It is very convenient to provide online ; documentation in the form of HLP files, and this utility allows the user ; to readily print out this documentation. PHELP is preferred over PRINT3 ; for printing HLP files because of its knowledge of their structure and ; its special way of handling them. ; ; PHELP is invoked by a command line of the following form: ; PHELP file1,file2,...,filen o... ; where each "filen" is an ambiguous file name and "o" is zero or more of ; the following options: ; 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 ; Snnnn Skip to Specified Page ; Printing begins at the indicated page ; T Toggle Time Display ; Time/Date information is optionally included ; in the page header ; ; ; This program is Copyright (c) 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 ; C$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 AS DECIMAL CHARS EXT COUT ; CONSOLE OUTPUT ROUTINE EXT CST ; CONSOLE STATUS 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 ext lcrlf ext lpstr ext lprint ext lout ext lhldc ext condin ext moveb ; if timeok ext time endif ; ; ; Insert Function-Required Library References Here ; ; ; 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'-'@' CTRLS EQU 'S'-'@' CTRLX EQU 'X'-'@' CTRLZ EQU 'Z'-'@' eold equ 0FFH ;End of Load Indicator ; ; Branch to Start of Program ; JMP T$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 ; PRINTER LINE WIDTH 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 ; DLNUMFL: DB 0 ; LINE NUMBER FLAG (DEFAULT TO NO) DTIMEPFL: DB 0FFH ; TIME PRINT FLAG (DEFAULT TO YES) DINSPECT: DB 0 ; INSPECT FILES (DEFAULT TO NO) ; ; WORKING BUFFERS ; LNUMFL: DB 0 ; LINE NUMBER FLAG TIMEPFL: DB 0FFH ; TIME PRINT FLAG INSPECT: DB 0 ; INSPECT FLAG 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 ; ; Start of Program ; T$START: LXI H,0 ; GET STACK PTR DAD SP SHLD V$STACK ; SAVE IT LXI SP,V$STACK ; SET SP XRA A ; A=0 STA V$INSPECT ; TURN OFF FILE INSPECTION CALL PUTUD ; SAVE CURRENT USER/DISK AWAY CALL RETUD ; GET CURRENT USER/DISK MOV A,B ; SAVE DISK STA V$DISK MOV A,C ; SAVE USER STA V$USER CALL ZGPINS ; INIT BUFFERS LXI H,TBUFF ; SAVE COMMAND LINE CALL CLINE SHLD V$CMDLNE ; SAVE PTR ; ; Banner of Program ; CALL BANNER ; PRINT BANNER PROVIDED BY USER ; ; Check for Help Request ; LDA FCB+1 ; GET FIRST CHAR OF FILE NAME CPI ' ' ; NO FILE SPEC? JZ T$HELPENT CPI '/' ; OPTION CAUGHT? JNZ T$ECONT ; ; Print Help Information ; T$HELPENT: CALL HELP ; PRINT PROGRAM'S HELP MESSAGE ; ; RETURN TO OS ; T$RETURN: CALL DINIT ; DEINIT PROGRAM LHLD V$STACK ; GET OLD STACK SPHL ; SET IT RET ; ; PROGRAM'S INIT ROUTINE ; T$ECONT: CALL INIT ; PROG INIT ROUTINE ; ; EXTRACT FLAGS IF PRESENT ; LXI H,0 ; SET FILE COUNT SHLD V$FILECNT LHLD V$CMDLNE ; PT TO BUFFER ; ; SKIP TO FILE NAME STRING ; CALL T$SBLANK ; SKIP OVER BLANKS ; ; SKIP TO END OF FILE NAME STRING ; CALL T$SNBLANK ; SKIP OVER NON-BLANKS ; ; CHECK FOR LEADING SLASH ON OPTION AND SKIP IT IF SO ; T$OPT: CPI '/' ; OPTION CHAR? JNZ T$OPTION INX H ; SKIP SLASH ; ; PROCESS LIST OF OPTIONS ; T$OPTION: MOV A,M ; GET BYTE ORA A ; DONE? JZ T$DSPEC INX H ; PT TO NEXT CHAR CPI ' ' ; SKIP OVER SPACES JZ T$OPTION MOV C,A ; COMMAND IN C LXI D,OPTAB ; PT TO OPTION TABLE T$OPTL: LDAX D ; GET OPTION LETTER ORA A ; END OF TABLE? JZ T$HELPENT ; HELP IF SO CMP C ; MATCH? JZ T$OPTM ; PROCESS IF SO INX D ; PT TO NEXT ENTRY INX D INX D JMP T$OPTL ; ; PROCESS OPTION ; T$OPTM: PUSH H ; SAVE HL ON STACK LXI H,T$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 ; ; BEGIN MOVING THROUGH FILE NAMES, SEPARATED BY COMMAS ; T$DSPEC: LHLD V$CMDLNE ; PT TO FIRST BYTE CALL T$SBLANK ; SKIP TO NON-BLANK ; ; MAJOR REENTRY POINT WHEN FILE SPECS ARE SEPARATED BY COMMAS ; HL PTS TO FIRST BYTE OF NEXT FILE SPEC ; T$DSPEC1: LXI SP,V$STACK ; RESET STACK CALL GETUD ; RESET USER IF NECESSARY LXI D,V$NTFCB ; PT TO FCB IN DE, PT TO 1ST CHAR OF FN IN HL CALL ZFNAME ; EXTRACT FILE NAME INTO FCB, AND GET DISK AND USER JZ T$DERR ; ERROR HANDLER push b ;save disk/user push h ;save others push d lxi h,hlptyp ;optionally set default HLP type lxi d,V$NTFCB+9 ;check for any specified ldax d ;' ' means none cpi ' ' jnz hlpskp mvi b,3 ;3 chars call moveb hlpskp: pop d ;restore others pop h pop b ;restore disk/user SHLD V$NEXTCH ; SAVE PTR TO DELIMITER WHICH ENDED SCAN MOV A,B ; SAVE POSSIBLE DRIVE SPEC CPI 0FFH ; CURRENT DISK? JZ T$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 T$USPEC T$DERR: CALL PRINT DB CR,LF,'Invalid Disk Specification',0 JMP T$RETURN ; ; SET CURRENT DISK ; T$DSPEC2: LDA V$DISK ;GET CURRENT DISK MOV B,A ;... IN B ; CHECK FOR USER NUMBER T$USPEC: MOV A,C ; GET NEW USER NUMBER CPI 0FFH ; DEFAULT USER? JZ T$USPEC1 CPI '?' ; ALL USERS NOT ALLOWED? JZ T$UERR LDA MUSER ; GET MAX USER NUMBER CMP C MOV A,C ; USER NUMBER IN A JNC T$FCT T$UERR: CALL PRINT DB CR,LF,'Invalid User Number',0 JMP T$RETURN T$USPEC1: LDA V$USER ;GET CURRENT USER MOV C,A ;... IN C ; ; LOAD DIRECTORY AND PERFORM FUNCTION ; T$FCT: MOV A,B ; SAVE NEW DISK/USER AWAY STA V$CDISK ; CURRENT DISK MOV A,C STA V$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,V$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 SIZE IN PAGES (BCNT) ; PUSH H ; SAVE PTR AND COUNT PUSH B LXI D,C$ESIZE ; SET PTR TO NEXT FREE BLOCK T$FCTFRE: MOV A,B ; DONE? ORA C JZ T$FCTFR1 DAD D ; PT TO NEXT DCX B ; COUNT DOWN JMP T$FCTFRE T$FCTFR1: INR H ; NEXT PAGE MVI L,0 SHLD V$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 V$BCNT ; SET BLOCK COUNT POP B ; RESTORE AND SAVE REGS POP H ; ; ALLOW USER TO INSPECT FILES ; PUSH H PUSH B CALL T$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 ; T$FCTL: MOV A,B ; CHECK FOR COMPLETION (COUNT = 0) ORA C JZ T$FCTL1 DCX B ; COUNT DOWN LXI SP,V$STACK ; RESET STACK PUSH B ; SAVE COUNT AND PTR PUSH H MOV A,M ; SELECTED FILE? ORA A ; 0=YES CZ FUNCTION ; PERFORM FUNCTION ; ; ENTRY POINT TO SKIP TO NEXT FILE IN LIST ; E$FCTLNXT: LXI SP,V$STACK-4 ; RESTORE STACK POP H ; RESTORE PTR POP B ; RESTORE COUNT LXI D,C$ESIZE ; PT TO NEXT ENTRY DAD D JMP T$FCTL ; ; CHECK FOR NEXT FILE SPEC ; T$FCTL1: CALL GETUD ; RETURN TO BASE USER/DISK LHLD V$NEXTCH ; GET PTR MOV A,M ; GET DELIM CPI ',' ; ANOTHER FILE? JNZ T$RETURN INX H ; PT TO CHAR AFTER COMMA JMP T$DSPEC1 ; CONTINUE PROCESSING ; ; INSPECT FILES -- THIS ROUTINE IS TO PERFORM A FILE INSPECTION ; ON INPUT, HL PTS TO FIRST 16-BYTE ENTRY AND BC=NUMBER OF ENTRIES ; T$ICHECK: MOV A,B ;ANY FILES? ORA C ;0=NO RZ PUSH H ;SAVE PTRS PUSH B LXI D,C$ESIZE ;SIZE OF ENTRY T$ICHK1: MVI M,0 ;CLEAR MSBYTES DAD D ;PT TO NEXT DCX B ;COUNT DOWN MOV A,B ;DONE? ORA C JNZ T$ICHK1 POP B ;RESTORE PTRS POP H LDA V$INSPECT ;INSPECT? ORA A ;0=NO RZ CALL PRINT DB CR,LF,'File Inspect Mode',0 T$ICHK2: CALL PRINT DB CR,LF,'Select ',0 CALL E$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 T$ICHKYR CPI 'S' ;SKIP REST JZ T$ICHKNR CPI 'N' ;NO TO THIS ONE? JNZ T$ICHK3 MVI M,0FFH ;SET NO FLAG IN FILE FCB T$ICHK3: DAD D ;PT TO NEXT ONE DCX B ;COUNT DOWN MOV A,B ;DONE? ORA C JNZ T$ICHK2 RET ; CHECK REST OF FILES AS SELECTED T$ICHKYR: CALL PRINT DB CR,LF,' Rest of Files Selected',0 RET ; CHECK REST OF FILES AS NOT SELECTED T$ICHKNR: MVI M,0FFH ;SET NO FLAG DAD D ;PT TO NEXT DCX B ;COUNT DOWN MOV A,B ;DONE? ORA C JNZ T$ICHKNR CALL PRINT DB CR,LF,' Rest of Files NOT Selected',0 RET ; ; UTILITIES ; T$SBLANK -- SKIP BLANKS PTED TO BY HL UNTIL NON-BLANK ENCOUNTERED; HL ; T$SNBLANK -- SKIP NON-BLANKS PTED TO BY HL UNTIL BLANK OR EOL; HL ; E$PRFN -- PRINT FILE NAME PTED TO BY HL; AFFECT NOTHING ; ; SKIP UNTIL NON-BLANK ; T$SBLANK: MOV A,M ; LOOK FOR BLANK INX H ; PT TO NEXT CPI ' ' ; BLANK? JZ T$SBLANK DCX H ; BACK UP RET ; ; SKIP UNTIL BLANK OR EOL ; T$SNBLANK: MOV A,M ; GET CHAR INX H ; PT TO NEXT CPI ' ' ; BLANK? JZ T$SNB1 ORA A ; EOL? JNZ T$SNBLANK T$SNB1: DCX H ; BACK UP RET ; ; PRINT FILE NAME PTED TO BY HL ; OUTPUT TO CON: ; E$PRFN: PUSH H ; SAVE REGS PUSH B CALL RETUD ; GET CURRENT USER/DISK MOV A,B ; GET DISK NUMBER ADI 'A' ; CONVERT TO LETTER CALL COUT ; PRINT LETTER MOV A,C ; GET USER NUMBER CALL PADC ; PRINT USER NUMBER CALL PRINT DB ': ',0 INX H ; PT TO FILE NAME MVI B,8 ; PRINT NAME CALL T$PRNT MVI A,'.' ; DECIMAL CALL COUT MVI B,3 ; PRINT TYPE CALL T$PRNT POP B ; GET REGS POP H RET ; ; PRINT CHARS PTED TO BY HL FOR B BYTES ; OUTPUT TO CON: ; T$PRNT: MOV A,M ; GET CHAR CALL COUT INX H ; PT TO NEXT DCR B ; COUNT DOWN JNZ T$PRNT RET ;*********************************************** ;* Application-Specific Section ;*********************************************** ;**************************************************** ;* ;* Function-Specific Routines ;* These routines need to be customized for the ;* specific function being performed. These, in ;* effect, implement the function. Other Entry Points ;* useful to the programmer are: ;* E$FCTLNXT -- Clean Abort of Current ;* Processing and Skip ;* to Next File in List; ;* This is a Clean Way to ;* Abort FUNCTION for the ;* Next File ;* E$PRFN -- Print File Name Pted to ;* by HL; No Regs Affected ;* ;**************************************************** ; ; **** EMERGENCY ABORT ; ABORT: CALL PRINT db cr,lf,'** PHELP Abort **' DB 0 CALL GETUD ; RETURN HOME JMP T$RETURN ; ; **** BANNER -- PRINT BANNER FOR PROGRAM (PROGRAM NAME ET AL) ; BANNER: CALL PRINT db 'PHELP Version ' db (vers/10)+'0','.',(vers mod 10)+'0' DB 0 RET ; ; **** HELP -- PRINT PROGRAM'S HELP MESSAGE ; HELP: CALL PRINT db cr,lf,' PHELP is used to print out HLP Files. It is invoked' db cr,lf,'by a command line of the following form: ' db cr,lf,' PHELP file1,file2,...,filen o...' db cr,lf,'where "filen" is an ambiguous file name and "o" is zero' db cr,lf,'or more of the following options:' db cr,lf,' H@head@ -- Use "head" as header on every page' db cr,lf,' (@ is any character, used as a delimiter)' db cr,lf,' I -- Inspect Files for Printing' db cr,lf,' L -- Number Each Line' db cr,lf,' Snn -- Skip to Page nn and Start Printing' db cr,lf,' T -- Toggle Time Display' db cr,lf db cr,lf,' PHELP assumes HLP to be the file type if none is given' DB 0 RET ; ; **** PROGRAM INIT ROUTINE ; THIS ROUTINE IS USED BY THE PROGRAM TO PERFORM ANY NECESSARY ; INITIALIZATIONS ; INIT: lxi h,dlnumfl ;copy defaults into buffers lxi d,lnumfl mvi b,3 ;3 bytes call moveb 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 inx h ;pt to next inx d ora a ;done? jnz initt endif ; RET ; ; **** FUNCTION COMPLETE -- CLEANUP AND EXIT ; FILL THIS IN WITH CLEANUP CODE FOR EXIT ; DINIT: RET ; ; **** OPTION TABLE USED TO PROCESS COMMAND LINE ; EACH OPTION IS A CAPITAL LETTER OR SPECIAL CHAR FOLLOWED BY ; AN ADDRESS; THE TABLE IS TERMINATED BY A BINARY ZERO ; OPTAB: DB 'I' ; FILE INSPECTION OPTION DW OPTINSP ; REMOVE THESE TWO LINES AND THE FOLLOWING ROUTINE ; IF YOU DO NOT WANT FILE INSPECTION OPTION IN ; COMMAND LINE db 'H' ;heading dw opthead db 'L' ;line numbers dw optln db 'S' ;skip dw optskip ; if timeok db 'T' ;time display dw opttime endif ; DB 0 ; END OF TABLE ; ; **** OPTION ROUTINES ; EACH ROUTINE IS PROVIDED THE OPTION CHARACTER IN THE A REGISTER ; AND A POINTER TO THE NEXT CHARACTER IN THE COMMAND LINE IN THE ; HL REGISTER PAIR; ONLY HL NEED TO BE PRESERVED (WITH OPTIONAL ; ADVANCEMENT TO THE NEXT OPTION) ON EXIT ; OPTINSP: MVI A,0FFH ; TURN ON FILE INSPECTION OPTION STA V$INSPECT ; THIS IS PROVIDED AS A SAMPLE ROUTINE ; AND FOR THE INDICATED FUNCTION RET ; ; Option: H (Set Heading) ; opthead: 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? 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 ; ; Option: L (Set Line Numbering) ; optln: lda lnumfl ;flip flag cma sta lnumfl ret ; ; Option: S (Skip Lines) ; 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, turn off skip flag sta skipfl ret ; if timeok ; ; Set Time Flag ; opttime: lda timepfl ;flip flag cma sta timepfl ret ; endif ; ; **** 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: ; ; HELP FILE PRINT Routine -- Print the Help File Whose Name is Pointed to by ; HL; we are already logged into the correct directory ; call prinit ;init print buffers call fload ;load buffer initially call prhead ;print heading line lhld V$SCRATCH ;pt to first char in file shld nxtln ;set pointer to next line mvi a,0ffh ;first line sta firstf call prline ;print first line (special case) xra a ;not first line now sta firstf fprloop: call prline ;print line of file jnz fprloop ;done if EOF 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 Help File ',0 lxi h,tfcb ;pt to FCB call e$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 e$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 V$BCNT ;get number of blocks to load mov c,a ;... in C lhld V$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: 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) lda firstf ;first char? ora a ;0=no jnz prl1 mov a,m ;get first char of line cpi ':' ;new information section? jz prff ;set it as such 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 prldn cpi ff ;form feed? jz prldn cpi lf ;end of line? jz prl1 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 V$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 ; ; 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 ; ; Carriage Return -- End of Routine ; prldn: mov a,m ;skip to non-LF cpi lf jnz prldn1 inx h ;skip to first char of next line prldn1: mvi a,cr ;output call prout mvi a,lf ;output 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 lwidth ;get line 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? cnz 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 e$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 call prpnum ;print page heading and number call e$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 pop h ;restore ptr 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 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 ; e$prfname: lda skipfl ;skipping? ora a rnz call lprint ;print separator db ' -- Help File: ',0 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 RET ; ; **** BUFFERS -- PLACE APPLICATION-SPECIFIC BUFFERS HERE ; firstf: ds 1 ;first line in file flag tfcb: ds 36 ;FCB for current file nxtblk: ds 2 ;ptr to next block to load nxtln: ds 2 ;ptr to next line to read lcount: ds 1 ;count of text lines left on page hlptyp: db 'HLP' ;file type of HLP file ;*********************************************** ;* End of Application-Specific Section ;*********************************************** ; ; BUFFERS ; V$DISK: DS 1 ; HOME DISK NUMBER V$USER: DS 1 ; HOME USER NUMBER V$CDISK: DS 1 ; CURRENT DISK NUMBER V$CUSER: DS 1 ; CURRENT USER NUMBER V$CMDLNE: DS 2 ; PTR TO COMMAND LINE STRING V$NEXTCH: DS 2 ; PTR TO NEXT CHAR IN MULTIFILE COMMAND LINE V$FILECNT: DS 2 ; COUNT OF NUMBER OF FILES RENAMED V$SCRATCH: DS 2 ; ADDRESS OF FIRST BYTE OF SCRATCH AREA V$BCNT: DS 1 ; NUMBER OF PAGES IN SCRATCH AREA V$INSPECT: DS 1 ; INSPECT FLAG V$NTFCB: DS 36 ; FCB FOR NEW FILE ; ; Stack ; DS 100 ; STACK AREA V$STACK: DS 2 ; OLD STACK PTR END