[Libreoffice-commits] core.git: sw/qa sw/source

Umesh Kadam umesh.kadam at synerzip.com
Thu May 22 00:32:18 PDT 2014


 sw/qa/extras/ooxmlexport/data/ShapeOverlappingWithSdt.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport.cxx                   |    9 +
 sw/source/filter/ww8/attributeoutputbase.hxx               |    9 +
 sw/source/filter/ww8/docxattributeoutput.cxx               |   69 +++++++++++
 sw/source/filter/ww8/docxattributeoutput.hxx               |    6 +
 sw/source/filter/ww8/wrtw8nds.cxx                          |   78 +++++++++++--
 sw/source/filter/ww8/wrtww8.hxx                            |   13 ++
 7 files changed, 174 insertions(+), 10 deletions(-)

New commits:
commit 80fd9fb7209cfd5c0622ee99d59e42e6db32f021
Author: Umesh Kadam <umesh.kadam at synerzip.com>
Date:   Thu May 15 23:02:34 2014 +0530

    fdo#78333 : SdtContent and a Shape overlapping causes corruption
    
    - Normally if there is a case where text/shape is overlapped with (another)
       shape then LO used to write the text and the AlternateContent in the same run.
    - This is supported in MSO and there is no visual difference.
    - But in case if the SdtContent(with text) is overlapped with the Shape then LO
       processes sdtContent as a text and ends up putting the alternateContent and the
       text in a single run. Ultimately it includes the entire run in a SdtContent,
       which is incorrect.
    - The fix checks for the aforementioned scenario and puts them in a different run
       and also restricts the sdtContent being written in an invalid AlternateContent.
    
    Change-Id: I36f4cdb1b583523dd8f717ae094bdf09c7a61f62
    Reviewed-on: https://gerrit.libreoffice.org/9374
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/sw/qa/extras/ooxmlexport/data/ShapeOverlappingWithSdt.docx b/sw/qa/extras/ooxmlexport/data/ShapeOverlappingWithSdt.docx
new file mode 100644
index 0000000..e1ec074
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/ShapeOverlappingWithSdt.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
index 7a69e67..16d13a2 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
@@ -2052,6 +2052,15 @@ DECLARE_OOXMLEXPORT_TEST(testFileOpenInputOutputError,"floatingtbl_with_formula.
       assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:pPr/w:pStyle", "val", "Normal");
 }
 
+DECLARE_OOXMLEXPORT_TEST(testSdtAndShapeOverlapping,"ShapeOverlappingWithSdt.docx")
+{
+     xmlDocPtr pXmlDoc = parseExport("word/document.xml");
+     if (!pXmlDoc)
+         return;
+      assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r[1]/mc:AlternateContent");
+      assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt[1]/w:sdtContent[1]/w:r[1]/w:t[1]");
+}
+
 DECLARE_OOXMLEXPORT_TEST(testRelorientation, "relorientation.docx")
 {
     uno::Reference<drawing::XShape> xShape = getShape(1);
diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx b/sw/source/filter/ww8/attributeoutputbase.hxx
index 5a25c86..d2df9c0 100644
--- a/sw/source/filter/ww8/attributeoutputbase.hxx
+++ b/sw/source/filter/ww8/attributeoutputbase.hxx
@@ -309,6 +309,15 @@ public:
     /// Has different headers/footers for the title page.
     virtual void SectionTitlePage() = 0;
 
+    /// If the node has an anchor linked.
+    virtual void SetAnchorIsLinkedToNode( bool /*bAnchorLinkedToNode*/){};
+
+    /// Is processing of fly postponed ?
+    virtual bool IsFlyProcessingPostponed(){ return false; };
+
+    /// Reset the flag for FlyProcessing
+    virtual void ResetFlyProcessingFlag(){};
+
     /// Description of the page borders.
     virtual void SectionPageBorders( const SwFrmFmt* pFmt, const SwFrmFmt* pFirstPageFmt ) = 0;
 
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 96602c3..fb5933d 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -287,6 +287,20 @@ void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pText
     m_bIsFirstParagraph = false;
 }
 
+static void lcl_deleteAndResetTheLists( ::sax_fastparser::FastAttributeList* &pSdtPrTokenChildren, ::sax_fastparser::FastAttributeList* &pSdtPrDataBindingAttrs)
+{
+    if( pSdtPrTokenChildren )
+    {
+        delete pSdtPrTokenChildren ;
+        pSdtPrTokenChildren = NULL;
+    }
+    if( pSdtPrDataBindingAttrs )
+    {
+        delete pSdtPrDataBindingAttrs;
+        pSdtPrDataBindingAttrs = NULL;
+    }
+}
+
 void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner )
 {
     // write the paragraph properties + the run, already in the correct order
@@ -382,8 +396,16 @@ void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pT
     }
 
     m_pSerializer->endElementNS( XML_w, XML_p );
+    if( !m_bAnchorLinkedToNode )
+        WriteSdtBlock( m_nParagraphSdtPrToken, m_pParagraphSdtPrTokenChildren, m_pParagraphSdtPrDataBindingAttrs );
+    else
+    {
+        //These should be written out to the actual Node and not to the anchor.
+        //Clear them as they will be repopulated when the node is processed.
+        m_nParagraphSdtPrToken = 0;
+        lcl_deleteAndResetTheLists( m_pParagraphSdtPrTokenChildren, m_pParagraphSdtPrDataBindingAttrs );
+    }
 
-    WriteSdtBlock( m_nParagraphSdtPrToken, m_pParagraphSdtPrTokenChildren, m_pParagraphSdtPrDataBindingAttrs );
     //sdtcontent is written so Set m_bParagraphHasDrawing to false
     m_rExport.SdrExporter().setParagraphHasDrawing( false );
     m_bRunTextIsOn = false;
@@ -701,6 +723,21 @@ void DocxAttributeOutput::EndParagraphProperties( const SfxItemSet* pParagraphMa
     m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
 }
 
+void DocxAttributeOutput::SetAnchorIsLinkedToNode( bool bAnchorLinkedToNode )
+{
+    m_bAnchorLinkedToNode = bAnchorLinkedToNode ;
+}
+
+void DocxAttributeOutput::ResetFlyProcessingFlag()
+{
+    m_bPostponedProcessingFly = false ;
+}
+
+bool DocxAttributeOutput::IsFlyProcessingPostponed()
+{
+    return m_bPostponedProcessingFly;
+}
+
 void DocxAttributeOutput::StartRun( const SwRedlineData* pRedlineData, bool /*bSingleEmptyRun*/ )
 {
     // Don't start redline data here, possibly there is a hyperlink later, and
@@ -858,7 +895,15 @@ void DocxAttributeOutput::EndRun()
     EndRedline( m_pRedlineData );
 
     // enclose in a sdt block, if necessary
-    WriteSdtBlock( m_nRunSdtPrToken, m_pRunSdtPrTokenChildren, m_pRunSdtPrDataBindingAttrs );
+    if ( !m_bAnchorLinkedToNode )
+        WriteSdtBlock( m_nRunSdtPrToken, m_pRunSdtPrTokenChildren, m_pRunSdtPrDataBindingAttrs );
+    else
+    {
+        //These should be written out to the actual Node and not to the anchor.
+        //Clear them as they will be repopulated when the node is processed.
+        m_nRunSdtPrToken = 0;
+        lcl_deleteAndResetTheLists( m_pRunSdtPrTokenChildren, m_pRunSdtPrDataBindingAttrs );
+    }
     m_pSerializer->mergeTopMarks();
 
     WritePostponedMath();
@@ -4270,9 +4315,13 @@ void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Po
                 if ( pGrfNode )
                 {
                     if( m_postponedGraphic == NULL )
+                    {
+                        m_bPostponedProcessingFly = false ;
                         FlyFrameGraphic( pGrfNode, rFrame.GetLayoutSize(), 0, 0, pSdrObj);
+                    }
                     else // we are writing out attributes, but w:drawing should not be inside w:rPr,
                     {    // so write it out later
+                        m_bPostponedProcessingFly = true ;
                         m_postponedGraphic->push_back( PostponedGraphic( pGrfNode, rFrame.GetLayoutSize(), 0, 0, pSdrObj));
                     }
                 }
@@ -4286,9 +4335,13 @@ void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Po
                     if ( IsDiagram( pSdrObj ) )
                     {
                         if ( m_postponedDiagram == NULL )
+                        {
+                            m_bPostponedProcessingFly = false ;
                             m_rExport.SdrExporter().writeDiagram( pSdrObj, rFrame.GetFrmFmt(), m_anchorId++);
+                        }
                         else // we are writing out attributes, but w:drawing should not be inside w:rPr,
                         {    // so write it out later
+                            m_bPostponedProcessingFly = true ;
                             m_postponedDiagram->push_back( PostponedDiagram( pSdrObj, &(rFrame.GetFrmFmt()) ));
                         }
                     }
@@ -4302,6 +4355,8 @@ void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Po
                                 m_rExport.SdrExporter().writeDMLDrawing( pSdrObj, &rFrame.GetFrmFmt(), m_anchorId++);
                             else
                                 m_rExport.SdrExporter().writeDMLAndVMLDrawing( pSdrObj, rFrame.GetFrmFmt(), rNdTopLeft, m_anchorId++);
+
+                            m_bPostponedProcessingFly = false ;
                         }
                         // IsAlternateContentChoiceOpen() : check is to ensure that only one object is getting added. Without this check, plus one obejct gets added
                         // m_bParagraphFrameOpen : Check if the frame is open.
@@ -4311,8 +4366,11 @@ void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Po
                             m_postponedCustomShape->push_back(PostponedDrawing(pSdrObj, &(rFrame.GetFrmFmt()), &rNdTopLeft));
                         }
                         else
+                        {
                             // we are writing out attributes, but w:drawing should not be inside w:rPr, so write it out later
+                            m_bPostponedProcessingFly = true ;
                             m_postponedDMLDrawing->push_back(PostponedDrawing(pSdrObj, &(rFrame.GetFrmFmt()), &rNdTopLeft));
+                        }
                     }
                 }
             }
@@ -4335,7 +4393,10 @@ void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Po
                 }
 
                 if( !bDuplicate )
+                {
+                    m_bPostponedProcessingFly = true ;
                     m_aFramesOfParagraph.push_back(sw::Frame(rFrame));
+                }
             }
             break;
         case sw::Frame::eOle:
@@ -4347,6 +4408,7 @@ void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Po
                     SwNodeIndex aIdx(*rFrmFmt.GetCntnt().GetCntntIdx(), 1);
                     SwOLENode& rOLENd = *aIdx.GetNode().GetOLENode();
                     WriteOLE2Obj( pSdrObj, rOLENd, rFrame.GetLayoutSize(), dynamic_cast<const SwFlyFrmFmt*>( &rFrmFmt ));
+                    m_bPostponedProcessingFly = false ;
                 }
             }
             break;
@@ -4354,6 +4416,7 @@ void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Po
             {
                 const SdrObject* pObject = rFrame.GetFrmFmt().FindRealSdrObject();
                 m_aPostponedFormControls.push_back(pObject);
+                m_bPostponedProcessingFly = true ;
             }
             break;
         default:
@@ -7432,6 +7495,7 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri
       m_bOpenedSectPr( false ),
       m_bRunTextIsOn( false ),
       m_bWritingHeaderFooter( false ),
+      m_bAnchorLinkedToNode(false),
       m_sFieldBkm( ),
       m_nNextBookmarkId( 0 ),
       m_nNextAnnotationMarkId( 0 ),
@@ -7440,6 +7504,7 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri
       m_bParagraphFrameOpen( false ),
       m_bIsFirstParagraph( true ),
       m_bAlternateContentChoiceOpen( false ),
+      m_bPostponedProcessingFly( false ),
       m_nColBreakStatus( COLBRK_NONE ),
       m_nTextFrameLevel( 0 ),
       m_closeHyperlinkInThisRun( false ),
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index 2c0472d..ea609a6 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -210,6 +210,10 @@ public:
     /// End of the tag that encloses the run.
     void EndRedline( const SwRedlineData * pRedlineData );
 
+    virtual void SetAnchorIsLinkedToNode( bool bAnchorLinkedToNode = false ) SAL_OVERRIDE;
+    virtual bool IsFlyProcessingPostponed() SAL_OVERRIDE;
+    virtual void ResetFlyProcessingFlag() SAL_OVERRIDE;
+
     virtual void FormatDrop( const SwTxtNode& rNode, const SwFmtDrop& rSwFmtDrop, sal_uInt16 nStyle, ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner ) SAL_OVERRIDE;
 
     /// Output style.
@@ -726,6 +730,7 @@ private:
 
     /// Flag indicating that the header \ footer are being written
     bool m_bWritingHeaderFooter;
+    bool m_bAnchorLinkedToNode;
 
     /// Field data to remember in the text run
     std::vector< FieldInfos > m_Fields;
@@ -767,6 +772,7 @@ private:
     bool m_bParagraphFrameOpen;
     bool m_bIsFirstParagraph;
     bool m_bAlternateContentChoiceOpen;
+    bool m_bPostponedProcessingFly;
 
     // Remember that a column break has to be opened at the
     // beginning of the next paragraph
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
index 1601997..e176259 100644
--- a/sw/source/filter/ww8/wrtw8nds.cxx
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -540,7 +540,26 @@ bool SwWW8AttrIter::IsWatermarkFrame()
     return false;
 }
 
-void SwWW8AttrIter::OutFlys(sal_Int32 nSwPos)
+bool SwWW8AttrIter::IsAnchorLinkedToThisNode( sal_uLong nNodePos )
+{
+    sw::FrameIter aTmpFlyIter = maFlyIter ;
+
+    while ( aTmpFlyIter != maFlyFrms.end() )
+    {
+        const SwPosition &rAnchor  = maFlyIter->GetPosition();
+        sal_uLong nAnchorPos = rAnchor.nNode.GetIndex();
+        /* if current node position and the anchor position are the same
+           then the frame anchor is linked to this node
+        */
+        if ( nAnchorPos == nNodePos )
+            return true ;
+
+        ++aTmpFlyIter;
+    }
+    return false ;
+}
+
+sal_Int16 SwWW8AttrIter::OutFlys(sal_Int32 nSwPos)
 {
     /*
      #i2916#
@@ -553,7 +572,7 @@ void SwWW8AttrIter::OutFlys(sal_Int32 nSwPos)
         const sal_Int32 nPos = rAnchor.nContent.GetIndex();
 
         if ( nPos != nSwPos )
-            break;
+            return FLY_NOT_PROCESSED ; //We havent processed the fly
 
         const SdrObject* pSdrObj = maFlyIter->GetFrmFmt().FindRealSdrObject();
 
@@ -585,6 +604,7 @@ void SwWW8AttrIter::OutFlys(sal_Int32 nSwPos)
         }
         ++maFlyIter;
     }
+    return ( m_rExport.AttrOutput().IsFlyProcessingPostponed() ? FLY_POSTPONED : FLY_PROCESSED ) ;
 }
 
 bool SwWW8AttrIter::IsTxtAttr( sal_Int32 nSwPos )
@@ -2017,6 +2037,7 @@ void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode )
     sal_Int32 const nEnd = aStr.getLength();
     bool bRedlineAtEnd = false;
     sal_Int32 nOpenAttrWithRange = 0;
+    OUString aStringForImage("\001");
 
     ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner;
     if ( pTextNodeInfo.get() != NULL )
@@ -2024,18 +2045,33 @@ void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode )
 
     do {
         const SwRedlineData* pRedlineData = aAttrIter.GetRunLevelRedline( nAktPos );
+        sal_Int16 nStateOfFlyFrame   = 0;
+        bool bPostponeWritingText    = false ;
+        OUString aSavedSnippet ;
 
         sal_Int32 nNextAttr = GetNextPos( &aAttrIter, rNode, nAktPos );
         // Is this the only run in this paragraph and it's empty?
         bool bSingleEmptyRun = nAktPos == 0 && nNextAttr == 0;
         AttrOutput().StartRun( pRedlineData, bSingleEmptyRun );
+
         if( nTxtTyp == TXT_FTN || nTxtTyp == TXT_EDN )
             AttrOutput().FootnoteEndnoteRefTag();
 
         if( nNextAttr > nEnd )
             nNextAttr = nEnd;
 
-        aAttrIter.OutFlys( nAktPos );
+        /*
+            1) If there is a text node and an overlapping anchor, then write them in two different
+            runs and not as part of the same run.
+            2) Ensure that it is a text node and not in a fly.
+            3) If the anchor is associated with a text node with empty text then we ignore.
+        */
+        if ( rNode.IsTxtNode() && aStr != aStringForImage && aStr != ""  &&
+            !rNode.GetFlyFmt() && aAttrIter.IsAnchorLinkedToThisNode(rNode.GetIndex()))
+            bPostponeWritingText = true ;
+
+        nStateOfFlyFrame = aAttrIter.OutFlys( nAktPos );
+        AttrOutput().SetAnchorIsLinkedToNode( bPostponeWritingText && (FLY_POSTPONED != nStateOfFlyFrame) );
         // Append bookmarks in this range after flys, exclusive of final
         // position of this range
         AppendBookmarks( rNode, nAktPos, nNextAttr - nAktPos );
@@ -2152,7 +2188,17 @@ void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode )
                 if ( aSnippet[0] != 0x09 )
                     aSnippet = OUString( 0x09 ) + aSnippet;
             }
-            AttrOutput().RunText( aSnippet, eChrSet );
+
+            if ( bPostponeWritingText && ( FLY_POSTPONED != nStateOfFlyFrame ) )
+            {
+                bPostponeWritingText = true ;
+                aSavedSnippet = aSnippet ;
+            }
+            else
+            {
+                bPostponeWritingText = false ;
+                AttrOutput().RunText( aSnippet, eChrSet );
+            }
         }
 
         if ( aAttrIter.IsDropCap( nNextAttr ) )
@@ -2179,7 +2225,7 @@ void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode )
                 else
                 {
                     // insert final graphic anchors if any before CR
-                    aAttrIter.OutFlys( nEnd );
+                    nStateOfFlyFrame = aAttrIter.OutFlys( nEnd );
                     // insert final bookmarks if any before CR and after flys
                     AppendBookmarks( rNode, nEnd, 1 );
                     AppendAnnotationMarks( rNode, nEnd, 1 );
@@ -2228,7 +2274,7 @@ void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode )
             if ( bTxtAtr || bAttrWithRange || bRedlineAtEnd )
             {
                 // insert final graphic anchors if any before CR
-                aAttrIter.OutFlys( nEnd );
+                nStateOfFlyFrame = aAttrIter.OutFlys( nEnd );
                 // insert final bookmarks if any before CR and after flys
                 AppendBookmarks( rNode, nEnd, 1 );
                 AppendAnnotationMarks( rNode, nEnd, 1 );
@@ -2256,7 +2302,25 @@ void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode )
 
         AttrOutput().WritePostitFieldReference();
 
-        AttrOutput().EndRun();
+        if( bPostponeWritingText && FLY_PROCESSED == nStateOfFlyFrame )
+        {
+            AttrOutput().EndRun();
+            //write the postponed text run
+            bPostponeWritingText = false ;
+            AttrOutput().StartRun( pRedlineData, bSingleEmptyRun );
+            AttrOutput().SetAnchorIsLinkedToNode( false );
+            AttrOutput().ResetFlyProcessingFlag();
+            if (0 != nEnd)
+            {
+                AttrOutput().StartRunProperties();
+                aAttrIter.OutAttr( nAktPos );
+                AttrOutput().EndRunProperties( pRedlineData );
+            }
+            AttrOutput().RunText( aSavedSnippet, eChrSet );
+            AttrOutput().EndRun();
+        }
+        else
+            AttrOutput().EndRun();
 
         nAktPos = nNextAttr;
         UpdatePosition( &aAttrIter, nAktPos, nEnd );
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
index 9229fa5..36b260f 100644
--- a/sw/source/filter/ww8/wrtww8.hxx
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -145,6 +145,16 @@ enum TxtTypes  //enums for TextTypes
     TXT_EDN = 4, TXT_ATN = 5, TXT_TXTBOX = 6, TXT_HFTXTBOX= 7
 };
 
+/**
+enum to state the present state of the fly
+*/
+enum FlyProcessingState
+{
+    FLY_PROCESSED,
+    FLY_POSTPONED,
+    FLY_NOT_PROCESSED
+};
+
 struct WW8_SepInfo
 {
     const SwPageDesc* pPageDesc;
@@ -1533,7 +1543,7 @@ public:
     int OutAttrWithRange(sal_Int32 nPos);
     const SwRedlineData* GetParagraphLevelRedline( );
     const SwRedlineData* GetRunLevelRedline( sal_Int32 nPos );
-    void OutFlys(sal_Int32 nSwPos);
+    sal_Int16 OutFlys(sal_Int32 nSwPos);
 
     sal_Int32 WhereNext() const { return nAktSwPos; }
     sal_uInt16 GetScript() const { return mnScript; }
@@ -1545,6 +1555,7 @@ public:
     const SwFmtDrop& GetSwFmtDrop() const { return mrSwFmtDrop; }
 
     bool IsWatermarkFrame();
+    bool IsAnchorLinkedToThisNode( sal_uLong nNodePos );
 };
 
 /// Class to collect and output the styles table.


More information about the Libreoffice-commits mailing list