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

Generated by: LCOV version 1.10