Files
harbour-core/harbour/examples/hbvpdf/hbvpdft.prg
Viktor Szakats 6ff6aa0f45 2009-09-16 12:59 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
* utils/hbmk2/examples/contribf.hbc
  * contrib/Makefile
  - contrib/hbvpdf
  + examples/hbvpdf
    * Moved hbvpdf lib to examples section.
      This code is barely updated and offers duplicate functionality
      of superior hbhpdf lib.

  * source/rtl/filesys.c
    * Minor formatting.
2009-09-16 11:00:23 +00:00

2647 lines
76 KiB
Plaintext

/*
* $Id$
*/
//-------------------------\\
//
// Program Cl_Pdf.prg
//
// Original : Victor K. . http://www.ihaveparts.com
//
// Class Code : Pritpal Bedi . http://www.vouchcac.com
//
//-------------------------\\
#ifndef __HARBOUR__
#ifndef __XPP__
#define __CLP__
#endif
#endif
#ifdef __HARBOUR__ // Harbour and xHarbour
#include "hbclass.ch"
#endif
#ifdef __XPP__ // Xbase++
#command CREATE CLASS <x> [ FROM <y> ] => CLASS <x> [ FROM <y> ]
#command MESSAGE <x> METHOD <y> => METHOD <x> IS <y>
#command CLASS MESSAGE <x> METHOD <y> => CLASS METHOD <x> IS <y>
#endif
#ifdef __CLP__ // Clipper
#include "class(y).ch"
#endif
//-------------------------\\
#include "hbvpdf.ch"
//-------------------------\\
CREATE CLASS tPdf
#ifndef __HARBOUR__
EXPORT:
#endif
VAR aReport
#ifndef __HARBOUR__
EXPORT:
#endif
#ifdef __HARBOUR__
METHOD Init( cFile, nLen, lOptimize ) CONSTRUCTOR
#else
METHOD Init
#endif
METHOD AtSay
METHOD Normal
METHOD Bold
METHOD Italic
METHOD UnderLine
METHOD BoldItalic
METHOD BookAdd
METHOD BookClose
METHOD BookOpen
METHOD Box
METHOD Box1
METHOD Center
METHOD Close
METHOD Image
METHOD Length
METHOD NewLine
METHOD NewPage
METHOD PageSize
METHOD PageOrient
METHOD PageNumber
METHOD Reverse
METHOD RJust
METHOD SetFont
METHOD SetLPI
METHOD StringB
METHOD TextCount
METHOD Text
METHOD OpenHeader
METHOD EditOnHeader
METHOD EditOffHeader
METHOD CloseHeader
METHOD DeleteHeader
METHOD EnableHeader
METHOD DisableHeader
METHOD SaveHeader
METHOD Header
METHOD DrawHeader
METHOD Margins
METHOD CreateHeader
METHOD ImageInfo
METHOD TIFFInfo
METHOD JPEGInfo
METHOD FilePrint
METHOD BookCount
METHOD BookFirst
METHOD BookLast
METHOD BookNext
METHOD BookParent
METHOD BookPrev
METHOD CheckLine
METHOD ClosePage
METHOD GetFontInfo
METHOD M2R
METHOD M2X
METHOD M2Y
METHOD R2D
METHOD R2M
METHOD X2M
METHOD TextPrint
METHOD TextNextPara
METHOD Execute
ENDCLASS
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:Init( cFile, nLen, lOptimize )
#else
METHOD Init( cFile, nLen, lOptimize )
#endif
local cTemp, nI, nJ, n1, n2 := 896, n12
DEFAULT nLen TO 200
DEFAULT lOptimize TO .f.
::aReport := array( PARAMLEN )
::aReport[ FONTNAME ] := 1
::aReport[ FONTSIZE ] := 10
::aReport[ LPI ] := 6
::aReport[ PAGESIZE ] := "LETTER"
::aReport[ PAGEORIENT ] := "P"
::aReport[ PAGEX ] := 8.5 * 72
::aReport[ PAGEY ] := 11.0 * 72
::aReport[ REPORTWIDTH ] := nLen // 200 // should be as parameter
::aReport[ REPORTPAGE ] := 0
::aReport[ REPORTLINE ] := 0 // 5
::aReport[ FONTNAMEPREV ] := 0
::aReport[ FONTSIZEPREV ] := 0
::aReport[ PAGEBUFFER ] := ""
::aReport[ REPORTOBJ ] := 1 //2
::aReport[ DOCLEN ] := 0
::aReport[ TYPE1 ] := { "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic", ;
"Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique", ;
"Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique" }
::aReport[ MARGINS ] := .t.
::aReport[ HEADEREDIT ] := .f.
::aReport[ NEXTOBJ ] := 0
::aReport[ PDFTOP ] := 1 // top
::aReport[ PDFLEFT ] := 10 // left & right
::aReport[ PDFBOTTOM ] := ::aReport[ PAGEY ] / 72 * ::aReport[ LPI ] - 1 // bottom, default "LETTER", "P", 6
::aReport[ HANDLE ] := fcreate( cFile )
::aReport[ PAGES ] := {}
::aReport[ REFS ] := { 0, 0 }
::aReport[ BOOKMARK ] := {}
::aReport[ HEADER ] := {}
::aReport[ FONTS ] := {}
::aReport[ IMAGES ] := {}
::aReport[ PAGEIMAGES ] := {}
::aReport[ PAGEFONTS ] := {}
cTemp := vpdf_FontsDat()
n1 := len( cTemp ) / ( 2 * n2 )
::aReport[ FONTWIDTH ] := array( n1, n2 )
::aReport[ OPTIMIZE ] := lOptimize
::aReport[ NEXTOBJ ] := ::aReport[ REPORTOBJ ] + 4
n12 := 2 * n2
for nI := 1 to n1
for nJ := 1 to n2
::aReport[ FONTWIDTH ][ nI ][ nJ ] := bin2i( substr( cTemp, ( nI - 1 ) * n12 + ( nJ - 1 ) * 2 + 1, 2 ) )
next
next
::aReport[ DOCLEN ] := 0
cTemp := "%PDF-1.3" + CRLF
::aReport[ DOCLEN ] += len( cTemp )
fwrite( ::aReport[ HANDLE ], cTemp )
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:AtSay( cString, nRow, nCol, cUnits, lExact, cId )
#else
METHOD AtSay( cString, nRow, nCol, cUnits, lExact, cId )
#endif
local _nFont, lReverse, nAt
DEFAULT nRow TO ::aReport[ REPORTLINE ]
DEFAULT cUnits TO "R"
DEFAULT lExact TO .f.
DEFAULT cId TO ""
IF ::aReport[ HEADEREDIT ]
return ::Header( "PDFATSAY", cId, { cString, nRow, nCol, cUnits, lExact } )
ENDIF
IF ( nAt := at( "#pagenumber#", cString ) ) > 0
cString := left( cString, nAt - 1 ) + ltrim(str( ::PageNumber())) + substr( cString, nAt + 12 )
ENDIF
lReverse := .f.
IF cUnits == "M"
nRow := ::M2Y( nRow )
nCol := ::M2X( nCol )
ELSEIF cUnits == "R"
IF .not. lExact
::CheckLine( nRow )
nRow := nRow + ::aReport[ PDFTOP]
ENDIF
nRow := ::R2D( nRow )
nCol := ::M2X( ::aReport[ PDFLEFT ] ) + ;
nCol * 100.00 / ::aReport[ REPORTWIDTH ] * ;
( ::aReport[ PAGEX ] - ::M2X( ::aReport[ PDFLEFT ] ) * 2 - 9.0 ) / 100.00
ENDIF
IF !empty( cString )
cString := ::StringB( cString )
IF right( cString, 1 ) == chr(255) //reverse
cString := left( cString, len( cString ) - 1 )
::Box( ::aReport[ PAGEY ] - nRow - ::aReport[ FONTSIZE ] + 2.0 , nCol, ::aReport[ PAGEY ] - nRow + 2.0, nCol + ::M2X( ::length( cString )) + 1,,100, "D")
::aReport[ PAGEBUFFER ] += " 1 g "
lReverse := .t.
ELSEIF right( cString, 1 ) == chr(254) //underline
cString := left( cString, len( cString ) - 1 )
::Box( ::aReport[ PAGEY ] - nRow + 0.5, nCol, ::aReport[ PAGEY ] - nRow + 1, nCol + ::M2X( ::length( cString )) + 1,,100, "D")
ENDIF
// version 0.01
IF ( nAt := at( chr(253), cString )) > 0 // some color text inside
::aReport[ PAGEBUFFER ] += CRLF + ;
Chr_RGB( substr( cString, nAt + 1, 1 )) + " " + ;
Chr_RGB( substr( cString, nAt + 2, 1 )) + " " + ;
Chr_RGB( substr( cString, nAt + 3, 1 )) + " rg "
cString := stuff( cString, nAt, 4, "")
ENDIF
// version 0.01
_nFont := ascan( ::aReport[ FONTS ], {|arr| arr[1] == ::aReport[ FONTNAME ]} )
IF !( ::aReport[ FONTNAME ] == ::aReport[ FONTNAMEPREV ] )
::aReport[ FONTNAMEPREV ] := ::aReport[ FONTNAME ]
::aReport[ PAGEBUFFER ] += CRLF + "BT /Fo" + ltrim(str( _nFont )) + " " + ltrim(transform( ::aReport[ FONTSIZE ], "999.99")) + " Tf " + ltrim(transform( nCol, "9999.99" )) + " " + ltrim(transform( nRow, "9999.99" )) + " Td (" + cString + ") Tj ET"
ELSEIF ::aReport[ FONTSIZE ] != ::aReport[ FONTSIZEPREV ]
::aReport[ FONTSIZEPREV ] := ::aReport[ FONTSIZE ]
::aReport[ PAGEBUFFER ] += CRLF + "BT /Fo" + ltrim(str( _nFont )) + " " + ltrim(transform( ::aReport[ FONTSIZE ], "999.99")) + " Tf " + ltrim(transform( nCol, "9999.99" )) + " " + ltrim(transform( nRow, "9999.99" )) + " Td (" + cString + ") Tj ET"
ELSE
::aReport[ PAGEBUFFER ] += CRLF + "BT " + ltrim(transform( nCol, "9999.99" )) + " " + ltrim(transform( nRow, "9999.99" )) + " Td (" + cString + ") Tj ET"
ENDIF
IF lReverse
::aReport[ PAGEBUFFER ] += " 0 g "
ENDIF
ENDIF
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:Normal()
#else
METHOD Normal()
#endif
local cName := ::GetFontInfo( "NAME" )
IF cName = "Times"
::aReport[ FONTNAME ] := 1
ELSEIF cName = "Helvetica"
::aReport[ FONTNAME ] := 5
ELSE
::aReport[ FONTNAME ] := 9
ENDIF
aadd( ::aReport[ PAGEFONTS ], ::aReport[ FONTNAME ] )
IF ascan( ::aReport[ FONTS ], { |arr| arr[1] == ::aReport[ FONTNAME ] } ) == 0
aadd( ::aReport[ FONTS ], { ::aReport[ FONTNAME ], ++::aReport[ NEXTOBJ ] } )
ENDIF
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:Italic()
#else
METHOD Italic()
#endif
local cName := ::GetFontInfo( "NAME" )
IF cName = "Times"
::aReport[ FONTNAME ] := 3
ELSEIF cName = "Helvetica"
::aReport[ FONTNAME ] := 7
ELSE
::aReport[ FONTNAME ] := 11
ENDIF
aadd( ::aReport[ PAGEFONTS ], ::aReport[ FONTNAME ] )
IF ascan( ::aReport[ FONTS ], { |arr| arr[1] == ::aReport[ FONTNAME ] } ) == 0
aadd( ::aReport[ FONTS ], { ::aReport[ FONTNAME ], ++::aReport[ NEXTOBJ ] } )
ENDIF
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:Bold()
#else
METHOD Bold()
#endif
local cName := ::GetFontInfo( "NAME" )
IF cName == "Times"
::aReport[ FONTNAME ] := 2
ELSEIF cName == "Helvetica"
::aReport[ FONTNAME ] := 6
ELSEIF cName == "Courier"
::aReport[ FONTNAME ] := 10 // Courier // 0.04
ENDIF
aadd( ::aReport[ PAGEFONTS ], ::aReport[ FONTNAME ] )
IF ascan( ::aReport[ FONTS ], { |arr| arr[1] == ::aReport[ FONTNAME ] } ) == 0
aadd( ::aReport[ FONTS ], { ::aReport[ FONTNAME ], ++::aReport[ NEXTOBJ ] } )
ENDIF
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:BoldItalic()
#else
METHOD BoldItalic()
#endif
local cName := ::GetFontInfo( "NAME" )
IF cName == "Times"
::aReport[ FONTNAME ] := 4
ELSEIF cName == "Helvetica"
::aReport[ FONTNAME ] := 8
ELSEIF cName == "Courier"
::aReport[ FONTNAME ] := 12 // 0.04
ENDIF
aadd( ::aReport[ PAGEFONTS ], ::aReport[ FONTNAME ] )
IF ascan( ::aReport[ FONTS ], { |arr| arr[1] == ::aReport[ FONTNAME ] } ) == 0
aadd( ::aReport[ FONTS ], { ::aReport[ FONTNAME ], ++::aReport[ NEXTOBJ ] } )
ENDIF
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:BookAdd( cTitle, nLevel, nPage, nLine )
#else
METHOD BookAdd( cTitle, nLevel, nPage, nLine )
#endif
aadd( ::aReport[ BOOKMARK ], { nLevel, alltrim( cTitle ), 0, 0, 0, 0, 0, 0, nPage, IIF( nLevel == 1, ::aReport[ PAGEY ], ::aReport[ PAGEY ] - nLine * 72 / ::aReport[ LPI ] ) })
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:BookClose( )
#else
METHOD BookClose( )
#endif
::aReport[ BOOKMARK ] := nil
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:BookOpen( )
#else
METHOD BookOpen( )
#endif
::aReport[ BOOKMARK ] := {}
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:Box( x1, y1, x2, y2, nBorder, nShade, cUnits, cColor, cId )
#else
METHOD Box( x1, y1, x2, y2, nBorder, nShade, cUnits, cColor, cId )
#endif
local cBoxColor
DEFAULT nBorder TO 0
DEFAULT nShade TO 0
DEFAULT cUnits TO "M"
DEFAULT cColor TO ""
cBoxColor := ""
IF !empty( cColor )
cBoxColor := " " + Chr_RGB( substr( cColor, 2, 1 )) + " " + ;
Chr_RGB( substr( cColor, 3, 1 )) + " " + ;
Chr_RGB( substr( cColor, 4, 1 )) + " rg "
IF empty( alltrim( cBoxColor ) )
cBoxColor := ""
ENDIF
ENDIF
IF ::aReport[ HEADEREDIT ]
return ::Header( "PDFBOX", cId, { x1, y1, x2, y2, nBorder, nShade, cUnits } )
ENDIF
IF cUnits == "M"
y1 += 0.5
y2 += 0.5
IF nShade > 0
::aReport[ PAGEBUFFER ] += CRLF + transform( 1.00 - nShade / 100.00, "9.99") + " g " + cBoxColor + ltrim(str(::M2X( y1 ))) + " " + ltrim(str(::M2Y( x1 ))) + " " + ltrim(str(::M2X( y2 - y1 ))) + " -" + ltrim(str(::M2X( x2 - x1 ))) + " re f 0 g"
ENDIF
IF nBorder > 0
::aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str(::M2X( y1 ))) + " " + ltrim(str(::M2Y( x1 ))) + " " + ltrim(str(::M2X( y2 - y1 ))) + " -" + ltrim(str(::M2X( nBorder ))) + " re f"
::aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str(::M2X( y2 - nBorder ))) + " " + ltrim(str(::M2Y( x1 ))) + " " + ltrim(str(::M2X( nBorder ))) + " -" + ltrim(str(::M2X( x2 - x1 ))) + " re f"
::aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str(::M2X( y1 ))) + " " + ltrim(str(::M2Y( x2 - nBorder ))) + " " + ltrim(str(::M2X( y2 - y1 ))) + " -" + ltrim(str(::M2X( nBorder ))) + " re f"
::aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str(::M2X( y1 ))) + " " + ltrim(str(::M2Y( x1 ))) + " " + ltrim(str(::M2X( nBorder ))) + " -" + ltrim(str(::M2X( x2 - x1 ))) + " re f"
ENDIF
ELSEIF cUnits == "D" // "Dots"
IF nShade > 0
::aReport[ PAGEBUFFER ] += CRLF + transform( 1.00 - nShade / 100.00, "9.99") + " g " + cBoxColor + ltrim(str( y1 )) + " " + ltrim(str( ::aReport[ PAGEY ] - x1 )) + " " + ltrim(str( y2 - y1 )) + " -" + ltrim(str( x2 - x1 )) + " re f 0 g"
ENDIF
IF nBorder > 0
/*
1
Ú-----¿
4 ³ ³ 2
À-----Ù
3
*/
::aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str( y1 )) + " " + ltrim(str( ::aReport[ PAGEY ] - x1 )) + " " + ltrim(str( y2 - y1 )) + " -" + ltrim(str( nBorder )) + " re f"
::aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str( y2 - nBorder )) + " " + ltrim(str( ::aReport[ PAGEY ] - x1 )) + " " + ltrim(str( nBorder )) + " -" + ltrim(str( x2 - x1 )) + " re f"
::aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str( y1 )) + " " + ltrim(str( ::aReport[ PAGEY ] - x2 + nBorder )) + " " + ltrim(str( y2 - y1 )) + " -" + ltrim(str( nBorder )) + " re f"
::aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str( y1 )) + " " + ltrim(str( ::aReport[ PAGEY ] - x1 )) + " " + ltrim(str( nBorder )) + " -" + ltrim(str( x2 - x1 )) + " re f"
ENDIF
ENDIF
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:Box1( nTop, nLeft, nBottom, nRight, nBorderWidth, cBorderColor, cBoxColor )
#else
METHOD Box1( nTop, nLeft, nBottom, nRight, nBorderWidth, cBorderColor, cBoxColor )
#endif
DEFAULT nBorderWidth to 0.5
DEFAULT cBorderColor to chr(0) + chr(0) + chr(0)
DEFAULT cBoxColor to chr(255) + chr(255) + chr(255)
::aReport[ PAGEBUFFER ] += CRLF + ;
Chr_RGB( substr( cBorderColor, 1, 1 )) + " " + ;
Chr_RGB( substr( cBorderColor, 2, 1 )) + " " + ;
Chr_RGB( substr( cBorderColor, 3, 1 )) + ;
" RG" + ;
CRLF + ;
Chr_RGB( substr( cBoxColor, 1, 1 )) + " " + ;
Chr_RGB( substr( cBoxColor, 2, 1 )) + " " + ;
Chr_RGB( substr( cBoxColor, 3, 1 )) + ;
" rg" + ;
CRLF + ltrim(str( nBorderWidth )) + " w" + ;
CRLF + ltrim( str ( nLeft + nBorderWidth / 2 )) + " " + ;
CRLF + ltrim( str ( ::aReport[ PAGEY ] - nBottom + nBorderWidth / 2)) + " " + ;
CRLF + ltrim( str ( nRight - nLeft - nBorderWidth )) + ;
CRLF + ltrim( str ( nBottom - nTop - nBorderWidth )) + " " + ;
" re" + ;
CRLF + "B"
return nil
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:Center( cString, nRow, nCol, cUnits, lExact, cId )
#else
METHOD Center( cString, nRow, nCol, cUnits, lExact, cId )
#endif
local nLen, nAt
DEFAULT nRow TO ::aReport[ REPORTLINE ]
DEFAULT cUnits TO "R"
DEFAULT lExact TO .f.
DEFAULT nCol TO IIF( cUnits == "R", ::aReport[ REPORTWIDTH ] / 2, ::aReport[ PAGEX ] / 72 * 25.4 / 2 )
IF ::aReport[ HEADEREDIT ]
return ::Header( "PDFCENTER", cId, { cString, nRow, nCol, cUnits, lExact } )
ENDIF
IF ( nAt := at( "#pagenumber#", cString ) ) > 0
cString := left( cString, nAt - 1 ) + ltrim(str( ::PageNumber())) + substr( cString, nAt + 12 )
ENDIF
nLen := ::length( cString ) / 2
IF cUnits == "R"
IF .not. lExact
::CheckLine( nRow )
nRow := nRow + ::aReport[ PDFTOP]
ENDIF
ENDIF
::AtSay( cString, ::R2M( nRow ), IIF( cUnits == "R", ::aReport[ PDFLEFT ] + ( ::aReport[ PAGEX ] / 72 * 25.4 - 2 * ::aReport[ PDFLEFT ] ) * nCol / ::aReport[ REPORTWIDTH ], nCol ) - nLen, "M", lExact )
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:Close()
#else
METHOD Close()
#endif
local nI, cTemp, nCurLevel, nObj1, nLast, nCount, nFirst, nRecno, nBooklen
// FIELD FIRST, PREV, NEXT, LAST, COUNT, PARENT, PAGE, COORD, TITLE, LEVEL
::ClosePage()
// kids
::aReport[ REFS ][ 2 ] := ::aReport[ DOCLEN ]
cTemp := ;
"1 0 obj"+CRLF+;
"<<"+CRLF+;
"/Type /Pages /Count " + ltrim(str(::aReport[ REPORTPAGE ])) + CRLF +;
"/Kids ["
for nI := 1 to ::aReport[ REPORTPAGE ]
cTemp += " " + ltrim(str( ::aReport[ PAGES ][ nI ] )) + " 0 R"
next
cTemp += " ]" + CRLF + ;
">>" + CRLF + ;
"endobj" + CRLF
::aReport[ DOCLEN ] += len( cTemp )
fwrite( ::aReport[ HANDLE ], cTemp )
// info
++::aReport[ REPORTOBJ ]
aadd( ::aReport[ REFS ], ::aReport[ DOCLEN ] )
cTemp := ltrim(str( ::aReport[ REPORTOBJ ] )) + " 0 obj" + CRLF + ;
"<<" + CRLF + ;
"/Producer ()" + CRLF + ;
"/Title ()" + CRLF + ;
"/Author ()" + CRLF + ;
"/Creator ()" + CRLF + ;
"/Subject ()" + CRLF + ;
"/Keywords ()" + CRLF + ;
"/CreationDate (D:" + str(year(date()), 4) + padl( month(date()), 2, "0") + padl( day(date()), 2, "0") + substr( time(), 1, 2 ) + substr( time(), 4, 2 ) + substr( time(), 7, 2 ) + ")" + CRLF + ;
">>" + CRLF + ;
"endobj" + CRLF
::aReport[ DOCLEN ] += len( cTemp )
fwrite( ::aReport[ HANDLE ], cTemp )
// root
++::aReport[ REPORTOBJ ]
aadd( ::aReport[ REFS ], ::aReport[ DOCLEN ] )
cTemp := ltrim(str( ::aReport[ REPORTOBJ ] )) + " 0 obj" + CRLF + ;
"<< /Type /Catalog /Pages 1 0 R /Outlines " + ltrim(str( ::aReport[ REPORTOBJ ] + 1 )) + " 0 R" + IIF( ( nBookLen := len( ::aReport[ BOOKMARK ] )) > 0, " /PageMode /UseOutlines", "") + " >>" + CRLF + "endobj" + CRLF
::aReport[ DOCLEN ] += len( cTemp )
fwrite( ::aReport[ HANDLE ], cTemp )
++::aReport[ REPORTOBJ ]
nObj1 := ::aReport[ REPORTOBJ ]
IF nBookLen > 0
nRecno := 1
nFirst := ::aReport[ REPORTOBJ ] + 1
nLast := 0
nCount := 0
while nRecno <= nBookLen
nCurLevel := ::aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
::aReport[ BOOKMARK ][ nRecno ][ BOOKPARENT ] := ::BookParent( nRecno, nCurLevel, ::aReport[ REPORTOBJ ] )
::aReport[ BOOKMARK ][ nRecno ][ BOOKPREV ] := ::BookPrev( nRecno, nCurLevel, ::aReport[ REPORTOBJ ] )
::aReport[ BOOKMARK ][ nRecno ][ BOOKNEXT ] := ::BookNext( nRecno, nCurLevel, ::aReport[ REPORTOBJ ] )
::aReport[ BOOKMARK ][ nRecno ][ BOOKFIRST ] := ::BookFirst( nRecno, nCurLevel, ::aReport[ REPORTOBJ ] )
::aReport[ BOOKMARK ][ nRecno ][ BOOKLAST ] := ::BookLast( nRecno, nCurLevel, ::aReport[ REPORTOBJ ] )
::aReport[ BOOKMARK ][ nRecno ][ BOOKCOUNT ] := ::BookCount( nRecno, nCurLevel )
IF nCurLevel == 1
nLast := nRecno
++nCount
ENDIF
++nRecno
enddo
nLast += ::aReport[ REPORTOBJ ]
cTemp := ltrim(str( ::aReport[ REPORTOBJ ] )) + " 0 obj" + CRLF + "<< /Type /Outlines /Count " + ltrim(str( nCount )) + " /First " + ltrim(str( nFirst )) + " 0 R /Last " + ltrim(str( nLast )) + " 0 R >>" + CRLF + "endobj" //+ CRLF
aadd( ::aReport[ REFS ], ::aReport[ DOCLEN ] )
::aReport[ DOCLEN ] += len( cTemp )
fwrite( ::aReport[ HANDLE ], cTemp )
++::aReport[ REPORTOBJ ]
nRecno := 1
FOR nI := 1 to nBookLen
//cTemp := IIF ( nI > 1, CRLF, "") + ltrim(str( ::aReport[ REPORTOBJ ] + nI - 1)) + " 0 obj" + CRLF + ;
cTemp := CRLF + ltrim(str( ::aReport[ REPORTOBJ ] + nI - 1)) + " 0 obj" + CRLF + ;
"<<" + CRLF + ;
"/Parent " + ltrim(str( ::aReport[ BOOKMARK ][ nRecno ][ BOOKPARENT ])) + " 0 R" + CRLF + ;
"/Dest [" + ltrim(str( ::aReport[ PAGES ][ ::aReport[ BOOKMARK ][ nRecno ][ BOOKPAGE ] ] )) + " 0 R /XYZ 0 " + ltrim( str( ::aReport[ BOOKMARK ][ nRecno ][ BOOKCOORD ])) + " 0]" + CRLF + ;
"/Title (" + alltrim( ::aReport[ BOOKMARK ][ nRecno ][ BOOKTITLE ]) + ")" + CRLF + ;
IIF( ::aReport[ BOOKMARK ][ nRecno ][ BOOKPREV ] > 0, "/Prev " + ltrim(str( ::aReport[ BOOKMARK ][ nRecno ][ BOOKPREV ])) + " 0 R" + CRLF, "") + ;
IIF( ::aReport[ BOOKMARK ][ nRecno ][ BOOKNEXT ] > 0, "/Next " + ltrim(str( ::aReport[ BOOKMARK ][ nRecno ][ BOOKNEXT ])) + " 0 R" + CRLF, "") + ;
IIF( ::aReport[ BOOKMARK ][ nRecno ][ BOOKFIRST ] > 0, "/First " + ltrim(str( ::aReport[ BOOKMARK ][ nRecno ][ BOOKFIRST ])) + " 0 R" + CRLF, "") + ;
IIF( ::aReport[ BOOKMARK ][ nRecno ][ BOOKLAST ] > 0, "/Last " + ltrim(str( ::aReport[ BOOKMARK ][ nRecno ][ BOOKLAST ])) + " 0 R" + CRLF, "") + ;
IIF( ::aReport[ BOOKMARK ][ nRecno ][ BOOKCOUNT ] != 0, "/Count " + ltrim(str( ::aReport[ BOOKMARK ][ nRecno ][ BOOKCOUNT ])) + CRLF, "") + ;
">>" + CRLF + "endobj" + CRLF
// "/Dest [" + ltrim(str( ::aReport[ BOOKMARK ][ nRecno ][ BOOKPAGE ] * 3 )) + " 0 R /XYZ 0 " + ltrim( str( ::aReport[ BOOKMARK ][ nRecno ][ BOOKCOORD ])) + " 0]" + CRLF + ;
// "/Dest [" + ltrim(str( ::aReport[ PAGES ][ nRecno ] )) + " 0 R /XYZ 0 " + ltrim( str( ::aReport[ BOOKMARK ][ nRecno ][ BOOKCOORD ])) + " 0]" + CRLF + ;
aadd( ::aReport[ REFS ], ::aReport[ DOCLEN ] + 2 )
::aReport[ DOCLEN ] += len( cTemp )
fwrite( ::aReport[ HANDLE ], cTemp )
++nRecno
NEXT
::BookClose()
::aReport[ REPORTOBJ ] += nBookLen - 1
ELSE
cTemp := ltrim(str( ::aReport[ REPORTOBJ ] )) + " 0 obj" + CRLF + "<< /Type /Outlines /Count 0 >>" + CRLF + "endobj" + CRLF
aadd( ::aReport[ REFS ], ::aReport[ DOCLEN ] )
::aReport[ DOCLEN ] += len( cTemp )
fwrite( ::aReport[ HANDLE ], cTemp )
ENDIF
cTemp := CRLF
::aReport[ DOCLEN ] += len( cTemp )
++::aReport[ REPORTOBJ ]
cTemp += "xref" + CRLF + ;
"0 " + ltrim(str( ::aReport[ REPORTOBJ ] )) + CRLF +;
padl( ::aReport[ REFS ][ 1 ], 10, "0") + " 65535 f" + CRLF
for nI := 2 to len( ::aReport[ REFS ] )
cTemp += padl( ::aReport[ REFS ][ nI ], 10, "0") + " 00000 n" + CRLF
next
cTemp += "trailer << /Size " + ltrim(str( ::aReport[ REPORTOBJ ] )) + " /Root " + ltrim(str( nObj1 - 1 )) + " 0 R /Info " + ltrim(str( nObj1 - 2 )) + " 0 R >>" + CRLF + ;
"startxref" + CRLF + ;
ltrim(str( ::aReport[ DOCLEN ] )) + CRLF + ;
"%%EOF" + CRLF
fwrite( ::aReport[ HANDLE ], cTemp )
fclose( ::aReport[ HANDLE ] )
::aReport := nil
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:Image( cFile, nRow, nCol, cUnits, nHeight, nWidth, cId )
#else
METHOD Image( cFile, nRow, nCol, cUnits, nHeight, nWidth, cId )
#endif
DEFAULT nRow TO ::aReport[ REPORTLINE ]
DEFAULT nCol TO 0
DEFAULT nHeight TO 0
DEFAULT nWidth TO 0
DEFAULT cUnits TO "R"
DEFAULT cId TO ""
IF ::aReport[ HEADEREDIT ]
return ::Header( "PDFIMAGE", cId, { cFile, nRow, nCol, cUnits, nHeight, nWidth } )
ENDIF
IF cUnits == "M"
nRow := ::aReport[ PAGEY ] - ::M2Y( nRow )
nCol := ::M2X( nCol )
nHeight := ::aReport[ PAGEY ] - ::M2Y( nHeight )
nWidth := ::M2X( nWidth )
ELSEIF cUnits == "R"
//IF .not. lExact
// ::CheckLine( nRow )
// nRow := nRow + ::aReportStyle[ PDFTOP]
//ENDIF
nRow := ::aReport[ PAGEY ] - ::R2D( nRow )
nCol := ::M2X( ::aReport[ PDFLEFT ] ) + ;
nCol * 100.00 / ::aReport[ REPORTWIDTH ] * ;
( ::aReport[ PAGEX ] - ::M2X( ::aReport[ PDFLEFT ] ) * 2 - 9.0 ) / 100.00
nHeight := ::aReport[ PAGEY ] - ::R2D( nHeight )
nWidth := ::M2X( ::aReport[ PDFLEFT ] ) + ;
nWidth * 100.00 / ::aReport[ REPORTWIDTH ] * ;
( ::aReport[ PAGEX ] - ::M2X( ::aReport[ PDFLEFT ] ) * 2 - 9.0 ) / 100.00
ELSEIF cUnits == "D"
ENDIF
aadd( ::aReport[ PAGEIMAGES ], { cFile, nRow, nCol, nHeight, nWidth } )
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:Length( cString )
#else
METHOD Length( cString )
#endif
local nWidth := 0.00, nI, nLen, nArr, nAdd := ( ::aReport[ FONTNAME ] - 1 ) % 4
nLen := len( cString )
IF right( cString, 1 ) == chr( 255 ) .or. right( cString, 1 ) == chr( 254 )
--nLen
ENDIF
IF ::GetFontInfo("NAME") = "Times"
nArr := 1
ELSEIF ::GetFontInfo("NAME") = "Helvetica"
nArr := 2
ELSE
nArr := 3
ENDIF
For nI:= 1 To nLen
nWidth += ::aReport[ FONTWIDTH ][ nArr ][ ( asc( substr( cString, nI, 1 )) - 32 ) * 4 + 1 + nAdd ] * 25.4 * ::aReport[ FONTSIZE ] / 720.00 / 100.00
Next
RETURN nWidth
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:NewLine( n )
#else
METHOD NewLine( n )
#endif
DEFAULT n TO 1
IF ::aReport[ REPORTLINE ] + n + ::aReport[ PDFTOP] > ::aReport[ PDFBOTTOM ]
::NewPage()
::aReport[ REPORTLINE ] += 1
ELSE
::aReport[ REPORTLINE ] += n
ENDIF
RETURN ::aReport[ REPORTLINE ]
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:NewPage( _cPageSize, _cPageOrient, _nLpi, _cFontName, _nFontType, _nFontSize )
#else
METHOD NewPage( _cPageSize, _cPageOrient, _nLpi, _cFontName, _nFontType, _nFontSize )
#endif
DEFAULT _cPageSize TO ::aReport[ PAGESIZE ]
DEFAULT _cPageOrient TO ::aReport[ PAGEORIENT ]
DEFAULT _nLpi TO ::aReport[ LPI ]
DEFAULT _cFontName TO ::GetFontInfo( "NAME" )
DEFAULT _nFontType TO ::GetFontInfo( "TYPE" )
DEFAULT _nFontSize TO ::aReport[ FONTSIZE ]
IF !empty( ::aReport[ PAGEBUFFER ] )
::ClosePage()
ENDIF
::aReport[ PAGEFONTS ] := {}
::aReport[ PAGEIMAGES ] := {}
++::aReport[ REPORTPAGE ]
::PageSize( _cPageSize )
::PageOrient( _cPageOrient )
::SetLPI( _nLpi )
::SetFont( _cFontName, _nFontType, _nFontSize )
::DrawHeader()
::aReport[ REPORTLINE ] := 0
::aReport[ FONTNAMEPREV ] := 0
::aReport[ FONTSIZEPREV ] := 0
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:PageSize( _cPageSize )
#else
METHOD PageSize( _cPageSize )
#endif
local nSize, aSize := { { "LETTER", 8.50, 11.00 }, ;
{ "LEGAL" , 8.50, 14.00 }, ;
{ "LEDGER", 11.00, 17.00 }, ;
{ "EXECUTIVE", 7.25, 10.50 }, ;
{ "A4", 8.27, 11.69 }, ;
{ "A3", 11.69, 16.54 }, ;
{ "JIS B4", 10.12, 14.33 }, ;
{ "JIS B5", 7.16, 10.12 }, ;
{ "JPOST", 3.94, 5.83 }, ;
{ "JPOSTD", 5.83, 7.87 }, ;
{ "COM10", 4.12, 9.50 }, ;
{ "MONARCH", 3.87, 7.50 }, ;
{ "C5", 6.38, 9.01 }, ;
{ "DL", 4.33, 8.66 }, ;
{ "B5", 6.93, 9.84 } }
DEFAULT _cPageSize TO "LETTER"
nSize := ascan( aSize, { |arr| arr[ 1 ] = _cPageSize } )
IF nSize == 0 .or. nSize > 2
nSize := 1
ENDIF
::aReport[ PAGESIZE ] := aSize[ nSize ][ 1 ]
IF ::aReport[ PAGEORIENT ] = "P"
::aReport[ PAGEX ] := aSize[ nSize ][ 2 ] * 72
::aReport[ PAGEY ] := aSize[ nSize ][ 3 ] * 72
ELSE
::aReport[ PAGEX ] := aSize[ nSize ][ 3 ] * 72
::aReport[ PAGEY ] := aSize[ nSize ][ 2 ] * 72
ENDIF
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:PageOrient( _cPageOrient )
#else
METHOD PageOrient( _cPageOrient )
#endif
DEFAULT _cPageOrient TO "P"
::aReport[ PAGEORIENT ] := _cPageOrient
::PageSize( ::aReport[ PAGESIZE ] )
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:PageNumber( n )
#else
METHOD PageNumber( n )
#endif
DEFAULT n TO 0
IF n > 0
::aReport[ REPORTPAGE ] := n // NEW !!!
ENDIF
RETURN ::aReport[ REPORTPAGE ]
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:Reverse( cString )
#else
METHOD Reverse( cString )
#endif
RETURN cString + chr(255)
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:RJust( cString, nRow, nCol, cUnits, lExact, cId )
#else
METHOD RJust( cString, nRow, nCol, cUnits, lExact, cId )
#endif
local nLen, nAdj := 1.0, nAt
DEFAULT nRow TO ::aReport[ REPORTLINE ]
DEFAULT cUnits TO "R"
DEFAULT lExact TO .f.
IF ::aReport[ HEADEREDIT ]
return ::Header( "PDFRJUST", cId, { cString, nRow, nCol, cUnits, lExact } )
ENDIF
IF ( nAt := at( "#pagenumber#", cString ) ) > 0
cString := left( cString, nAt - 1 ) + ltrim(str( ::PageNumber())) + substr( cString, nAt + 12 )
ENDIF
nLen := ::length( cString )
IF cUnits == "R"
IF .not. lExact
::CheckLine( nRow )
nRow := nRow + ::aReport[ PDFTOP]
ENDIF
ENDIF
::AtSay( cString, ::R2M( nRow ), IIF( cUnits == "R", ::aReport[ PDFLEFT ] + ( ::aReport[ PAGEX ] / 72 * 25.4 - 2 * ::aReport[ PDFLEFT ] ) * nCol / ::aReport[ REPORTWIDTH ] - nAdj, nCol ) - nLen, "M", lExact )
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:SetFont( _cFont, _nType, _nSize, cId )
#else
METHOD SetFont( _cFont, _nType, _nSize, cId )
#endif
DEFAULT _cFont TO "Times"
DEFAULT _nType TO 0
DEFAULT _nSize TO 10
IF ::aReport[ HEADEREDIT ]
return ::Header( "PDFSETFONT", cId, { _cFont, _nType, _nSize } )
ENDIF
_cFont := upper( _cFont )
::aReport[ FONTSIZE ] := _nSize
IF _cFont == "TIMES"
::aReport[ FONTNAME ] := _nType + 1
ELSEIF _cFont == "HELVETICA"
::aReport[ FONTNAME ] := _nType + 5
ELSE
::aReport[ FONTNAME ] := _nType + 9 // 0.04
ENDIF
aadd( ::aReport[ PAGEFONTS ], ::aReport[ FONTNAME ] )
IF ascan( ::aReport[ FONTS ], { |arr| arr[1] == ::aReport[ FONTNAME ] } ) == 0
aadd( ::aReport[ FONTS ], { ::aReport[ FONTNAME ], ++::aReport[ NEXTOBJ ] } )
ENDIF
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:SetLPI(_nLpi)
#else
METHOD SetLPI(_nLpi)
#endif
local cLpi := alltrim(str(_nLpi))
DEFAULT _nLpi TO 6
cLpi := iif(cLpi$"1;2;3;4;6;8;12;16;24;48",cLpi,"6")
::aReport[ LPI ] := val( cLpi )
::PageSize( ::aReport[ PAGESIZE ] )
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:StringB( cString )
#else
METHOD StringB( cString )
#endif
cString := strtran( cString, "(", "\(" )
cString := strtran( cString, ")", "\)" )
RETURN cString
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:TextCount( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits )
#else
METHOD TextCount( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits )
#endif
RETURN ::Text( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits, .f. )
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:Text( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits, cColor, lPrint )
#else
METHOD Text( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits, cColor, lPrint )
#endif
local cDelim := chr(0)+chr(9)+chr(10)+chr(13)+chr(26)+chr(32)+chr(138)+chr(141)
local nI, cTemp, cToken, k, nL, nRow, nLines, nLineLen, nStart
local lParagraph, nSpace, nNew, nTokenLen, nCRLF, nTokens, nLen
DEFAULT nTab TO -1
DEFAULT cUnits TO "R"
DEFAULT nJustify TO 4
DEFAULT lPrint TO .t.
DEFAULT cColor TO ""
IF cUnits == "M"
nTop := ::M2R( nTop )
ELSEIF cUnits == "R"
nLeft := ::X2M( ::M2X( ::aReport[ PDFLEFT ] ) + ;
nLeft * 100.00 / ::aReport[ REPORTWIDTH ] * ;
( ::aReport[ PAGEX ] - ::M2X( ::aReport[ PDFLEFT ] ) * 2 - 9.0 ) / 100.00 )
ENDIF
::aReport[ REPORTLINE ] := nTop - 1
nSpace := ::length( " " )
nLines := 0
nCRLF := 0
nNew := nTab
cString := alltrim( cString )
nTokens := numtoken( cString, cDelim )
nStart := 1
IF nJustify == 1 .or. nJustify == 4
nLeft := nLeft
ELSEIF nJustify == 2
nLeft := nLeft - nLength / 2
ELSEIF nJustify == 3
nLeft := nLeft - nLength
ENDIF
nL := nLeft
nL += nNew * nSpace
nLineLen := nSpace * nNew - nSpace
lParagraph := .t.
nI := 1
while nI <= nTokens
cToken := token( cString, cDelim, nI )
nTokenLen := ::length( cToken )
nLen := len( cToken )
IF nLineLen + nSpace + nTokenLen > nLength
IF nStart == nI // single word > nLength
k := 1
while k <= nLen
cTemp := ""
nLineLen := 0.00
nL := nLeft
IF lParagraph
nLineLen += nSpace * nNew
IF nJustify != 2
nL += nSpace * nNew
ENDIF
lParagraph := .f.
ENDIF
IF nJustify == 2
nL := nLeft + ( nLength - ::length( cTemp ) ) / 2
ELSEIF nJustify == 3
nL := nLeft + nLength - ::length( cTemp )
ENDIF
while k <= nLen .and. ( ( nLineLen += ::length( substr( cToken, k, 1 ))) <= nLength )
nLineLen += ::length( substr( cToken, k, 1 ))
cTemp += substr( cToken, k, 1 )
++k
enddo
IF empty( cTemp ) // single character > nlength
cTemp := substr( cToken, k, 1 )
++k
ENDIF
++nLines
IF lPrint
nRow := ::NewLine( 1 )
::AtSay( cColor + cTemp, ::R2M( nRow + ::aReport[ PDFTOP] ), nL, "M" )
ENDIF
enddo
++nI
nStart := nI
ELSE
::TextPrint( nI - 1, nLeft, @lParagraph, nJustify, nSpace, nNew, nLength, @nLineLen, @nLines, @nStart, cString, cDelim, cColor, lPrint )
ENDIF
ELSEIF ( nI == nTokens ) .or. ( nI < nTokens .and. ( nCRLF := ::TextNextPara( cString, cDelim, nI ) ) > 0 )
IF nI == nTokens
nLineLen += nSpace + nTokenLen
ENDIF
::TextPrint( nI, nLeft, @lParagraph, nJustify, nSpace, nNew, nLength, @nLineLen, @nLines, @nStart, cString, cDelim, cColor, lPrint )
++nI
IF nCRLF > 1
nLines += nCRLF - 1
ENDIF
IF lPrint
/*nRow :=*/ ::NewLine( nCRLF - 1 )
ENDIF
ELSE
nLineLen += nSpace + nTokenLen
++nI
ENDIF
enddo
RETURN nLines
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:UnderLine( cString )
#else
METHOD UnderLine( cString )
#endif
RETURN cString + chr(254)
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:OpenHeader( cFile )
#else
METHOD OpenHeader( cFile )
#endif
local nAt, cCmd
DEFAULT cFile TO ""
IF !empty( cFile )
cFile := alltrim( cFile )
IF len( cFile ) > 12 .or. ;
at( " ", cFile ) > 0 .or. ;
( at( " ", cFile ) == 0 .and. len( cFile ) > 8 ) .or. ;
( ( nAt := at( ".", cFile )) > 0 .and. len( substr( cFile, nAt + 1 )) > 3 )
cCmd := "copy " + cFile + " temp.tmp > nul"
RunExternal( cCmd )
cFile := "temp.tmp"
ENDIF
// ::aReport[ HEADER ] := FT_RestArr( cFile, @nErrorCode )
::aReport[ HEADER ] := File2Array( cFile )
ELSE
::aReport[ HEADER ] := {}
ENDIF
::aReport[ MARGINS ] := .t.
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:EditOnHeader()
#else
METHOD EditOnHeader()
#endif
::aReport[ HEADEREDIT ] := .t.
::aReport[ MARGINS ] := .t.
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:EditOffHeader()
#else
METHOD EditOffHeader()
#endif
::aReport[ HEADEREDIT ] := .f.
::aReport[ MARGINS ] := .t.
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:CloseHeader()
#else
METHOD CloseHeader()
#endif
::aReport[ HEADER ] := {}
::aReport[ MARGINS ] := .f.
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:DeleteHeader( cId )
#else
METHOD DeleteHeader( cId )
#endif
local nRet := -1, nId
cId := upper( cId )
nId := ascan( ::aReport[ HEADER ], {| arr | arr[ 3 ] == cId })
IF nId > 0
nRet := len( ::aReport[ HEADER ] ) - 1
aDel( ::aReport[ HEADER ], nId )
aSize( ::aReport[ HEADER ], nRet )
::aReport[ MARGINS ] := .t.
ENDIF
RETURN nRet
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:EnableHeader( cId )
#else
METHOD EnableHeader( cId )
#endif
local nId
cId := upper( cId )
nId := ascan( ::aReport[ HEADER ], {| arr | arr[ 3 ] == cId })
IF nId > 0
::aReport[ HEADER ][ nId ][ 1 ] := .t.
::aReport[ MARGINS ] := .t.
ENDIF
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:DisableHeader( cId )
#else
METHOD DisableHeader( cId )
#endif
local nId
cId := upper( cId )
nId := ascan( ::aReport[ HEADER ], {| arr | arr[ 3 ] == cId })
IF nId > 0
::aReport[ HEADER ][ nId ][ 1 ] := .f.
::aReport[ MARGINS ] := .t.
ENDIF
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:SaveHeader( cFile )
#else
METHOD SaveHeader( cFile )
#endif
local cCmd
Array2File( "temp.tmp", ::aReport[ HEADER ] )
cCmd := "copy temp.tmp " + cFile + " > nul"
RunExternal( cCmd )
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:Header( cFunction, cId, arr )
#else
METHOD Header( cFunction, cId, arr )
#endif
local nId, nI, nLen, nIdLen
nId := 0
IF !empty( cId )
cId := upper( cId )
nId := ascan( ::aReport[ HEADER ], {| arr | arr[ 3 ] == cId })
ENDIF
IF nId == 0
nLen := len( ::aReport[ HEADER ] )
IF empty( cId )
cId := cFunction
nIdLen := len( cId )
for nI := 1 to nLen
IF ::aReport[ HEADER ][ nI ][ 2 ] == cId
IF val( substr( ::aReport[ HEADER ][ nI ][ 3 ], nIdLen + 1 ) ) > nId
nId := val( substr( ::aReport[ HEADER ][ nI ][ 3 ], nIdLen + 1 ) )
ENDIF
ENDIF
next
++nId
cId += ltrim(str(nId))
ENDIF
aadd( ::aReport[ HEADER ], { .t., cFunction, cId } )
++nLen
for nI := 1 to len( arr )
aadd( ::aReport[ HEADER ][ nLen ], arr[ nI ] )
next
ELSE
aSize( ::aReport[ HEADER ][ nId ], 3 )
for nI := 1 to len( arr )
aadd( ::aReport[ HEADER ][ nId ], arr[ nI ] )
next
ENDIF
RETURN cId
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:DrawHeader()
#else
METHOD DrawHeader()
#endif
local nI, _nFont, _nSize, nLen := len( ::aReport[ HEADER ] )
IF nLen > 0
// save font
_nFont := ::aReport[ FONTNAME ]
_nSize := ::aReport[ FONTSIZE ]
for nI := 1 to nLen
IF ::aReport[ HEADER ][ nI ][ 1 ] // enabled
do case
case ::aReport[ HEADER ][ nI ][ 2 ] == "PDFATSAY"
::AtSay( ::aReport[ HEADER ][ nI ][ 4 ], ::aReport[ HEADER ][ nI ][ 5 ], ::aReport[ HEADER ][ nI ][ 6 ], ::aReport[ HEADER ][ nI ][ 7 ], ::aReport[ HEADER ][ nI ][ 8 ], ::aReport[ HEADER ][ nI ][ 3 ] )
case ::aReport[ HEADER ][ nI ][ 2 ] == "PDFCENTER"
::Center( ::aReport[ HEADER ][ nI ][ 4 ], ::aReport[ HEADER ][ nI ][ 5 ], ::aReport[ HEADER ][ nI ][ 6 ], ::aReport[ HEADER ][ nI ][ 7 ], ::aReport[ HEADER ][ nI ][ 8 ], ::aReport[ HEADER ][ nI ][ 3 ] )
case ::aReport[ HEADER ][ nI ][ 2 ] == "PDFRJUST"
::RJust( ::aReport[ HEADER ][ nI ][ 4 ], ::aReport[ HEADER ][ nI ][ 5 ], ::aReport[ HEADER ][ nI ][ 6 ], ::aReport[ HEADER ][ nI ][ 7 ], ::aReport[ HEADER ][ nI ][ 8 ], ::aReport[ HEADER ][ nI ][ 3 ] )
case ::aReport[ HEADER ][ nI ][ 2 ] == "PDFBOX"
::Box( ::aReport[ HEADER ][ nI ][ 4 ], ::aReport[ HEADER ][ nI ][ 5 ], ::aReport[ HEADER ][ nI ][ 6 ], ::aReport[ HEADER ][ nI ][ 7 ], ::aReport[ HEADER ][ nI ][ 8 ], ::aReport[ HEADER ][ nI ][ 9 ], ::aReport[ HEADER ][ nI ][ 10 ], ::aReport[ HEADER ][ nI ][ 3 ] )
case ::aReport[ HEADER ][ nI ][ 2 ] == "PDFSETFONT"
::SetFont( ::aReport[ HEADER ][ nI ][ 4 ], ::aReport[ HEADER ][ nI ][ 5 ], ::aReport[ HEADER ][ nI ][ 6 ], ::aReport[ HEADER ][ nI ][ 3 ] )
case ::aReport[ HEADER ][ nI ][ 2 ] == "PDFIMAGE"
::Image( ::aReport[ HEADER ][ nI ][ 4 ], ::aReport[ HEADER ][ nI ][ 5 ], ::aReport[ HEADER ][ nI ][ 6 ], ::aReport[ HEADER ][ nI ][ 7 ], ::aReport[ HEADER ][ nI ][ 8 ], ::aReport[ HEADER ][ nI ][ 9 ], ::aReport[ HEADER ][ nI ][ 3 ] )
endcase
ENDIF
next
::aReport[ FONTNAME ] := _nFont
::aReport[ FONTSIZE ] := _nSize
IF ::aReport[ MARGINS ]
::Margins()
ENDIF
ELSE
IF ::aReport[ MARGINS ]
::aReport[ PDFTOP] := 1 // top
::aReport[ PDFLEFT ] := 10 // left & right
::aReport[ PDFBOTTOM ] := ::aReport[ PAGEY ] / 72 * ::aReport[ LPI ] - 1 // bottom, default "LETTER", "P", 6
::aReport[ MARGINS ] := .f.
ENDIF
ENDIF
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:Margins( nTop, nLeft, nBottom )
#else
METHOD Margins( nTop, nLeft, nBottom )
#endif
local nI, nLen := len( ::aReport[ HEADER ] ), nTemp, aTemp, nHeight
for nI := 1 to nLen
IF ::aReport[ HEADER ][ nI ][ 1 ] // enabled
IF ::aReport[ HEADER ][ nI ][ 2 ] == "PDFSETFONT"
ELSEIF ::aReport[ HEADER ][ nI ][ 2 ] == "PDFIMAGE"
IF ::aReport[ HEADER ][ nI ][ 8 ] == 0 // picture in header, first at all, not at any page yet
aTemp := ::ImageInfo( ::aReport[ HEADER ][ nI ][ 4 ] )
nHeight := aTemp[ IMAGE_HEIGHT ] / aTemp[ IMAGE_YRES ] * 25.4
IF ::aReport[ HEADER ][ nI ][ 7 ] == "D"
nHeight := ::M2X( nHeight )
ENDIF
ELSE
nHeight := ::aReport[ HEADER ][ nI ][ 8 ]
ENDIF
IF ::aReport[ HEADER ][ nI ][ 7 ] == "M"
nTemp := ::aReport[ PAGEY ] / 72 * 25.4 / 2
IF ::aReport[ HEADER ][ nI ][ 5 ] < nTemp
nTemp := ( ::aReport[ HEADER ][ nI ][ 5 ] + nHeight ) * ::aReport[ LPI ] / 25.4 // top
IF nTemp > ::aReport[ PDFTOP]
::aReport[ PDFTOP] := nTemp
ENDIF
ELSE
nTemp := ::aReport[ HEADER ][ nI ][ 5 ] * ::aReport[ LPI ] / 25.4 // top
IF nTemp < ::aReport[ PDFBOTTOM ]
::aReport[ PDFBOTTOM ] := nTemp
ENDIF
ENDIF
ELSEIF ::aReport[ HEADER ][ nI ][ 7 ] == "D"
nTemp := ::aReport[ PAGEY ] / 2
IF ::aReport[ HEADER ][ nI ][ 5 ] < nTemp
nTemp := ( ::aReport[ HEADER ][ nI ][ 5 ] + nHeight ) * ::aReport[ LPI ] / 72 // top
IF nTemp > ::aReport[ PDFTOP]
::aReport[ PDFTOP] := nTemp
ENDIF
ELSE
nTemp := ::aReport[ HEADER ][ nI ][ 5 ] * ::aReport[ LPI ] / 72 // top
IF nTemp < ::aReport[ PDFBOTTOM ]
::aReport[ PDFBOTTOM ] := nTemp
ENDIF
ENDIF
ENDIF
ELSEIF ::aReport[ HEADER ][ nI ][ 2 ] == "PDFBOX"
IF ::aReport[ HEADER ][ nI ][ 10 ] == "M"
nTemp := ::aReport[ PAGEY ] / 72 * 25.4 / 2
IF ::aReport[ HEADER ][ nI ][ 4 ] < nTemp .and. ;
::aReport[ HEADER ][ nI ][ 6 ] < nTemp
nTemp := ::aReport[ HEADER ][ nI ][ 6 ] * ::aReport[ LPI ] / 25.4 // top
IF nTemp > ::aReport[ PDFTOP]
::aReport[ PDFTOP] := nTemp
ENDIF
ELSEIF ::aReport[ HEADER ][ nI ][ 4 ] < nTemp .and. ;
::aReport[ HEADER ][ nI ][ 6 ] > nTemp
nTemp := ( ::aReport[ HEADER ][ nI ][ 4 ] + ::aReport[ HEADER ][ nI ][ 8 ] ) * ::aReport[ LPI ] / 25.4 // top
IF nTemp > ::aReport[ PDFTOP]
::aReport[ PDFTOP] := nTemp
ENDIF
nTemp := ( ::aReport[ HEADER ][ nI ][ 6 ] - ::aReport[ HEADER ][ nI ][ 8 ] ) * ::aReport[ LPI ] / 25.4 // top
IF nTemp < ::aReport[ PDFBOTTOM ]
::aReport[ PDFBOTTOM ] := nTemp
ENDIF
ELSEIF ::aReport[ HEADER ][ nI ][ 4 ] > nTemp .and. ;
::aReport[ HEADER ][ nI ][ 6 ] > nTemp
nTemp := ::aReport[ HEADER ][ nI ][ 4 ] * ::aReport[ LPI ] / 25.4 // top
IF nTemp < ::aReport[ PDFBOTTOM ]
::aReport[ PDFBOTTOM ] := nTemp
ENDIF
ENDIF
ELSEIF ::aReport[ HEADER ][ nI ][ 10 ] == "D"
nTemp := ::aReport[ PAGEY ] / 2
IF ::aReport[ HEADER ][ nI ][ 4 ] < nTemp .and. ;
::aReport[ HEADER ][ nI ][ 6 ] < nTemp
nTemp := ::aReport[ HEADER ][ nI ][ 6 ] / ::aReport[ LPI ] // top
IF nTemp > ::aReport[ PDFTOP]
::aReport[ PDFTOP] := nTemp
ENDIF
ELSEIF ::aReport[ HEADER ][ nI ][ 4 ] < nTemp .and. ;
::aReport[ HEADER ][ nI ][ 6 ] > nTemp
nTemp := ( ::aReport[ HEADER ][ nI ][ 4 ] + ::aReport[ HEADER ][ nI ][ 8 ] ) / ::aReport[ LPI ] // top
IF nTemp > ::aReport[ PDFTOP]
::aReport[ PDFTOP] := nTemp
ENDIF
nTemp := ( ::aReport[ HEADER ][ nI ][ 6 ] - ::aReport[ HEADER ][ nI ][ 8 ] ) / ::aReport[ LPI ] // top
IF nTemp < ::aReport[ PDFBOTTOM ]
::aReport[ PDFBOTTOM ] := nTemp
ENDIF
ELSEIF ::aReport[ HEADER ][ nI ][ 4 ] > nTemp .and. ;
::aReport[ HEADER ][ nI ][ 6 ] > nTemp
nTemp := ::aReport[ HEADER ][ nI ][ 4 ] / ::aReport[ LPI ] // top
IF nTemp < ::aReport[ PDFBOTTOM ]
::aReport[ PDFBOTTOM ] := nTemp
ENDIF
ENDIF
ENDIF
ELSE
IF ::aReport[ HEADER ][ nI ][ 7 ] == "R"
nTemp := ::aReport[ HEADER ][ nI ][ 5 ] // top
IF ::aReport[ HEADER ][ nI ][ 5 ] > ::aReport[ PAGEY ] / 72 * ::aReport[ LPI ] / 2
IF nTemp < ::aReport[ PDFBOTTOM ]
::aReport[ PDFBOTTOM ] := nTemp
ENDIF
ELSE
IF nTemp > ::aReport[ PDFTOP]
::aReport[ PDFTOP] := nTemp
ENDIF
ENDIF
ELSEIF ::aReport[ HEADER ][ nI ][ 7 ] == "M"
nTemp := ::aReport[ HEADER ][ nI ][ 5 ] * ::aReport[ LPI ] / 25.4 // top
IF ::aReport[ HEADER ][ nI ][ 5 ] > ::aReport[ PAGEY ] / 72 * 25.4 / 2
IF nTemp < ::aReport[ PDFBOTTOM ]
::aReport[ PDFBOTTOM ] := nTemp
ENDIF
ELSE
IF nTemp > ::aReport[ PDFTOP]
::aReport[ PDFTOP] := nTemp
ENDIF
ENDIF
ELSEIF ::aReport[ HEADER ][ nI ][ 7 ] == "D"
nTemp := ::aReport[ HEADER ][ nI ][ 5 ] / ::aReport[ LPI ] // top
IF ::aReport[ HEADER ][ nI ][ 5 ] > ::aReport[ PAGEY ] / 2
IF nTemp < ::aReport[ PDFBOTTOM ]
::aReport[ PDFBOTTOM ] := nTemp
ENDIF
ELSE
IF nTemp > ::aReport[ PDFTOP]
::aReport[ PDFTOP] := nTemp
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
next
IF nTop != NIL
::aReport[ PDFTOP] := nTop
ENDIF
IF nLeft != NIL
::aReport[ PDFLEFT ] := nLeft
ENDIF
IF nBottom != NIL
::aReport[ PDFBOTTOM ] := nBottom
ENDIF
::aReport[ MARGINS ] := .f.
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:CreateHeader( _file, _size, _orient, _lpi, _width )
#else
METHOD CreateHeader( _file, _size, _orient, _lpi, _width )
#endif
local ;
aReportStyle := { ;
{ 1, 2, 3, 4, 5, 6 }, ; //"Default"
{ 2.475, 4.0, 4.9, 6.4, 7.5, 64.0 }, ; //"P6"
{ 3.3 , 5.4, 6.5, 8.6, 10.0, 85.35 }, ; //"P8"
{ 2.475, 4.0, 4.9, 6.4, 7.5, 48.9 }, ; //"L6"
{ 3.3 , 5.4, 6.5, 8.6, 10.0, 65.2 }, ; //"L8"
{ 2.475, 4.0, 4.9, 6.4, 7.5, 82.0 }, ; //"P6"
{ 3.3 , 5.4, 6.5, 8.6, 10.0, 109.35 } ; //"P8"
}
local nStyle := 1, nAdd := 0.00
DEFAULT _size TO ::aReport[ PAGESIZE ]
DEFAULT _orient TO ::aReport[ PAGEORIENT ]
DEFAULT _lpi TO ::aReport[ LPI ]
DEFAULT _width TO 200
IF _size == "LETTER"
IF _orient == "P"
IF _lpi == 6
nStyle := 2
ELSEIF _lpi == 8
nStyle := 3
ENDIF
ELSEIF _orient == "L"
IF _lpi == 6
nStyle := 4
ELSEIF _lpi == 8
nStyle := 5
ENDIF
ENDIF
ELSEIF _size == "LEGAL"
IF _orient == "P"
IF _lpi == 6
nStyle := 6
ELSEIF _lpi == 8
nStyle := 7
ENDIF
ELSEIF _orient == "L"
IF _lpi == 6
nStyle := 4
ELSEIF _lpi == 8
nStyle := 5
ENDIF
ENDIF
ENDIF
::EditOnHeader()
IF _size == "LEGAL"
nAdd := 76.2
ENDIF
IF _orient == "P"
::Box( 5.0, 5.0, 274.0 + nAdd, 210.0, 1.0 )
::Box( 6.5, 6.5, 272.5 + nAdd, 208.5, 0.5 )
::Box( 11.5, 9.5, 22.0 , 205.5, 0.5, 5 )
::Box( 23.0, 9.5, 33.5 , 205.5, 0.5, 5 )
::Box( 34.5, 9.5, 267.5 + nAdd, 205.5, 0.5 )
ELSE
::Box( 5.0, 5.0, 210.0, 274.0 + nAdd, 1.0 )
::Box( 6.5, 6.5, 208.5, 272.5 + nAdd, 0.5 )
::Box( 11.5, 9.5, 22.0, 269.5 + nAdd, 0.5, 5 )
::Box( 23.0, 9.5, 33.5, 269.5 + nAdd, 0.5, 5 )
::Box( 34.5, 9.5, 203.5, 269.5 + nAdd, 0.5 )
ENDIF
::SetFont("Arial", BOLD, 10)
::AtSay( "Test Line 1", aReportStyle[ nStyle ][ 1 ], 1, "R", .t. )
::SetFont("Times", BOLD, 18)
::Center( "Test Line 2", aReportStyle[ nStyle ][ 2 ],,"R", .t. )
::SetFont("Times", BOLD, 12)
::Center( "Test Line 3", aReportStyle[ nStyle ][ 3 ],,"R", .t. )
::SetFont("Arial", BOLD, 10)
::AtSay( "Test Line 4", aReportStyle[ nStyle ][ 4 ], 1, "R", .t. )
::SetFont("Arial", BOLD, 10)
::AtSay( "Test Line 5", aReportStyle[ nStyle ][ 5 ], 1, "R", .t. )
::AtSay( dtoc( date()) + " " + TimeAsAMPM( time() ), aReportStyle[ nStyle ][ 6 ], 1, "R", .t. )
::RJust( "Page: #pagenumber#", aReportStyle[ nStyle ][ 6 ], ::aReport[ REPORTWIDTH ], "R", .t. )
::EditOffHeader()
::SaveHeader( _file )
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:ImageInfo( cFile )
#else
METHOD ImageInfo( cFile )
#endif
local cTemp := upper(substr( cFile, rat(".", cFile) + 1 )), aTemp := {}
do case
case cTemp == "TIF"
aTemp := ::TIFFInfo( cFile )
case cTemp == "JPG"
aTemp := ::JPEGInfo( cFile )
endcase
RETURN aTemp
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:TIFFInfo( cFile )
#else
METHOD TIFFInfo( cFile )
#endif
local c40 := chr(0)+chr(0)+chr(0)+chr(0)
//local aType := {"BYTE","ASCII","SHORT","LONG","RATIONAL","SBYTE","UNDEFINED","SSHORT","SLONG","SRATIONAL","FLOAT","DOUBLE"}
local aCount := { 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8 }
local nTemp, nHandle, cValues, c2, nFieldType, nCount, nPos, nTag, nValues
local nOffset, cTemp, cIFDNext, nIFD, nFields, cTag, nn
local nWidth := 0, nHeight := 0, nBits := 0, nFrom := 0, nLength := 0, xRes := 0, yRes := 0, aTemp := {}
nHandle := fopen( cFile )
c2 := " "
fread( nHandle, @c2, 2 )
fread( nHandle, @c2, 2 )
cIFDNext := " "
fread( nHandle, @cIFDNext, 4 )
cTemp := space(12)
while !( cIFDNext == c40 ) //read IFD's
nIFD := bin2l( cIFDNext )
fseek( nHandle, nIFD )
fread( nHandle, @c2, 2 )
nFields := bin2i( c2 )
for nn := 1 to nFields
fread( nHandle, @cTemp, 12 )
nTag := bin2w( substr( cTemp, 1, 2 ) )
nFieldType := bin2w( substr( cTemp, 3, 2 ) )
nCount := bin2l( substr( cTemp, 5, 4 ) )
nOffset := bin2l( substr( cTemp, 9, 4 ) )
IF nCount > 1 .or. nFieldType == RATIONAL .or. nFieldType == SRATIONAL
nPos := filepos( nHandle )
fseek( nHandle, nOffset)
nValues := nCount * aCount[ nFieldType ]
cValues := space( nValues )
fread( nHandle, @cValues, nValues )
fseek( nHandle, nPos )
ELSE
cValues := substr( cTemp, 9, 4 )
ENDIF
IF nFieldType == ASCII
--nCount
ENDIF
//cTag := ""
do case
case nTag == 256
cTag := "ImageWidth"
IF nFieldType == SHORT
nWidth := bin2w( substr( cValues, 1, 2 ))
ELSEIF nFieldType == LONG
nWidth := bin2l( substr( cValues, 1, 4 ))
ENDIF
case nTag == 257
cTag := "ImageLength"
IF nFieldType == SHORT
nHeight := bin2w(substr( cValues, 1, 2 ))
ELSEIF nFieldType == LONG
nHeight := bin2l(substr( cValues, 1, 4 ))
ENDIF
case nTag == 258
cTag := "BitsPerSample"
nTemp := 0
IF nFieldType == SHORT
nTemp := bin2w( cValues )
ENDIF
nBits := nTemp
case nTag == 259
cTag := "Compression"
/*nTemp := 0
IF nFieldType == SHORT
nTemp := bin2w( cValues )
ENDIF*/
case nTag == 262
cTag := "PhotometricInterpretation"
/*nTemp := -1
IF nFieldType == SHORT
nTemp := bin2w( cValues )
ENDIF*/
case nTag == 264
cTag := "CellWidth"
case nTag == 265
cTag := "CellLength"
case nTag == 266
cTag := "FillOrder"
case nTag == 273
cTag := "StripOffsets"
IF nFieldType == SHORT
nFrom := bin2w(substr( cValues, 1, 2 ))
ELSEIF nFieldType == LONG
nFrom := bin2l(substr( cValues, 1, 4 ))
ENDIF
case nTag == 277
cTag := "SamplesPerPixel"
case nTag == 278
cTag := "RowsPerStrip"
case nTag == 279
cTag := "StripByteCounts"
IF nFieldType == SHORT
nLength := bin2w(substr( cValues, 1, 2 ))
ELSEIF nFieldType == LONG
nLength := bin2l(substr( cValues, 1, 4 ))
ENDIF
nLength *= nCount // Count all strips !!!
case nTag == 282
cTag := "XResolution"
xRes := bin2l(substr( cValues, 1, 4 ))
case nTag == 283
cTag := "YResolution"
yRes := bin2l(substr( cValues, 1, 4 ))
case nTag == 284
cTag := "PlanarConfiguration"
case nTag == 288
cTag := "FreeOffsets"
case nTag == 289
cTag := "FreeByteCounts"
case nTag == 296
cTag := "ResolutionUnit"
/*nTemp := 0
IF nFieldType == SHORT
nTemp := bin2w( cValues )
ENDIF*/
case nTag == 305
cTag := "Software"
case nTag == 306
cTag := "DateTime"
case nTag == 315
cTag := "Artist"
case nTag == 320
cTag := "ColorMap"
case nTag == 338
cTag := "ExtraSamples"
case nTag == 33432
cTag := "Copyright"
otherwise
cTag := "Unknown"
endcase
next
fread( nHandle, @cIFDNext, 4 )
enddo
HB_SYMBOL_UNUSED( cTag ) // TOFIX
fclose( nHandle )
aadd( aTemp, nWidth )
aadd( aTemp, nHeight )
aadd( aTemp, xRes )
aadd( aTemp, yRes )
aadd( aTemp, nBits )
aadd( aTemp, nFrom )
aadd( aTemp, nLength )
return aTemp
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:JPEGInfo( cFile )
#else
METHOD JPEGInfo( cFile )
#endif
local c255, nAt, nHandle
local nWidth, nHeight, nBits := 8, nFrom := 0
local nLength, xRes, yRes, aTemp := {}
nHandle := fopen( cFile )
c255 := space(1024)
fread( nHandle, @c255, 1024 )
xRes := asc(substr( c255, 15, 1 )) * 256 + asc(substr( c255, 16, 1 ))
yRes := asc( substr( c255, 17, 1 )) * 256 + asc(substr( c255, 18, 1 ))
nAt := at( chr(255) + chr(192), c255 ) + 5
nHeight := asc(substr( c255, nAt, 1 )) * 256 + asc(substr( c255, nAt + 1, 1 ))
nWidth := asc( substr( c255, nAt + 2, 1 )) * 256 + asc(substr( c255, nAt + 3, 1 ))
fclose( nHandle )
nLength := filesize( cFile )
aadd( aTemp, nWidth )
aadd( aTemp, nHeight )
aadd( aTemp, xRes )
aadd( aTemp, yRes )
aadd( aTemp, nBits )
aadd( aTemp, nFrom )
aadd( aTemp, nLength )
return aTemp
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:BookCount( nRecno, nCurLevel )
#else
METHOD BookCount( nRecno, nCurLevel )
#endif
local nTempLevel, nCount := 0, nLen := len( ::aReport[ BOOKMARK ] )
++nRecno
while nRecno <= nLen
nTempLevel := ::aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
IF nTempLevel <= nCurLevel
exit
ELSE
IF nCurLevel + 1 == nTempLevel
++nCount
ENDIF
ENDIF
++nRecno
enddo
return -1 * nCount
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:BookFirst( nRecno, nCurLevel, nObj )
#else
METHOD BookFirst( nRecno, nCurLevel, nObj )
#endif
local nFirst := 0, nLen := len( ::aReport[ BOOKMARK ] )
++nRecno
IF nRecno <= nLen
IF nCurLevel + 1 == ::aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
nFirst := nRecno
ENDIF
ENDIF
return IIF( nFirst == 0, nFirst, nObj + nFirst )
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:BookLast( nRecno, nCurLevel, nObj )
#else
METHOD BookLast( nRecno, nCurLevel, nObj )
#endif
local nLast := 0, nLen := len( ::aReport[ BOOKMARK ] )
++nRecno
IF nRecno <= nLen
IF nCurLevel + 1 == ::aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
while nRecno <= nLen .and. nCurLevel + 1 <= ::aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
IF nCurLevel + 1 == ::aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
nLast := nRecno
ENDIF
++nRecno
enddo
ENDIF
ENDIF
return IIF( nLast == 0, nLast, nObj + nLast )
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:BookNext( nRecno, nCurLevel, nObj )
#else
METHOD BookNext( nRecno, nCurLevel, nObj )
#endif
local nTempLevel, nNext := 0, nLen := len( ::aReport[ BOOKMARK ] )
++nRecno
while nRecno <= nLen
nTempLevel := ::aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
IF nCurLevel > nTempLevel
exit
ELSEIF nCurLevel == nTempLevel
nNext := nRecno
exit
ELSE
// keep going
ENDIF
++nRecno
enddo
return IIF( nNext == 0, nNext, nObj + nNext )
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:BookParent( nRecno, nCurLevel, nObj )
#else
METHOD BookParent( nRecno, nCurLevel, nObj )
#endif
local nTempLevel
local nParent := 0
--nRecno
while nRecno > 0
nTempLevel := ::aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
IF nTempLevel < nCurLevel
nParent := nRecno
exit
ENDIF
--nRecno
enddo
return IIF( nParent == 0, nObj - 1, nObj + nParent )
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:BookPrev( nRecno, nCurLevel, nObj )
#else
METHOD BookPrev( nRecno, nCurLevel, nObj )
#endif
local nTempLevel
local nPrev := 0
--nRecno
while nRecno > 0
nTempLevel := ::aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
IF nCurLevel > nTempLevel
exit
ELSEIF nCurLevel == nTempLevel
nPrev := nRecno
exit
ELSE
// keep going
ENDIF
--nRecno
enddo
return IIF( nPrev == 0, nPrev, nObj + nPrev )
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:CheckLine( nRow )
#else
METHOD CheckLine( nRow )
#endif
IF nRow + ::aReport[ PDFTOP] > ::aReport[ PDFBOTTOM ]
::NewPage()
nRow := ::aReport[ REPORTLINE ]
ENDIF
::aReport[ REPORTLINE ] := nRow
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:GetFontInfo( cParam )
#else
METHOD GetFontInfo( cParam )
#endif
local cRet
IF cParam == "NAME"
IF left( ::aReport[ TYPE1 ][ ::aReport[ FONTNAME ] ], 5 ) == "Times"
cRet := "Times"
ELSEIF left( ::aReport[ TYPE1 ][ ::aReport[ FONTNAME ] ], 9 ) == "Helvetica"
cRet := "Helvetica"
ELSE
cRet := "Courier" // 0.04
ENDIF
ELSE // size
cRet := int(( ::aReport[ FONTNAME ] - 1 ) % 4)
ENDIF
return cRet
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:M2R( mm )
#else
METHOD M2R( mm )
#endif
return int( ::aReport[ LPI ] * mm / 25.4 )
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:M2X( n )
#else
METHOD M2X( n )
#endif
return n * 72 / 25.4
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:M2Y( n )
#else
METHOD M2Y( n )
#endif
return ::aReport[ PAGEY ] - n * 72 / 25.4
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:R2D( nRow )
#else
METHOD R2D( nRow )
#endif
return ::aReport[ PAGEY ] - nRow * 72 / ::aReport[ LPI ]
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:R2M( nRow )
#else
METHOD R2M( nRow )
#endif
return 25.4 * nRow / ::aReport[ LPI ]
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:X2M( n )
#else
METHOD X2M( n )
#endif
return n * 25.4 / 72
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:TextPrint( nI, nLeft, lParagraph, nJustify, nSpace, nNew, nLength, nLineLen, nLines, nStart, cString, cDelim, cColor, lPrint )
#else
METHOD TextPrint( nI, nLeft, lParagraph, nJustify, nSpace, nNew, nLength, nLineLen, nLines, nStart, cString, cDelim, cColor, lPrint )
#endif
local nFinish, nL, nB, nJ, cToken, nRow
nFinish := nI
nL := nLeft
IF lParagraph
IF nJustify != 2
nL += nSpace * nNew
ENDIF
ENDIF
IF nJustify == 3 // right
nL += nLength - nLineLen
ELSEIF nJustify == 2 // center
nL += ( nLength - nLineLen ) / 2
ENDIF
++nLines
IF lPrint
nRow := ::NewLine( 1 )
ENDIF
nB := nSpace
IF nJustify == 4
nB := ( nLength - nLineLen + ( nFinish - nStart ) * nSpace ) / ( nFinish - nStart )
ENDIF
for nJ := nStart to nFinish
cToken := token( cString, cDelim, nJ )
IF lPrint
// version 0.02
::AtSay( cColor + cToken, ::R2M( nRow + ::aReport[ PDFTOP ] ), nL, "M" )
ENDIF
nL += ::Length( cToken ) + nB
next
nStart := nFinish + 1
lParagraph := .f.
nLineLen := 0.00
nLineLen += nSpace * nNew
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:TextNextPara( cString, cDelim, nI )
#else
METHOD TextNextPara( cString, cDelim, nI )
#endif
local nAt, cAt, nCRLF, nNew, nRat, nRet := 0
// check if next spaces paragraph(s)
nAt := attoken( cString, cDelim, nI ) + len( token( cString, cDelim, nI ) )
cAt := substr( cString, nAt, attoken( cString, cDelim, nI + 1 ) - nAt )
nCRLF := numat( chr(13) + chr(10), cAt )
nRat := rat( chr(13) + chr(10), cAt )
nNew := len( cAt ) - nRat - IIF( nRat > 0, 1, 0 )
IF nCRLF > 1 .or. ( nCRLF == 1 .and. nNew > 0 )
nRet := nCRLF
ENDIF
return nRet
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:ClosePage()
#else
METHOD ClosePage()
#endif
local cTemp, cBuffer, nBuffer, nRead, nI, k, nImage, nFont, nImageHandle
aadd( ::aReport[ REFS ], ::aReport[ DOCLEN ] )
aadd( ::aReport[ PAGES ], ::aReport[ REPORTOBJ ] + 1 )
cTemp := ;
ltrim(str( ++::aReport[ REPORTOBJ ] )) + " 0 obj" + CRLF + ;
"<<" + CRLF + ;
"/Type /Page /Parent 1 0 R" + CRLF + ;
"/Resources " + ltrim(str( ++::aReport[ REPORTOBJ ] )) + " 0 R" + CRLF + ;
"/MediaBox [ 0 0 " + ltrim(transform( ::aReport[ PAGEX ], "9999.99")) + " " + ;
ltrim(transform(::aReport[ PAGEY ], "9999.99")) + " ]" + CRLF + ;
"/Contents " + ltrim(str( ++::aReport[ REPORTOBJ ] )) + " 0 R" + CRLF + ;
">>" + CRLF + ;
"endobj" + CRLF
::aReport[ DOCLEN ] += len( cTemp )
fwrite( ::aReport[ HANDLE ], cTemp )
aadd( ::aReport[ REFS ], ::aReport[ DOCLEN ] )
cTemp := ;
ltrim(str(::aReport[ REPORTOBJ ] - 1)) + " 0 obj" + CRLF + ;
"<<"+CRLF+;
"/ColorSpace << /DeviceRGB /DeviceGray >>" + CRLF + ; //version 0.01
"/ProcSet [ /PDF /Text /ImageB /ImageC ]"
IF len( ::aReport[ PAGEFONTS ] ) > 0
cTemp += CRLF + ;
"/Font" + CRLF + ;
"<<"
for nI := 1 to len( ::aReport[ PAGEFONTS ] )
nFont := ascan( ::aReport[ FONTS ], { |arr| arr[1] == ::aReport[ PAGEFONTS ][ nI ] } )
cTemp += CRLF + "/Fo" + ltrim(str( nFont )) + " " + ltrim(str( ::aReport[ FONTS ][ nFont ][ 2 ])) + " 0 R"
next
cTemp += CRLF + ">>"
ENDIF
IF len( ::aReport[ PAGEIMAGES ] ) > 0
cTemp += CRLF + "/XObject" + CRLF + "<<"
for nI := 1 to len( ::aReport[ PAGEIMAGES ] )
nImage := ascan( ::aReport[ IMAGES ], { |arr| arr[1] == ::aReport[ PAGEIMAGES ][ nI ][ 1 ] } )
IF nImage == 0
aadd( ::aReport[ IMAGES ], { ::aReport[ PAGEIMAGES ][ nI ][ 1 ], ++::aReport[ NEXTOBJ ], ::ImageInfo( ::aReport[ PAGEIMAGES ][ nI ][ 1 ] ) } )
nImage := len( ::aReport[ IMAGES ] )
ENDIF
cTemp += CRLF + "/Image" + ltrim(str( nImage )) + " " + ltrim(str( ::aReport[ IMAGES ][ nImage ][ 2 ])) + " 0 R"
next
cTemp += CRLF + ">>"
ENDIF
cTemp += CRLF + ">>" + CRLF + "endobj" + CRLF
::aReport[ DOCLEN ] += len( cTemp )
fwrite( ::aReport[ HANDLE ], cTemp )
aadd( ::aReport[ REFS ], ::aReport[ DOCLEN ] )
cTemp := ltrim(str( ::aReport[ REPORTOBJ ] )) + " 0 obj << /Length " + ;
ltrim(str( ::aReport[ REPORTOBJ ] + 1 )) + " 0 R >>" + CRLF +;
"stream"
::aReport[ DOCLEN ] += len( cTemp )
fwrite( ::aReport[ HANDLE ], cTemp )
IF len( ::aReport[ PAGEIMAGES ] ) > 0
cTemp := ""
for nI := 1 to len( ::aReport[ PAGEIMAGES ] )
cTemp += CRLF + "q"
nImage := ascan( ::aReport[ IMAGES ], { |arr| arr[1] == ::aReport[ PAGEIMAGES ][ nI ][ 1 ] } )
cTemp += CRLF + ltrim(str( IIF( ::aReport[ PAGEIMAGES ][ nI ][ 5 ] == 0, ::M2X( ::aReport[ IMAGES ][ nImage ][ 3 ][ IMAGE_WIDTH ] / ::aReport[ IMAGES ][ nImage ][ 3 ][ IMAGE_XRES ] * 25.4 ), ::aReport[ PAGEIMAGES ][ nI ][ 5 ]))) + ;
" 0 0 " + ;
ltrim(str( IIF( ::aReport[ PAGEIMAGES ][ nI ][ 4 ] == 0, ::M2X( ::aReport[ IMAGES ][ nImage ][ 3 ][ IMAGE_HEIGHT ] / ::aReport[ IMAGES ][ nImage ][ 3 ][ IMAGE_YRES ] * 25.4 ), ::aReport[ PAGEIMAGES ][ nI ][ 4 ]))) + ;
" " + ltrim(str( ::aReport[ PAGEIMAGES ][ nI ][ 3 ] )) + ;
" " + ltrim(str( ::aReport[ PAGEY ] - ::aReport[ PAGEIMAGES ][ nI ][ 2 ] - ;
IIF( ::aReport[ PAGEIMAGES ][ nI ][ 4 ] == 0, ::M2X( ::aReport[ IMAGES ][ nImage ][ 3 ][ IMAGE_HEIGHT ] / ::aReport[ IMAGES ][ nImage ][ 3 ][ IMAGE_YRES ] * 25.4 ), ::aReport[ PAGEIMAGES ][ nI ][ 4 ]))) + " cm"
cTemp += CRLF + "/Image" + ltrim(str( nImage )) + " Do"
cTemp += CRLF + "Q"
next
::aReport[ PAGEBUFFER ] := cTemp + ::aReport[ PAGEBUFFER ]
ENDIF
cTemp := ::aReport[ PAGEBUFFER ]
cTemp += CRLF + "endstream" + CRLF + ;
"endobj" + CRLF
::aReport[ DOCLEN ] += len( cTemp )
fwrite( ::aReport[ HANDLE ], cTemp )
aadd( ::aReport[ REFS ], ::aReport[ DOCLEN ] )
cTemp := ltrim(str( ++::aReport[ REPORTOBJ ] )) + " 0 obj" + CRLF + ;
ltrim(str(len( ::aReport[ PAGEBUFFER ] ))) + CRLF + ;
"endobj" + CRLF
::aReport[ DOCLEN ] += len( cTemp )
fwrite( ::aReport[ HANDLE ], cTemp )
for nI := 1 to len( ::aReport[ FONTS ] )
IF ::aReport[ FONTS ][ nI ][ 2 ] > ::aReport[ REPORTOBJ ]
aadd( ::aReport[ REFS ], ::aReport[ DOCLEN ] )
cTemp := ;
ltrim(str( ::aReport[ FONTS ][ nI ][ 2 ] )) + " 0 obj" + CRLF + ;
"<<" + CRLF + ;
"/Type /Font" + CRLF + ;
"/Subtype /Type1" + CRLF + ;
"/Name /Fo" + ltrim(str( nI )) + CRLF + ;
"/BaseFont /" + ::aReport[ TYPE1 ][ ::aReport[ FONTS ][ nI ][ 1 ] ] + CRLF + ;
"/Encoding /WinAnsiEncoding" + CRLF + ;
">>" + CRLF + ;
"endobj" + CRLF
::aReport[ DOCLEN ] += len( cTemp )
fwrite( ::aReport[ HANDLE ], cTemp )
ENDIF
next
for nI := 1 to len( ::aReport[ IMAGES ] )
IF ::aReport[ IMAGES ][ nI ][ 2 ] > ::aReport[ REPORTOBJ ]
aadd( ::aReport[ REFS ], ::aReport[ DOCLEN ] )
cTemp := ;
ltrim(str( ::aReport[ IMAGES ][ nI ][ 2 ] )) + " 0 obj" + CRLF + ;
"<<" + CRLF + ;
"/Type /XObject" + CRLF + ;
"/Subtype /Image" + CRLF + ;
"/Name /Image" + ltrim(str(nI)) + CRLF + ;
"/Filter [" + IIF( at( ".jpg", lower( ::aReport[ IMAGES ][ nI ][ 1 ]) ) > 0, " /DCTDecode", "" ) + " ]" + CRLF + ;
"/Width " + ltrim(str( ::aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_WIDTH ] )) + CRLF + ;
"/Height " + ltrim(str( ::aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_HEIGHT ] )) + CRLF + ;
"/BitsPerComponent " + ltrim(str( ::aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_BITS ] )) + CRLF + ;
"/ColorSpace /" + IIF( ::aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_BITS ] == 1, "DeviceGray", "DeviceRGB") + CRLF + ;
"/Length " + ltrim(str( ::aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_LENGTH ])) + CRLF + ;
">>" + CRLF + ;
"stream" + CRLF
::aReport[ DOCLEN ] += len( cTemp )
fwrite( ::aReport[ HANDLE ], cTemp )
nImageHandle := fopen( ::aReport[ IMAGES ][ nI ][ 1 ] )
fseek( nImageHandle, ::aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_FROM ] )
nBuffer := 8192
cBuffer := space( nBuffer )
k := 0
while k < ::aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_LENGTH ]
IF k + nBuffer <= ::aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_LENGTH ]
nRead := nBuffer
ELSE
nRead := ::aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_LENGTH ] - k
ENDIF
fread( nImageHandle, @cBuffer, nRead )
::aReport[ DOCLEN ] += nRead
fwrite( ::aReport[ HANDLE ], cBuffer, nRead )
k += nRead
enddo
cTemp := CRLF + "endstream" + CRLF + "endobj" + CRLF
::aReport[ DOCLEN ] += len( cTemp )
fwrite( ::aReport[ HANDLE ], cTemp )
fClose( nImageHandle )
ENDIF
next
::aReport[ REPORTOBJ ] := ::aReport[ NEXTOBJ ]
::aReport[ NEXTOBJ ] := ::aReport[ REPORTOBJ ] + 4
::aReport[ PAGEBUFFER ] := ""
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:FilePrint( cFile )
#else
METHOD FilePrint( cFile )
#endif
local cPathAcro := "C:\progra~1\Adobe\Acroba~1.0\Reader"
local cRun := cPathAcro + "\AcroRd32.exe /t " + cFile + " " + ;
chr(34) + "HP LaserJet 5/5M PostScript" + chr(34) + " " + ;
chr(34) + "LPT1" + chr(34)
IF ( ! RunExternal( cRun, "print" ) )
alert( "Error printing to PDF reader." )
break
ENDIF
RETURN self
//-------------------------\\
#ifdef __XPP__
METHOD tPdf:Execute( cFile )
#else
METHOD Execute( cFile )
#endif
// Replace cPathAcro with the path at your system
local cPathAcro := "C:\progra~1\Adobe\Acroba~1.0\Reader"
local cRun := cPathAcro + "\AcroRd32.exe /t " + cFile + " " + chr(34) + "HP LaserJet 5/5M PostScript" + chr(34) + " " + chr(34) + "LPT1" + chr(34)
IF (! RunExternal( cRun, "open", cFile ) )
alert("Error printing to PDF reader.")
break
ENDIF
RETURN self
//-------------------------\\
//-------------------------\\
//-------------------------\\
static function FilePos( nHandle )
return FSEEK( nHandle, 0, FS_RELATIVE )
//-------------------------\\
/*
static function stuff( cStr, nBeg, nDel, cIns )
return PosIns( PosDel( cStr, nBeg, nDel ), cIns, nBeg )
*/
//-------------------------\\
static function Chr_RGB( cChar )
return str(asc( cChar ) / 255, 4, 2)
//-------------------------\\
static function TimeAsAMPM( cTime )
IF VAL(cTime) < 12
cTime += " am"
ELSEIF VAL(cTime) == 12
cTime += " pm"
ELSE
cTime := STR(VAL(cTime) - 12, 2) + SUBSTR(cTime, 3) + " pm"
ENDIF
cTime := left( cTime, 5 ) + substr( cTime, 10 )
return cTime
//-------------------------\\
static function FileSize( cFile )
LOCAL nLength
LOCAL nHandle
nHandle := fOpen( cFile )
nLength := fSeek( nHandle, 0, FS_END )
fClose( nHandle )
return nLength
//-------------------------\\
static FUNCTION NumToken( cString, cDelimiter )
RETURN AllToken( cString, cDelimiter )
//-------------------------\\
static FUNCTION Token( cString, cDelimiter, nPointer )
RETURN AllToken( cString, cDelimiter, nPointer, 1 )
//-------------------------\\
static function AtToken( cString, cDelimiter, nPointer )
return AllToken( cString, cDelimiter, nPointer, 2 )
//-------------------------\\
static function AllToken( cString, cDelimiter, nPointer, nAction )
local nTokens := 0
local nPos := 1
local nLen := len( cString )
local nStart
local cRet := 0
DEFAULT cDelimiter TO chr(0)+chr(9)+chr(10)+chr(13)+chr(26)+chr(32)+chr(138)+chr(141)
DEFAULT nAction to 0
// nAction == 0 - numtoken
// nAction == 1 - token
// nAction == 2 - attoken
while nPos <= nLen
if .not. substr( cString, nPos, 1 ) $ cDelimiter
nStart := nPos
while nPos <= nLen .and. .not. substr( cString, nPos, 1 ) $ cDelimiter
++nPos
enddo
++nTokens
IF nAction > 0
IF nPointer == nTokens
IF nAction == 1
cRet := substr( cString, nStart, nPos - nStart )
ELSE
cRet := nStart
ENDIF
exit
ENDIF
ENDIF
endif
if substr( cString, nPos, 1 ) $ cDelimiter
while nPos <= nLen .and. substr( cString, nPos, 1 ) $ cDelimiter
++nPos
enddo
endif
cRet := nTokens
ENDDO
RETURN cRet
//-------------------------\\
//
// next 3 function written by Peter Kulek
// modified for compatibility with common.ch by V.K.
// modified DATE processing by V.K.
//
static function Array2File( cFile, aRay, nDepth, hFile )
local nBytes := 0
local i
local lOpen := ( hFile != nil )
nDepth := iif( ISNUMBER( nDepth ), nDepth, 0 )
//if hFile == NIL
if !lOpen
if ( hFile := fCreate( cFile,FC_NORMAL ) ) == -1
return nBytes
endif
endif
nDepth++
nBytes += WriteData( hFile,aRay )
if ISARRAY( aRay )
for i := 1 to len( aRay )
nBytes += Array2File( cFile,aRay[i],nDepth,hFile )
next
endif
nDepth--
// if nDepth == 0
if !lOpen
fClose(hFile)
endif
return nBytes
//-------------------------\\
static function WriteData(hFile,xData)
local cData := valtype(xData)
if ISCHARACTER(xData)
cData += i2bin( len( xData ) ) + xData
elseif ISNUMBER(xData)
cData += i2bin( len( alltrim( str( xData ) ) ) ) + alltrim( str( xData ) )
elseif ISDATE( xData )
cData += i2bin( 8 )+dtos(xData)
elseif ISLOGICAL(xData)
cData += i2bin( 1 )+iif( xData,"T","F" )
elseif ISARRAY( xData )
cData += i2bin( len( xData ) )
else
cData += i2bin( 0 ) // NIL
endif
return fWrite( hFile, cData, len( cData ) )
//-------------------------\\
static function File2Array( cFile, nLen, hFile )
LOCAL cData,cType,nDataLen,nBytes
local nDepth := 0
local aRay := {}
local lOpen := ( hFile != nil )
if hFile == NIL // First Timer
if ( hFile := fOpen( cFile,FO_READ ) ) == -1
return aRay
endif
cData := space( 3 )
fRead( hFile, @cData, 3 )
if !( left( cData,1 ) == "A" ) // If format of file != array
fClose( hFile ) //////////
return aRay
endif
nLen := bin2i( right( cData,2 ) )
endif
do while nDepth < nLen
cData := space( 3 )
nBytes := fRead( hFile, @cData, 3 )
if nBytes < 3
exit
endif
cType := padl( cData,1 )
nDataLen := bin2i( right( cData,2 ) )
if !( cType == "A" )
cData := space( nDataLen )
nBytes:= fRead( hFile, @cData, nDataLen )
if nBytes < nDataLen
exit
endif
endif
nDepth++
aadd( aRay,NIL )
if cType=="C"
aRay[ nDepth ] := cData
elseif cType=="N"
aRay[ nDepth ] := val(cData)
elseif cType=="D"
aRay[ nDepth ] := ctod( left( cData, 4 ) + "/" + substr( cData, 5, 2 ) + "/" + substr( cData, 7, 2 )) //stod(cData)
elseif cType=="L"
aRay[ nDepth ] := ( cData=="T" )
elseif cType=="A"
aRay[ nDepth ] := File2Array( , nDataLen, hFile )
endif
enddo
if !lOpen
fClose( hFile )
endif
return aRay
//-------------------------\\
static FUNCTION NumAt( cSearch, cString )
LOCAL n := 0, nAt, nPos := 0
WHILE ( nAt := at( cSearch, substr( cString, nPos + 1 ) )) > 0
nPos += nAt
++n
ENDDO
RETURN n
//-------------------------\\
static function RunExternal( cCmd, cVerb, cFile )
local lRet := .t.
#ifdef __CLP__
lRet := SwpRunCmd( cCmd, 0, "", "" )
#endif
#ifdef __HARBOUR__
if cVerb != nil
// TOFIX: This requires hbwhat, which in turns requires xhb.
// This has to be solved differently.
// ShellExecute( GetDeskTopWindow(), cVerb, cFile, , , 1 )
HB_SYMBOL_UNUSED( cFile )
else
hb_run( cCmd )
endif
#endif
#ifdef __XPP__
RunShell( cCmd, , .t., .t. )
#endif
return lRet
//-------------------------\\