home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
laser
/
lp_hp.arc
/
LP16.ASM
next >
Wrap
Assembly Source File
|
1986-06-19
|
14KB
|
665 lines
Page 75,132
Title LP - Print File With Pagination
Comment |
LP Command
________________
Purpose: To print an ASCII file on the standard printer
device at either 66 or 88 lines per page. A title
is printed at the top of each page which contains
the file name, creation date, and page number.
Syntax: LP [d][path]filename[.ext] [/6][/8]
[/L1][/L2]
[/10][/12][/17]
Remarks:
Written by Vernon Buerg for the IBM PC using
DOS 2.0 or later. For public domain use. Not
for sale or hire.
Version 1.1, April 27, 1984.
Version 1.2, Sept 12, 1984.
Version 1.4, Aug 8, 1985.
- account for TABs and long lines
- remove Int 17h due to bad spoolers
Version 1.5, June 13, 1986.
- minimal changes for HP LaserJet
Version 1.6, June 19, 1986
- expand tabs and use HP LJ printer codes
- fine tune cpi and lpi
- use Int 17h for quicker printing
________________ |
Cseg Segment Public Para 'CODE'
Assume CS:Cseg, DS:Cseg
Org 100h
LP Proc Far
Jmp Start ; Put usage data up front
Page
;
; Constants and Data Areas
BEL Equ 07
BS Equ 08
TAB Equ 09
LF Equ 10
FF Equ 12
CR Equ 13
EOF Equ 26
ESC Equ 27
Stopper Equ '$' ; Ends text message strings
Dater Record Yr:7,Mo:4,Dy:5
Db BS,BS,BS
Version Db CR,LF,'LP - Version 1.6l - V.Buerg',CR,LF,Stopper,BS,BS
Db CR,LF,'Usage:'
Db CR,LF,' LP [d:][\path]filename[.ext]'
Db CR,LF,' [/6][/8] [/L1][/L2] [/10][/12][/17]'
Db CR,LF,EOF
AlocMsg Db CR,LF
Db 'Not enough memory',CR,LF,BEL,Stopper
ErrMsg Db CR,LF
Db 'Invalid command option(s)',CR,LF,BEL,Stopper
Sorry Db CR,LF
Db 'Sorry, PC DOS 2.0 or later required',CR,LF,BEL,Stopper
EofMsg Db CR,LF
Db 'End of file.',CR,LF,Stopper
Buflen Dw 0 ;I/O buffer size (variable)
Stk_Top Dw 0 ;Stack ptr at entry
LPTn Dw 0 ;Printer port
Errlvl Db 0 ;Error level returned
Heading Db ESC,'&a0C' ;Top line title
Db ESC,'&dD' ; underlined
Db ESC,'(s3B' ; bold (if available) title
FileNm Db 60 Dup (' ')
Date Db 'mm-dd-yy',' '
Db 'Page '
Pageno Db '1'
Db LF,ESC,'(s0B' ; medium data
Db ESC,'&d@' ; no more underlining
Db CR,LF
Len_H Equ This Byte - Heading
Page
;
; Printer intialization set-up commands
Lcnt Db 0 ; Line counter
Ccnt Db 0 ; Chars in current line
Cpp Db 80 ; Max chars per page
LPP Db 61 ; Max lines per page
Reset Db ESC,'E' ; Printer initialization codes
Margin Db ESC,'&a0L' ; Left margin of 1
Wrap Db ESC,'&s0C' ; Enable line wrapping
Perf Db ESC,'&l0L' ; Perforation skip mode off
Db ESC,'&l2E' ; Top margin
Db ESC,'&l'
PL Db '62F' ; Page length
Db ESC,'&l'
Lpi Db '6','D' ; Lines per inch
Db ESC,'&k'
Cpi Db '0S' ; Chars per inch
Reset_L Equ $-Reset ; Length of initial string
Page
;
; File variables and messages
MsgIn Db CR,LF,'Enter INPUT filename $'
Msg1 Db CR,LF,'Unable to open input'
InKey Db 32,32 ; Keyboard buffer
Input Db 76 Dup (0),Stopper ; Drive:path\name.ext
IHandle Dw 0 ; Input file handle
Ilen Dw 0 ; Input block length
Iptr Dw Offset Buffer ; Offset to next char
Msg2 Db CR,LF,'Unable to open LPT'
Msg2a Db '1$'
Output Db 'LPT1:',0,Stopper ;Printer name
OHandle Dw 0 ;Output file handle
Olen Dw 0 ;Output block length
Optr Dw 0 ;Offset to next char
OutPtr Dw 0 ;Offset to output buffer
OutChar Db 0
Page
;
; Program initialization and main sequence
Start:
Mov SP,Offset CS:Lstack ;Use local stack
Push DS ;For DOS return
Sub AX,AX
Push AX
Mov Stk_Top,SP
Call Ver ; Check DOS version
Call Alloc ; Allocate memory
Call GetFile ; Get file name
Call Opens ; Open input
Call InitLPT ; Initialize printer
Call GetName ; Format title line
Call Titles ; and print it
Call List ; Print the file
Call Flush ; Drain the output buffer
Eod: Mov DX,Offset EofMsg ; Say END-OF-FILE
Jmp Fini
Error: Mov CS:Errlvl,1
Fini: Mov AX,CS ; Insure final seg regs
Mov DS,AX
Mov SP,Stk_Top ; and stack
Mov AH,9 ; Print error message
Int 21h
Mov BX,IHandle ; Close input
Mov AH,3Eh
Int 21h
Exit:
Mov AL,Errlvl ; Set ERROR LEVEL
Mov AH,4Ch ; and Exit
Int 21h
Page
;
; Copy file to printer
List Proc Near
List1: Call Read ; Get one character
And AL,7FH ; and hi-order bit (?)
Cmp AL,FF ; Is it form feed?
Je Eject
Cmp AL,LF ; Pass line feed
Je Passit
Cmp AL,CR ; Pass carriage return
Je Passit
Cmp AL,BS ; Pass back space
Je PassBS
Cmp AL,TAB ; Expand tab chars
Je PassTAB
Inc Ccnt ; Incr count of chars in line
Cmp AL,EOF ; End of file?
Jne Check32
Jmp Done
Check32:
Cmp AL,32 ; Other control char?
Jns Passit
Jmp CtlChr
PassTAB:Mov DL,Ccnt ; Current column count
Sub DH,DH
Add Ccnt,8 ; Round up to TAB column
And Ccnt,0F8h
Mov CL,CCnt
Sub CH,CH
Sub CX,DX ; Blanks to fill
Mov AL,' '
Jcxz Check_Wrap
PassTabs:
Call PutChar
Loop PassTabs
Jmp Check_Wrap
PassBS: Dec Ccnt ;Account for backspace
Jns Passit
Mov Ccnt,0
Passit: Call PutChar
Check_Wrap:
Mov AH,Cpp ; Max chars per line
Cmp Ccnt,AH ; filled up a line?
Ja Check_Wrap2
Cmp AL,LF ; Is it line feed?
Jne List1 ; no, get next char
Check_Wrap2:
Inc Lcnt ; yes, incr line count
Mov Ccnt,0
Mov AL,Lcnt
Cmp AL,LPP ; End of page?
Jbe List1 ; no, get next char
Eject: Mov Ccnt,0 ; Reset char count in line
Cmp Lcnt,2 ; Printed any lines yet?
Ja Eject1
Jmp List1 ; no, ignore form feed
Eject1:
Call NewPage
Jmp List1 ;Get next record
CtlChr: Cmp AL,0 ; Null char?
Je Blanks ; yes, make it a space
Push AX
Mov AL,'^' ; Indicate a control char
Call PutChar
Inc Ccnt
Pop AX ; Get char again
Blanks: Add AL,20H ; Make it printable
Jmp Passit
Done: Ret
List Endp
Page
;
; Process end of page
NewPage Proc Near
Cmp Lcnt,2 ; Is it title line?
Je Titles ; yes, skip rest
Mov AL,FF ; and send form feed
Call PutChar
Mov Lcnt,0 ; Reset line counter
Push DI ; Format new page number
Mov DI,Offset Pageno
Mov AX,3A30h
Next: Inc Byte Ptr [DI] ; Incr page number
Cmp [DI],AL ; End in zero?
Js Set1 ; yes, make it a one
Cmp [DI],AH ; Over nine?
Jne PgSet ; no, have good number
Mov [DI],AL ; yes, make last digit zero
Dec DI ; and incr hi-order
Jmp Next
Set1: Mov Byte Ptr [DI],'1'
PgSet: Pop DI
;
; Print top line titles
Titles: Mov SI,Offset Heading ; Print title line
Mov CX,Len_H
Next1: Lodsb
Cmp AL,0 ; Replace nulls in filename
Jne Next2 ; with spaces
Mov AL,' '
Next2: Call PutChar
Loop Next1
Mov Lcnt,2 ; Reset line counter
Ret
;
; Initialize the printer
InitLPT Proc Near ;Initialize the printer
Init1: Mov CX,Reset_L ; Length of
Mov SI,Offset Reset ; initial codes
Init2: Call Next1
Ret
InitLPT Endp
NewPage Endp
Page
;
; Format title line
GetName Proc Near ; Format title line
Mov SI,Offset Input ; Copy file name
Mov DI,Offset Filenm ; to heading
Mov CX,42 ; Max for title
Cld
Repz Movsb
Mov AX,5700h ; Return file's date and time
Mov BX,IHandle ; Input handle
Int 21h
Mov DI,Offset Date ; Date field in title
Mov AX,DX ; Get month part
And AX,Mask Mo
Mov CL,Mo
Call Format
Stosw
Inc DI ; Add delimiter
Mov AX,DX ; Get day part
And AX,Mask Dy
Mov CL,Dy
Call Format
Stosw
Inc DI ; Add delimiter
Mov AX,DX ; Get year part
And AX,Mask Yr
Mov CL,Yr
Call Format
Or AL,'8'
Stosw
Ret
GetName Endp
Format Proc Near ; Convert binary to ASCII
Shr AX,CL
Aam
Or AX,'00'
Xchg AH,AL
Ret
Format Endp
Page
;
; Extract one char from record
Read Proc Near ; Read char into AL
Read1: Cmp Ilen,0 ; Any in buffer?
Je Read2 ; no, read next block
Mov SI,Iptr ; yes, get offset in buf
Lodsb
Inc Iptr ; Offset for next one
Dec Ilen ; Decr buffer size left
Ret ; and return
Read2: Mov BX,IHandle ; Read input
Mov CX,BufLen
Mov DX,Offset Buffer ; Set up DS:DX
Mov AH,3Fh
Int 21h ; Read a block
Mov DX,Offset Buffer
Mov Iptr,DX ; Reset buffer ptr
Mov Ilen,AX ; and length
Jc Read8
Or AX,AX ; Anything read?
Jnz Read1 ; yes, pick it up
Mov AL,EOF ; no, return EOF
Ret
Read8: Mov DX,Offset Msg3 ;Say I/O ERROR
Jmp Error
Msg3 Db CR,LF,'I/O error',CR,LF,BEL,Stopper
Read Endp
;
; Use Int 17h to print a character
PutChar Proc Near ;Write from AL
Push AX
Push DX
PutCh1:
Mov DX,LPTn ; Printer port number
Mov AH,0 ; Print one char
Int 17h ; via BIOS
Test AH,025h ; Successful?
Jnz PutCh1 ; no, wait for printer
Pop DX ; Recover registers
Pop AX
Ret
Flush: Mov AL,FF ; Eject last page
Call PutChar
Ret
PutChar Endp
Page
;
; Get file names from parm
GetFile Proc Near ;Get file name(s)
Mov SI,80h ;Point to command line
Sub CX,CX ;Clear length reg
Or CL,Byte Ptr [SI] ;Get command tail length
Jz GetF8 ; none, ask for them
Mov DI,Offset Input ;Point fname target
Inc SI ;Bump command ptr
GetF1: Lodsb ;Get next char
Cmp AL,' ' ;Skip leading blanks
Jne GetF2
Loope GetF1
Jcxz GetF8 ; all blank
GetF2: Cmp AL,CR ;End of parm?
Je GetF7 ; yes, terminate fname
Cmp AL,' ' ;Delimiter?
Je GetF4 ; yes, look for swithes
Cmp AL,'/' ;Switch char?
Je GetF5
Stosb ;Save fname char
Lodsb
Loop GetF2
Jmp GetF7
GetF4: Dec CX
Jz GetF8
GetF4a: Lodsb
Cmp AL,' ' ;Skip intervening blanks
Jne GetF4b
Loope GetF4a
Jcxz GetF7 ; just trailing blanks
GetF4b: Cmp AL,CR ;End of parm?
Je GetF7 ; yes, no switches
Jmp Short GetF5b
GetF5: Dec CX
Jz GetF7
GetF5a: Lodsb
GetF5b: Cmp AL,'/' ;Switch char?
Jne GetFx ; no, invalid
Dec SI ; yes, back up to it
Call GetParm ; and set switches
GetF7:
GetF8: Cmp Input,0 ;Any input name?
Jne GetF9 ; no, ask for it
Call AskIn
GetF9: Ret
GetFx: Mov DX,Offset ErrMsg
Jmp Error
Page
;
; Determine switch parameters
GetParm Proc Near
Push DI
Push SI ;Offset to parm string
Push CX ;Length of string
Mov DI,SI ;Save string ptr
Add DI,CX ; ending offset
GetP0: Cmp SI,DI ;Any left?
Jb GetP1
Jmp GetP9 ; no, done
GetP1: Lodsb
Cmp AL,'/' ;Switch char?
Je GetP2
Jmp Short GetP0
GetP2: Cmp SI,DI ;Any string left?
Jae GetPx ; no, invalid option
GetP2a: Lodsb
Cmp AL,'L' ;Printer port?
Je GetPl
Cmp AL,'l'
Je GetPl
Cmp AL,'6' ; for 6 lpi?
Je GetP6
Cmp AL,'8' ; for 8 lpi?
Je GetP8
Cmp AL,'1' ; for cpi?
Je GetPc
GetPx: Mov DX,Offset ErrMsg ; no, say INVALID OPTIONS
Jmp Error
GetPl: Cmp SI,DI ;Have next char?
Jae GetPx
Lodsb
Cmp AL,'1' ;Valid printer?
Jb GetPx
Cmp AL,'2'
Ja GetPx
Mov Msg2a,AL ; Put 'n' into message
Mov Output+3,AL ; and into file name
Sub AL,'1' ; Form port address
Sub AH,AH
Mov LPTn,AX
Jmp GetP0 ; try next field
GetP6: Mov LPP,61 ; Set 6 lpi
Mov Lpi,'6'
Mov Word Ptr PL,'36'
Jmp GetP0
GetP8: Mov LPP,81 ; Set 8 lpi
Mov Lpi,'8'
Mov Word Ptr PL,'48'
Jmp GetP0
GetPc: Cmp SI,DI ; Any string left?
Jae GetPx ; no, invalid
Lodsb
GetPc12:
Cmp AL,'2' ; Is it /12?
Jne GetPc17
Mov Cpp,96 ; chars per line
Mov Cpi,'1' ; printer control code
Jmp GetPc2
GetPc17:
Cmp AL,'7' ; Is it /17?
Jne GetPc10
Mov Cpp,136
Mov Byte Ptr Cpi,'2' ; Compressed for cpi
Jmp Short GetPc2
GetPc10:
Cmp AL,'0' ;Is it 10?
Jne GetPx ; none of the above
Mov Cpp,80
Mov Cpi,'0' ; Default font cpi
GetPc2:
Jmp GetP0 ; and try next switch
GetP9: Pop CX
Pop SI
Pop DI
Ret
GetParm Endp
Page
;
; Ask for input file name
AskIn Proc Near
Ask: Mov DX,Offset MsgIn ;Prompt msg for input
Mov AH,9 ;Print string
Int 21h
Mov InKey,64
Mov DX,Offset InKey ;Ptr to keyboard buffer
Mov AH,10 ;Buffered keyboard input
Int 21h
Sub BX,BX ;Clear for insert
Add BL,InKey+1 ;Get length read
Jz Ask ;If nothing read
Mov Byte Ptr Input[BX],0 ;Set ASCIIZ stopper
Mov Word Ptr InKey,' :' ;Clear error message part
Ret
AskIn Endp
GetFile Endp
Page
;
; Open files
Opens Proc Near
Mov DX,Offset Input
Mov AX,3D00h ; Open for input
Int 21h
Jnc Openi
Mov DX,Offset Msg1
Jmp Error
Openi: Mov IHandle,AX ; Return input handle
Ret
Opens Endp
;
; Check DOS version
Ver Proc Near
Mov AH,30h ;Get DOS version
Int 21h
Cmp AL,2 ;Rel 2 or later?
Jae Ver1 ; if not
Mov DX,Offset Sorry
Jmp Error
Ver1: Mov DX,Offset Version
Mov AH,9 ;Display title
Int 21h
Ret
Ver Endp
Page
;
; Allocate up to 64K for read buffer
Alloc Proc Near ; Allocate storage
Mov BX,Word Ptr DS:6 ; Highest segment address
Mov CX,CS ; Program starting seg addr
Sub BX,CX ; Size of program segment
Sub BX,Pgmsize ; less size of code
Sub BX,MinSize ; Minimum buffer request size
Cmp BX,MinSize ; Have enough?
Jb Alloc9
Mov CL,4 ; Convert paras
Shl BX,CL ; to bytes available
Mov Buflen,BX
Ret
Alloc9: Mov DX,Offset AlocMsg
Jmp Error
Alloc Endp
LP Endp
Lstack Equ $+128 ; End of local stack
Minsize Equ 256 ; Require 4k minimum
Buffer Equ Lstack + 128 ; Input buffer
PgmSize Equ ($-Cseg+1024) / 16 ; Program size in paragraphs
Cseg Ends
End LP