hbvpdf

  Previous topic Next topic JavaScript is required for the print function Mail us feedback on this topic! Mail us feedback on this topic!  
c:\harbour\contrib\hbvpdf
hbvpdf.prg
TypeFunctionSourceLine
FUNCTIONpdfInit()
function pdfInit()                                                            /*
=============================================================                 */

s_aReport := array( PARAMLEN )

return s_aReport
hbvpdf.prg10
FUNCTIONpdfWidth( _nWidth )
function pdfWidth( _nWidth )                                                  /*
=============================================================                 */

s_aReport[ REPORTWIDTH ] := _nWidth

return nil
hbvpdf.prg18
FUNCTIONpdfTextWidth( cStr )
function pdfTextWidth( cStr )                                                 /*
=============================================================                 */

return pdfLen( cStr ) / 25.4
hbvpdf.prg26
FUNCTIONpdfAtSay( cString, nRow, nCol, cUnits, lExact, cId )
function pdfAtSay( cString, nRow, nCol, cUnits, lExact, cId )                 /*
=============================================================                 */
local _nFont, lReverse, nAt

DEFAULT nRow to s_aReport[ REPORTLINE ]
DEFAULT cUnits to "R"
DEFAULT lExact to .f.
DEFAULT cId to ""

   IF s_aReport[ HEADEREDIT ]
      return pdfHeader( "PDFATSAY", cId, { cString, nRow, nCol, cUnits, lExact } )
   ENDIF

   IF ( nAt := at( "#pagenumber#", cString ) ) > 0
      cString := left( cString, nAt - 1 ) + ltrim(str( pdfPageNumber())) + substr( cString, nAt + 12 )
   ENDIF

   lReverse := .f.
   IF cUnits == "M"
      nRow := pdfM2Y( nRow )
      nCol := pdfM2X( nCol )
   ELSEIF cUnits == "R"
      IF !lExact
         pdfCheckLine( nRow )
         nRow := nRow + s_aReport[ PDFTOP ]
      ENDIF
      nRow := pdfR2D( nRow )
      nCol := pdfM2X( s_aReport[ PDFLEFT ] ) + ;
              nCol * 100.00 / s_aReport[ REPORTWIDTH ] * ;
              ( s_aReport[ PAGEX ] - pdfM2X( s_aReport[ PDFLEFT ] ) * 2 - 9.0 ) / 100.00
   ENDIF
   IF !empty( cString )
      cString := pdfStringB( cString )
      IF right( cString, 1 ) == chr(255) //reverse
         cString := left( cString, len( cString ) - 1 )
         pdfBox( s_aReport[ PAGEY ] - nRow - s_aReport[ FONTSIZE ] + 2.0 , nCol, s_aReport[ PAGEY ] - nRow + 2.0, nCol + pdfM2X( pdfLen( cString )) + 1,,100, "D")
         s_aReport[ PAGEBUFFER ] += " 1 g "
         lReverse := .t.
      ELSEIF right( cString, 1 ) == chr(254) //underline
         cString := left( cString, len( cString ) - 1 )
         pdfBox( s_aReport[ PAGEY ] - nRow + 0.5,  nCol, s_aReport[ PAGEY ] - nRow + 1, nCol + pdfM2X( pdfLen( cString )) + 1,,100, "D")
      ENDIF

      // version 0.01
      IF ( nAt := at( chr(253), cString )) > 0 // some color text inside
         s_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( s_aReport[ FONTS ], {|arr| arr[1] == s_aReport[ FONTNAME ]} )
      IF !( s_aReport[ FONTNAME ] == s_aReport[ FONTNAMEPREV ] )
         s_aReport[ FONTNAMEPREV ] := s_aReport[ FONTNAME ]
         s_aReport[ PAGEBUFFER ] += CRLF + "BT /Fo" + ltrim(str( _nFont )) + " " + ltrim(transform( s_aReport[ FONTSIZE ], "999.99")) + " Tf " + ltrim(transform( nCol, "9999.99" )) + " " + ltrim(transform( nRow, "9999.99" )) + " Td (" + cString + ") Tj ET"
      ELSEIF s_aReport[ FONTSIZE ] != s_aReport[ FONTSIZEPREV ]
         s_aReport[ FONTSIZEPREV ] := s_aReport[ FONTSIZE ]
         s_aReport[ PAGEBUFFER ] += CRLF + "BT /Fo" + ltrim(str( _nFont )) + " " + ltrim(transform( s_aReport[ FONTSIZE ], "999.99")) + " Tf " + ltrim(transform( nCol, "9999.99" )) + " " + ltrim(transform( nRow, "9999.99" )) + " Td (" + cString + ") Tj ET"
      ELSE
         s_aReport[ PAGEBUFFER ] += CRLF + "BT " + ltrim(transform( nCol, "9999.99" )) + " " + ltrim(transform( nRow, "9999.99" )) + " Td (" + cString + ") Tj ET"
      ENDIF
      IF lReverse
         s_aReport[ PAGEBUFFER ] += " 0 g "
      ENDIF
   ENDIF
return nil
hbvpdf.prg32
FUNCTIONpdfBold()
function pdfBold()                                                            /*
==================                                                            */
   IF pdfGetFontInfo("NAME") = "Times"
      s_aReport[ FONTNAME ] := 2
   ELSEIF pdfGetFontInfo("NAME") = "Helvetica"
      s_aReport[ FONTNAME ] := 6
   ELSE
      s_aReport[ FONTNAME ] := 10 // Courier // 0.04
   ENDIF
   aadd( s_aReport[ PAGEFONTS ], s_aReport[ FONTNAME ] )
   IF ascan( s_aReport[ FONTS ], { |arr| arr[1] == s_aReport[ FONTNAME ] } ) == 0
      aadd( s_aReport[ FONTS ], { s_aReport[ FONTNAME ], ++s_aReport[ NEXTOBJ ] } )
   ENDIF
return nil
hbvpdf.prg102
FUNCTIONpdfBoldItalic()
function pdfBoldItalic()                                                      /*
========================                                                      */
   IF pdfGetFontInfo("NAME") = "Times"
      s_aReport[ FONTNAME ] := 4
   ELSEIF pdfGetFontInfo("NAME") = "Helvetica"
      s_aReport[ FONTNAME ] := 8
   ELSE
      s_aReport[ FONTNAME ] := 12 // 0.04
   ENDIF
   aadd( s_aReport[ PAGEFONTS ], s_aReport[ FONTNAME ] )
   IF ascan( s_aReport[ FONTS ], { |arr| arr[1] == s_aReport[ FONTNAME ] } ) == 0
      aadd( s_aReport[ FONTS ], { s_aReport[ FONTNAME ], ++s_aReport[ NEXTOBJ ] } )
   ENDIF
return nil
hbvpdf.prg118
FUNCTIONpdfBookAdd( cTitle, nLevel, nPage, nLine )
function pdfBookAdd( cTitle, nLevel, nPage, nLine )                           /*
===================================================                           */
   aadd( s_aReport[ BOOKMARK ], { nLevel, alltrim( cTitle ), 0, 0, 0, 0, 0, 0, nPage, IIF( nLevel == 1, s_aReport[ PAGEY ], s_aReport[ PAGEY ] - nLine * 72 / s_aReport[ LPI ] ) })
return Nil
hbvpdf.prg134
FUNCTIONpdfBookClose( )
function pdfBookClose( )                                                      /*
========================                                                      */
   s_aReport[ BOOKMARK ] := nil
return Nil
hbvpdf.prg140
STATIC FUNCTIONpdfBookCount( nRecno, nCurLevel )
static function pdfBookCount( nRecno, nCurLevel )                             /*
=================================================                             */
local nTempLevel := 0, nCount := 0, nLen := len( s_aReport[ BOOKMARK ] )
   ++nRecno
   while nRecno <= nLen
      nTempLevel := s_aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
      IF nTempLevel <= nCurLevel
         exit
      ELSE
         IF nCurLevel + 1 == nTempLevel
            ++nCount
         ENDIF
      ENDIF
      ++nRecno
   enddo
return -1 * nCount
hbvpdf.prg146
STATIC FUNCTIONpdfBookFirst( nRecno, nCurLevel, nObj )
static function pdfBookFirst( nRecno, nCurLevel, nObj )                       /*
=======================================================                       */
local nFirst := 0, nLen := len( s_aReport[ BOOKMARK ] )
   ++nRecno
   IF nRecno <= nLen
      IF nCurLevel + 1 == s_aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
         nFirst := nRecno
      ENDIF
   ENDIF
return IIF( nFirst == 0, nFirst, nObj + nFirst )
hbvpdf.prg164
STATIC FUNCTIONpdfBookLast( nRecno, nCurLevel, nObj )
static function pdfBookLast( nRecno, nCurLevel, nObj )                        /*
======================================================                        */
local nLast := 0, nLen := len( s_aReport[ BOOKMARK ] )
   ++nRecno
   IF nRecno <= nLen
      IF nCurLevel + 1 == s_aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
         while nRecno <= nLen .and. nCurLevel + 1 <= s_aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
            IF nCurLevel + 1 == s_aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
               nLast := nRecno
            ENDIF
            ++nRecno
         enddo
      ENDIF
   ENDIF
return IIF( nLast == 0, nLast, nObj + nLast )
hbvpdf.prg176
STATIC FUNCTIONpdfBookNext( nRecno, nCurLevel, nObj )
static function pdfBookNext( nRecno, nCurLevel, nObj )                        /*
======================================================                        */
local nTempLevel := 0, nNext := 0, nLen := len( s_aReport[ BOOKMARK ] )
   ++nRecno
   while nRecno <= nLen
      nTempLevel := s_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 )
hbvpdf.prg193
FUNCTIONpdfBookOpen( )
function pdfBookOpen( )                                                       /*
=======================                                                       */
   s_aReport[ BOOKMARK ] := {}
return Nil
hbvpdf.prg212
STATIC FUNCTIONpdfBookParent( nRecno, nCurLevel, nObj )
static function pdfBookParent( nRecno, nCurLevel, nObj )                      /*
========================================================                      */
local nTempLevel := 0
local nParent := 0
   --nRecno
   while nRecno > 0
      nTempLevel := s_aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
      IF nTempLevel < nCurLevel
         nParent := nRecno
         exit
      ENDIF
      --nRecno
   enddo
return IIF( nParent == 0, nObj - 1, nObj + nParent )
hbvpdf.prg218
STATIC FUNCTIONpdfBookPrev( nRecno, nCurLevel, nObj )
static function pdfBookPrev( nRecno, nCurLevel, nObj )                        /*
======================================================                        */
local nTempLevel := 0
local nPrev := 0
   --nRecno
   while nRecno > 0
      nTempLevel := s_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 )
hbvpdf.prg234
FUNCTIONpdfBox( x1, y1, x2, y2, nBorder, nShade, cUnits, cColor, cId )
function pdfBox( x1, y1, x2, y2, nBorder, nShade, cUnits, cColor, cId )       /*
===============================================================               */
local cBoxColor
DEFAULT nBorder to 0
DEFAULT nShade to 0
DEFAULT cUnits to "M"
DEFAULT cColor to ""

   // version 0.02
   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
   // version 0.02

   IF s_aReport[ HEADEREDIT ]
      return pdfHeader( "PDFBOX", cId, { x1, y1, x2, y2, nBorder, nShade, cUnits } )
   ENDIF

   IF cUnits == "M"
      y1 += 0.5
      y2 += 0.5

      IF nShade > 0
         // version 0.02
         s_aReport[ PAGEBUFFER ] += CRLF + transform( 1.00 - nShade / 100.00, "9.99") + " g " + cBoxColor + ltrim(str(pdfM2X( y1 ))) + " " + ltrim(str(pdfM2Y( x1 ))) + " " + ltrim(str(pdfM2X( y2 - y1 ))) + " -" + ltrim(str(pdfM2X( x2 - x1 ))) + " re f 0 g"
      ENDIF

      IF nBorder > 0
         s_aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str(pdfM2X( y1 ))) + " " + ltrim(str(pdfM2Y( x1 ))) + " " + ltrim(str(pdfM2X( y2 - y1 ))) + " -" + ltrim(str(pdfM2X( nBorder ))) + " re f"
         s_aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str(pdfM2X( y2 - nBorder ))) + " " + ltrim(str(pdfM2Y( x1 ))) + " " + ltrim(str(pdfM2X( nBorder ))) + " -" + ltrim(str(pdfM2X( x2 - x1 ))) + " re f"
         s_aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str(pdfM2X( y1 ))) + " " + ltrim(str(pdfM2Y( x2 - nBorder ))) + " " + ltrim(str(pdfM2X( y2 - y1 ))) + " -" + ltrim(str(pdfM2X( nBorder ))) + " re f"
         s_aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str(pdfM2X( y1 ))) + " " + ltrim(str(pdfM2Y( x1 ))) + " " + ltrim(str(pdfM2X( nBorder ))) + " -" + ltrim(str(pdfM2X( x2 - x1 ))) + " re f"
      ENDIF
   ELSEIF cUnits == "D"// "Dots"
      //x1, y1, x2, y2 - nTop, nLeft, nBottom, nRight
      IF nShade > 0
         // version 0.02
         s_aReport[ PAGEBUFFER ] += CRLF + transform( 1.00 - nShade / 100.00, "9.99") + " g " + cBoxColor + ltrim(str( y1 )) + " " + ltrim(str( s_aReport[ PAGEY ] - x1 )) + " " + ltrim(str( y2 - y1 )) + " -" + ltrim(str( x2 - x1 )) + " re f 0 g"
      ENDIF

      IF nBorder > 0
/*
            1
         ÚÄÄÄÄÄ¿
       4 ³     ³ 2
         ÀÄÄÄÄÄÙ
            3
*/
         s_aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str( y1 )) + " " + ltrim(str( s_aReport[ PAGEY ] - x1 )) + " " + ltrim(str( y2 - y1 )) + " -" + ltrim(str( nBorder )) + " re f"
         s_aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str( y2 - nBorder )) + " " + ltrim(str( s_aReport[ PAGEY ] - x1 )) + " " + ltrim(str( nBorder )) + " -" + ltrim(str( x2 - x1 )) + " re f"
         s_aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str( y1 )) + " " + ltrim(str( s_aReport[ PAGEY ] - x2 + nBorder )) + " " + ltrim(str( y2 - y1 )) + " -" + ltrim(str( nBorder )) + " re f"
         s_aReport[ PAGEBUFFER ] += CRLF + "0 g " + ltrim(str( y1 )) + " " + ltrim(str( s_aReport[ PAGEY ] - x1 )) + " " + ltrim(str( nBorder )) + " -" + ltrim(str( x2 - x1 )) + " re f"
      ENDIF
   ENDIF

return nil
hbvpdf.prg254
FUNCTIONpdfBox1( nTop, nLeft, nBottom, nRight, nBorderWidth, cBorderColor, cBoxColor )
function pdfBox1( nTop, nLeft, nBottom, nRight, nBorderWidth, cBorderColor, cBoxColor )       /*
===============================================================                               */
DEFAULT nBorderWidth to 0.5
DEFAULT cBorderColor to chr(0) + chr(0) + chr(0)
DEFAULT cBoxColor to chr(255) + chr(255) + chr(255)

   s_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 ( s_aReport[ PAGEY ] - nBottom + nBorderWidth / 2)) + " " + ;
                         CRLF + ltrim( str ( nRight - nLeft -  nBorderWidth )) + ;
                         CRLF + ltrim( str ( nBottom - nTop - nBorderWidth )) + " " + ;
                         " re" + ;
                         CRLF + "B"
return nil
hbvpdf.prg319
FUNCTIONpdfCenter( cString, nRow, nCol, cUnits, lExact, cId )
function pdfCenter( cString, nRow, nCol, cUnits, lExact, cId )                /*
==============================================================                */
local nLen, nAt
DEFAULT nRow to s_aReport[ REPORTLINE ]
DEFAULT cUnits to "R"
DEFAULT lExact to .f.
DEFAULT nCol to IIF( cUnits == "R", s_aReport[ REPORTWIDTH ] / 2, s_aReport[ PAGEX ] / 72 * 25.4 / 2 )

   IF s_aReport[ HEADEREDIT ]
      return pdfHeader( "PDFCENTER", cId, { cString, nRow, nCol, cUnits, lExact } )
   ENDIF

   IF ( nAt := at( "#pagenumber#", cString ) ) > 0
      cString := left( cString, nAt - 1 ) + ltrim(str( pdfPageNumber())) + substr( cString, nAt + 12 )
   ENDIF

   nLen := pdfLen( cString ) / 2
   IF cUnits == "R"
      IF !lExact
         pdfCheckLine( nRow )
         nRow := nRow + s_aReport[ PDFTOP ]
      ENDIF
   ENDIF
   pdfAtSay( cString, pdfR2M( nRow ), IIF( cUnits == "R", s_aReport[ PDFLEFT ] + ( s_aReport[ PAGEX ] / 72 * 25.4 - 2 * s_aReport[ PDFLEFT ] ) * nCol / s_aReport[ REPORTWIDTH ], nCol ) - nLen, "M", lExact )
return nil
hbvpdf.prg345
STATIC FUNCTIONpdfCheckLine( nRow )
static function pdfCheckLine( nRow )                                          /*
====================================                                          */
   IF nRow + s_aReport[ PDFTOP ] > s_aReport[ PDFBOTTOM ]
      pdfNewPage()
      nRow := s_aReport[ REPORTLINE ]
   ENDIF
   s_aReport[ REPORTLINE ] := nRow
return nil
hbvpdf.prg372
FUNCTIONpdfClose()
function pdfClose()                                                           /*
===================                                                           */
local nI, cTemp, nCurLevel, nObj1, nLast, nCount, nFirst, nRecno, nBooklen

   FIELD FIRST, PREV, NEXT, LAST, COUNT, PARENT, PAGE, COORD, TITLE, LEVEL

   pdfClosePage()

   // kids
   s_aReport[ REFS ][ 2 ] := s_aReport[ DOCLEN ]
   cTemp := ;
   "1 0 obj"+CRLF+;
   "<<"+CRLF+;
   "/Type /Pages /Count " + ltrim(str(s_aReport[ REPORTPAGE ])) + CRLF +;
   "/Kids ["

   for nI := 1 to s_aReport[ REPORTPAGE ] 
      cTemp += " " + ltrim(str( s_aReport[ PAGES ][ nI ] )) + " 0 R"
   next

   cTemp += " ]" + CRLF + ;
   ">>" + CRLF + ;
   "endobj" + CRLF

   s_aReport[ DOCLEN ] += len( cTemp )
   fwrite( s_aReport[ HANDLE ], cTemp )

   // info
   ++s_aReport[ REPORTOBJ ]
   aadd( s_aReport[ REFS ], s_aReport[ DOCLEN ] )
   cTemp := ltrim(str( s_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
   s_aReport[ DOCLEN ] += len( cTemp )
   fwrite( s_aReport[ HANDLE ], cTemp )

   // root
   ++s_aReport[ REPORTOBJ ]
   aadd( s_aReport[ REFS ], s_aReport[ DOCLEN ] )
   cTemp := ltrim(str( s_aReport[ REPORTOBJ ] )) + " 0 obj" + CRLF + ;
   "<< /Type /Catalog /Pages 1 0 R /Outlines " + ltrim(str( s_aReport[ REPORTOBJ ] + 1 )) + " 0 R" + IIF( ( nBookLen := len( s_aReport[ BOOKMARK ] )) > 0, " /PageMode /UseOutlines", "") + " >>" + CRLF + "endobj" + CRLF
   s_aReport[ DOCLEN ] += len( cTemp )
   fwrite( s_aReport[ HANDLE ], cTemp )

   ++s_aReport[ REPORTOBJ ]
   nObj1 := s_aReport[ REPORTOBJ ]

   IF nBookLen > 0

      nRecno := 1
      nFirst := s_aReport[ REPORTOBJ ] + 1
      nLast := 0
      nCount := 0
      while nRecno <= nBookLen
         nCurLevel := s_aReport[ BOOKMARK ][ nRecno ][ BOOKLEVEL ]
         s_aReport[ BOOKMARK ][ nRecno ][ BOOKPARENT ] := pdfBookParent( nRecno, nCurLevel, s_aReport[ REPORTOBJ ] )
         s_aReport[ BOOKMARK ][ nRecno ][ BOOKPREV ]   := pdfBookPrev( nRecno, nCurLevel, s_aReport[ REPORTOBJ ] )
         s_aReport[ BOOKMARK ][ nRecno ][ BOOKNEXT ]   := pdfBookNext( nRecno, nCurLevel, s_aReport[ REPORTOBJ ] )
         s_aReport[ BOOKMARK ][ nRecno ][ BOOKFIRST ]  := pdfBookFirst( nRecno, nCurLevel, s_aReport[ REPORTOBJ ] )
         s_aReport[ BOOKMARK ][ nRecno ][ BOOKLAST ]   := pdfBookLast( nRecno, nCurLevel, s_aReport[ REPORTOBJ ] )
         s_aReport[ BOOKMARK ][ nRecno ][ BOOKCOUNT ]  := pdfBookCount( nRecno, nCurLevel )
         IF nCurLevel == 1
            nLast := nRecno
            ++nCount
         ENDIF
         ++nRecno
      enddo

      nLast += s_aReport[ REPORTOBJ ]

      cTemp := ltrim(str( s_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( s_aReport[ REFS ], s_aReport[ DOCLEN ] )
      s_aReport[ DOCLEN ] += len( cTemp )
      fwrite( s_aReport[ HANDLE ], cTemp )

      ++s_aReport[ REPORTOBJ ]
      nRecno := 1
      FOR nI := 1 to nBookLen
         cTemp := CRLF + ltrim(str( s_aReport[ REPORTOBJ ] + nI - 1 )) + " 0 obj" + CRLF + ;
                 "<<" + CRLF + ;
                 "/Parent " + ltrim(str( s_aReport[ BOOKMARK ][ nRecno ][ BOOKPARENT ])) + " 0 R" + CRLF + ;
                 "/Dest [" + ltrim(str( s_aReport[ PAGES ][ s_aReport[ BOOKMARK ][ nRecno ][ BOOKPAGE ] ] )) + " 0 R /XYZ 0 " + ltrim( str( s_aReport[ BOOKMARK ][ nRecno ][ BOOKCOORD ])) + " 0]" + CRLF + ;
                 "/Title (" + alltrim( s_aReport[ BOOKMARK ][ nRecno ][ BOOKTITLE ]) + ")" + CRLF + ;
                 IIF( s_aReport[ BOOKMARK ][ nRecno ][ BOOKPREV ] > 0, "/Prev " + ltrim(str( s_aReport[ BOOKMARK ][ nRecno ][ BOOKPREV ])) + " 0 R" + CRLF, "") + ;
                 IIF( s_aReport[ BOOKMARK ][ nRecno ][ BOOKNEXT ] > 0, "/Next " + ltrim(str( s_aReport[ BOOKMARK ][ nRecno ][ BOOKNEXT ])) + " 0 R" + CRLF, "") + ;
                 IIF( s_aReport[ BOOKMARK ][ nRecno ][ BOOKFIRST ] > 0, "/First " + ltrim(str( s_aReport[ BOOKMARK ][ nRecno ][ BOOKFIRST ])) + " 0 R" + CRLF, "") + ;
                 IIF( s_aReport[ BOOKMARK ][ nRecno ][ BOOKLAST ] > 0, "/Last " + ltrim(str( s_aReport[ BOOKMARK ][ nRecno ][ BOOKLAST ])) + " 0 R" + CRLF, "") + ;
                 IIF( s_aReport[ BOOKMARK ][ nRecno ][ BOOKCOUNT ] != 0, "/Count " + ltrim(str( s_aReport[ BOOKMARK ][ nRecno ][ BOOKCOUNT ])) + CRLF, "") + ;
                 ">>" + CRLF + "endobj" + CRLF

         aadd( s_aReport[ REFS ], s_aReport[ DOCLEN ] + 2 )
         s_aReport[ DOCLEN ] += len( cTemp )
         fwrite( s_aReport[ HANDLE ], cTemp )
         ++nRecno
      NEXT
      pdfBookClose()

      s_aReport[ REPORTOBJ ] += nBookLen - 1
   ELSE
      cTemp := ltrim(str( s_aReport[ REPORTOBJ ] )) + " 0 obj" + CRLF + "<< /Type /Outlines /Count 0 >>" + CRLF + "endobj" + CRLF
      aadd( s_aReport[ REFS ], s_aReport[ DOCLEN ] )
      s_aReport[ DOCLEN ] += len( cTemp )
      fwrite( s_aReport[ HANDLE ], cTemp )
   ENDIF

   cTemp := CRLF
   s_aReport[ DOCLEN ] += len( cTemp )

   ++s_aReport[ REPORTOBJ ]

   cTemp += "xref" + CRLF + ;
   "0 " + ltrim(str( s_aReport[ REPORTOBJ ] )) + CRLF +;
   padl( s_aReport[ REFS ][ 1 ], 10, "0") + " 65535 f" + CRLF

   for nI := 2 to len( s_aReport[ REFS ] )
      cTemp += padl( s_aReport[ REFS ][ nI ], 10, "0") + " 00000 n" + CRLF
   next

   cTemp += "trailer << /Size " + ltrim(str( s_aReport[ REPORTOBJ ] )) + " /Root " + ltrim(str( nObj1 - 1 )) + " 0 R /Info " + ltrim(str( nObj1 - 2 )) + " 0 R >>" + CRLF + ;
            "startxref" + CRLF + ;
            ltrim(str( s_aReport[ DOCLEN ] )) + CRLF + ;
            "%%EOF" + CRLF
   fwrite( s_aReport[ HANDLE ], cTemp )
/*
   IF s_aReport[ OPTIMIZE ]
      pdfOptimize( ) coming !
   ENDIF
*/
   fclose( s_aReport[ HANDLE ] )

   s_aReport := nil

return nil
hbvpdf.prg382
STATIC FUNCTIONpdfClosePage()
static function pdfClosePage()                                                /*
==============================                                                */
local cTemp, cBuffer, nBuffer, nRead, nI, k, nImage, nFont, nImageHandle

   aadd( s_aReport[ REFS ], s_aReport[ DOCLEN ] )

   aadd( s_aReport[ PAGES ], s_aReport[ REPORTOBJ ] + 1 )

   cTemp := ;
   ltrim(str( ++s_aReport[ REPORTOBJ ] )) + " 0 obj" + CRLF + ;
   "<<" + CRLF + ;
   "/Type /Page /Parent 1 0 R" + CRLF + ;
   "/Resources " + ltrim(str( ++s_aReport[ REPORTOBJ ] )) + " 0 R" + CRLF + ;
   "/MediaBox [ 0 0 " + ltrim(transform( s_aReport[ PAGEX ], "9999.99")) + " " + ;
   ltrim(transform(s_aReport[ PAGEY ], "9999.99")) + " ]" + CRLF + ;
   "/Contents " + ltrim(str( ++s_aReport[ REPORTOBJ ] )) + " 0 R" + CRLF + ;
   ">>" + CRLF + ;
   "endobj" + CRLF

   s_aReport[ DOCLEN ] += len( cTemp )
   fwrite( s_aReport[ HANDLE ], cTemp )

   aadd( s_aReport[ REFS ], s_aReport[ DOCLEN ] )
   cTemp := ;
   ltrim(str(s_aReport[ REPORTOBJ ] - 1)) + " 0 obj" + CRLF + ;
   "<<"+CRLF+;
   "/ColorSpace << /DeviceRGB /DeviceGray >>" + CRLF + ; //version 0.01
   "/ProcSet [ /PDF /Text /ImageB /ImageC ]"

   IF len( s_aReport[ PAGEFONTS ] ) > 0
      cTemp += CRLF + ;
      "/Font" + CRLF + ;
      "<<"

      for nI := 1 to len( s_aReport[ PAGEFONTS ] )
         nFont := ascan( s_aReport[ FONTS ], { |arr| arr[1] == s_aReport[ PAGEFONTS ][ nI ] } )
         cTemp += CRLF + "/Fo" + ltrim(str( nFont )) + " " + ltrim(str( s_aReport[ FONTS ][ nFont ][ 2 ])) + " 0 R"
      next

      cTemp += CRLF + ">>"
   ENDIF

   IF len( s_aReport[ PAGEIMAGES ] ) > 0
      cTemp += CRLF + "/XObject" + CRLF + "<<"
      for nI := 1 to len( s_aReport[ PAGEIMAGES ] )
         nImage := ascan( s_aReport[ IMAGES ], { |arr| arr[1] == s_aReport[ PAGEIMAGES ][ nI ][ 1 ] } )
         IF nImage == 0
            aadd( s_aReport[ IMAGES ], { s_aReport[ PAGEIMAGES ][ nI ][ 1 ], ++s_aReport[ NEXTOBJ ], pdfImageInfo( s_aReport[ PAGEIMAGES ][ nI ][ 1 ] ) } )
            nImage := len( s_aReport[ IMAGES ] )
         ENDIF
         cTemp += CRLF + "/Image" + ltrim(str( nImage )) + " " + ltrim(str( s_aReport[ IMAGES ][ nImage ][ 2 ])) + " 0 R"
      next
      cTemp += CRLF + ">>"
   ENDIF

   cTemp += CRLF + ">>" + CRLF + "endobj" + CRLF

   s_aReport[ DOCLEN ] += len( cTemp )
   fwrite( s_aReport[ HANDLE ], cTemp )

   aadd( s_aReport[ REFS ], s_aReport[ DOCLEN ] )
   cTemp := ltrim(str( s_aReport[ REPORTOBJ ] )) + " 0 obj << /Length " + ;
   ltrim(str( s_aReport[ REPORTOBJ ] + 1 )) + " 0 R >>" + CRLF +;
   "stream"

   s_aReport[ DOCLEN ] += len( cTemp )
   fwrite( s_aReport[ HANDLE ], cTemp )

   IF len( s_aReport[ PAGEIMAGES ] ) > 0
      cTemp := ""
      for nI := 1 to len( s_aReport[ PAGEIMAGES ] )
         cTemp += CRLF + "q"
         nImage := ascan( s_aReport[ IMAGES ], { |arr| arr[1] == s_aReport[ PAGEIMAGES ][ nI ][ 1 ] } )
         cTemp += CRLF + ltrim(str( IIF( s_aReport[ PAGEIMAGES ][ nI ][ 5 ] == 0, pdfM2X( s_aReport[ IMAGES ][ nImage ][ 3 ][ IMAGE_WIDTH ] / s_aReport[ IMAGES ][ nImage ][ 3 ][ IMAGE_XRES ] * 25.4 ), s_aReport[ PAGEIMAGES ][ nI ][ 5 ]))) + ;
         " 0 0 " + ;
         ltrim(str( IIF( s_aReport[ PAGEIMAGES ][ nI ][ 4 ] == 0, pdfM2X( s_aReport[ IMAGES ][ nImage ][ 3 ][ IMAGE_HEIGHT ] / s_aReport[ IMAGES ][ nImage ][ 3 ][ IMAGE_YRES ] * 25.4 ), s_aReport[ PAGEIMAGES ][ nI ][ 4 ]))) + ;
         " " + ltrim(str( s_aReport[ PAGEIMAGES ][ nI ][ 3 ] )) + ;
         " " + ltrim(str( s_aReport[ PAGEY ] - s_aReport[ PAGEIMAGES ][ nI ][ 2 ] - ;
         IIF( s_aReport[ PAGEIMAGES ][ nI ][ 4 ] == 0, pdfM2X( s_aReport[ IMAGES ][ nImage ][ 3 ][ IMAGE_HEIGHT ] / s_aReport[ IMAGES ][ nImage ][ 3 ][ IMAGE_YRES ] * 25.4 ), s_aReport[ PAGEIMAGES ][ nI ][ 4 ]))) + " cm"
         cTemp += CRLF + "/Image" + ltrim(str( nImage )) + " Do"
         cTemp += CRLF + "Q"
      next
      s_aReport[ PAGEBUFFER ] := cTemp + s_aReport[ PAGEBUFFER ]
   ENDIF

   cTemp := s_aReport[ PAGEBUFFER ]

   cTemp += CRLF + "endstream" + CRLF + ;
   "endobj" + CRLF

   s_aReport[ DOCLEN ] += len( cTemp )
   fwrite( s_aReport[ HANDLE ], cTemp )

   aadd( s_aReport[ REFS ], s_aReport[ DOCLEN ] )

   cTemp := ltrim(str( ++s_aReport[ REPORTOBJ ] )) + " 0 obj" + CRLF + ;
   ltrim(str(len( s_aReport[ PAGEBUFFER ] ))) + CRLF + ;
   "endobj" + CRLF

   s_aReport[ DOCLEN ] += len( cTemp )
   fwrite( s_aReport[ HANDLE ], cTemp )

   for nI := 1 to len( s_aReport[ FONTS ] )
      IF s_aReport[ FONTS ][ nI ][ 2 ] > s_aReport[ REPORTOBJ ]

         aadd( s_aReport[ REFS ], s_aReport[ DOCLEN ] )

         cTemp := ;
         ltrim(str( s_aReport[ FONTS ][ nI ][ 2 ] )) + " 0 obj" + CRLF + ;
         "<<" + CRLF + ;
         "/Type /Font" + CRLF + ;
         "/Subtype /Type1" + CRLF + ;
         "/Name /Fo" + ltrim(str( nI )) + CRLF + ;
         "/BaseFont /" + s_aReport[ TYPE1 ][ s_aReport[ FONTS ][ nI ][ 1 ] ] + CRLF + ;
         "/Encoding /WinAnsiEncoding" + CRLF + ;
         ">>" + CRLF + ;
         "endobj" + CRLF

         s_aReport[ DOCLEN ] += len( cTemp )
         fwrite( s_aReport[ HANDLE ], cTemp )

      ENDIF
   next

   for nI := 1 to len( s_aReport[ IMAGES ] )
      IF s_aReport[ IMAGES ][ nI ][ 2 ] > s_aReport[ REPORTOBJ ]

         aadd( s_aReport[ REFS ], s_aReport[ DOCLEN ] )

         // "/Filter /CCITTFaxDecode" for B&W only ?
         cTemp :=  ;
         ltrim(str( s_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( s_aReport[ IMAGES ][ nI ][ 1 ]) ) > 0, " /DCTDecode", "" ) + " ]" + CRLF + ;
         "/Width " + ltrim(str( s_aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_WIDTH ] )) + CRLF + ;
         "/Height " + ltrim(str( s_aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_HEIGHT ] )) + CRLF + ;
         "/BitsPerComponent " + ltrim(str( s_aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_BITS ] )) + CRLF + ;
         "/ColorSpace /" + IIF( s_aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_SPACE ] == 1, "DeviceGray", "DeviceRGB") + CRLF + ;
         "/Length " + ltrim(str( s_aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_LENGTH ])) + CRLF + ;
         ">>" + CRLF + ;
         "stream" + CRLF

         s_aReport[ DOCLEN ] += len( cTemp )
         fwrite( s_aReport[ HANDLE ], cTemp )

         nImageHandle := fopen( s_aReport[ IMAGES ][ nI ][ 1 ] )
         fseek( nImageHandle, s_aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_FROM ] )

         nBuffer := 8192
         cBuffer := space( nBuffer )
         k := 0
         while k < s_aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_LENGTH ]
            IF k + nBuffer <= s_aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_LENGTH ]
               nRead := nBuffer
            ELSE
               nRead := s_aReport[ IMAGES ][ nI ][ 3 ][ IMAGE_LENGTH ] - k
            ENDIF
            fread( nImageHandle, @cBuffer, nRead )

            s_aReport[ DOCLEN ] += nRead
            fwrite( s_aReport[ HANDLE ], cBuffer, nRead )
            k += nRead
         enddo

         fclose( nImageHandle )

         cTemp := CRLF + "endstream" + CRLF + ;
         "endobj" + CRLF

         s_aReport[ DOCLEN ] += len( cTemp )
         fwrite( s_aReport[ HANDLE ], cTemp )

      ENDIF
   next

   s_aReport[ REPORTOBJ ] := s_aReport[ NEXTOBJ ]

   s_aReport[ NEXTOBJ ] := s_aReport[ REPORTOBJ ] + 4

   s_aReport[ PAGEBUFFER ] := ""

return nil
hbvpdf.prg525
STATIC FUNCTIONpdfGetFontInfo( cParam )
static function pdfGetFontInfo( cParam )                                      /*
========================================                                      */
local cRet
   IF cParam == "NAME"
      IF left( s_aReport[ TYPE1 ][ s_aReport[ FONTNAME ] ], 5 ) == "Times"
         cRet := "Times"
      ELSEIF left( s_aReport[ TYPE1 ][ s_aReport[ FONTNAME ] ], 9 ) == "Helvetica"
         cRet := "Helvetica"
      ELSE
         cRet := "Courier" // 0.04
      ENDIF
   ELSE // size
      cRet := int(( s_aReport[ FONTNAME ] - 1 ) % 4)
   ENDIF
return cRet
hbvpdf.prg712
FUNCTIONpdfImage( cFile, nRow, nCol, cUnits, nHeight, nWidth, cId )
function pdfImage( cFile, nRow, nCol, cUnits, nHeight, nWidth, cId )          /*
====================================================================          */

DEFAULT nRow to s_aReport[ REPORTLINE ]
DEFAULT nCol to 0
DEFAULT nHeight to 0
DEFAULT nWidth to 0
DEFAULT cUnits to "R"
DEFAULT cId to ""

   IF s_aReport[ HEADEREDIT ]
      return pdfHeader( "PDFIMAGE", cId, { cFile, nRow, nCol, cUnits, nHeight, nWidth } )
   ENDIF

   IF cUnits == "M"
      nRow := s_aReport[ PAGEY ] - pdfM2Y( nRow )
      nCol := pdfM2X( nCol )
      nHeight := s_aReport[ PAGEY ] - pdfM2Y( nHeight )
      nWidth := pdfM2X( nWidth )
   ELSEIF cUnits == "R"
      nRow := s_aReport[ PAGEY ] - pdfR2D( nRow )
      nCol := pdfM2X( s_aReport[ PDFLEFT ] ) + ;
              nCol * 100.00 / s_aReport[ REPORTWIDTH ] * ;
              ( s_aReport[ PAGEX ] - pdfM2X( s_aReport[ PDFLEFT ] ) * 2 - 9.0 ) / 100.00
      nHeight := s_aReport[ PAGEY ] - pdfR2D( nHeight )
      nWidth := pdfM2X( s_aReport[ PDFLEFT ] ) + ;
              nWidth * 100.00 / s_aReport[ REPORTWIDTH ] * ;
              ( s_aReport[ PAGEX ] - pdfM2X( s_aReport[ PDFLEFT ] ) * 2 - 9.0 ) / 100.00
   ELSEIF cUnits == "D"
   ENDIF

   aadd( s_aReport[ PAGEIMAGES ], { cFile, nRow, nCol, nHeight, nWidth } )

return nil
hbvpdf.prg729
FUNCTIONpdfItalic()
function pdfItalic()                                                          /*
====================                                                          */
   IF pdfGetFontInfo("NAME") = "Times"
      s_aReport[ FONTNAME ] := 3
   ELSEIF pdfGetFontInfo("NAME") = "Helvetica"
      s_aReport[ FONTNAME ] := 7
   ELSE
      s_aReport[ FONTNAME ] := 11 // 0.04
   ENDIF
   aadd( s_aReport[ PAGEFONTS ], s_aReport[ FONTNAME ] )
   IF ascan( s_aReport[ FONTS ], { |arr| arr[1] == s_aReport[ FONTNAME ] } ) == 0
      aadd( s_aReport[ FONTS ], { s_aReport[ FONTNAME ], ++s_aReport[ NEXTOBJ ] } )
   ENDIF
return nil
hbvpdf.prg765
FUNCTIONpdfLen( cString )
function pdfLen( cString )                                                    /*
==========================                                                    */
local nWidth := 0.00, nI, nLen, nArr, nAdd := ( s_aReport[ FONTNAME ] - 1 ) % 4

   nLen := len( cString )
   IF right( cString, 1 ) == chr(255) .or. right( cString, 1 ) == chr(254 )// reverse or underline
      --nLen
   ENDIF
   IF pdfGetFontInfo("NAME") = "Times"
      nArr := 1
   ELSEIF pdfGetFontInfo("NAME") = "Helvetica"
      nArr := 2
   ELSE
      nArr := 3 // 0.04
   ENDIF
  
   if !empty( s_aReport[ FONTWIDTH ] )
      For nI:= 1 To nLen
         nWidth += s_aReport[ FONTWIDTH ][ nArr ][ ( asc( substr( cString, nI, 1 )) - 32 ) * 4 + 1 + nAdd ] * 25.4 * s_aReport[ FONTSIZE ] / 720.00 / 100.00
      Next
   endif

return nWidth
hbvpdf.prg781
STATIC FUNCTIONpdfM2R( mm )
static function pdfM2R( mm )                                                  /*
============================                                                  */
return int( s_aReport[ LPI ] * mm / 25.4 )
hbvpdf.prg806
STATIC FUNCTIONpdfM2X( n )
static function pdfM2X( n )                                                   /*
===========================                                                   */
return n * 72 / 25.4
hbvpdf.prg811
STATIC FUNCTIONpdfM2Y( n )
static function pdfM2Y( n )                                                   /*
===========================                                                   */
return s_aReport[ PAGEY ] -  n * 72 / 25.4
hbvpdf.prg816
FUNCTIONpdfNewLine( n )
function pdfNewLine( n )                                                      /*
========================                                                      */
DEFAULT n to 1
   IF s_aReport[ REPORTLINE ] + n + s_aReport[ PDFTOP ] > s_aReport[ PDFBOTTOM ]
      pdfNewPage()
      s_aReport[ REPORTLINE ] += 1
   ELSE
      s_aReport[ REPORTLINE ] += n
   ENDIF
return s_aReport[ REPORTLINE ]
hbvpdf.prg821
FUNCTIONpdfNewPage( _cPageSize, _cPageOrient, _nLpi, _cFontName, _nFontType, _nFontSize )
function pdfNewPage( _cPageSize, _cPageOrient, _nLpi, _cFontName, _nFontType, _nFontSize )/*
==========================================================================================*/
local nAdd := 76.2
DEFAULT _cPageSize to s_aReport[ PAGESIZE ]
DEFAULT _cPageOrient to s_aReport[ PAGEORIENT ]
DEFAULT _nLpi to s_aReport[ LPI ]
DEFAULT _cFontName to pdfGetFontInfo("NAME")
DEFAULT _nFontType to pdfGetFontInfo("TYPE")
DEFAULT _nFontSize to s_aReport[ FONTSIZE ]

   IF !empty(s_aReport[ PAGEBUFFER ]) 
      pdfClosePage()
   ENDIF

   s_aReport[ PAGEFONTS ] := {}
   s_aReport[ PAGEIMAGES ] := {}

   ++s_aReport[ REPORTPAGE ] // NEW !!!

   pdfPageSize( _cPageSize )
   pdfPageOrient( _cPageOrient )
   pdfSetLPI( _nLpi )

   pdfSetFont( _cFontName, _nFontType, _nFontSize )

   pdfDrawHeader()

   s_aReport[ REPORTLINE ] := 0//5
   s_aReport[ FONTNAMEPREV ] := 0
   s_aReport[ FONTSIZEPREV ] := 0
return nil
hbvpdf.prg833
FUNCTIONpdfNormal()
function pdfNormal()                                                          /*
====================                                                          */
   IF pdfGetFontInfo("NAME") = "Times"
      s_aReport[ FONTNAME ] := 1
   ELSEIF pdfGetFontInfo("NAME") = "Helvetica"
      s_aReport[ FONTNAME ] := 5
   ELSE
      s_aReport[ FONTNAME ] := 9 // 0.04
   ENDIF
   aadd( s_aReport[ PAGEFONTS ], s_aReport[ FONTNAME ] )
   IF ascan( s_aReport[ FONTS ], { |arr| arr[1] == s_aReport[ FONTNAME ] } ) == 0
      aadd( s_aReport[ FONTS ], { s_aReport[ FONTNAME ], ++s_aReport[ NEXTOBJ ] } )
   ENDIF
return nil
hbvpdf.prg866
FUNCTIONpdfOpen( cFile, nLen, lOptimize )
function pdfOpen( cFile, nLen, lOptimize )                                    /*
==========================================                                    */
local cTemp, nI, nJ, n1, n2 := 896, n12
DEFAULT nLen to 200
DEFAULT lOptimize to .f.

   s_aReport[ FONTNAME     ] := 1
   s_aReport[ FONTSIZE     ] := 10
   s_aReport[ LPI          ] := 6
   s_aReport[ PAGESIZE     ] := "LETTER"
   s_aReport[ PAGEORIENT   ] := "P"
   s_aReport[ PAGEX        ] := 8.5 * 72
   s_aReport[ PAGEY        ] := 11.0 * 72
   s_aReport[ REPORTWIDTH  ] := nLen // 200 // should be as parameter
   s_aReport[ REPORTPAGE   ] := 0
   s_aReport[ REPORTLINE   ] := 0//5
   s_aReport[ FONTNAMEPREV ] := 0
   s_aReport[ FONTSIZEPREV ] := 0
   s_aReport[ PAGEBUFFER   ] := ""
   s_aReport[ REPORTOBJ    ] := 1//2
   s_aReport[ DOCLEN       ] := 0
   s_aReport[ TYPE1        ] := { "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic", "Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique", "Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique"  } // 0.04
   s_aReport[ MARGINS      ] := .t.
   s_aReport[ HEADEREDIT   ] := .f.
   s_aReport[ NEXTOBJ      ] := 0
   s_aReport[ PDFTOP       ] := 1 // top
   s_aReport[ PDFLEFT      ] := 10 // left & right
   s_aReport[ PDFBOTTOM    ] := s_aReport[ PAGEY ] / 72 * s_aReport[ LPI ] - 1 // bottom, default "LETTER", "P", 6
   s_aReport[ HANDLE       ] := fcreate( cFile )
   s_aReport[ PAGES        ] := {}
   s_aReport[ REFS         ] := { 0, 0 }
   s_aReport[ BOOKMARK     ] := {}
   s_aReport[ HEADER       ] := {}
   s_aReport[ FONTS        ] := {}
   s_aReport[ IMAGES       ] := {}
   s_aReport[ PAGEIMAGES   ] := {}
   s_aReport[ PAGEFONTS    ] := {}

   // TOFIX: This external file dependency should be removed.

   cTemp := vpdf_FontsDat() // times, times-bold, times-italic, times-bolditalic, helvetica..., courier... // 0.04
   n1 := len( cTemp ) / ( 2 * n2 )
   s_aReport[ FONTWIDTH ] := array( n1, n2 )

   s_aReport[ OPTIMIZE     ] := lOptimize

   s_aReport[ NEXTOBJ ] := s_aReport[ REPORTOBJ ] + 4

   n12 := 2 * n2 // 0.04
   for nI := 1 to n1
      for nJ := 1 to n2
         s_aReport[ FONTWIDTH ][ nI ][ nJ ] := bin2i(substr( cTemp, ( nI - 1 ) * n12 + ( nJ - 1 ) * 2 + 1, 2 ))
      next
   next

   s_aReport[ DOCLEN ] := 0
   cTemp := "%PDF-1.3" + CRLF
   s_aReport[ DOCLEN ] += len( cTemp )
   fwrite( s_aReport[ HANDLE ], cTemp )

return nil
hbvpdf.prg882
FUNCTIONpdfPageSize( _cPageSize, _nWidth, _nHeight )
function pdfPageSize( _cPageSize, _nWidth, _nHeight )                         /*
==================================                                            */
local nSize, aSize, nWidth, nHeight 

   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 }, ;
              { "USSTDFOLD", 14.87, 11.00 } }
             
   DEFAULT _cPageSize to "LETTER"

   if empty( _nWidth ) .or. empty( _nHeight )

      nSize := ascan( aSize, { |arr| arr[ 1 ] == _cPageSize } )

      IF nSize = 0
         nSize := 1
      ENDIF

      s_aReport[ PAGESIZE ] := aSize[ nSize ][ 1 ]

      nWidth := aSize[ nSize ][ 2 ] 
      nHeight := aSize[ nSize ][ 3 ]

   else

      _nWidth := val( str( _nWidth ) )
      _nHeight := val( str( _nHeight ) )

      nSize := ascan( aSize, { |arr| ( arr[ 2 ] == _nWidth  ) .and. ( arr[ 3 ] == _nHeight ) } )

      if nSize == 0
         nSize := ascan( aSize, { |arr| ( arr[ 3 ] == _nWidth ) .and. ( arr[ 2 ] == _nHeight ) } )
      endif   

      IF nSize = 0
         nSize := 1
      ENDIF

      s_aReport[ PAGESIZE ] := aSize[ nSize ][ 1 ]

      nWidth = _nWidth
      nHeight = _nHeight
   
   endif   

   IF s_aReport[ PAGEORIENT ] = "P"
      s_aReport[ PAGEX ] := nWidth * 72
      s_aReport[ PAGEY ] := nHeight * 72
   ELSE
      s_aReport[ PAGEX ] := nHeight * 72
      s_aReport[ PAGEY ] := nWidth * 72
   ENDIF
   
   return nil
hbvpdf.prg945
FUNCTIONpdfPageOrient( _cPageOrient )
function pdfPageOrient( _cPageOrient )                                        /*
======================================                                        */
DEFAULT _cPageOrient to "P"

   s_aReport[ PAGEORIENT ] := _cPageOrient
   pdfPageSize( s_aReport[ PAGESIZE ] )
return nil
hbvpdf.prg1014
STATIC FUNCTIONpdfR2D( nRow )
static function pdfR2D( nRow )                                                /*
==============================                                                */
return s_aReport[ PAGEY ] - nRow * 72 / s_aReport[ LPI ]
hbvpdf.prg1023
STATIC FUNCTIONpdfR2M( nRow )
static function pdfR2M( nRow )                                                /*
==============================                                                */
return 25.4 * nRow / s_aReport[ LPI ]
hbvpdf.prg1029
FUNCTIONpdfPageNumber( n )
function pdfPageNumber( n )                                                   /*
===========================                                                   */
DEFAULT n to 0
   IF n > 0
      s_aReport[ REPORTPAGE ] := n // NEW !!!
   ENDIF
return s_aReport[ REPORTPAGE ]
hbvpdf.prg1034
FUNCTIONpdfReverse( cString )
function pdfReverse( cString )                                                /*
==============================                                                */
return cString + chr(255)
hbvpdf.prg1043
FUNCTIONpdfRJust( cString, nRow, nCol, cUnits, lExact, cId )
function pdfRJust( cString, nRow, nCol, cUnits, lExact, cId )                 /*
=============================================================                 */
local nLen, nAdj := 1.0, nAt
DEFAULT nRow to s_aReport[ REPORTLINE ]
DEFAULT cUnits to "R"
DEFAULT lExact to .f.

   IF s_aReport[ HEADEREDIT ]
      return pdfHeader( "PDFRJUST", cId, { cString, nRow, nCol, cUnits, lExact } )
   ENDIF

   IF ( nAt := at( "#pagenumber#", cString ) ) > 0
      cString := left( cString, nAt - 1 ) + ltrim(str( pdfPageNumber())) + substr( cString, nAt + 12 )
   ENDIF

   nLen := pdfLen( cString )

   IF cUnits == "R"
      IF !lExact
         pdfCheckLine( nRow )
         nRow := nRow + s_aReport[ PDFTOP ]
      ENDIF
   ENDIF
   pdfAtSay( cString, pdfR2M( nRow ), IIF( cUnits == "R", s_aReport[ PDFLEFT ] + ( s_aReport[ PAGEX ] / 72 * 25.4 - 2 * s_aReport[ PDFLEFT ] ) * nCol / s_aReport[ REPORTWIDTH ] - nAdj, nCol ) - nLen, "M", lExact )
return nil
hbvpdf.prg1048
FUNCTIONpdfSetFont( _cFont, _nType, _nSize, cId )
function pdfSetFont( _cFont, _nType, _nSize, cId )                            /*
==================================================                            */

DEFAULT _cFont to "Times"
DEFAULT _nType to 0
DEFAULT _nSize to 10

   IF s_aReport[ HEADEREDIT ]
      return pdfHeader( "PDFSETFONT", cId, { _cFont, _nType, _nSize } )
   ENDIF

   _cFont := upper( _cFont )
   s_aReport[ FONTSIZE ] := _nSize

   IF _cFont == "TIMES"
      s_aReport[ FONTNAME ] := _nType + 1
   ELSEIF _cFont == "HELVETICA"
      s_aReport[ FONTNAME ] := _nType + 5
   ELSE
      s_aReport[ FONTNAME ] := _nType + 9 // 0.04
   ENDIF

   aadd( s_aReport[ PAGEFONTS ], s_aReport[ FONTNAME ] )

   IF ascan( s_aReport[ FONTS ], { |arr| arr[1] == s_aReport[ FONTNAME ] } ) == 0
      aadd( s_aReport[ FONTS ], { s_aReport[ FONTNAME ], ++s_aReport[ NEXTOBJ ] } )
   ENDIF
return nil
hbvpdf.prg1075
FUNCTIONpdfSetLPI(_nLpi)
function pdfSetLPI(_nLpi)                                                     /*
=========================                                                     */
local cLpi := alltrim(str(_nLpi))
DEFAULT _nLpi to 6

   cLpi := iif(cLpi$"1;2;3;4;6;8;12;16;24;48",cLpi,"6")
   s_aReport[ LPI ] := val( cLpi )

   pdfPageSize( s_aReport[ PAGESIZE ] )
return nil
hbvpdf.prg1105
FUNCTIONpdfStringB( cString )
function pdfStringB( cString )                                                /*
==============================                                                */
   cString := strtran( cString, "(", "\(" )
   cString := strtran( cString, ")", "\)" )
return cString
hbvpdf.prg1117
FUNCTIONpdfTextCount( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits )
function pdfTextCount( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits )/*
==============================================================================*/
return pdfText( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits, .f. )
hbvpdf.prg1124
FUNCTIONpdfText( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits, cColor, lPrint )
function pdfText( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits, cColor, lPrint )/*
=================================================================================*/
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 // justify
DEFAULT lPrint to .t.
DEFAULT cColor to ""

   IF cUnits == "M"
      nTop := pdfM2R( nTop )
   ELSEIF cUnits == "R"
      nLeft := pdfX2M( pdfM2X( s_aReport[ PDFLEFT ] ) + ;
              nLeft * 100.00 / s_aReport[ REPORTWIDTH ] * ;
              ( s_aReport[ PAGEX ] - pdfM2X( s_aReport[ PDFLEFT ] ) * 2 - 9.0 ) / 100.00 )
   ENDIF

   s_aReport[ REPORTLINE ] := nTop - 1

   nSpace := pdfLen( " " )
   nLines := 0
   nCRLF := 0

   nNew := nTab

   cString := alltrim( cString )
   nTokens := numtoken( cString, cDelim )
   nTokenLen := 0.00
   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 // first always paragraph
   nLineLen := nSpace * nNew - nSpace

   lParagraph := .t.
   nI := 1

   while nI <= nTokens
      cToken := token( cString, cDelim, nI )
      nTokenLen := pdfLen( 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 - pdfLen( cTemp ) ) / 2
               ELSEIF nJustify == 3
                  nL := nLeft + nLength - pdfLen( cTemp )
               ENDIF
               while k <= nLen .and. ( ( nLineLen += pdfLen( substr( cToken, k, 1 ))) <= nLength )
                  nLineLen += pdfLen( 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 := pdfNewLine( 1 )
                  // version 0.02
                  pdfAtSay( cColor + cTemp, pdfR2M( nRow + s_aReport[ PDFTOP ] ), nL, "M" )
               ENDIF
            enddo
            ++nI
            nStart := nI
         ELSE
            pdfTextPrint( nI - 1, nLeft, @lParagraph, nJustify, nSpace, nNew, nLength, @nLineLen, @nLines, @nStart, cString, cDelim, cColor, lPrint )
         ENDIF
      ELSEIF ( nI == nTokens ) .or. ( nI < nTokens .and. ( nCRLF := pdfTextNextPara( cString, cDelim, nI ) ) > 0 )
         IF nI == nTokens
            nLineLen += nSpace + nTokenLen
         ENDIF
         pdfTextPrint( 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 := pdfNewLine( nCRLF - 1 )
         ENDIF

      ELSE
         nLineLen += nSpace + nTokenLen
         ++nI
      ENDIF
   enddo

return nLines
hbvpdf.prg1129
STATIC FUNCTIONpdfTextPrint( nI, nLeft, lParagraph, nJustify, nSpace, nNew, nLength, nLineLen, nLines, nStart, cString, cDelim, cColor, lPrint )
static function pdfTextPrint( nI, nLeft, lParagraph, nJustify, nSpace, nNew, nLength, nLineLen, nLines, nStart, cString, cDelim, cColor, lPrint )/*
=========================================================================================================================================*/
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 := pdfNewLine( 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
         pdfAtSay( cColor + cToken, pdfR2M( nRow + s_aReport[ PDFTOP ] ), nL, "M" )
      ENDIF
      nL += pdfLen ( cToken ) + nB
   next

   nStart := nFinish + 1

   lParagraph := .f.

   nLineLen := 0.00
   nLineLen += nSpace * nNew

return nil
hbvpdf.prg1244
STATIC FUNCTIONpdfTextNextPara( cString, cDelim, nI )
static function pdfTextNextPara( cString, cDelim, nI )                        /*
======================================================                        */
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
hbvpdf.prg1290
FUNCTIONpdfUnderLine( cString )
function pdfUnderLine( cString )                                              /*
================================                                              */
return cString + chr(254)
hbvpdf.prg1305
STATIC FUNCTIONpdfX2M( n )
static function pdfX2M( n )                                                   /*
===========================                                                   */
return n * 25.4 / 72
hbvpdf.prg1310
STATIC FUNCTIONTimeAsAMPM( cTime )
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
hbvpdf.prg1315
FUNCTIONpdfOpenHeader( cFile )
function pdfOpenHeader( cFile )
local nErrorCode := 0, nAt
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 )
         copy file (cFile) to temp.tmp
         cFile := "temp.tmp"
      ENDIF
      //s_aReport[ HEADER ] := FT_RestArr( cFile, @nErrorCode )
      s_aReport[ HEADER ] := File2Array( cFile )
   ELSE
      s_aReport[ HEADER ] := {}
   ENDIF
   s_aReport[ MARGINS ] := .t.
return nil
hbvpdf.prg1327
FUNCTIONpdfEditOnHeader()
function pdfEditOnHeader()
   s_aReport[ HEADEREDIT ] := .t.
   s_aReport[ MARGINS ] := .t.
return nil
hbvpdf.prg1347
FUNCTIONpdfEditOffHeader()
function pdfEditOffHeader()
   s_aReport[ HEADEREDIT ] := .f.
   s_aReport[ MARGINS ] := .t.
return nil
hbvpdf.prg1352
FUNCTIONpdfCloseHeader()
function pdfCloseHeader()
   s_aReport[ HEADER ] := {}
   s_aReport[ MARGINS ] := .f.
return nil
hbvpdf.prg1357
FUNCTIONpdfDeleteHeader( cId )
function pdfDeleteHeader( cId )
local nRet := -1, nId
   cId := upper( cId )
   nId := ascan( s_aReport[ HEADER ], {| arr | arr[ 3 ] == cId })
   IF nId > 0
      nRet := len( s_aReport[ HEADER ] ) - 1
      aDel( s_aReport[ HEADER ], nId )
      aSize( s_aReport[ HEADER ], nRet )
      s_aReport[ MARGINS ] := .t.
   ENDIF
return nRet
hbvpdf.prg1362
FUNCTIONpdfEnableHeader( cId )
function pdfEnableHeader( cId )
local nId
   cId := upper( cId )
   nId := ascan( s_aReport[ HEADER ], {| arr | arr[ 3 ] == cId })
   IF nId > 0
      s_aReport[ HEADER ][ nId ][ 1 ] := .t.
      s_aReport[ MARGINS ] := .t.
   ENDIF
return nil
hbvpdf.prg1374
FUNCTIONpdfDisableHeader( cId )
function pdfDisableHeader( cId )
local nId
   cId := upper( cId )
   nId := ascan( s_aReport[ HEADER ], {| arr | arr[ 3 ] == cId })
   IF nId > 0
      s_aReport[ HEADER ][ nId ][ 1 ] := .f.
      s_aReport[ MARGINS ] := .t.
   ENDIF
return nil
hbvpdf.prg1384
FUNCTIONpdfSaveHeader( cFile )
function pdfSaveHeader( cFile )
local nErrorCode := 0
   Array2File( 'temp.tmp', s_aReport[ HEADER ] )
   copy file temp.tmp to (cFile)
return nil
hbvpdf.prg1394
FUNCTIONpdfHeader( cFunction, cId, arr )
function pdfHeader( cFunction, cId, arr )
local nId, nI, nLen, nIdLen
   nId := 0
   IF !empty( cId )
      cId := upper( cId )
      nId := ascan( s_aReport[ HEADER ], {| arr | arr[ 3 ] == cId })
   ENDIF
   IF nId == 0
      nLen := len( s_aReport[ HEADER ] )
      IF empty( cId )
         cId := cFunction
         nIdLen := len( cId )
         for nI := 1 to nLen
            IF s_aReport[ HEADER ][ nI ][ 2 ] == cId
               IF val( substr( s_aReport[ HEADER ][ nI ][ 3 ], nIdLen + 1 ) ) > nId
                  nId := val( substr( s_aReport[ HEADER ][ nI ][ 3 ], nIdLen + 1 ) )
               ENDIF
            ENDIF
         next
         ++nId
         cId += ltrim(str(nId))
      ENDIF
      aadd( s_aReport[ HEADER ], { .t., cFunction, cId } )
      ++nLen
      for nI := 1 to len( arr )
         aadd( s_aReport[ HEADER ][ nLen ], arr[ nI ] )
      next
   ELSE
      aSize( s_aReport[ HEADER ][ nId ], 3 )
      for nI := 1 to len( arr )
         aadd( s_aReport[ HEADER ][ nId ], arr[ nI ] )
      next
   ENDIF
return cId
hbvpdf.prg1400
FUNCTIONpdfDrawHeader()
function pdfDrawHeader()
local nI, _nFont, _nSize, nLen := len( s_aReport[ HEADER ] )

   IF nLen > 0

      // save font
      _nFont := s_aReport[ FONTNAME ]
      _nSize := s_aReport[ FONTSIZE ]

      for nI := 1 to nLen
         IF s_aReport[ HEADER ][ nI ][ 1 ] // enabled
            do case
            case s_aReport[ HEADER ][ nI ][ 2 ] == "PDFATSAY"
               pdfAtSay( s_aReport[ HEADER ][ nI ][ 4 ], s_aReport[ HEADER ][ nI ][ 5 ], s_aReport[ HEADER ][ nI ][ 6 ], s_aReport[ HEADER ][ nI ][ 7 ], s_aReport[ HEADER ][ nI ][ 8 ], s_aReport[ HEADER ][ nI ][ 3 ] )

            case s_aReport[ HEADER ][ nI ][ 2 ] == "PDFCENTER"
               pdfCenter( s_aReport[ HEADER ][ nI ][ 4 ], s_aReport[ HEADER ][ nI ][ 5 ], s_aReport[ HEADER ][ nI ][ 6 ], s_aReport[ HEADER ][ nI ][ 7 ], s_aReport[ HEADER ][ nI ][ 8 ], s_aReport[ HEADER ][ nI ][ 3 ] )

            case s_aReport[ HEADER ][ nI ][ 2 ] == "PDFRJUST"
               pdfRJust( s_aReport[ HEADER ][ nI ][ 4 ], s_aReport[ HEADER ][ nI ][ 5 ], s_aReport[ HEADER ][ nI ][ 6 ], s_aReport[ HEADER ][ nI ][ 7 ], s_aReport[ HEADER ][ nI ][ 8 ], s_aReport[ HEADER ][ nI ][ 3 ] )

            case s_aReport[ HEADER ][ nI ][ 2 ] == "PDFBOX"
               pdfBox( s_aReport[ HEADER ][ nI ][ 4 ], s_aReport[ HEADER ][ nI ][ 5 ], s_aReport[ HEADER ][ nI ][ 6 ], s_aReport[ HEADER ][ nI ][ 7 ], s_aReport[ HEADER ][ nI ][ 8 ], s_aReport[ HEADER ][ nI ][ 9 ], s_aReport[ HEADER ][ nI ][ 10 ], s_aReport[ HEADER ][ nI ][ 3 ] )

            case s_aReport[ HEADER ][ nI ][ 2 ] == "PDFSETFONT"
               pdfSetFont( s_aReport[ HEADER ][ nI ][ 4 ], s_aReport[ HEADER ][ nI ][ 5 ], s_aReport[ HEADER ][ nI ][ 6 ], s_aReport[ HEADER ][ nI ][ 3 ] )

            case s_aReport[ HEADER ][ nI ][ 2 ] == "PDFIMAGE"
               pdfImage( s_aReport[ HEADER ][ nI ][ 4 ], s_aReport[ HEADER ][ nI ][ 5 ], s_aReport[ HEADER ][ nI ][ 6 ], s_aReport[ HEADER ][ nI ][ 7 ], s_aReport[ HEADER ][ nI ][ 8 ], s_aReport[ HEADER ][ nI ][ 9 ], s_aReport[ HEADER ][ nI ][ 3 ] )

            endcase
         ENDIF
      next
      s_aReport[ FONTNAME ] := _nFont
      s_aReport[ FONTSIZE ] := _nSize

      IF s_aReport[ MARGINS ]
         pdfMargins()
      ENDIF

   ELSE
      IF s_aReport[ MARGINS ]
         s_aReport[ PDFTOP ] := 1 // top
         s_aReport[ PDFLEFT ] := 10 // left & right
         s_aReport[ PDFBOTTOM ] := s_aReport[ PAGEY ] / 72 * s_aReport[ LPI ] - 1 // bottom, default "LETTER", "P", 6

         s_aReport[ MARGINS ] := .f.
      ENDIF
   ENDIF
return nil
hbvpdf.prg1435
FUNCTIONpdfMargins( nTop, nLeft, nBottom )
function pdfMargins( nTop, nLeft, nBottom )
local nI, nLen := len( s_aReport[ HEADER ] ), nTemp, aTemp, nHeight

// version 0.07 begin

   DEFAULT nTop to 1 // top
   DEFAULT nLeft to 10 // left & right
   DEFAULT nBottom to s_aReport[ PAGEY ] / 72 * s_aReport[ LPI ] - 1 // bottom, default "LETTER", "P", 6

   s_aReport[ PDFTOP ] := nTop
   s_aReport[ PDFLEFT ] := nLeft
   s_aReport[ PDFBOTTOM ] := nBottom

// version 0.07 end

   for nI := 1 to nLen
      IF s_aReport[ HEADER ][ nI ][ 1 ] // enabled

         IF s_aReport[ HEADER ][ nI ][ 2 ] == "PDFSETFONT"

         ELSEIF s_aReport[ HEADER ][ nI ][ 2 ] == "PDFIMAGE"
            IF s_aReport[ HEADER ][ nI ][ 8 ] == 0 // picture in header, first at all, not at any page yet
               aTemp := pdfImageInfo( s_aReport[ HEADER ][ nI ][ 4 ] )
               nHeight := aTemp[ IMAGE_HEIGHT ] / aTemp[ IMAGE_YRES ] * 25.4
               IF s_aReport[ HEADER ][ nI ][ 7 ] == "D"
                  nHeight := pdfM2X( nHeight )
               ENDIF
            ELSE
               nHeight := s_aReport[ HEADER ][ nI ][ 8 ]
            ENDIF

            IF s_aReport[ HEADER ][ nI ][ 7 ] == "M"

               nTemp := s_aReport[ PAGEY ] / 72 * 25.4 / 2

               IF s_aReport[ HEADER ][ nI ][ 5 ] < nTemp
                  nTemp := ( s_aReport[ HEADER ][ nI ][ 5 ] + nHeight ) * s_aReport[ LPI ] / 25.4 // top
                  IF nTemp > s_aReport[ PDFTOP ]
                     s_aReport[ PDFTOP ] := nTemp
                  ENDIF
               ELSE
                  nTemp := s_aReport[ HEADER ][ nI ][ 5 ] * s_aReport[ LPI ] / 25.4 // top
                  IF nTemp < s_aReport[ PDFBOTTOM ]
                     s_aReport[ PDFBOTTOM ] := nTemp
                  ENDIF
               ENDIF

            ELSEIF s_aReport[ HEADER ][ nI ][ 7 ] == "D"
               nTemp := s_aReport[ PAGEY ] / 2

               IF s_aReport[ HEADER ][ nI ][ 5 ] < nTemp
                  nTemp := ( s_aReport[ HEADER ][ nI ][ 5 ] + nHeight ) * s_aReport[ LPI ] / 72 // top
                  IF nTemp > s_aReport[ PDFTOP ]
                     s_aReport[ PDFTOP ] := nTemp
                  ENDIF
               ELSE
                  nTemp := s_aReport[ HEADER ][ nI ][ 5 ] * s_aReport[ LPI ] / 72 // top
                  IF nTemp < s_aReport[ PDFBOTTOM ]
                     s_aReport[ PDFBOTTOM ] := nTemp
                  ENDIF

               ENDIF

            ENDIF

         ELSEIF s_aReport[ HEADER ][ nI ][ 2 ] == "PDFBOX"

            IF s_aReport[ HEADER ][ nI ][ 10 ] == "M"

               nTemp := s_aReport[ PAGEY ] / 72 * 25.4 / 2

               IF s_aReport[ HEADER ][ nI ][ 4 ] < nTemp .and. ;
                  s_aReport[ HEADER ][ nI ][ 6 ] < nTemp
                  nTemp := s_aReport[ HEADER ][ nI ][ 6 ] * s_aReport[ LPI ] / 25.4 // top
                  IF nTemp > s_aReport[ PDFTOP ]
                     s_aReport[ PDFTOP ] := nTemp
                  ENDIF
               ELSEIF s_aReport[ HEADER ][ nI ][ 4 ] < nTemp .and. ;
                      s_aReport[ HEADER ][ nI ][ 6 ] > nTemp

                  nTemp := ( s_aReport[ HEADER ][ nI ][ 4 ] + s_aReport[ HEADER ][ nI ][ 8 ] ) * s_aReport[ LPI ] / 25.4 // top
                  IF nTemp > s_aReport[ PDFTOP ]
                     s_aReport[ PDFTOP ] := nTemp
                  ENDIF

                  nTemp := ( s_aReport[ HEADER ][ nI ][ 6 ] - s_aReport[ HEADER ][ nI ][ 8 ] ) * s_aReport[ LPI ] / 25.4 // top
                  IF nTemp < s_aReport[ PDFBOTTOM ]
                     s_aReport[ PDFBOTTOM ] := nTemp
                  ENDIF

               ELSEIF s_aReport[ HEADER ][ nI ][ 4 ] > nTemp .and. ;
                      s_aReport[ HEADER ][ nI ][ 6 ] > nTemp
                  nTemp := s_aReport[ HEADER ][ nI ][ 4 ] * s_aReport[ LPI ] / 25.4 // top
                  IF nTemp < s_aReport[ PDFBOTTOM ]
                     s_aReport[ PDFBOTTOM ] := nTemp
                  ENDIF
               ENDIF

            ELSEIF s_aReport[ HEADER ][ nI ][ 10 ] == "D"
               nTemp := s_aReport[ PAGEY ] / 2

               IF s_aReport[ HEADER ][ nI ][ 4 ] < nTemp .and. ;
                  s_aReport[ HEADER ][ nI ][ 6 ] < nTemp
                  nTemp := s_aReport[ HEADER ][ nI ][ 6 ] / s_aReport[ LPI ] // top
                  IF nTemp > s_aReport[ PDFTOP ]
                     s_aReport[ PDFTOP ] := nTemp
                  ENDIF
               ELSEIF s_aReport[ HEADER ][ nI ][ 4 ] < nTemp .and. ;
                      s_aReport[ HEADER ][ nI ][ 6 ] > nTemp

                  nTemp := ( s_aReport[ HEADER ][ nI ][ 4 ] + s_aReport[ HEADER ][ nI ][ 8 ] ) / s_aReport[ LPI ] // top
                  IF nTemp > s_aReport[ PDFTOP ]
                     s_aReport[ PDFTOP ] := nTemp
                  ENDIF

                  nTemp := ( s_aReport[ HEADER ][ nI ][ 6 ] - s_aReport[ HEADER ][ nI ][ 8 ] ) / s_aReport[ LPI ] // top
                  IF nTemp < s_aReport[ PDFBOTTOM ]
                     s_aReport[ PDFBOTTOM ] := nTemp
                  ENDIF

               ELSEIF s_aReport[ HEADER ][ nI ][ 4 ] > nTemp .and. ;
                      s_aReport[ HEADER ][ nI ][ 6 ] > nTemp
                  nTemp := s_aReport[ HEADER ][ nI ][ 4 ] / s_aReport[ LPI ] // top
                  IF nTemp < s_aReport[ PDFBOTTOM ]
                     s_aReport[ PDFBOTTOM ] := nTemp
                  ENDIF
               ENDIF

            ENDIF

         ELSE
            IF s_aReport[ HEADER ][ nI ][ 7 ] == "R"
               nTemp := s_aReport[ HEADER ][ nI ][ 5 ] // top
               IF s_aReport[ HEADER ][ nI ][ 5 ] > s_aReport[ PAGEY ] / 72 * s_aReport[ LPI ] / 2
                  IF nTemp < s_aReport[ PDFBOTTOM ]
                     s_aReport[ PDFBOTTOM ] := nTemp
                  ENDIF
               ELSE
                  IF nTemp > s_aReport[ PDFTOP ]
                     s_aReport[ PDFTOP ] := nTemp
                  ENDIF
               ENDIF
            ELSEIF s_aReport[ HEADER ][ nI ][ 7 ] == "M"
               nTemp := s_aReport[ HEADER ][ nI ][ 5 ] * s_aReport[ LPI ] / 25.4 // top
               IF s_aReport[ HEADER ][ nI ][ 5 ] > s_aReport[ PAGEY ] / 72 * 25.4 / 2
                  IF nTemp < s_aReport[ PDFBOTTOM ]
                     s_aReport[ PDFBOTTOM ] := nTemp
                  ENDIF
               ELSE
                  IF nTemp > s_aReport[ PDFTOP ]
                     s_aReport[ PDFTOP ] := nTemp
                  ENDIF
               ENDIF
            ELSEIF s_aReport[ HEADER ][ nI ][ 7 ] == "D"
               nTemp := s_aReport[ HEADER ][ nI ][ 5 ] / s_aReport[ LPI ] // top
               IF s_aReport[ HEADER ][ nI ][ 5 ] > s_aReport[ PAGEY ] / 2
                  IF nTemp < s_aReport[ PDFBOTTOM ]
                     s_aReport[ PDFBOTTOM ] := nTemp
                  ENDIF
               ELSE
                  IF nTemp > s_aReport[ PDFTOP ]
                     s_aReport[ PDFTOP ] := nTemp
                  ENDIF
               ENDIF
            ENDIF
         ENDIF
      ENDIF
   next

   s_aReport[ MARGINS ] := .f.

return nil
hbvpdf.prg1486
FUNCTIONpdfCreateHeader( _file, _size, _orient, _lpi, _width )
function pdfCreateHeader( _file, _size, _orient, _lpi, _width )
local ;
   s_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 s_aReport[ PAGESIZE ]
DEFAULT _orient to s_aReport[ PAGEORIENT ]
DEFAULT _lpi to s_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

   pdfEditOnHeader()

   IF _size == "LEGAL"
      nAdd := 76.2
   ENDIF

   IF _orient == "P"
      pdfBox(   5.0, 5.0, 274.0 + nAdd, 210.0,  1.0 )
      pdfBox(   6.5, 6.5, 272.5 + nAdd, 208.5,  0.5 )

      pdfBox(  11.5, 9.5,  22.0       , 205.5,  0.5, 5 )
      pdfBox(  23.0, 9.5,  33.5       , 205.5,  0.5, 5 )
      pdfBox(  34.5, 9.5, 267.5 + nAdd, 205.5,  0.5 )

   ELSE
      pdfBox(  5.0, 5.0, 210.0, 274.0 + nAdd, 1.0 )
      pdfBox(  6.5, 6.5, 208.5, 272.5 + nAdd, 0.5 )

      pdfBox( 11.5, 9.5,  22.0, 269.5 + nAdd, 0.5, 5 )
      pdfBox( 23.0, 9.5,  33.5, 269.5 + nAdd, 0.5, 5 )
      pdfBox( 34.5, 9.5, 203.5, 269.5 + nAdd, 0.5 )
   ENDIF

   pdfSetFont("Helvetica", BOLD, 10) // 0.04
   pdfAtSay( "Test Line 1", s_aReportStyle[ nStyle ][ 1 ], 1, "R", .t. )

   pdfSetFont("Times", BOLD, 18)
   pdfCenter( "Test Line 2", s_aReportStyle[ nStyle ][ 2 ],,"R", .t. )

   pdfSetFont("Times", BOLD, 12)
   pdfCenter( "Test Line 3", s_aReportStyle[ nStyle ][ 3 ],,"R", .t. )

   pdfSetFont("Helvetica", BOLD, 10) // 0.04
   pdfAtSay( "Test Line 4", s_aReportStyle[ nStyle ][ 4 ], 1, "R", .t. )

   pdfSetFont("Helvetica", BOLD, 10) // 0.04
   pdfAtSay( "Test Line 5", s_aReportStyle[ nStyle ][ 5 ], 1, "R", .t. )

   pdfAtSay( dtoc( date()) + " " + TimeAsAMPM( time() ), s_aReportStyle[ nStyle ][ 6 ], 1, "R", .t. )
   pdfRJust( "Page: #pagenumber#", s_aReportStyle[ nStyle ][ 6 ], s_aReport[ REPORTWIDTH ], "R", .t. )

   pdfEditOffHeader()
   pdfSaveHeader( _file )

return nil
hbvpdf.prg1659
FUNCTIONpdfImageInfo( cFile )
function pdfImageInfo( cFile )
local cTemp := upper(substr( cFile, rat('.', cFile) + 1 )), aTemp := {}
   do case
   case cTemp == "TIF"
      aTemp := pdfTIFFInfo( cFile )
   case cTemp == "JPG"
      aTemp := pdfJPEGInfo( cFile )
   endcase
return aTemp
hbvpdf.prg1753
FUNCTIONpdfTIFFInfo( cFile )
function pdfTIFFInfo( cFile )
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, nPages, nn

local nWidth := 0, nHeight := 0, nBits := 0, nFrom := 0, nLength := 0, xRes := 0, yRes := 0, aTemp := {}, nSpace

   nHandle := fopen( cFile )

   c2 := '  '
   fread( nHandle, @c2, 2 )
   fread( nHandle, @c2, 2 )
   cIFDNext := '    '
   fread( nHandle, @cIFDNext, 4 )

   cTemp := space(12)
   nPages := 0

   while !( cIFDNext == c40 ) //read IFD's

      nIFD := bin2l( cIFDNext )

      fseek( nHandle, nIFD )
      //?'*** IFD ' + ltrim(str( ++nPages ))

      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 ))
      /*
      1 = BYTE       8-bit unsigned integer.
      2 = ASCII      8-bit byte that contains a 7-bit ASCII code; the last byte
                     must be NUL (binary zero).
      3 = SHORT      16-bit (2-byte) unsigned integer.
      4 = LONG       32-bit (4-byte) unsigned integer.
      5 = RATIONAL   Two LONGs: the first represents the numerator of a
                     fraction; the second, the denominator.

      In TIFF 6.0, some new field types have been defined:

      6 = SBYTE      An 8-bit signed (twos-complement) integer.
      7 = UNDEFINED  An 8-bit byte that may contain anything, depending on
                     the definition of the field.
      8 = SSHORT     A 16-bit (2-byte) signed (twos-complement) integer.
      9 = SLONG      A 32-bit (4-byte) signed (twos-complement) integer.
      10 = SRATIONAL Two SLONG’s: the first represents the numerator of a
                     fraction, the second the denominator.
      11 = FLOAT     Single precision (4-byte) IEEE format.
      12 = DOUBLE    Double precision (8-byte) IEEE format.
      */
         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
         //?'Tag'
         //??' ' + padr( nTag, 10 )
         cTag := ''
         do case
         case nTag == 256
               /*
               ImageWidth
               Tag = 256 (100.H)
               Type = SHORT or LONG
               The number of columns in the image, i.e., the number of pixels per scanline.
               */
            //??'ImageWidth'
            cTag := 'ImageWidth'
/*
               IF nFieldType != SHORT .and. nFieldType != LONG
                  alert('Wrong Type for ImageWidth')
               ENDIF
*/
            IF nFieldType ==  SHORT
               nWidth := bin2w(substr( cValues, 1, 2 ))
            ELSEIF nFieldType ==  LONG
               nWidth := bin2l(substr( cValues, 1, 4 ))
            ENDIF

         case nTag == 257
               /*
               ImageLength
               Tag = 257 (101.H)
               Type = SHORT or LONG
               The number of rows (sometimes described as scanlines) in the image.
               */
            //??'ImageLength'
            cTag := 'ImageLength'
/*
               IF nFieldType != SHORT .and. nFieldType != LONG
                  alert('Wrong Type for ImageLength')
               ENDIF
*/
            IF nFieldType ==  SHORT
               nHeight := bin2w(substr( cValues, 1, 2 ))
            ELSEIF nFieldType ==  LONG
               nHeight := bin2l(substr( cValues, 1, 4 ))
            ENDIF

         case nTag == 258
               /*
               BitsPerSample
               Tag = 258 (102.H)
               Type = SHORT
               The number of bits per component.
               Allowable values for Baseline TIFF grayscale images are 4 and 8, allowing either
               16 or 256 distinct shades of gray.
               */
            //??'BitsPerSample'
            cTag := 'BitsPerSample'
            nTemp := 0
            IF nFieldType == SHORT
               nTemp := bin2w( cValues )
            ELSE
               //alert('Wrong Type for BitsPerSample')
            ENDIF
            nBits := nTemp
            //IF nTemp != 4 .and. nTemp != 8
            //   alert('Wrong Value for BitsPerSample')
            //ENDIF
         case nTag == 259
               /*
               Compression
               Tag = 259 (103.H)
               Type = SHORT
               Values:
               1 = No compression, but pack data into bytes as tightly as possible, leaving no unused
               bits (except at the end of a row). The component values are stored as an array of
               type BYTE. Each scan line (row) is padded to the next BYTE boundary.
               2 = CCITT Group 3 1-Dimensional Modified Huffman run length encoding. See
               Section 10 for a description of Modified Huffman Compression.
               32773 = PackBits compression, a simple byte-oriented run length scheme. See the
               PackBits section for details.
               Data compression applies only to raster image data. All other TIFF fields are
               unaffected.
               Baseline TIFF readers must handle all three compression schemes.
               */
            //??'Compression'
            cTag := 'Compression'
            nTemp := 0
            IF nFieldType == SHORT
               nTemp := bin2w( cValues )
            ELSE
               //alert('Wrong Type for Compression')
            ENDIF
            //IF nTemp != 1 .and. nTemp != 2 .and. nTemp != 32773
            //   alert('Wrong Value for Compression')
            //ENDIF
         case nTag == 262
               /*
               PhotometricInterpretation
               Tag = 262 (106.H)
               Type = SHORT
               Values:
               0 = WhiteIsZero. For bilevel and grayscale images: 0 is imaged as white. The maxi-mum
               value is imaged as black. This is the normal value for Compression=2.
               1 = BlackIsZero. For bilevel and grayscale images: 0 is imaged as black. The maxi-mum
               value is imaged as white. If this value is specified for Compression=2, the
               image should display and print reversed.
               */
            //??'PhotometricInterpretation'
            cTag := 'PhotometricInterpretation'
            nTemp := -1
            IF nFieldType == SHORT
               nTemp := bin2w( cValues )
            ELSE
               //alert('Wrong Type for PhotometricInterpretation')
            ENDIF
            IF nTemp != 0 .and. nTemp != 1 .and. nTemp != 2 .and. nTemp != 3
               //alert('Wrong Value for PhotometricInterpretation')
            ENDIF
         case nTag == 264
               /*
               CellWidth
               The width of the dithering or halftoning matrix used to create a dithered or
               halftoned bilevel file.Tag = 264 (108.H)
               Type = SHORT
               N = 1
               No default. See also Threshholding.
               */
            //??'CellWidth'
            cTag := 'CellWidth'
            IF nFieldType != SHORT
               //alert('Wrong Type for CellWidth')
            ENDIF
         case nTag == 265
               /*
               CellLength
               The length of the dithering or halftoning matrix used to create a dithered or
               halftoned bilevel file.
               Tag = 265 (109.H)
               Type = SHORT
               N = 1
               This field should only be present if Threshholding = 2
               No default. See also Threshholding.
               */
            //??'CellLength'
            cTag := 'CellLength'
            IF nFieldType != SHORT
               //alert('Wrong Type for CellLength')
            ENDIF
         case nTag == 266
               /*
               FillOrder
               The logical order of bits within a byte.
               Tag = 266 (10A.H)
               Type = SHORT
               N = 1
               */
            //??'FillOrder'
            cTag := 'FillOrder'
            IF nFieldType != SHORT
               //alert('Wrong Type for FillOrder')
            ENDIF
         case nTag == 273
               /*
               StripOffsets
               Tag = 273 (111.H)
               Type = SHORT or LONG
               For each strip, the byte offset of that strip.
               */
            //??'StripOffsets'
            cTag := 'StripOffsets'
            IF nFieldType != SHORT .and. nFieldType != LONG
               //alert('Wrong Type for StripOffsets')
            ENDIF

            IF nFieldType ==  SHORT
               nFrom := bin2w(substr( cValues, 1, 2 ))
            ELSEIF nFieldType ==  LONG
               nFrom := bin2l(substr( cValues, 1, 4 ))
            ENDIF

         case nTag == 277
               /*
               SamplesPerPixel
               Tag = 277 (115.H)
               Type = SHORT
               The number of components per pixel. This number is 3 for RGB images, unless
               extra samples are present. See the ExtraSamples field for further information.
               */
            //??'SamplesPerPixel'
            cTag := 'SamplesPerPixel'
            IF nFieldType != SHORT
               //alert('Wrong Type for SamplesPerPixel')
            ENDIF
         case nTag == 278
               /*
               RowsPerStrip
               Tag = 278 (116.H)
               Type = SHORT or LONG
               The number of rows in each strip (except possibly the last strip.)
               For example, if ImageLength is 24, and RowsPerStrip is 10, then there are 3
               strips, with 10 rows in the first strip, 10 rows in the second strip, and 4 rows in the
               third strip. (The data in the last strip is not padded with 6 extra rows of dummy
               data.)
               */
            //??'RowsPerStrip'
            cTag := 'RowsPerStrip'
            IF nFieldType != SHORT .and. nFieldType != LONG
               //alert('Wrong Type for RowsPerStrip')
            ENDIF
         case nTag == 279
               /*
               StripByteCounts
               Tag = 279 (117.H)
               Type = SHORT or LONG
               For each strip, the number of bytes in that strip after any compression.
               */
            //??'StripByteCounts'
            cTag := 'StripByteCounts'
            IF nFieldType != SHORT .and. nFieldType != LONG
               //alert('Wrong Type for StripByteCounts')
            ENDIF

            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
               /*
               XResolution
               Tag = 282 (11A.H)
               Type = RATIONAL
               The number of pixels per ResolutionUnit in the ImageWidth (typically, horizontal
               - see Orientation) direction.
               */
            //??'XResolution'
            cTag := 'XResolution'
            IF nFieldType != RATIONAL
               //alert('Wrong Type for XResolution')
            ENDIF
            xRes := bin2l(substr( cValues, 1, 4 ))
         case nTag == 283
               /*
               YResolution
               Tag = 283 (11B.H)
               Type = RATIONAL
               The number of pixels per ResolutionUnit in the ImageLength (typically, vertical)
               direction.
               */
            //??'YResolution'
            cTag := 'YResolution'
            IF nFieldType != RATIONAL
               //alert('Wrong Type for YResolution')
            ENDIF
            yRes := bin2l(substr( cValues, 1, 4 ))
         case nTag == 284
            //??'PlanarConfiguration'
            cTag := 'PlanarConfiguration'
            IF nFieldType != SHORT
               //alert('Wrong Type for PlanarConfiguration')
            ENDIF
         case nTag == 288
               /*
               FreeOffsets
               For each string of contiguous unused bytes in a TIFF file, the byte offset of the
               string.
               Tag = 288 (120.H)
               Type = LONG
               Not recommended for general interchange.
               See also FreeByteCounts.
               */
            //??'FreeOffsets'
            cTag := 'FreeOffsets'
            IF nFieldType != LONG
               //alert('Wrong Type for FreeOffsets')
            ENDIF
         case nTag == 289
               /*
               FreeByteCounts
               For each string of contiguous unused bytes in a TIFF file, the number of bytes in
               the string.
               Tag = 289 (121.H)
               Type = LONG
               Not recommended for general interchange.
               See also FreeOffsets.
               */
            //??'FreeByteCounts'
            cTag := 'FreeByteCounts'
            IF nFieldType != LONG
               //alert('Wrong Type for FreeByteCounts')
            ENDIF
         case nTag == 296
               /*
               ResolutionUnit
               Tag = 296 (128.H)
               Type = SHORT
               Values:
               1 = No absolute unit of measurement. Used for images that may have a non-square
               aspect ratio but no meaningful absolute dimensions.
               2 = Inch.
               3 = Centimeter.
               Default = 2 (inch).
               */
            //??'ResolutionUnit'
            cTag := 'ResolutionUnit'
            nTemp := 0
            IF nFieldType == SHORT
               nTemp := bin2w( cValues )
            ELSE
               //alert('Wrong Type for ResolutionUnit')
            ENDIF
            IF nTemp != 1 .and. nTemp != 2 .and. nTemp != 3
               //alert('Wrong Value for ResolutionUnit')
            ENDIF
         case nTag == 305
            //??'Software'
            cTag := 'Software'
            IF nFieldType != ASCII
               //alert('Wrong Type for Software')
            ENDIF
         case nTag == 306
               /*
               DateTime
               Date and time of image creation.
               Tag = 306 (132.H)
               Type = ASCII
               N = 2 0
               The format is: YYYY:MM:DD HH:MM:SS, with hours like those on a 24-hour
               clock, and one space character between the date and the time. The length of the
               string, including the terminating NUL, is 20 bytes.
               */
            //??'DateTime'
            cTag := 'DateTime'
            IF nFieldType != ASCII
               //alert('Wrong Type for DateTime')
            ENDIF
         case nTag == 315
               /*
               Artist
               Person who created the image.
               Tag = 315 (13B.H)
               Type = ASCII
               Note: some older TIFF files used this tag for storing Copyright information.
               */
            //??'Artist'
            cTag := 'Artist'
            IF nFieldType != ASCII
               //alert('Wrong Type for Artist')
            ENDIF
         case nTag == 320
               /*
               ColorMap
               Tag = 320 (140.H)
               Type = SHORT
               N = 3 * (2**BitsPerSample)
               This field defines a Red-Green-Blue color map (often called a lookup table) for
               palette color images. In a palette-color image, a pixel value is used to index into an
               RGB-lookup table. For example, a palette-color pixel having a value of 0 would
               be displayed according to the 0th Red, Green, Blue triplet.
               In a TIFF ColorMap, all the Red values come first, followed by the Green values,
               then the Blue values. In the ColorMap, black is represented by 0,0,0 and white is
               represented by 65535, 65535, 65535.
               */
            //??'ColorMap'
            cTag := 'ColorMap'
            IF nFieldType != SHORT
               //alert('Wrong Type for ColorMap')
            ENDIF
         case nTag == 338
               /*
               ExtraSamples
               Description of extra components.
               Tag = 338 (152.H)
               Type = SHORT
               N = m
               */
            //??'ExtraSamples'
            cTag := 'ExtraSamples'
            IF nFieldType != SHORT
               //alert('Wrong Type for ExtraSamples')
            ENDIF
         case nTag == 33432
               /*
               Copyright
               Copyright notice.
               Tag = 33432 (8298.H)
               Type = ASCII
               Copyright notice of the person or organization that claims the copyright to the
               image. The complete copyright statement should be listed in this field including
               any dates and statements of claims. For example, “Copyright, John Smith, 19xx.
               All rights reserved.
               */
            //??'Copyright'
            cTag := 'Copyright'
            IF nFieldType != ASCII
               //alert('Wrong Type for Copyright')
            ENDIF
         otherwise
            //??'Unknown'
            cTag := 'Unknown'
         endcase
      /*
      ??padr( cTag, 30 )
      ??' type ' + padr(aType[ nFieldType ], 10) + ' count ' + ltrim(str(nCount)) + ' <'
      do case
         case nFieldType ==  BYTE
              for nI := 1 to nCount
                  ??' ' + ltrim(str(asc( substr( cValues, nI, 1 ))))
              next
         case nFieldType ==  ASCII
              ??' '
              for nI := 1 to nCount
                  ??substr( cValues, nI, 1 )
              next
         case nFieldType ==  SHORT
              for nI := 1 to nCount
                  ??' ' + ltrim(str(bin2w(substr( cValues, ( nI - 1 ) * 2 + 1, 2 ))))
              next
         case nFieldType ==  LONG
              for nI := 1 to nCount
                  ??' ' + ltrim(str(bin2l(substr( cValues, ( nI - 1 ) * 4 + 1, 4 ))))
              next
         case nFieldType ==  RATIONAL
              for nI := 1 to nCount
                  ??' ' + ltrim(str(bin2l(substr( cValues, ( nI - 1 ) * 8 + 1, 4 )))) + '/' + ltrim(str(bin2l(substr( cValues, nI + 4, 4 ))))
              next
         case nFieldType ==  SBYTE
              for nI := 1 to nCount
                  ??' ' + ltrim(str(asc( substr( cValues, nI, 1 ))))
              next
         case nFieldType ==  UNDEFINED
              for nI := 1 to nCount
                  ??' ' + substr( cValues, nI, 1 )
              next
         case nFieldType ==  SSHORT
              for nI := 1 to nCount
                  ??' ' + ltrim(str(bin2i(substr( cValues, ( nI - 1 ) * 2 + 1, 2 ))))
              next
         case nFieldType ==  SLONG
              for nI := 1 to nCount
                  ??' ' + ltrim(str(bin2l(substr( cValues, ( nI - 1 ) * 4 + 1, 4 ))))
              next
         case nFieldType == SRATIONAL
              for nI := 1 to nCount
                  ??' ' + ltrim(str(bin2l(substr( cValues, ( nI - 1 ) * 8 + 1, 4 )))) + '/' + ltrim(str(bin2l(substr( cValues, nI + 4, 4 ))))
              next
         case nFieldType == FLOAT
         case nFieldType == DOUBLE
              for nI := 1 to nCount
                  ??' ' + ltrim(str(ctof(substr( cValues, ( nI - 1 ) * 8 + 1, 8 ))))
              next

      endcase
      ??' >'
      */
      next
      fread( nHandle, @cIFDNext, 4 )
   enddo

   fclose( nHandle )

   aadd( aTemp, nWidth )
   aadd( aTemp, nHeight )
   aadd( aTemp, xRes )
   aadd( aTemp, yRes )
   aadd( aTemp, nBits )
   aadd( aTemp, nFrom )
   aadd( aTemp, nLength )

   nSpace := 0
   aadd( aTemp, nSpace )
return aTemp
hbvpdf.prg1763
FUNCTIONpdfJPEGInfo( cFile )
function pdfJPEGInfo( cFile )
local c255, nAt, nHandle
local nWidth := 0, nHeight := 0, nBits := 8, nFrom := 0, nLength := 0, xRes := 0, yRes := 0, aTemp := {}
local nBuffer := 20000
local nSpace := 3 // 3 - RGB, 1 - GREY, 4 - CMYK

   nHandle := fopen( cFile )

   c255 := space( nBuffer )
   fread( nHandle, @c255, nBuffer )

   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 := rat( 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 ))

   nSpace := asc( substr( c255, nAt + 4, 1 ))

   nLength := filesize( nHandle )

   fclose( nHandle )

   aadd( aTemp, nWidth )
   aadd( aTemp, nHeight )
   aadd( aTemp, xRes )
   aadd( aTemp, yRes )
   aadd( aTemp, nBits )
   aadd( aTemp, nFrom )
   aadd( aTemp, nLength )
   aadd( aTemp, nSpace )

return aTemp
hbvpdf.prg2311
STATIC FUNCTIONFilePos( nHandle )
STATIC FUNCTION FilePos( nHandle )
RETURN ( FSEEK( nHandle, 0, FS_RELATIVE ) )
hbvpdf.prg2346
STATIC FUNCTIONChr_RGB( cChar )
STATIC FUNCTION Chr_RGB( cChar )
RETURN str(asc( cChar ) / 255, 4, 2)
hbvpdf.prg2349
STATIC FUNCTIONNumToken( cString, cDelimiter )
STATIC FUNCTION NumToken( cString, cDelimiter )
RETURN AllToken( cString, cDelimiter )
hbvpdf.prg2352
STATIC FUNCTIONToken( cString, cDelimiter, nPointer )
STATIC FUNCTION Token( cString, cDelimiter, nPointer )
RETURN AllToken( cString, cDelimiter, nPointer, 1 )
hbvpdf.prg2355
STATIC FUNCTIONAtToken( cString, cDelimiter, nPointer )
STATIC FUNCTION AtToken( cString, cDelimiter, nPointer )
RETURN AllToken( cString, cDelimiter, nPointer, 2 )
hbvpdf.prg2358
STATIC FUNCTIONAllToken( cString, cDelimiter, nPointer, nAction )
STATIC FUNCTION AllToken( cString, cDelimiter, nPointer, nAction )
LOCAL nTokens := 0, nPos := 1, nLen := len( cString ), nStart := 0, cToken := "", cRet
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 !substr( cString, nPos, 1 ) $ cDelimiter
               nStart := nPos
               while nPos <= nLen .and. !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
hbvpdf.prg2361
STATIC FUNCTIONNumAt( cSearch, cString )
STATIC FUNCTION NumAt( cSearch, cString )
   LOCAL n := 0, nAt := 0, nPos := 0
   WHILE ( nAt := at( cSearch, substr( cString, nPos + 1 ) )) > 0
           nPos += nAt
           ++n
   ENDDO
RETURN n
hbvpdf.prg2397
STATIC FUNCTIONFileSize( nHandle )
STATIC FUNCTION FileSize( nHandle )

   LOCAL nCurrent
   LOCAL nLength

   // Get file position
   nCurrent := FilePos( nHandle )

   // Get file length
   nLength := FSEEK( nHandle, 0, FS_END )

   // nLength := FilePos( nHandle )

   // Reset file position
   FSEEK( nHandle, nCurrent )

RETURN ( nLength )
hbvpdf.prg2405
STATIC FUNCTIONArray2File(cFile,aRay,nDepth,hFile)
static function Array2File(cFile,aRay,nDepth,hFile)
local nBytes := 0
local i
nDepth := iif(ISNUMBER(nDepth),nDepth,0)
if hFile == NIL
   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
   fClose(hFile)
endif
return(nBytes)
hbvpdf.prg2426
STATIC FUNCTIONWriteData(hFile,xData)
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)) )
hbvpdf.prg2448
STATIC FUNCTIONFile2Array(cFile,nLen,hFile)
static function File2Array(cFile,nLen,hFile)
LOCAL cData,cType,nDataLen,nBytes
local nDepth := 0
local aRay   := {}
if hFile == NIL
     if (hFile:=fOpen(cFile,FO_READ)) == -1
         return(aRay)
     endif
     cData := space(3)
     fRead(hFile,@cData,3)
     if left(cData,1) != 'A'
         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
hbvpdf.prg2465
hbvpdft.prg
TypeFunctionSourceLine
METHODInit( cFile, nLen, lOptimize ) CONSTRUCTOR
METHOD Init( cFile, nLen, lOptimize ) CONSTRUCTOR
hbvpdft.prg55
METHODInit
METHOD Init
hbvpdft.prg57
METHODAtSay
METHOD AtSay
hbvpdft.prg60
METHODNormal
METHOD Normal
hbvpdft.prg61
METHODBold
METHOD Bold
hbvpdft.prg62
METHODItalic
METHOD Italic
hbvpdft.prg63
METHODUnderLine
METHOD UnderLine
hbvpdft.prg64
METHODBoldItalic
METHOD BoldItalic
hbvpdft.prg65
METHODBookAdd
METHOD BookAdd
hbvpdft.prg66
METHODBookClose
METHOD BookClose
hbvpdft.prg67
METHODBookOpen
METHOD BookOpen
hbvpdft.prg68
METHODBox
METHOD Box
hbvpdft.prg69
METHODBox1
METHOD Box1
hbvpdft.prg70
METHODCenter
METHOD Center
hbvpdft.prg71
METHODClose
METHOD Close
hbvpdft.prg72
METHODImage
METHOD Image
hbvpdft.prg73
METHODLength
METHOD Length
hbvpdft.prg74
METHODNewLine
METHOD NewLine
hbvpdft.prg75
METHODNewPage
METHOD NewPage
hbvpdft.prg76
METHODPageSize
METHOD PageSize
hbvpdft.prg77
METHODPageOrient
METHOD PageOrient
hbvpdft.prg78
METHODPageNumber
METHOD PageNumber
hbvpdft.prg79
METHODReverse
METHOD Reverse
hbvpdft.prg80
METHODRJust
METHOD RJust
hbvpdft.prg81
METHODSetFont
METHOD SetFont
hbvpdft.prg82
METHODSetLPI
METHOD SetLPI
hbvpdft.prg83
METHODStringB
METHOD StringB
hbvpdft.prg84
METHODTextCount
METHOD TextCount
hbvpdft.prg85
METHODText
METHOD Text
hbvpdft.prg86
METHODOpenHeader
METHOD OpenHeader
hbvpdft.prg87
METHODEditOnHeader
METHOD EditOnHeader
hbvpdft.prg88
METHODEditOffHeader
METHOD EditOffHeader
hbvpdft.prg89
METHODCloseHeader
METHOD CloseHeader
hbvpdft.prg90
METHODDeleteHeader
METHOD DeleteHeader
hbvpdft.prg91
METHODEnableHeader
METHOD EnableHeader
hbvpdft.prg92
METHODDisableHeader
METHOD DisableHeader
hbvpdft.prg93
METHODSaveHeader
METHOD SaveHeader
hbvpdft.prg94
METHODHeader
METHOD Header
hbvpdft.prg95
METHODDrawHeader
METHOD DrawHeader
hbvpdft.prg96
METHODMargins
METHOD Margins
hbvpdft.prg97
METHODCreateHeader
METHOD CreateHeader
hbvpdft.prg98
METHODImageInfo
METHOD ImageInfo
hbvpdft.prg99
METHODTIFFInfo
METHOD TIFFInfo
hbvpdft.prg100
METHODJPEGInfo
METHOD JPEGInfo
hbvpdft.prg101
METHODFilePrint
METHOD FilePrint
hbvpdft.prg102
METHODBookCount
METHOD BookCount
hbvpdft.prg103
METHODBookFirst
METHOD BookFirst
hbvpdft.prg104
METHODBookLast
METHOD BookLast
hbvpdft.prg105
METHODBookNext
METHOD BookNext
hbvpdft.prg106
METHODBookParent
METHOD BookParent
hbvpdft.prg107
METHODBookPrev
METHOD BookPrev
hbvpdft.prg108
METHODCheckLine
METHOD CheckLine
hbvpdft.prg109
METHODClosePage
METHOD ClosePage
hbvpdft.prg110
METHODGetFontInfo
METHOD GetFontInfo
hbvpdft.prg111
METHODM2R
METHOD M2R
hbvpdft.prg112
METHODM2X
METHOD M2X
hbvpdft.prg113
METHODM2Y
METHOD M2Y
hbvpdft.prg114
METHODR2D
METHOD R2D
hbvpdft.prg115
METHODR2M
METHOD R2M
hbvpdft.prg116
METHODX2M
METHOD X2M
hbvpdft.prg117
METHODTextPrint
METHOD TextPrint
hbvpdft.prg118
METHODTextNextPara
METHOD TextNextPara
hbvpdft.prg119
METHODExecute
METHOD Execute

ENDCLASS
hbvpdft.prg120
METHOD TPDFInit( cFile, nLen, lOptimize )
METHOD tPdf:Init( cFile, nLen, lOptimize )
hbvpdft.prg127
METHODInit( cFile, nLen, lOptimize )
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
hbvpdft.prg129
METHOD TPDFAtSay( cString, nRow, nCol, cUnits, lExact, cId )
METHOD tPdf:AtSay( cString, nRow, nCol, cUnits, lExact, cId )
hbvpdft.prg198
METHODAtSay( cString, nRow, nCol, cUnits, lExact, cId )
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
hbvpdft.prg200
METHOD TPDFNormal()
METHOD tPdf:Normal()
hbvpdft.prg274
METHODNormal()
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
hbvpdft.prg276
METHOD TPDFItalic()
METHOD tPdf:Italic()
hbvpdft.prg296
METHODItalic()
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
hbvpdft.prg298
METHOD TPDFBold()
METHOD tPdf:Bold()
hbvpdft.prg318
METHODBold()
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
hbvpdft.prg320
METHOD TPDFBoldItalic()
METHOD tPdf:BoldItalic()
hbvpdft.prg342
METHODBoldItalic()
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
hbvpdft.prg344
METHOD TPDFBookAdd( cTitle, nLevel, nPage, nLine )
METHOD tPdf:BookAdd( cTitle, nLevel, nPage, nLine )
hbvpdft.prg366
METHODBookAdd( cTitle, nLevel, nPage, nLine )
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
hbvpdft.prg368
METHOD TPDFBookClose( )
METHOD tPdf:BookClose( )
hbvpdft.prg378
METHODBookClose( )
METHOD BookClose( ) 
#endif

::aReport[ BOOKMARK ] := nil

RETURN self
hbvpdft.prg380
METHOD TPDFBookOpen( )
METHOD tPdf:BookOpen( )
hbvpdft.prg390
METHODBookOpen( )
METHOD BookOpen( ) 
#endif

::aReport[ BOOKMARK ] := {}

RETURN self
hbvpdft.prg392
METHOD TPDFBox( x1, y1, x2, y2, nBorder, nShade, cUnits, cColor, cId )
METHOD tPdf:Box( x1, y1, x2, y2, nBorder, nShade, cUnits, cColor, cId )
hbvpdft.prg402
METHODBox( x1, y1, x2, y2, nBorder, nShade, cUnits, cColor, cId )
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
hbvpdft.prg404
METHOD TPDFBox1( nTop, nLeft, nBottom, nRight, nBorderWidth, cBorderColor, cBoxColor )
METHOD tPdf:Box1( nTop, nLeft, nBottom, nRight, nBorderWidth, cBorderColor, cBoxColor )
hbvpdft.prg466
METHODBox1( nTop, nLeft, nBottom, nRight, nBorderWidth, cBorderColor, cBoxColor )
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
hbvpdft.prg468
METHOD TPDFCenter( cString, nRow, nCol, cUnits, lExact, cId )
METHOD tPdf:Center( cString, nRow, nCol, cUnits, lExact, cId )
hbvpdft.prg497
METHODCenter( cString, nRow, nCol, cUnits, lExact, cId )
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
hbvpdft.prg499
METHOD TPDFClose()
METHOD tPdf:Close()
hbvpdft.prg529
METHODClose()
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
hbvpdft.prg531
METHOD TPDFImage( cFile, nRow, nCol, cUnits, nHeight, nWidth, cId )
METHOD tPdf:Image( cFile, nRow, nCol, cUnits, nHeight, nWidth, cId )
hbvpdft.prg675
METHODImage( cFile, nRow, nCol, cUnits, nHeight, nWidth, cId )
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
hbvpdft.prg677
METHOD TPDFLength( cString )
METHOD tPdf:Length( cString )
hbvpdft.prg719
METHODLength( cString )
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
hbvpdft.prg721
METHOD TPDFNewLine( n )
METHOD tPdf:NewLine( n )
hbvpdft.prg746
METHODNewLine( n )
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 ]
hbvpdft.prg748
METHOD TPDFNewPage( _cPageSize, _cPageOrient, _nLpi, _cFontName, _nFontType, _nFontSize )
METHOD tPdf:NewPage( _cPageSize, _cPageOrient, _nLpi, _cFontName, _nFontType, _nFontSize )
hbvpdft.prg764
METHODNewPage( _cPageSize, _cPageOrient, _nLpi, _cFontName, _nFontType, _nFontSize )
METHOD NewPage( _cPageSize, _cPageOrient, _nLpi, _cFontName, _nFontType, _nFontSize ) 
#endif

local nAdd := 76.2

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
hbvpdft.prg766
METHOD TPDFPageSize( _cPageSize )
METHOD tPdf:PageSize( _cPageSize )
hbvpdft.prg804
METHODPageSize( _cPageSize )
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
hbvpdft.prg806
METHOD TPDFPageOrient( _cPageOrient )
METHOD tPdf:PageOrient( _cPageOrient )
hbvpdft.prg848
METHODPageOrient( _cPageOrient )
METHOD PageOrient( _cPageOrient ) 
#endif

DEFAULT _cPageOrient TO "P"

   ::aReport[ PAGEORIENT ] := _cPageOrient
   ::PageSize( ::aReport[ PAGESIZE ] )
RETURN self
hbvpdft.prg850
METHOD TPDFPageNumber( n )
METHOD tPdf:PageNumber( n )
hbvpdft.prg862
METHODPageNumber( n )
METHOD PageNumber( n ) 
#endif

DEFAULT n TO 0
   IF n > 0
      ::aReport[ REPORTPAGE ] := n // NEW !!!
   ENDIF
RETURN ::aReport[ REPORTPAGE ]
hbvpdft.prg864
METHOD TPDFReverse( cString )
METHOD tPdf:Reverse( cString )
hbvpdft.prg876
METHODReverse( cString )
METHOD Reverse( cString ) 
#endif

RETURN cString + chr(255)
hbvpdft.prg878
METHOD TPDFRJust( cString, nRow, nCol, cUnits, lExact, cId )
METHOD tPdf:RJust( cString, nRow, nCol, cUnits, lExact, cId )
hbvpdft.prg886
METHODRJust( cString, nRow, nCol, cUnits, lExact, cId )
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
hbvpdft.prg888
METHOD TPDFSetFont( _cFont, _nType, _nSize, cId )
METHOD tPdf:SetFont( _cFont, _nType, _nSize, cId )
hbvpdft.prg919
METHODSetFont( _cFont, _nType, _nSize, cId )
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
hbvpdft.prg921
METHOD TPDFSetLPI(_nLpi)
METHOD tPdf:SetLPI(_nLpi)
hbvpdft.prg953
METHODSetLPI(_nLpi)
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
hbvpdft.prg955
METHOD TPDFStringB( cString )
METHOD tPdf:StringB( cString )
hbvpdft.prg970
METHODStringB( cString )
METHOD StringB( cString ) 
#endif

cString := strtran( cString, "(", "\(" )
cString := strtran( cString, ")", "\)" )

RETURN cString
hbvpdft.prg972
METHOD TPDFTextCount( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits )
METHOD tPdf:TextCount( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits )
hbvpdft.prg983
METHODTextCount( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits )
METHOD TextCount( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits ) 
#endif

RETURN ::Text( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits, .f. )
hbvpdft.prg985
METHOD TPDFText( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits, cColor, lPrint )
METHOD tPdf:Text( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits, cColor, lPrint )
hbvpdft.prg993
METHODText( cString, nTop, nLeft, nLength, nTab, nJustify, cUnits, cColor, lPrint )
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 )
   nTokenLen := 0.00
   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
hbvpdft.prg995
METHOD TPDFUnderLine( cString )
METHOD tPdf:UnderLine( cString )
hbvpdft.prg1112
METHODUnderLine( cString )
METHOD UnderLine( cString ) 
#endif

RETURN cString + chr(254)
hbvpdft.prg1114
METHOD TPDFOpenHeader( cFile )
METHOD tPdf:OpenHeader( cFile )
hbvpdft.prg1122
METHODOpenHeader( cFile )
METHOD OpenHeader( cFile ) 
#endif

local nErrorCode := 0, 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
hbvpdft.prg1124
METHOD TPDFEditOnHeader()
METHOD tPdf:EditOnHeader()
hbvpdft.prg1155
METHODEditOnHeader()
METHOD EditOnHeader() 
#endif

::aReport[ HEADEREDIT ] := .t.
::aReport[ MARGINS ] := .t.

RETURN self
hbvpdft.prg1157
METHOD TPDFEditOffHeader()
METHOD tPdf:EditOffHeader()
hbvpdft.prg1168
METHODEditOffHeader()
METHOD EditOffHeader() 
#endif

::aReport[ HEADEREDIT ] := .f.
::aReport[ MARGINS    ] := .t.

RETURN self
hbvpdft.prg1170
METHOD TPDFCloseHeader()
METHOD tPdf:CloseHeader()
hbvpdft.prg1181
METHODCloseHeader()
METHOD CloseHeader() 
#endif

   ::aReport[ HEADER ] := {}
   ::aReport[ MARGINS ] := .f.
RETURN self
hbvpdft.prg1183
METHOD TPDFDeleteHeader( cId )
METHOD tPdf:DeleteHeader( cId )
hbvpdft.prg1193
METHODDeleteHeader( cId )
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
hbvpdft.prg1195
METHOD TPDFEnableHeader( cId )
METHOD tPdf:EnableHeader( cId )
hbvpdft.prg1212
METHODEnableHeader( cId )
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
hbvpdft.prg1214
METHOD TPDFDisableHeader( cId )
METHOD tPdf:DisableHeader( cId )
hbvpdft.prg1229
METHODDisableHeader( cId )
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
hbvpdft.prg1231
METHOD TPDFSaveHeader( cFile )
METHOD tPdf:SaveHeader( cFile )
hbvpdft.prg1246
METHODSaveHeader( cFile )
METHOD SaveHeader( cFile ) 
#endif

local nErrorCode := 0, cCmd

Array2File( "temp.tmp", ::aReport[ HEADER ] )

cCmd := "copy temp.tmp " + cFile + " > nul"
RunExternal( cCmd )

RETURN self
hbvpdft.prg1248
METHOD TPDFHeader( cFunction, cId, arr )
METHOD tPdf:Header( cFunction, cId, arr )
hbvpdft.prg1263
METHODHeader( cFunction, cId, arr )
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
hbvpdft.prg1265
METHOD TPDFDrawHeader()
METHOD tPdf:DrawHeader()
hbvpdft.prg1305
METHODDrawHeader()
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
hbvpdft.prg1307
METHOD TPDFMargins( nTop, nLeft, nBottom )
METHOD tPdf:Margins( nTop, nLeft, nBottom )
hbvpdft.prg1363
METHODMargins( nTop, nLeft, nBottom )
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
hbvpdft.prg1365
METHOD TPDFCreateHeader( _file, _size, _orient, _lpi, _width )
METHOD tPdf:CreateHeader( _file, _size, _orient, _lpi, _width )
hbvpdft.prg1541
METHODCreateHeader( _file, _size, _orient, _lpi, _width )
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
hbvpdft.prg1543
METHOD TPDFImageInfo( cFile )
METHOD tPdf:ImageInfo( cFile )
hbvpdft.prg1641
METHODImageInfo( cFile )
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
hbvpdft.prg1643
METHOD TPDFTIFFInfo( cFile )
METHOD tPdf:TIFFInfo( cFile )
hbvpdft.prg1658
METHODTIFFInfo( cFile )
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, nPages, 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)
   nPages := 0

   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

   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
hbvpdft.prg1660
METHOD TPDFJPEGInfo( cFile )
METHOD tPdf:JPEGInfo( cFile )
hbvpdft.prg1833
METHODJPEGInfo( cFile )
METHOD JPEGInfo( cFile ) 
#endif

local c255, nAt, nHandle
local nWidth := 0, nHeight := 0, nBits := 8, nFrom := 0
local nLength := 0, xRes := 0, yRes := 0, 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
hbvpdft.prg1835
METHOD TPDFBookCount( nRecno, nCurLevel )
METHOD tPdf:BookCount( nRecno, nCurLevel )
hbvpdft.prg1871
METHODBookCount( nRecno, nCurLevel )
METHOD BookCount( nRecno, nCurLevel ) 
#endif

local nTempLevel := 0, 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
hbvpdft.prg1873
METHOD TPDFBookFirst( nRecno, nCurLevel, nObj )
METHOD tPdf:BookFirst( nRecno, nCurLevel, nObj )
hbvpdft.prg1894
METHODBookFirst( nRecno, nCurLevel, nObj )
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 )
hbvpdft.prg1896
METHOD TPDFBookLast( nRecno, nCurLevel, nObj )
METHOD tPdf:BookLast( nRecno, nCurLevel, nObj )
hbvpdft.prg1911
METHODBookLast( nRecno, nCurLevel, nObj )
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 )
hbvpdft.prg1913
METHOD TPDFBookNext( nRecno, nCurLevel, nObj )
METHOD tPdf:BookNext( nRecno, nCurLevel, nObj )
hbvpdft.prg1933
METHODBookNext( nRecno, nCurLevel, nObj )
METHOD BookNext( nRecno, nCurLevel, nObj ) 
#endif

local nTempLevel := 0, 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 )
hbvpdft.prg1935
METHOD TPDFBookParent( nRecno, nCurLevel, nObj )
METHOD tPdf:BookParent( nRecno, nCurLevel, nObj )
hbvpdft.prg1957
METHODBookParent( nRecno, nCurLevel, nObj )
METHOD BookParent( nRecno, nCurLevel, nObj ) 
#endif

local nTempLevel := 0
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 )
hbvpdft.prg1959
METHOD TPDFBookPrev( nRecno, nCurLevel, nObj )
METHOD tPdf:BookPrev( nRecno, nCurLevel, nObj )
hbvpdft.prg1978
METHODBookPrev( nRecno, nCurLevel, nObj )
METHOD BookPrev( nRecno, nCurLevel, nObj ) 
#endif

local nTempLevel := 0
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 )
hbvpdft.prg1980
METHOD TPDFCheckLine( nRow )
METHOD tPdf:CheckLine( nRow )
hbvpdft.prg2003
METHODCheckLine( nRow )
METHOD CheckLine( nRow ) 
#endif

   IF nRow + ::aReport[ PDFTOP] > ::aReport[ PDFBOTTOM ]
      ::NewPage()
      nRow := ::aReport[ REPORTLINE ]
   ENDIF
   ::aReport[ REPORTLINE ] := nRow
RETURN self
hbvpdft.prg2005
METHOD TPDFGetFontInfo( cParam )
METHOD tPdf:GetFontInfo( cParam )
hbvpdft.prg2018
METHODGetFontInfo( cParam )
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
hbvpdft.prg2020
METHOD TPDFM2R( mm )
METHOD tPdf:M2R( mm )
hbvpdft.prg2041
METHODM2R( mm )
METHOD M2R( mm ) 
#endif

return int( ::aReport[ LPI ] * mm / 25.4 )
hbvpdft.prg2043
METHOD TPDFM2X( n )
METHOD tPdf:M2X( n )
hbvpdft.prg2051
METHODM2X( n )
METHOD M2X( n ) 
#endif

return n * 72 / 25.4
hbvpdft.prg2053
METHOD TPDFM2Y( n )
METHOD tPdf:M2Y( n ) 
hbvpdft.prg2061
METHODM2Y( n )
METHOD M2Y( n ) 
#endif

return ::aReport[ PAGEY ] -  n * 72 / 25.4
hbvpdft.prg2063
METHOD TPDFR2D( nRow )
METHOD tPdf:R2D( nRow )
hbvpdft.prg2071
METHODR2D( nRow )
METHOD R2D( nRow ) 
#endif

return ::aReport[ PAGEY ] - nRow * 72 / ::aReport[ LPI ]
hbvpdft.prg2073
METHOD TPDFR2M( nRow )
METHOD tPdf:R2M( nRow )
hbvpdft.prg2081
METHODR2M( nRow )
METHOD R2M( nRow ) 
#endif

return 25.4 * nRow / ::aReport[ LPI ]
hbvpdft.prg2083
METHOD TPDFX2M( n )
METHOD tPdf:X2M( n )
hbvpdft.prg2091
METHODX2M( n )
METHOD X2M( n ) 
#endif

return n * 25.4 / 72
hbvpdft.prg2093
METHOD TPDFTextPrint( nI, nLeft, lParagraph, nJustify, nSpace, nNew, nLength, nLineLen, nLines, nStart, cString, cDelim, cColor, lPrint )
METHOD tPdf:TextPrint( nI, nLeft, lParagraph, nJustify, nSpace, nNew, nLength, nLineLen, nLines, nStart, cString, cDelim, cColor, lPrint )
hbvpdft.prg2101
METHODTextPrint( nI, nLeft, lParagraph, nJustify, nSpace, nNew, nLength, nLineLen, nLines, nStart, cString, cDelim, cColor, lPrint )
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
hbvpdft.prg2103
METHOD TPDFTextNextPara( cString, cDelim, nI )
METHOD tPdf:TextNextPara( cString, cDelim, nI )
hbvpdft.prg2152
METHODTextNextPara( cString, cDelim, nI )
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
hbvpdft.prg2154
METHOD TPDFClosePage()
METHOD tPdf:ClosePage()
hbvpdft.prg2172
METHODClosePage()
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
hbvpdft.prg2174
METHOD TPDFFilePrint( cFile )
METHOD tPdf:FilePrint( cFile )
hbvpdft.prg2361
METHODFilePrint( cFile )
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
hbvpdft.prg2363
METHOD TPDFExecute( cFile )
METHOD tPdf:Execute( cFile )
hbvpdft.prg2380
METHODExecute( cFile )
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
hbvpdft.prg2382
STATIC FUNCTIONFilePos( nHandle )
static function FilePos( nHandle )
return ( FSEEK( nHandle, 0, FS_RELATIVE ) )
hbvpdft.prg2399
STATIC FUNCTIONChr_RGB( cChar )
static function Chr_RGB( cChar )
return str(asc( cChar ) / 255, 4, 2)
hbvpdft.prg2409
STATIC FUNCTIONTimeAsAMPM( cTime )
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
hbvpdft.prg2414
STATIC FUNCTIONFileSize( cFile )
static function FileSize( cFile )

   LOCAL nLength
   LOCAL nHandle

   nHandle := fOpen( cFile )
   nLength := fSeek( nHandle, 0, FS_END )
   fClose( nHandle )

return ( nLength )
hbvpdft.prg2427
STATIC FUNCTIONNumToken( cString, cDelimiter )
static FUNCTION NumToken( cString, cDelimiter )
RETURN AllToken( cString, cDelimiter )
hbvpdft.prg2440
STATIC FUNCTIONToken( cString, cDelimiter, nPointer )
static FUNCTION Token( cString, cDelimiter, nPointer )
RETURN AllToken( cString, cDelimiter, nPointer, 1 )
hbvpdft.prg2445
STATIC FUNCTIONAtToken( cString, cDelimiter, nPointer )
static function AtToken( cString, cDelimiter, nPointer )
return AllToken( cString, cDelimiter, nPointer, 2 )
hbvpdft.prg2450
STATIC FUNCTIONAllToken( cString, cDelimiter, nPointer, nAction )
static function AllToken( cString, cDelimiter, nPointer, nAction )
local nTokens := 0
local nPos    := 1
local nLen    := len( cString )
local nStart  := 0
local cToken  := ""
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
hbvpdft.prg2455
STATIC FUNCTIONArray2File( cFile, aRay, nDepth, hFile )
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 )
hbvpdft.prg2504
STATIC FUNCTIONWriteData(hFile,xData)
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 ) ) )
hbvpdft.prg2533
STATIC FUNCTIONFile2Array( cFile, nLen, hFile )
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 )
hbvpdft.prg2554
STATIC FUNCTIONNumAt( cSearch, cString )
static FUNCTION NumAt( cSearch, cString )

   LOCAL n := 0, nAt := 0, nPos := 0
   WHILE ( nAt := at( cSearch, substr( cString, nPos + 1 ) )) > 0
           nPos += nAt
           ++n
   ENDDO

RETURN n
hbvpdft.prg2611
STATIC FUNCTIONRunExternal( cCmd, cVerb, cFile )
static function RunExternal( cCmd, cVerb, cFile )
local lRet := .t.

#ifdef __CLP__
   lRet := SwpRunCmd( cCmd, 0, "", "" )
#endif

#ifdef __HARBOUR__
    if cVerb != nil
// TOFIX: This requires hbwhat32, which in turns requires xhb.
//        This has to 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
hbvpdft.prg2623
hbvpsup.prg
TypeFunctionSourceLine
FUNCTIONvpdf_FontsDat()
FUNCTION vpdf_FontsDat()
   RETURN StrB64Decode( ;
      "+gD6APoA+gBNAU0BTQGFAZgBKwKkASsC9AH0AfQB9AH0AfQB9AH0AUED6ANBA0EDCgNBAwoDCgNN" +;
      "AU0BTQFNAU0BTQFNAU0BTQFNAU0BTQH0AfQB9AH0ATQCOgKjAjoC+gD6APoA+gBNAU0BTQFNAfoA" +;
      "+gD6APoAFgEWARYBFgH0AfQB9AH0AfQB9AH0AfQB9AH0AfQB9AH0AfQB9AH0AfQB9AH0AfQB9AH0" +;
      "AfQB9AH0AfQB9AH0AfQB9AH0AfQB9AH0AfQB9AH0AfQB9AH0ARYBTQFNAU0BFgFNAU0BTQE0AjoC" +;
      "owI6AjQCOgKjAjoCNAI6AqMCOgK8AfQB9AH0AZkDogOYA0AD0gLSAmMCmwKbApsCYwKbApsC0gKb" +;
      "ApsC0gLSAtIC0gJjApsCYwKbAiwCYwJjApsC0gIKA9IC0gLSAgoD0gIKA00BhQFNAYUBhQH0AbwB" +;
      "9AHSAgoDmwKbAmMCmwIsAmMCeQOwA0EDeQPSAtICmwLSAtICCgPSAtICLAJjAmMCYwLSAgoD0gLS" +;
      "ApsC0gJjApsCLAIsAvQBLAJjApsCLAJjAtIC0gLSAtIC0gLSAmMCmwKwA+gDQQN5A9IC0gJjApsC" +;
      "0gLSAiwCYwJjApsCLAJjAk0BTQGFAU0BFgEWARYBFgFNAU0BhQFNAdUBRQKmAToC9AH0AfQB9AFN" +;
      "AU0BTQFNAbwB9AH0AfQB9AEsAvQB9AG8AbwBvAG8AfQBLAL0AfQBvAG8AbwBvAFNAU0BFgFNAfQB" +;
      "9AH0AfQB9AEsAvQBLAIWARYBFgEWARYBTQEWARYB9AEsArwB9AEWARYBFgEWAQoDQQPSAgoD9AEs" +;
      "AvQBLAL0AfQB9AH0AfQBLAL0AfQB9AEsAvQB9AFNAbwBhQGFAYUBhQGFAYUBFgFNARYBFgH0ASwC" +;
      "9AEsAvQB9AG8AbwB0gLSApsCmwL0AfQBvAH0AfQB9AG8AbwBvAG8AYUBhQHgAYoBkAFcAcgA3AAT" +;
      "AdwA4AGKAZABXAEdAggCHQI6AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +;
      "AAAAAAAATQFNAYUBhQH0AfQB9AH0AfQB9AH0AfQBpwCnAKcApwD0AfQB9AH0AfQB9AH0AfQB9AH0" +;
      "AfQB9AH0AfQB9AH0AbQAFgHWABYBvAH0ASwC9AH0AfQB9AH0AU0BTQFNAU0BTQFNAU0BTQEsAiwC" +;
      "9AEsAiwCLAL0ASwCAAAAAAAAAAD0AfQB9AH0AfQB9AH0AfQB9AH0AfQB9AH6APoA+gD6AAAAAAAA" +;
      "AAAAxQEcAgsC9AFeAV4BXgFeAU0BTQFNAU0BvAH0ASwC9AG8AfQBLAL0AfQB9AH0AfQB6APoA3kD" +;
      "6APoA+gD6APoAwAAAAAAAAAAvAH0AfQB9AEAAAAAAAAAAE0BTQFNAU0BTQFNAU0BTQFNAU0BTQFN" +;
      "AU0BTQFNAU0BTQFNAU0BTQFNAU0BTQFNAU0BTQFNAU0BTQFNAU0BTQEAAAAAAAAAAE0BTQFNAU0B" +;
      "TQFNAU0BTQEAAAAAAAAAAE0BTQFNAU0BTQFNAU0BTQFNAU0BTQFNAegD6AN5A+gDAAAAAAAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +;
      "AAAAAAB5A+gDeQOwAwAAAAAAAAAAFAEsARQBCgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +;
      "AAAAAGMCmwIsAmMC0gIKA9IC0gJ5A+gDsAOwAzYBSgE2ASwBAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAJsC0gKbAtICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgEWARYB" +;
      "FgEAAAAAAAAAAAAAAAAAAAAAFgEWARYBFgH0AfQB9AH0AdIC0gKbAtIC9AEsAvQB9AEAAAAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYBFgEWARYBFgFNARYBTQFjAdoBYwHaASwCLAIsAiwC" +;
      "LAIsAiwCLAJ5A3kDeQN5A5sC0gKbAtIC3gAWAd4AFgFNAU0BTQFNAU0BTQFNAU0BhQGFAYUBhQFI" +;
      "AkgCSAJIAhYBFgEWARYBTQFNAU0BTQEWARYBFgEWARYBFgEWARYBLAIsAiwCLAIsAiwCLAIsAiwC" +;
      "LAIsAiwCLAIsAiwCLAIsAiwCLAIsAiwCLAIsAiwCLAIsAiwCLAIsAiwCLAIsAiwCLAIsAiwCLAIs" +;
      "AiwCLAIWAU0BFgFNARYBTQEWAU0BSAJIAkgCSAJIAkgCSAJIAkgCSAJIAkgCLAJjAiwCYwL3A88D" +;
      "9wPPA5sC0gKbAtICmwLSApsC0gLSAtIC0gLSAtIC0gLSAtICmwKbApsCmwJjAmMCYwJjAgoDCgMK" +;
      "AwoD0gLSAtIC0gIWARYBFgEWAfQBLAL0ASwCmwLSApsC0gIsAmMCLAJjAkEDQQNBA0ED0gLSAtIC" +;
      "0gIKAwoDCgMKA5sCmwKbApsCCgMKAwoDCgPSAtIC0gLSApsCmwKbApsCYwJjAmMCYwLSAtIC0gLS" +;
      "ApsCmwKbApsCsAOwA7ADsAObApsCmwKbApsCmwKbApsCYwJjAmMCYwIWAU0BFgFNARYBFgEWARYB" +;
      "FgFNARYBTQHVAUgC1QFIAiwCLAIsAiwC3gAWAd4AFgEsAiwCLAIsAiwCYwIsAmMC9AEsAvQBLAIs" +;
      "AmMCLAJjAiwCLAIsAiwCFgFNARYBTQEsAmMCLAJjAiwCYwIsAmMC3gAWAd4AFgHeABYB3gAWAfQB" +;
      "LAL0ASwC3gAWAd4AFgFBA3kDQQN5AywCYwIsAmMCLAJjAiwCYwIsAmMCLAJjAiwCYwIsAmMCTQGF" +;
      "AU0BhQH0ASwC9AEsAhYBTQEWAU0BLAJjAiwCYwL0ASwC9AEsAtICCgPSAgoD9AEsAvQBLAL0ASwC" +;
      "9AEsAvQB9AH0AfQBTgGFAU4BhQEEARgBBAEYAU4BhQFOAYUBSAJIAkgCSAIAAAAAAAAAAAAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE0BTQFNAU0BLAIsAiwCLAIsAiwCLAIsAqcA" +;
      "pwCnAKcALAIsAiwCLAIsAiwCLAIsAiwCLAIsAiwCLAIsAiwCLAK/AO4AvwDuAE0B9AFNAfQBLAIs" +;
      "AiwCLAJNAU0BTQFNAU0BTQFNAU0B9AFjAvQBYwL0AWMC9AFjAgAAAAAAAAAALAIsAiwCLAIsAiwC" +;
      "LAIsAiwCLAIsAiwCFgEWARYBFgEAAAAAAAAAABkCLAIZAiwCXgFeAV4BXgHeABYB3gAWAU0B9AFN" +;
      "AfQBTQH0AU0B9AEsAiwCLAIsAugD6APoA+gD6APoA+gD6AMAAAAAAAAAAGMCYwJjAmMCAAAAAAAA" +;
      "AABNAU0BTQFNAU0BTQFNAU0BTQFNAU0BTQFNAU0BTQFNAU0BTQFNAU0BTQFNAU0BTQFNAU0BTQFN" +;
      "AU0BTQFNAU0BAAAAAAAAAABNAU0BTQFNAU0BTQFNAU0BAAAAAAAAAABNAU0BTQFNAU0BTQFNAU0B" +;
      "TQFNAU0BTQHoA+gD6APoAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6APoA+gD6AMAAAAAAAAAAHIBcgFyAXIBAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAmMCLAJjAgoDCgMKAwoD6APoA+gD6ANtAW0B" +;
      "bQFtAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB5A3kDeQN5AwAAAAAA" +;
      "AAAAAAAAAAAAAAAAAAAAAAAAABYBFgEWARYBAAAAAAAAAAAAAAAAAAAAAN4AFgHeABYBYwJjAmMC" +;
      "YwKwA7ADsAOwA2MCYwJjAmMCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJY" +;
      "AlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgCWAJYAlgC" +;
      "WAJYAlgCWAJYAlgCWAJYAlgC" )
hbvpsup.prg5
STATIC FUNCTIONStrB64Decode( cString )
STATIC FUNCTION StrB64Decode( cString )
   LOCAL cResult

   LOCAL nLen
   LOCAL nGroupPos
   LOCAL nGroup
   LOCAL nCharPos
   LOCAL nDataLen
   LOCAL nData
  
   // ; remove white spaces, If any
   cString := StrTran( cString, Chr( 10 ), "" )
   cString := StrTran( cString, Chr( 13 ), "" )
   cString := StrTran( cString, Chr( 9 ), "" )
   cString := StrTran( cString, " ", "" )
   
   // ; The source must consists from groups with Len of 4 chars
   IF ( nLen := Len( cString ) ) % 4 != 0 
      RETURN "" // ; Bad Base64 string.
   ENDIF

   /*
   IF nLen > Int( MAXSTRINGLENGTH / 1.34 ) // ; Base64 is 1/3rd larger than source text.
      RETURN "" // ; Not enough memory to decode.
   ENDIF
   */

   cResult := ""
   
   // ; Now decode each group:
   FOR nGroupPos := 1 TO nLen STEP 4
     
      // ; Each data group encodes up To 3 actual bytes.
      nDataLen := 3
      nGroup := 0
     
      FOR nCharPos := 0 TO 3
        
         // ; Convert each character into 6 bits of data, And add it To
         // ; an integer For temporary storage.  If a character is a '=', there
         // ; is one fewer data byte.  (There can only be a maximum of 2 '=' In
         // ; the whole string.)
        
         nData := At( SubStr( cString, nGroupPos + nCharPos, 1 ), "=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ) - 2

         DO CASE
         CASE nData >= 0
            // ; Do nothing (for speed)
         CASE nData == -1
            nData := 0
            nDataLen--
         CASE nData == -2
            RETURN "" // ; Bad character In Base64 string.
         ENDCASE
        
         nGroup := 64 * nGroup + nData
      NEXT

      // ; Convert the 24 bits to 3 characters
      // ; and add nDataLen characters To out string
      cResult += Left( Chr( nGroup / 65536 ) +;          // ; bitwise AND 255, which is done by Chr() automatically
                       Chr( nGroup /   256 ) +;          // ; bitwise AND 255, which is done by Chr() automatically
                       Chr( nGroup         ), nDataLen ) // ; bitwise AND 255, which is done by Chr() automatically
   NEXT
  
   RETURN cResult
hbvpsup.prg107

Page url: http://www.yourdomain.com/help/index.html?hbvpdf.htm