/*
┌─ Programa ───────────────────────────────────────────────────────────────┐
│ Aplication: Class TDosPrint │
│ File: TDOSPRN.PRG │
│ Date: 09/13/96 │
│ Time: 20:20:07 │
└──────────────────────────────────────────────────────────────────────────┘
NOTES:
The following code will let you print directly to the printer from inside
any Fivewin program, like OLD DOS days. Those users that need DOS printing
speed can use this class instead of the TPrinter class.
This is a little sample of how to use the new class:
LOCAL oPrn
oPrn := TDosPrn():New("lpt1")
oPrn:StartPage() // optional
oPrn:Say(10,20, "This goes in line 10, column 20")
oPrn:EndPage() // optional
oPrn:End()
A little description of all the members of this class:
DATA:
cPort: Printing port, by default "LPT1"
cCompress: String for compressed mode, by default "15"
cNormal: String for normal mode, by default "18"
cFormFeed: String for EJECT, by default "12"
hDC: Printing file Handle (Internal use)
nRow: Current printing row
nCol: Current pringing column
nLeftMargin: Left margin, by default 0
nTopMargin: Top margin, by default 0
lAnsiToOem: If .T. a Ansi to Oem translation is done automatically
whe printing, by default is .T.
lScreen
METHODS:
New(cPort) Constructor, no comment
End() Destructor, no comment
StartPage() Begining of a page, this method is optional
EndPage() End of page, this method is optional if there is only on page
Command(c) Let you send any command to the printer without changing the
current row and col. The string to pass as a parameter should
content the ascii values of the command separated with commas,
for example, the command to reset Epson printers should
be: "27,69"
SetCoors(r,c) Let you change the current row and col is the equivalent of
SetPrc() of Ca-Clipper
NewLine() Increments the current row
Write(cText) Prints the string cText in the current row and column
Say(nRow ,; Prints the string cText in nRow, nCol
nCol ,; lAtoO indicates if the string should be transformed to Oem,
cText ,; by default is ::lAnsiToOem
lAtoO )
SayCmp() The same as the method Say but prints in compressed mode and
the row is updated accordly.
NOTE:
If you try to print on a row before the current one a EJECT will be
done automatically.
In the same way if you try to print on the same row as the current, but
in a previous column from the current one a EJECT will be done automatically
At the end of this class is a little function call WorkSheet that will make
the job of DOS printing a lot easier.
Enjoy it!
*/
#include "fivewin.ch"
#include "fileio.ch"
#translate nTrim(<n>) => AllTrim(Str(<n>,10,0))
#define PF_BUFLEN 2048
//----------------------------------------------------------------------------//
CLASS TDosPrn
DATA LastError
DATA cPort, cCompress, cNormal, cFormFeed, cBuffer, cOrgPort
DATA cInitPrn //RDC
DATA cNegOn //RDC
DATA cNegOff //RDC
DATA cItaOn //RDC
DATA cItaOff //RDC
DATA cEmpOn //RDC
DATA cEmpOff //RDC
DATA c10Cpi //RDC
DATA c12Cpi //RDC
DATA cWidOn //RDC
DATA cWidOff //RDC
DATA hDC, nRow, nCol, nLeftMargin, nTopMargin AS NUMERIC
DATA lAnsiToOem AS LOGICAL
DATA oWnd, oPagina // Ednaldo
DATA nPage AS NUMERIC // Ednaldo
DATA cDevice // Ralph
DATA nMaxLine, nLength, nLastError AS NUMERIC // Ralph
DATA lCancel, lPreview, lModograf, lIsLaser AS LOGICAL // Ralph
DATA lUserConfig AS LOGICAL INIT .F. // Anser
METHOD New(lUserConfig) CONSTRUCTOR // Mdified by Anser to pass the parameter lUserConfig
METHOD End()
METHOD StartPage() INLINE ::ShowProc() // Ednaldo
METHOD EndPage()
METHOD Command(xPar1, xPar2, xPar3, xPar4, xPar5)
METHOD SetCoors(nRow, nCol)
METHOD NewLine() INLINE (::cBuffer += CRLF ,;
::nRow++ ,;
::nCol := 0 )
METHOD Write(cText, lAToO) ;
INLINE (iif(lAtoO == NIL, lAtoO := .T.,),;
::cBuffer += iif(lAtoO, AnsitoOem(cText), cText) ,;
::nCol += len(cText) )
METHOD Say(nRow, nCol, cText, lAToO)
METHOD SayCmp(nRow, nCol, cText)
METHOD PrintFile(cFile)
METHOD ShowProc() // Ednaldo
METHOD PrintSetup() // Ralph
ENDCLASS
//----------------------------------------------------------------------------//
METHOD New(lUserConfig) CLASS TDosPrn
::cCompress := "15"
::cNormal := "18"
::cFormFeed := "12"
::cInitPrn := "18,27,80"
::cNegOn := "27,71"
::cNegOff := "27,72"
::c10cpi := "27,80"
::c12cpi := "27,77"
::cWidOn := "27,87,1"
::cWidOff := "27,87,0"
::cBuffer := ""
::nLeftMargin := 0
::nTopMargin := 0
::nRow := 0
::nCol := 0
::lAnsiToOem := .T.
::cPort := StrTran( PrnGetPort(), ":", "" )
::nLastError := fError()
::lUserConfig :=lUserConfig
if ::nLastError <> 0
MsgInfo('There is no printer available')
endif
::cDevice := ::cPort+iif(!"."$::cPort,".PRN","")
::hDC := fCreate(::cPort)
::lPreview := .t.
::lCancel := .f.
::nMaxLine := 66
::nLength := 66
::lModoGraf := .f.
::lIsLaser := .f.
::nPage := 1 // Ednaldo
::PrintSetup() //Ralph
RETURN Self
//----------------------------------------------------------------------------//
METHOD End() CLASS TDosPrn
IF !empty(::nRow+::nCol)
::EndPage()
ENDIF
::LastError := 0
IF !fClose(::hDC)
::LastError := fError()
ENDIF
CursorArrow()
if ::oWnd != Nil // Ednaldo
::oWnd:End() // Ednaldo
endif // Ednaldo
RETURN NIL
//----------------------------------------------------------------------------//
METHOD EndPage() CLASS TDosPrn
LOCAL nFor, nLen, nSec
LOCAL lError
::Command(::cFormFeed)
::LastError := 0
IF fWrite(::hDC, ::cBuffer) < len(::cBuffer)
::LastError := fError()
ENDIF
::cBuffer := ""
::nRow := 0
::nCol := 0
RETURN NIL
//----------------------------------------------------------------------------//
METHOD Command(xPar1, xPar2, xPar3, xPar4, xPar5) CLASS TDosPrn
LOCAL cCommand, cToken, cString
LOCAL nToken
cString := cValToChar(xPar1)
IF xPar2 != NIL
cString += ","+cValToChar(xPar2)
ENDIF
IF xPar3 != NIL
cString += ","+cValToChar(xPar3)
ENDIF
IF xPar4 != NIL
cString += ","+cValToChar(xPar4)
ENDIF
IF xPar5 != NIL
cString += ","+cValToChar(xPar5)
ENDIF
cCommand := ""
nToken := 1
DO WHILE !Empty(cToken := StrToken(cString, nToken++, ","))
cCommand += Chr(Val(cToken))
ENDDO
::cBuffer += cCommand
RETURN NIL
//----------------------------------------------------------------------------//
METHOD SetCoors(nRow, nCol) CLASS TDosPrn
nRow += ::nTopMargin
nCol += ::nLeftMargin
IF ::nRow > nRow
::EndPage()
::nPage++ // Ednaldo
::StartPage()
ENDIF
IF nRow == ::nRow .AND. nCol < ::nCol
::EndPage()
::nPage++ // Ednaldo
::StartPage()
ENDIF
DO WHILE ::nRow < nRow
::NewLine()
ENDDO
IF nCol > ::nCol
::Write(Space(nCol-::nCol))
ENDIF
RETURN NIL
//----------------------------------------------------------------------------//
METHOD Say(nRow, nCol, cText, lAToO) CLASS TDosPrn
DEFAULT lAToO := ::lAnsiToOem
IF VALTYPE( cText ) = "D"
cText := DTOC( cText )
ENDIF
IF VALTYPE( cText ) = "N"
cText := STR( cText )
ENDIF
::SetCoors(nRow, nCol)
::Write(cText, lAToO)
RETURN NIL
//----------------------------------------------------------------------------//
METHOD SayCmp(nRow, nCol, cText, lAToO) CLASS TDosPrn
DEFAULT lAToO := ::lAnsiToOem
::SetCoors(nRow, nCol)
::Command(::cCompress)
::cBuffer += iif(lAToO, AnsitoOem(cText), cText)
::nCol += Int(len(cText)/1.7+.5)
::Command(::cNormal)
RETURN NIL
//----------------------------------------------------------------------------//
METHOD PrintFile(cFile) CLASS TDosPrn
LOCAL hFile
LOCAL nRead
LOCAL cBuffer
hFile := FOpen(cFile, FO_READ)
IF hFile < 0
RETURN .F.
ENDIF
cBuffer := Space(PF_BUFLEN)
DO
nRead := fRead(hFile, @cBuffer, PF_BUFLEN)
IF fWrite(::hDC, Left(cBuffer, nRead)) < nRead
::LastError := fError()
fClose(hFile)
RETURN .F.
ENDIF
UNTIL nRead == PF_BUFLEN
fClose(hFile)
RETURN .T.
//----------------------------------------------------------------------------//
// Print Process status display // Ednaldo
//----------------------------------------------------------------------------//
METHOD ShowProc() CLASS TDosPrn
IF ::oWnd = Nil
DEFINE DIALOG ::oWnd TITLE "Printing..." ;
FROM 230, 217 TO 360, 575 PIXEL
* @ 10, 08 TO 40, 172 OF ::oWnd PIXEL
@ 1.4, 2 ICON NAME "PRINT.ICO" OF ::oWnd
@ 25, 45 SAY "Printing Page:" PIXEL OF ::oWnd SIZE 65, 12 RIGHT
@ 25, 115 SAY ::oPagina VAR ::nPage PIXEL OF ::oWnd UPDATE SIZE 20, 12 RIGHT
@ 47, 60 BUTTON "Wait..." SIZE 60, 12 PIXEL OF ::oWnd ACTION .t.
::oWnd:bPainted := {|| iif(::nPage>0, ::oPagina:Refresh(), )}
ACTIVATE DIALOG ::oWnd CENTER NOWAIT
CursorWait()
SysRefresh()
ELSE
::oWnd:BeginPaint()
::oWnd:Paint()
::oWnd:EndPaint()
ENDIF
RETURN NIL
//----------------------------------------------------------------------------//
FUNCTION WorkSheet(cPort)
LOCAL oPrn
LOCAL cLine
LOCAL nFor
cLine := ""
FOR nFor := 0 TO 7
cLine += Str(nFor,1)+Replicate(".",9)
NEXT
cLine := Substr(cLine,3)
oPrn := TDosPrn():New(cPort)
oPrn:StartPage()
FOR nFor := 0 TO 65
oPrn:Say(nFor,0,StrZero(nFor,2)+cLine)
NEXT
oPrn:EndPage()
oPrn:End()
RETURN NIL
//----------------------------------------------------------------------------//
// Parameters for Printer by the user // Ralph
METHOD PrintSetup() CLASS TDosPrn
//----------------------------------------------------------------------------//
local oDlg, oRad, oChk, oSay := array(4)
local nModo := 1
local nLinP := ::nLength, lPreview := .f.
local nTipo, oP := self
local oBtnOk, oBtnCn, oBtnSetup, oBtnAtrib, cModoImp
::lCancel := .t.
// we closed the port to be opened to the top
if (::hDC # -1) .and. ! fClose(::hDC)
::nLastError := fError()
endif
cOutPort := ::cPort
cPrnName := PrnGetName()
lPreview := ::lPreview
nModo := iif (::lModoGraf, 2, 1)
nLinP := ::nLength
// Added by Anser
// ActivePrnType() will return .T. if the selected printer is DOT MAtrix, else .F.
// Now the class itself decides whether Graphics or Text and the user is not given the choice
// By doinf this we can avoid error caused when a user selects text and print to a Laser or Inkjet
// Because if user select Text the we use the DosPrint.Bat to copy the file to the port
nModo:=if( ActivePrnType(), 1, 2)
// Added by Anser, the dialog is displayed only when the users Passes .T. while creating the TDosPrn Object
// This will avoid the second time display of the dialog when the user clicks on the Print button from the
// Print Preview Window
if ::lUserConfig
DEFINE DIALOG oDlg TITLE "Printer" ;
FROM 129, 178 TO 333, 670 PIXEL OF ::oWnd
* @ 06, 08 TO 84, 240 OF oDlg PIXEL PROMPT "Printer:"
@ 15, 15 SAY "Name :" PIXEL OF oDlg SIZE 30, 8
@ 24, 15 SAY "Type :" PIXEL OF oDlg SIZE 30, 8
@ 33, 15 SAY "Port :" PIXEL OF oDlg SIZE 30, 8
// Added by Anser just to display to user the port going to be used
@ 42, 15 SAY "Print to :" PIXEL OF oDlg SIZE 30, 8
@ 52, 15 SAY "Lines per page :" PIXEL OF oDlg SIZE 50, 8
@ 62, 15 SAY "Print Mode " PIXEL OF oDlg SIZE 40, 8
@ 14.8,205 BUTTON "Printer" SIZE 30,10 PIXEL OF oDlg ;
ACTION (PrinterSetup(),;
oSay[1]:Settext(PrnGetName()), ;
oSay[2]:Settext(PrnGetDrive()),;
cOutPort := PrnGetPort() ,;
oSay[3]:Settext(cOutPort),;
oSay[4]:Settext( TDosPrnPort(cOutPort) ),;
oSay[1]:refresh(),oSay[2]:refresh(),;
oSay[3]:refresh(),oSay[4]:refresh(), sysrefresh(),;
nModo:=if( ActivePrnType(), 1, 2), oRad:Refresh() ) // ActivePrnType is used
@ 15, 55 SAY oSay[1] PROMPT PrnGetName() PIXEL OF oDlg SIZE 150, 8
@ 24, 55 SAY oSay[2] PROMPT PrnGetDrive() PIXEL OF oDlg SIZE 150, 8
@ 33, 55 SAY oSay[3] PROMPT cOutPort PIXEL OF oDlg SIZE 150, 8
@ 42, 55 SAY oSay[4] PROMPT TDosPrnPort(cOutPort) PIXEL OF oDlg SIZE 150, 8
@ 51.4,55 GET nLinP SIZE 20, 11 PIXEL OF oDlg UPDATE ;
VALID nLinP > 0 .and. nLinP <= 140 PICTURE "999"
// Modified by Anser so that the radio is read only, I have used WHEN .F.
@ 62, 55 RADIO oRad VAR nModo ;
ITEMS "&Text (Dot matrix)", "&Graphics (InkJet/Laser)" ;
When .F. SIZE 63, 10 PIXEL OF oDlg
@ 61,150 CHECKBOX oChk VAR lPreview PROMPT "Preview" SIZE 40, 10 PIXEL OF oDlg
@ 89,125 BUTTON "&OK" SIZE 50,11 PIXEL OF oDlg ;
ACTION ( ::lCancel := .f., oDlg:End() )
@ 89, 180 BUTTON "&Cancel" SIZE 50,11 PIXEL OF oDlg ;
ACTION ( ::lCancel := .t., oDlg:End() ) CANCEL
ACTIVATE DIALOG oDlg CENTERED
Endif
if ! ::lCancel
::lModoGraf := ( nModo = 2 )
::lPreview := lPreview
::nLength := nLinP
::nMaxLine := ::nLength
if ::lIsLaser
::cCompress := "27,40,115,49,56,72"
::cNormal := "27,40,115,49,50,72"
if ::nWidth > 132
::cCompress := "27,40,115,50,50,72"
endif
else
::cCompress := "15"
::cNormal := "18"
endif
// Added by Anser
// This function will return the string \\PcName\PrintShareName if the user selected
// a Dot Matrix Network printer
if ISNetWorkPrn( PrnGetName() ) .and. left(cOutPort,3) == "LPT"
cOutPort:=PrnPortUrl( PrnGetName() )
Endif
if ::lPreview
::cPort := cOutPort
::cDevice :=".\"+ Upper( cTempFile() ) // ".\" added by Anser
else
::cPort := StrTran( cOutPort, ":", "" )
::cDevice := trim(::cPort)
endif
if ( ::hDC := fCreate(::cDevice) ) < 0
::lCancel := .t.
::nLastError := fError()
MsgInfo( "Error [" + str(::nLastError) + "] : Print Canceled "+;
"Unable to create "+ ::cDevice, "Error" )
endif
endif
Return NIL
*------------------------------------------*
Static Function TDosPrnPort(cOutPort)
*------------------------------------------*
// This fuction is added by Anser
// This function will return the string \\PcName\PrintShareName if the user selected
// a Dot Matrix Network printer
Local cPrintToPort:=""
if ISNetWorkPrn( PrnGetName() ) .and. left(cOutPort,3) == "LPT"
cPrintToPort:=PrnPortUrl( PrnGetName() )
else
cPrintToPort:=cOutPort
Endif
Return cPrintToPort