xref: /trunk/main/sw/source/core/doc/doc.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 #include <doc.hxx>
32 #include <UndoManager.hxx>
33 #include <hintids.hxx>
34 
35 #include <tools/shl.hxx>
36 #include <tools/globname.hxx>
37 #include <svx/svxids.hrc>
38 #include <com/sun/star/i18n/WordType.hdl>
39 #include <com/sun/star/i18n/ForbiddenCharacters.hdl>
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/beans/NamedValue.hpp>
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
44 #include <com/sun/star/document/XDocumentProperties.hpp>
45 #include <comphelper/processfactory.hxx>
46 #include <tools/urlobj.hxx>
47 #include <tools/poly.hxx>
48 #include <tools/multisel.hxx>
49 #include <rtl/ustring.hxx>
50 #include <vcl/virdev.hxx>
51 #include <svl/itemiter.hxx>
52 #include <svl/poolitem.hxx>
53 #include <unotools/syslocale.hxx>
54 #include <sfx2/printer.hxx>
55 #include <editeng/keepitem.hxx>
56 #include <editeng/cscoitem.hxx>
57 #include <editeng/brkitem.hxx>
58 #include <sfx2/linkmgr.hxx>
59 #include <editeng/forbiddencharacterstable.hxx>
60 #include <svx/svdmodel.hxx>
61 #include <editeng/pbinitem.hxx>
62 #include <unotools/charclass.hxx>
63 #include <unotools/localedatawrapper.hxx>
64 
65 #include <swatrset.hxx>
66 #include <swmodule.hxx>
67 #include <fmtpdsc.hxx>
68 #include <fmtanchr.hxx>
69 #include <fmtrfmrk.hxx>
70 #include <fmtinfmt.hxx>
71 #include <fmtfld.hxx>
72 #include <txtfld.hxx>
73 #include <dbfld.hxx>
74 #include <txtinet.hxx>
75 #include <txtrfmrk.hxx>
76 #include <frmatr.hxx>
77 #include <linkenum.hxx>
78 #include <errhdl.hxx>
79 #include <pagefrm.hxx>
80 #include <rootfrm.hxx>
81 #include <swtable.hxx>
82 #include <pam.hxx>
83 #include <ndtxt.hxx>
84 #include <swundo.hxx>			// fuer die UndoIds
85 #include <UndoCore.hxx>
86 #include <UndoInsert.hxx>
87 #include <UndoSplitMove.hxx>
88 #include <UndoTable.hxx>
89 #include <pagedesc.hxx> //DTor
90 #include <breakit.hxx>
91 #include <ndole.hxx>
92 #include <ndgrf.hxx>
93 #include <rolbck.hxx>			// Undo-Attr
94 #include <doctxm.hxx>			// fuer die Verzeichnisse
95 #include <grfatr.hxx>
96 #include <poolfmt.hxx>			// PoolVorlagen-Id's
97 #include <mvsave.hxx>			// fuer Server-Funktionalitaet
98 #include <SwGrammarMarkUp.hxx>
99 #include <scriptinfo.hxx>
100 #include <acorrect.hxx>			// Autokorrektur
101 #include <mdiexp.hxx>	   		// Statusanzeige
102 #include <docstat.hxx>
103 #include <docary.hxx>
104 #include <redline.hxx>
105 #include <fldupde.hxx>
106 #include <swbaslnk.hxx>
107 #include <printdata.hxx>
108 #include <cmdid.h>              // fuer den dflt - Printer in SetJob
109 #include <statstr.hrc>      	// StatLine-String
110 #include <comcore.hrc>
111 #include <SwUndoTOXChange.hxx>
112 #include <SwUndoFmt.hxx>
113 #include <unocrsr.hxx>
114 #include <docsh.hxx>
115 #include <viewopt.hxx>
116 #include <docfld.hxx>           // _SetGetExpFld
117 #include <docufld.hxx>          // SwPostItField
118 #include <viewsh.hxx>
119 #include <shellres.hxx>
120 #include <txtfrm.hxx>
121 #include <attrhint.hxx>
122 
123 #include <wdocsh.hxx>           // SwWebDocShell
124 #include <prtopt.hxx>           // SwPrintOptions
125 
126 #include <vector>
127 #include <map>
128 
129 #include <osl/diagnose.h>
130 #include <osl/interlck.h>
131 #include <vbahelper/vbaaccesshelper.hxx>
132 
133 #include "switerator.hxx"
134 
135 /* @@@MAINTAINABILITY-HORROR@@@
136    Probably unwanted dependency on SwDocShell
137 */
138 // --> OD 2005-08-29 #125370#
139 #include <layouter.hxx>
140 // <--
141 
142 using namespace ::com::sun::star;
143 using ::rtl::OUString;
144 
145 
146 // Seiten-Deskriptoren
147 SV_IMPL_PTRARR(SwPageDescs,SwPageDescPtr);
148 // Verzeichnisse
149 SV_IMPL_PTRARR( SwTOXTypes, SwTOXTypePtr )
150 // FeldTypen
151 SV_IMPL_PTRARR( SwFldTypes, SwFldTypePtr)
152 
153 /** IInterface
154 */
155 sal_Int32 SwDoc::acquire()
156 {
157     OSL_ASSERT(mReferenceCount >= 0 && "Negative reference count detected! This is a sign for unbalanced acquire/release calls.");
158     return osl_incrementInterlockedCount(&mReferenceCount);
159 }
160 
161 sal_Int32 SwDoc::release()
162 {
163     OSL_PRECOND(mReferenceCount >= 1, "Object is already released! Releasing it again leads to a negative reference count.");
164     return osl_decrementInterlockedCount(&mReferenceCount);
165 }
166 
167 sal_Int32 SwDoc::getReferenceCount() const
168 {
169     OSL_ASSERT(mReferenceCount >= 0 && "Negative reference count detected! This is a sign for unbalanced acquire/release calls.");
170     return mReferenceCount;
171 }
172 
173 /** IDocumentSettingAccess
174 */
175 bool SwDoc::get(/*[in]*/ DocumentSettingId id) const
176 {
177     switch (id)
178     {
179         // COMPATIBILITY FLAGS START
180         case PARA_SPACE_MAX: return mbParaSpaceMax; //(n8Dummy1 & DUMMY_PARASPACEMAX);
181         case PARA_SPACE_MAX_AT_PAGES: return mbParaSpaceMaxAtPages; //(n8Dummy1 & DUMMY_PARASPACEMAX_AT_PAGES);
182         case TAB_COMPAT: return mbTabCompat; //(n8Dummy1 & DUMMY_TAB_COMPAT);
183         case ADD_FLY_OFFSETS: return mbAddFlyOffsets; //(n8Dummy2 & DUMMY_ADD_FLY_OFFSETS);
184         case ADD_EXT_LEADING: return mbAddExternalLeading; //(n8Dummy2 & DUMMY_ADD_EXTERNAL_LEADING);
185         case USE_VIRTUAL_DEVICE: return mbUseVirtualDevice; //(n8Dummy1 & DUMMY_USE_VIRTUAL_DEVICE);
186         case USE_HIRES_VIRTUAL_DEVICE: return mbUseHiResolutionVirtualDevice; //(n8Dummy2 & DUMMY_USE_HIRES_VIR_DEV);
187         case OLD_NUMBERING: return mbOldNumbering;
188         case OLD_LINE_SPACING: return mbOldLineSpacing;
189         case ADD_PARA_SPACING_TO_TABLE_CELLS: return mbAddParaSpacingToTableCells;
190         case USE_FORMER_OBJECT_POS: return mbUseFormerObjectPos;
191         case USE_FORMER_TEXT_WRAPPING: return mbUseFormerTextWrapping;
192         case CONSIDER_WRAP_ON_OBJECT_POSITION: return mbConsiderWrapOnObjPos;
193         case DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK: return mbDoNotJustifyLinesWithManualBreak;
194         case IGNORE_FIRST_LINE_INDENT_IN_NUMBERING: return mbIgnoreFirstLineIndentInNumbering;
195         case OUTLINE_LEVEL_YIELDS_OUTLINE_RULE: return mbOutlineLevelYieldsOutlineRule;
196 	    case TABLE_ROW_KEEP: return mbTableRowKeep;
197 	    case IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION: return mbIgnoreTabsAndBlanksForLineCalculation;
198 	    case DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE: return mbDoNotCaptureDrawObjsOnPage;
199         // --> OD 2006-08-25 #i68949#
200         case CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAME: return mbClipAsCharacterAnchoredWriterFlyFrames;
201         // <--
202         case UNIX_FORCE_ZERO_EXT_LEADING: return mbUnixForceZeroExtLeading;
203         case USE_OLD_PRINTER_METRICS: return mbOldPrinterMetrics;
204         case TABS_RELATIVE_TO_INDENT : return mbTabRelativeToIndent;
205         case PROTECT_FORM: return mbProtectForm;
206         // --> OD 2008-06-05 #i89181#
207         case TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST: return mbTabAtLeftIndentForParagraphsInList;
208         // <--
209          // COMPATIBILITY FLAGS END
210 
211         case BROWSE_MODE: return mbLastBrowseMode; // Attention: normally the ViewShell has to be asked!
212         case HTML_MODE: return mbHTMLMode;
213         case GLOBAL_DOCUMENT: return mbIsGlobalDoc;
214         case GLOBAL_DOCUMENT_SAVE_LINKS: return mbGlblDocSaveLinks;
215         case LABEL_DOCUMENT: return mbIsLabelDoc;
216         case PURGE_OLE: return mbPurgeOLE;
217         case KERN_ASIAN_PUNCTUATION: return mbKernAsianPunctuation;
218         case DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT: return mbDoNotResetParaAttrsForNumFont;
219         case MATH_BASELINE_ALIGNMENT: return mbMathBaselineAlignment;
220         default:
221             ASSERT(false, "Invalid setting id");
222     }
223     return false;
224 }
225 
226 void SwDoc::set(/*[in]*/ DocumentSettingId id, /*[in]*/ bool value)
227 {
228     switch (id)
229     {
230         // COMPATIBILITY FLAGS START
231         case PARA_SPACE_MAX:
232             mbParaSpaceMax = value;
233             break;
234         case PARA_SPACE_MAX_AT_PAGES:
235             mbParaSpaceMaxAtPages = value;
236             break;
237         case TAB_COMPAT:
238             mbTabCompat = value;
239             break;
240         case ADD_FLY_OFFSETS:
241             mbAddFlyOffsets = value;
242             break;
243         case ADD_EXT_LEADING:
244             mbAddExternalLeading = value;
245             break;
246         case USE_VIRTUAL_DEVICE:
247             mbUseVirtualDevice = value;
248             break;
249         case USE_HIRES_VIRTUAL_DEVICE:
250             mbUseHiResolutionVirtualDevice = value;
251             break;
252         case OLD_NUMBERING:
253             if (mbOldNumbering != value)
254             {
255                 mbOldNumbering = value;
256 
257                 const SwNumRuleTbl& rNmTbl = GetNumRuleTbl();
258                 for( sal_uInt16 n = 0; n < rNmTbl.Count(); ++n )
259                     rNmTbl[n]->SetInvalidRule(sal_True);
260 
261                 UpdateNumRule();
262 
263                 if (pOutlineRule)
264                 {
265                     pOutlineRule->Validate();
266                     // --> OD 2005-10-21 - counting of phantoms depends on <IsOldNumbering()>
267                     pOutlineRule->SetCountPhantoms( !mbOldNumbering );
268                     // <--
269                 }
270             }
271             break;
272         case OLD_LINE_SPACING:
273             mbOldLineSpacing = value;
274             break;
275         case ADD_PARA_SPACING_TO_TABLE_CELLS:
276             mbAddParaSpacingToTableCells = value;
277             break;
278         case USE_FORMER_OBJECT_POS:
279             mbUseFormerObjectPos = value;
280             break;
281         case USE_FORMER_TEXT_WRAPPING:
282             mbUseFormerTextWrapping = value;
283             break;
284         case CONSIDER_WRAP_ON_OBJECT_POSITION:
285             mbConsiderWrapOnObjPos = value;
286             break;
287         case DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK:
288             mbDoNotJustifyLinesWithManualBreak = value;
289             break;
290         case IGNORE_FIRST_LINE_INDENT_IN_NUMBERING:
291             mbIgnoreFirstLineIndentInNumbering = value;
292             break;
293 
294         case OUTLINE_LEVEL_YIELDS_OUTLINE_RULE:
295             mbOutlineLevelYieldsOutlineRule = value;
296             break;
297 
298 	    case TABLE_ROW_KEEP:
299 	        mbTableRowKeep = value;
300 	        break;
301 
302 	    case IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION:
303 		    mbIgnoreTabsAndBlanksForLineCalculation = value;
304 			break;
305 
306 	    case DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE:
307 		    mbDoNotCaptureDrawObjsOnPage = value;
308 			break;
309 
310         // --> OD 2006-08-25 #i68949#
311         case CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAME:
312             mbClipAsCharacterAnchoredWriterFlyFrames = value;
313             break;
314         // <--
315         case UNIX_FORCE_ZERO_EXT_LEADING:
316             mbUnixForceZeroExtLeading = value;
317             break;
318         case PROTECT_FORM:
319 	    mbProtectForm = value;
320 	    break;
321 
322         case USE_OLD_PRINTER_METRICS:
323             mbOldPrinterMetrics = value;
324             break;
325         case TABS_RELATIVE_TO_INDENT:
326             mbTabRelativeToIndent = value;
327         break;
328         // --> OD 2008-06-05 #i89181#
329         case TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST:
330             mbTabAtLeftIndentForParagraphsInList = value;
331         break;
332         // <--
333          // COMPATIBILITY FLAGS END
334 
335         case BROWSE_MODE: //can be used temporary (load/save) when no ViewShell is avaiable
336             mbLastBrowseMode = value;
337             break;
338         case HTML_MODE:
339             mbHTMLMode = value;
340             break;
341         case GLOBAL_DOCUMENT:
342             mbIsGlobalDoc = value;
343             break;
344         case GLOBAL_DOCUMENT_SAVE_LINKS:
345             mbGlblDocSaveLinks = value;
346             break;
347         case LABEL_DOCUMENT:
348             mbIsLabelDoc = value;
349             break;
350         case PURGE_OLE:
351             mbPurgeOLE = value;
352             break;
353         case KERN_ASIAN_PUNCTUATION:
354             mbKernAsianPunctuation = value;
355             break;
356         case DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT:
357             mbDoNotResetParaAttrsForNumFont = value;
358             break;
359         case MATH_BASELINE_ALIGNMENT:
360             mbMathBaselineAlignment  = value;
361             break;
362         default:
363             ASSERT(false, "Invalid setting id");
364     }
365 }
366 
367 const i18n::ForbiddenCharacters*
368     SwDoc::getForbiddenCharacters(/*[in]*/ sal_uInt16 nLang, /*[in]*/ bool bLocaleData ) const
369 {
370     const i18n::ForbiddenCharacters* pRet = 0;
371     if( xForbiddenCharsTable.isValid() )
372         pRet = xForbiddenCharsTable->GetForbiddenCharacters( nLang, sal_False );
373     if( bLocaleData && !pRet && pBreakIt )
374         pRet = &pBreakIt->GetForbidden( (LanguageType)nLang );
375     return pRet;
376 }
377 
378 void SwDoc::setForbiddenCharacters(/*[in]*/ sal_uInt16 nLang,
379                                    /*[in]*/ const com::sun::star::i18n::ForbiddenCharacters& rFChars )
380 {
381     if( !xForbiddenCharsTable.isValid() )
382     {
383         uno::Reference<
384             lang::XMultiServiceFactory > xMSF =
385                                     ::comphelper::getProcessServiceFactory();
386         xForbiddenCharsTable = new SvxForbiddenCharactersTable( xMSF );
387     }
388     xForbiddenCharsTable->SetForbiddenCharacters( nLang, rFChars );
389     if( pDrawModel )
390     {
391         pDrawModel->SetForbiddenCharsTable( xForbiddenCharsTable );
392         if( !mbInReading )
393             pDrawModel->ReformatAllTextObjects();
394     }
395 
396     SwRootFrm* pTmpRoot = GetCurrentLayout();
397 	if( pTmpRoot && !mbInReading )
398     {
399         pTmpRoot->StartAllAction();
400 		std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
401 		std::for_each( aAllLayouts.begin(), aAllLayouts.end(), std::bind2nd(std::mem_fun(&SwRootFrm::InvalidateAllCntnt), INV_SIZE));
402         pTmpRoot->EndAllAction();
403     }//swmod 080310
404     SetModified();
405 }
406 
407 vos::ORef<SvxForbiddenCharactersTable>& SwDoc::getForbiddenCharacterTable()
408 {
409     if( !xForbiddenCharsTable.isValid() )
410     {
411         uno::Reference<
412             lang::XMultiServiceFactory > xMSF =
413                                     ::comphelper::getProcessServiceFactory();
414         xForbiddenCharsTable = new SvxForbiddenCharactersTable( xMSF );
415     }
416     return xForbiddenCharsTable;
417 }
418 
419 const vos::ORef<SvxForbiddenCharactersTable>& SwDoc::getForbiddenCharacterTable() const
420 {
421     return xForbiddenCharsTable;
422 }
423 
424 sal_uInt16 SwDoc::getLinkUpdateMode( /*[in]*/bool bGlobalSettings ) const
425 {
426     sal_uInt16 nRet = nLinkUpdMode;
427     if( bGlobalSettings && GLOBALSETTING == nRet )
428         nRet = SW_MOD()->GetLinkUpdMode(get(IDocumentSettingAccess::HTML_MODE));
429     return nRet;
430 }
431 
432 void SwDoc::setLinkUpdateMode( /*[in]*/sal_uInt16 eMode )
433 {
434     nLinkUpdMode = eMode;
435 }
436 
437 SwFldUpdateFlags SwDoc::getFieldUpdateFlags( /*[in]*/bool bGlobalSettings ) const
438 {
439     SwFldUpdateFlags eRet = eFldUpdMode;
440     if( bGlobalSettings && AUTOUPD_GLOBALSETTING == eRet )
441         eRet = SW_MOD()->GetFldUpdateFlags(get(IDocumentSettingAccess::HTML_MODE));
442     return eRet;
443 }
444 
445 void SwDoc::setFieldUpdateFlags(/*[in]*/SwFldUpdateFlags eMode )
446 {
447     eFldUpdMode = eMode;
448 }
449 
450 SwCharCompressType SwDoc::getCharacterCompressionType() const
451 {
452     return eChrCmprType;
453 }
454 
455 void SwDoc::setCharacterCompressionType( /*[in]*/SwCharCompressType n )
456 {
457     if( eChrCmprType != n )
458     {
459         eChrCmprType = n;
460         if( pDrawModel )
461         {
462             pDrawModel->SetCharCompressType( static_cast<sal_uInt16>(n) );
463             if( !mbInReading )
464                 pDrawModel->ReformatAllTextObjects();
465         }
466 
467 		SwRootFrm* pTmpRoot = GetCurrentLayout();
468 		if( pTmpRoot && !mbInReading )
469         {
470 			pTmpRoot->StartAllAction();
471 			std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
472 			std::for_each( aAllLayouts.begin(), aAllLayouts.end(), std::bind2nd(std::mem_fun(&SwRootFrm::InvalidateAllCntnt), INV_SIZE));
473 			pTmpRoot->EndAllAction();
474 		}//swmod 080310
475         SetModified();
476     }
477 }
478 
479 /** IDocumentDeviceAccess
480 */
481 SfxPrinter* SwDoc::getPrinter(/*[in]*/ bool bCreate ) const
482 {
483     SfxPrinter* pRet = 0;
484     if ( !bCreate || pPrt )
485         pRet = pPrt;
486     else
487         pRet = &CreatePrinter_();
488 
489     return pRet;
490 }
491 
492 void SwDoc::setPrinter(/*[in]*/ SfxPrinter *pP,/*[in]*/ bool bDeleteOld,/*[in]*/ bool bCallPrtDataChanged )
493 {
494     if ( pP != pPrt )
495     {
496         if ( bDeleteOld )
497             delete pPrt;
498         pPrt = pP;
499 
500         // our printer should always use TWIP. Don't rely on this being set in ViewShell::InitPrt, there
501         // are situations where this isn't called.
502         // #i108712# / 2010-02-26 / frank.schoenheit@sun.com
503         if ( pPrt )
504         {
505             MapMode aMapMode( pPrt->GetMapMode() );
506             aMapMode.SetMapUnit( MAP_TWIP );
507             pPrt->SetMapMode( aMapMode );
508         }
509 
510         if ( pDrawModel && !get( IDocumentSettingAccess::USE_VIRTUAL_DEVICE ) )
511             pDrawModel->SetRefDevice( pPrt );
512     }
513 
514     if ( bCallPrtDataChanged &&
515          // --> FME 2005-01-21 #i41075# Do not call PrtDataChanged() if we do not
516          // use the printer for formatting:
517          !get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) )
518         // <--
519         PrtDataChanged();
520 }
521 
522 VirtualDevice* SwDoc::getVirtualDevice(/*[in]*/ bool bCreate ) const
523 {
524     VirtualDevice* pRet = 0;
525     if ( !bCreate || pVirDev )
526         pRet = pVirDev;
527     else
528         pRet = &CreateVirtualDevice_();
529 
530     return pRet;
531 }
532 
533 void SwDoc::setVirtualDevice(/*[in]*/ VirtualDevice* pVd,/*[in]*/ bool bDeleteOld, /*[in]*/ bool )
534 {
535     if ( pVirDev != pVd )
536     {
537         if ( bDeleteOld )
538             delete pVirDev;
539         pVirDev = pVd;
540 
541         if ( pDrawModel && get( IDocumentSettingAccess::USE_VIRTUAL_DEVICE ) )
542             pDrawModel->SetRefDevice( pVirDev );
543     }
544 }
545 
546 OutputDevice* SwDoc::getReferenceDevice(/*[in]*/ bool bCreate ) const
547 {
548     OutputDevice* pRet = 0;
549     if ( !get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) )
550     {
551         pRet = getPrinter( bCreate );
552 
553         if ( bCreate && !pPrt->IsValid() )
554         {
555             pRet = getVirtualDevice( sal_True );
556         }
557     }
558     else
559     {
560         pRet = getVirtualDevice( bCreate );
561     }
562 
563     return pRet;
564 }
565 
566 void SwDoc::setReferenceDeviceType(/*[in]*/ bool bNewVirtual,/*[in]*/ bool bNewHiRes )
567 {
568     if ( get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) != bNewVirtual ||
569          get(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE) != bNewHiRes )
570     {
571         if ( bNewVirtual )
572         {
573             VirtualDevice* pMyVirDev = getVirtualDevice( true );
574             if ( !bNewHiRes )
575                 pMyVirDev->SetReferenceDevice( VirtualDevice::REFDEV_MODE06 );
576             else
577                 pMyVirDev->SetReferenceDevice( VirtualDevice::REFDEV_MODE_MSO1 );
578 
579             if( pDrawModel )
580                 pDrawModel->SetRefDevice( pMyVirDev );
581         }
582         else
583         {
584             // --> FME 2005-01-21 #i41075#
585             // We have to take care that a printer exists before calling
586             // PrtDataChanged() in order to prevent that PrtDataChanged()
587             // triggers this funny situation:
588             // getReferenceDevice()->getPrinter()->CreatePrinter_()
589             // ->setPrinter()-> PrtDataChanged()
590             SfxPrinter* pPrinter = getPrinter( true );
591             // <--
592             if( pDrawModel )
593                 pDrawModel->SetRefDevice( pPrinter );
594         }
595 
596         set(IDocumentSettingAccess::USE_VIRTUAL_DEVICE, bNewVirtual );
597         set(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE, bNewHiRes );
598         PrtDataChanged();
599         SetModified();
600     }
601 }
602 
603 const JobSetup* SwDoc::getJobsetup() const
604 {
605     return pPrt ? &pPrt->GetJobSetup() : 0;
606 }
607 
608 void SwDoc::setJobsetup(/*[in]*/ const JobSetup &rJobSetup )
609 {
610     sal_Bool bCheckPageDescs = 0 == pPrt;
611     sal_Bool bDataChanged = sal_False;
612 
613     if ( pPrt )
614     {
615         if ( pPrt->GetName() == rJobSetup.GetPrinterName() )
616         {
617             if ( pPrt->GetJobSetup() != rJobSetup )
618             {
619                 pPrt->SetJobSetup( rJobSetup );
620                 bDataChanged = sal_True;
621             }
622         }
623         else
624             delete pPrt, pPrt = 0;
625     }
626 
627     if( !pPrt )
628     {
629         //Das ItemSet wird vom Sfx geloescht!
630         SfxItemSet *pSet = new SfxItemSet( GetAttrPool(),
631                         FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER,
632                         SID_HTML_MODE,  SID_HTML_MODE,
633                         SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
634                         SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
635                         0 );
636         SfxPrinter *p = new SfxPrinter( pSet, rJobSetup );
637         if ( bCheckPageDescs )
638             setPrinter( p, true, true );
639         else
640         {
641             pPrt = p;
642             bDataChanged = sal_True;
643         }
644     }
645     if ( bDataChanged && !get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) )
646         PrtDataChanged();
647 }
648 
649 const SwPrintData & SwDoc::getPrintData() const
650 {
651     if(!pPrtData)
652     {
653         SwDoc * pThis = const_cast< SwDoc * >(this);
654         pThis->pPrtData = new SwPrintData;
655 
656         // SwPrintData should be initialized from the configuration,
657         // the respective config item is implememted by SwPrintOptions which
658         // is also derived from SwPrintData
659         const SwDocShell *pDocSh = GetDocShell();
660         DBG_ASSERT( pDocSh, "pDocSh is 0, can't determine if this is a WebDoc or not" );
661         bool bWeb = 0 != dynamic_cast< const SwWebDocShell * >(pDocSh);
662         SwPrintOptions aPrintOptions( bWeb );
663         *pThis->pPrtData = aPrintOptions;
664     }
665     return *pPrtData;
666 }
667 
668 void SwDoc::setPrintData(/*[in]*/ const SwPrintData& rPrtData )
669 {
670     if(!pPrtData)
671         pPrtData = new SwPrintData;
672     *pPrtData = rPrtData;
673 }
674 
675 /** Implementations the next Interface here
676 */
677 
678 /*
679  * Dokumenteditieren (Doc-SS) zum Fuellen des Dokuments
680  * durch den RTF Parser und fuer die EditShell.
681  */
682 void SwDoc::ChgDBData(const SwDBData& rNewData)
683 {
684 	if( rNewData != aDBData )
685 	{
686 		aDBData = rNewData;
687 		SetModified();
688 	}
689 	GetSysFldType(RES_DBNAMEFLD)->UpdateFlds();
690 }
691 
692 bool SwDoc::SplitNode( const SwPosition &rPos, bool bChkTableStart )
693 {
694 	SwCntntNode *pNode = rPos.nNode.GetNode().GetCntntNode();
695 	if(0 == pNode)
696         return false;
697 
698 	{
699 		// Bug 26675:	DataChanged vorm loeschen verschicken, dann bekommt
700 		//			man noch mit, welche Objecte sich im Bereich befinden.
701 		//			Danach koennen sie vor/hinter der Position befinden.
702 		SwDataChanged aTmp( this, rPos, 0 );
703 	}
704 
705 	SwUndoSplitNode* pUndo = 0;
706     if (GetIDocumentUndoRedo().DoesUndo())
707     {
708         GetIDocumentUndoRedo().ClearRedo();
709 		// einfuegen vom Undo-Object, z.Z. nur beim TextNode
710 		if( pNode->IsTxtNode() )
711         {
712             pUndo = new SwUndoSplitNode( this, rPos, bChkTableStart );
713             GetIDocumentUndoRedo().AppendUndo(pUndo);
714         }
715     }
716 
717 	//JP 28.01.97: Sonderfall fuer SplitNode am Tabellenanfang:
718 	//				steht die am Doc/Fly/Footer/..-Anfang oder direkt
719 	//				hinter einer Tabelle, dann fuege davor
720 	//				einen Absatz ein
721 	if( bChkTableStart && !rPos.nContent.GetIndex() && pNode->IsTxtNode() )
722 	{
723 		sal_uLong nPrevPos = rPos.nNode.GetIndex() - 1;
724 		const SwTableNode* pTblNd;
725 		const SwNode* pNd = GetNodes()[ nPrevPos ];
726 		if( pNd->IsStartNode() &&
727 			SwTableBoxStartNode == ((SwStartNode*)pNd)->GetStartNodeType() &&
728 			0 != ( pTblNd = GetNodes()[ --nPrevPos ]->GetTableNode() ) &&
729 			((( pNd = GetNodes()[ --nPrevPos ])->IsStartNode() &&
730 			   SwTableBoxStartNode != ((SwStartNode*)pNd)->GetStartNodeType() )
731                || ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsTableNode() )
732 			   || pNd->IsCntntNode() ))
733 		{
734 			if( pNd->IsCntntNode() )
735 			{
736 				//JP 30.04.99 Bug 65660:
737 				// ausserhalb des normalen BodyBereiches gibt es keine
738 				// Seitenumbrueche, also ist das hier kein gueltige
739 				// Bedingung fuers einfuegen eines Absatzes
740 				if( nPrevPos < GetNodes().GetEndOfExtras().GetIndex() )
741 					pNd = 0;
742 				else
743 				{
744 					// Dann nur, wenn die Tabelle Umbrueche traegt!
745 					const SwFrmFmt* pFrmFmt = pTblNd->GetTable().GetFrmFmt();
746 					if( SFX_ITEM_SET != pFrmFmt->GetItemState(RES_PAGEDESC, sal_False) &&
747 						SFX_ITEM_SET != pFrmFmt->GetItemState( RES_BREAK, sal_False ) )
748 						pNd = 0;
749 				}
750 			}
751 
752 			if( pNd )
753 			{
754 				SwTxtNode* pTxtNd = GetNodes().MakeTxtNode(
755 										SwNodeIndex( *pTblNd ),
756 										GetTxtCollFromPool( RES_POOLCOLL_TEXT ));
757 				if( pTxtNd )
758 				{
759 					((SwPosition&)rPos).nNode = pTblNd->GetIndex()-1;
760 					((SwPosition&)rPos).nContent.Assign( pTxtNd, 0 );
761 
762 					// nur im BodyBereich den SeitenUmbruch/-Vorlage umhaengem
763 					if( nPrevPos > GetNodes().GetEndOfExtras().GetIndex() )
764 					{
765 						SwFrmFmt* pFrmFmt = pTblNd->GetTable().GetFrmFmt();
766 						const SfxPoolItem *pItem;
767 						if( SFX_ITEM_SET == pFrmFmt->GetItemState( RES_PAGEDESC,
768 							sal_False, &pItem ) )
769 						{
770                             pTxtNd->SetAttr( *pItem );
771                             pFrmFmt->ResetFmtAttr( RES_PAGEDESC );
772 						}
773 						if( SFX_ITEM_SET == pFrmFmt->GetItemState( RES_BREAK,
774 							sal_False, &pItem ) )
775 						{
776                             pTxtNd->SetAttr( *pItem );
777                             pFrmFmt->ResetFmtAttr( RES_BREAK );
778 						}
779 					}
780 
781 					if( pUndo )
782 						pUndo->SetTblFlag();
783 					SetModified();
784                     return true;
785                 }
786             }
787         }
788     }
789 
790 	SvULongs aBkmkArr( 15, 15 );
791 	_SaveCntntIdx( this, rPos.nNode.GetIndex(), rPos.nContent.GetIndex(),
792 					aBkmkArr, SAVEFLY_SPLIT );
793     // FIXME: only SwTxtNode has a valid implementation of SplitCntntNode!
794     ASSERT(pNode->IsTxtNode(), "splitting non-text node?");
795     pNode = pNode->SplitCntntNode( rPos );
796     if (pNode)
797 	{
798 		// verschiebe noch alle Bookmarks/TOXMarks/FlyAtCnt
799 		if( aBkmkArr.Count() )
800 			_RestoreCntntIdx( this, aBkmkArr, rPos.nNode.GetIndex()-1, 0, sal_True );
801 
802 		if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
803 		{
804 			SwPaM aPam( rPos );
805 			aPam.SetMark();
806 			aPam.Move( fnMoveBackward );
807 			if( IsRedlineOn() )
808 				AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
809 			else
810 				SplitRedline( aPam );
811 		}
812 	}
813 
814 	SetModified();
815     return true;
816 }
817 
818 bool SwDoc::AppendTxtNode( SwPosition& rPos )
819 {
820     // create new node before EndOfContent
821     SwTxtNode * pCurNode = rPos.nNode.GetNode().GetTxtNode();
822 	if( !pCurNode )
823 	{
824 		// dann kann ja einer angelegt werden!
825 		SwNodeIndex aIdx( rPos.nNode, 1 );
826 		pCurNode = GetNodes().MakeTxtNode( aIdx,
827 						GetTxtCollFromPool( RES_POOLCOLL_STANDARD ));
828 	}
829 	else
830 		pCurNode = (SwTxtNode*)pCurNode->AppendNode( rPos );
831 
832 	rPos.nNode++;
833 	rPos.nContent.Assign( pCurNode, 0 );
834 
835     if (GetIDocumentUndoRedo().DoesUndo())
836     {
837         GetIDocumentUndoRedo().AppendUndo( new SwUndoInsert( rPos.nNode ) );
838     }
839 
840 	if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
841 	{
842 		SwPaM aPam( rPos );
843 		aPam.SetMark();
844 		aPam.Move( fnMoveBackward );
845 		if( IsRedlineOn() )
846 			AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
847 		else
848 			SplitRedline( aPam );
849 	}
850 
851 	SetModified();
852 	return sal_True;
853 }
854 
855 bool SwDoc::InsertString( const SwPaM &rRg, const String &rStr,
856         const enum InsertFlags nInsertMode )
857 {
858     if (GetIDocumentUndoRedo().DoesUndo())
859     {
860         GetIDocumentUndoRedo().ClearRedo(); // AppendUndo not always called!
861     }
862 
863     const SwPosition& rPos = *rRg.GetPoint();
864 
865 	if( pACEWord )					// Aufnahme in die Autokorrektur
866 	{
867 		if( 1 == rStr.Len() && pACEWord->IsDeleted() )
868         {
869             pACEWord->CheckChar( rPos, rStr.GetChar( 0 ) );
870         }
871 		delete pACEWord, pACEWord = 0;
872 	}
873 
874     SwTxtNode *const pNode = rPos.nNode.GetNode().GetTxtNode();
875 	if(!pNode)
876     {
877         return false;
878     }
879 
880 	SwDataChanged aTmp( rRg, 0 );
881 
882     if (!GetIDocumentUndoRedo().DoesUndo() ||
883         !GetIDocumentUndoRedo().DoesGroupUndo())
884     {
885         pNode->InsertText( rStr, rPos.nContent, nInsertMode );
886 
887         if (GetIDocumentUndoRedo().DoesUndo())
888         {
889             SwUndoInsert * const pUndo( new SwUndoInsert(
890                 rPos.nNode, rPos.nContent.GetIndex(), rStr.Len(), nInsertMode));
891             GetIDocumentUndoRedo().AppendUndo(pUndo);
892         }
893     }
894     else
895 	{			// ist Undo und Gruppierung eingeschaltet, ist alles anders !
896         SwUndoInsert * pUndo = NULL; // #111827#
897 
898         // don't group the start if hints at the start should be expanded
899         if (!(nInsertMode & IDocumentContentOperations::INS_FORCEHINTEXPAND))
900         // -> #111827#
901         {
902             SwUndo *const pLastUndo = GetUndoManager().GetLastUndo();
903             SwUndoInsert *const pUndoInsert(
904                 dynamic_cast<SwUndoInsert *>(pLastUndo) );
905             if (pUndoInsert && pUndoInsert->CanGrouping(rPos))
906             {
907                 pUndo = pUndoInsert;
908             }
909         }
910         // <- #111827#
911 
912         CharClass const& rCC = GetAppCharClass();
913         xub_StrLen nInsPos = rPos.nContent.GetIndex();
914 
915         if (!pUndo)
916 		{
917             pUndo = new SwUndoInsert( rPos.nNode, nInsPos, 0, nInsertMode,
918 							!rCC.isLetterNumeric( rStr, 0 ) );
919             GetIDocumentUndoRedo().AppendUndo( pUndo );
920         }
921 
922         pNode->InsertText( rStr, rPos.nContent, nInsertMode );
923 
924 		for( xub_StrLen i = 0; i < rStr.Len(); ++i )
925 		{
926 			nInsPos++;
927 			// wenn CanGrouping() sal_True returnt, ist schon alles erledigt
928 			if( !pUndo->CanGrouping( rStr.GetChar( i ) ))
929 			{
930                 pUndo = new SwUndoInsert( rPos.nNode, nInsPos, 1, nInsertMode,
931 							!rCC.isLetterNumeric( rStr, i ) );
932                 GetIDocumentUndoRedo().AppendUndo( pUndo );
933             }
934         }
935     }
936 
937 	if( IsRedlineOn() || (!IsIgnoreRedline() && pRedlineTbl->Count() ))
938 	{
939         SwPaM aPam( rPos.nNode, aTmp.GetCntnt(),
940                     rPos.nNode, rPos.nContent.GetIndex());
941 		if( IsRedlineOn() )
942         {
943             AppendRedline(
944                 new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
945         }
946         else
947         {
948 			SplitRedline( aPam );
949         }
950 	}
951 
952 	SetModified();
953     return true;
954 }
955 
956 SwFlyFrmFmt* SwDoc::_InsNoTxtNode( const SwPosition& rPos, SwNoTxtNode* pNode,
957 									const SfxItemSet* pFlyAttrSet,
958 									const SfxItemSet* pGrfAttrSet,
959 									SwFrmFmt* pFrmFmt)
960 {
961 	SwFlyFrmFmt *pFmt = 0;
962 	if( pNode )
963 	{
964         pFmt = _MakeFlySection( rPos, *pNode, FLY_AT_PARA,
965 								pFlyAttrSet, pFrmFmt );
966 		if( pGrfAttrSet )
967 			pNode->SetAttr( *pGrfAttrSet );
968 	}
969 	return pFmt;
970 }
971 
972 SwFlyFrmFmt* SwDoc::Insert( const SwPaM &rRg,
973 							const String& rGrfName,
974 							const String& rFltName,
975 							const Graphic* pGraphic,
976 							const SfxItemSet* pFlyAttrSet,
977 							const SfxItemSet* pGrfAttrSet,
978 							SwFrmFmt* pFrmFmt )
979 {
980 	if( !pFrmFmt )
981 		pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_GRAPHIC );
982 	return _InsNoTxtNode( *rRg.GetPoint(), GetNodes().MakeGrfNode(
983 							SwNodeIndex( GetNodes().GetEndOfAutotext() ),
984 							rGrfName, rFltName, pGraphic,
985 							pDfltGrfFmtColl ),
986 							pFlyAttrSet, pGrfAttrSet, pFrmFmt );
987 }
988 SwFlyFrmFmt* SwDoc::Insert( const SwPaM &rRg, const GraphicObject& rGrfObj,
989 							const SfxItemSet* pFlyAttrSet,
990 							const SfxItemSet* pGrfAttrSet,
991 							SwFrmFmt* pFrmFmt )
992 {
993 	if( !pFrmFmt )
994 		pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_GRAPHIC );
995 	return _InsNoTxtNode( *rRg.GetPoint(), GetNodes().MakeGrfNode(
996 							SwNodeIndex( GetNodes().GetEndOfAutotext() ),
997 							rGrfObj, pDfltGrfFmtColl ),
998 							pFlyAttrSet, pGrfAttrSet, pFrmFmt );
999 }
1000 
1001 SwFlyFrmFmt* SwDoc::Insert(const SwPaM &rRg, const svt::EmbeddedObjectRef& xObj,
1002 						const SfxItemSet* pFlyAttrSet,
1003 						const SfxItemSet* pGrfAttrSet,
1004 						SwFrmFmt* pFrmFmt )
1005 {
1006 	if( !pFrmFmt )
1007 	{
1008 		sal_uInt16 nId = RES_POOLFRM_OLE;
1009         SvGlobalName aClassName( xObj->getClassID() );
1010         if (SotExchange::IsMath(aClassName))
1011             nId = RES_POOLFRM_FORMEL;
1012 
1013 		pFrmFmt = GetFrmFmtFromPool( nId );
1014 	}
1015 	return _InsNoTxtNode( *rRg.GetPoint(), GetNodes().MakeOLENode(
1016 							SwNodeIndex( GetNodes().GetEndOfAutotext() ),
1017                             xObj,
1018 							pDfltGrfFmtColl ),
1019 							pFlyAttrSet, pGrfAttrSet,
1020 							pFrmFmt );
1021 }
1022 
1023 SwFlyFrmFmt* SwDoc::InsertOLE(const SwPaM &rRg, const String& rObjName,
1024 						sal_Int64 nAspect,
1025 						const SfxItemSet* pFlyAttrSet,
1026 						const SfxItemSet* pGrfAttrSet,
1027 						SwFrmFmt* pFrmFmt )
1028 {
1029 	if( !pFrmFmt )
1030 		pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_OLE );
1031 
1032 	return _InsNoTxtNode( *rRg.GetPoint(),
1033 							GetNodes().MakeOLENode(
1034 								SwNodeIndex( GetNodes().GetEndOfAutotext() ),
1035 								rObjName,
1036 								nAspect,
1037 								pDfltGrfFmtColl,
1038 								0 ),
1039 							pFlyAttrSet, pGrfAttrSet,
1040 							pFrmFmt );
1041 }
1042 
1043 /*************************************************************************
1044 |*				  SwDoc::GetFldType()
1045 |*	  Beschreibung: liefert den am Doc eingerichteten Feldtypen zurueck
1046 *************************************************************************/
1047 
1048 SwFieldType *SwDoc::GetSysFldType( const sal_uInt16 eWhich ) const
1049 {
1050 	for( sal_uInt16 i = 0; i < INIT_FLDTYPES; ++i )
1051 		if( eWhich == (*pFldTypes)[i]->Which() )
1052 			return (*pFldTypes)[i];
1053 	return 0;
1054 }
1055 /*************************************************************************
1056  *			   void SetDocStat( const SwDocStat& rStat );
1057  *************************************************************************/
1058 
1059 void SwDoc::SetDocStat( const SwDocStat& rStat )
1060 {
1061 	*pDocStat = rStat;
1062 }
1063 
1064 const SwDocStat& SwDoc::GetDocStat() const
1065 {
1066 	return *pDocStat;
1067 }
1068 
1069 /*************************************************************************/
1070 
1071 
1072 struct _PostItFld : public _SetGetExpFld
1073 {
1074     _PostItFld( const SwNodeIndex& rNdIdx, const SwTxtFld* pFld,  const SwIndex* pIdx = 0 )
1075         : _SetGetExpFld( rNdIdx, pFld, pIdx ) {}
1076 
1077     sal_uInt16 GetPageNo( const StringRangeEnumerator &rRangeEnum,
1078             const std::set< sal_Int32 > &rPossiblePages,
1079             sal_uInt16& rVirtPgNo, sal_uInt16& rLineNo );
1080 
1081     SwPostItField* GetPostIt() const
1082     {
1083         return (SwPostItField*) GetFld()->GetFld().GetFld();
1084     }
1085 };
1086 
1087 
1088 sal_uInt16 _PostItFld::GetPageNo(
1089     const StringRangeEnumerator &rRangeEnum,
1090     const std::set< sal_Int32 > &rPossiblePages,
1091     /* out */ sal_uInt16& rVirtPgNo, /* out */ sal_uInt16& rLineNo )
1092 {
1093     //Problem: Wenn ein PostItFld in einem Node steht, der von mehr als
1094     //einer Layout-Instanz repraesentiert wird, steht die Frage im Raum,
1095     //ob das PostIt nur ein- oder n-mal gedruck werden soll.
1096     //Wahrscheinlich nur einmal, als Seitennummer soll hier keine Zufaellige
1097     //sondern die des ersten Auftretens des PostIts innerhalb des selektierten
1098     //Bereichs ermittelt werden.
1099     rVirtPgNo = 0;
1100     sal_uInt16 nPos = GetCntnt();
1101     SwIterator<SwTxtFrm,SwTxtNode> aIter( GetFld()->GetTxtNode() );
1102     for( SwTxtFrm* pFrm = aIter.First(); pFrm;  pFrm = aIter.Next() )
1103     {
1104         if( pFrm->GetOfst() > nPos ||
1105             (pFrm->HasFollow() && pFrm->GetFollow()->GetOfst() <= nPos) )
1106             continue;
1107         sal_uInt16 nPgNo = pFrm->GetPhyPageNum();
1108         if( rRangeEnum.hasValue( nPgNo, &rPossiblePages ))
1109         {
1110             rLineNo = (sal_uInt16)(pFrm->GetLineCount( nPos ) +
1111                       pFrm->GetAllLines() - pFrm->GetThisLines());
1112             rVirtPgNo = pFrm->GetVirtPageNum();
1113             return nPgNo;
1114         }
1115     }
1116     return 0;
1117 }
1118 
1119 
1120 bool lcl_GetPostIts(
1121     IDocumentFieldsAccess* pIDFA,
1122     _SetGetExpFlds * pSrtLst )
1123 {
1124     bool bHasPostIts = false;
1125 
1126     SwFieldType* pFldType = pIDFA->GetSysFldType( RES_POSTITFLD );
1127     DBG_ASSERT( pFldType, "kein PostItType ? ");
1128 
1129     if( pFldType->GetDepends() )
1130     {
1131         // Modify-Object gefunden, trage alle Felder ins Array ein
1132         SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
1133         const SwTxtFld* pTxtFld;
1134         for( SwFmtFld* pFld = aIter.First(); pFld;  pFld = aIter.Next() )
1135         {
1136             if( 0 != ( pTxtFld = pFld->GetTxtFld() ) &&
1137                 pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
1138             {
1139                 bHasPostIts = true;
1140                 if (pSrtLst)
1141                 {
1142                     SwNodeIndex aIdx( pTxtFld->GetTxtNode() );
1143                     _PostItFld* pNew = new _PostItFld( aIdx, pTxtFld );
1144                     pSrtLst->Insert( pNew );
1145                 }
1146                 else
1147                     break;  // we just wanted to check for the existence of postits ...
1148             }
1149         }
1150     }
1151 
1152     return bHasPostIts;
1153 }
1154 
1155 
1156 static void lcl_FormatPostIt(
1157     IDocumentContentOperations* pIDCO,
1158     SwPaM& aPam,
1159     SwPostItField* pField,
1160     bool bNewPage, bool bIsFirstPostIt,
1161     sal_uInt16 nPageNo, sal_uInt16 nLineNo )
1162 {
1163     static char __READONLY_DATA sTmp[] = " : ";
1164 
1165     DBG_ASSERT( ViewShell::GetShellRes(), "missing ShellRes" );
1166 
1167     if (bNewPage)
1168     {
1169         pIDCO->InsertPoolItem( aPam, SvxFmtBreakItem( SVX_BREAK_PAGE_AFTER, RES_BREAK ), 0 );
1170         pIDCO->SplitNode( *aPam.GetPoint(), false );
1171     }
1172     else if (!bIsFirstPostIt)
1173     {
1174         // add an empty line between different notes
1175         pIDCO->SplitNode( *aPam.GetPoint(), false );
1176         pIDCO->SplitNode( *aPam.GetPoint(), false );
1177     }
1178 
1179     String aStr( ViewShell::GetShellRes()->aPostItPage );
1180     aStr.AppendAscii(sTmp);
1181 
1182     aStr += XubString::CreateFromInt32( nPageNo );
1183     aStr += ' ';
1184     if( nLineNo )
1185     {
1186         aStr += ViewShell::GetShellRes()->aPostItLine;
1187         aStr.AppendAscii(sTmp);
1188         aStr += XubString::CreateFromInt32( nLineNo );
1189         aStr += ' ';
1190     }
1191     aStr += ViewShell::GetShellRes()->aPostItAuthor;
1192     aStr.AppendAscii(sTmp);
1193     aStr += pField->GetPar1();
1194     aStr += ' ';
1195 	SvtSysLocale aSysLocale;
1196     aStr += /*(LocaleDataWrapper&)*/aSysLocale.GetLocaleData().getDate( pField->GetDate() );
1197     pIDCO->InsertString( aPam, aStr );
1198 
1199     pIDCO->SplitNode( *aPam.GetPoint(), false );
1200     aStr = pField->GetPar2();
1201 #if defined( WNT ) || defined( PM2 )
1202     // Bei Windows und Co alle CR rausschmeissen
1203     aStr.EraseAllChars( '\r' );
1204 #endif
1205     pIDCO->InsertString( aPam, aStr );
1206 }
1207 
1208 
1209 // provide the paper tray to use according to the page style in use,
1210 // but do that only if the respective item is NOT just the default item
1211 static sal_Int32 lcl_GetPaperBin( const SwPageFrm *pStartFrm )
1212 {
1213     sal_Int32 nRes = -1;
1214 
1215     const SwFrmFmt &rFmt = pStartFrm->GetPageDesc()->GetMaster();
1216     const SfxPoolItem *pItem = NULL;
1217     SfxItemState eState = rFmt.GetItemState( RES_PAPER_BIN, sal_False, &pItem );
1218     const SvxPaperBinItem *pPaperBinItem = dynamic_cast< const SvxPaperBinItem * >(pItem);
1219     if (eState > SFX_ITEM_DEFAULT && pPaperBinItem)
1220         nRes = pPaperBinItem->GetValue();
1221 
1222     return nRes;
1223 }
1224 
1225 
1226 void SwDoc::CalculatePagesForPrinting(
1227     const SwRootFrm& rLayout,
1228     /* out */ SwRenderData &rData,
1229     const SwPrintUIOptions &rOptions,
1230     bool bIsPDFExport,
1231     sal_Int32 nDocPageCount )
1232 {
1233     const sal_Int32 nContent = rOptions.getIntValue( "PrintContent", 0 );
1234     const bool bPrintSelection = nContent == 2;
1235 
1236     // properties to take into account when calcualting the set of pages
1237     // (PDF export UI does not allow for selecting left or right pages only)
1238     bool bPrintLeftPages    = bIsPDFExport ? true : rOptions.IsPrintLeftPages();
1239     bool bPrintRightPages   = bIsPDFExport ? true : rOptions.IsPrintRightPages();
1240     // #i103700# printing selections should not allow for automatic inserting empty pages
1241     bool bPrintEmptyPages   = bPrintSelection ? false : rOptions.IsPrintEmptyPages( bIsPDFExport );
1242 
1243     Range aPages( 1, nDocPageCount );
1244 
1245     MultiSelection aMulti( aPages );
1246     aMulti.SetTotalRange( Range( 0, RANGE_MAX ) );
1247     aMulti.Select( aPages );
1248 
1249     const SwPageFrm *pStPage  = dynamic_cast<const SwPageFrm*>( rLayout.Lower() );
1250     const SwFrm     *pEndPage = pStPage;
1251 
1252     sal_uInt16 nFirstPageNo = 0;
1253     sal_uInt16 nLastPageNo  = 0;
1254     sal_uInt16 nPageNo      = 1;
1255 
1256     for( sal_uInt16 i = 1; i <= (sal_uInt16)aPages.Max(); ++i )
1257     {
1258         if( i < (sal_uInt16)aPages.Min() )
1259         {
1260             if( !pStPage->GetNext() )
1261                 break;
1262             pStPage = (SwPageFrm*)pStPage->GetNext();
1263             pEndPage= pStPage;
1264         }
1265         else if( i == (sal_uInt16)aPages.Min() )
1266         {
1267             nFirstPageNo = i;
1268             nLastPageNo = nFirstPageNo;
1269             if( !pStPage->GetNext() || (i == (sal_uInt16)aPages.Max()) )
1270                 break;
1271             pEndPage = pStPage->GetNext();
1272         }
1273         else if( i > (sal_uInt16)aPages.Min() )
1274         {
1275             nLastPageNo = i;
1276             if( !pEndPage->GetNext() || (i == (sal_uInt16)aPages.Max()) )
1277                 break;
1278             pEndPage = pEndPage->GetNext();
1279         }
1280     }
1281 
1282     DBG_ASSERT( nFirstPageNo, "first page not found!  Should not happen!" );
1283     if (nFirstPageNo)
1284     {
1285 // HACK: Hier muss von der MultiSelection noch eine akzeptable Moeglichkeit
1286 // geschaffen werden, alle Seiten von Seite x an zu deselektieren.
1287 // Z.B. durch SetTotalRange ....
1288 
1289 //              aMulti.Select( Range( nLastPageNo+1, SELECTION_MAX ), sal_False );
1290         MultiSelection aTmpMulti( Range( 1, nLastPageNo ) );
1291         long nTmpIdx = aMulti.FirstSelected();
1292         static long nEndOfSelection = SFX_ENDOFSELECTION;
1293         while ( nEndOfSelection != nTmpIdx && nTmpIdx <= long(nLastPageNo) )
1294         {
1295             aTmpMulti.Select( nTmpIdx );
1296             nTmpIdx = aMulti.NextSelected();
1297         }
1298         aMulti = aTmpMulti;
1299 // Ende des HACKs
1300 
1301         nPageNo = nFirstPageNo;
1302 
1303         std::map< sal_Int32, sal_Int32 > &rPrinterPaperTrays = rData.GetPrinterPaperTrays();
1304         std::set< sal_Int32 > &rValidPages = rData.GetValidPagesSet();
1305         std::map< sal_Int32, const SwPageFrm * > &rValidStartFrms = rData.GetValidStartFrames();
1306         rValidPages.clear();
1307         rValidStartFrms.clear();
1308         while ( pStPage )
1309         {
1310             const sal_Bool bRightPg = pStPage->OnRightPage();
1311             if ( aMulti.IsSelected( nPageNo ) &&
1312                 ( (bRightPg && bPrintRightPages) ||
1313                     (!bRightPg && bPrintLeftPages) ) )
1314             {
1315                 // --> FME 2005-12-12 #b6354161# Feature - Print empty pages
1316                 if ( bPrintEmptyPages || pStPage->Frm().Height() )
1317                 // <--
1318                 {
1319                     rValidPages.insert( nPageNo );
1320                     rValidStartFrms[ nPageNo ] = pStPage;
1321 
1322                     rPrinterPaperTrays[ nPageNo ] = lcl_GetPaperBin( pStPage );
1323                 }
1324             }
1325 
1326             if ( pStPage == pEndPage )
1327             {
1328                 pStPage = 0;
1329             }
1330             else
1331             {   ++nPageNo;
1332                 pStPage = (SwPageFrm*)pStPage->GetNext();
1333             }
1334         }
1335     }
1336 
1337 
1338     //
1339     // now that we have identified the valid pages for printing according
1340     // to the print settings we need to get the PageRange to use and
1341     // use both results to get the actual pages to be printed
1342     // (post-it settings need to be taken into account later on!)
1343     //
1344 
1345     // get PageRange value to use
1346     OUString aPageRange;
1347     // --> PL, OD #i116085# - adjusting fix for i113919
1348 //    if (bIsPDFExport)
1349 //    {
1350 //        aPageRange = rOptions.getStringValue( "PageRange", OUString() );
1351 //    }
1352 //    else
1353     if ( !bIsPDFExport )
1354     // <--
1355     {
1356         // PageContent :
1357         // 0 -> print all pages (default if aPageRange is empty)
1358         // 1 -> print range according to PageRange
1359         // 2 -> print selection
1360         if (1 == nContent)
1361             aPageRange = rOptions.getStringValue( "PageRange", OUString() );
1362         if (2 == nContent)
1363         {
1364             // note that printing selections is actually implemented by copying
1365             // the selection to a new temporary document and printing all of that one.
1366             // Thus for Writer "PrintContent" must never be 2.
1367             // See SwXTextDocument::GetRenderDoc for evaluating if a selection is to be
1368             // printed and for creating the temporary document.
1369         }
1370 
1371         // please note
1372     }
1373     if (aPageRange.getLength() == 0)    // empty string -> print all
1374     {
1375         // set page range to print to 'all pages'
1376         aPageRange = OUString::valueOf( (sal_Int32)1 );
1377         aPageRange += OUString::valueOf( (sal_Unicode)'-');
1378         aPageRange += OUString::valueOf( nDocPageCount );
1379     }
1380     rData.SetPageRange( aPageRange );
1381 
1382     // get vector of pages to print according to PageRange and valid pages set from above
1383     // (result may be an empty vector, for example if the range string is not correct)
1384     StringRangeEnumerator::getRangesFromString(
1385             aPageRange, rData.GetPagesToPrint(),
1386             1, nDocPageCount, 0, &rData.GetValidPagesSet() );
1387 }
1388 
1389 
1390 void SwDoc::UpdatePagesForPrintingWithPostItData(
1391     /* out */ SwRenderData &rData,
1392     const SwPrintUIOptions &rOptions,
1393     bool /*bIsPDFExport*/,
1394     sal_Int32 nDocPageCount )
1395 {
1396 
1397     sal_Int16 nPostItMode = (sal_Int16) rOptions.getIntValue( "PrintAnnotationMode", 0 );
1398     DBG_ASSERT(nPostItMode == POSTITS_NONE || rData.HasPostItData(),
1399             "print post-its without post-it data?" );
1400     const sal_uInt16 nPostItCount = rData.HasPostItData() ? rData.m_pPostItFields->Count() : 0;
1401     if (nPostItMode != POSTITS_NONE && nPostItCount > 0)
1402     {
1403         SET_CURR_SHELL( rData.m_pPostItShell );
1404 
1405         // clear document and move to end of it
1406         SwPaM aPam( rData.m_pPostItDoc->GetNodes().GetEndOfContent() );
1407         aPam.Move( fnMoveBackward, fnGoDoc );
1408         aPam.SetMark();
1409         aPam.Move( fnMoveForward, fnGoDoc );
1410         rData.m_pPostItDoc->DeleteRange( aPam );
1411 
1412         const StringRangeEnumerator aRangeEnum( rData.GetPageRange(), 1, nDocPageCount, 0 );
1413 
1414         // For mode POSTITS_ENDPAGE:
1415         // maps a physical page number to the page number in post-it document that holds
1416         // the first post-it for that physical page . Needed to relate the correct start frames
1417         // from the post-it doc to the physical page of the document
1418         std::map< sal_Int32, sal_Int32 >  aPostItLastStartPageNum;
1419 
1420         // add all post-its on valid pages within the the page range to the
1421         // temporary post-it document.
1422         // Since the array of post-it fileds is sorted by page and line number we will
1423         // already get them in the correct order
1424         sal_uInt16 nVirtPg = 0, nLineNo = 0, nLastPageNum = 0, nPhyPageNum = 0;
1425         bool bIsFirstPostIt = true;
1426         for (sal_uInt16 i = 0; i < nPostItCount; ++i)
1427         {
1428             _PostItFld& rPostIt = (_PostItFld&)*(*rData.m_pPostItFields)[ i ];
1429             nLastPageNum = nPhyPageNum;
1430             nPhyPageNum = rPostIt.GetPageNo(
1431                     aRangeEnum, rData.GetValidPagesSet(), nVirtPg, nLineNo );
1432             if (nPhyPageNum)
1433             {
1434                 // need to insert a page break?
1435                 // In POSTITS_ENDPAGE mode for each document page the following
1436                 // post-it page needs to start on a new page
1437                 const bool bNewPage = nPostItMode == POSTITS_ENDPAGE &&
1438                         !bIsFirstPostIt && nPhyPageNum != nLastPageNum;
1439 
1440                 lcl_FormatPostIt( rData.m_pPostItShell->GetDoc(), aPam,
1441                         rPostIt.GetPostIt(), bNewPage, bIsFirstPostIt, nVirtPg, nLineNo );
1442                 bIsFirstPostIt = false;
1443 
1444                 if (nPostItMode == POSTITS_ENDPAGE)
1445                 {
1446                     // get the correct number of current pages for the post-it document
1447                     rData.m_pPostItShell->CalcLayout();
1448                     const sal_Int32 nPages = rData.m_pPostItShell->GetPageCount();
1449                     aPostItLastStartPageNum[ nPhyPageNum ] = nPages;
1450                 }
1451             }
1452         }
1453 
1454         // format post-it doc to get correct number of pages
1455         rData.m_pPostItShell->CalcLayout();
1456         const sal_Int32 nPostItDocPageCount = rData.m_pPostItShell->GetPageCount();
1457 
1458         if (nPostItMode == POSTITS_ONLY || nPostItMode == POSTITS_ENDDOC)
1459         {
1460             // now add those post-it pages to the vector of pages to print
1461             // or replace them if only post-its should be printed
1462 
1463             rData.GetPostItStartFrames().clear();
1464             if (nPostItMode == POSTITS_ENDDOC)
1465             {
1466                 // set all values up to number of pages to print currently known to NULL,
1467                 // meaning none of the pages currently in the vector is from the
1468                 // post-it document, they are the documents pages.
1469                 rData.GetPostItStartFrames().resize( rData.GetPagesToPrint().size() );
1470             }
1471             else if (nPostItMode == POSTITS_ONLY)
1472             {
1473                 // no document page to be printed
1474                 rData.GetPagesToPrint().clear();
1475             }
1476 
1477             // now we just need to add the post-it pages to be printed to the end
1478             // of the vector of pages to print and keep the GetValidStartFrames
1479             // data conform with it
1480             sal_Int32 nPageNum = 0;
1481             const SwPageFrm * pPageFrm = (SwPageFrm*)rData.m_pPostItShell->GetLayout()->Lower();
1482             while( pPageFrm && nPageNum < nPostItDocPageCount )
1483             {
1484                 DBG_ASSERT( pPageFrm, "Empty page frame. How are we going to print this?" );
1485                 ++nPageNum;
1486                 rData.GetPagesToPrint().push_back( 0 );  // a page number of 0 indicates this page is from the post-it doc
1487                 DBG_ASSERT( pPageFrm, "pPageFrm is NULL!" );
1488                 rData.GetPostItStartFrames().push_back( pPageFrm );
1489                 pPageFrm = (SwPageFrm*)pPageFrm->GetNext();
1490             }
1491             DBG_ASSERT( nPageNum == nPostItDocPageCount, "unexpected number of pages" );
1492         }
1493         else if (nPostItMode == POSTITS_ENDPAGE)
1494         {
1495             // the next step is to find all the start frames from the post-it
1496             // document that should be printed for a given physical page of the document
1497             std::map< sal_Int32, std::vector< const SwPageFrm * > > aPhysPageToPostItFrames;
1498 
1499             // ... thus, first collect all post-it doc start frames in a vector
1500             sal_Int32 nPostItPageNum = 0;
1501             std::vector< const SwPageFrm * > aAllPostItStartFrames;
1502             const SwPageFrm * pPageFrm = (SwPageFrm*)rData.m_pPostItShell->GetLayout()->Lower();
1503             while( pPageFrm && sal_Int32(aAllPostItStartFrames.size()) < nPostItDocPageCount )
1504             {
1505                 DBG_ASSERT( pPageFrm, "Empty page frame. How are we going to print this?" );
1506                 ++nPostItPageNum;
1507                 aAllPostItStartFrames.push_back( pPageFrm );
1508                 pPageFrm = (SwPageFrm*)pPageFrm->GetNext();
1509             }
1510             DBG_ASSERT( sal_Int32(aAllPostItStartFrames.size()) == nPostItDocPageCount,
1511                     "unexpected number of frames; does not match number of pages" );
1512 
1513             // get a map that holds all post-it frames to be printed for a
1514             // given physical page from the document
1515             sal_Int32 nLastStartPageNum = 0;
1516             std::map< sal_Int32, sal_Int32 >::const_iterator  aIt;
1517             for (aIt = aPostItLastStartPageNum.begin();  aIt != aPostItLastStartPageNum.end();  ++aIt)
1518             {
1519                 const sal_Int32 nFrames = aIt->second - nLastStartPageNum;
1520                 const sal_Int32 nFirstStartPageNum = aIt == aPostItLastStartPageNum.begin() ?
1521                         1 : aIt->second - nFrames + 1;
1522                 DBG_ASSERT( 1 <= nFirstStartPageNum && nFirstStartPageNum <= nPostItDocPageCount,
1523                         "page number for first frame out of range" );
1524                 std::vector<  const SwPageFrm * > aStartFrames;
1525                 for (sal_Int32 i = 0; i < nFrames; ++i)
1526                 {
1527                     const sal_Int32 nIdx = nFirstStartPageNum - 1 + i;   // -1 because lowest page num is 1
1528                     DBG_ASSERT( 0 <= nIdx && nIdx < sal_Int32(aAllPostItStartFrames.size()),
1529                             "index out of range" );
1530                     aStartFrames.push_back( aAllPostItStartFrames[ nIdx ] );
1531                 }
1532                 aPhysPageToPostItFrames[ aIt->first /* phys page num */ ] = aStartFrames;
1533                 nLastStartPageNum = aIt->second;
1534             }
1535 
1536 
1537             // ok, now that aPhysPageToPostItFrames can give the start frames for all
1538             // post-it pages to be printed we need to merge those at the correct
1539             // position into the GetPagesToPrint vector and build and maintain the
1540             // GetValidStartFrames vector as well.
1541             // Since inserting a larger number of entries in the middle of a vector
1542             // isn't that efficient we will create new vectors by copying the required data
1543             std::vector< sal_Int32 >            aTmpPagesToPrint;
1544             std::vector< const SwPageFrm * >    aTmpPostItStartFrames;
1545             const size_t nNum = rData.GetPagesToPrint().size();
1546             for (size_t i = 0 ;  i < nNum;  ++i)
1547             {
1548                 // add the physical page to print from the document
1549                 const sal_Int32 nPhysPage = rData.GetPagesToPrint()[i];
1550                 aTmpPagesToPrint.push_back( nPhysPage );
1551                 aTmpPostItStartFrames.push_back( NULL );
1552 
1553                 // add the post-it document pages to print, i.e those
1554                 // post-it pages that have the data for the above physical page
1555                 const std::vector< const SwPageFrm * > &rPostItFrames = aPhysPageToPostItFrames[ nPhysPage ];
1556                 const size_t nPostItFrames = rPostItFrames.size();
1557                 for (size_t k = 0;  k < nPostItFrames;  ++k)
1558                 {
1559                     aTmpPagesToPrint.push_back( 0 );
1560                     aTmpPostItStartFrames.push_back( rPostItFrames[k] );
1561                 }
1562             }
1563 
1564             // finally we need to assign those vectors to the resulting ones.
1565             // swapping the data should be more efficient than assigning since
1566             // we won't need the temporary vectors anymore
1567             rData.GetPagesToPrint().swap( aTmpPagesToPrint );
1568             rData.GetPostItStartFrames().swap( aTmpPostItStartFrames );
1569         }
1570     }
1571 }
1572 
1573 
1574 void SwDoc::CalculatePagePairsForProspectPrinting(
1575     const SwRootFrm& rLayout,
1576     /* out */ SwRenderData &rData,
1577     const SwPrintUIOptions &rOptions,
1578     sal_Int32 nDocPageCount )
1579 {
1580     std::map< sal_Int32, sal_Int32 > &rPrinterPaperTrays = rData.GetPrinterPaperTrays();
1581     std::set< sal_Int32 > &rValidPagesSet = rData.GetValidPagesSet();
1582     std::map< sal_Int32, const SwPageFrm * > &rValidStartFrms = rData.GetValidStartFrames();
1583     std::vector< std::pair< sal_Int32, sal_Int32 > > &rPagePairs = rData.GetPagePairsForProspectPrinting();
1584 
1585     rPagePairs.clear();
1586     rValidPagesSet.clear();
1587     rValidStartFrms.clear();
1588 
1589     rtl::OUString aPageRange = rOptions.getStringValue( "PageRange", rtl::OUString() );
1590     // PageContent :
1591     // 0 -> print all pages (default if aPageRange is empty)
1592     // 1 -> print range according to PageRange
1593     // 2 -> print selection
1594     const sal_Int32 nContent = rOptions.getIntValue( "PrintContent", 0 );
1595     if (0 == nContent)
1596     {
1597         // set page range to print to 'all pages'
1598         aPageRange = OUString::valueOf( (sal_Int32)1 );
1599         aPageRange += OUString::valueOf( (sal_Unicode)'-');
1600         aPageRange += OUString::valueOf( nDocPageCount );
1601     }
1602     StringRangeEnumerator aRange( aPageRange, 1, nDocPageCount, 0 );
1603 
1604     if ( aRange.size() <= 0)
1605         return;
1606 
1607     const SwPageFrm *pStPage  = dynamic_cast<const SwPageFrm*>( rLayout.Lower() );
1608     sal_Int32 i = 0;
1609     for ( i = 1; pStPage && i < nDocPageCount; ++i )
1610         pStPage = (SwPageFrm*)pStPage->GetNext();
1611     if ( !pStPage )          // dann wars das
1612         return;
1613 
1614     // currently for prospect printing all pages are valid to be printed
1615     // thus we add them all to the respective map and set for later use
1616     sal_Int32 nPageNum = 0;
1617     const SwPageFrm *pPageFrm  = dynamic_cast<const SwPageFrm*>( rLayout.Lower() );
1618     while( pPageFrm && nPageNum < nDocPageCount )
1619     {
1620         DBG_ASSERT( pPageFrm, "Empty page frame. How are we going to print this?" );
1621         ++nPageNum;
1622         rValidPagesSet.insert( nPageNum );
1623         rValidStartFrms[ nPageNum ] = pPageFrm;
1624         pPageFrm = (SwPageFrm*)pPageFrm->GetNext();
1625 
1626         rPrinterPaperTrays[ nPageNum ] = lcl_GetPaperBin( pStPage );
1627     }
1628     DBG_ASSERT( nPageNum == nDocPageCount, "unexpected number of pages" );
1629 
1630     // properties to take into account when calcualting the set of pages
1631     // Note: here bPrintLeftPages and bPrintRightPages refer to the (virtual) resulting pages
1632     //      of the prospect!
1633     bool bPrintLeftPages     = rOptions.IsPrintLeftPages();
1634     bool bPrintRightPages    = rOptions.IsPrintRightPages();
1635     bool bPrintProspectRTL = rOptions.getIntValue( "PrintProspectRTL",  0 ) ? true : false;
1636 
1637     // get pages for prospect printing according to the 'PageRange'
1638     // (duplicates and any order allowed!)
1639     std::vector< sal_Int32 > aPagesToPrint;
1640     StringRangeEnumerator::getRangesFromString(
1641             aPageRange, aPagesToPrint, 1, nDocPageCount, 0 );
1642 
1643     // now fill the vector for calculating the page pairs with the start frames
1644     // from the above obtained vector
1645     std::vector< const SwPageFrm * > aVec;
1646     for ( i = 0; i < sal_Int32(aPagesToPrint.size()); ++i)
1647     {
1648         const sal_Int32 nPage = aPagesToPrint[i];
1649         const SwPageFrm *pFrm = rValidStartFrms[ nPage ];
1650         aVec.push_back( pFrm );
1651     }
1652 
1653     // just one page is special ...
1654     if ( 1 == aVec.size() )
1655         aVec.insert( aVec.begin() + 1, 0 ); // insert a second empty page
1656     else
1657     {
1658         // now extend the number of pages to fit a multiple of 4
1659         // (4 'normal' pages are needed for a single prospect paper
1660         //  with back and front)
1661         while( aVec.size() & 3 )
1662             aVec.push_back( 0 );
1663     }
1664 
1665     // dann sorge mal dafuer, das alle Seiten in der richtigen
1666     // Reihenfolge stehen:
1667     sal_uInt16 nSPg = 0, nEPg = aVec.size(), nStep = 1;
1668     if ( 0 == (nEPg & 1 ))      // ungerade gibt es nicht!
1669         --nEPg;
1670 
1671     if ( !bPrintLeftPages )
1672         ++nStep;
1673     else if ( !bPrintRightPages )
1674     {
1675         ++nStep;
1676         ++nSPg, --nEPg;
1677     }
1678 
1679     // the number of 'virtual' pages to be printed
1680     sal_Int32 nCntPage = (( nEPg - nSPg ) / ( 2 * nStep )) + 1;
1681 
1682     for ( sal_uInt16 nPrintCount = 0; nSPg < nEPg &&
1683             nPrintCount < nCntPage; ++nPrintCount )
1684     {
1685         pStPage = aVec[ nSPg ];
1686         const SwPageFrm* pNxtPage = nEPg < aVec.size() ? aVec[ nEPg ] : 0;
1687 
1688         short nRtlOfs = bPrintProspectRTL ? 1 : 0;
1689         if ( 0 == (( nSPg + nRtlOfs) & 1 ) )     // switch for odd number in LTR, even number in RTL
1690         {
1691             const SwPageFrm* pTmp = pStPage;
1692             pStPage = pNxtPage;
1693             pNxtPage = pTmp;
1694         }
1695 
1696         sal_Int32 nFirst = -1, nSecond = -1;
1697         for ( int nC = 0; nC < 2; ++nC )
1698         {
1699             sal_Int32 nPage = -1;
1700             if ( pStPage )
1701                 nPage = pStPage->GetPhyPageNum();
1702             if (nC == 0)
1703                 nFirst  = nPage;
1704             else
1705                 nSecond = nPage;
1706 
1707             pStPage = pNxtPage;
1708         }
1709         rPagePairs.push_back( std::pair< sal_Int32, sal_Int32 >(nFirst, nSecond) );
1710 
1711         nSPg = nSPg + nStep;
1712         nEPg = nEPg - nStep;
1713     }
1714     DBG_ASSERT( size_t(nCntPage) == rPagePairs.size(), "size mismatch for number of page pairs" );
1715 
1716     // luckily prospect printing does not make use of post-its so far,
1717     // thus we are done here.
1718 }
1719 
1720 /*************************************************************************
1721  *			  void UpdateDocStat( const SwDocStat& rStat );
1722  *************************************************************************/
1723 
1724 void SwDoc::UpdateDocStat( SwDocStat& rStat )
1725 {
1726 	if( rStat.bModified )
1727 	{
1728 		rStat.Reset();
1729 		rStat.nPara = 0;        // Default ist auf 1 !!
1730 		SwNode* pNd;
1731 
1732         for( sal_uLong i = GetNodes().Count(); i; )
1733         {
1734             switch( ( pNd = GetNodes()[ --i ])->GetNodeType() )
1735 			{
1736             case ND_TEXTNODE:
1737                 ((SwTxtNode*)pNd)->CountWords( rStat, 0, ((SwTxtNode*)pNd)->GetTxt().Len() );
1738                 break;
1739 			case ND_TABLENODE:		++rStat.nTbl;	break;
1740 			case ND_GRFNODE:		++rStat.nGrf;	break;
1741 			case ND_OLENODE:		++rStat.nOLE;	break;
1742 			case ND_SECTIONNODE:	break;
1743 			}
1744         }
1745 
1746         // #i93174#: notes contain paragraphs that are not nodes
1747         {
1748             SwFieldType * const pPostits( GetSysFldType(RES_POSTITFLD) );
1749             SwIterator<SwFmtFld,SwFieldType> aIter( *pPostits );
1750             for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld;  pFmtFld = aIter.Next() )
1751             {
1752                 if (pFmtFld->IsFldInDoc())
1753                 {
1754                     SwPostItField const * const pField(
1755                         static_cast<SwPostItField const*>(pFmtFld->GetFld()));
1756                     rStat.nAllPara += pField->GetNumberOfParagraphs();
1757                 }
1758             }
1759         }
1760 
1761 		rStat.nPage 	= GetCurrentLayout() ? GetCurrentLayout()->GetPageNum() : 0;	//swmod 080218
1762 		rStat.bModified = sal_False;
1763 		SetDocStat( rStat );
1764 
1765 		com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aStat( rStat.nPage ? 7 : 6);
1766 		sal_Int32 n=0;
1767 		aStat[n].Name = ::rtl::OUString::createFromAscii("TableCount");
1768 		aStat[n++].Value <<= (sal_Int32)rStat.nTbl;
1769 		aStat[n].Name = ::rtl::OUString::createFromAscii("ImageCount");
1770 		aStat[n++].Value <<= (sal_Int32)rStat.nGrf;
1771 		aStat[n].Name = ::rtl::OUString::createFromAscii("ObjectCount");
1772 		aStat[n++].Value <<= (sal_Int32)rStat.nOLE;
1773 		if ( rStat.nPage )
1774 		{
1775 			aStat[n].Name = ::rtl::OUString::createFromAscii("PageCount");
1776 			aStat[n++].Value <<= (sal_Int32)rStat.nPage;
1777 		}
1778 		aStat[n].Name = ::rtl::OUString::createFromAscii("ParagraphCount");
1779 		aStat[n++].Value <<= (sal_Int32)rStat.nPara;
1780 		aStat[n].Name = ::rtl::OUString::createFromAscii("WordCount");
1781 		aStat[n++].Value <<= (sal_Int32)rStat.nWord;
1782 		aStat[n].Name = ::rtl::OUString::createFromAscii("CharacterCount");
1783 		aStat[n++].Value <<= (sal_Int32)rStat.nChar;
1784 
1785 		// For e.g. autotext documents there is no pSwgInfo (#i79945)
1786         SfxObjectShell * const pObjShell( GetDocShell() );
1787         if (pObjShell)
1788         {
1789             const uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1790                 pObjShell->GetModel(), uno::UNO_QUERY_THROW);
1791             const uno::Reference<document::XDocumentProperties> xDocProps(
1792                 xDPS->getDocumentProperties());
1793             // #i96786#: do not set modified flag when updating statistics
1794             const bool bDocWasModified( IsModified() );
1795             const ModifyBlocker_Impl b(pObjShell);
1796             xDocProps->setDocumentStatistics(aStat);
1797             if (!bDocWasModified)
1798             {
1799                 ResetModified();
1800             }
1801         }
1802 
1803 		// event. Stat. Felder Updaten
1804 		SwFieldType *pType = GetSysFldType(RES_DOCSTATFLD);
1805 		pType->UpdateFlds();
1806 	}
1807 }
1808 
1809 
1810 // Dokument - Info
1811 
1812 void SwDoc::DocInfoChgd( )
1813 {
1814 	GetSysFldType( RES_DOCINFOFLD )->UpdateFlds();
1815 	GetSysFldType( RES_TEMPLNAMEFLD )->UpdateFlds();
1816 	SetModified();
1817 }
1818 
1819 	// returne zum Namen die im Doc gesetzte Referenz
1820 const SwFmtRefMark* SwDoc::GetRefMark( const String& rName ) const
1821 {
1822 	const SfxPoolItem* pItem;
1823 	sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_REFMARK );
1824 	for( sal_uInt32 n = 0; n < nMaxItems; ++n )
1825 	{
1826 		if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_REFMARK, n ) ))
1827 			continue;
1828 
1829 		const SwFmtRefMark* pFmtRef = (SwFmtRefMark*)pItem;
1830 		const SwTxtRefMark* pTxtRef = pFmtRef->GetTxtRefMark();
1831 		if( pTxtRef && &pTxtRef->GetTxtNode().GetNodes() == &GetNodes() &&
1832 			rName.Equals( pFmtRef->GetRefName() ) )
1833 			return pFmtRef;
1834 	}
1835 	return 0;
1836 }
1837 
1838 	// returne die RefMark per Index - fuer Uno
1839 const SwFmtRefMark* SwDoc::GetRefMark( sal_uInt16 nIndex ) const
1840 {
1841 	const SfxPoolItem* pItem;
1842 	const SwTxtRefMark* pTxtRef;
1843 	const SwFmtRefMark* pRet = 0;
1844 
1845 	sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_REFMARK );
1846 	sal_uInt32 nCount = 0;
1847 	for( sal_uInt32 n = 0; n < nMaxItems; ++n )
1848 		if( 0 != (pItem = GetAttrPool().GetItem2( RES_TXTATR_REFMARK, n )) &&
1849 			0 != (pTxtRef = ((SwFmtRefMark*)pItem)->GetTxtRefMark()) &&
1850 			&pTxtRef->GetTxtNode().GetNodes() == &GetNodes() )
1851 		{
1852 			if(nCount == nIndex)
1853 			{
1854 				pRet = (SwFmtRefMark*)pItem;
1855 				break;
1856 			}
1857 			nCount++;
1858 		}
1859    return pRet;
1860 }
1861 
1862 	// returne die Namen aller im Doc gesetzten Referenzen
1863 	//JP 24.06.96: Ist der ArrayPointer 0 dann returne nur, ob im Doc. eine
1864 	//				RefMark gesetzt ist
1865 	// OS 25.06.96: ab jetzt wird immer die Anzahl der Referenzen returnt
1866 sal_uInt16 SwDoc::GetRefMarks( SvStringsDtor* pNames ) const
1867 {
1868 	const SfxPoolItem* pItem;
1869 	const SwTxtRefMark* pTxtRef;
1870 
1871 	sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_REFMARK );
1872 	sal_uInt32 nCount = 0;
1873 	for( sal_uInt32 n = 0; n < nMaxItems; ++n )
1874 		if( 0 != (pItem = GetAttrPool().GetItem2( RES_TXTATR_REFMARK, n )) &&
1875 			0 != (pTxtRef = ((SwFmtRefMark*)pItem)->GetTxtRefMark()) &&
1876 			&pTxtRef->GetTxtNode().GetNodes() == &GetNodes() )
1877 		{
1878 			if( pNames )
1879 			{
1880 				String* pTmp = new String( ((SwFmtRefMark*)pItem)->GetRefName() );
1881 				pNames->Insert( pTmp, nCount );
1882 			}
1883 			nCount ++;
1884 		}
1885 
1886 	return nCount;
1887 }
1888 
1889 bool SwDoc::IsLoaded() const
1890 {
1891 	return mbLoaded;
1892 }
1893 
1894 bool SwDoc::IsUpdateExpFld() const
1895 {
1896 	return mbUpdateExpFld;
1897 }
1898 
1899 bool SwDoc::IsNewDoc() const
1900 {
1901 	return mbNewDoc;
1902 }
1903 
1904 bool SwDoc::IsPageNums() const
1905 {
1906   return mbPageNums;
1907 }
1908 
1909 void SwDoc::SetPageNums(bool b)
1910 {
1911 	mbPageNums = b;
1912 }
1913 
1914 void SwDoc::SetNewDoc(bool b)
1915 {
1916 	mbNewDoc = b;
1917 }
1918 
1919 void SwDoc::SetUpdateExpFldStat(bool b)
1920 {
1921 	mbUpdateExpFld = b;
1922 }
1923 
1924 void SwDoc::SetLoaded(bool b)
1925 {
1926 	mbLoaded = b;
1927 }
1928 
1929 bool SwDoc::IsModified() const
1930 {
1931 	return mbModified;
1932 }
1933 
1934 void SwDoc::SetModified()
1935 {
1936     // --> OD 2005-08-29 #125370#
1937     SwLayouter::ClearMovedFwdFrms( *this );
1938     SwLayouter::ClearObjsTmpConsiderWrapInfluence( *this );
1939     SwLayouter::ClearFrmsNotToWrap( *this );
1940     // <--
1941     // --> OD 2006-05-10 #i65250#
1942     SwLayouter::ClearMoveBwdLayoutInfo( *this );
1943     // <--
1944 	// dem Link wird der Status returnt, wie die Flags waren und werden
1945 	// 	Bit 0:	-> alter Zustand
1946 	//	Bit 1: 	-> neuer Zustand
1947 	long nCall = mbModified ? 3 : 2;
1948 	mbModified = sal_True;
1949 	pDocStat->bModified = sal_True;
1950 	if( aOle2Link.IsSet() )
1951 	{
1952 		mbInCallModified = sal_True;
1953 		aOle2Link.Call( (void*)nCall );
1954 		mbInCallModified = sal_False;
1955 	}
1956 
1957 	if( pACEWord && !pACEWord->IsDeleted() )
1958 		delete pACEWord, pACEWord = 0;
1959 }
1960 
1961 void SwDoc::ResetModified()
1962 {
1963 	// dem Link wird der Status returnt, wie die Flags waren und werden
1964 	// 	Bit 0:	-> alter Zustand
1965 	//	Bit 1: 	-> neuer Zustand
1966     long nCall = mbModified ? 1 : 0;
1967 	mbModified = sal_False;
1968     // If there is already a document statistic, we assume that
1969     // it is correct. In this case we reset the modified flag.
1970     if ( 0 != pDocStat->nChar )
1971         pDocStat->bModified = sal_False;
1972     GetIDocumentUndoRedo().SetUndoNoModifiedPosition();
1973 	if( nCall && aOle2Link.IsSet() )
1974 	{
1975 		mbInCallModified = sal_True;
1976 		aOle2Link.Call( (void*)nCall );
1977 		mbInCallModified = sal_False;
1978 	}
1979 }
1980 
1981 
1982 void SwDoc::ReRead( SwPaM& rPam, const String& rGrfName,
1983 					const String& rFltName, const Graphic* pGraphic,
1984 					const GraphicObject* pGrafObj )
1985 {
1986 	SwGrfNode *pGrfNd;
1987 	if( ( !rPam.HasMark()
1988 		 || rPam.GetPoint()->nNode.GetIndex() == rPam.GetMark()->nNode.GetIndex() )
1989 		 && 0 != ( pGrfNd = rPam.GetPoint()->nNode.GetNode().GetGrfNode() ) )
1990     {
1991         if (GetIDocumentUndoRedo().DoesUndo())
1992         {
1993             GetIDocumentUndoRedo().AppendUndo(new SwUndoReRead(rPam, *pGrfNd));
1994         }
1995 
1996 		// Weil nicht bekannt ist, ob sich die Grafik spiegeln laesst,
1997 		// immer das SpiegelungsAttribut zuruecksetzen
1998         if( RES_MIRROR_GRAPH_DONT != pGrfNd->GetSwAttrSet().
1999 												GetMirrorGrf().GetValue() )
2000 			pGrfNd->SetAttr( SwMirrorGrf() );
2001 
2002 		pGrfNd->ReRead( rGrfName, rFltName, pGraphic, pGrafObj, sal_True );
2003 		SetModified();
2004 	}
2005 }
2006 
2007 sal_Bool lcl_SpellAndGrammarAgain( const SwNodePtr& rpNd, void* pArgs )
2008 {
2009 	SwTxtNode *pTxtNode = (SwTxtNode*)rpNd->GetTxtNode();
2010 	sal_Bool bOnlyWrong = *(sal_Bool*)pArgs;
2011 	if( pTxtNode )
2012 	{
2013 		if( bOnlyWrong )
2014 		{
2015 			if( pTxtNode->GetWrong() &&
2016 				pTxtNode->GetWrong()->InvalidateWrong() )
2017                 pTxtNode->SetWrongDirty( true );
2018             if( pTxtNode->GetGrammarCheck() &&
2019                 pTxtNode->GetGrammarCheck()->InvalidateWrong() )
2020                 pTxtNode->SetGrammarCheckDirty( true );
2021 		}
2022 		else
2023 		{
2024             pTxtNode->SetWrongDirty( true );
2025 			if( pTxtNode->GetWrong() )
2026 				pTxtNode->GetWrong()->SetInvalid( 0, STRING_LEN );
2027             pTxtNode->SetGrammarCheckDirty( true );
2028             if( pTxtNode->GetGrammarCheck() )
2029                 pTxtNode->GetGrammarCheck()->SetInvalid( 0, STRING_LEN );
2030 		}
2031 	}
2032 	return sal_True;
2033 }
2034 
2035 sal_Bool lcl_CheckSmartTagsAgain( const SwNodePtr& rpNd, void*  )
2036 {
2037 	SwTxtNode *pTxtNode = (SwTxtNode*)rpNd->GetTxtNode();
2038 //	sal_Bool bOnlyWrong = *(sal_Bool*)pArgs;
2039 	if( pTxtNode )
2040 	{
2041         pTxtNode->SetSmartTagDirty( true );
2042         if( pTxtNode->GetSmartTags() )
2043         {
2044 //            if ( bOnlyWrong ) // only some smart tag types have been enabled or disabled
2045 //				pTxtNode->GetSmartTags()->SetInvalid( 0, STRING_LEN );
2046 //            else // smart tags all have been enabled or disabled
2047 				pTxtNode->SetSmartTags( NULL );
2048         }
2049 	}
2050 	return sal_True;
2051 }
2052 
2053 
2054 /*************************************************************************
2055  * 		SwDoc::SpellItAgainSam( sal_Bool bInvalid, sal_Bool bOnlyWrong )
2056  *
2057  * stoesst das Spelling im Idle-Handler wieder an.
2058  * Wird bInvalid als sal_True uebergeben, so werden zusaetzlich die WrongListen
2059  * an allen Nodes invalidiert und auf allen Seiten das SpellInvalid-Flag
2060  * gesetzt.
2061  * Mit bOnlyWrong kann man dann steuern, ob nur die Bereiche mit falschen
2062  * Woertern oder die kompletten Bereiche neu ueberprueft werden muessen.
2063  ************************************************************************/
2064 
2065 void SwDoc::SpellItAgainSam( sal_Bool bInvalid, sal_Bool bOnlyWrong, sal_Bool bSmartTags )
2066 {
2067 	std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();//swmod 080307
2068 	ASSERT( GetCurrentLayout(), "SpellAgain: Where's my RootFrm?" );
2069 	if( bInvalid )
2070 	{
2071 		std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::AllInvalidateSmartTagsOrSpelling),bSmartTags));//swmod 080305
2072 		std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::SetNeedGrammarCheck), true) );
2073     	if ( bSmartTags )
2074             GetNodes().ForEach( lcl_CheckSmartTagsAgain, &bOnlyWrong );
2075         GetNodes().ForEach( lcl_SpellAndGrammarAgain, &bOnlyWrong );
2076 	}
2077 
2078 	std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::SetIdleFlags));//swmod 080307
2079 }
2080 
2081 void SwDoc::InvalidateAutoCompleteFlag()
2082 {
2083 	SwRootFrm* pTmpRoot = GetCurrentLayout();
2084 	if( pTmpRoot )
2085 	{
2086 		std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
2087 		std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllInvalidateAutoCompleteWords));//swmod 080305
2088 		for( sal_uLong nNd = 1, nCnt = GetNodes().Count(); nNd < nCnt; ++nNd )
2089         {
2090             SwTxtNode* pTxtNode = GetNodes()[ nNd ]->GetTxtNode();
2091             if ( pTxtNode ) pTxtNode->SetAutoCompleteWordDirty( true );
2092         }
2093 
2094 		std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::SetIdleFlags));//swmod 080228
2095 	}	//swmod 080219
2096 }
2097 
2098 const SwFmtINetFmt* SwDoc::FindINetAttr( const String& rName ) const
2099 {
2100 	const SwFmtINetFmt* pItem;
2101 	const SwTxtINetFmt* pTxtAttr;
2102 	const SwTxtNode* pTxtNd;
2103 	sal_uInt32 n, nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_INETFMT );
2104 	for( n = 0; n < nMaxItems; ++n )
2105 		if( 0 != (pItem = (SwFmtINetFmt*)GetAttrPool().GetItem2(
2106 			RES_TXTATR_INETFMT, n ) ) &&
2107 			pItem->GetName().Equals( rName ) &&
2108 			0 != ( pTxtAttr = pItem->GetTxtINetFmt()) &&
2109 			0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) &&
2110 			&pTxtNd->GetNodes() == &GetNodes() )
2111 		{
2112 			return pItem;
2113 		}
2114 
2115 	return 0;
2116 }
2117 
2118 void SwDoc::Summary( SwDoc* pExtDoc, sal_uInt8 nLevel, sal_uInt8 nPara, sal_Bool bImpress )
2119 {
2120 	const SwOutlineNodes& rOutNds = GetNodes().GetOutLineNds();
2121 	if( pExtDoc && rOutNds.Count() )
2122 	{
2123 		sal_uInt16 i;
2124 		::StartProgress( STR_STATSTR_SUMMARY, 0, rOutNds.Count(), GetDocShell() );
2125 		SwNodeIndex aEndOfDoc( pExtDoc->GetNodes().GetEndOfContent(), -1 );
2126 		for( i = 0; i < rOutNds.Count(); ++i )
2127 		{
2128 			::SetProgressState( i, GetDocShell() );
2129             const sal_uLong nIndex = rOutNds[ i ]->GetIndex();
2130 			//sal_uInt8 nLvl = ((SwTxtNode*)GetNodes()[ nIndex ])->GetTxtColl()//#outline level,zhaojianwei
2131 						// ->GetOutlineLevel();
2132             const int nLvl = ((SwTxtNode*)GetNodes()[ nIndex ])->GetAttrOutlineLevel()-1;//<-end,zhaojianwei
2133 			if( nLvl > nLevel )
2134 				continue;
2135 			sal_uInt16 nEndOfs = 1;
2136 			sal_uInt8 nWish = nPara;
2137 			sal_uLong nNextOutNd = i + 1 < rOutNds.Count() ?
2138 				rOutNds[ i + 1 ]->GetIndex() : GetNodes().Count();
2139 			sal_Bool bKeep = sal_False;
2140 			while( ( nWish || bKeep ) && nIndex + nEndOfs < nNextOutNd &&
2141 				   GetNodes()[ nIndex + nEndOfs ]->IsTxtNode() )
2142 			{
2143 				SwTxtNode* pTxtNode = (SwTxtNode*)GetNodes()[ nIndex+nEndOfs ];
2144 				if( pTxtNode->GetTxt().Len() && nWish )
2145 					--nWish;
2146 				bKeep = pTxtNode->GetSwAttrSet().GetKeep().GetValue();
2147 				++nEndOfs;
2148 			}
2149 
2150 			SwNodeRange aRange( *rOutNds[ i ], 0, *rOutNds[ i ], nEndOfs );
2151 			GetNodes()._Copy( aRange, aEndOfDoc );
2152 		}
2153 		const SwTxtFmtColls *pColl = pExtDoc->GetTxtFmtColls();
2154 		for( i = 0; i < pColl->Count(); ++i )
2155             (*pColl)[ i ]->ResetFmtAttr( RES_PAGEDESC, RES_BREAK );
2156 		SwNodeIndex aIndx( pExtDoc->GetNodes().GetEndOfExtras() );
2157 		++aEndOfDoc;
2158 		while( aIndx < aEndOfDoc )
2159 		{
2160 			SwNode *pNode;
2161 			sal_Bool bDelete = sal_False;
2162 			if(	(pNode = &aIndx.GetNode())->IsTxtNode() )
2163 			{
2164 				SwTxtNode *pNd = (SwTxtNode*)pNode;
2165 				if( pNd->HasSwAttrSet() )
2166 					pNd->ResetAttr( RES_PAGEDESC, RES_BREAK );
2167 				if( bImpress )
2168 				{
2169 					SwTxtFmtColl* pMyColl = pNd->GetTxtColl();
2170 					//sal_uInt16 nHeadLine = static_cast<sal_uInt16>(pMyColl->GetOutlineLevel()==NO_NUMBERING ?//#outlinelevel,zhaojianwei
2171                     const sal_uInt16 nHeadLine = static_cast<sal_uInt16>(
2172                                 !pMyColl->IsAssignedToListLevelOfOutlineStyle() //<-end,zhaojianwei
2173                                 ? RES_POOLCOLL_HEADLINE2
2174                                 : RES_POOLCOLL_HEADLINE1 );
2175 					pMyColl = pExtDoc->GetTxtCollFromPool( nHeadLine );
2176 					pNd->ChgFmtColl( pMyColl );
2177 				}
2178 				if( !pNd->Len() &&
2179 					pNd->StartOfSectionIndex()+2 < pNd->EndOfSectionIndex() )
2180 				{
2181 					bDelete = sal_True;
2182 					pExtDoc->GetNodes().Delete( aIndx );
2183 				}
2184 			}
2185 			if( !bDelete )
2186 				++aIndx;
2187 		}
2188 		::EndProgress( GetDocShell() );
2189 	}
2190 }
2191 
2192 	// loesche den nicht sichtbaren Content aus dem Document, wie z.B.:
2193 	// versteckte Bereiche, versteckte Absaetze
2194 bool SwDoc::RemoveInvisibleContent()
2195 {
2196 	sal_Bool bRet = sal_False;
2197     GetIDocumentUndoRedo().StartUndo( UNDO_UI_DELETE_INVISIBLECNTNT, NULL );
2198 
2199 	{
2200 		SwTxtNode* pTxtNd;
2201         SwIterator<SwFmtFld,SwFieldType> aIter( *GetSysFldType( RES_HIDDENPARAFLD )  );
2202         for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld;  pFmtFld = aIter.Next() )
2203         {
2204 			if( pFmtFld->GetTxtFld() &&
2205 				0 != ( pTxtNd = (SwTxtNode*)pFmtFld->GetTxtFld()->GetpTxtNode() ) &&
2206                 pTxtNd->GetpSwpHints() && pTxtNd->HasHiddenParaField() &&
2207 				&pTxtNd->GetNodes() == &GetNodes() )
2208 			{
2209 				bRet = sal_True;
2210                 SwPaM aPam( *pTxtNd, 0, *pTxtNd, pTxtNd->GetTxt().Len() );
2211 
2212                 // Remove hidden paragraph or delete contents:
2213                 // Delete contents if
2214                 // 1. removing the paragraph would result in an empty section or
2215                 // 2. if the paragraph is the last paragraph in the section and
2216                 //    there is no paragraph in front of the paragraph:
2217                 if ( ( 2 == pTxtNd->EndOfSectionIndex() - pTxtNd->StartOfSectionIndex() ) ||
2218                      ( 1 == pTxtNd->EndOfSectionIndex() - pTxtNd->GetIndex() &&
2219                        !GetNodes()[ pTxtNd->GetIndex() - 1 ]->GetTxtNode() ) )
2220                 {
2221                     DeleteRange( aPam );
2222                 }
2223                 else
2224                 {
2225                     aPam.DeleteMark();
2226                     DelFullPara( aPam );
2227                 }
2228             }
2229         }
2230 	}
2231 
2232     //
2233     // Remove any hidden paragraph (hidden text attribute)
2234     //
2235     for( sal_uLong n = GetNodes().Count(); n; )
2236     {
2237         SwTxtNode* pTxtNd = GetNodes()[ --n ]->GetTxtNode();
2238         if ( pTxtNd )
2239         {
2240             bool bRemoved = false;
2241             SwPaM aPam( *pTxtNd, 0, *pTxtNd, pTxtNd->GetTxt().Len() );
2242             if ( pTxtNd->HasHiddenCharAttribute( true ) )
2243             {
2244                 bRemoved = sal_True;
2245                 bRet = sal_True;
2246 
2247                 // Remove hidden paragraph or delete contents:
2248                 // Delete contents if
2249                 // 1. removing the paragraph would result in an empty section or
2250                 // 2. if the paragraph is the last paragraph in the section and
2251                 //    there is no paragraph in front of the paragraph:
2252 
2253                 if ( ( 2 == pTxtNd->EndOfSectionIndex() - pTxtNd->StartOfSectionIndex() ) ||
2254                      ( 1 == pTxtNd->EndOfSectionIndex() - pTxtNd->GetIndex() &&
2255                        !GetNodes()[ pTxtNd->GetIndex() - 1 ]->GetTxtNode() ) )
2256                 {
2257                     DeleteRange( aPam );
2258                 }
2259                 else
2260                 {
2261                     aPam.DeleteMark();
2262 					DelFullPara( aPam );
2263 				}
2264             }
2265             else if ( pTxtNd->HasHiddenCharAttribute( false ) )
2266             {
2267                 bRemoved = sal_True;
2268                 bRet = sal_True;
2269                 SwScriptInfo::DeleteHiddenRanges( *pTxtNd );
2270             }
2271 
2272             // --> FME 2006-01-11 #120473#
2273             // Footnotes/Frames may have been removed, therefore we have
2274             // to reset n:
2275             if ( bRemoved )
2276                 n = aPam.GetPoint()->nNode.GetIndex();
2277             // <--
2278         }
2279     }
2280 
2281 	{
2282 		// dann noch alle versteckten Bereiche loeschen/leeren
2283 		SwSectionFmts aSectFmts;
2284 		SwSectionFmts& rSectFmts = GetSections();
2285 		sal_uInt16 n;
2286 
2287 		for( n = rSectFmts.Count(); n; )
2288 		{
2289 			SwSectionFmt* pSectFmt = rSectFmts[ --n ];
2290 		    // don't add sections in Undo/Redo
2291             if( !pSectFmt->IsInNodesArr())
2292                 continue;
2293 			SwSection* pSect = pSectFmt->GetSection();
2294 			if( pSect->CalcHiddenFlag() )
2295 			{
2296 				SwSection* pParent = pSect, *pTmp;
2297 				while( 0 != (pTmp = pParent->GetParent() ))
2298 				{
2299 					if( pTmp->IsHiddenFlag() )
2300 						pSect = pTmp;
2301 					pParent = pTmp;
2302 				}
2303 
2304 				if( USHRT_MAX == aSectFmts.GetPos( pSect->GetFmt() ) )
2305 					aSectFmts.Insert( pSect->GetFmt(), 0 );
2306 			}
2307 			if( pSect->GetCondition().Len() )
2308             {
2309                 SwSectionData aSectionData( *pSect );
2310                 aSectionData.SetCondition( aEmptyStr );
2311                 aSectionData.SetHidden( false );
2312                 UpdateSection( n, aSectionData );
2313             }
2314         }
2315 
2316 		if( 0 != ( n = aSectFmts.Count() ))
2317 		{
2318 			while( n )
2319 			{
2320 				SwSectionFmt* pSectFmt = aSectFmts[ --n ];
2321 				SwSectionNode* pSectNd = pSectFmt->GetSectionNode();
2322 				if( pSectNd )
2323 				{
2324 					bRet = sal_True;
2325 					SwPaM aPam( *pSectNd );
2326 
2327                     if( pSectNd->StartOfSectionNode()->StartOfSectionIndex() ==
2328 						pSectNd->GetIndex() - 1 &&
2329                         pSectNd->StartOfSectionNode()->EndOfSectionIndex() ==
2330 						pSectNd->EndOfSectionIndex() + 1 )
2331 					{
2332 						// nur den Inhalt loeschen
2333 						SwCntntNode* pCNd = GetNodes().GoNext(
2334 												&aPam.GetPoint()->nNode );
2335 						aPam.GetPoint()->nContent.Assign( pCNd, 0 );
2336 						aPam.SetMark();
2337 						aPam.GetPoint()->nNode = *pSectNd->EndOfSectionNode();
2338 						pCNd = GetNodes().GoPrevious(
2339 												&aPam.GetPoint()->nNode );
2340 						aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
2341 
2342                         DeleteRange( aPam );
2343                     }
2344 					else
2345 					{
2346 						// die gesamte Section loeschen
2347 						aPam.SetMark();
2348 						aPam.GetPoint()->nNode = *pSectNd->EndOfSectionNode();
2349 						DelFullPara( aPam );
2350 					}
2351 
2352 				}
2353 			}
2354 			aSectFmts.Remove( 0, aSectFmts.Count() );
2355 		}
2356 	}
2357 
2358 	if( bRet )
2359 		SetModified();
2360     GetIDocumentUndoRedo().EndUndo( UNDO_UI_DELETE_INVISIBLECNTNT, NULL );
2361 	return bRet;
2362 }
2363 /*-- 25.08.2010 14:18:12---------------------------------------------------
2364 
2365   -----------------------------------------------------------------------*/
2366 bool SwDoc::HasInvisibleContent() const
2367 {
2368     sal_Bool bRet = sal_False;
2369 
2370     SwClientIter aIter( *GetSysFldType( RES_HIDDENPARAFLD ) );
2371     if( aIter.First( TYPE( SwFmtFld ) ) )
2372         bRet = sal_True;
2373 
2374     //
2375     // Search for any hidden paragraph (hidden text attribute)
2376     //
2377     if( ! bRet )
2378     {
2379         for( sal_uLong n = GetNodes().Count(); !bRet && (n > 0); )
2380         {
2381             SwTxtNode* pTxtNd = GetNodes()[ --n ]->GetTxtNode();
2382             if ( pTxtNd )
2383             {
2384                 SwPaM aPam( *pTxtNd, 0, *pTxtNd, pTxtNd->GetTxt().Len() );
2385                 if( pTxtNd->HasHiddenCharAttribute( true ) ||  ( pTxtNd->HasHiddenCharAttribute( false ) ) )
2386                 {
2387                     bRet = sal_True;
2388                 }
2389             }
2390         }
2391     }
2392 
2393     if( ! bRet )
2394     {
2395         const SwSectionFmts& rSectFmts = GetSections();
2396         sal_uInt16 n;
2397 
2398         for( n = rSectFmts.Count(); !bRet && (n > 0); )
2399         {
2400             SwSectionFmt* pSectFmt = rSectFmts[ --n ];
2401             // don't add sections in Undo/Redo
2402             if( !pSectFmt->IsInNodesArr())
2403                 continue;
2404             SwSection* pSect = pSectFmt->GetSection();
2405             if( pSect->IsHidden() )
2406                 bRet = sal_True;
2407         }
2408     }
2409     return bRet;
2410 }
2411 
2412 bool SwDoc::RestoreInvisibleContent()
2413 {
2414     bool bRet = false;
2415     SwUndoId nLastUndoId(UNDO_EMPTY);
2416     if (GetIDocumentUndoRedo().GetLastUndoInfo(0, & nLastUndoId)
2417         && (UNDO_UI_DELETE_INVISIBLECNTNT == nLastUndoId))
2418     {
2419         GetIDocumentUndoRedo().Undo();
2420         GetIDocumentUndoRedo().ClearRedo();
2421         bRet = true;
2422     }
2423     return bRet;
2424 }
2425 
2426 /*-- 11.06.2004 08:34:04---------------------------------------------------
2427 
2428   -----------------------------------------------------------------------*/
2429 sal_Bool SwDoc::ConvertFieldsToText()
2430 {
2431     sal_Bool bRet = sal_False;
2432     LockExpFlds();
2433     GetIDocumentUndoRedo().StartUndo( UNDO_UI_REPLACE, NULL );
2434 
2435     const SwFldTypes* pMyFldTypes = GetFldTypes();
2436     sal_uInt16 nCount = pMyFldTypes->Count();
2437     //go backward, field types are removed
2438     for(sal_uInt16 nType = nCount;  nType > 0;  --nType)
2439     {
2440         const SwFieldType *pCurType = pMyFldTypes->GetObject(nType - 1);
2441 
2442         if ( RES_POSTITFLD == pCurType->Which() )
2443             continue;
2444 
2445         SwIterator<SwFmtFld,SwFieldType> aIter( *pCurType );
2446         ::std::vector<const SwFmtFld*> aFieldFmts;
2447         for( SwFmtFld* pCurFldFmt = aIter.First(); pCurFldFmt; pCurFldFmt = aIter.Next() )
2448             aFieldFmts.push_back(pCurFldFmt);
2449 
2450         ::std::vector<const SwFmtFld*>::iterator aBegin = aFieldFmts.begin();
2451         ::std::vector<const SwFmtFld*>::iterator aEnd = aFieldFmts.end();
2452         while(aBegin != aEnd)
2453         {
2454             const SwTxtFld *pTxtFld = (*aBegin)->GetTxtFld();
2455             // skip fields that are currently not in the document
2456             // e.g. fields in undo or redo array
2457 
2458             sal_Bool bSkip = !pTxtFld ||
2459                          !pTxtFld->GetpTxtNode()->GetNodes().IsDocNodes();
2460 
2461             if (!bSkip)
2462             {
2463                 sal_Bool bInHeaderFooter = IsInHeaderFooter(SwNodeIndex(*pTxtFld->GetpTxtNode()));
2464                 const SwFmtFld& rFmtFld = pTxtFld->GetFld();
2465                 const SwField*  pField = rFmtFld.GetFld();
2466 
2467                 //#i55595# some fields have to be excluded in headers/footers
2468                 sal_uInt16 nWhich = pField->GetTyp()->Which();
2469                 if(!bInHeaderFooter ||
2470                         (nWhich != RES_PAGENUMBERFLD &&
2471                         nWhich != RES_CHAPTERFLD &&
2472                         nWhich != RES_GETEXPFLD&&
2473                         nWhich != RES_SETEXPFLD&&
2474                         nWhich != RES_INPUTFLD&&
2475                         nWhich != RES_REFPAGEGETFLD&&
2476                         nWhich != RES_REFPAGESETFLD))
2477                 {
2478                     String sText = pField->ExpandField(true);
2479                     //database fields should not convert their command into text
2480                     if( RES_DBFLD == pCurType->Which() && !static_cast<const SwDBField*>(pField)->IsInitialized())
2481                         sText.Erase();
2482 
2483                     //now remove the field and insert the string
2484                     SwPaM aPam1(*pTxtFld->GetpTxtNode(), *pTxtFld->GetStart());
2485                     aPam1.Move();
2486                     //insert first to keep the field's attributes
2487                     InsertString( aPam1, sText );
2488                     SwPaM aPam2(*pTxtFld->GetpTxtNode(), *pTxtFld->GetStart());
2489                     aPam2.SetMark();
2490                     aPam2.Move();
2491                     DeleteAndJoin(aPam2);//remove the field
2492                 }
2493             }
2494             ++aBegin;
2495         }
2496     }
2497 
2498     if( bRet )
2499         SetModified();
2500     GetIDocumentUndoRedo().EndUndo( UNDO_UI_REPLACE, NULL );
2501     UnlockExpFlds();
2502     return bRet;
2503 
2504 }
2505 
2506 bool SwDoc::IsVisibleLinks() const
2507 {
2508     return mbVisibleLinks;
2509 }
2510 
2511 void SwDoc::SetVisibleLinks(bool bFlag)
2512 {
2513     mbVisibleLinks = bFlag;
2514 }
2515 
2516 sfx2::LinkManager& SwDoc::GetLinkManager()
2517 {
2518     return *pLinkMgr;
2519 }
2520 
2521 const sfx2::LinkManager& SwDoc::GetLinkManager() const
2522 {
2523     return *pLinkMgr;
2524 }
2525 
2526 void SwDoc::SetLinksUpdated(const bool bNewLinksUpdated)
2527 {
2528     mbLinksUpdated = bNewLinksUpdated;
2529 }
2530 
2531 bool SwDoc::LinksUpdated() const
2532 {
2533     return mbLinksUpdated;
2534 }
2535 
2536 	// embedded alle lokalen Links (Bereiche/Grafiken)
2537 ::sfx2::SvBaseLink* lcl_FindNextRemovableLink( const ::sfx2::SvBaseLinks& rLinks, sfx2::LinkManager& rLnkMgr )
2538 {
2539     for( sal_uInt16 n = 0; n < rLinks.Count(); ++n )
2540     {
2541         ::sfx2::SvBaseLink* pLnk = &(*rLinks[ n ]);
2542         if( pLnk &&
2543             ( OBJECT_CLIENT_GRF == pLnk->GetObjType() ||
2544               OBJECT_CLIENT_FILE == pLnk->GetObjType() ) &&
2545             pLnk->ISA( SwBaseLink ) )
2546         {
2547                 ::sfx2::SvBaseLinkRef xLink = pLnk;
2548 
2549                 String sFName;
2550                 rLnkMgr.GetDisplayNames( xLink, 0, &sFName, 0, 0 );
2551 
2552                 INetURLObject aURL( sFName );
2553                 if( INET_PROT_FILE == aURL.GetProtocol() ||
2554                     INET_PROT_CID == aURL.GetProtocol() )
2555                     return pLnk;
2556         }
2557     }
2558     return 0;
2559 }
2560 bool SwDoc::EmbedAllLinks()
2561 {
2562 	sal_Bool bRet = sal_False;
2563 	sfx2::LinkManager& rLnkMgr = GetLinkManager();
2564     const ::sfx2::SvBaseLinks& rLinks = rLnkMgr.GetLinks();
2565     if( rLinks.Count() )
2566 	{
2567         ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
2568 
2569         ::sfx2::SvBaseLink* pLnk = 0;
2570         while( 0 != (pLnk = lcl_FindNextRemovableLink( rLinks, rLnkMgr ) ) )
2571 		{
2572             ::sfx2::SvBaseLinkRef xLink = pLnk;
2573             // dem Link sagen, das er aufgeloest wird!
2574             xLink->Closed();
2575 
2576             // falls einer vergessen hat sich auszutragen
2577             if( xLink.Is() )
2578                 rLnkMgr.Remove( xLink );
2579 
2580             bRet = sal_True;
2581 		}
2582 
2583         GetIDocumentUndoRedo().DelAllUndoObj();
2584 		SetModified();
2585 	}
2586 	return bRet;
2587 }
2588 
2589 /*--------------------------------------------------------------------
2590 	Beschreibung:
2591  --------------------------------------------------------------------*/
2592 
2593 sal_Bool SwDoc::IsInsTblFormatNum() const
2594 {
2595 	return SW_MOD()->IsInsTblFormatNum(get(IDocumentSettingAccess::HTML_MODE));
2596 }
2597 
2598 sal_Bool SwDoc::IsInsTblChangeNumFormat() const
2599 {
2600 	return SW_MOD()->IsInsTblChangeNumFormat(get(IDocumentSettingAccess::HTML_MODE));
2601 }
2602 
2603 /*--------------------------------------------------------------------
2604 	Beschreibung:
2605  --------------------------------------------------------------------*/
2606 
2607 sal_Bool SwDoc::IsInsTblAlignNum() const
2608 {
2609 	return SW_MOD()->IsInsTblAlignNum(get(IDocumentSettingAccess::HTML_MODE));
2610 }
2611 
2612         // setze das InsertDB als Tabelle Undo auf:
2613 void SwDoc::AppendUndoForInsertFromDB( const SwPaM& rPam, sal_Bool bIsTable )
2614 {
2615 	if( bIsTable )
2616 	{
2617 		const SwTableNode* pTblNd = rPam.GetPoint()->nNode.GetNode().FindTableNode();
2618 		if( pTblNd )
2619 		{
2620 			SwUndoCpyTbl* pUndo = new SwUndoCpyTbl;
2621 			pUndo->SetTableSttIdx( pTblNd->GetIndex() );
2622             GetIDocumentUndoRedo().AppendUndo( pUndo );
2623         }
2624     }
2625 	else if( rPam.HasMark() )
2626 	{
2627 		SwUndoCpyDoc* pUndo = new SwUndoCpyDoc( rPam );
2628 		pUndo->SetInsertRange( rPam, sal_False );
2629         GetIDocumentUndoRedo().AppendUndo( pUndo );
2630     }
2631 }
2632 
2633 void SwDoc::ChgTOX(SwTOXBase & rTOX, const SwTOXBase & rNew)
2634 {
2635     if (GetIDocumentUndoRedo().DoesUndo())
2636     {
2637         GetIDocumentUndoRedo().DelAllUndoObj();
2638 
2639         SwUndo * pUndo = new SwUndoTOXChange(&rTOX, rNew);
2640 
2641         GetIDocumentUndoRedo().AppendUndo(pUndo);
2642     }
2643 
2644     rTOX = rNew;
2645 
2646     if (rTOX.ISA(SwTOXBaseSection))
2647     {
2648         static_cast<SwTOXBaseSection &>(rTOX).Update();
2649         static_cast<SwTOXBaseSection &>(rTOX).UpdatePageNum();
2650     }
2651 }
2652 
2653 // #111827#
2654 String SwDoc::GetPaMDescr(const SwPaM & rPam) const
2655 {
2656     String aResult;
2657     bool bOK = false;
2658 
2659     if (rPam.GetNode(sal_True) == rPam.GetNode(sal_False))
2660     {
2661         SwTxtNode * pTxtNode = rPam.GetNode(sal_True)->GetTxtNode();
2662 
2663         if (0 != pTxtNode)
2664         {
2665             xub_StrLen nStart = rPam.Start()->nContent.GetIndex();
2666             xub_StrLen nEnd = rPam.End()->nContent.GetIndex();
2667 
2668             aResult += String(SW_RES(STR_START_QUOTE));
2669             aResult += ShortenString(pTxtNode->GetTxt().
2670                                      Copy(nStart, nEnd - nStart),
2671                                      nUndoStringLength,
2672                                      String(SW_RES(STR_LDOTS)));
2673             aResult += String(SW_RES(STR_END_QUOTE));
2674 
2675             bOK = true;
2676         }
2677     }
2678     else if (0 != rPam.GetNode(sal_True))
2679     {
2680         if (0 != rPam.GetNode(sal_False))
2681             aResult += String(SW_RES(STR_PARAGRAPHS));
2682 
2683         bOK = true;
2684     }
2685 
2686     if (! bOK)
2687         aResult += String("??", RTL_TEXTENCODING_ASCII_US);
2688 
2689     return aResult;
2690 }
2691 
2692 // -> #111840#
2693 SwField * SwDoc::GetField(const SwPosition & rPos)
2694 {
2695     SwTxtFld * const pAttr = GetTxtFld(rPos);
2696 
2697     return (pAttr) ? const_cast<SwField *>( pAttr->GetFld().GetFld() ) : 0;
2698 }
2699 
2700 SwTxtFld * SwDoc::GetTxtFld(const SwPosition & rPos)
2701 {
2702     SwTxtNode * const pNode = rPos.nNode.GetNode().GetTxtNode();
2703 
2704     return (pNode)
2705         ? static_cast<SwTxtFld*>( pNode->GetTxtAttrForCharAt(
2706                     rPos.nContent.GetIndex(), RES_TXTATR_FIELD) )
2707         : 0;
2708 }
2709 // <- #111840#
2710 
2711 bool SwDoc::ContainsHiddenChars() const
2712 {
2713     for( sal_uLong n = GetNodes().Count(); n; )
2714     {
2715         SwNode* pNd = GetNodes()[ --n ];
2716         if ( ND_TEXTNODE == pNd->GetNodeType() &&
2717              ((SwTxtNode*)pNd)->HasHiddenCharAttribute( false ) )
2718             return true;
2719     }
2720 
2721     return false;
2722 }
2723 
2724 SwUnoCrsr* SwDoc::CreateUnoCrsr( const SwPosition& rPos, sal_Bool bTblCrsr )
2725 {
2726 	SwUnoCrsr* pNew;
2727 	if( bTblCrsr )
2728 		pNew = new SwUnoTableCrsr( rPos );
2729 	else
2730 		pNew = new SwUnoCrsr( rPos );
2731 
2732 	pUnoCrsrTbl->Insert( pNew, pUnoCrsrTbl->Count() );
2733 	return pNew;
2734 }
2735 
2736 void SwDoc::ChkCondColls()
2737 {
2738      for (sal_uInt16 n = 0; n < pTxtFmtCollTbl->Count(); n++)
2739      {
2740         SwTxtFmtColl *pColl = (*pTxtFmtCollTbl)[n];
2741         if (RES_CONDTXTFMTCOLL == pColl->Which())
2742             pColl->CallSwClientNotify( SwAttrHint(RES_CONDTXTFMTCOLL) );
2743      }
2744 }
2745 
2746 #ifdef FUTURE_VBA
2747 uno::Reference< script::vba::XVBAEventProcessor >
2748 SwDoc::GetVbaEventProcessor()
2749 {
2750 	if( !mxVbaEvents.is() && pDocShell && ooo::vba::isAlienWordDoc( *pDocShell ) )
2751 	{
2752         try
2753         {
2754             uno::Reference< frame::XModel > xModel( pDocShell->GetModel(), uno::UNO_SET_THROW );
2755             uno::Sequence< uno::Any > aArgs(1);
2756             aArgs[0] <<= xModel;
2757             mxVbaEvents.set( ooo::vba::createVBAUnoAPIServiceWithArgs( pDocShell, "com.sun.star.script.vba.VBATextEventProcessor" , aArgs ), uno::UNO_QUERY_THROW );
2758         }
2759         catch( uno::Exception& )
2760         {
2761         }
2762 	}
2763 	return mxVbaEvents;
2764 }
2765 #endif
2766 
2767 void SwDoc::setExternalData(::sw::tExternalDataType eType,
2768                             ::sw::tExternalDataPointer pPayload)
2769 {
2770     m_externalData[eType] = pPayload;
2771 }
2772 
2773 ::sw::tExternalDataPointer SwDoc::getExternalData(::sw::tExternalDataType eType)
2774 {
2775     return m_externalData[eType];
2776 }
2777