LCOV - code coverage report
Current view: top level - sw/source/filter/writer - writer.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 200 216 92.6 %
Date: 2015-06-13 12:38:46 Functions: 30 36 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <hintids.hxx>
      21             : 
      22             : #include <sot/storage.hxx>
      23             : #include <sfx2/docfile.hxx>
      24             : #include <svl/urihelper.hxx>
      25             : #include <vcl/graphicfilter.hxx>
      26             : #include <editeng/fontitem.hxx>
      27             : #include <editeng/eeitem.hxx>
      28             : #include <o3tl/make_unique.hxx>
      29             : #include <shellio.hxx>
      30             : #include <doc.hxx>
      31             : #include <docary.hxx>
      32             : #include <IMark.hxx>
      33             : #include <IDocumentSettingAccess.hxx>
      34             : #include <numrule.hxx>
      35             : #include <swerror.h>
      36             : 
      37             : using namespace css;
      38             : 
      39             : namespace
      40             : {
      41       12873 :     SvStream& lcl_OutLongExt( SvStream& rStrm, sal_uLong nVal, bool bNeg )
      42             :     {
      43             :         sal_Char aBuf[28];
      44             : 
      45       12873 :         int i = SAL_N_ELEMENTS(aBuf);
      46       12873 :         aBuf[--i] = 0;
      47       23672 :         do
      48             :         {
      49       23672 :             aBuf[--i] = '0' + static_cast<sal_Char>(nVal % 10);
      50       23672 :             nVal /= 10;
      51             :         } while (nVal);
      52             : 
      53       12873 :         if (bNeg)
      54         361 :             aBuf[--i] = '-';
      55             : 
      56       12873 :         return rStrm.WriteCharPtr( &aBuf[i] );
      57             :     }
      58             : }
      59             : 
      60             : typedef std::multimap<sal_uLong, const ::sw::mark::IMark*> SwBookmarkNodeTable;
      61             : 
      62             : struct Writer_Impl
      63             : {
      64             :     SvStream * m_pStream;
      65             : 
      66             :     std::vector<const SvxFontItem*> aFontRemoveLst;
      67             :     SwBookmarkNodeTable aBkmkNodePos;
      68             : 
      69             :     Writer_Impl();
      70             :     ~Writer_Impl();
      71             : 
      72             :     void RemoveFontList( SwDoc& rDoc );
      73             :     void InsertBkmk( const ::sw::mark::IMark& rBkmk );
      74             : };
      75             : 
      76       16485 : Writer_Impl::Writer_Impl()
      77       16485 :     : m_pStream(0)
      78             : {
      79       16485 : }
      80             : 
      81       16485 : Writer_Impl::~Writer_Impl()
      82             : {
      83       16485 : }
      84             : 
      85        8195 : void Writer_Impl::RemoveFontList( SwDoc& rDoc )
      86             : {
      87       25200 :     for( std::vector<const SvxFontItem*>::const_iterator it = aFontRemoveLst.begin();
      88       16800 :         it != aFontRemoveLst.end(); ++it )
      89             :     {
      90         205 :         rDoc.GetAttrPool().Remove( **it );
      91             :     }
      92        8195 : }
      93             : 
      94           9 : void Writer_Impl::InsertBkmk(const ::sw::mark::IMark& rBkmk)
      95             : {
      96           9 :     sal_uLong nNd = rBkmk.GetMarkPos().nNode.GetIndex();
      97             : 
      98           9 :     aBkmkNodePos.insert( SwBookmarkNodeTable::value_type( nNd, &rBkmk ) );
      99             : 
     100           9 :     if(rBkmk.IsExpanded() && rBkmk.GetOtherMarkPos().nNode != nNd)
     101             :     {
     102           0 :         nNd = rBkmk.GetOtherMarkPos().nNode.GetIndex();
     103           0 :         aBkmkNodePos.insert( SwBookmarkNodeTable::value_type( nNd, &rBkmk ));
     104             :     }
     105           9 : }
     106             : 
     107             : /*
     108             :  * This module is the central collection point for all writer-filters
     109             :  * and is a DLL !
     110             :  *
     111             :  * So that the Writer can work with different writers, the output-functions
     112             :  * of the content carrying objects have to be mapped to the various
     113             :  * output-functions.
     114             :  *
     115             :  * For that, to inquire its output function, every object can be gripped
     116             :  * via the which-value in a table.
     117             :  * These functions are available in the corresponding Writer-DLL's.
     118             :  */
     119             : 
     120        8290 : Writer::Writer()
     121             :     : m_pImpl(o3tl::make_unique<Writer_Impl>())
     122        8290 :     , pOrigPam(0), pOrigFileName(0), pDoc(0), pCurPam(0)
     123             : {
     124        8290 :     bWriteAll = bShowProgress = bUCS2_WithStartChar = true;
     125             :     bASCII_NoLastLineEnd = bASCII_ParaAsBlanc = bASCII_ParaAsCR =
     126             :         bWriteClipboardDoc = bWriteOnlyFirstTable = bBlock =
     127        8290 :         bOrganizerMode = false;
     128        8290 :     bExportPargraphNumbering = true;
     129        8290 : }
     130             : 
     131        8290 : Writer::~Writer()
     132             : {
     133        8290 : }
     134             : 
     135             : /*
     136             :  * Document Interface Access
     137             :  */
     138          32 : IDocumentSettingAccess* Writer::getIDocumentSettingAccess() { return &pDoc->getIDocumentSettingAccess(); }
     139           0 : const IDocumentSettingAccess* Writer::getIDocumentSettingAccess() const { return &pDoc->getIDocumentSettingAccess(); }
     140          28 : IDocumentStylePoolAccess* Writer::getIDocumentStylePoolAccess() { return &pDoc->getIDocumentStylePoolAccess(); }
     141           0 : const IDocumentStylePoolAccess* Writer::getIDocumentStylePoolAccess() const { return &pDoc->getIDocumentStylePoolAccess(); }
     142             : 
     143        8195 : void Writer::ResetWriter()
     144             : {
     145        8195 :     m_pImpl->RemoveFontList( *pDoc );
     146        8195 :     m_pImpl.reset(new Writer_Impl);
     147             : 
     148        8195 :     if( pCurPam )
     149             :     {
     150       16390 :         while( pCurPam->GetNext() != pCurPam )
     151           0 :             delete pCurPam->GetNext();
     152        8195 :         delete pCurPam;
     153             :     }
     154        8195 :     pCurPam = 0;
     155        8195 :     pOrigFileName = 0;
     156        8195 :     pDoc = 0;
     157             : 
     158        8195 :     bShowProgress = bUCS2_WithStartChar = true;
     159             :     bASCII_NoLastLineEnd = bASCII_ParaAsBlanc = bASCII_ParaAsCR =
     160             :         bWriteClipboardDoc = bWriteOnlyFirstTable = bBlock =
     161        8195 :         bOrganizerMode = false;
     162        8195 : }
     163             : 
     164        8353 : bool Writer::CopyNextPam( SwPaM ** ppPam )
     165             : {
     166        8353 :     if( (*ppPam)->GetNext() == pOrigPam )
     167             :     {
     168        8353 :         *ppPam = pOrigPam;          // set back to the beginning pam
     169        8353 :         return false;           // end of the ring
     170             :     }
     171             : 
     172             :     // otherwise copy the next value from the next Pam
     173           0 :     *ppPam = static_cast<SwPaM*>((*ppPam)->GetNext() );
     174             : 
     175           0 :     *pCurPam->GetPoint() = *(*ppPam)->Start();
     176           0 :     *pCurPam->GetMark() = *(*ppPam)->End();
     177             : 
     178           0 :     return true;
     179             : }
     180             : 
     181             : // search the next Bookmark-Position from the Bookmark-Table
     182             : 
     183         541 : sal_Int32 Writer::FindPos_Bkmk(const SwPosition& rPos) const
     184             : {
     185         541 :     const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
     186             :     const IDocumentMarkAccess::const_iterator_t ppBkmk = ::std::lower_bound(
     187         541 :         pMarkAccess->getAllMarksBegin(),
     188         541 :         pMarkAccess->getAllMarksEnd(),
     189             :         rPos,
     190        1082 :         sw::mark::CompareIMarkStartsBefore()); // find the first Mark that does not start before
     191         541 :     if(ppBkmk != pMarkAccess->getAllMarksEnd())
     192           1 :         return ppBkmk - pMarkAccess->getAllMarksBegin();
     193         540 :     return -1;
     194             : }
     195             : 
     196             : SwPaM *
     197         953 : Writer::NewSwPaM(SwDoc & rDoc, sal_uLong const nStartIdx, sal_uLong const nEndIdx)
     198             : {
     199         953 :     SwNodes *const pNds = &rDoc.GetNodes();
     200             : 
     201         953 :     SwNodeIndex aStt( *pNds, nStartIdx );
     202         953 :     SwContentNode* pCNode = aStt.GetNode().GetContentNode();
     203         953 :     if( !pCNode && 0 == pNds->GoNext( &aStt ) )
     204             :     {
     205             :         OSL_FAIL( "No more ContentNode at StartPos" );
     206             :     }
     207             : 
     208         953 :     SwPaM* pNew = new SwPaM( aStt );
     209         953 :     pNew->SetMark();
     210         953 :     aStt = nEndIdx;
     211         953 :     pCNode = aStt.GetNode().GetContentNode();
     212         953 :     if (!pCNode)
     213         953 :         pCNode = SwNodes::GoPrevious(&aStt);
     214             :     assert(pCNode && "No more ContentNode at StartPos");
     215         953 :     pCNode->MakeEndIndex( &pNew->GetPoint()->nContent );
     216         953 :     pNew->GetPoint()->nNode = aStt;
     217         953 :     return pNew;
     218             : }
     219             : 
     220             : // Stream-specific
     221       93155 : SvStream& Writer::Strm()
     222             : {
     223             :     assert(m_pImpl->m_pStream && "Oh-oh. Writer with no Stream!");
     224       93155 :     return *m_pImpl->m_pStream;
     225             : }
     226             : 
     227         262 : void Writer::SetStream(SvStream *const pStream)
     228             : {
     229         262 :     m_pImpl->m_pStream = pStream;
     230         262 : }
     231             : 
     232        1586 : SvStream& Writer::OutLong( SvStream& rStrm, long nVal )
     233             : {
     234        1586 :     const bool bNeg = nVal < 0;
     235        1586 :     if (bNeg)
     236         361 :         nVal = -nVal;
     237             : 
     238        1586 :     return lcl_OutLongExt(rStrm, static_cast<sal_uLong>(nVal), bNeg);
     239             : }
     240             : 
     241       11287 : SvStream& Writer::OutULong( SvStream& rStrm, sal_uLong nVal )
     242             : {
     243       11287 :     return lcl_OutLongExt(rStrm, nVal, false);
     244             : }
     245             : 
     246        8124 : sal_uLong Writer::Write( SwPaM& rPaM, SvStream& rStrm, const OUString* pFName )
     247             : {
     248        8124 :     if ( IsStgWriter() )
     249             :     {
     250          32 :         sal_uLong nResult = ERRCODE_ABORT;
     251             :         try
     252             :         {
     253          32 :             tools::SvRef<SotStorage> aRef = new SotStorage( rStrm );
     254          32 :             nResult = Write( rPaM, *aRef, pFName );
     255          32 :             if ( nResult == ERRCODE_NONE )
     256          32 :                 aRef->Commit();
     257             :         }
     258           0 :         catch (const css::ucb::ContentCreationException &e)
     259             :         {
     260             :             SAL_WARN("sw", "Writer::Write caught " << e.Message);
     261             :         }
     262          32 :         return nResult;
     263             :     }
     264             : 
     265        8092 :     pDoc = rPaM.GetDoc();
     266        8092 :     pOrigFileName = pFName;
     267        8092 :     m_pImpl->m_pStream = &rStrm;
     268             : 
     269             :     // Copy PaM, so that it can be modified
     270        8092 :     pCurPam = new SwPaM( *rPaM.End(), *rPaM.Start() );
     271             :     // for comparison secure to the current Pam
     272        8092 :     pOrigPam = &rPaM;
     273             : 
     274        8092 :     sal_uLong nRet = WriteStream();
     275             : 
     276        8092 :     ResetWriter();
     277             : 
     278        8092 :     return nRet;
     279             : }
     280             : 
     281          33 : void Writer::SetupFilterOptions(SfxMedium& /*rMedium*/)
     282          33 : {}
     283             : 
     284          48 : sal_uLong Writer::Write( SwPaM& rPam, SfxMedium& rMedium, const OUString* pFileName )
     285             : {
     286          48 :     SetupFilterOptions(rMedium);
     287             :     // This method must be overridden in SwXMLWriter a storage from medium will be used there.
     288             :     // The microsoft format can write to storage but the storage will be based on the stream.
     289          48 :     return Write( rPam, *rMedium.GetOutStream(), pFileName );
     290             : }
     291             : 
     292           0 : sal_uLong Writer::Write( SwPaM& /*rPam*/, SotStorage&, const OUString* )
     293             : {
     294             :     OSL_ENSURE( false, "Write in Storages on a stream?" );
     295           0 :     return ERR_SWG_WRITE_ERROR;
     296             : }
     297             : 
     298           0 : sal_uLong Writer::Write( SwPaM&, const uno::Reference < embed::XStorage >&, const OUString*, SfxMedium* )
     299             : {
     300             :     OSL_ENSURE( false, "Write in Storages on a stream?" );
     301           0 :     return ERR_SWG_WRITE_ERROR;
     302             : }
     303             : 
     304          71 : void Writer::PutNumFormatFontsInAttrPool()
     305             : {
     306             :     // then there are a few fonts in the NumRules
     307             :     // These put into the Pool. After this does they have a RefCount > 1
     308             :     // it can be removed - it is already in the Pool
     309          71 :     SfxItemPool& rPool = pDoc->GetAttrPool();
     310          71 :     const SwNumRuleTable& rListTable = pDoc->GetNumRuleTable();
     311             :     const SwNumRule* pRule;
     312             :     const SwNumFormat* pFormat;
     313             :     const vcl::Font* pFont;
     314          71 :     const vcl::Font* pDefFont = &numfunc::GetDefBulletFont();
     315          71 :     bool bCheck = false;
     316             : 
     317         280 :     for( size_t nGet = rListTable.size(); nGet; )
     318         138 :         if( SwDoc::IsUsed( *(pRule = rListTable[ --nGet ] )))
     319         143 :             for( sal_uInt8 nLvl = 0; nLvl < MAXLEVEL; ++nLvl )
     320         226 :                 if( SVX_NUM_CHAR_SPECIAL == (pFormat = &pRule->Get( nLvl ))->GetNumberingType() ||
     321          96 :                     SVX_NUM_BITMAP == pFormat->GetNumberingType() )
     322             :                 {
     323          34 :                     if( 0 == ( pFont = pFormat->GetBulletFont() ) )
     324          10 :                         pFont = pDefFont;
     325             : 
     326          34 :                     if( bCheck )
     327             :                     {
     328           9 :                         if( *pFont == *pDefFont )
     329           9 :                             continue;
     330             :                     }
     331          25 :                     else if( *pFont == *pDefFont )
     332           1 :                         bCheck = true;
     333             : 
     334             :                     _AddFontItem( rPool, SvxFontItem( pFont->GetFamily(),
     335          25 :                                 pFont->GetName(), pFont->GetStyleName(),
     336          50 :                                 pFont->GetPitch(), pFont->GetCharSet(), RES_CHRATR_FONT ));
     337             :                 }
     338          71 : }
     339             : 
     340          71 : void Writer::PutEditEngFontsInAttrPool( bool bIncl_CJK_CTL )
     341             : {
     342          71 :     SfxItemPool& rPool = pDoc->GetAttrPool();
     343          71 :     if( rPool.GetSecondaryPool() )
     344             :     {
     345          71 :         _AddFontItems( rPool, EE_CHAR_FONTINFO );
     346          71 :         if( bIncl_CJK_CTL )
     347             :         {
     348          71 :             _AddFontItems( rPool, EE_CHAR_FONTINFO_CJK );
     349          71 :             _AddFontItems( rPool, EE_CHAR_FONTINFO_CTL );
     350             :         }
     351             :     }
     352          71 : }
     353             : 
     354         213 : void Writer::_AddFontItems( SfxItemPool& rPool, sal_uInt16 nW )
     355             : {
     356         213 :     const SvxFontItem* pFont = static_cast<const SvxFontItem*>(&rPool.GetDefaultItem( nW ));
     357         213 :     _AddFontItem( rPool, *pFont );
     358             : 
     359         213 :     if( 0 != ( pFont = static_cast<const SvxFontItem*>(rPool.GetPoolDefaultItem( nW ))) )
     360         213 :         _AddFontItem( rPool, *pFont );
     361             : 
     362         213 :     sal_uInt32 nMaxItem = rPool.GetItemCount2( nW );
     363         229 :     for( sal_uInt32 nGet = 0; nGet < nMaxItem; ++nGet )
     364          16 :         if( 0 != (pFont = static_cast<const SvxFontItem*>(rPool.GetItem2( nW, nGet ))) )
     365          16 :             _AddFontItem( rPool, *pFont );
     366         213 : }
     367             : 
     368         467 : void Writer::_AddFontItem( SfxItemPool& rPool, const SvxFontItem& rFont )
     369             : {
     370             :     const SvxFontItem* pItem;
     371         467 :     if( RES_CHRATR_FONT != rFont.Which() )
     372             :     {
     373         442 :         SvxFontItem aFont( rFont );
     374         442 :         aFont.SetWhich( RES_CHRATR_FONT );
     375         442 :         pItem = static_cast<const SvxFontItem*>(&rPool.Put( aFont ));
     376             :     }
     377             :     else
     378          25 :         pItem = static_cast<const SvxFontItem*>(&rPool.Put( rFont ));
     379             : 
     380         467 :     if( 1 < pItem->GetRefCount() )
     381         262 :         rPool.Remove( *pItem );
     382             :     else
     383             :     {
     384         205 :         m_pImpl->aFontRemoveLst.push_back( pItem );
     385             :     }
     386         467 : }
     387             : 
     388             : // build a bookmark table, which is sort by the node position. The
     389             : // OtherPos of the bookmarks also inserted.
     390          32 : void Writer::CreateBookmarkTable()
     391             : {
     392          32 :     const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
     393         123 :     for(IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->getBookmarksBegin();
     394          82 :         ppBkmk != pMarkAccess->getBookmarksEnd();
     395             :         ++ppBkmk)
     396             :     {
     397           9 :         m_pImpl->InsertBkmk(**ppBkmk);
     398             :     }
     399          32 : }
     400             : 
     401             : // search alle Bookmarks in the range and return it in the Array
     402        1006 : bool Writer::GetBookmarks(const SwContentNode& rNd, sal_Int32 nStt,
     403             :     sal_Int32 nEnd, std::vector< const ::sw::mark::IMark* >& rArr)
     404             : {
     405             :     OSL_ENSURE( rArr.empty(), "there are still entries available" );
     406             : 
     407        1006 :     sal_uLong nNd = rNd.GetIndex();
     408             :     std::pair<SwBookmarkNodeTable::const_iterator, SwBookmarkNodeTable::const_iterator> aIterPair
     409        1006 :         = m_pImpl->aBkmkNodePos.equal_range( nNd );
     410        1006 :     if( aIterPair.first != aIterPair.second )
     411             :     {
     412             :         // there exist some bookmarks, search now all which is in the range
     413          53 :         if( !nStt && nEnd == rNd.Len() )
     414             :             // all
     415           6 :             for( SwBookmarkNodeTable::const_iterator it = aIterPair.first; it != aIterPair.second; ++it )
     416           3 :                 rArr.push_back( it->second );
     417             :         else
     418             :         {
     419         109 :             for( SwBookmarkNodeTable::const_iterator it = aIterPair.first; it != aIterPair.second; ++it )
     420             :             {
     421          59 :                 const ::sw::mark::IMark& rBkmk = *(it->second);
     422             :                 sal_Int32 nContent;
     423         177 :                 if( rBkmk.GetMarkPos().nNode == nNd &&
     424         101 :                     (nContent = rBkmk.GetMarkPos().nContent.GetIndex() ) >= nStt &&
     425             :                     nContent < nEnd )
     426             :                 {
     427           6 :                     rArr.push_back( &rBkmk );
     428             :                 }
     429         121 :                 else if( rBkmk.IsExpanded() && nNd ==
     430          30 :                         rBkmk.GetOtherMarkPos().nNode.GetIndex() && (nContent =
     431          77 :                         rBkmk.GetOtherMarkPos().nContent.GetIndex() ) >= nStt &&
     432             :                         nContent < nEnd )
     433             :                 {
     434           5 :                     rArr.push_back( &rBkmk );
     435             :                 }
     436             :             }
     437             :         }
     438             :     }
     439        1006 :     return !rArr.empty();
     440             : }
     441             : 
     442             : // Storage-specific
     443           0 : sal_uLong StgWriter::WriteStream()
     444             : {
     445             :     OSL_ENSURE( false, "Write in Storages on a stream?" );
     446           0 :     return ERR_SWG_WRITE_ERROR;
     447             : }
     448             : 
     449          32 : sal_uLong StgWriter::Write( SwPaM& rPaM, SotStorage& rStg, const OUString* pFName )
     450             : {
     451          32 :     SetStream(0);
     452          32 :     pStg = &rStg;
     453          32 :     pDoc = rPaM.GetDoc();
     454          32 :     pOrigFileName = pFName;
     455             : 
     456             :     // Copy PaM, so that it can be modified
     457          32 :     pCurPam = new SwPaM( *rPaM.End(), *rPaM.Start() );
     458             :     // for comparison secure to the current Pam
     459          32 :     pOrigPam = &rPaM;
     460             : 
     461          32 :     sal_uLong nRet = WriteStorage();
     462             : 
     463          32 :     pStg = NULL;
     464          32 :     ResetWriter();
     465             : 
     466          32 :     return nRet;
     467             : }
     468             : 
     469          71 : sal_uLong StgWriter::Write( SwPaM& rPaM, const uno::Reference < embed::XStorage >& rStg, const OUString* pFName, SfxMedium* pMedium )
     470             : {
     471          71 :     SetStream(0);
     472          71 :     pStg = 0;
     473          71 :     xStg = rStg;
     474          71 :     pDoc = rPaM.GetDoc();
     475          71 :     pOrigFileName = pFName;
     476             : 
     477             :     // Copy PaM, so that it can be modified
     478          71 :     pCurPam = new SwPaM( *rPaM.End(), *rPaM.Start() );
     479             :     // for comparison secure to the current Pam
     480          71 :     pOrigPam = &rPaM;
     481             : 
     482          71 :     sal_uLong nRet = pMedium ? WriteMedium( *pMedium ) : WriteStorage();
     483             : 
     484          71 :     pStg = NULL;
     485          71 :     ResetWriter();
     486             : 
     487          71 :     return nRet;
     488         177 : }
     489             : 
     490             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11