Category : Files from Magazines
Archive   : VOL11N21.ZIP
Filename : MLPRINT.ASM

 
Output of file : MLPRINT.ASM contained in archive : VOL11N21.ZIP
; MLPrint.ASM
; Mailing List Printing Utility
; Prints ASCII TXT mailing list to labels or envelopes with barcodes
;---------------------------------------------------------------------------
; Copyright (c) 1992 Jay Munro
; First Published in PC Magazine December 15, 1992
; Compile using Masm 6.0
; Syntax
; ML /FPi /Gc /W3 /Zm /Ta MLPRINT.ASM
;---------------------------------------------------------------------------
;Files used:
; MLPrint.ASM - Main program code
; Support.INC - data only module
; MLPrint2.INC - support procedures
; MLPrint3.INC - support procedures

.Model Tiny ;New under Masm 6.0, directly generates
.Code ; COM file from simplified syntax
Org 100h ;Still need the ORG.

;---------------------------------------------------------------------------
MLPrint Proc Near

Start:
Jmp SetErrorTrap

Include Support.Inc ;--- Prototypes - Masm 6.0 equivalent of Declarations

SetErrorTrap:
Call HookInt24

MenuStart: ;--- Initialize Screen et al.
Call LoadDefaultValues

Invoke CLS,0,0,18h,50h ;screen coords to clear

;--- Print Main Menu and Logo
Xor DX,DX ;look at page zero
Mov ES,DX ;through ES
Xor CX,CX
Mov BX,0B000h ;assume mono screen segment initially
Mov AL,ES:[463h] ;get equipment list
Cmp AL,0B4h ;is it mono?
Jnz @F
Mov DX,MonoColor ;get mono color
Mov Color,DX
Mov DX,MonoErrCol ;and error color
Mov ErrColor,DX
Jmp Get_Params ;yes, skip over adding 800h
@@:
Add BX,800h ;no, adjust to point to color screen memory
Inc CX
Push BX ;save BX
Mov AH,12h ;specify EGA BIOS special function service
Mov BL,10h ;request EGA info
Int 10h ;call the EGA BIOS
Cmp BL,10h ;if BL is still 10h, there's no EGA installed
Pop BX ;get BX back (screen segment)
Jnz Get_Params ;it IS an EGA, leave retrace port at 0
Mov RTP,3DAh ;must be a CGA, indicate the port to check for retrace

Get_Params:
Mov ES,BX ;point ES at Screen memory
Mov ScrnSeg,BX ;save for DPrint
Mov SI,Offset MainMnu ;get address of menu screen
Xor DI,DI ;start from top of screen
Invoke PrintZStr,SI, Color, DI
Mov DI,3680
Mov SI,Offset Copyrite
Invoke PrintZStr,SI, color, DI

TopData: ;Print data on top
Mov DI,Offset MlFileLc
Push DI
Mov CX,NumTopFields
Call TopLoop

Cmp Byte Ptr LabelFlag,'L'
Jnz @F
Invoke LabelMenu, 1 ;default screen
Jmp Short ShowDone

@@:
Mov SI,Offset EnvMenu
Invoke PrintZStr,SI, Color, BLoc
Mov DI,Offset EnvScrLoc ;envelope input
Push DI ;preserve through field printing
Mov CX,9 ;number of fields in the envelope screen
Call TopLoop ;color in each field
Pop DI ;retrieve screen location

ShowDone:
Pop SI
Mov DI,SI ;first field offset

GetInfo: ;This section loops through
Cmp Byte Ptr [DI],0 ;the menu to receive data from
Jnz NoSwitch ;are we at the end of our fields?
Push SI
Mov DI,BLoc ;new menu location
Mov ES,ScrnSeg ;point ES at screen seg
Cmp Byte Ptr LabelFlag,'L'
Jnz @F
Invoke CLS,12,0,22,79
Invoke LabelMenu, 0
Pop SI
Mov DI,Offset LabelScrLoc ;Label input
Jmp GetInfo

@@:
Invoke CLS,12,0,22,79
Mov SI,Offset EnvMenu
Invoke PrintZStr,SI, Color, DI
Pop SI
Mov DI,Offset EnvScrLoc ;envelope input
Push DI ;preserve through field printing
Mov CX,9 ;number of fields in the envelope screen
Call TopLoop ;color in each field
Pop DI ;retrieve screen location

GetLily:
Jmp GetInfo

TopLoop:
Push CX
Invoke SetScreenString,Word Ptr [DI+5],Word Ptr [DI+2],Byte Ptr [DI],Byte Ptr [DI+1],Byte Ptr [DI+4]
Pop CX
Add DI,7 ;move to next field
Loop TopLoop
Retn

NoSwitch:
Cmp Byte Ptr [DI],-1 ;did we hit the end?
Jnz @F ;no, keep going
Mov DI,SI ;retread pointer
Jmp GetInfo ;go for more input

@@:
Push CX
Invoke GetString,Word Ptr CS:[DI+5],Word Ptr CS:[DI+2],Byte Ptr CS:[DI],Byte Ptr CS:[DI+1],Byte Ptr CS:[DI+4]
Pop CX

;updown handler
Cmp AL,13 ;carriage return?
Jnz @F
Jmp NextField
@@:
Cmp AL,27 ;esc key pressed?
Jnz @F
Jmp Exit

@@:
Cmp AL,-68 ;F10 to print
Jnz @F
Jmp MenuDone ;jump to print the labels

@@:
Cmp AL,-60 ;F2 to test
Jnz @F
Mov Byte Ptr TestPrint,-1
Jmp MenuDone
@@:
Or AL,AL ;is it an extended key?
Jns SameField
Cmp AL,-72 ;up arrow
Jz LastField
Cmp AL,-15 ;shift tab
Jz LastField
Cmp AL,-80 ;down array
Jz NextField
Cmp AL,9 ;tab
Jmp NextField

SameField:
Jmp GetInfo ;loop back

NextField:
; checks for a Y on the return address
Call RetCheck ;don't do it here
Jc @F
Add DI,7 ;move to next field
@@:
Jmp GetInfo

LastField:
Sub DI,7
Cmp DI,SI ;is it less than offset?
Jl @F ;if it's not less then we're ok.
Jmp GetInfo
@@:
Mov DI,SI
Jmp SameField

RetCheck: ;check for return address field?
Cmp Word Ptr [DI+5], Offset RetAddrYN ;are we looking at the Ret field?
Jnz @F
Cmp Byte Ptr RetAddrYN,'N' ;get
Jnz @F
Mov DI,Offset CenterEnvLoc
Stc
RetN
@@:
Clc
RetN


MenuDone: ;Data List Processing starts here
Call SaveDefaultValues
Mov BX,Color ;get the color
Or BX,128 ;set hi bit to flash it
Invoke PrintZStr,Addr PrintMsg, BX, PrintMsgLoc
Call PrintLabels
Mov Byte Ptr TestPrint,0
Jmp MenuStart

Exit:
Push AX ;save error code
Xor DX,DX
Call SetCursor ;set cursor
Invoke CLS,0,0,18h,50h ;clear whole screen
Call UnHookInt24 ;put back int 24h
Pop AX ;retrieve error code
Mov AH,4Ch ;exit here
Int 21h ;
MLPrint EndP
;- End of main module code

Include MLPrint2.INC ;misc tested routines
Include MLPrint3.INC

DPrint Proc Near ;direct to screen printing routine
; Character in AL, attribute in AH
; ES:DI points to screen destination
Mov BX,AX ;put character into BL
Or DX,DX ;are we doing monochrome or EGA?
Jz Mono_Video1 ;yes, go do it

No_Retrace1:
In AL,DX ;get the video status byte
Test AL,1 ;test just the horizontal retrace bit
Jnz No_Retrace1 ;if doing a retrace, wait until it's not
Cli ;disable interrupts until we're done writing to screen

Retrace1:
In AL,DX ;get the status byte again
Test AL,1 ;are we currently doing a retrace?
Jz Retrace1 ;no wait until we are

Mono_Video1:
Mov AX,BX
Stosw ;store the character and attribute into screen memory
Sti ;re-enable interrupts
Ret
DPrint EndP

ExtError Proc Near
Mov AH,59h ;extended error service
Xor BX,BX ;clear BX
Int 21h
Cmp AX,53h ;Int 24h error!
Jnz @F
Mov AX,DOSErrCode
Cmp AX,2 ;file not found + int 24h = Disk not ready
Jnz @F
Mov AX,15h
@@:
Mov ErrorNum,AX
Or AX,AX ;no error
Jz ExtErrorExit
Push DI ;preserve DI
Cmp AX,2h ;File not found
Jnz @F
Invoke MessageBox,Addr FileNotFound
Jmp SetCExit
@@:
Cmp AX,3h ;Path Not Found
Jnz @F
Invoke MessageBox,Addr PathNotFound
Jmp SetCExit
@@:
Cmp AX,5h ;Access denied
Jnz @F
Invoke MessageBox,Addr AccessDenied
Jmp SetCExit
@@:
Cmp AX,15h ;drive not ready
Jnz @F
Invoke MessageBox,Addr DiskNotReady
Jmp SetCExit
@@:
Cmp AX,1ch ;out of paper
Jnz @F
Invoke MessageBox,Addr OutOfPaper
Jmp SetCExit
@@:
Invoke MessageBox,Addr UnKnownError
SetCExit:
Pop DI
ExtErrorExit:
Ret
ExtError EndP

;--- File is read in chunks into the 2k buffer and scanned for CRLF's.
;--- Errors are reported by message box.

PrintLabels Proc Near
;--- Open List file
Invoke OpenFile,Addr MFileBuff, 0 ;open list file
Jnc @F
Jmp ExitPrint
@@:
Mov LFileHandle,AX ;save file handle
Cmp UseDestFile,'N' ;are we using a destination file?
Jnz @F

Invoke OpenFile,Addr LPTFile, 2 ;open the printer port
Jnc LoadOutHandle

ErrorLily:
Jmp ExitPrint
@@: ;if using destination file then open it
Invoke OpenFile,Addr DestFile, 3c00h ;open the destfile port
Jc ErrorLily ;short jump to the error
Mov OFIleHandle,AX
Jmp @F

LoadOutHandle:
Mov OFIleHandle,AX ;save out file for printer
Invoke SetRawMode,OFileHandle
Jc ErrorLily
@@:
Cmp Byte Ptr UsePostNet,'N'
Jz @F
Call LoadBarMacros
@@:
Cmp Byte Ptr RetAddrYN,'N'
Jz @F
Call ReturnAdrMaker
@@:
Call MultLabel ;load up things
Cmp Byte Ptr LabelFlag,'L' ;L for labels, E for Envelopes
Jz SetUpLabel
Invoke Write,OFileHandle,Addr Landscape,5
Jc ExitPrint
Jmp @F

SetUpLabel:
Invoke Write,OFileHandle,Addr Portrait,5
Jc ExitPrint
Invoke Write,OFileHandle,Addr PerfSkip,5
Jc ExitPrint
@@:
Cmp Byte Ptr ManualFeed,'Y'
Jnz AutoFed
Mov BX,Offset ManFeed
Jmp @F

AutoFed:
Mov BX,Offset AutoFeed

@@:
Invoke Write,OFileHandle, BX,5
Jc ExitPrint
Call AddressReader

ExitPrint:
Ret
PrintLabels EndP

;start by checking file size and setting variables
AddressReader Proc Near
Xor AX,AX ;clear AX to clear everything else
Mov LoadFlag,AL
Mov Word Ptr CurFilePtr,AX ;clear file pointer
Mov Word Ptr CurFilePtr[2],AX ; dword = 0
Mov Word Ptr LSize,AX
Mov Word Ptr CurBufPtr,AX ;clear buffer pointer too
Mov Word Ptr FIBufferSz,800h ;Buffer Size 2K

Push DS
Pop ES

Invoke FileSize
Or DX,DX ;DX contains high word of size
Jnz BufferIsOk ;if it's got a value, then were ok
Cmp AX,FIBufferSz ;now check the low bytes
Jae BufferIsOk ;if atleast that size, then keep going
Mov FIBufferSz,AX ;assign the smaller size

BufferIsOk:
Mov DI,Offset AddressBuffer ;up to 16 lines! (just in case)
Call BufferLoad

Error1:
Jnc NoError1 ;error check
Cmp Word Ptr LSize,0 ;if there's something in the buffer
Jz @F ;then flush it (print)
Call PrintAddressBlock
Jc CloseUp
@@:
Invoke Write,OFileHandle,Addr Reset,2

CloseUp:
Invoke Close,LFileHandle
Invoke Close,OFileHandle
Stc ;set carry, and exit
Ret
NoError1: ;-- Buffer has info for now
Mov CX,FIBufferSz ;CX will have max to scan
Clc

SpaceLoop: ;eat leading spaces
Test Byte Ptr LoadFlag,1 ;in addr block?
Jz @F ;no, then strip away
Test Byte Ptr LoadFlag,2 ;ok, then have we stripped before?
Jnz CRLFLoop ;yes, we're done
@@:
Jcxz ReRead ;CX = 0 from delimit check
Lodsb
Cmp AL,32 ;space ?
Jz BumpLine ;yes, eat it up

Cmp AL,13 ;CR ?
Jz BumpLine ;yes eat that too

Cmp AL,10 ;LF ?
Jz BumpLine ;yes eat that too
Jmp @F

BumpLine:
Inc Byte Ptr LineCount
Jcxz ReRead ;just in case a zero slips by
Loop SpaceLoop ;eat the space
Jmp ReRead ;

CRLFLoop: ;moves bytes til it hits a delimeter
Lodsb ;grab a character

@@:
Call Checkey
Jc ParseLily ;if user hit escape then hangout
Or Byte Ptr LoadFlag,3 ;set Stripped
Jcxz ReRead ;CX = 0 from delimit check
Call Check4Delimiter
Or AL,AL ;bump a line?
Jz BumpLine ;kludgie, but it works
Cmp AL,1 ;are reading another chunk?
Jz ReRead
Cmp AL,-1 ;check for results of delimeter check
Jz NextAddr
Mov DX, LMax
Cmp Byte Ptr LineCount,DL ;if greater line count is done, then
Jg @F ;don't save it
Stosb ;store it otherwise
Inc Word Ptr LSize
@@:
Loop CrLfLoop

ReRead:
Cmp Word Ptr LFileSize[2],0
Jnz GetBuffer
Cmp Word Ptr LFIleSize,0
Jnz GetBuffer
Cmp Byte Ptr LabelFlag,'L' ;L for labels, E for Envelopes
Jnz ParseLily
Cmp Byte Ptr SheetDone,0
Jz ParseLily
Invoke Write,OFileHandle, Addr PageFeed,1
Jc ErrLily1

ParseLily:
Jmp ParseExit

GetBuffer:
Call BufferLoad ;load file

ErrLily1:
Jmp Error1 ;jump to start of loop again

; When printing, use left margin to control where address goes
; then you just need to use a crlf to go to next line.

NextAddr:
Call PrintAddressBlock
Jc ErrLily1
And Byte Ptr LoadFlag,011111110b ;clear in address flag
Cmp Byte Ptr LabelFlag,'L' ;L for labels, E for Envelopes
Jnz EnvOnly
Cmp Byte Ptr TestPrint,0
Jz KeepPrinting
Cmp Byte Ptr SheetDone,0
Jnz KeepPrinting
Jmp TestOut

EnvOnly:
Cmp Byte Ptr TestPrint,0
Jz KeepPrinting

TestOut:
Mov Word Ptr LSize,0
Mov Byte Ptr TestPrint,0
Jmp ParseExit


KeepPrinting:
Mov DI,Offset AddressBuffer ;freshen up address buffer
Mov Word Ptr LSize,0 ;clear lsize
Jmp BumpLine ;jump to the loop to dec CX correctly

ParseExit:
Cmp Word Ptr LSize,0 ;if there's something in the buffer
Jz @F
Call PrintAddressBlock
Jc CloseUp2
@@:
Invoke Write,OFileHandle,Addr Reset,2

CloseUp2:
Invoke Close,LFileHandle ;close both files and return
Invoke Close,OFileHandle ;to the main menu
Clc ;clearing carry to show
Ret

Check4Delimiter:
Cmp AL,13 ;is it a CR?
Jz CR1
Cmp AL,10 ;is it a LF?
Jz LF1
Jmp NotDelimiter
CR1:
Stosb ;store it
Inc Word Ptr LSize ;bump size of label up.
Jcxz EndOfFile ;check for end of buffer

Dec CX ;count it
Lodsb ;get next one
LF1:
Stosb ;store it
Inc Word Ptr LSize ;bump size of label up.
Jcxz EndOfFile ;check for end of buffer

Cmp Byte Ptr [SI],13 ;is next one a CR?
Jnz @F ;nope go get another line,
Dec CX ;count it
Inc SI ;skip to end of file
Dec CX
Inc SI

EndOfBuffer:
Mov AL,-1 ;tell caller, that's all folks
Jmp NotDelimiter

EndOfFile:
Mov AL,1 ;Go read file
Jmp NotDelimiter ;this is a real fudge!

@@:
Mov AL,0 ;Tell caller it's just another line
Jmp NotDelimiter

NotDelimiter:
Retn

BufferLoad: ;start here for the read!
Cmp Word Ptr LFileSize,0 ;check for zero bytes left
Jnz @F ;low word, ok!
Cmp Word Ptr LFileSize[2],0 ;high word?
Jnz @F ;high word ok!
Stc ;no, both zero, exit with carry set
Retn
@@:
Cmp Word Ptr LFileSize[2],0 ;no problem if high word has value
Jnz @F ; the buffer is fine
Mov AX,Word Ptr LFileSize ;get size of low word of file
Cmp AX,FiBufferSz ;if what's left is smaller than
Jae @F ; buffer, use that size
Mov FiBufferSz,AX ; to just read that much
@@:
Mov SI,Offset FileInBuffer ;get start of buffer

Invoke Seek,LFileHandle, CurFilePtr
Invoke Read,LFileHandle, Addr FileInBuffer, FiBufferSz
Jc @F
Mov Word Ptr CurBufPtr,0 ;clear a counter
Mov AX,FiBufferSz
Sub Word Ptr LFileSize,AX ;track our file size left
Sbb Word Ptr LFileSize[2],0
Add Word Ptr CurFilePtr,AX ;move file pointer along
Adc Word Ptr CurFilePtr[2],0
@@:
Ret
AddressReader EndP

PrintAddressBlock Proc Near
Push CX
Mov Byte Ptr LineCount,0 ;keep track of number of lines....
Invoke ClearPunct,Addr AddressBuffer, LSize
Call AddrPrint
Pop CX
Ret
PrintAddressBlock EndP

AddrPrint Proc Near ;Print Address bloc
Push SI
Push CX ;Check for envelope or label -
Cmp Byte Ptr LabelFlag,'L' ;L for labels, E for Envelopes
Jnz DoEnvelope
Call PrintSheet
Call ZipAndAdrPrint
Jc @F
Cmp Byte Ptr SheetDone,0
Jnz @F
Invoke Write,OFileHandle, Addr PageFeed,1
Jc @F
Invoke Write,OFileHandle, Addr TopMargin, 5 ;resets top margin
@@:
Jmp ADPExit

DoEnvelope: ;-- check and do return address
Mov DX,Offset Personal
Cmp Byte Ptr EnvCentered,'Y'
Jz @F
Add DX,CenterJump
@@:
Mov AL,EnvSize
Xor AH,AH
Sub AX,'1'
Mov CX,TotalLen
Mul CL
Add DX,AX
Push DX
Invoke Write,OFileHandle, DX, FirstLen
Jc ADPExit
Cmp Byte Ptr RetAddrYN,'N'
Jz @F
Invoke FireMacro,12 ;macro for return address
Jc ADPExit
Invoke Write,OFileHandle, Addr CRLF, 2
Jc ADPExit
@@:
Pop DX
Add DX,FirstLen
Invoke Write,OFileHandle, DX, SecondLen
Jc ADPExit
Call ZipAndAdrPrint
Jc ADPExit
Invoke Write,OFileHandle, Addr PageFeed,1

ADPExit:
Pop CX
Pop SI
Ret

ZipAndAdrPrint:
Invoke FindZip ,Addr AddressBuffer,Addr ZipString, LSize
Cmp Byte Ptr UsePostNet,'N'
Jz @F
Invoke PrintZipBarcode,Addr ZipString
Jc ZipErrExit
Invoke Write,OFileHandle, Addr CRLF, 2
Jc ZipErrExit
Invoke Write,OFileHandle, Addr CRLF, 2
Jc ZipErrExit
@@:
Invoke Write,OFileHandle, Addr AddressBuffer , LSize
Jc ZipErrExit

ZipErrExit:
Retn
AddrPrint EndP

ReturnAdrMaker Proc Near ;-create a macro
Push DI
Invoke StartMacro,12 ;macro 12 for return addr
Mov DI,Offset RetLabel1Adr ;get first line
Mov CX,6

RetPrintLoop:
Push CX
Invoke Write,OFileHandle,[DI], 40 ;write up to 40 characters

Jc RetAErrExit
Invoke Write,OFileHandle, Addr CRLF,2
Jc RetAErrExit
Add DI,7
Pop CX
Loop RetPrintLoop
Invoke EndMacro
RetErrExit:
Pop DI
Retn
RetAErrExit:
Pop CX
Jmp RetErrExit
ReturnAdrMaker EndP

FindZip Proc Near Uses DI SI, AdrBuffer:Word, ZipBuffer:Word, MaxChars:Word
Push DS
Pop ES
Mov CX,12 ;try up to 20 chars
Mov DI,ZipBuffer ;get pointer to zip buffer
Push DI ;save it for a second
Mov AL,20h ;use a space
Rep Stosb ;clear it with spaces
Pop DI
Add DI,9 ;point DI at end
Mov SI,AdrBuffer ;get pointer to address buffer
Mov CX,MaxChars
Dec CX
Add SI,CX
Std ;scan backwards
Xor DX,DX ;use DX for a flag
Xor BX,BX
;flags - DH = Zip number count <= 9, BH = CRLF count
; BL = other character count, DL = space count
ZipLoop:
Lodsb ;get a character
Call IsNumber ;is it a number?
Jc CheckChar1 ;@F ;not a number
Cmp DH,9
Jge CheckChar1 ;have we gotten more than 9?,
Cmp BH,1 ;more than one CRLF?
Jg CheckChar1 ;sorry, no way dude
Or BL,BL ;any other character between?
Jnz CheckChar1 ;yes, end of zip
Inc DH ;count it
Stosb ;store number
Loop ZipLoop
CheckChar1:
Cmp AL,32 ;space?
Jnz CheckLF
Cmp DH,4 ;have we gotten 4 characters?
Jne @F
Cmp [SI],AL ;is the next char a space???
Jz @F ;yes, then thats about it
Mov Byte Ptr [SI+1],'-' ;put the dash back
@@:
Loop ZipLoop ;eat space

CheckLF:
Cmp AL,10 ;Line feed?
Jnz NextChar
Cmp Word Ptr FirstCRLF,0
Jnz @F
Mov FirstCRLF,SI ;save it
@@:
Or BL,BL ;have we gotton past the zip?
Jnz NumbersDone
Dec SI ;clear then next
Loop ZipLoop ;go back for more
NextChar:
Cmp AL,20h ;is it a space?
Jz @F
Mov BL,1
Jmp NumbersDone
@@:
Loop ZipLoop
NumbersDone: ;slide zip, state and
; city up to one line
Mov ZipCount,DH ;save Zipcount
SlideLeft:
Mov SI,AdrBuffer ;get pointer to address buffer
Mov CX,MaxChars
Dec SI
Add SI,CX
Mov DX,CX
Mov DI,SI ;point DI at the end too
Mov AL,10 ;look for that last CRLF
Xor BX,BX ;flags
Scan4LF:
Repne Scasb ;scoot backwards looking for 10
Or BL,BL ;been here before?
Jnz @F
Sub DX,CX ;is this the last one?
Mov BL,-1 ;signal once through
Cmp DX,2 ;is it it the first position
Jle Scan4LF ;go back again
@@:
Mov DX,MaxChars ;get total size of buffer yet again
Sub DX,CX ;get length of last line
Xchg CX,DX
Cld ;forward scan now
Mov SI,DI ;point SI at current position.
Mov AH,20h ;scan for a space
Xor BX,BX ;BH = number of spaces eaten, BL = in/out space flag
ScanLoop:
Lodsb ;get a character
Cmp AL,AH ;is it a space?
Jnz @F
Or BL,BL ;did we get one?
Jnz EatSpace ;yes we'll just eat it
Stosb ;store it.
Mov BL,-1 ;set first space
Loop ScanLoop ;
Jmp PadSpaces

@@:
Cmp BL,-1 ;are we coming back to characters
Jnz @F
Xor BL,BL
@@:
Stosb ;store it
Loop ScanLoop ;go back for more
Jmp PadSpaces
EatSpace:
Inc BH
Loop ScanLoop ;go back for more

PadSpaces:
Or BH,BH ;any spaces to finish?
Jz DPLoop
Xor CH,CH ;clear CH to all of CX
Mov CL,BH ;spaces in BH
Mov AL,AH
Rep Stosb

DPLoop: ;delivery point loop
Mov CX,10 ;currently we're at 10 digits
Cmp Byte Ptr ZipCount,9 ;do we have exactly 9?
Jnz NormalizeZip ;nope, than no DP chars
Cmp Byte Ptr DPFlag,'N' ;are we even doing a DP Flag?
Jz NormalizeZip ;nope, then skip this section altogether
Mov DI,AdrBuffer ;get pointer to address buffer
Mov CX,MaxChars
Sub CX,9 ;start back since we know we might have
Dec DI ; an ending CRLF (back up width of zip)
Add DI,CX
Mov AL,10 ;look for that last LF
Std ;reverse direction
Xor BL,BL

@@:
Inc BL ;set a through flag
Repne Scasb ;scan til we find that CR
Cmp BL,1 ;been though before?
Jz @B ;go back once more...
Mov SI,DI ;move it into SI for next phase
Mov DI,ZipBuffer ;destination
Add DI,10 ;go to end of buffer
Xor BX,BX
Cld ;forward move now
Add SI,2 ;move SI up past last characters

GetDPLoop:
Inc BL ;character counter
Lodsb
Cmp AL,20h ;is it a space?
Jz @F
Mov BH,1 ;set BH for start of characters...
Loop GetDPLoop ;go back for more
@@:
Or BH,BH ;if BH = 0 then we're stripping spaces
Jnz @F
Loop GetDPLoop

@@:
Dec SI

TryNumber: ;get 2
Dec SI
Dec BL ;
Jz Put99 ;that's all
Mov AL,[SI] ;get a character
Call IsNumber
Jc TryNumber ;nope, go back for more
Mov [DI+1],AL ;put character in
Dec SI
Dec BL
Jz PutZero ;no more, put zero
Mov AL,[SI] ;get the number
Call IsNumber
Jc PutZero
Mov [DI],AL ;put the number
Jmp @F

PutZero:
Mov Byte Ptr [DI],30h ;put a zero in there
Jmp @F
Put99:
Mov Word Ptr [DI],3939h ;put a 99 in the end of the code
@@:
Mov CX,12 ;reflect extra digits
Jmp NormalizeZip

NormalizeZip:
Cld ;clear direction to go forward
Mov DI,ZipBuffer ;get start of zip
Mov SI,DI

ClearSpace:
Lodsb ;get a character
Call IsNumber ;is it a number
Jc @F
Stosb
@@:
Loop ClearSpace
Mov [DI],CL ;store a zero
Ret
FindZip EndP

;redirects Int24 to our own error handler
HookInt24 Proc Near

Mov AX,3524h ;get Int24 vector
Int 21h ; into ES:BX
Mov OldInt24IP,BX ; and save.
Mov OldInt24CS,ES

Lea DX,Int24ErrHandler ;DS = CS of CEH
Mov AX,2524h ;revector Int24h
Int 21h
Retn
HookInt24 EndP

;Function: Restores the original Int24 vector that was saved by HookInt24
UnHookInt24 Proc Far

Push DS ;save registers
Push DX
Push AX
Push SS ;set DS = DGROUP
Pop DS
Mov DX,OldInt24IP ;get the original Int24 vector
Mov DS,OldInt24CS
Mov AX,2524h ;restore the vector
Int 21h

Pop AX ;restore registers
Pop DX
Pop DS
Ret
UnHookInt24 EndP

;On entry: Error code in DI (provided by DOS)
; On exit: DOSErrCode = Critical error
; AL directs DOS to ignore the error

Int24ErrHandler Proc Near ;our replacement error handler
Sti ;restore interrupts
Push DI ;save DI
Push DX ;save DX
Push DS ;save DS
Push AX ;save AX
Mov CS:DOSErrCode,DI ;save error code
CEH_Exit:
Mov CS:CritErrFlag,1 ;verify that a critical error occurred
Pop AX ;restore AX (really just AH)
Mov AL,0 ;tell DOS to ignore the error
Pop DS ;restore DS
Pop DX ;restore DX
Pop DI ;restore DI
Iret ;get back to dos
Int24ErrHandler EndP
;-- prints multiple label sheets

MultLabel Proc Near
Mov BX,LabelIndex ;grab label index
Or BX,BX ;if it's zero
Jz @F ;it's never been touched
Dec BX ;otherwise make it zero based
@@:
Mov SI,Offset A5160 ;get address of start of
Mov AX,AVLen ;get length of data
Mul BL ;multiply by index to get offset to data
Add SI,AX ;address via DI
Mov CX,7
Mov DI,Offset Across ;get address of temp variable
Rep Movsw ;slide the variables from table to temps
Mov Byte Ptr SheetDone,0
Retn
MultLabel EndP

PrintSheet Proc Near
Inc Byte Ptr SheetDone
Call SetLocation
Inc Word Ptr SAcross ;bump to next column/label
Mov AX,Across ;get value of across
Cmp SAcross,AX ;are we there yet?
Jnz @F
Mov SAcross,0
Inc Word Ptr SDown ;bump to next Row
Mov AX,Down ;get value of down
Cmp SDown,AX ;are we done with the sheet
Jnz @F
Mov SDown,0
Mov SAcross,0
Mov Byte Ptr SheetDone,0
@@:
Retn

SetLocation:
Mov CX,24 ;move 10 Words
Mov DI,Offset InfoBuf
Xor AL,AL
Push DI
Rep Stosb ;clear buffer
Pop DI
;---Horizontal
Mov BX,SAcross ;get number of labels across so far
Mov AX,LWidth ;get width
Mul BL ;multiply by BL (never more then 3 across)
Add AX,LeftSide ;add the left margin
Push AX ;save left margin for setting
Invoke Num2Ascii,AX,DI ;convert number to text
Mov AH,'l'
Call MoveDI
Pop AX
Invoke Num2Ascii,AX,DI
Mov AH,'C' ;horizontal cursor setting
Call MoveDI
Mov AH,27
Call MoveDI
Mov AH,'*'
Call MoveDI
Mov AH,'p'
Call MoveDI
Xor DX,DX ;
Mov BX,SDown ;now number of rows down
Mov AX,LHeight ;and height of labels
Mul BX
Add AX,TopMarg ;add in the top margin for the labels
Push AX
Pop AX
Invoke Num2Ascii,AX,DI ;go to next
Mov AH,'Y' ;set vert dot location
Call MoveDI
Mov AX,Offset LocBuffer
Sub DI,AX ;get length by subtracting difference
Invoke Write,OFileHandle, Addr LocBuffer, DI
Retn

MoveDI:
Mov CX,5
Xor AL,AL
Repne Scasb
Dec DI
Mov AL,AH
Stosb
Retn
PrintSheet EndP

Checkey Proc Near
Push AX
Mov AH,1h ;service 0
Int 16h ;wait for a character
Jz @F
Mov AH,0 ;eat key
Int 16h
Invoke MessageBox, Addr WaitMsg
Pop AX
Ret
@@:
Clc
Pop AX
Ret
Checkey EndP

HelpCursor DW 0

HelpPrint Proc Near
Push AX
Push BX
Push CX
Push DX
Push SI
Push DI
Invoke CursorOff, Addr HelpCursor
Call SaveScrn
Mov ES,ScrnSeg
Mov DI,OffSet HelpScrn
Invoke PrintZStr, DI, 31, 0
Call GetChar
Call RestScrn
Invoke CursorOn, CS:HelpCursor
Pop DI
Pop SI
Pop DX
Pop CX
Pop BX
Pop AX
Ret
HelpPrint EndP

END Start


  3 Responses to “Category : Files from Magazines
Archive   : VOL11N21.ZIP
Filename : MLPRINT.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/