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 0 : SvStream& lcl_OutLongExt( SvStream& rStrm, sal_uLong nVal, bool bNeg )
40 : {
41 : sal_Char aBuf[28];
42 :
43 0 : int i = SAL_N_ELEMENTS(aBuf);
44 0 : aBuf[--i] = 0;
45 0 : do
46 : {
47 0 : aBuf[--i] = '0' + static_cast<sal_Char>(nVal % 10);
48 0 : nVal /= 10;
49 : } while (nVal);
50 :
51 0 : if (bNeg)
52 0 : aBuf[--i] = '-';
53 :
54 0 : 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 0 : Writer_Impl::Writer_Impl()
75 0 : : m_pStream(0)
76 : {
77 0 : }
78 :
79 0 : Writer_Impl::~Writer_Impl()
80 : {
81 0 : }
82 :
83 0 : void Writer_Impl::RemoveFontList( SwDoc& rDoc )
84 : {
85 0 : for( std::vector<const SvxFontItem*>::const_iterator it = aFontRemoveLst.begin();
86 0 : it != aFontRemoveLst.end(); ++it )
87 : {
88 0 : rDoc.GetAttrPool().Remove( **it );
89 : }
90 0 : }
91 :
92 0 : void Writer_Impl::InsertBkmk(const ::sw::mark::IMark& rBkmk)
93 : {
94 0 : sal_uLong nNd = rBkmk.GetMarkPos().nNode.GetIndex();
95 :
96 0 : aBkmkNodePos.insert( SwBookmarkNodeTable::value_type( nNd, &rBkmk ) );
97 :
98 0 : 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 0 : }
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 0 : Writer::Writer()
119 0 : : m_pImpl(new Writer_Impl)
120 0 : , pOrigPam(0), pOrigFileName(0), pDoc(0), pCurPam(0)
121 : {
122 0 : bWriteAll = bShowProgress = bUCS2_WithStartChar = true;
123 : bASCII_NoLastLineEnd = bASCII_ParaAsBlanc = bASCII_ParaAsCR =
124 : bWriteClipboardDoc = bWriteOnlyFirstTable = bBlock =
125 0 : bOrganizerMode = false;
126 0 : bExportPargraphNumbering = sal_True;
127 0 : }
128 :
129 0 : Writer::~Writer()
130 : {
131 0 : }
132 :
133 : /*
134 : * Document Interface Access
135 : */
136 0 : IDocumentSettingAccess* Writer::getIDocumentSettingAccess() { return pDoc; }
137 0 : const IDocumentSettingAccess* Writer::getIDocumentSettingAccess() const { return pDoc; }
138 0 : IDocumentStylePoolAccess* Writer::getIDocumentStylePoolAccess() { return pDoc; }
139 0 : const IDocumentStylePoolAccess* Writer::getIDocumentStylePoolAccess() const { return pDoc; }
140 :
141 0 : void Writer::ResetWriter()
142 : {
143 0 : m_pImpl->RemoveFontList( *pDoc );
144 0 : m_pImpl.reset(new Writer_Impl);
145 :
146 0 : if( pCurPam )
147 : {
148 0 : while( pCurPam->GetNext() != pCurPam )
149 0 : delete pCurPam->GetNext();
150 0 : delete pCurPam;
151 : }
152 0 : pCurPam = 0;
153 0 : pOrigFileName = 0;
154 0 : pDoc = 0;
155 :
156 0 : bShowProgress = bUCS2_WithStartChar = sal_True;
157 : bASCII_NoLastLineEnd = bASCII_ParaAsBlanc = bASCII_ParaAsCR =
158 : bWriteClipboardDoc = bWriteOnlyFirstTable = bBlock =
159 0 : bOrganizerMode = sal_False;
160 0 : }
161 :
162 0 : sal_Bool Writer::CopyNextPam( SwPaM ** ppPam )
163 : {
164 0 : if( (*ppPam)->GetNext() == pOrigPam )
165 : {
166 0 : *ppPam = pOrigPam; // set back to the beginning pam
167 0 : 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 0 : sal_Int32 Writer::FindPos_Bkmk(const SwPosition& rPos) const
182 : {
183 0 : const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
184 : const IDocumentMarkAccess::const_iterator_t ppBkmk = ::std::lower_bound(
185 0 : pMarkAccess->getAllMarksBegin(),
186 0 : pMarkAccess->getAllMarksEnd(),
187 : rPos,
188 0 : sw::mark::CompareIMarkStartsBefore()); // find the first Mark that does not start before
189 0 : if(ppBkmk != pMarkAccess->getAllMarksEnd())
190 0 : return ppBkmk - pMarkAccess->getAllMarksBegin();
191 0 : return -1;
192 : }
193 :
194 : SwPaM *
195 0 : Writer::NewSwPaM(SwDoc & rDoc, sal_uLong const nStartIdx, sal_uLong const nEndIdx)
196 : {
197 0 : SwNodes *const pNds = &rDoc.GetNodes();
198 :
199 0 : SwNodeIndex aStt( *pNds, nStartIdx );
200 0 : SwCntntNode* pCNode = aStt.GetNode().GetCntntNode();
201 0 : if( !pCNode && 0 == ( pCNode = pNds->GoNext( &aStt )) )
202 : {
203 : OSL_FAIL( "No more ContentNode at StartPos" );
204 : }
205 :
206 0 : SwPaM* pNew = new SwPaM( aStt );
207 0 : pNew->SetMark();
208 0 : aStt = nEndIdx;
209 0 : if( 0 == (pCNode = aStt.GetNode().GetCntntNode()) &&
210 : 0 == (pCNode = pNds->GoPrevious( &aStt )) )
211 : {
212 : OSL_FAIL( "No more ContentNode at StartPos" );
213 : }
214 0 : pCNode->MakeEndIndex( &pNew->GetPoint()->nContent );
215 0 : pNew->GetPoint()->nNode = aStt;
216 0 : return pNew;
217 : }
218 :
219 : // Stream-specific
220 0 : SvStream& Writer::Strm()
221 : {
222 : OSL_ENSURE( m_pImpl->m_pStream, "Oh-oh. Writer with no Stream!" );
223 0 : return *m_pImpl->m_pStream;
224 : }
225 :
226 0 : void Writer::SetStream(SvStream *const pStream)
227 0 : { m_pImpl->m_pStream = pStream; }
228 :
229 0 : SvStream& Writer::OutLong( SvStream& rStrm, long nVal )
230 : {
231 0 : const bool bNeg = nVal < 0;
232 0 : if (bNeg)
233 0 : nVal = -nVal;
234 :
235 0 : return lcl_OutLongExt(rStrm, static_cast<sal_uLong>(nVal), bNeg);
236 : }
237 :
238 0 : SvStream& Writer::OutULong( SvStream& rStrm, sal_uLong nVal )
239 : {
240 0 : return lcl_OutLongExt(rStrm, nVal, false);
241 : }
242 :
243 0 : sal_uLong Writer::Write( SwPaM& rPaM, SvStream& rStrm, const OUString* pFName )
244 : {
245 0 : if ( IsStgWriter() )
246 : {
247 0 : SotStorageRef aRef = new SotStorage( rStrm );
248 0 : sal_uLong nResult = Write( rPaM, *aRef, pFName );
249 0 : if ( nResult == ERRCODE_NONE )
250 0 : aRef->Commit();
251 0 : return nResult;
252 : }
253 :
254 0 : pDoc = rPaM.GetDoc();
255 0 : pOrigFileName = pFName;
256 0 : m_pImpl->m_pStream = &rStrm;
257 :
258 : // Copy PaM, so that it can be modified
259 0 : pCurPam = new SwPaM( *rPaM.End(), *rPaM.Start() );
260 : // for comparison secure to the current Pam
261 0 : pOrigPam = &rPaM;
262 :
263 0 : sal_uLong nRet = WriteStream();
264 :
265 0 : ResetWriter();
266 :
267 0 : return nRet;
268 : }
269 :
270 0 : void Writer::SetupFilterOptions(SfxMedium& /*rMedium*/)
271 0 : {}
272 :
273 0 : sal_uLong Writer::Write( SwPaM& rPam, SfxMedium& rMedium, const OUString* pFileName )
274 : {
275 0 : 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 0 : 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 0 : 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 0 : SfxItemPool& rPool = pDoc->GetAttrPool();
299 0 : const SwNumRuleTbl& rListTbl = pDoc->GetNumRuleTbl();
300 : const SwNumRule* pRule;
301 : const SwNumFmt* pFmt;
302 : const Font* pFont;
303 0 : const Font* pDefFont = &numfunc::GetDefBulletFont();
304 0 : bool bCheck = false;
305 :
306 0 : for( sal_uInt16 nGet = rListTbl.size(); nGet; )
307 0 : 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 0 : }
328 :
329 0 : void Writer::PutEditEngFontsInAttrPool( bool bIncl_CJK_CTL )
330 : {
331 0 : SfxItemPool& rPool = pDoc->GetAttrPool();
332 0 : if( rPool.GetSecondaryPool() )
333 : {
334 0 : _AddFontItems( rPool, EE_CHAR_FONTINFO );
335 0 : if( bIncl_CJK_CTL )
336 : {
337 0 : _AddFontItems( rPool, EE_CHAR_FONTINFO_CJK );
338 0 : _AddFontItems( rPool, EE_CHAR_FONTINFO_CTL );
339 : }
340 : }
341 0 : }
342 :
343 0 : void Writer::_AddFontItems( SfxItemPool& rPool, sal_uInt16 nW )
344 : {
345 0 : const SvxFontItem* pFont = (const SvxFontItem*)&rPool.GetDefaultItem( nW );
346 0 : _AddFontItem( rPool, *pFont );
347 :
348 0 : if( 0 != ( pFont = (const SvxFontItem*)rPool.GetPoolDefaultItem( nW )) )
349 0 : _AddFontItem( rPool, *pFont );
350 :
351 0 : sal_uInt32 nMaxItem = rPool.GetItemCount2( nW );
352 0 : for( sal_uInt32 nGet = 0; nGet < nMaxItem; ++nGet )
353 0 : if( 0 != (pFont = (const SvxFontItem*)rPool.GetItem2( nW, nGet )) )
354 0 : _AddFontItem( rPool, *pFont );
355 0 : }
356 :
357 0 : void Writer::_AddFontItem( SfxItemPool& rPool, const SvxFontItem& rFont )
358 : {
359 : const SvxFontItem* pItem;
360 0 : if( RES_CHRATR_FONT != rFont.Which() )
361 : {
362 0 : SvxFontItem aFont( rFont );
363 0 : aFont.SetWhich( RES_CHRATR_FONT );
364 0 : pItem = (SvxFontItem*)&rPool.Put( aFont );
365 : }
366 : else
367 0 : pItem = (SvxFontItem*)&rPool.Put( rFont );
368 :
369 0 : if( 1 < pItem->GetRefCount() )
370 0 : rPool.Remove( *pItem );
371 : else
372 : {
373 0 : m_pImpl->aFontRemoveLst.push_back( pItem );
374 : }
375 0 : }
376 :
377 : // build a bookmark table, which is sort by the node position. The
378 : // OtherPos of the bookmarks also inserted.
379 0 : void Writer::CreateBookmarkTbl()
380 : {
381 0 : const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
382 0 : for(IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->getBookmarksBegin();
383 0 : ppBkmk != pMarkAccess->getBookmarksEnd();
384 : ++ppBkmk)
385 : {
386 0 : m_pImpl->InsertBkmk(**ppBkmk);
387 : }
388 0 : }
389 :
390 : // search alle Bookmarks in the range and return it in the Array
391 0 : 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 0 : sal_uLong nNd = rNd.GetIndex();
397 : std::pair<SwBookmarkNodeTable::const_iterator, SwBookmarkNodeTable::const_iterator> aIterPair
398 0 : = m_pImpl->aBkmkNodePos.equal_range( nNd );
399 0 : if( aIterPair.first != aIterPair.second )
400 : {
401 : // there exist some bookmarks, search now all which is in the range
402 0 : if( !nStt && nEnd == rNd.Len() )
403 : // all
404 0 : for( SwBookmarkNodeTable::const_iterator it = aIterPair.first; it != aIterPair.second; ++it )
405 0 : rArr.push_back( it->second );
406 : else
407 : {
408 0 : for( SwBookmarkNodeTable::const_iterator it = aIterPair.first; it != aIterPair.second; ++it )
409 : {
410 0 : const ::sw::mark::IMark& rBkmk = *(it->second);
411 : sal_Int32 nCntnt;
412 0 : if( rBkmk.GetMarkPos().nNode == nNd &&
413 0 : (nCntnt = rBkmk.GetMarkPos().nContent.GetIndex() ) >= nStt &&
414 : nCntnt < nEnd )
415 : {
416 0 : rArr.push_back( &rBkmk );
417 : }
418 0 : else if( rBkmk.IsExpanded() && nNd ==
419 0 : rBkmk.GetOtherMarkPos().nNode.GetIndex() && (nCntnt =
420 0 : rBkmk.GetOtherMarkPos().nContent.GetIndex() ) >= nStt &&
421 : nCntnt < nEnd )
422 : {
423 0 : rArr.push_back( &rBkmk );
424 : }
425 : }
426 : }
427 : }
428 0 : 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 0 : sal_uLong StgWriter::Write( SwPaM& rPaM, SvStorage& rStg, const OUString* pFName )
439 : {
440 0 : SetStream(0);
441 0 : pStg = &rStg;
442 0 : pDoc = rPaM.GetDoc();
443 0 : pOrigFileName = pFName;
444 :
445 : // Copy PaM, so that it can be modified
446 0 : pCurPam = new SwPaM( *rPaM.End(), *rPaM.Start() );
447 : // for comparison secure to the current Pam
448 0 : pOrigPam = &rPaM;
449 :
450 0 : sal_uLong nRet = WriteStorage();
451 :
452 0 : pStg = NULL;
453 0 : ResetWriter();
454 :
455 0 : return nRet;
456 : }
457 :
458 0 : sal_uLong StgWriter::Write( SwPaM& rPaM, const uno::Reference < embed::XStorage >& rStg, const OUString* pFName, SfxMedium* pMedium )
459 : {
460 0 : SetStream(0);
461 0 : pStg = 0;
462 0 : xStg = rStg;
463 0 : pDoc = rPaM.GetDoc();
464 0 : pOrigFileName = pFName;
465 :
466 : // Copy PaM, so that it can be modified
467 0 : pCurPam = new SwPaM( *rPaM.End(), *rPaM.Start() );
468 : // for comparison secure to the current Pam
469 0 : pOrigPam = &rPaM;
470 :
471 0 : sal_uLong nRet = pMedium ? WriteMedium( *pMedium ) : WriteStorage();
472 :
473 0 : pStg = NULL;
474 0 : ResetWriter();
475 :
476 0 : return nRet;
477 : }
478 :
479 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|