home *** CD-ROM | disk | FTP | other *** search
- PAGE 75,132
- TITLE "LASERLST - List file to HP LaserJet"
- ;
- ; The original LASERLST program by Michael Holmes and Bob Flanders formats
- ; and prints two 80-column pages side-by-side on one 8.5x11 inch page on
- ; a HP LaserJet printer. The program thus allows you to cut your paper
- ; usage in half.
- ;
- ; The LASER4UP program is the LASERLST program modified to send what would
- ; be every other *physical* page to a disk file with all the appropriate
- ; LaserJet control codes. This allows you to print on the front side of
- ; each page, then put the pages back into the original order, flip them
- ; over in the printer, and then print every other physical page on the
- ; back. This cuts your paper usage to one-fourth of what it would have
- ; been without LASERLST or LASER4UP. LASERLST would work fine without
- ; modification if everyone was using the LaserJet IID, which has the
- ; capability of printing on the back side of the page automatically.
- ; Unfortunately, this is not so... LASER4UP requires re-sorting the
- ; printed output and re-inserting that back into the printer, so it's a bit
- ; more trouble to use than LASERLST, but it does have the advantage of
- ; minimizing the paper required to print your documentation or program
- ; listings.
- ;
- ; Original LASERLST program by Michael Holmes and Bob Flanders
- ; Modified LASER4UP program by Bob White 3/28/89.
- ; Minor bug fixed by Bob White 8/17/89 (program lost track of pages
- ; when a file had only one page in it and the program was printing
- ; multiple files.)
- ;
- ; Minor bug fixed by Bob White on 2/12/90 to let the program work on
- ; a LaserJet IIP printer. Reversed two escape sequences. See PC Mag,
- ; 2/27/90, Vol 9 #4, P. 338 for more info.
- ;
- CSEG SEGMENT PARA PUBLIC 'CODE'
- ASSUME CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
- ORG 100H
-
- START: JMP MAIN ; go to start of program
-
- HEADER_MSG DB "LaserLst 1.0 (c) 1989 Ziff Communications Co.", 0DH,0AH
- DB "PC Magazine",254," Michael Holmes & Bob Flanders",0DH,0AH
- DB "Laser4up 1.1",254," Bob White 2/12/90",0Dh,0Ah
- CRLF DB 0DH,0AH
- DOLLAR DB "$"
- ; ---------------------------------------------------------------------------
- ; Initialized work areas
- ; ---------------------------------------------------------------------------
- ARG1 DW 0 ; addr of first argument
- ARG2 DW 0 ; addr of second argument
- CHandle DW 0 ;; Current output handle
- NHandle DW 0 ;; Next output handle
- BHandle DW 0 ;; Back side file handle
- PHANDLE DW 4 ; printer handle (stdprn)
- TABCOL DW 8 ; tab width
- NEWPAGE DB 0 ; new page requested flag
- HPSTATE DB 0 ; printer state (1 = initialized)
- BackFile DB "LASER4UP.TXT",0 ;; ASCIIZ back side file name
-
- TITLE_ DB 1BH,"&dD" ; title line for heading
- TITLE_DTE DB "mm/dd/yyyy " ; ..and display
- TITLE_TME DB "hh:mm Filename: "
- TITLE_FLE DB 19 dup(32)
- TITLE_DSP EQU $-TITLE_DTE
- DB " Page"
- TITLE_PGE DB "xxxx",0dh,0ah,0ah
- DB 1BH,"&d@"
- TITLE_LEN EQU $-TITLE_ ; length of title
- ;----------------------------------------------------------------------
- ; DTA structure for DOS "find matching" call
- ;----------------------------------------------------------------------
- DTA EQU 80H ; dta offset
- DTA_ATTR EQU BYTE PTR DTA+21 ; file attribute
- DTA_TIME EQU WORD PTR DTA_ATTR+1 ; file time
- DTA_DATE EQU WORD PTR DTA_TIME+2 ; file date
- DTA_LSIZ EQU WORD PTR DTA_DATE+2 ; file lsw of size
- DTA_HSIZ EQU WORD PTR DTA_LSIZ+2 ; file msw of size
- DTA_NAME EQU BYTE PTR DTA_HSIZ+2 ; file name of file
- DTA_LEN EQU DTA_NAME+15-DTA ; length of dta find entry
- ;----------------------------------------------------------------------
- ; Messages to user
- ;----------------------------------------------------------------------
- FILENF DB "File not found.",0DH,0AH,"$"
- PRTOERR DB "Could not open output file.",0DH,0AH,"$"
- Backerr DB "Could not open back side output file.",0Dh,0Ah,"$"
- FORMAT DB 0DH,0AH,"SYNTAX:",09H,"LASERLST [d:][path]filename[.ext] "
- DB "[outfile] [/Tn]",0DH, 0AH, 0AH
- DB " ofile defaults to LPT1:",0DH,0AH
- DB " n is tab width (16 max)",0DH,0AH,"$"
- ;----------------------------------------------------------------------
- ; HP control strings
- ;----------------------------------------------------------------------
- STRING1 DB 1BH,"E",1BH,"&l1O",1BH,"(s17H",1BH,"&l5.14C"
- DB 1BH,"&l6E",1BH,"&l71F",1BH,"(s-3B"
- DB 1BH,"&a0R",1BH,"&a85M",1BH,"&a5L",0DH
- STRING1_LEN EQU $-STRING1
-
- STRING2 DB 0ch,1BH,"E"
- STRING2_LEN EQU $-STRING2
-
- STRING3 DB 1BH,"&a0R",1BH,"&a90M",1BH,"&a88L",0DH,0AH,0DH,0AH
- STRING3_LEN EQU $-STRING3
-
- STRING4 DB "|", 0DH,0AH
-
- STRING5 DB 1BH,"&a0R",1BH,"&a171M",1BH,"&a91L",0DH
- STRING5_LEN EQU $-STRING5
-
- ;
- ; Note: leading formfeed (0Ch) replaced by carriage return (0Dh) for
- ; the first pass through each input file. Changed to FF in code.
- ;
- STRING6 DB 0Dh,1BH,"&a0R",1BH,"&a85M",1BH,"&a5L",0DH
- STRING6_LEN EQU $-STRING6
- ; ---------------------------------------------------------------------------
- ; MAIN - Mainline of program
- ; ---------------------------------------------------------------------------
- MAIN PROC ; start of program
-
- CALL INIT ; initialize program
-
- MAIN10: CALL OPEN ; open the input file
- JC MAIN80 ; if we can't .. try next
-
- MAIN20: CALL READ ; read a block
-
- CALL PRINT ; print the line
-
- OR SI, SI ; q. end of file?
- JNZ MAIN20 ; a. no .. get next line
-
- MOV BX, FHANDLE ; bx = input file handle
- MOV AH, 3EH ; ah = close file
- INT 21H ; .. ask DOS to do it
-
- MAIN80: MOV AH, 4FH ; ah = find next file
- INT 21H ; q. file found?
- JNC MAIN10 ; a. yes .. continue
-
- Mov BX,BHandle ;; Get back side file handle
- Mov AH,3Eh ;; AH = close file
- Int 21h ;; Ask DOS to do it.
-
- MOV DX, OFFSET DOLLAR ; dx -> null message
- CALL DIE ; .. say goodnight
-
- MAIN ENDP
- ; ---------------------------------------------------------------------------
- ; INIT - Handle initialization
- ; ---------------------------------------------------------------------------
- INIT PROC
-
- CLD ; assure ascending
- MOV AH, 19H ; ah = get current drive
- INT 21H ; al = current drive
- MOV EDRV, AL ; save entry drive
-
- MOV SI, OFFSET EDIR ; si -> current directory area
- MOV BYTE PTR [SI], '\' ; .. start with backslash
- INC SI ; si -> next byte
- XOR DL, DL ; dl = default drive
- MOV AH, 47H ; ah = get current dir
- INT 21H ; .. save in area
-
- Mov DX,Offset BackFile ;; Point to filename to create
- Mov AH,3Ch ;; DOS Create file call
- Xor CX,CX ;; File attributes (none)
- Int 21h ;; Call DOS to do it.
- Jnc Init05 ;; Continue if no error on create
-
- Mov DX,Offset Backerr ;; Point to error message
- Call Die ;; And bail out...
-
- Init05: Mov BHandle,AX ;; Save file handle
-
- MOV DX, OFFSET HEADER_MSG ; dx -> header message
- MOV AH, 9 ; ah = print ascii$ message
- INT 21H ; .. ask DOS to do it
-
- CALL PARMS ; check parameters
-
- CMP ARG2, 0 ; q. arg2 specified?
- JE INIT20 ; a. yes .. skip open
-
- MOV DX, ARG2 ; dx -> arg2 value
- MOV AH, 3CH ; ah = create file
- XOR CX, CX ; .. cx = file attributes
- INT 21H ; q. open the file ok?
- JNC INIT10 ; a. yes .. continue
-
- MOV DX, OFFSET PRTOERR ; dx -> open error message
- CALL DIE ; .. you're dead, Jim.
-
- INIT10: MOV PHANDLE, AX ; save printer handle
-
- INIT20: CALL DFLPATH ; set up dir & drive
-
- MOV AH, 4EH ; ah = find first
- MOV DX, OFFSET FILENAME ; dx -> file to find
- XOR CX, CX ; cx = search attribute
- INT 21H ; q. find first file ok?
- JNC INIT90 ; a. yes .. continue
-
- MOV DX, OFFSET FILENF ; dx -> file not found
- CALL DIE ; .. gasp you're final breath
-
- INIT90: RET ; return to caller
-
- INIT ENDP
- ; ---------------------------------------------------------------------------
- ; OPEN - Opens the next file to process and update title line
- ; Exit: Carry indicates file would not open.
- ; ---------------------------------------------------------------------------
- OPEN PROC
-
- MOV DX, OFFSET DTA_NAME ; dx -> file name
- MOV AX, 3D00H ; al = open for read
- INT 21H ; .. ask DOS to do it.
- JNC OPEN05 ; ok .. continue
-
- RET ; else .. return if error
-
- OPEN05: MOV FHANDLE, AX ; save file handle
- MOV LASTBUFF, 0 ; show last buffer not read
-
- MOV SI, OFFSET DTA_NAME ; si -> file name
- MOV DI, OFFSET TITLE_FLE ; di -> file name area
- PUSH DI ; .. save it
- MOV AL, ' ' ; al = blank
- MOV CX, 15 ; .. amount to blank
- REP STOSB ; .. clear the file name
- POP DI ; .. restore output pointer
-
- OPEN10: LODSB ; al = byte from file name
-
- OR AL, AL ; q. end of name?
- JZ OPEN20 ; a. yes .. end loop
-
- STOSB ; store a byte
- JMP OPEN10 ; .. and move next
-
- OPEN20: MOV BL, '0' ; fill value
- MOV AX, DS:DTA_DATE ; ax = date field
- PUSH AX ; save for later
- PUSH AX ; .. again
-
- MOV CL, 5 ; cl = shift value
- SHR AX, CL ; .. mm to lower bits
- AND AX, 0FH ; .. upper bits off
- MOV CX, 2 ; cx = number of characters
- MOV DI, OFFSET TITLE_DTE ; di -> mm
- CALL ITOA ; .. move in mm
-
- POP AX ; ax = date
- AND AX, 1FH ; al = dd
- MOV CX, 2 ; cx = number of chars
- MOV DI, OFFSET TITLE_DTE+3 ; di -> dd
- CALL ITOA ; .. move into dd
-
- POP AX ; ax = date
- MOV CL, 9 ; cl = shift amount
- SHR AX, CL ; .. ax = yy
- ADD AX, 1980 ; ax = year
- MOV CX, 4 ; cx = length of output
- MOV DI, OFFSET TITLE_DTE+6 ; di -> yyyy
- CALL ITOA ; .. move into yyyy
-
- MOV AX, DS:DTA_TIME ; ax = time
- PUSH AX ; .. save for later
- MOV CL, 11 ; cl = shift value
- SHR AX, CL ; .. ax = hh
- MOV CX, 2 ; cx = length of output
- MOV DI, OFFSET TITLE_TME ; di -> hh
- CALL ITOA ; .. move into hh
-
- POP AX ; ax = time
- MOV CL, 5 ; cl = shift value
- SHR AX, CL ; ax = mm
- AND AX, 3FH ; .. upper bits off
- MOV CX, 2 ; cx = length of output
- MOV DI, OFFSET TITLE_TME+3 ; di -> mm
- CALL ITOA ; .. move into mm
-
- MOV AH, 40H ; ah = write to device
- MOV BX, 1 ; bx = stdout device
- MOV CX, TITLE_DSP ; cx = length to display
- MOV DX, OFFSET TITLE_DTE ; dx -> part of header line
- INT 21H ; issue dos call
-
- MOV AH, 40H ; ah = write to device
- MOV BX, 1 ; bx = stdout device
- MOV CX, 2 ; cx = length to display
- MOV DX, OFFSET CRLF ; dx -> <cr><lf> string
- INT 21H ; issue dos call
-
- CLC ; show all went ok
- OPEN90: RET
-
- OPEN ENDP
- ; ---------------------------------------------------------------------------
- ; READ - Read the next buffer full
- ; Exit: si -> next line, 0 if eof, cx = length of line
- ; ---------------------------------------------------------------------------
- READ PROC
-
- PUSH AX ; save registers
- PUSH BX
- PUSH DX
-
- MOV SI, 0 ; si -> nothing
-
- CMP LASTBUFF, 1 ; q. last buffer have 1ah?
- JE READ90 ; a. yes .. end it all
-
- MOV AH, 03FH ; ah = read file
- MOV BX, FHANDLE ; bx = handle of file to read
- MOV CX, BUFLEN ; cx = amount to read
- MOV DX, OFFSET BUFFER ; dx -> buffer
- INT 21H ; read, please
- JC READ90 ; error .. return eof
-
- OR AX, AX ; q. any read?
- JZ READ90 ; a. yes .. return with something
-
- MOV SI, OFFSET BUFFER ; si -> start of line
- MOV CX, AX ; cx = nbr of characters read
- MOV BX, AX ; .. and bx
-
- MOV DI, SI ; di -> chars read
- MOV AL, 1AH ; al = EOF indicator
-
- REPNE SCASB ; q. eof found?
- JNE READ80 ; a. no .. continue
-
- INC CX ; .. increment count
- NEG CX ; .. and negate it
- MOV LASTBUFF, 1 ; .. and set lastbuff flag
-
- READ80: ADD CX, BX ; q. any bytes this buffer?
- JNZ READ90 ; a. yes .. continue
-
- MOV SI, 0 ; a. else .. show end of file.
-
- READ90: POP DX ; restore registers
- POP BX ;
- POP AX ;
- RET ; ..and return to caller
-
- READ ENDP
- ; ---------------------------------------------------------------------------
- ; PRINT - Print requested data
- ; Entry: si -> string to print or 0, cx = length of input string
- ; ---------------------------------------------------------------------------
- PRINT PROC
-
- OR SI, SI ; q. end of file call?
- JNE PRINT10 ; a. no .. continue
-
- CALL EPILOGUE ; put out trailing characters
- RET ; ..and return to caller
-
- PRINT10: PUSH AX ; save registers
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH SI
-
- CMP HPSTATE, 0 ; q. initial state?
- JNE PRINT20 ; a. no .. continue
-
- CALL PROLOGUE ; send out initial string
-
- PRINT20: CALL EXPAND ; handle tab expansion
- MOV DX, SI ; dx -> start of new buffer
- MOV BX, CX ; bx = nbr of chars in buffer
- XOR CX, CX ; cx = nbr of chars to print
- MOV AH, USEDLEN ; ah = printed chars in this line
-
- PRINT30: LODSB ; al = first character
-
- CMP AL, 0CH ; q. formfeed?
- JNE PRINT40 ; a. yes .. process it
-
- CALL LINEPRT ; print the line
- CALL PAGEBREAK ; do a page break
- XOR AH, AH ; ah = nbr of columns used
- DEC BX ; bx = decrement remaining count
- INC DX ; dx -> next printable character
- JMP PRINT70 ; ..and continue w/common code
-
- PRINT40: CMP AL, 0AH ; q. linefeed?
- JNE PRINT50 ; a. no .. continue
-
- DEC BX ; bx = remaining chars in buffer
- INC CX ; cx = nbr of characters to print
- CALL LINEPRT ; print the line
- XOR AH, AH ; ah = nbr of columns used
- CALL BUMPLINE ; increment/test line counter
- JMP PRINT70 ; ..and continue w/common code
-
- PRINT50: CMP AL, 0DH ; q. carriage return?
- JNE PRINT55 ; a. no .. continue
- JMP SHORT PRINT57 ; ..and continue w/common code
-
- PRINT55: CMP AL, 08H ; q. BackSpace?
- JNE PRINT60 ; a. no .. continue
-
- DEC AH ; move back a column
- JNS PRINT65 ; .. but not beyond first
-
- PRINT57: XOR AH, AH ; ah = start of line
- JMP SHORT PRINT65 ; .. and continue
-
- PRINT60: INC AH ; increment nbr of columns used
- PRINT65: INC CX ; ..and nbr of chars to print
- DEC BX ; decrement remaining char count
-
- CMP AH, 81 ; q. reached end of line?
- JL PRINT70 ; a. no .. continue
-
- CALL LINEPRT ; print upto page width
- PUSH CX ; save registers
- PUSH DX ;
- MOV DX, OFFSET CRLF ; dx -> <cr><lf>
- MOV CX, 2 ; cx = string length
- CALL WRITE ; print the crlf to do line wrapping
- POP DX ; restore registers
- POP CX ;
- XOR AH, AH ; ah = nbr of columns used
- CALL BUMPLINE ; increment/test line counter
-
- PRINT70: OR BX, BX ; q. anything left to check?
- JNZ PRINT30 ; a. yes .. loop till done
-
- CALL LINEPRT ; print the line
- MOV USEDLEN, AH ; save nbr of columns used
-
- POP SI ; restore registers
- POP DX ;
- POP CX ;
- POP BX ;
- POP AX ;
- RET ; ..and return to caller
-
- PRINT ENDP
- ; ---------------------------------------------------------------------------
- ; DIE - Display an error message and return to DOS
- ; Entry: dx -> error message ended in dollar sign.
- ; ---------------------------------------------------------------------------
- DIE PROC
-
- MOV AH, 9 ; ah = print string
- INT 21H ; .. call dos to print error
-
- MOV DL, EDRV ; dl = drive to select
- MOV AH, 0EH ; ah = select drive
- INT 21H ; .. select the drive
-
- MOV DX, OFFSET EDIR ; dx -> directory
- MOV AH, 3BH ; ah = CHDIR request
- INT 21H ; .. ask DOS to do it
-
- MOV AX, 4C00H ; ax = exit
- INT 21H ; .. terminate routine
-
- DIE ENDP
- ; ---------------------------------------------------------------------------
- ; PARMS - Parses the command line
- ; ---------------------------------------------------------------------------
- PARMS PROC
-
- CALL UPCASE ; upper case the parm area
- MOV SI, 81H ; si -> parms area
-
- PARMS10: LODSB ; get parameter character
-
- CMP AL, '/' ; q. option?
- JE PARMS80 ; a. yes .. check option
- CMP AL, 0DH ; q. end of line?
- JE PARMS50 ; a. yes .. exit
- CMP AL, ' ' ; q. blank?
- JNA PARMS10 ; a. yes .. skip
- CALL ARG ; set the argument
- JC PARMSERR ; .. die on an error
-
- PARMS30: LODSB ; get next character
- CMP AL, 0DH ; q. end of line?
- JE PARMS50 ; a. yes .. process
- CMP AL, '/' ; q. start of option?
- JE PARMS80 ; a. yes .. process
- CMP AL, ' ' ; q. end of PARMS?
- JA PARMS30 ; a. no .. next char
-
- CALL ENDPARM ; terminate parm string
- JMP PARMS10 ; .. look for next
-
- PARMS50: CALL ENDPARM ; terminate parm string
-
- CMP ARG1, 0 ; q. PARMS 1 available?
- JE PARMSERR ; a. no .. error
- RET ; .. else .. return to caller
-
- PARMS80: CALL ENDPARM ; terminate parm string
- LODSB ; al = option character
-
- CMP AL, 'T' ; q. Tab width?
- JNE PARMSERR ; a. no .. error in option
-
- CALL ATOI ; ax = tab width
-
- CMP AX, 16 ; q. request greater than max?
- JG PARMS10 ; a. yes .. unreasonable
-
- MOV TABCOL, AX ; .. save tab width
- JMP PARMS10 ; .. continue scan
-
- PARMSERR: MOV DX, OFFSET FORMAT ; dx -> format message
- CALL DIE ; abort
-
- PARMS ENDP
- ; ---------------------------------------------------------------------------
- ; ARG - Setup pointers to the command line arguments
- ; Entry: si -> second character in argument.
- ; Exit: ARG1 or ARG2 pointers filled in.
- ; Carry set if more than 2 arguments detected.
- ; ---------------------------------------------------------------------------
- ARG PROC
-
- LEA BX, [SI-1] ; bx -> argument
- CMP ARG1, 0 ; q. arg1 filled in?
- JNE ARG10 ; a. yes .. check 2
- MOV ARG1, BX ; save arg1 pointer
- JMP SHORT ARG90 ; .. exit ok!
-
- ARG10: CMP ARG2, 0 ; q. arg2 filled in?
- JE ARG20 ; a. no .. fill it in
- STC ; else .. error
- RET ; .. and return to caller
-
- ARG20: MOV ARG2, BX ; save arg2 pointer
- ARG90: CLC ; show no error
- RET ; return to caller
-
- ARG ENDP
- ; ---------------------------------------------------------------------------
- ; ENDPARM - Handle parameters which end in a colon
- ; Entry: si -> first character past end of parameter
- ; ---------------------------------------------------------------------------
- ENDPARM PROC
-
- CMP BYTE PTR [SI-2], ':' ; q. argument end in a colon?
- JNE ENDPARM10 ; a. no .. continue
-
- MOV BYTE PTR [SI-2], 0 ; ..it doesn't any more
- RET ; ..and return
-
- ENDPARM10: MOV BYTE PTR [SI-1], 0 ; end the parameter
- RET ; ..and return
-
- ENDPARM ENDP
- ; ---------------------------------------------------------------------------
- ; DFLPATH - Setup the default drive and path
- ; ---------------------------------------------------------------------------
- DFLPATH PROC
-
- MOV DI, ARG1 ; di -> first arg
-
- DFLPATH10: CMP BYTE PTR [DI+1], ':' ; q. drive specified?
- JNE DFLPATH20 ; a. no .. use current drive
- MOV DL, [DI] ; dl = drive to use
- SUB DL, 'A' ; get requested drive number
- MOV AH, 0EH ; set requested drive
- INT 21H ; .. via dos
- ADD DI, 2 ; di -> next part
-
- DFLPATH20: PUSH DI ; save pointer
- MOV BX, DI ; bx -> start of area
- XOR AL, AL ; al = search for null
- MOV CX, 128 ; very max to search
- CLD
- REPNE SCASB ; find end of arg
- LEA SI, [DI-1] ; si -> nul
- MOV CX, 0 ; cx = # chars to move
- CMP SI, BX ; q. any file name
- JE DFLPATH80 ; a. no .. error
-
- DFLPATH30: DEC SI ; si -> prev char
- CMP BYTE PTR [SI], '\' ; q. dir?
- JE DFLPATH35 ; a. yes .. end of file name.
- INC CX ; cx = char count
- CMP SI, BX ; q. done?
- JE DFLPATH37 ; a. yes .. move file name
- JMP DFLPATH30 ; .. continue
-
- DFLPATH35: INC SI ; si -> start of file name
- DFLPATH37: OR CX, CX ; q. file name spec'd?
- JZ DFLPATH80 ; a. no .. error
- CMP CX, 12 ; q. too long?
- JA DFLPATH85 ; a. yes .. error
- PUSH SI ; save start pointer
- MOV DI, OFFSET FILENAME ; di -> file name
- INC CX ; .. assure nul moves too
- REP MOVSB ; .. move in the file name
- POP SI ; restore start pointer
- POP DI ; .. and dir pointer
- CMP SI, BX ; q. at start of parm?
- JE DFLPATH90 ; a. yes .. return
- INC BX ; bx -> next char
- CMP SI, BX ; q. root only given?
- JE DFLPATH40 ; a. yes .. continue
- DEC SI ; si -> last \
-
- DFLPATH40: MOV BYTE PTR [SI], 0 ; make dir ASCIIZ
- DFLPATH50: MOV DX, DI ; dx -> directory
- MOV AH, 3BH ; ah = CHDIR opcode
- INT 21H ; .. change directory
- JNC DFLPATH90 ; if ok .. continue
- JMP SHORT DFLPATH85 ; dx -> baddir request
-
- DFLPATH80: MOV DX, OFFSET FORMAT ; dx -> no file specified
- CALL DIE
-
- DFLPATH85: MOV DX, OFFSET FILENF ; dx -> invalid filename spec'd
- CALL DIE
-
- DFLPATH90: RET ; return to caller
-
- DFLPATH ENDP
- ; ---------------------------------------------------------------------------
- ; EXPAND - Handle tab expansion
- ; Entry:
- ; si -> line read from file ended by a linefeed
- ; cx = length of line
- ; Exit:
- ; si -> reformatted line in output buffer
- ; cx = new line length
- ; ---------------------------------------------------------------------------
- EXPAND PROC
-
- PUSH AX ; save registers
- PUSH BX
- PUSH DX
- PUSH DI
-
- MOV DI, OFFSET OBUFF ; di -> start of output buffer
-
- EXPAND10: LODSB ; al = character from input line
-
- CMP AL, 09H ; q. tab character?
- JNE EXPAND30 ; a. no .. continue processing
-
- MOV AX, CURCOL ; ax = current column
- DEC AX ; ax = column offset
- XOR DX, DX ; dx:ax = current column
- MOV BX, TABCOL ; bx = nbr of columns per tab
- IDIV BX ; dx = space within tab stop
-
- SUB BX, DX ; bx = spaces left in tab stop
-
- MOV AL, 20H ; al = space char to padding string
-
- EXPAND20: STOSB ; put a blank in output buffer
- INC CURCOL ; bump current column nbr
-
- DEC BX ; q. done yet?
- JNZ EXPAND20 ; a. no .. keep looping
- JMP SHORT EXPAND50 ; a. yes .. get next character
-
- EXPAND30: CMP AL, 0DH ; q. carriage return?
- JE EXPAND33 ; a. yes .. reset column
-
- CMP AL, 0CH ; q. form feed?
- JNE EXPAND35 ; a. no .. continue processing
-
- EXPAND33: MOV CURCOL, 0 ; setup for start of new line
- JMP SHORT EXPAND40 ; .. continue
-
- EXPAND35: CMP AL, 08H ; q. backspace?
- JNE EXPAND40 ; a. no .. continue
-
- STOSB ; save the BS
- DEC CURCOL ; .. move back a space
- JNZ EXPAND50 ; .. get next character
-
- MOV CURCOL, 1 ; init current column
- JMP SHORT EXPAND50 ; .. continue
-
- EXPAND40: STOSB ; move character to output line
- CMP AL, 0AH ; q. line feed?
- JE EXPAND50 ; a. yes .. don't count it
-
- INC CURCOL ; bump current column nbr
-
- EXPAND50: LOOP EXPAND10 ; ..loop till input exhausted
-
- MOV SI, OFFSET OBUFF ; si -> start of output buffer
- MOV CX, DI ; di -> just past last char of output
- SUB CX, SI ; cx = nbr of characters in output
-
- POP DI ; restore registers
- POP DX
- POP BX
- POP AX
- RET ; ..and return to caller
-
- EXPAND ENDP
- ; ---------------------------------------------------------------------------
- ; LINEPRT - Handle printing a line
- ; Entry:
- ; dx -> start of line
- ; cx = nbr of characters to print
- ; Exit:
- ; dx -> start of next line
- ; cx = 0
- ; ---------------------------------------------------------------------------
- LINEPRT PROC
-
- JCXZ LINEPRT90 ; if nothing to print.. return
-
- CMP NEWPAGE, 1 ; q. need a new page?
- JNE LINEPRT10 ; a. no .. continue
-
- CALL PAGEBREAK ; else .. do a pagebreak
-
- LINEPRT10: CALL WRITE ; write the line
-
- ADD DX, CX ; dx -> start of next line
- XOR CX, CX ; cx = nbr of characters to print
- LINEPRT90: RET
-
- LINEPRT ENDP
- ; ---------------------------------------------------------------------------
- ; MKTITLE - Make the title line be ready to print
- ; Exit:
- ; dx -> title line
- ; cx = title line length
- ; ---------------------------------------------------------------------------
- MKTITLE PROC
- PUSH AX ; save registers
- PUSH BX
- PUSH DI
-
- MOV AX, PAGENO ; ax = page number
- MOV CX, 4 ; cx = length of output
- MOV BL, ' ' ; bl = fill char (blank)
- MOV DI, OFFSET TITLE_PGE ; di -> output area
- CALL ITOA ; .. fill in page number
-
- MOV DX, OFFSET TITLE_ ; dx -> title
- MOV CX, TITLE_LEN ; cx = length of title
- CALL WRITE ; print title line
-
- POP DI ; restore registers
- POP BX
- POP AX
- RET ; return to caller
-
- MKTITLE ENDP
- ; ---------------------------------------------------------------------------
- ; PAGEBREAK - Handle page overflow condition
- ; ---------------------------------------------------------------------------
- PAGEBREAK PROC
-
- Push AX ; save registers
- PUSH BX ;
- PUSH CX ;
- PUSH DX ;
-
- TEST PAGENO, 1 ; q. finishing up with left page?
- JZ PAGEBRK20 ; a. no .. do other page
-
- MOV DX, OFFSET STRING3 ; dx -> get to right page string
- MOV CX, STRING3_LEN ; cx = length
- CALL WRITE ; write out 1st part of string
-
- MOV BX, 66 ; bx = loop count
- MOV CX, 3 ; cx = nbr of chars to print
- MOV DX, OFFSET STRING4 ; dx -> vertical bar string
-
- PAGEBRK10: CALL WRITE ; write on line of vertical bars
-
- DEC BX ; q. done yet?
- JNZ PAGEBRK10 ; a. no .. keep looping
-
- MOV DX, OFFSET STRING5 ; dx -> string to finish up
- MOV CX, STRING5_LEN ; cx = length
- Call Write ;; Output it...
- JMP PAGEBRK30 ; ..and continue w/common code
-
- PAGEBRK20:
-
- Mov AX,CHandle ;; Get current handle
- Xchg AX,NHandle ;; Get next handle
- Mov CHandle,AX ;; Swap current handle
-
- MOV DX, OFFSET STRING6 ; dx -> get to left page string
- MOV CX, STRING6_LEN ; cx = length
- CALL WRITE ; print the init line
- Mov AL,0Ch ;; Get a formfeed
- Mov String6,AL ;; Don't want FF on first pass
-
- Pagebrk30: MOV LINECNT, 1 ; reset line counter
- MOV NEWPAGE, 0 ; clear new page request flag
- INC PAGENO ; ..and bump page number
-
- CALL MKTITLE ; print title line
-
- POP DX ; restore registers
- POP CX ;
- POP BX ;
- Pop AX ;
- RET ; ..and return to caller
-
- PAGEBREAK ENDP
- ; ---------------------------------------------------------------------------
- ; BUMPLINE - Increment line counter and test for overflow
- ; ---------------------------------------------------------------------------
- BUMPLINE PROC
- INC LINECNT ; increment line counter
-
- CMP LINECNT, 66 ; q. reached max lines/page?
- JLE BUMPLINE90 ; a. no .. continue
-
- MOV NEWPAGE, 1 ; else .. show we'll need a new one
-
- BUMPLINE90: RET ; ..then return to caller
-
- BUMPLINE ENDP
- ; ---------------------------------------------------------------------------
- ; PROLOGUE - Put out laserjet initialization string
- ; ---------------------------------------------------------------------------
- PROLOGUE PROC
-
- PUSH CX ; save registers
- PUSH DX
- ;
- ; The initialization string is first sent to the back side file, then to
- ; the printer. The handles are set up so the next handle to be used (NHandle)
- ; points to the back side file, and after the initialization string is sent
- ; to the printer with the second call, the current handle (CHandle) points
- ; to the printer. After each physical page is printed, the two handles are
- ; swapped. The Write subroutine writes to whichever file is pointed to by
- ; Chandle.
- ;
- Mov AX,BHandle ;; Get pointer to back side file
- Mov CHandle,AX ;; Point to back side file
- Mov NHandle,AX ;; Also save as next handle to use
- MOV DX, OFFSET STRING1 ; dx -> initialization string
- MOV CX, STRING1_LEN ; cx = length
- CALL WRITE ; print the init line
-
- Mov AX,PHandle ;; Point to Printer
- Mov CHandle,AX ;; Save as current handle
- Mov CX,String1_Len ;; CX = Length
- Mov DX,Offset String1 ;; DX -> Initialization string
- Call Write ;; And send to printer
-
- MOV PAGENO, 1 ; setup page number
- MOV CURCOL, 1 ; ..and current column number
- MOV LINECNT, 1 ; ..and line counter
- MOV HPSTATE, 1 ; ..show in left page
- MOV USEDLEN, 0 ; ..clear column position
- CALL MKTITLE ; print title line
-
- POP DX ; restore registers
- POP CX ;
- RET ; ..and return to caller
-
- PROLOGUE ENDP
- ; ---------------------------------------------------------------------------
- ; EPILOGUE - Put out laserjet finish up string
- ; ---------------------------------------------------------------------------
- EPILOGUE PROC
-
- Push AX ; save registers
- Push BX ;
- PUSH CX ;
- PUSH DX ;
-
- ;
- ; Calculate how many formfeeds we need at the end of the back side file.
- ;
- Mov AX,BHandle ;; Point to back side file
- Mov CHandle,AX ;; Make current output file
- Mov BX,1 ;; Only one formfeed needed
- Mov AX,PageNo ;; Get last page number
- Cmp AX,1 ;; Have we only printed 1 pg?
- Je Epil10 ;; Only need 1 formfeed
- Inc AX ;; Add 1
- Shr AX,1 ;; Divide by 2
- Test AX,1 ;; Is physical page odd?
- Jz Epil10 ;; No - page is even
- Inc BX ;; Page is odd - 2 formfeeds
-
- Epil10: MOV DX, OFFSET STRING2 ; dx -> termination string
- MOV CX, STRING2_LEN ; cx = length
- CALL WRITE ; print the init line
- Dec BX ;; Need any more?
- Jnz Epil10 ;; Continue as needed
- ;
- ; Now send the reset string to the printer itself.
- ;
- Mov AX,PHandle ;; Point to the printer
- Mov CHandle,AX ;; Make it current
- Mov DX,Offset String2 ;; DX -> termination string
- Mov CX,String2_len ;; CX = length
- Call Write ;; And send it.
-
- Mov String6,0Dh ;; Don't want FF on first pass
-
- MOV HPSTATE, 0 ; show back to initialization state
-
- POP DX ; restore registers
- POP CX ;
- Pop BX ;
- Pop AX ;
-
- RET ; ..and return to caller
-
- EPILOGUE ENDP
- ; ---------------------------------------------------------------------------
- ; WRITE - Send a string to the printer
- ; Entry:
- ; dx -> string to write
- ; cx = nbr of characters
- ; ---------------------------------------------------------------------------
- WRITE PROC
-
- PUSH AX ; save registers
- PUSH BX
-
- MOV AH, 40H ; ah = write to file/device function
- MOV BX, CHANDLE ; bx = printer handle
- INT 21H ; issue dos call
-
- POP BX ; restore registers
- POP AX ;
- RET ; ..and return to caller
-
- WRITE ENDP
- ; ---------------------------------------------------------------------------
- ; UPCASE - Convert command line arguments to uppercase
- ; ---------------------------------------------------------------------------
- UPCASE PROC
-
- PUSH SI ; save caller regs
- PUSH DI
- MOV SI, 81H ; si -> start of parm area
- MOV DI, SI ; .. same for di
- CLD ; .. assure ascending
-
- UPCASE10: LODSB ; al = char
- CMP AL, 0DH ; q. end of line?
- JE UPCASE90 ; a. yes .. end of line!
- CMP AL, 'a' ; q. is it below 'a'?
- JB UPCASE20 ; a. yes .. continue
- CMP AL, 'z' ; q. is it above 'z'?
- JA UPCASE20 ; a. yes .. continue
- SUB AL, 20H ; set to upper case
-
- UPCASE20: STOSB ; save the byte
- JMP UPCASE10 ; .. and continue
-
- UPCASE90: POP DI ; restore caller regs
- POP SI
- RET ; .. and return to caller
-
- UPCASE ENDP
- ; ---------------------------------------------------------------------------
- ; ATOI - Translate an ascii value to binary
- ; Entry:
- ; si -> ascii value
- ; Exit:
- ; al = binary value
- ; ---------------------------------------------------------------------------
- ATOI PROC
-
- XOR AX, AX ; ax = accumulator = 0
-
- ATOI10: CMP BYTE PTR [SI], '0' ; q. below ascii 0?
- JB ATOI90 ; a. yes.. exit
-
- CMP BYTE PTR [SI], '9' ; q. above ascii 9?
- JA ATOI90 ; a. yes.. exit
-
- XOR AH, AH ; reset ah
- MOV BL, 10 ; bl = multiply value
- MUL BL ; .. multiply by 10
- MOV BL, [SI] ; bl = value
- AND BL, 0FH ; .. upper bits off
- ADD AL, BL ; .. add to bl
-
- INC SI ; si -> next char
- JMP ATOI10 ; .. tranlate it
-
- ATOI90: RET ; .. return to caller
-
- ATOI ENDP
- ; ---------------------------------------------------------------------------
- ; ITOA - Integer to ASCII characters
- ; Entry:
- ; ax = value to convert
- ; bl = fill character
- ; cx = nbr of characters
- ; di -> start of alpha area
- ; ---------------------------------------------------------------------------
- ITOA PROC
-
- PUSH AX ; save registers
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DI
- PUSHF
- STD ; ..and set direction flag
-
- ADD DI, CX ; di -> 1st char past work area
- DEC DI ; di -> last char in work area
- PUSH BX ; save fill character
- MOV BX, 10 ; bx = divisor
-
- ITOA10: OR AX, AX ; q. any value to convert?
- JZ ITOA20 ; a. no .. exit loop
-
- XOR DX, DX ; dx:ax = value to divide
- IDIV BX ; ax = dividend, dx = remainder
- OR DL, 30H ; dl = ASCII number
- MOV [DI], DL ; store character in buffer
- DEC DI ; di -> next output char location
-
- DEC CX ; q. any more room in buffer?
- JNZ ITOA10 ; a. yes .. continue loop
-
- POP BX ; restore register
- JMP ITOA90 ; ..and exit through common code
-
- ITOA20: POP AX ; al = fill character
-
- ITOA30: STOSB ; store fill character
-
- DEC CX ; q. any more room in buffer?
- JNZ ITOA30 ; a. yes .. continue loop
-
- ITOA90: POPF ; restore flags
- POP DI ; ..and registers
- POP DX ;
- POP CX ;
- POP BX ;
- POP AX ;
- RET ; ..and return
-
- ITOA ENDP
- ; ---------------------------------------------------------------------------
- ; Uninitialized data areas
- ; ---------------------------------------------------------------------------
- UDATA EQU $ ; start of unitialized data
- PAGENO EQU WORD PTR UDATA ; current page number
- CURCOL EQU WORD PTR PAGENO+2 ; current column
- LINECNT EQU WORD PTR CURCOL+2 ; line count
- EDRV EQU BYTE PTR LINECNT+2 ; current disk
- EDIR EQU BYTE PTR EDRV+1 ; current directory
- FILENAME EQU BYTE PTR EDIR+65 ; filename specifed as ARG1
- LASTBUFF EQU BYTE PTR FILENAME+13 ; last buffer indicator
- FHANDLE EQU WORD PTR LASTBUFF+1 ; input file handle
- BUFFER EQU BYTE PTR FHANDLE+2 ; file buffer
- BUFLEN EQU 2048 ; length of buffer
- USEDLEN EQU BYTE PTR BUFFER+BUFLEN ; used length in a logical line
- OBUFF EQU BYTE PTR USEDLEN+1 ; output buffer - must be last!
-
- CSEG ENDS ; end of code segment
- END START