/* * $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 [ FROM ] => CLASS [ FROM ] #command MESSAGE METHOD => METHOD IS #command CLASS MESSAGE METHOD => CLASS METHOD IS #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 //-------------------------\\