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