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: */
|