#include "hbclass.ch"

#define HBXML_ERROR_NOT_LT        1
#define HBXML_ERROR_NOT_GT        2
#define HBXML_ERROR_WRONG_TAG_END 3
#define HBXML_ERROR_WRONG_END     4
#define HBXML_ERROR_WRONG_ENTITY  5
#define HBXML_ERROR_NOT_QUOTE     6
#define HBXML_ERROR_TERMINATION   7

#define HBXML_TYPE_TAG            0
#define HBXML_TYPE_SINGLE         1
#define HBXML_TYPE_COMMENT        2
#define HBXML_TYPE_CDATA          3
#define HBXML_TYPE_PI             4




#define STYLE_TEXT     0
#define STYLE_PARA     1
#define STYLE_TABLE    2

#define  P_FONT_NAME        1



STATIC xObj,xParent
STATIC cListSep:=";"


CLASS HOOWriter

   DATA cPath, cFileName, cTmpDir
   DATA oContent,oBody
   DATA aStyles INIT {}                    /*  { { name,nType,cFont,cAlign },... } */
   DATA oDefStyle
   DATA nColumns, aColumns


   METHOD New( cName)

   METHOD AddStyle( nType, oStyle )       /* nType: 0-text,1-para */

   METHOD AddPara( oStyle )
   METHOD AddTab()
   METHOD AddSpaces(n)
   METHOD AddText( oStyle )
   METHOD SetStyleDefault( oStyle )

   METHOD AddTable( cAlign,aCols )
   METHOD AddHeadRow( aCells )
   METHOD AddRow( aCells )
   METHOD AddCell( cText, oStyleCell )

   METHOD Save()

ENDCLASS


METHOD New(cFileName,cTmpDir) CLASS HOOWriter

   ::cTmpDir:=cTmpDir
   ::cPath := cTmpDir+"odt"+StrZero(ROUND(HB_Random(1,9999999999),0),10,0)
   ::cFileName:=cFileName

   ::oContent := HXMLDoc():New()

   ::oContent:Add( HXMLNode():New( "office:document-content",, { ;
           {"xmlns:office","urn:oasis:names:tc:opendocument:xmlns:office:1.0"},;
           {"xmlns:style","urn:oasis:names:tc:opendocument:xmlns:style:1.0"},;
           {"xmlns:text","urn:oasis:names:tc:opendocument:xmlns:text:1.0"},;
           {"xmlns:table","urn:oasis:names:tc:opendocument:xmlns:table:1.0"},;
           {"xmlns:draw","urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"},;
           {"xmlns:fo","urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"},;
           {"xmlns:xlink","http://www.w3.org/1999/xlink"},;
           {"xmlns:dc","http://purl.org/dc/elements/1.1/"},;
           {"xmlns:meta","urn:oasis:names:tc:opendocument:xmlns:meta:1.0"},;
           {"xmlns:number","urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"},;
           {"xmlns:svg","urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"},;
           {"xmlns:chart","urn:oasis:names:tc:opendocument:xmlns:chart:1.0"},;
           {"xmlns:dr3d","urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"},;
           {"xmlns:math","http://www.w3.org/1998/Math/MathML"},;
           {"xmlns:form","urn:oasis:names:tc:opendocument:xmlns:form:1.0"},;
           {"xmlns:script","urn:oasis:names:tc:opendocument:xmlns:script:1.0"},;
           {"xmlns:ooo","http://openoffice.org/2004/office"},;
           {"xmlns:ooow","http://openoffice.org/2004/writer"},;
           {"xmlns:oooc","http://openoffice.org/2004/calc"},;
           {"xmlns:dom","http://www.w3.org/2001/xml-events"},;
           {"xmlns:xforms","http://www.w3.org/2002/xforms"},;
           {"xmlns:xsd","http://www.w3.org/2001/XMLSchema"},;
           {"xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance"},;
           {"office:version","1.0"} } ) )
   ::oContent:aItems[1]:Add( HXMLNode():New( "office:scripts" ) ) //1
   ::oContent:aItems[1]:Add( HXMLNode():New( "office:font-face-decls" ) ) //2

   ::oContent:aItems[1]:Add( HXMLNode():New( "office:automatic-styles" ) ) //3
   ::oContent:aItems[1]:Add( HXMLNode():New( "office:body" ) ) //4
   ::oBody := ::oContent:aItems[1]:aItems[4]
   ::oBody:Add( HXMLNode():New( "office:text" ) )
   ::oBody := ::oBody:aItems[1]

Return Self

METHOD AddStyle( nType, oStyle ) CLASS HOOWriter
Local i, n := 1, oNode, aLen := Len( ::aStyles ), l

   IF oStyle:id == Nil

      oStyle:type := nType
      FOR i := 1 TO aLen
         IF ::aStyles[i]:type == nType
            n ++
            IF oStyle:Compare( ::aStyles[i] )
               oStyle:id := ::aStyles[i]:id
               Return oStyle:id
            ENDIF
         ENDIF
      NEXT

      oStyle:id   := Iif(nType==0,"T","P") + Ltrim(Str(n))
      Aadd( ::aStyles, __objClone( oStyle ) )

      IF nType == STYLE_TEXT
         oNode := HXMLNode():New( "style:style",, ;
             { {"style:name",oStyle:id}, {"style:family","text"} } )
      ELSE
         oNode := HXMLNode():New( "style:style",, ;
             { {"style:name",oStyle:id}, {"style:family","paragraph"}, ;
             {"style:parent-style-name","Standard"} } )
      ENDIF
      IF oStyle:BreakPage()
         oNode:Add( HXMLNode():New( "style:paragraph-properties",HBXML_TYPE_SINGLE, ;
          {{"fo:break-before","page"}} ) )
      ENDIF

      oNode:Add( HXMLNode():New( "style:text-properties",HBXML_TYPE_SINGLE, ;
          oStyle:CreateXML() ) )
      ::oContent:aItems[1]:aItems[3]:Add( oNode )
      IF !Empty( oStyle:aProp[P_FONT_NAME] )
         l := .T.
         FOR i := 1 TO Len( ::oContent:aItems[1]:aItems[2]:aItems )
            IF ::oContent:aItems[1]:aItems[2]:aItems[i]:GetAttribute("style:name") == oStyle:aProp[P_FONT_NAME]
               l := .F.
               EXIT
            ENDIF
         NEXT
         IF l
            oNode := HXMLNode():New( "style:font-face",, ;
                { {"style:name",oStyle:aProp[P_FONT_NAME]}, {"svg:font-family","'"+oStyle:aProp[P_FONT_NAME]+"'"} } )
            ::oContent:aItems[1]:aItems[2]:Add( oNode )
         ENDIF
      ENDIF

   ENDIF

Return oStyle


METHOD AddPara( oStyle ) CLASS HOOWriter
Local oPara, cStyle

   IF oStyle == Nil
      IF ::oDefStyle != Nil
         cStyle := ::oDefStyle:id
      ELSE
         cStyle := "Standard"
      ENDIF
   ELSE
      ::AddStyle( STYLE_PARA,oStyle )
      cStyle := oStyle:id
   ENDIF

   oPara := ::oBody:Add( HXMLNode():New( "text:p",, ;
                  { {"text:style-name",cStyle} } ) )

Return oPara

METHOD AddTab() CLASS HOOWriter
Local oBody := ::oBody, oPara

   IF !Empty( oBody:aItems ) .AND. Valtype( oPara := Atail( oBody:aItems ) ) != "C" ;
        .AND. oPara:title == "text:p"
   ELSE
      oPara := ::AddPara()
   ENDIF

   oPara:Add( HXMLNode():New( "text:tab-stop", HBXML_TYPE_SINGLE ) )

Return Nil

METHOD AddSpaces( n ) CLASS HOOWriter
Local oBody := ::oBody, oPara

   IF !Empty( oBody:aItems ) .AND. Valtype( oPara := Atail( oBody:aItems ) ) != "C" ;
        .AND. oPara:title == "text:p"
   ELSE
      oPara := ::AddPara()
   ENDIF

   oPara:Add( HXMLNode():New( "text:s", HBXML_TYPE_SINGLE, { {"text:c",Ltrim(Str(n))} } ) )

Return Nil

METHOD AddText( cText,oStyle ) CLASS HOOWriter
Local oBody := ::oBody, oPara

   IF !Empty( oBody:aItems ) .AND. Valtype( oPara := Atail( oBody:aItems ) ) != "C" ;
        .AND. oPara:title == "text:p"
   ELSE
      oPara := ::AddPara()
   ENDIF

   IF oStyle != Nil
      ::AddStyle( STYLE_TEXT,oStyle )
      oPara := oPara:Add( HXMLNode():New( "text:span",,{ {"text:style-name",oStyle:id} } ) )
   ENDIF
   oPara:Add( cText )

Return Nil


METHOD SetStyleDefault( oStyle ) CLASS HOOWriter

   ::AddStyle( STYLE_PARA, oStyle )
   ::cDefStyle := __ObjClone( oStyle )

Return Nil


METHOD AddTable( cAlign,aCols ) CLASS HOOWriter
Local oStyleT, i, j, nWidthT, aAttrT := {}
Local oStyleC, nWidthC, cNameLastCell, aAttrC
Local oTable, aColsInfo, lColsInfo := .F., oStyleTable
Local cNameC

   cAlign := Iif( cAlign==Nil,"J",Upper(cAlign) )
   i := 1
   IF !Empty( ::aStyles )
      Aeval( ::aStyles, {|o|Iif(o:type==STYLE_TABLE,i:=i+1,.T.)} )
   ENDIF
   oStyleTable := HOOStyle():New()
   oStyleTable:id := "Table"+Ltrim(Str(i))
   oStyleTable:type := STYLE_TABLE
   ::nColumns := Len(aCols)
   ::aColumns := Nil
   Aadd( ::aStyles, oStyleTable )

   /* Adding the table to the list of "automatic-styles" */
   oStyleT := HXMLNode():New( "style:style",, ;
       { {"style:name",oStyleTable:id}, {"style:family","table"} } )
   ::oContent:aItems[1]:aItems[3]:Add( oStyleT )

   /* Adding the table to the body */
   oTable := Atail( ::oContent:aItems[1]:aItems ):Add( HXMLNode():New( "table:table",, ;
                  { {"table:name",oStyleTable:id},{"table:style-name",oStyleTable:id} } ) )

   /* going through the columns descriptions */
   nWidthT := 0
   FOR j := 1 TO Len( aCols )
      IF Valtype( aCols[j] ) == "A"
         nWidthC := aCols[j,1]
         lColsInfo := .T.
      ELSE
         nWidthC := aCols[j]
      ENDIF
      nWidthT += nWidthC
   NEXT

   IF lColsInfo
      /*  Create the columns info array */
      aColsInfo := {}
      FOR j := 1 TO Len( aCols )
         IF Valtype( aCols[j] ) == "A" .AND. Len( aCols[j] ) > 1
            Aadd( aColsInfo, ::AddStyle( STYLE_PARA, aCols[j,2] ):id )
         ELSE
            Aadd( aColsInfo,Nil )
         ENDIF
      NEXT
      ::aColumns := aColsInfo
   ENDIF
   FOR j := 1 TO Len( aCols )

      nWidthC := Iif( Valtype( aCols[j] )=="A",aCols[j,1],aCols[j] )
      FOR i := j+1 TO Len( aCols )
         IF nWidthC != Iif( Valtype( aCols[i] )=="A",aCols[i,1],aCols[i] ) // ;
              // .OR. ( lColsInfo .AND. !( aColsInfo[i] == aColsInfo[j] ) )
            EXIT
         ENDIF
      NEXT
      i := i - j

      /* Adding the column to the list of "automatic-styles" */
      cNameC := oStyleTable:id+"."+Chr(j+64)
      oStyleC := HXMLNode():New( "style:style",, ;
         { {"style:name",cNameC}, {"style:family","table-column"} } )
      oStyleC:Add( HXMLNode():New( "style:properties",HBXML_TYPE_SINGLE, ;
         { {"style:column-width",Ltrim(Str(nWidthC,10,2))+"cm"} } ) )
      ::oContent:aItems[1]:aItems[3]:Add( oStyleC )

      /* Adding the column to the table body */
      aAttrC := { {"table:style-name",cNameC} }
      IF i > 1
         Aadd( aAttrC, {"table:number-columns-repeated",Ltrim(Str(i))} )
         j += i-1
      ENDIF
      oTable:Add( HXMLNode():New( "table:table-column",HBXML_TYPE_SINGLE,aAttrC ) )
   NEXT

   /* Adding the cells to the list of "automatic-styles" */
   cNameLastCell := oStyleTable:id + "." + Chr( Len(aCols)+64 )
   oStyleC := HXMLNode():New( "style:style",, ;
      { {"style:name",oStyleTable:id+".A1"}, {"style:family","table-cell"} } )
   oStyleC:Add( HXMLNode():New( "style:properties",HBXML_TYPE_SINGLE, ;
      { {"fo:padding","0.097cm"}, {"fo:border-left","0.002cm solid #000000"}, ;
      {"fo:border-right","none"}, {"fo:border-top","0.002cm solid #000000"}, ;
      {"fo:border-bottom","0.002cm solid #000000"} } ) )
   ::oContent:aItems[1]:aItems[3]:Add( oStyleC )

   oStyleC := HXMLNode():New( "style:style",, ;
      { {"style:name",oStyleTable:id+".A2"}, {"style:family","table-cell"} } )
   oStyleC:Add( HXMLNode():New( "style:properties",HBXML_TYPE_SINGLE, ;
      { {"fo:padding","0.097cm"}, {"fo:border-left","0.002cm solid #000000"}, ;
      {"fo:border-right","none"}, {"fo:border-top","none"}, ;
      {"fo:border-bottom","0.002cm solid #000000"} } ) )
   ::oContent:aItems[1]:aItems[3]:Add( oStyleC )

   oStyleC := HXMLNode():New( "style:style",, ;
      { {"style:name",cNameLastCell+"1"}, {"style:family","table-cell"} } )
   oStyleC:Add( HXMLNode():New( "style:properties",HBXML_TYPE_SINGLE, ;
      { {"fo:padding","0.097cm"}, {"fo:border","0.002cm solid #000000"} } ) )
   ::oContent:aItems[1]:aItems[3]:Add( oStyleC )

   oStyleC := HXMLNode():New( "style:style",, ;
      { {"style:name",cNameLastCell+"2"}, {"style:family","table-cell"} } )
   oStyleC:Add( HXMLNode():New( "style:properties",HBXML_TYPE_SINGLE, ;
      { {"fo:padding","0.097cm"}, {"fo:border-left","0.002cm solid #000000"}, ;
      {"fo:border-right","0.002cm solid #000000"}, {"fo:border-top","none"}, ;
      {"fo:border-bottom","0.002cm solid #000000"} } ) )
   ::oContent:aItems[1]:aItems[3]:Add( oStyleC )

   /* Updating the table style property */
   IF cAlign != "J"
      Aadd( aAttrT, {"style:width",Ltrim(Str(nWidthT,10,2))+"cm"} )
   ENDIF
   Aadd( aAttrT, {"table:align",Iif(cAlign=="C","center", ;
                 Iif(cAlign=="R","end",Iif(cAlign=="J","marjins","start")))} )
   oStyleT:Add( HXMLNode():New( "style:properties",HBXML_TYPE_SINGLE, aAttrT ) )

   oTable:Add( HXMLNode():New( "table:table-header-rows" ) )
  
Return oTable


METHOD AddHeadRow( aCells ) CLASS HOOWriter
Local oBody := ::oBody, oTable, oRow
Local i, aLen

   IF !Empty( oBody:aItems ) .AND. Valtype( oTable := Atail( oBody:aItems ) ) != "C" ;
        .AND. oTable:title == "table:table"
      oTable := Atail( oTable:aItems )
      IF oTable:title == "table:table-header-rows"
         oRow := oTable:Add( HXMLNode():New( "table:table-row" ) )
         IF aCells != Nil
            FOR i := 1 TO Len( aCells )
               IF ValType( aCells[i] ) == "A"
                  aLen := Len( aCells[i] )
                  ::AddCell( aCells[i,1], Iif(aLen>1,aCells[i,2],Nil) )
               ELSE
                  ::AddCell( aCells[i] )
               ENDIF
            NEXT
         ENDIF
      ENDIF
   ENDIF

Return oRow

METHOD AddRow( aCells ) CLASS HOOWriter
Local oBody := ::oBody, oTable, oRow
Local i, aLen

   IF !Empty( oBody:aItems ) .AND. Valtype( oTable := Atail( oBody:aItems ) ) != "C" ;
        .AND. oTable:title == "table:table"
      oRow := oTable:Add( HXMLNode():New( "table:table-row" ) )
      IF aCells != Nil
         FOR i := 1 TO Len( aCells )
            IF ValType( aCells[i] ) == "A"
               aLen := Len( aCells[i] )
               ::AddCell( aCells[i,1], Iif(aLen>1,aCells[i,2],Nil) )
            ELSE
               ::AddCell( aCells[i] )
            ENDIF
         NEXT
      ENDIF
   ENDIF

Return oRow

METHOD AddCell( cText, oStyleCell ) CLASS HOOWriter
Local oBody := ::oBody
Local oTable, oRow, oCell, cNameT, lHead := .F., nColsAll, nCol
Local oStyleTable, cStyleCell, cNameCell

   IF !Empty( oBody:aItems ) .AND. Valtype( oTable := Atail( oBody:aItems ) ) != "C" ;
        .AND. oTable:title == "table:table"

      cNameT := oTable:GetAttribute( "table:name" )
      oStyleTable := ::aStyles[ Ascan( ::aStyles, {|o|o:id==cNameT} ) ]
      nColsAll := ::nColumns
      oRow := Atail( oTable:aItems )
      IF oRow:title == "table:table-header-rows"
         lHead := .T.
         IF Empty( oRow:aItems )
            oRow := oRow:Add( HXMLNode():New( "table:table-row" ) )
         ELSE
            oRow := Atail( oRow:aItems )
         ENDIF
      ENDIF
      nCol := Len(oRow:aItems) + 1
      IF nCol > nColsAll
         Return Nil
      ENDIF

      IF oStyleCell == Nil
         IF !lHead .AND. ::aColumns != Nil .AND. ::aColumns[nCol] != Nil
            cStyleCell := ::aColumns[nCol]
         ELSE
            cStyleCell := Iif(lHead,"Table Heading","Table Contents")
         ENDIF
      ELSE
         cStyleCell := oStyleCell:id
      ENDIF

      cNameCell := cNameT + "." + ;
           Iif( nCol<nColsAll,"A",Chr(nColsAll+64) ) + Iif( lHead,"1","2" )
      oCell := oRow:Add( HXMLNode():New( "table:table-cell",, ;
           { {"table:style-name",cNameCell}, {"table:value-type","string"} } ) )
      oCell:Add( HXMLNode():New( "text:p",, ;
        { {"text:style-name",cStyleCell} }, ;
        cText ) )
      
   ENDIF

Return Nil


METHOD Save(lShow) CLASS HOOWriter
Local oDoc,aFiles:={}
LOCAL cSep := set( _SET_DIRSEPARATOR )
Local handle, cDir,cFullDir
Local i, oStyle, aAttr
LOCAL cOldPath := DirName(),cOldDisk := DiskName()
IF EMPTY(cSep)
   cSep:="\"
ENDIF



   cDir :=::cPath

   IF Makedir( cDir ) != 0
      EraseDir(cDir)
   ENDIF

   IF MakeDir1( cDir + cSep + "META-INF" ) != 0
      EraseDir( cDir + cSep + "META-INF")
   ENDIF

   oDoc := HXMLDoc():New()
   oDoc:Add( HXMLNode():New( "manifest:manifest",,;
   { {"xmlns:manifest","urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"} } ) )

   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type","application/vnd.oasis.opendocument.text"},;
           {"manifest:full-path","/"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type",""},;
           {"manifest:full-path","Configurations2/statusbar/"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type",""},;
           {"manifest:full-path","Configurations2/accelerator/current.xml"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type",""},;
           {"manifest:full-path","Configurations2/accelerator/"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type",""},;
           {"manifest:full-path","Configurations2/floater/"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type",""},;
           {"manifest:full-path","Configurations2/popupmenu/"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type",""},;
           {"manifest:full-path","Configurations2/progressbar/"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type",""},;
           {"manifest:full-path","Configurations2/menubar/"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type",""},;
           {"manifest:full-path","Configurations2/toolbar/"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type",""},;
           {"manifest:full-path","Configurations2/images/Bitmaps/"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type",""},;
           {"manifest:full-path","Configurations2/images/"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type","application/vnd.sun.xml.ui.configuration"},;
           {"manifest:full-path","Configurations2/"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type","text/xml"},;
           {"manifest:full-path","content.xml"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type","text/xml"},;
           {"manifest:full-path","styles.xml"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type","text/xml"},;
           {"manifest:full-path","meta.xml"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type",""},;
           {"manifest:full-path","Thumbnails/thumbnail.png"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type",""},;
           {"manifest:full-path","Thumbnails/"} } ) )
   oDoc:aItems[1]:Add( HXMLNode():New( "manifest:file-entry", HBXML_TYPE_SINGLE, ;
         { {"manifest:media-type","text/xml"},;
           {"manifest:full-path","settings.xml"} } ) )
   FErase(cDir+cSep+"META-INF\manifest.xml")
   oDoc:Save(cDir+cSep+"META-INF\manifest.xml" )


   oDoc := HXMLDoc():New()
   oDoc:Add( HXMLNode():New( "office:document-meta",, {       ;
           {"xmlns:office","urn:oasis:names:tc:opendocument:xmlns:office:1.0"}, ;
           {"xmlns:xlink","http://www.w3.org/1999/xlink" },      ;
           {"xmlns:dc","http://purl.org/dc/elements/1.1/"},      ;
           {"xmlns:meta","urn:oasis:names:tc:opendocument:xmlns:meta:1.0"},     ;
           {"xmlns:ooo","http://openoffice.org/2004/office"},     ;
           {"office:version","1.0"} } ) )

   oDoc:aItems[1]:Add( HXMLNode():New( "office:meta" ) )

   oDoc:Save( cDir + cSep + "meta.xml" )

   handle := FCreate(cDir+cSep+"mimetype" )
   FWrite( handle,"application/vnd.oasis.opendocument.text" )
   FClose( handle )

   ::oContent:Save( cDir + cSep + "content.xml" )
    


//   AADD(aFiles,cDir + cSep + "content.xml"

    cFullDir:=TruePath(cDir)



    
   aFiles:=DirectoryRecurse(cFullDir+cSep+"*","D")

    AEVAL(aFiles,{|x,i|aFiles[i]:=SUBSTR(x[1],AT(UPPER(cDir),UPPER(x[1]))+LEN(cDir)+1)})


   FERASE(::cFileName)

   IF FILE(::cFileName)
      SayError("Не могу записать "+::cFileName)
   ELSE

      IF (i := AT( ':', cFullDir ) ) <> 0
         DISKCHANGE( LEFT( cFullDir, i-1 ) )
      ENDIF
      DIRCHANGE(cFullDir)

      HB_ZIPFILE(::cFileName,aFiles,,,,,.T.)    

      DISKCHANGE( cOldDisk )
      DIRCHANGE( cOldPath )
   ENDIF


   altd()

   IF !EMPTY(lShow)
      ViewWriter(::cFileName,.T.)
   ENDIF
   altd()
   EraseDir(cFullDir)
  //запись в файл дочистки, так как архиватор не отпускает папку
   EraseList(cFullDir,::cTmpDir) 
RETURN .T.



FUNCTION ViewWriter(cFile,lAsTemplate)
LOCAL oApp,oDeskTop,oDoc
LOCAL aProp:={}

TRY
   oApp := CreateObject( "com.sun.star.ServiceManager" )
CATCH
   ALERT( "OOWriter не доступен!" )
   ClearTotRepStatic()
   RETURN .F.
END

oDeskTop:=oApp:createInstance("com.sun.star.frame.Desktop")

IF !EMPTY(lAsTemplate)
   aProp:=ARRAY(1)
   oProperty:=oApp:Bridge_GetStruct("com.sun.star.beans.PropertyValue")  
   oProperty:Name:= "AsTemplate"  
   oProperty:Value:= .T.  
   aProp[1]:=oProperty
ENDIF

oDoc:=oDeskTop:LoadComponentFromURL(ConvertToURL(cFile),"_blank", 0,aProp) 
RETURN oDoc


STATIC FUNCTION xFix(o)
xObj:=o
RETURN xObj

STATIC FUNCTION xAdd(cName,aa,v)
RETURN xObj:Add(HXMLNode():New(cName,,aa,v))

STATIC FUNCTION xRight()
xParent:=xObj
xObj:=ATAIL(xObj:aItems)
RETURN xObj

STATIC FUNCTION xLeft()
xObj:=xParent
RETURN xObj

