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

Generated by: LCOV version 1.10