xref: /trunk/main/sw/source/filter/writer/writer.cxx (revision 870262e3)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 #include <hintids.hxx>
27 
28 #define _SVSTDARR_STRINGSSORTDTOR
29 #include <svl/svstdarr.hxx>
30 
31 #include <sot/storage.hxx>
32 #include <sfx2/docfile.hxx>
33 #include <svl/urihelper.hxx>
34 #include <svtools/filter.hxx>
35 #include <editeng/fontitem.hxx>
36 #include <editeng/eeitem.hxx>
37 #include <shellio.hxx>
38 #include <pam.hxx>
39 #include <doc.hxx>
40 #include <docary.hxx>
41 #include <IMark.hxx>
42 #include <numrule.hxx>
43 #include <swerror.h>
44 #include <boost/bind.hpp>
45 
46 using namespace ::com::sun::star;
47 
48 
49 // Stringbuffer fuer die umgewandelten Zahlen
50 static sal_Char aNToABuf[] = "0000000000000000000000000";
51 #define NTOABUFLEN (sizeof(aNToABuf))
52 
53 DECLARE_TABLE( SwBookmarkNodeTable, SvPtrarr* )
54 
55 struct Writer_Impl
56 {
57     SvStream * m_pStream;
58 
59 	SvStringsSortDtor *pSrcArr, *pDestArr;
60 	SvPtrarr* pFontRemoveLst, *pBkmkArr;
61 	SwBookmarkNodeTable* pBkmkNodePos;
62 
63     Writer_Impl();
64 	~Writer_Impl();
65 
66 	void RemoveFontList( SwDoc& rDoc );
67 	void InsertBkmk( const ::sw::mark::IMark& rBkmk );
68 };
69 
Writer_Impl()70 Writer_Impl::Writer_Impl()
71     : m_pStream(0)
72     , pSrcArr( 0 ), pDestArr( 0 ), pFontRemoveLst( 0 ), pBkmkNodePos( 0 )
73 {
74 }
75 
~Writer_Impl()76 Writer_Impl::~Writer_Impl()
77 {
78 	delete pSrcArr;
79 	delete pDestArr;
80 	delete pFontRemoveLst;
81 
82 	if( pBkmkNodePos )
83 	{
84 		for( SvPtrarr* p = pBkmkNodePos->First(); p; p = pBkmkNodePos->Next() )
85 			delete p;
86 		delete pBkmkNodePos;
87 	}
88 }
89 
RemoveFontList(SwDoc & rDoc)90 void Writer_Impl::RemoveFontList( SwDoc& rDoc )
91 {
92 	ASSERT( pFontRemoveLst, "wo ist die FontListe?" );
93 	for( sal_uInt16 i = pFontRemoveLst->Count(); i; )
94 	{
95 		SvxFontItem* pItem = (SvxFontItem*)(*pFontRemoveLst)[ --i ];
96 		rDoc.GetAttrPool().Remove( *pItem );
97 	}
98 }
99 
InsertBkmk(const::sw::mark::IMark & rBkmk)100 void Writer_Impl::InsertBkmk(const ::sw::mark::IMark& rBkmk)
101 {
102     if( !pBkmkNodePos )
103         pBkmkNodePos = new SwBookmarkNodeTable;
104 
105     sal_uLong nNd = rBkmk.GetMarkPos().nNode.GetIndex();
106     SvPtrarr* pArr = pBkmkNodePos->Get( nNd );
107     if( !pArr )
108     {
109         pArr = new SvPtrarr( 1, 4 );
110         pBkmkNodePos->Insert( nNd, pArr );
111     }
112 
113     void* p = (void*)&rBkmk;
114     pArr->Insert( p, pArr->Count() );
115 
116     if(rBkmk.IsExpanded() && rBkmk.GetOtherMarkPos().nNode != nNd)
117     {
118         nNd = rBkmk.GetOtherMarkPos().nNode.GetIndex();
119         pArr = pBkmkNodePos->Get( nNd );
120         if( !pArr )
121         {
122             pArr = new SvPtrarr( 1, 4 );
123             pBkmkNodePos->Insert( nNd, pArr );
124         }
125         pArr->Insert( p, pArr->Count() );
126     }
127 }
128 
129 /*
130  * Dieses Modul ist die Zentrale-Sammelstelle fuer alle Write-Filter
131  * und ist eine DLL !
132  *
133  * Damit der Writer mit den unterschiedlichen Writern arbeiten kann,
134  * muessen fuer diese die Ausgabe-Funktionen der Inhalts tragenden
135  * Objecte auf die verschiedenen Ausgabe-Funktionen gemappt werden.
136  *
137  * Dazu kann fuer jedes Object ueber den Which-Wert in einen Tabelle ge-
138  * griffen werden, um seine Ausgabe-Funktion zu erfragen.
139  * Diese Funktionen stehen in den entsprechenden Writer-DLL's.
140  */
141 
Writer()142 Writer::Writer()
143     : m_pImpl(new Writer_Impl)
144     , pOrigPam(0), pOrigFileName(0), pDoc(0), pCurPam(0)
145 {
146 	bWriteAll = bShowProgress = bUCS2_WithStartChar = true;
147 	bASCII_NoLastLineEnd = bASCII_ParaAsBlanc = bASCII_ParaAsCR =
148 		bWriteClipboardDoc = bWriteOnlyFirstTable = bBlock =
149 		bOrganizerMode = false;
150     bExportPargraphNumbering = sal_True;
151 }
152 
~Writer()153 Writer::~Writer()
154 {
155 }
156 
157 /*
158  * Document Interface Access
159  */
getIDocumentSettingAccess()160 IDocumentSettingAccess* Writer::getIDocumentSettingAccess() { return pDoc; }
getIDocumentSettingAccess() const161 const IDocumentSettingAccess* Writer::getIDocumentSettingAccess() const { return pDoc; }
getIDocumentStylePoolAccess()162 IDocumentStylePoolAccess* Writer::getIDocumentStylePoolAccess() { return pDoc; }
getIDocumentStylePoolAccess() const163 const IDocumentStylePoolAccess* Writer::getIDocumentStylePoolAccess() const { return pDoc; }
164 
ResetWriter()165 void Writer::ResetWriter()
166 {
167     if (m_pImpl->pFontRemoveLst)
168     {
169         m_pImpl->RemoveFontList( *pDoc );
170     }
171     m_pImpl.reset(new Writer_Impl);
172 
173 	if( pCurPam )
174 	{
175 		while( pCurPam->GetNext() != pCurPam )
176 			delete pCurPam->GetNext();
177 		delete pCurPam;
178 	}
179 	pCurPam = 0;
180 	pOrigFileName = 0;
181 	pDoc = 0;
182 
183 	bShowProgress = bUCS2_WithStartChar = sal_True;
184 	bASCII_NoLastLineEnd = bASCII_ParaAsBlanc = bASCII_ParaAsCR =
185 		bWriteClipboardDoc = bWriteOnlyFirstTable = bBlock =
186 		bOrganizerMode = sal_False;
187 }
188 
CopyNextPam(SwPaM ** ppPam)189 sal_Bool Writer::CopyNextPam( SwPaM ** ppPam )
190 {
191 	if( (*ppPam)->GetNext() == pOrigPam )
192 	{
193 		*ppPam = pOrigPam;			// wieder auf den Anfangs-Pam setzen
194 		return sal_False;				// Ende vom Ring
195 	}
196 
197 	// ansonsten kopiere den die Werte aus dem naechsten Pam
198 	*ppPam = ((SwPaM*)(*ppPam)->GetNext() );
199 
200 	*pCurPam->GetPoint() = *(*ppPam)->Start();
201 	*pCurPam->GetMark() = *(*ppPam)->End();
202 
203 	return sal_True;
204 }
205 
206 // suche die naechste Bookmark-Position aus der Bookmark-Tabelle
207 
FindPos_Bkmk(const SwPosition & rPos) const208 sal_Int32 Writer::FindPos_Bkmk(const SwPosition& rPos) const
209 {
210     const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
211     const IDocumentMarkAccess::const_iterator_t ppBkmk = ::std::lower_bound(
212         pMarkAccess->getAllMarksBegin(),
213         pMarkAccess->getAllMarksEnd(),
214         rPos,
215         ::boost::bind(&::sw::mark::IMark::StartsBefore, _1, _2)); // find the first Mark that does not start before
216     if(ppBkmk != pMarkAccess->getAllMarksEnd())
217         return ppBkmk - pMarkAccess->getAllMarksBegin();
218     return -1;
219 }
220 
221 
222 SwPaM *
NewSwPaM(SwDoc & rDoc,sal_uLong const nStartIdx,sal_uLong const nEndIdx)223 Writer::NewSwPaM(SwDoc & rDoc, sal_uLong const nStartIdx, sal_uLong const nEndIdx)
224 {
225     SwNodes *const pNds = &rDoc.GetNodes();
226 
227 	SwNodeIndex aStt( *pNds, nStartIdx );
228 	SwCntntNode* pCNode = aStt.GetNode().GetCntntNode();
229 	if( !pCNode && 0 == ( pCNode = pNds->GoNext( &aStt )) )
230     {
231 		ASSERT( false, "An StartPos kein ContentNode mehr" );
232     }
233 
234 	SwPaM* pNew = new SwPaM( aStt );
235 	pNew->SetMark();
236 	aStt = nEndIdx;
237 	if( 0 == (pCNode = aStt.GetNode().GetCntntNode()) &&
238 		0 == (pCNode = pNds->GoPrevious( &aStt )) )
239     {
240 		ASSERT( false, "An StartPos kein ContentNode mehr" );
241     }
242 	pCNode->MakeEndIndex( &pNew->GetPoint()->nContent );
243 	pNew->GetPoint()->nNode = aStt;
244 	return pNew;
245 }
246 
247 /////////////////////////////////////////////////////////////////////////////
248 
249 // Stream-spezifisches
Strm()250 SvStream& Writer::Strm()
251 {
252     ASSERT( m_pImpl->m_pStream, "Oh-oh. Writer with no Stream!" );
253     return *m_pImpl->m_pStream;
254 }
255 
SetStream(SvStream * const pStream)256 void Writer::SetStream(SvStream *const pStream)
257 { m_pImpl->m_pStream = pStream; }
258 
259 
OutHex(SvStream & rStrm,sal_uLong nHex,sal_uInt8 nLen)260 SvStream& Writer::OutHex( SvStream& rStrm, sal_uLong nHex, sal_uInt8 nLen )
261 {												   // in einen Stream aus
262 	// Pointer an das Bufferende setzen
263 	sal_Char* pStr = aNToABuf + (NTOABUFLEN-1);
264 	for( sal_uInt8 n = 0; n < nLen; ++n )
265 	{
266 		*(--pStr) = (sal_Char)(nHex & 0xf ) + 48;
267 		if( *pStr > '9' )
268 			*pStr += 39;
269 		nHex >>= 4;
270 	}
271 	return rStrm << pStr;
272 }
273 
OutLong(SvStream & rStrm,long nVal)274 SvStream& Writer::OutLong( SvStream& rStrm, long nVal )
275 {
276 	// Pointer an das Bufferende setzen
277 	sal_Char* pStr = aNToABuf + (NTOABUFLEN-1);
278 
279 	int bNeg = nVal < 0;
280 	if( bNeg )
281 		nVal = -nVal;
282 
283 	do {
284 		*(--pStr) = (sal_Char)(nVal % 10 ) + 48;
285 		nVal /= 10;
286 	} while( nVal );
287 
288 	// Ist Zahl negativ, dann noch -
289 	if( bNeg )
290 		*(--pStr) = '-';
291 
292 	return rStrm << pStr;
293 }
294 
OutULong(SvStream & rStrm,sal_uLong nVal)295 SvStream& Writer::OutULong( SvStream& rStrm, sal_uLong nVal )
296 {
297 	// Pointer an das Bufferende setzen
298 	sal_Char* pStr = aNToABuf + (NTOABUFLEN-1);
299 
300 	do {
301 		*(--pStr) = (sal_Char)(nVal % 10 ) + 48;
302 		nVal /= 10;
303 	} while ( nVal );
304 	return rStrm << pStr;
305 }
306 
307 
Write(SwPaM & rPaM,SvStream & rStrm,const String * pFName)308 sal_uLong Writer::Write( SwPaM& rPaM, SvStream& rStrm, const String* pFName )
309 {
310     if ( IsStgWriter() )
311     {
312         SotStorageRef aRef = new SotStorage( rStrm );
313         sal_uLong nResult = Write( rPaM, *aRef, pFName );
314 		if ( nResult == ERRCODE_NONE )
315 			aRef->Commit();
316 		return nResult;
317     }
318 
319 	pDoc = rPaM.GetDoc();
320 	pOrigFileName = pFName;
321     m_pImpl->m_pStream = &rStrm;
322 
323 	// PaM kopieren, damit er veraendert werden kann
324 	pCurPam = new SwPaM( *rPaM.End(), *rPaM.Start() );
325 	// zum Vergleich auf den akt. Pam sichern
326 	pOrigPam = &rPaM;
327 
328 	sal_uLong nRet = WriteStream();
329 
330 	ResetWriter();
331 
332 	return nRet;
333 }
334 
Write(SwPaM & rPam,SfxMedium & rMed,const String * pFileName)335 sal_uLong Writer::Write( SwPaM& rPam, SfxMedium& rMed, const String* pFileName )
336 {
337 	// This method must be overloaded in SwXMLWriter a storage from medium will be used there.
338 	// The microsoft format can write to storage but the storage will be based on the stream.
339 	return Write( rPam, *rMed.GetOutStream(), pFileName );
340 }
341 
Write(SwPaM &,SvStorage &,const String *)342 sal_uLong Writer::Write( SwPaM& /*rPam*/, SvStorage&, const String* )
343 {
344 	ASSERT( sal_False, "Write in storage on a stream?" );
345 	return ERR_SWG_WRITE_ERROR;
346 }
347 
Write(SwPaM &,const uno::Reference<embed::XStorage> &,const String *,SfxMedium *)348 sal_uLong Writer::Write( SwPaM&, const uno::Reference < embed::XStorage >&, const String*, SfxMedium* )
349 {
350 	ASSERT( sal_False, "Write in storage on a stream?" );
351 	return ERR_SWG_WRITE_ERROR;
352 }
353 
CopyLocalFileToINet(String & rFileNm)354 sal_Bool Writer::CopyLocalFileToINet( String& rFileNm )
355 {
356 	if( !pOrigFileName )		        // can be happen, by example if we
357 		return sal_False;                   // write into the clipboard
358 
359 	sal_Bool bRet = sal_False;
360 	INetURLObject aFileUrl( rFileNm ), aTargetUrl( *pOrigFileName );
361 
362 // JP 01.11.00: what is the correct question for the portal??
363 //	if( aFileUrl.GetProtocol() == aFileUrl.GetProtocol() )
364 //		return bRet;
365 // this is our old without the Mail-Export
366     if( ! ( INET_PROT_FILE == aFileUrl.GetProtocol() &&
367 			INET_PROT_FILE != aTargetUrl.GetProtocol() &&
368         	INET_PROT_FTP <= aTargetUrl.GetProtocol() &&
369         	INET_PROT_NEWS >= aTargetUrl.GetProtocol() ) )
370 		return bRet;
371 
372     if (m_pImpl->pSrcArr)
373 	{
374 		// wurde die Datei schon verschoben
375 		sal_uInt16 nPos;
376         if (m_pImpl->pSrcArr->Seek_Entry( &rFileNm, &nPos ))
377         {
378             rFileNm = *(*m_pImpl->pDestArr)[ nPos ];
379 			return sal_True;
380 		}
381 	}
382 	else
383     {
384         m_pImpl->pSrcArr = new SvStringsSortDtor( 4, 4 );
385         m_pImpl->pDestArr = new SvStringsSortDtor( 4, 4 );
386     }
387 
388 	String *pSrc = new String( rFileNm );
389 	String *pDest = new String( aTargetUrl.GetPartBeforeLastName() );
390 	*pDest += String(aFileUrl.GetName());
391 
392 	SfxMedium aSrcFile( *pSrc, STREAM_READ, sal_False );
393 	SfxMedium aDstFile( *pDest, STREAM_WRITE | STREAM_SHARE_DENYNONE, sal_False );
394 
395 	*aDstFile.GetOutStream() << *aSrcFile.GetInStream();
396 
397 	aSrcFile.Close();
398 	aDstFile.Commit();
399 
400 	bRet = 0 == aDstFile.GetError();
401 
402 	if( bRet )
403     {
404         m_pImpl->pSrcArr->Insert( pSrc );
405         m_pImpl->pDestArr->Insert( pDest );
406 		rFileNm = *pDest;
407 	}
408 	else
409 	{
410 		delete pSrc;
411 		delete pDest;
412 	}
413 
414 	return bRet;
415 }
416 
PutNumFmtFontsInAttrPool()417 void Writer::PutNumFmtFontsInAttrPool()
418 {
419 	// dann gibt es noch in den NumRules ein paar Fonts
420 	// Diese in den Pool putten. Haben sie danach einen RefCount > 1
421 	// kann es wieder entfernt werden - ist schon im Pool
422 	SfxItemPool& rPool = pDoc->GetAttrPool();
423 	const SwNumRuleTbl& rListTbl = pDoc->GetNumRuleTbl();
424 	const SwNumRule* pRule;
425 	const SwNumFmt* pFmt;
426     // --> OD 2006-06-27 #b644095#
427 //    const Font *pFont, *pDefFont = &SwNumRule::GetDefBulletFont();
428     const Font* pFont;
429     const Font* pDefFont = &numfunc::GetDefBulletFont();
430     // <--
431 	sal_Bool bCheck = sal_False;
432 
433 	for( sal_uInt16 nGet = rListTbl.Count(); nGet; )
434 		if( pDoc->IsUsed( *(pRule = rListTbl[ --nGet ] )))
435 			for( sal_uInt8 nLvl = 0; nLvl < MAXLEVEL; ++nLvl )
436 				if( SVX_NUM_CHAR_SPECIAL == (pFmt = &pRule->Get( nLvl ))->GetNumberingType() ||
437 					SVX_NUM_BITMAP == pFmt->GetNumberingType() )
438 				{
439 					if( 0 == ( pFont = pFmt->GetBulletFont() ) )
440 						pFont = pDefFont;
441 
442 					if( bCheck )
443 					{
444 						if( *pFont == *pDefFont )
445 							continue;
446 					}
447 					else if( *pFont == *pDefFont )
448 						bCheck = sal_True;
449 
450 					_AddFontItem( rPool, SvxFontItem( pFont->GetFamily(),
451 								pFont->GetName(), pFont->GetStyleName(),
452                                 pFont->GetPitch(), pFont->GetCharSet(), RES_CHRATR_FONT ));
453 				}
454 }
455 
PutEditEngFontsInAttrPool(sal_Bool bIncl_CJK_CTL)456 void Writer::PutEditEngFontsInAttrPool( sal_Bool bIncl_CJK_CTL )
457 {
458 	SfxItemPool& rPool = pDoc->GetAttrPool();
459 	if( rPool.GetSecondaryPool() )
460 	{
461 		_AddFontItems( rPool, EE_CHAR_FONTINFO );
462 		if( bIncl_CJK_CTL )
463 		{
464 			_AddFontItems( rPool, EE_CHAR_FONTINFO_CJK );
465 			_AddFontItems( rPool, EE_CHAR_FONTINFO_CTL );
466 		}
467 	}
468 }
469 
PutCJKandCTLFontsInAttrPool()470 void Writer::PutCJKandCTLFontsInAttrPool()
471 {
472 	SfxItemPool& rPool = pDoc->GetAttrPool();
473 	_AddFontItems( rPool, RES_CHRATR_CJK_FONT );
474 	_AddFontItems( rPool, RES_CHRATR_CTL_FONT );
475 }
476 
477 
_AddFontItems(SfxItemPool & rPool,sal_uInt16 nW)478 void Writer::_AddFontItems( SfxItemPool& rPool, sal_uInt16 nW )
479 {
480 	const SvxFontItem* pFont = (const SvxFontItem*)&rPool.GetDefaultItem( nW );
481 	_AddFontItem( rPool, *pFont );
482 
483 	if( 0 != ( pFont = (const SvxFontItem*)rPool.GetPoolDefaultItem( nW )) )
484 		_AddFontItem( rPool, *pFont );
485 
486 	sal_uInt32 nMaxItem = rPool.GetItemCount2( nW );
487 	for( sal_uInt32 nGet = 0; nGet < nMaxItem; ++nGet )
488 		if( 0 != (pFont = (const SvxFontItem*)rPool.GetItem2( nW, nGet )) )
489 			_AddFontItem( rPool, *pFont );
490 }
491 
_AddFontItem(SfxItemPool & rPool,const SvxFontItem & rFont)492 void Writer::_AddFontItem( SfxItemPool& rPool, const SvxFontItem& rFont )
493 {
494 	const SvxFontItem* pItem;
495 	if( RES_CHRATR_FONT != rFont.Which() )
496 	{
497 		SvxFontItem aFont( rFont );
498 		aFont.SetWhich( RES_CHRATR_FONT );
499 		pItem = (SvxFontItem*)&rPool.Put( aFont );
500 	}
501 	else
502 		pItem = (SvxFontItem*)&rPool.Put( rFont );
503 
504 	if( 1 < pItem->GetRefCount() )
505 		rPool.Remove( *pItem );
506 	else
507     {
508         if (!m_pImpl->pFontRemoveLst)
509         {
510             m_pImpl->pFontRemoveLst = new SvPtrarr( 0, 10 );
511         }
512 
513 		void* p = (void*)pItem;
514         m_pImpl->pFontRemoveLst->Insert( p, m_pImpl->pFontRemoveLst->Count() );
515 	}
516 }
517 
518 // build a bookmark table, which is sort by the node position. The
519 // OtherPos of the bookmarks also inserted.
CreateBookmarkTbl()520 void Writer::CreateBookmarkTbl()
521 {
522     const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
523     for(IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->getBookmarksBegin();
524         ppBkmk != pMarkAccess->getBookmarksEnd();
525         ++ppBkmk)
526     {
527         m_pImpl->InsertBkmk(**ppBkmk);
528     }
529 }
530 
531 
532 // search alle Bookmarks in the range and return it in the Array
GetBookmarks(const SwCntntNode & rNd,xub_StrLen nStt,xub_StrLen nEnd,SvPtrarr & rArr)533 sal_uInt16 Writer::GetBookmarks(const SwCntntNode& rNd, xub_StrLen nStt,
534     xub_StrLen nEnd, SvPtrarr& rArr)
535 {
536     ASSERT( !rArr.Count(), "es sind noch Eintraege vorhanden" );
537 
538     sal_uLong nNd = rNd.GetIndex();
539     SvPtrarr* pArr = (m_pImpl->pBkmkNodePos) ?
540         m_pImpl->pBkmkNodePos->Get( nNd ) : 0;
541     if( pArr )
542     {
543         // there exist some bookmarks, search now all which is in the range
544         if( !nStt && nEnd == rNd.Len() )
545             // all
546             rArr.Insert( pArr, 0 );
547         else
548         {
549             sal_uInt16 n;
550             xub_StrLen nCntnt;
551             for( n = 0; n < pArr->Count(); ++n )
552             {
553                 void* p = (*pArr)[ n ];
554                 const ::sw::mark::IMark& rBkmk = *(::sw::mark::IMark *)p;
555                 if( rBkmk.GetMarkPos().nNode == nNd &&
556                     (nCntnt = rBkmk.GetMarkPos().nContent.GetIndex() ) >= nStt &&
557                     nCntnt < nEnd )
558                 {
559                     rArr.Insert( p, rArr.Count() );
560                 }
561                 else if( rBkmk.IsExpanded() && nNd ==
562                         rBkmk.GetOtherMarkPos().nNode.GetIndex() && (nCntnt =
563                         rBkmk.GetOtherMarkPos().nContent.GetIndex() ) >= nStt &&
564                         nCntnt < nEnd )
565                 {
566                     rArr.Insert( p, rArr.Count() );
567                 }
568             }
569         }
570     }
571     return rArr.Count();
572 }
573 
574 ////////////////////////////////////////////////////////////////////////////
575 
576 // Storage-spezifisches
577 
WriteStream()578 sal_uLong StgWriter::WriteStream()
579 {
580 	ASSERT( sal_False, "Write in streams on a storage?" );
581 	return ERR_SWG_WRITE_ERROR;
582 }
583 
Write(SwPaM & rPaM,SvStorage & rStg,const String * pFName)584 sal_uLong StgWriter::Write( SwPaM& rPaM, SvStorage& rStg, const String* pFName )
585 {
586     SetStream(0);
587 	pStg = &rStg;
588 	pDoc = rPaM.GetDoc();
589 	pOrigFileName = pFName;
590 
591 	// PaM kopieren, damit er veraendert werden kann
592 	pCurPam = new SwPaM( *rPaM.End(), *rPaM.Start() );
593 	// zum Vergleich auf den akt. Pam sichern
594 	pOrigPam = &rPaM;
595 
596 	sal_uLong nRet = WriteStorage();
597 
598 	pStg = NULL;
599 	ResetWriter();
600 
601 	return nRet;
602 }
603 
Write(SwPaM & rPaM,const uno::Reference<embed::XStorage> & rStg,const String * pFName,SfxMedium * pMedium)604 sal_uLong StgWriter::Write( SwPaM& rPaM, const uno::Reference < embed::XStorage >& rStg, const String* pFName, SfxMedium* pMedium )
605 {
606     SetStream(0);
607     pStg = 0;
608     xStg = rStg;
609 	pDoc = rPaM.GetDoc();
610 	pOrigFileName = pFName;
611 
612 	// PaM kopieren, damit er veraendert werden kann
613 	pCurPam = new SwPaM( *rPaM.End(), *rPaM.Start() );
614 	// zum Vergleich auf den akt. Pam sichern
615 	pOrigPam = &rPaM;
616 
617 	sal_uLong nRet = pMedium ? WriteMedium( *pMedium ) : WriteStorage();
618 
619 	pStg = NULL;
620 	ResetWriter();
621 
622 	return nRet;
623 }
624 
625