update credits
[LibreOffice.git] / sw / source / core / doc / doc.cxx
blob8cf4f11aae04bd55d06b1cb70131156c67c06521
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <doc.hxx>
22 #include <UndoManager.hxx>
23 #include <hintids.hxx>
25 #include <tools/shl.hxx>
26 #include <tools/globname.hxx>
27 #include <svx/svxids.hrc>
28 #include <rtl/random.h>
30 #include <com/sun/star/i18n/WordType.hpp>
31 #include <com/sun/star/i18n/ForbiddenCharacters.hpp>
32 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
33 #include <com/sun/star/beans/NamedValue.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
36 #include <com/sun/star/document/XDocumentProperties.hpp>
37 #include <comphelper/processfactory.hxx>
38 #include <comphelper/string.hxx>
39 #include <tools/urlobj.hxx>
40 #include <tools/poly.hxx>
41 #include <tools/multisel.hxx>
42 #include <rtl/ustring.hxx>
43 #include <vcl/virdev.hxx>
44 #include <svl/itemiter.hxx>
45 #include <svl/poolitem.hxx>
46 #include <unotools/syslocale.hxx>
47 #include <sfx2/printer.hxx>
48 #include <editeng/keepitem.hxx>
49 #include <editeng/charsetcoloritem.hxx>
50 #include <editeng/formatbreakitem.hxx>
51 #include <sfx2/linkmgr.hxx>
52 #include <editeng/forbiddencharacterstable.hxx>
53 #include <svx/svdmodel.hxx>
54 #include <editeng/pbinitem.hxx>
55 #include <unotools/charclass.hxx>
56 #include <unotools/localedatawrapper.hxx>
57 #include <vcl/timer.hxx>
59 #include <swatrset.hxx>
60 #include <swmodule.hxx>
61 #include <fmtpdsc.hxx>
62 #include <fmtanchr.hxx>
63 #include <fmtrfmrk.hxx>
64 #include <fmtinfmt.hxx>
65 #include <fmtfld.hxx>
66 #include <txtfld.hxx>
67 #include <dbfld.hxx>
68 #include <txtinet.hxx>
69 #include <txtrfmrk.hxx>
70 #include <frmatr.hxx>
71 #include <linkenum.hxx>
72 #include <pagefrm.hxx>
73 #include <rootfrm.hxx>
74 #include <swtable.hxx>
75 #include <pam.hxx>
76 #include <ndtxt.hxx>
77 #include <swundo.hxx> // for the UndoIds
78 #include <UndoCore.hxx>
79 #include <UndoInsert.hxx>
80 #include <UndoSplitMove.hxx>
81 #include <UndoTable.hxx>
82 #include <pagedesc.hxx> // DTor
83 #include <breakit.hxx>
84 #include <ndole.hxx>
85 #include <ndgrf.hxx>
86 #include <rolbck.hxx> // Undo attr
87 #include <doctxm.hxx> // for the index stuff
88 #include <grfatr.hxx>
89 #include <poolfmt.hxx> // pool template ids
90 #include <mvsave.hxx> // for server functionality
91 #include <SwGrammarMarkUp.hxx>
92 #include <scriptinfo.hxx>
93 #include <acorrect.hxx> // auto correction
94 #include <mdiexp.hxx> // status indicator
95 #include <docstat.hxx>
96 #include <docary.hxx>
97 #include <redline.hxx>
98 #include <fldupde.hxx>
99 #include <swbaslnk.hxx>
100 #include <printdata.hxx>
101 #include <cmdid.h> // for the dflt printer in SetJob
102 #include <statstr.hrc> // StatLine string
103 #include <comcore.hrc>
104 #include <SwUndoTOXChange.hxx>
105 #include <SwUndoFmt.hxx>
106 #include <unocrsr.hxx>
107 #include <docsh.hxx>
108 #include <viewopt.hxx>
109 #include <docfld.hxx> // _SetGetExpFld
110 #include <docufld.hxx> // SwPostItField
111 #include <viewsh.hxx>
112 #include <shellres.hxx>
113 #include <txtfrm.hxx>
114 #include <attrhint.hxx>
115 #include <view.hxx>
117 #include <wdocsh.hxx> // SwWebDocShell
118 #include <prtopt.hxx> // SwPrintOptions
120 #include <vector>
121 #include <map>
123 #include <osl/diagnose.h>
124 #include <osl/interlck.h>
125 #include <vbahelper/vbaaccesshelper.hxx>
127 #include "switerator.hxx"
129 /* @@@MAINTAINABILITY-HORROR@@@
130 Probably unwanted dependency on SwDocShell
132 #include <layouter.hxx>
134 using namespace ::com::sun::star;
136 /* IInterface */
137 sal_Int32 SwDoc::acquire()
139 OSL_ENSURE(mReferenceCount >= 0, "Negative reference count detected! This is a sign for unbalanced acquire/release calls.");
140 return osl_atomic_increment(&mReferenceCount);
143 sal_Int32 SwDoc::release()
145 OSL_PRECOND(mReferenceCount >= 1, "Object is already released! Releasing it again leads to a negative reference count.");
146 return osl_atomic_decrement(&mReferenceCount);
149 sal_Int32 SwDoc::getReferenceCount() const
151 OSL_ENSURE(mReferenceCount >= 0, "Negative reference count detected! This is a sign for unbalanced acquire/release calls.");
152 return mReferenceCount;
155 /* IDocumentSettingAccess */
156 bool SwDoc::get(/*[in]*/ DocumentSettingId id) const
158 switch (id)
160 // COMPATIBILITY FLAGS START
161 case PARA_SPACE_MAX: return mbParaSpaceMax; //(n8Dummy1 & DUMMY_PARASPACEMAX);
162 case PARA_SPACE_MAX_AT_PAGES: return mbParaSpaceMaxAtPages; //(n8Dummy1 & DUMMY_PARASPACEMAX_AT_PAGES);
163 case TAB_COMPAT: return mbTabCompat; //(n8Dummy1 & DUMMY_TAB_COMPAT);
164 case ADD_FLY_OFFSETS: return mbAddFlyOffsets; //(n8Dummy2 & DUMMY_ADD_FLY_OFFSETS);
165 case ADD_EXT_LEADING: return mbAddExternalLeading; //(n8Dummy2 & DUMMY_ADD_EXTERNAL_LEADING);
166 case USE_VIRTUAL_DEVICE: return mbUseVirtualDevice; //(n8Dummy1 & DUMMY_USE_VIRTUAL_DEVICE);
167 case USE_HIRES_VIRTUAL_DEVICE: return mbUseHiResolutionVirtualDevice; //(n8Dummy2 & DUMMY_USE_HIRES_VIR_DEV);
168 case OLD_NUMBERING: return mbOldNumbering;
169 case OLD_LINE_SPACING: return mbOldLineSpacing;
170 case ADD_PARA_SPACING_TO_TABLE_CELLS: return mbAddParaSpacingToTableCells;
171 case USE_FORMER_OBJECT_POS: return mbUseFormerObjectPos;
172 case USE_FORMER_TEXT_WRAPPING: return mbUseFormerTextWrapping;
173 case CONSIDER_WRAP_ON_OBJECT_POSITION: return mbConsiderWrapOnObjPos;
174 case DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK: return mbDoNotJustifyLinesWithManualBreak;
175 case IGNORE_FIRST_LINE_INDENT_IN_NUMBERING: return mbIgnoreFirstLineIndentInNumbering;
176 case OUTLINE_LEVEL_YIELDS_OUTLINE_RULE: return mbOutlineLevelYieldsOutlineRule;
177 case TABLE_ROW_KEEP: return mbTableRowKeep;
178 case IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION: return mbIgnoreTabsAndBlanksForLineCalculation;
179 case DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE: return mbDoNotCaptureDrawObjsOnPage;
180 // #i68949#
181 case CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAME: return mbClipAsCharacterAnchoredWriterFlyFrames;
182 case UNIX_FORCE_ZERO_EXT_LEADING: return mbUnixForceZeroExtLeading;
183 case TABS_RELATIVE_TO_INDENT : return mbTabRelativeToIndent;
184 case PROTECT_FORM: return mbProtectForm;
185 // #i89181#
186 case TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST: return mbTabAtLeftIndentForParagraphsInList;
187 case INVERT_BORDER_SPACING: return mbInvertBorderSpacing;
188 case COLLAPSE_EMPTY_CELL_PARA: return mbCollapseEmptyCellPara;
189 case SMALL_CAPS_PERCENTAGE_66: return mbSmallCapsPercentage66;
190 case TAB_OVERFLOW: return mbTabOverflow;
191 case UNBREAKABLE_NUMBERINGS: return mbUnbreakableNumberings;
192 case CLIPPED_PICTURES: return mbClippedPictures;
193 case BACKGROUND_PARA_OVER_DRAWINGS: return mbBackgroundParaOverDrawings;
194 case TAB_OVER_MARGIN: return mbTabOverMargin;
196 case BROWSE_MODE: return mbLastBrowseMode; // Attention: normally the ViewShell has to be asked!
197 case HTML_MODE: return mbHTMLMode;
198 case GLOBAL_DOCUMENT: return mbIsGlobalDoc;
199 case GLOBAL_DOCUMENT_SAVE_LINKS: return mbGlblDocSaveLinks;
200 case LABEL_DOCUMENT: return mbIsLabelDoc;
201 case PURGE_OLE: return mbPurgeOLE;
202 case KERN_ASIAN_PUNCTUATION: return mbKernAsianPunctuation;
203 case DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT: return mbDoNotResetParaAttrsForNumFont;
204 case MATH_BASELINE_ALIGNMENT: return mbMathBaselineAlignment;
205 case STYLES_NODEFAULT: return mbStylesNoDefault;
206 case FLOATTABLE_NOMARGINS: return mbFloattableNomargins;
207 case EMBED_FONTS: return mEmbedFonts;
208 case EMBED_SYSTEM_FONTS: return mEmbedSystemFonts;
209 default:
210 OSL_FAIL("Invalid setting id");
212 return false;
215 void SwDoc::set(/*[in]*/ DocumentSettingId id, /*[in]*/ bool value)
217 switch (id)
219 // COMPATIBILITY FLAGS START
220 case PARA_SPACE_MAX:
221 mbParaSpaceMax = value;
222 break;
223 case PARA_SPACE_MAX_AT_PAGES:
224 mbParaSpaceMaxAtPages = value;
225 break;
226 case TAB_COMPAT:
227 mbTabCompat = value;
228 break;
229 case ADD_FLY_OFFSETS:
230 mbAddFlyOffsets = value;
231 break;
232 case ADD_EXT_LEADING:
233 mbAddExternalLeading = value;
234 break;
235 case USE_VIRTUAL_DEVICE:
236 mbUseVirtualDevice = value;
237 break;
238 case USE_HIRES_VIRTUAL_DEVICE:
239 mbUseHiResolutionVirtualDevice = value;
240 break;
241 case OLD_NUMBERING:
242 if (mbOldNumbering != value)
244 mbOldNumbering = value;
246 const SwNumRuleTbl& rNmTbl = GetNumRuleTbl();
247 for( sal_uInt16 n = 0; n < rNmTbl.size(); ++n )
248 rNmTbl[n]->SetInvalidRule(sal_True);
250 UpdateNumRule();
252 if (mpOutlineRule)
254 mpOutlineRule->Validate();
255 // counting of phantoms depends on <IsOldNumbering()>
256 mpOutlineRule->SetCountPhantoms( !mbOldNumbering );
259 break;
260 case OLD_LINE_SPACING:
261 mbOldLineSpacing = value;
262 break;
263 case ADD_PARA_SPACING_TO_TABLE_CELLS:
264 mbAddParaSpacingToTableCells = value;
265 break;
266 case USE_FORMER_OBJECT_POS:
267 mbUseFormerObjectPos = value;
268 break;
269 case USE_FORMER_TEXT_WRAPPING:
270 mbUseFormerTextWrapping = value;
271 break;
272 case CONSIDER_WRAP_ON_OBJECT_POSITION:
273 mbConsiderWrapOnObjPos = value;
274 break;
275 case DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK:
276 mbDoNotJustifyLinesWithManualBreak = value;
277 break;
278 case IGNORE_FIRST_LINE_INDENT_IN_NUMBERING:
279 mbIgnoreFirstLineIndentInNumbering = value;
280 break;
282 case OUTLINE_LEVEL_YIELDS_OUTLINE_RULE:
283 mbOutlineLevelYieldsOutlineRule = value;
284 break;
286 case TABLE_ROW_KEEP:
287 mbTableRowKeep = value;
288 break;
290 case IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION:
291 mbIgnoreTabsAndBlanksForLineCalculation = value;
292 break;
294 case DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE:
295 mbDoNotCaptureDrawObjsOnPage = value;
296 break;
298 // #i68949#
299 case CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAME:
300 mbClipAsCharacterAnchoredWriterFlyFrames = value;
301 break;
303 case UNIX_FORCE_ZERO_EXT_LEADING:
304 mbUnixForceZeroExtLeading = value;
305 break;
307 case PROTECT_FORM:
308 mbProtectForm = value;
309 break;
311 case TABS_RELATIVE_TO_INDENT:
312 mbTabRelativeToIndent = value;
313 break;
314 // #i89181#
315 case TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST:
316 mbTabAtLeftIndentForParagraphsInList = value;
317 break;
319 case INVERT_BORDER_SPACING:
320 mbInvertBorderSpacing = value;
321 break;
323 case COLLAPSE_EMPTY_CELL_PARA:
324 mbCollapseEmptyCellPara = value;
325 break;
327 case SMALL_CAPS_PERCENTAGE_66:
328 mbSmallCapsPercentage66 = value;
329 break;
331 case TAB_OVERFLOW:
332 mbTabOverflow = value;
333 break;
335 case UNBREAKABLE_NUMBERINGS:
336 mbUnbreakableNumberings = value;
337 break;
339 case CLIPPED_PICTURES:
340 mbClippedPictures = value;
341 break;
343 case BACKGROUND_PARA_OVER_DRAWINGS:
344 mbBackgroundParaOverDrawings = value;
345 break;
347 case TAB_OVER_MARGIN:
348 mbTabOverMargin = value;
349 break;
351 // COMPATIBILITY FLAGS END
353 case BROWSE_MODE: //can be used temporary (load/save) when no ViewShell is avaiable
354 mbLastBrowseMode = value;
355 break;
357 case HTML_MODE:
358 mbHTMLMode = value;
359 break;
361 case GLOBAL_DOCUMENT:
362 mbIsGlobalDoc = value;
363 break;
365 case GLOBAL_DOCUMENT_SAVE_LINKS:
366 mbGlblDocSaveLinks = value;
367 break;
369 case LABEL_DOCUMENT:
370 mbIsLabelDoc = value;
371 break;
373 case PURGE_OLE:
374 mbPurgeOLE = value;
375 break;
377 case KERN_ASIAN_PUNCTUATION:
378 mbKernAsianPunctuation = value;
379 break;
381 case DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT:
382 mbDoNotResetParaAttrsForNumFont = value;
383 break;
384 case MATH_BASELINE_ALIGNMENT:
385 mbMathBaselineAlignment = value;
386 break;
387 case STYLES_NODEFAULT:
388 mbStylesNoDefault = value;
389 break;
390 case FLOATTABLE_NOMARGINS:
391 mbFloattableNomargins = value;
392 break;
393 case EMBED_FONTS:
394 mEmbedFonts = value;
395 break;
396 case EMBED_SYSTEM_FONTS:
397 mEmbedSystemFonts = value;
398 break;
399 default:
400 OSL_FAIL("Invalid setting id");
404 const i18n::ForbiddenCharacters*
405 SwDoc::getForbiddenCharacters(/*[in]*/ sal_uInt16 nLang, /*[in]*/ bool bLocaleData ) const
407 const i18n::ForbiddenCharacters* pRet = 0;
408 if( mxForbiddenCharsTable.is() )
409 pRet = mxForbiddenCharsTable->GetForbiddenCharacters( nLang, sal_False );
410 if( bLocaleData && !pRet && g_pBreakIt )
411 pRet = &g_pBreakIt->GetForbidden( (LanguageType)nLang );
412 return pRet;
415 void SwDoc::setForbiddenCharacters(/*[in]*/ sal_uInt16 nLang,
416 /*[in]*/ const com::sun::star::i18n::ForbiddenCharacters& rFChars )
418 if( !mxForbiddenCharsTable.is() )
420 mxForbiddenCharsTable = new SvxForbiddenCharactersTable( ::comphelper::getProcessComponentContext() );
422 mxForbiddenCharsTable->SetForbiddenCharacters( nLang, rFChars );
423 if( mpDrawModel )
425 mpDrawModel->SetForbiddenCharsTable( mxForbiddenCharsTable );
426 if( !mbInReading )
427 mpDrawModel->ReformatAllTextObjects();
430 SwRootFrm* pTmpRoot = GetCurrentLayout();
431 if( pTmpRoot && !mbInReading )
433 pTmpRoot->StartAllAction();
434 std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
435 std::for_each( aAllLayouts.begin(), aAllLayouts.end(), std::bind2nd(std::mem_fun(&SwRootFrm::InvalidateAllCntnt), INV_SIZE));
436 pTmpRoot->EndAllAction();
437 }//swmod 080310
438 SetModified();
441 rtl::Reference<SvxForbiddenCharactersTable>& SwDoc::getForbiddenCharacterTable()
443 if( !mxForbiddenCharsTable.is() )
445 mxForbiddenCharsTable = new SvxForbiddenCharactersTable( ::comphelper::getProcessComponentContext() );
447 return mxForbiddenCharsTable;
450 const rtl::Reference<SvxForbiddenCharactersTable>& SwDoc::getForbiddenCharacterTable() const
452 return mxForbiddenCharsTable;
455 sal_uInt16 SwDoc::getLinkUpdateMode( /*[in]*/bool bGlobalSettings ) const
457 sal_uInt16 nRet = mnLinkUpdMode;
458 if( bGlobalSettings && GLOBALSETTING == nRet )
459 nRet = SW_MOD()->GetLinkUpdMode(get(IDocumentSettingAccess::HTML_MODE));
460 return nRet;
463 void SwDoc::setLinkUpdateMode( /*[in]*/sal_uInt16 eMode )
465 mnLinkUpdMode = eMode;
468 sal_uInt32 SwDoc::getRsid() const
470 return mnRsid;
473 void SwDoc::setRsid( sal_uInt32 nVal )
475 // Increase the rsid with a random number smaller than 2^17. This way we
476 // expect to be able to edit a document 2^12 times before rsid overflows.
477 sal_uInt32 nIncrease = 0;
478 static rtlRandomPool aPool = rtl_random_createPool();
479 rtl_random_getBytes( aPool, &nIncrease, sizeof ( nIncrease ) );
480 nIncrease &= ( 1<<17 ) - 1;
481 nIncrease++; // make sure the new rsid is not the same
482 mnRsid = nVal + nIncrease;
485 sal_uInt32 SwDoc::getRsidRoot() const
487 return mnRsidRoot;
490 void SwDoc::setRsidRoot( sal_uInt32 nVal )
492 mnRsidRoot = nVal;
495 SwFldUpdateFlags SwDoc::getFieldUpdateFlags( /*[in]*/bool bGlobalSettings ) const
497 SwFldUpdateFlags eRet = meFldUpdMode;
498 if( bGlobalSettings && AUTOUPD_GLOBALSETTING == eRet )
499 eRet = SW_MOD()->GetFldUpdateFlags(get(IDocumentSettingAccess::HTML_MODE));
500 return eRet;
503 void SwDoc::setFieldUpdateFlags(/*[in]*/SwFldUpdateFlags eMode )
505 meFldUpdMode = eMode;
508 SwCharCompressType SwDoc::getCharacterCompressionType() const
510 return meChrCmprType;
513 void SwDoc::setCharacterCompressionType( /*[in]*/SwCharCompressType n )
515 if( meChrCmprType != n )
517 meChrCmprType = n;
518 if( mpDrawModel )
520 mpDrawModel->SetCharCompressType( static_cast<sal_uInt16>(n) );
521 if( !mbInReading )
522 mpDrawModel->ReformatAllTextObjects();
525 SwRootFrm* pTmpRoot = GetCurrentLayout();
526 if( pTmpRoot && !mbInReading )
528 pTmpRoot->StartAllAction();
529 std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
530 std::for_each( aAllLayouts.begin(), aAllLayouts.end(), std::bind2nd(std::mem_fun(&SwRootFrm::InvalidateAllCntnt), INV_SIZE));
531 pTmpRoot->EndAllAction();
532 }//swmod 080310
533 SetModified();
537 /* IDocumentDeviceAccess */
538 SfxPrinter* SwDoc::getPrinter(/*[in]*/ bool bCreate ) const
540 SfxPrinter* pRet = 0;
541 if ( !bCreate || mpPrt )
542 pRet = mpPrt;
543 else
544 pRet = &CreatePrinter_();
546 return pRet;
549 void SwDoc::setPrinter(/*[in]*/ SfxPrinter *pP,/*[in]*/ bool bDeleteOld,/*[in]*/ bool bCallPrtDataChanged )
551 if ( pP != mpPrt )
553 if ( bDeleteOld )
554 delete mpPrt;
555 mpPrt = pP;
557 // our printer should always use TWIP. Don't rely on this being set in ViewShell::InitPrt, there
558 // are situations where this isn't called.
559 // #i108712# / 2010-02-26 / frank.schoenheit@sun.com
560 if ( mpPrt )
562 MapMode aMapMode( mpPrt->GetMapMode() );
563 aMapMode.SetMapUnit( MAP_TWIP );
564 mpPrt->SetMapMode( aMapMode );
567 if ( mpDrawModel && !get( IDocumentSettingAccess::USE_VIRTUAL_DEVICE ) )
568 mpDrawModel->SetRefDevice( mpPrt );
571 if ( bCallPrtDataChanged &&
572 // #i41075# Do not call PrtDataChanged() if we do not
573 // use the printer for formatting:
574 !get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) )
575 PrtDataChanged();
578 VirtualDevice* SwDoc::getVirtualDevice(/*[in]*/ bool bCreate ) const
580 VirtualDevice* pRet = 0;
581 if ( !bCreate || mpVirDev )
582 pRet = mpVirDev;
583 else
584 pRet = &CreateVirtualDevice_();
586 return pRet;
589 void SwDoc::setVirtualDevice(/*[in]*/ VirtualDevice* pVd,/*[in]*/ bool bDeleteOld, /*[in]*/ bool )
591 if ( mpVirDev != pVd )
593 if ( bDeleteOld )
594 delete mpVirDev;
595 mpVirDev = pVd;
597 if ( mpDrawModel && get( IDocumentSettingAccess::USE_VIRTUAL_DEVICE ) )
598 mpDrawModel->SetRefDevice( mpVirDev );
602 OutputDevice* SwDoc::getReferenceDevice(/*[in]*/ bool bCreate ) const
604 OutputDevice* pRet = 0;
605 if ( !get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) )
607 pRet = getPrinter( bCreate );
609 if ( bCreate && !mpPrt->IsValid() )
611 pRet = getVirtualDevice( sal_True );
614 else
616 pRet = getVirtualDevice( bCreate );
619 return pRet;
622 void SwDoc::setReferenceDeviceType(/*[in]*/ bool bNewVirtual,/*[in]*/ bool bNewHiRes )
624 if ( get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) != bNewVirtual ||
625 get(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE) != bNewHiRes )
627 if ( bNewVirtual )
629 VirtualDevice* pMyVirDev = getVirtualDevice( true );
630 if ( !bNewHiRes )
631 pMyVirDev->SetReferenceDevice( VirtualDevice::REFDEV_MODE06 );
632 else
633 pMyVirDev->SetReferenceDevice( VirtualDevice::REFDEV_MODE_MSO1 );
635 if( mpDrawModel )
636 mpDrawModel->SetRefDevice( pMyVirDev );
638 else
640 // #i41075#
641 // We have to take care that a printer exists before calling
642 // PrtDataChanged() in order to prevent that PrtDataChanged()
643 // triggers this funny situation:
644 // getReferenceDevice()->getPrinter()->CreatePrinter_()
645 // ->setPrinter()-> PrtDataChanged()
646 SfxPrinter* pPrinter = getPrinter( true );
647 if( mpDrawModel )
648 mpDrawModel->SetRefDevice( pPrinter );
651 set(IDocumentSettingAccess::USE_VIRTUAL_DEVICE, bNewVirtual );
652 set(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE, bNewHiRes );
653 PrtDataChanged();
654 SetModified();
658 const JobSetup* SwDoc::getJobsetup() const
660 return mpPrt ? &mpPrt->GetJobSetup() : 0;
663 void SwDoc::setJobsetup(/*[in]*/ const JobSetup &rJobSetup )
665 bool bCheckPageDescs = 0 == mpPrt;
666 bool bDataChanged = false;
668 if ( mpPrt )
670 if ( mpPrt->GetName() == rJobSetup.GetPrinterName() )
672 if ( mpPrt->GetJobSetup() != rJobSetup )
674 mpPrt->SetJobSetup( rJobSetup );
675 bDataChanged = true;
678 else
679 delete mpPrt, mpPrt = 0;
682 if( !mpPrt )
684 //The ItemSet is deleted by Sfx!
685 SfxItemSet *pSet = new SfxItemSet( GetAttrPool(),
686 FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER,
687 SID_HTML_MODE, SID_HTML_MODE,
688 SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN,
689 SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC,
690 0 );
691 SfxPrinter *p = new SfxPrinter( pSet, rJobSetup );
692 if ( bCheckPageDescs )
693 setPrinter( p, true, true );
694 else
696 mpPrt = p;
697 bDataChanged = true;
700 if ( bDataChanged && !get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE) )
701 PrtDataChanged();
704 const SwPrintData & SwDoc::getPrintData() const
706 if(!mpPrtData)
708 SwDoc * pThis = const_cast< SwDoc * >(this);
709 pThis->mpPrtData = new SwPrintData;
711 // SwPrintData should be initialized from the configuration,
712 // the respective config item is implememted by SwPrintOptions which
713 // is also derived from SwPrintData
714 const SwDocShell *pDocSh = GetDocShell();
715 OSL_ENSURE( pDocSh, "pDocSh is 0, can't determine if this is a WebDoc or not" );
716 bool bWeb = 0 != dynamic_cast< const SwWebDocShell * >(pDocSh);
717 SwPrintOptions aPrintOptions( bWeb );
718 *pThis->mpPrtData = aPrintOptions;
720 return *mpPrtData;
723 void SwDoc::setPrintData(/*[in]*/ const SwPrintData& rPrtData )
725 if(!mpPrtData)
726 mpPrtData = new SwPrintData;
727 *mpPrtData = rPrtData;
730 /* Implementations the next Interface here */
733 * Document editing (Doc-SS) to fill the document
734 * by the RTF parser and for the EditShell.
736 void SwDoc::ChgDBData(const SwDBData& rNewData)
738 if( rNewData != maDBData )
740 maDBData = rNewData;
741 SetModified();
743 GetSysFldType(RES_DBNAMEFLD)->UpdateFlds();
746 bool SwDoc::SplitNode( const SwPosition &rPos, bool bChkTableStart )
748 SwCntntNode *pNode = rPos.nNode.GetNode().GetCntntNode();
749 if(0 == pNode)
750 return false;
753 // BUG 26675: Send DataChanged before deleting, so that we notice which objects are in scope.
754 // After that they can be before/after the position.
755 SwDataChanged aTmp( this, rPos );
758 SwUndoSplitNode* pUndo = 0;
759 if (GetIDocumentUndoRedo().DoesUndo())
761 GetIDocumentUndoRedo().ClearRedo();
762 // insert the Undo object (currently only for TextNode)
763 if( pNode->IsTxtNode() )
765 pUndo = new SwUndoSplitNode( this, rPos, bChkTableStart );
766 GetIDocumentUndoRedo().AppendUndo(pUndo);
770 // Update the rsid of the old and the new node unless
771 // the old node is split at the beginning or at the end
772 SwTxtNode *pTxtNode = rPos.nNode.GetNode().GetTxtNode();
773 xub_StrLen nPos = rPos.nContent.GetIndex();
774 if( pTxtNode && nPos && nPos != pTxtNode->Len() )
776 UpdateParRsid( pTxtNode );
779 //JP 28.01.97: Special case for SplitNode at table start:
780 // If it is at the beginning of a Doc/Fly/Footer/... or right at after a table
781 // then insert a paragraph before it.
782 if( bChkTableStart && !rPos.nContent.GetIndex() && pNode->IsTxtNode() )
784 sal_uLong nPrevPos = rPos.nNode.GetIndex() - 1;
785 const SwTableNode* pTblNd;
786 const SwNode* pNd = GetNodes()[ nPrevPos ];
787 if( pNd->IsStartNode() &&
788 SwTableBoxStartNode == ((SwStartNode*)pNd)->GetStartNodeType() &&
789 0 != ( pTblNd = GetNodes()[ --nPrevPos ]->GetTableNode() ) &&
790 ((( pNd = GetNodes()[ --nPrevPos ])->IsStartNode() &&
791 SwTableBoxStartNode != ((SwStartNode*)pNd)->GetStartNodeType() )
792 || ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsTableNode() )
793 || pNd->IsCntntNode() ))
795 if( pNd->IsCntntNode() )
797 //JP 30.04.99 Bug 65660:
798 // There are no page breaks outside of the normal body area,
799 // so this is not a valid condition to insert a paragraph.
800 if( nPrevPos < GetNodes().GetEndOfExtras().GetIndex() )
801 pNd = 0;
802 else
804 // Only if the table has page breaks!
805 const SwFrmFmt* pFrmFmt = pTblNd->GetTable().GetFrmFmt();
806 if( SFX_ITEM_SET != pFrmFmt->GetItemState(RES_PAGEDESC, sal_False) &&
807 SFX_ITEM_SET != pFrmFmt->GetItemState( RES_BREAK, sal_False ) )
808 pNd = 0;
812 if( pNd )
814 SwTxtNode* pTxtNd = GetNodes().MakeTxtNode(
815 SwNodeIndex( *pTblNd ),
816 GetTxtCollFromPool( RES_POOLCOLL_TEXT ));
817 if( pTxtNd )
819 ((SwPosition&)rPos).nNode = pTblNd->GetIndex()-1;
820 ((SwPosition&)rPos).nContent.Assign( pTxtNd, 0 );
822 // only add page breaks/styles to the body area
823 if( nPrevPos > GetNodes().GetEndOfExtras().GetIndex() )
825 SwFrmFmt* pFrmFmt = pTblNd->GetTable().GetFrmFmt();
826 const SfxPoolItem *pItem;
827 if( SFX_ITEM_SET == pFrmFmt->GetItemState( RES_PAGEDESC,
828 sal_False, &pItem ) )
830 pTxtNd->SetAttr( *pItem );
831 pFrmFmt->ResetFmtAttr( RES_PAGEDESC );
833 if( SFX_ITEM_SET == pFrmFmt->GetItemState( RES_BREAK,
834 sal_False, &pItem ) )
836 pTxtNd->SetAttr( *pItem );
837 pFrmFmt->ResetFmtAttr( RES_BREAK );
841 if( pUndo )
842 pUndo->SetTblFlag();
843 SetModified();
844 return true;
850 std::vector<sal_uLong> aBkmkArr;
851 _SaveCntntIdx( this, rPos.nNode.GetIndex(), rPos.nContent.GetIndex(),
852 aBkmkArr, SAVEFLY_SPLIT );
853 // FIXME: only SwTxtNode has a valid implementation of SplitCntntNode!
854 OSL_ENSURE(pNode->IsTxtNode(), "splitting non-text node?");
855 pNode = pNode->SplitCntntNode( rPos );
856 if (pNode)
858 // move all bookmarks, TOXMarks, FlyAtCnt
859 if( !aBkmkArr.empty() )
860 _RestoreCntntIdx( this, aBkmkArr, rPos.nNode.GetIndex()-1, 0, true );
862 if( IsRedlineOn() || (!IsIgnoreRedline() && !mpRedlineTbl->empty() ))
864 SwPaM aPam( rPos );
865 aPam.SetMark();
866 aPam.Move( fnMoveBackward );
867 if( IsRedlineOn() )
868 AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
869 else
870 SplitRedline( aPam );
874 SetModified();
875 return true;
878 bool SwDoc::AppendTxtNode( SwPosition& rPos )
880 // create new node before EndOfContent
881 SwTxtNode * pCurNode = rPos.nNode.GetNode().GetTxtNode();
882 if( !pCurNode )
884 // so then one can be created!
885 SwNodeIndex aIdx( rPos.nNode, 1 );
886 pCurNode = GetNodes().MakeTxtNode( aIdx,
887 GetTxtCollFromPool( RES_POOLCOLL_STANDARD ));
889 else
890 pCurNode = (SwTxtNode*)pCurNode->AppendNode( rPos );
892 rPos.nNode++;
893 rPos.nContent.Assign( pCurNode, 0 );
895 if (GetIDocumentUndoRedo().DoesUndo())
897 GetIDocumentUndoRedo().AppendUndo( new SwUndoInsert( rPos.nNode ) );
900 if( IsRedlineOn() || (!IsIgnoreRedline() && !mpRedlineTbl->empty() ))
902 SwPaM aPam( rPos );
903 aPam.SetMark();
904 aPam.Move( fnMoveBackward );
905 if( IsRedlineOn() )
906 AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
907 else
908 SplitRedline( aPam );
911 SetModified();
912 return sal_True;
915 bool SwDoc::InsertString( const SwPaM &rRg, const String &rStr,
916 const enum InsertFlags nInsertMode )
918 // fetching DoesUndo is surprisingly expensive
919 bool bDoesUndo = GetIDocumentUndoRedo().DoesUndo();
920 if (bDoesUndo)
921 GetIDocumentUndoRedo().ClearRedo(); // AppendUndo not always called!
923 const SwPosition& rPos = *rRg.GetPoint();
925 if( mpACEWord ) // add to auto correction
927 if( 1 == rStr.Len() && mpACEWord->IsDeleted() )
929 mpACEWord->CheckChar( rPos, rStr.GetChar( 0 ) );
931 delete mpACEWord, mpACEWord = 0;
934 SwTxtNode *const pNode = rPos.nNode.GetNode().GetTxtNode();
935 if(!pNode)
936 return false;
938 SwDataChanged aTmp( rRg );
940 if (!bDoesUndo || !GetIDocumentUndoRedo().DoesGroupUndo())
942 OUString const ins(pNode->InsertText(rStr, rPos.nContent, nInsertMode));
943 if (bDoesUndo)
945 SwUndoInsert * const pUndo( new SwUndoInsert(rPos.nNode,
946 rPos.nContent.GetIndex(), ins.getLength(), nInsertMode));
947 GetIDocumentUndoRedo().AppendUndo(pUndo);
950 else
951 { // if Undo and grouping is enabled, everything changes!
952 SwUndoInsert * pUndo = NULL;
954 // don't group the start if hints at the start should be expanded
955 if (!(nInsertMode & IDocumentContentOperations::INS_FORCEHINTEXPAND))
957 SwUndo *const pLastUndo = GetUndoManager().GetLastUndo();
958 SwUndoInsert *const pUndoInsert(
959 dynamic_cast<SwUndoInsert *>(pLastUndo) );
960 if (pUndoInsert && pUndoInsert->CanGrouping(rPos))
962 pUndo = pUndoInsert;
966 CharClass const& rCC = GetAppCharClass();
967 xub_StrLen nInsPos = rPos.nContent.GetIndex();
969 if (!pUndo)
971 pUndo = new SwUndoInsert( rPos.nNode, nInsPos, 0, nInsertMode,
972 !rCC.isLetterNumeric( rStr, 0 ) );
973 GetIDocumentUndoRedo().AppendUndo( pUndo );
976 OUString const ins(pNode->InsertText(rStr, rPos.nContent, nInsertMode));
978 for (sal_Int32 i = 0; i < ins.getLength(); ++i)
980 nInsPos++;
981 // if CanGrouping() returns true, everything has already been done
982 if (!pUndo->CanGrouping(ins[i]))
984 pUndo = new SwUndoInsert(rPos.nNode, nInsPos, 1, nInsertMode,
985 !rCC.isLetterNumeric(ins, i));
986 GetIDocumentUndoRedo().AppendUndo( pUndo );
991 if( IsRedlineOn() || (!IsIgnoreRedline() && !mpRedlineTbl->empty() ))
993 SwPaM aPam( rPos.nNode, aTmp.GetCntnt(),
994 rPos.nNode, rPos.nContent.GetIndex());
995 if( IsRedlineOn() )
997 AppendRedline(
998 new SwRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
1000 else
1002 SplitRedline( aPam );
1006 SetModified();
1007 return true;
1010 SwFlyFrmFmt* SwDoc::_InsNoTxtNode( const SwPosition& rPos, SwNoTxtNode* pNode,
1011 const SfxItemSet* pFlyAttrSet,
1012 const SfxItemSet* pGrfAttrSet,
1013 SwFrmFmt* pFrmFmt)
1015 SwFlyFrmFmt *pFmt = 0;
1016 if( pNode )
1018 pFmt = _MakeFlySection( rPos, *pNode, FLY_AT_PARA,
1019 pFlyAttrSet, pFrmFmt );
1020 if( pGrfAttrSet )
1021 pNode->SetAttr( *pGrfAttrSet );
1023 return pFmt;
1026 SwFlyFrmFmt* SwDoc::Insert( const SwPaM &rRg,
1027 const String& rGrfName,
1028 const String& rFltName,
1029 const Graphic* pGraphic,
1030 const SfxItemSet* pFlyAttrSet,
1031 const SfxItemSet* pGrfAttrSet,
1032 SwFrmFmt* pFrmFmt )
1034 if( !pFrmFmt )
1035 pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_GRAPHIC );
1036 SwGrfNode* pSwGrfNode = GetNodes().MakeGrfNode(
1037 SwNodeIndex( GetNodes().GetEndOfAutotext() ),
1038 rGrfName, rFltName, pGraphic,
1039 mpDfltGrfFmtColl );
1040 SwFlyFrmFmt* pSwFlyFrmFmt = _InsNoTxtNode( *rRg.GetPoint(), pSwGrfNode,
1041 pFlyAttrSet, pGrfAttrSet, pFrmFmt );
1042 pSwGrfNode->onGraphicChanged();
1043 return pSwFlyFrmFmt;
1046 SwFlyFrmFmt* SwDoc::Insert( const SwPaM &rRg, const GraphicObject& rGrfObj,
1047 const SfxItemSet* pFlyAttrSet,
1048 const SfxItemSet* pGrfAttrSet,
1049 SwFrmFmt* pFrmFmt )
1051 if( !pFrmFmt )
1052 pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_GRAPHIC );
1053 SwGrfNode* pSwGrfNode = GetNodes().MakeGrfNode(
1054 SwNodeIndex( GetNodes().GetEndOfAutotext() ),
1055 rGrfObj, mpDfltGrfFmtColl );
1056 SwFlyFrmFmt* pSwFlyFrmFmt = _InsNoTxtNode( *rRg.GetPoint(), pSwGrfNode,
1057 pFlyAttrSet, pGrfAttrSet, pFrmFmt );
1058 pSwGrfNode->onGraphicChanged();
1059 return pSwFlyFrmFmt;
1062 SwFlyFrmFmt* SwDoc::Insert(const SwPaM &rRg, const svt::EmbeddedObjectRef& xObj,
1063 const SfxItemSet* pFlyAttrSet,
1064 const SfxItemSet* pGrfAttrSet,
1065 SwFrmFmt* pFrmFmt )
1067 if( !pFrmFmt )
1069 sal_uInt16 nId = RES_POOLFRM_OLE;
1070 SvGlobalName aClassName( xObj->getClassID() );
1071 if (SotExchange::IsMath(aClassName))
1072 nId = RES_POOLFRM_FORMEL;
1074 pFrmFmt = GetFrmFmtFromPool( nId );
1076 return _InsNoTxtNode( *rRg.GetPoint(), GetNodes().MakeOLENode(
1077 SwNodeIndex( GetNodes().GetEndOfAutotext() ),
1078 xObj,
1079 mpDfltGrfFmtColl ),
1080 pFlyAttrSet, pGrfAttrSet,
1081 pFrmFmt );
1084 SwFlyFrmFmt* SwDoc::InsertOLE(const SwPaM &rRg, const String& rObjName,
1085 sal_Int64 nAspect,
1086 const SfxItemSet* pFlyAttrSet,
1087 const SfxItemSet* pGrfAttrSet,
1088 SwFrmFmt* pFrmFmt )
1090 if( !pFrmFmt )
1091 pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_OLE );
1093 return _InsNoTxtNode( *rRg.GetPoint(),
1094 GetNodes().MakeOLENode(
1095 SwNodeIndex( GetNodes().GetEndOfAutotext() ),
1096 rObjName,
1097 nAspect,
1098 mpDfltGrfFmtColl,
1099 0 ),
1100 pFlyAttrSet, pGrfAttrSet,
1101 pFrmFmt );
1104 /// @returns the field type of the Doc
1105 SwFieldType *SwDoc::GetSysFldType( const sal_uInt16 eWhich ) const
1107 for( sal_uInt16 i = 0; i < INIT_FLDTYPES; ++i )
1108 if( eWhich == (*mpFldTypes)[i]->Which() )
1109 return (*mpFldTypes)[i];
1110 return 0;
1113 void SwDoc::SetDocStat( const SwDocStat& rStat )
1115 *mpDocStat = rStat;
1118 const SwDocStat& SwDoc::GetDocStat() const
1120 return *mpDocStat;
1123 const SwDocStat& SwDoc::GetUpdatedDocStat( bool bCompleteAsync, bool bFields )
1125 if( mpDocStat->bModified )
1127 UpdateDocStat( bCompleteAsync, bFields );
1129 return *mpDocStat;
1132 struct _PostItFld : public _SetGetExpFld
1134 _PostItFld( const SwNodeIndex& rNdIdx, const SwTxtFld* pFld, const SwIndex* pIdx = 0 )
1135 : _SetGetExpFld( rNdIdx, pFld, pIdx ) {}
1137 sal_uInt16 GetPageNo( const StringRangeEnumerator &rRangeEnum,
1138 const std::set< sal_Int32 > &rPossiblePages,
1139 sal_uInt16& rVirtPgNo, sal_uInt16& rLineNo );
1141 SwPostItField* GetPostIt() const
1143 return (SwPostItField*) GetFld()->GetFld().GetFld();
1147 sal_uInt16 _PostItFld::GetPageNo(
1148 const StringRangeEnumerator &rRangeEnum,
1149 const std::set< sal_Int32 > &rPossiblePages,
1150 /* out */ sal_uInt16& rVirtPgNo, /* out */ sal_uInt16& rLineNo )
1152 //Problem: If a PostItFld is contained in a Node that is represented
1153 //by more than one layout instance,
1154 //we have to decide whether it should be printed once or n-times.
1155 //Probably only once. For the page number we don't select a random one,
1156 //but the PostIt's first occurrence in the selected area.
1157 rVirtPgNo = 0;
1158 sal_uInt16 nPos = GetCntnt();
1159 SwIterator<SwTxtFrm,SwTxtNode> aIter( GetFld()->GetTxtNode() );
1160 for( SwTxtFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
1162 if( pFrm->GetOfst() > nPos ||
1163 (pFrm->HasFollow() && pFrm->GetFollow()->GetOfst() <= nPos) )
1164 continue;
1165 sal_uInt16 nPgNo = pFrm->GetPhyPageNum();
1166 if( rRangeEnum.hasValue( nPgNo, &rPossiblePages ))
1168 rLineNo = (sal_uInt16)(pFrm->GetLineCount( nPos ) +
1169 pFrm->GetAllLines() - pFrm->GetThisLines());
1170 rVirtPgNo = pFrm->GetVirtPageNum();
1171 return nPgNo;
1174 return 0;
1177 bool sw_GetPostIts(
1178 IDocumentFieldsAccess* pIDFA,
1179 _SetGetExpFlds * pSrtLst )
1181 bool bHasPostIts = false;
1183 SwFieldType* pFldType = pIDFA->GetSysFldType( RES_POSTITFLD );
1184 OSL_ENSURE( pFldType, "no PostItType ? ");
1186 if( pFldType->GetDepends() )
1188 // Found modify object; insert all fields into the array
1189 SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
1190 const SwTxtFld* pTxtFld;
1191 for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
1193 if( 0 != ( pTxtFld = pFld->GetTxtFld() ) &&
1194 pTxtFld->GetTxtNode().GetNodes().IsDocNodes() )
1196 bHasPostIts = true;
1197 if (pSrtLst)
1199 SwNodeIndex aIdx( pTxtFld->GetTxtNode() );
1200 _PostItFld* pNew = new _PostItFld( aIdx, pTxtFld );
1201 pSrtLst->insert( pNew );
1203 else
1204 break; // we just wanted to check for the existence of postits ...
1209 return bHasPostIts;
1212 static void lcl_FormatPostIt(
1213 IDocumentContentOperations* pIDCO,
1214 SwPaM& aPam,
1215 SwPostItField* pField,
1216 bool bNewPage, bool bIsFirstPostIt,
1217 sal_uInt16 nPageNo, sal_uInt16 nLineNo )
1219 static char const sTmp[] = " : ";
1221 OSL_ENSURE( ViewShell::GetShellRes(), "missing ShellRes" );
1223 if (bNewPage)
1225 pIDCO->InsertPoolItem( aPam, SvxFmtBreakItem( SVX_BREAK_PAGE_AFTER, RES_BREAK ), 0 );
1226 pIDCO->SplitNode( *aPam.GetPoint(), false );
1228 else if (!bIsFirstPostIt)
1230 // add an empty line between different notes
1231 pIDCO->SplitNode( *aPam.GetPoint(), false );
1232 pIDCO->SplitNode( *aPam.GetPoint(), false );
1235 String aStr( ViewShell::GetShellRes()->aPostItPage );
1236 aStr.AppendAscii(sTmp);
1238 aStr += OUString::number( nPageNo );
1239 aStr += ' ';
1240 if( nLineNo )
1242 aStr += ViewShell::GetShellRes()->aPostItLine;
1243 aStr.AppendAscii(sTmp);
1244 aStr += OUString::number( nLineNo );
1245 aStr += ' ';
1247 aStr += ViewShell::GetShellRes()->aPostItAuthor;
1248 aStr.AppendAscii(sTmp);
1249 aStr += pField->GetPar1();
1250 aStr += ' ';
1251 SvtSysLocale aSysLocale;
1252 aStr += /*(LocaleDataWrapper&)*/aSysLocale.GetLocaleData().getDate( pField->GetDate() );
1253 pIDCO->InsertString( aPam, aStr );
1255 pIDCO->SplitNode( *aPam.GetPoint(), false );
1256 aStr = pField->GetPar2();
1257 #if defined( WNT )
1258 // Throw out all CR in Windows
1259 aStr = comphelper::string::remove(aStr, '\r');
1260 #endif
1261 pIDCO->InsertString( aPam, aStr );
1264 /// provide the paper tray to use according to the page style in use,
1265 /// but do that only if the respective item is NOT just the default item
1266 static sal_Int32 lcl_GetPaperBin( const SwPageFrm *pStartFrm )
1268 sal_Int32 nRes = -1;
1270 const SwFrmFmt &rFmt = pStartFrm->GetPageDesc()->GetMaster();
1271 const SfxPoolItem *pItem = NULL;
1272 SfxItemState eState = rFmt.GetItemState( RES_PAPER_BIN, sal_False, &pItem );
1273 const SvxPaperBinItem *pPaperBinItem = dynamic_cast< const SvxPaperBinItem * >(pItem);
1274 if (eState > SFX_ITEM_DEFAULT && pPaperBinItem)
1275 nRes = pPaperBinItem->GetValue();
1277 return nRes;
1280 void SwDoc::CalculatePagesForPrinting(
1281 const SwRootFrm& rLayout,
1282 /* out */ SwRenderData &rData,
1283 const SwPrintUIOptions &rOptions,
1284 bool bIsPDFExport,
1285 sal_Int32 nDocPageCount )
1287 const sal_Int32 nContent = rOptions.getIntValue( "PrintContent", 0 );
1288 const bool bPrintSelection = nContent == 2;
1290 // properties to take into account when calcualting the set of pages
1291 // (PDF export UI does not allow for selecting left or right pages only)
1292 bool bPrintLeftPages = bIsPDFExport ? true : rOptions.IsPrintLeftPages();
1293 bool bPrintRightPages = bIsPDFExport ? true : rOptions.IsPrintRightPages();
1294 // #i103700# printing selections should not allow for automatic inserting empty pages
1295 bool bPrintEmptyPages = bPrintSelection ? false : rOptions.IsPrintEmptyPages( bIsPDFExport );
1297 std::map< sal_Int32, sal_Int32 > &rPrinterPaperTrays = rData.GetPrinterPaperTrays();
1298 std::set< sal_Int32 > &rValidPages = rData.GetValidPagesSet();
1299 rValidPages.clear();
1301 sal_Int32 nPageNum = 1;
1302 const SwPageFrm *pStPage = dynamic_cast<const SwPageFrm*>( rLayout.Lower() );
1303 while (pStPage && nPageNum <= nDocPageCount)
1305 const bool bPrintThisPage =
1306 ( (bPrintRightPages && pStPage->OnRightPage()) ||
1307 (bPrintLeftPages && !pStPage->OnRightPage()) ) &&
1308 ( bPrintEmptyPages || pStPage->Frm().Height() );
1310 if (bPrintThisPage)
1312 rValidPages.insert( nPageNum );
1313 rPrinterPaperTrays[ nPageNum ] = lcl_GetPaperBin( pStPage );
1316 ++nPageNum;
1317 pStPage = (SwPageFrm*)pStPage->GetNext();
1320 // now that we have identified the valid pages for printing according
1321 // to the print settings we need to get the PageRange to use and
1322 // use both results to get the actual pages to be printed
1323 // (post-it settings need to be taken into account later on!)
1325 // get PageRange value to use
1326 OUString aPageRange;
1327 // #i116085# - adjusting fix for i113919
1328 if ( !bIsPDFExport )
1330 // PageContent :
1331 // 0 -> print all pages (default if aPageRange is empty)
1332 // 1 -> print range according to PageRange
1333 // 2 -> print selection
1334 if (1 == nContent)
1335 aPageRange = rOptions.getStringValue( "PageRange", OUString() );
1336 if (2 == nContent)
1338 // note that printing selections is actually implemented by copying
1339 // the selection to a new temporary document and printing all of that one.
1340 // Thus for Writer "PrintContent" must never be 2.
1341 // See SwXTextDocument::GetRenderDoc for evaluating if a selection is to be
1342 // printed and for creating the temporary document.
1345 // please note
1347 if (aPageRange.isEmpty()) // empty string -> print all
1349 // set page range to print to 'all pages'
1350 aPageRange = OUString::valueOf( (sal_Int32)1 );
1351 aPageRange += OUString::valueOf( (sal_Unicode)'-');
1352 aPageRange += OUString::valueOf( nDocPageCount );
1354 rData.SetPageRange( aPageRange );
1356 // get vector of pages to print according to PageRange and valid pages set from above
1357 // (result may be an empty vector, for example if the range string is not correct)
1358 StringRangeEnumerator::getRangesFromString(
1359 aPageRange, rData.GetPagesToPrint(),
1360 1, nDocPageCount, 0, &rData.GetValidPagesSet() );
1363 void SwDoc::UpdatePagesForPrintingWithPostItData(
1364 /* out */ SwRenderData &rData,
1365 const SwPrintUIOptions &rOptions,
1366 bool /*bIsPDFExport*/,
1367 sal_Int32 nDocPageCount )
1370 sal_Int16 nPostItMode = (sal_Int16) rOptions.getIntValue( "PrintAnnotationMode", 0 );
1371 OSL_ENSURE(nPostItMode == POSTITS_NONE || rData.HasPostItData(),
1372 "print post-its without post-it data?" );
1373 const sal_uInt16 nPostItCount = rData.HasPostItData() ? rData.m_pPostItFields->size() : 0;
1374 if (nPostItMode != POSTITS_NONE && nPostItCount > 0)
1376 SET_CURR_SHELL( rData.m_pPostItShell.get() );
1378 // clear document and move to end of it
1379 SwDoc & rPostItDoc(*rData.m_pPostItShell->GetDoc());
1380 SwPaM aPam(rPostItDoc.GetNodes().GetEndOfContent());
1381 aPam.Move( fnMoveBackward, fnGoDoc );
1382 aPam.SetMark();
1383 aPam.Move( fnMoveForward, fnGoDoc );
1384 rPostItDoc.DeleteRange( aPam );
1386 const StringRangeEnumerator aRangeEnum( rData.GetPageRange(), 1, nDocPageCount, 0 );
1388 // For mode POSTITS_ENDPAGE:
1389 // maps a physical page number to the page number in post-it document that holds
1390 // the first post-it for that physical page . Needed to relate the correct start frames
1391 // from the post-it doc to the physical page of the document
1392 std::map< sal_Int32, sal_Int32 > aPostItLastStartPageNum;
1394 // add all post-its on valid pages within the page range to the
1395 // temporary post-it document.
1396 // Since the array of post-it fileds is sorted by page and line number we will
1397 // already get them in the correct order
1398 sal_uInt16 nVirtPg = 0, nLineNo = 0, nLastPageNum = 0, nPhyPageNum = 0;
1399 bool bIsFirstPostIt = true;
1400 for (sal_uInt16 i = 0; i < nPostItCount; ++i)
1402 _PostItFld& rPostIt = (_PostItFld&)*(*rData.m_pPostItFields)[ i ];
1403 nLastPageNum = nPhyPageNum;
1404 nPhyPageNum = rPostIt.GetPageNo(
1405 aRangeEnum, rData.GetValidPagesSet(), nVirtPg, nLineNo );
1406 if (nPhyPageNum)
1408 // need to insert a page break?
1409 // In POSTITS_ENDPAGE mode for each document page the following
1410 // post-it page needs to start on a new page
1411 const bool bNewPage = nPostItMode == POSTITS_ENDPAGE &&
1412 !bIsFirstPostIt && nPhyPageNum != nLastPageNum;
1414 lcl_FormatPostIt( rData.m_pPostItShell->GetDoc(), aPam,
1415 rPostIt.GetPostIt(), bNewPage, bIsFirstPostIt, nVirtPg, nLineNo );
1416 bIsFirstPostIt = false;
1418 if (nPostItMode == POSTITS_ENDPAGE)
1420 // get the correct number of current pages for the post-it document
1421 rData.m_pPostItShell->CalcLayout();
1422 const sal_Int32 nPages = rData.m_pPostItShell->GetPageCount();
1423 aPostItLastStartPageNum[ nPhyPageNum ] = nPages;
1428 // format post-it doc to get correct number of pages
1429 rData.m_pPostItShell->CalcLayout();
1430 const sal_Int32 nPostItDocPageCount = rData.m_pPostItShell->GetPageCount();
1432 if (nPostItMode == POSTITS_ONLY || nPostItMode == POSTITS_ENDDOC)
1434 // now add those post-it pages to the vector of pages to print
1435 // or replace them if only post-its should be printed
1437 if (nPostItMode == POSTITS_ONLY)
1439 // no document page to be printed
1440 rData.GetPagesToPrint().clear();
1443 // now we just need to add the post-it pages to be printed to the
1444 // end of the vector of pages to print
1445 sal_Int32 nPageNum = 0;
1446 const SwPageFrm * pPageFrm = (SwPageFrm*)rData.m_pPostItShell->GetLayout()->Lower();
1447 while( pPageFrm && nPageNum < nPostItDocPageCount )
1449 OSL_ENSURE( pPageFrm, "Empty page frame. How are we going to print this?" );
1450 ++nPageNum;
1451 // negative page number indicates page is from the post-it doc
1452 rData.GetPagesToPrint().push_back( -nPageNum );
1453 OSL_ENSURE( pPageFrm, "pPageFrm is NULL!" );
1454 pPageFrm = (SwPageFrm*)pPageFrm->GetNext();
1456 OSL_ENSURE( nPageNum == nPostItDocPageCount, "unexpected number of pages" );
1458 else if (nPostItMode == POSTITS_ENDPAGE)
1460 // the next step is to find all the pages from the post-it
1461 // document that should be printed for a given physical page
1462 // of the document
1464 std::vector< sal_Int32 > aTmpPagesToPrint;
1465 sal_Int32 nLastPostItPage(0);
1466 const size_t nNum = rData.GetPagesToPrint().size();
1467 for (size_t i = 0 ; i < nNum; ++i)
1469 // add the physical page to print from the document
1470 const sal_Int32 nPhysPage = rData.GetPagesToPrint()[i];
1471 aTmpPagesToPrint.push_back( nPhysPage );
1473 // add the post-it document pages to print, i.e those
1474 // post-it pages that have the data for the above physical page
1475 ::std::map<sal_Int32, sal_Int32>::const_iterator const iter(
1476 aPostItLastStartPageNum.find(nPhysPage));
1477 if (iter != aPostItLastStartPageNum.end())
1479 for (sal_Int32 j = nLastPostItPage + 1;
1480 j <= iter->second; ++j)
1482 // negative page number indicates page is from the
1483 aTmpPagesToPrint.push_back(-j); // post-it document
1485 nLastPostItPage = iter->second;
1489 // finally we need to assign those vectors to the resulting ones.
1490 // swapping the data should be more efficient than assigning since
1491 // we won't need the temporary vectors anymore
1492 rData.GetPagesToPrint().swap( aTmpPagesToPrint );
1497 void SwDoc::CalculatePagePairsForProspectPrinting(
1498 const SwRootFrm& rLayout,
1499 /* out */ SwRenderData &rData,
1500 const SwPrintUIOptions &rOptions,
1501 sal_Int32 nDocPageCount )
1503 std::map< sal_Int32, sal_Int32 > &rPrinterPaperTrays = rData.GetPrinterPaperTrays();
1504 std::set< sal_Int32 > &rValidPagesSet = rData.GetValidPagesSet();
1505 std::vector< std::pair< sal_Int32, sal_Int32 > > &rPagePairs = rData.GetPagePairsForProspectPrinting();
1506 std::map< sal_Int32, const SwPageFrm * > validStartFrms;
1508 rPagePairs.clear();
1509 rValidPagesSet.clear();
1511 OUString aPageRange;
1512 // PageContent :
1513 // 0 -> print all pages (default if aPageRange is empty)
1514 // 1 -> print range according to PageRange
1515 // 2 -> print selection
1516 const sal_Int32 nContent = rOptions.getIntValue( "PrintContent", 0 );
1517 if (nContent == 1)
1518 aPageRange = rOptions.getStringValue( "PageRange", OUString() );
1519 if (aPageRange.isEmpty()) // empty string -> print all
1521 // set page range to print to 'all pages'
1522 aPageRange = OUString::valueOf( (sal_Int32)1 );
1523 aPageRange += OUString::valueOf( (sal_Unicode)'-');
1524 aPageRange += OUString::valueOf( nDocPageCount );
1526 StringRangeEnumerator aRange( aPageRange, 1, nDocPageCount, 0 );
1528 if ( aRange.size() <= 0)
1529 return;
1531 const SwPageFrm *pStPage = dynamic_cast<const SwPageFrm*>( rLayout.Lower() );
1532 sal_Int32 i = 0;
1533 for ( i = 1; pStPage && i < nDocPageCount; ++i )
1534 pStPage = (SwPageFrm*)pStPage->GetNext();
1535 if ( !pStPage ) // Then it was that
1536 return;
1538 // currently for prospect printing all pages are valid to be printed
1539 // thus we add them all to the respective map and set for later use
1540 sal_Int32 nPageNum = 0;
1541 const SwPageFrm *pPageFrm = dynamic_cast<const SwPageFrm*>( rLayout.Lower() );
1542 while( pPageFrm && nPageNum < nDocPageCount )
1544 OSL_ENSURE( pPageFrm, "Empty page frame. How are we going to print this?" );
1545 ++nPageNum;
1546 rValidPagesSet.insert( nPageNum );
1547 validStartFrms[ nPageNum ] = pPageFrm;
1548 pPageFrm = (SwPageFrm*)pPageFrm->GetNext();
1550 rPrinterPaperTrays[ nPageNum ] = lcl_GetPaperBin( pStPage );
1552 OSL_ENSURE( nPageNum == nDocPageCount, "unexpected number of pages" );
1554 // properties to take into account when calcualting the set of pages
1555 // Note: here bPrintLeftPages and bPrintRightPages refer to the (virtual) resulting pages
1556 // of the prospect!
1557 bool bPrintLeftPages = rOptions.IsPrintLeftPages();
1558 bool bPrintRightPages = rOptions.IsPrintRightPages();
1559 bool bPrintProspectRTL = rOptions.getIntValue( "PrintProspectRTL", 0 ) ? true : false;
1561 // get pages for prospect printing according to the 'PageRange'
1562 // (duplicates and any order allowed!)
1563 std::vector< sal_Int32 > aPagesToPrint;
1564 StringRangeEnumerator::getRangesFromString(
1565 aPageRange, aPagesToPrint, 1, nDocPageCount, 0 );
1567 if (aPagesToPrint.empty())
1568 return;
1570 // now fill the vector for calculating the page pairs with the start frames
1571 // from the above obtained vector
1572 std::vector< const SwPageFrm * > aVec;
1573 for ( i = 0; i < sal_Int32(aPagesToPrint.size()); ++i)
1575 const sal_Int32 nPage = aPagesToPrint[i];
1576 const SwPageFrm *pFrm = validStartFrms[ nPage ];
1577 aVec.push_back( pFrm );
1580 // just one page is special ...
1581 if ( 1 == aVec.size() )
1582 aVec.insert( aVec.begin() + 1, (SwPageFrm *)0 ); // insert a second empty page
1583 else
1585 // now extend the number of pages to fit a multiple of 4
1586 // (4 'normal' pages are needed for a single prospect paper
1587 // with back and front)
1588 while( aVec.size() & 3 )
1589 aVec.push_back( 0 );
1592 // make sure that all pages are in correct order
1593 sal_uInt16 nSPg = 0, nEPg = aVec.size(), nStep = 1;
1594 if ( 0 == (nEPg & 1 )) // there are no uneven ones!
1595 --nEPg;
1597 if ( !bPrintLeftPages )
1598 ++nStep;
1599 else if ( !bPrintRightPages )
1601 ++nStep;
1602 ++nSPg, --nEPg;
1605 // the number of 'virtual' pages to be printed
1606 sal_Int32 nCntPage = (( nEPg - nSPg ) / ( 2 * nStep )) + 1;
1608 for ( sal_uInt16 nPrintCount = 0; nSPg < nEPg &&
1609 nPrintCount < nCntPage; ++nPrintCount )
1611 pStPage = aVec[ nSPg ];
1612 const SwPageFrm* pNxtPage = nEPg < aVec.size() ? aVec[ nEPg ] : 0;
1614 short nRtlOfs = bPrintProspectRTL ? 1 : 0;
1615 if ( 0 == (( nSPg + nRtlOfs) & 1 ) ) // switch for odd number in LTR, even number in RTL
1617 const SwPageFrm* pTmp = pStPage;
1618 pStPage = pNxtPage;
1619 pNxtPage = pTmp;
1622 sal_Int32 nFirst = -1, nSecond = -1;
1623 for ( int nC = 0; nC < 2; ++nC )
1625 sal_Int32 nPage = -1;
1626 if ( pStPage )
1627 nPage = pStPage->GetPhyPageNum();
1628 if (nC == 0)
1629 nFirst = nPage;
1630 else
1631 nSecond = nPage;
1633 pStPage = pNxtPage;
1635 rPagePairs.push_back( std::pair< sal_Int32, sal_Int32 >(nFirst, nSecond) );
1637 nSPg = nSPg + nStep;
1638 nEPg = nEPg - nStep;
1640 OSL_ENSURE( size_t(nCntPage) == rPagePairs.size(), "size mismatch for number of page pairs" );
1642 // luckily prospect printing does not make use of post-its so far,
1643 // thus we are done here.
1646 // returns true while there is more to do
1647 bool SwDoc::IncrementalDocStatCalculate(long nChars, bool bFields)
1649 mpDocStat->Reset();
1650 mpDocStat->nPara = 0; // default is 1!
1651 SwNode* pNd;
1653 // This is the inner loop - at least while the paras are dirty.
1654 for( sal_uLong i = GetNodes().Count(); i > 0 && nChars > 0; )
1656 switch( ( pNd = GetNodes()[ --i ])->GetNodeType() )
1658 case ND_TEXTNODE:
1660 long const nOldChars(mpDocStat->nChar);
1661 SwTxtNode *pTxt = static_cast< SwTxtNode * >( pNd );
1662 if (pTxt->CountWords(*mpDocStat, 0, pTxt->GetTxt().getLength()))
1664 nChars -= (mpDocStat->nChar - nOldChars);
1666 break;
1668 case ND_TABLENODE: ++mpDocStat->nTbl; break;
1669 case ND_GRFNODE: ++mpDocStat->nGrf; break;
1670 case ND_OLENODE: ++mpDocStat->nOLE; break;
1671 case ND_SECTIONNODE: break;
1675 // #i93174#: notes contain paragraphs that are not nodes
1677 SwFieldType * const pPostits( GetSysFldType(RES_POSTITFLD) );
1678 SwIterator<SwFmtFld,SwFieldType> aIter( *pPostits );
1679 for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
1681 if (pFmtFld->IsFldInDoc())
1683 SwPostItField const * const pField(
1684 static_cast<SwPostItField const*>(pFmtFld->GetFld()));
1685 mpDocStat->nAllPara += pField->GetNumberOfParagraphs();
1690 mpDocStat->nPage = GetCurrentLayout() ? GetCurrentLayout()->GetPageNum() : 0;
1691 mpDocStat->bModified = sal_False;
1693 com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aStat( mpDocStat->nPage ? 8 : 7);
1694 sal_Int32 n=0;
1695 aStat[n].Name = OUString("TableCount");
1696 aStat[n++].Value <<= (sal_Int32)mpDocStat->nTbl;
1697 aStat[n].Name = OUString("ImageCount");
1698 aStat[n++].Value <<= (sal_Int32)mpDocStat->nGrf;
1699 aStat[n].Name = OUString("ObjectCount");
1700 aStat[n++].Value <<= (sal_Int32)mpDocStat->nOLE;
1701 if ( mpDocStat->nPage )
1703 aStat[n].Name = OUString("PageCount");
1704 aStat[n++].Value <<= (sal_Int32)mpDocStat->nPage;
1706 aStat[n].Name = OUString("ParagraphCount");
1707 aStat[n++].Value <<= (sal_Int32)mpDocStat->nPara;
1708 aStat[n].Name = OUString("WordCount");
1709 aStat[n++].Value <<= (sal_Int32)mpDocStat->nWord;
1710 aStat[n].Name = OUString("CharacterCount");
1711 aStat[n++].Value <<= (sal_Int32)mpDocStat->nChar;
1712 aStat[n].Name = OUString("NonWhitespaceCharacterCount");
1713 aStat[n++].Value <<= (sal_Int32)mpDocStat->nCharExcludingSpaces;
1715 // For e.g. autotext documents there is no pSwgInfo (#i79945)
1716 SfxObjectShell * const pObjShell( GetDocShell() );
1717 if (pObjShell)
1719 const uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1720 pObjShell->GetModel(), uno::UNO_QUERY_THROW);
1721 const uno::Reference<document::XDocumentProperties> xDocProps(
1722 xDPS->getDocumentProperties());
1723 // #i96786#: do not set modified flag when updating statistics
1724 const bool bDocWasModified( IsModified() );
1725 const ModifyBlocker_Impl b(pObjShell);
1726 xDocProps->setDocumentStatistics(aStat);
1727 if (!bDocWasModified)
1729 ResetModified();
1733 // optionally update stat. fields
1734 if (bFields)
1736 SwFieldType *pType = GetSysFldType(RES_DOCSTATFLD);
1737 pType->UpdateFlds();
1740 return nChars <= 0;
1743 IMPL_LINK( SwDoc, DoIdleStatsUpdate, Timer *, pTimer )
1745 (void)pTimer;
1746 if (IncrementalDocStatCalculate(32000))
1747 maStatsUpdateTimer.Start();
1749 SwView* pView = GetDocShell() ? GetDocShell()->GetView() : NULL;
1750 if( pView )
1751 pView->UpdateDocStats();
1752 return 0;
1755 void SwDoc::UpdateDocStat( bool bCompleteAsync, bool bFields )
1757 if( mpDocStat->bModified )
1759 if (!bCompleteAsync)
1761 while (IncrementalDocStatCalculate(
1762 ::std::numeric_limits<long>::max(), bFields)) {}
1763 maStatsUpdateTimer.Stop();
1765 else if (IncrementalDocStatCalculate(5000, bFields))
1766 maStatsUpdateTimer.Start();
1770 void SwDoc::DocInfoChgd( )
1772 GetSysFldType( RES_DOCINFOFLD )->UpdateFlds();
1773 GetSysFldType( RES_TEMPLNAMEFLD )->UpdateFlds();
1774 SetModified();
1777 /// @return the reference in the doc for the name
1778 const SwFmtRefMark* SwDoc::GetRefMark( const String& rName ) const
1780 const SfxPoolItem* pItem;
1781 sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_REFMARK );
1782 for( sal_uInt32 n = 0; n < nMaxItems; ++n )
1784 if( 0 == (pItem = GetAttrPool().GetItem2( RES_TXTATR_REFMARK, n ) ))
1785 continue;
1787 const SwFmtRefMark* pFmtRef = (SwFmtRefMark*)pItem;
1788 const SwTxtRefMark* pTxtRef = pFmtRef->GetTxtRefMark();
1789 if( pTxtRef && &pTxtRef->GetTxtNode().GetNodes() == &GetNodes() &&
1790 rName.Equals( pFmtRef->GetRefName() ) )
1791 return pFmtRef;
1793 return 0;
1796 /// @return the RefMark per index - for Uno
1797 const SwFmtRefMark* SwDoc::GetRefMark( sal_uInt16 nIndex ) const
1799 const SfxPoolItem* pItem;
1800 const SwTxtRefMark* pTxtRef;
1801 const SwFmtRefMark* pRet = 0;
1803 sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_REFMARK );
1804 sal_uInt32 nCount = 0;
1805 for( sal_uInt32 n = 0; n < nMaxItems; ++n )
1806 if( 0 != (pItem = GetAttrPool().GetItem2( RES_TXTATR_REFMARK, n )) &&
1807 0 != (pTxtRef = ((SwFmtRefMark*)pItem)->GetTxtRefMark()) &&
1808 &pTxtRef->GetTxtNode().GetNodes() == &GetNodes() )
1810 if(nCount == nIndex)
1812 pRet = (SwFmtRefMark*)pItem;
1813 break;
1815 nCount++;
1817 return pRet;
1820 /// @return the names of all set references in the Doc
1821 //JP 24.06.96: If the array pointer is 0, then just return whether a RefMark is set in the Doc
1822 // OS 25.06.96: From now on we always return the reference count
1823 sal_uInt16 SwDoc::GetRefMarks( std::vector<OUString>* pNames ) const
1825 const SfxPoolItem* pItem;
1826 const SwTxtRefMark* pTxtRef;
1828 sal_uInt32 nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_REFMARK );
1829 sal_uInt32 nCount = 0;
1830 for( sal_uInt32 n = 0; n < nMaxItems; ++n )
1831 if( 0 != (pItem = GetAttrPool().GetItem2( RES_TXTATR_REFMARK, n )) &&
1832 0 != (pTxtRef = ((SwFmtRefMark*)pItem)->GetTxtRefMark()) &&
1833 &pTxtRef->GetTxtNode().GetNodes() == &GetNodes() )
1835 if( pNames )
1837 String pTmp(((SwFmtRefMark*)pItem)->GetRefName());
1838 pNames->insert(pNames->begin() + nCount, pTmp);
1840 nCount ++;
1843 return nCount;
1846 bool SwDoc::IsLoaded() const
1848 return mbLoaded;
1851 bool SwDoc::IsUpdateExpFld() const
1853 return mbUpdateExpFld;
1856 bool SwDoc::IsNewDoc() const
1858 return mbNewDoc;
1861 bool SwDoc::IsPageNums() const
1863 return mbPageNums;
1866 void SwDoc::SetPageNums(bool b)
1868 mbPageNums = b;
1871 void SwDoc::SetNewDoc(bool b)
1873 mbNewDoc = b;
1876 void SwDoc::SetUpdateExpFldStat(bool b)
1878 mbUpdateExpFld = b;
1881 void SwDoc::SetLoaded(bool b)
1883 mbLoaded = b;
1886 bool SwDoc::IsModified() const
1888 return mbModified;
1891 //Load document from fdo#42534 under valgrind, drag the scrollbar down so full
1892 //document layout is triggered. Close document before layout has completed, and
1893 //SwAnchoredObject objects deleted by the deletion of layout remain referenced
1894 //by the SwLayouter
1895 void SwDoc::ClearSwLayouterEntries()
1897 SwLayouter::ClearMovedFwdFrms( *this );
1898 SwLayouter::ClearObjsTmpConsiderWrapInfluence( *this );
1899 // #i65250#
1900 SwLayouter::ClearMoveBwdLayoutInfo( *this );
1903 void SwDoc::SetModified()
1905 ClearSwLayouterEntries();
1906 // give the old and new modified state to the link
1907 // Bit 0: -> old state
1908 // Bit 1: -> new state
1909 long nCall = mbModified ? 3 : 2;
1910 mbModified = sal_True;
1911 mpDocStat->bModified = sal_True;
1912 if( maOle2Link.IsSet() )
1914 mbInCallModified = sal_True;
1915 maOle2Link.Call( (void*)nCall );
1916 mbInCallModified = sal_False;
1919 if( mpACEWord && !mpACEWord->IsDeleted() )
1920 delete mpACEWord, mpACEWord = 0;
1923 void SwDoc::ResetModified()
1925 // give the old and new modified state to the link
1926 // Bit 0: -> old state
1927 // Bit 1: -> new state
1928 long nCall = mbModified ? 1 : 0;
1929 mbModified = sal_False;
1930 GetIDocumentUndoRedo().SetUndoNoModifiedPosition();
1931 if( nCall && maOle2Link.IsSet() )
1933 mbInCallModified = sal_True;
1934 maOle2Link.Call( (void*)nCall );
1935 mbInCallModified = sal_False;
1939 void SwDoc::ReRead( SwPaM& rPam, const String& rGrfName,
1940 const String& rFltName, const Graphic* pGraphic,
1941 const GraphicObject* pGrafObj )
1943 SwGrfNode *pGrfNd;
1944 if( ( !rPam.HasMark()
1945 || rPam.GetPoint()->nNode.GetIndex() == rPam.GetMark()->nNode.GetIndex() )
1946 && 0 != ( pGrfNd = rPam.GetPoint()->nNode.GetNode().GetGrfNode() ) )
1948 if (GetIDocumentUndoRedo().DoesUndo())
1950 GetIDocumentUndoRedo().AppendUndo(new SwUndoReRead(rPam, *pGrfNd));
1953 // Because we don't know if we can mirror the graphic, the mirror attribute is always reset
1954 if( RES_MIRROR_GRAPH_DONT != pGrfNd->GetSwAttrSet().
1955 GetMirrorGrf().GetValue() )
1956 pGrfNd->SetAttr( SwMirrorGrf() );
1958 pGrfNd->ReRead( rGrfName, rFltName, pGraphic, pGrafObj, sal_True );
1959 SetModified();
1963 static bool lcl_SpellAndGrammarAgain( const SwNodePtr& rpNd, void* pArgs )
1965 SwTxtNode *pTxtNode = (SwTxtNode*)rpNd->GetTxtNode();
1966 sal_Bool bOnlyWrong = *(sal_Bool*)pArgs;
1967 if( pTxtNode )
1969 if( bOnlyWrong )
1971 if( pTxtNode->GetWrong() &&
1972 pTxtNode->GetWrong()->InvalidateWrong() )
1973 pTxtNode->SetWrongDirty( true );
1974 if( pTxtNode->GetGrammarCheck() &&
1975 pTxtNode->GetGrammarCheck()->InvalidateWrong() )
1976 pTxtNode->SetGrammarCheckDirty( true );
1978 else
1980 pTxtNode->SetWrongDirty( true );
1981 if( pTxtNode->GetWrong() )
1982 pTxtNode->GetWrong()->SetInvalid( 0, STRING_LEN );
1983 pTxtNode->SetGrammarCheckDirty( true );
1984 if( pTxtNode->GetGrammarCheck() )
1985 pTxtNode->GetGrammarCheck()->SetInvalid( 0, STRING_LEN );
1988 return true;
1991 static bool lcl_CheckSmartTagsAgain( const SwNodePtr& rpNd, void* )
1993 SwTxtNode *pTxtNode = (SwTxtNode*)rpNd->GetTxtNode();
1994 if( pTxtNode )
1996 pTxtNode->SetSmartTagDirty( true );
1997 if( pTxtNode->GetSmartTags() )
1999 pTxtNode->SetSmartTags( NULL );
2002 return true;
2005 /** Re-trigger spelling in the idle handler.
2007 * @param bInvalid if <true>, the WrongLists in all nodes are invalidated
2008 * and the SpellInvalid flag is set on all pages.
2009 * @param bOnlyWrong controls whether only the areas with wrong words are
2010 * checked or the whole area.
2011 * @param bSmartTags ???
2012 ************************************************************************/
2013 void SwDoc::SpellItAgainSam( bool bInvalid, bool bOnlyWrong, bool bSmartTags )
2015 std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();//swmod 080307
2016 OSL_ENSURE( GetCurrentLayout(), "SpellAgain: Where's my RootFrm?" );
2017 if( bInvalid )
2019 std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::AllInvalidateSmartTagsOrSpelling),bSmartTags));//swmod 080305
2020 std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::SetNeedGrammarCheck), true) );
2021 if ( bSmartTags )
2022 GetNodes().ForEach( lcl_CheckSmartTagsAgain, &bOnlyWrong );
2023 GetNodes().ForEach( lcl_SpellAndGrammarAgain, &bOnlyWrong );
2026 std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::SetIdleFlags));//swmod 080307
2029 void SwDoc::InvalidateAutoCompleteFlag()
2031 SwRootFrm* pTmpRoot = GetCurrentLayout();
2032 if( pTmpRoot )
2034 std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
2035 std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllInvalidateAutoCompleteWords));//swmod 080305
2036 for( sal_uLong nNd = 1, nCnt = GetNodes().Count(); nNd < nCnt; ++nNd )
2038 SwTxtNode* pTxtNode = GetNodes()[ nNd ]->GetTxtNode();
2039 if ( pTxtNode ) pTxtNode->SetAutoCompleteWordDirty( true );
2042 std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::SetIdleFlags));//swmod 080228
2043 } //swmod 080219
2046 const SwFmtINetFmt* SwDoc::FindINetAttr( const String& rName ) const
2048 const SwFmtINetFmt* pItem;
2049 const SwTxtINetFmt* pTxtAttr;
2050 const SwTxtNode* pTxtNd;
2051 sal_uInt32 n, nMaxItems = GetAttrPool().GetItemCount2( RES_TXTATR_INETFMT );
2052 for( n = 0; n < nMaxItems; ++n )
2053 if( 0 != (pItem = (SwFmtINetFmt*)GetAttrPool().GetItem2(
2054 RES_TXTATR_INETFMT, n ) ) &&
2055 pItem->GetName().Equals( rName ) &&
2056 0 != ( pTxtAttr = pItem->GetTxtINetFmt()) &&
2057 0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) &&
2058 &pTxtNd->GetNodes() == &GetNodes() )
2060 return pItem;
2063 return 0;
2066 void SwDoc::Summary( SwDoc* pExtDoc, sal_uInt8 nLevel, sal_uInt8 nPara, bool bImpress )
2068 const SwOutlineNodes& rOutNds = GetNodes().GetOutLineNds();
2069 if( pExtDoc && !rOutNds.empty() )
2071 sal_uInt16 i;
2072 ::StartProgress( STR_STATSTR_SUMMARY, 0, rOutNds.size(), GetDocShell() );
2073 SwNodeIndex aEndOfDoc( pExtDoc->GetNodes().GetEndOfContent(), -1 );
2074 for( i = 0; i < rOutNds.size(); ++i )
2076 ::SetProgressState( i, GetDocShell() );
2077 const sal_uLong nIndex = rOutNds[ i ]->GetIndex();
2079 const int nLvl = ((SwTxtNode*)GetNodes()[ nIndex ])->GetAttrOutlineLevel()-1;//<-end,zhaojianwei
2080 if( nLvl > nLevel )
2081 continue;
2082 sal_uInt16 nEndOfs = 1;
2083 sal_uInt8 nWish = nPara;
2084 sal_uLong nNextOutNd = i + 1 < (sal_uInt16)rOutNds.size() ?
2085 rOutNds[ i + 1 ]->GetIndex() : GetNodes().Count();
2086 sal_Bool bKeep = sal_False;
2087 while( ( nWish || bKeep ) && nIndex + nEndOfs < nNextOutNd &&
2088 GetNodes()[ nIndex + nEndOfs ]->IsTxtNode() )
2090 SwTxtNode* pTxtNode = (SwTxtNode*)GetNodes()[ nIndex+nEndOfs ];
2091 if (pTxtNode->GetTxt().getLength() && nWish)
2092 --nWish;
2093 bKeep = pTxtNode->GetSwAttrSet().GetKeep().GetValue();
2094 ++nEndOfs;
2097 SwNodeRange aRange( *rOutNds[ i ], 0, *rOutNds[ i ], nEndOfs );
2098 GetNodes()._Copy( aRange, aEndOfDoc );
2100 const SwTxtFmtColls *pColl = pExtDoc->GetTxtFmtColls();
2101 for( i = 0; i < pColl->size(); ++i )
2102 (*pColl)[ i ]->ResetFmtAttr( RES_PAGEDESC, RES_BREAK );
2103 SwNodeIndex aIndx( pExtDoc->GetNodes().GetEndOfExtras() );
2104 ++aEndOfDoc;
2105 while( aIndx < aEndOfDoc )
2107 SwNode *pNode;
2108 bool bDelete = false;
2109 if( (pNode = &aIndx.GetNode())->IsTxtNode() )
2111 SwTxtNode *pNd = (SwTxtNode*)pNode;
2112 if( pNd->HasSwAttrSet() )
2113 pNd->ResetAttr( RES_PAGEDESC, RES_BREAK );
2114 if( bImpress )
2116 SwTxtFmtColl* pMyColl = pNd->GetTxtColl();
2118 const sal_uInt16 nHeadLine = static_cast<sal_uInt16>(
2119 !pMyColl->IsAssignedToListLevelOfOutlineStyle() //<-end,zhaojianwei
2120 ? RES_POOLCOLL_HEADLINE2
2121 : RES_POOLCOLL_HEADLINE1 );
2122 pMyColl = pExtDoc->GetTxtCollFromPool( nHeadLine );
2123 pNd->ChgFmtColl( pMyColl );
2125 if( !pNd->Len() &&
2126 pNd->StartOfSectionIndex()+2 < pNd->EndOfSectionIndex() )
2128 bDelete = true;
2129 pExtDoc->GetNodes().Delete( aIndx );
2132 if( !bDelete )
2133 ++aIndx;
2135 ::EndProgress( GetDocShell() );
2139 /// Remove the invisible content from the document e.g. hidden areas, hidden paragraphs
2140 bool SwDoc::RemoveInvisibleContent()
2142 bool bRet = false;
2143 GetIDocumentUndoRedo().StartUndo( UNDO_UI_DELETE_INVISIBLECNTNT, NULL );
2146 SwTxtNode* pTxtNd;
2147 SwIterator<SwFmtFld,SwFieldType> aIter( *GetSysFldType( RES_HIDDENPARAFLD ) );
2148 for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
2150 if( pFmtFld->GetTxtFld() &&
2151 0 != ( pTxtNd = (SwTxtNode*)pFmtFld->GetTxtFld()->GetpTxtNode() ) &&
2152 pTxtNd->GetpSwpHints() && pTxtNd->HasHiddenParaField() &&
2153 &pTxtNd->GetNodes() == &GetNodes() )
2155 bRet = true;
2156 SwPaM aPam(*pTxtNd, 0, *pTxtNd, pTxtNd->GetTxt().getLength());
2158 // Remove hidden paragraph or delete contents:
2159 // Delete contents if
2160 // 1. removing the paragraph would result in an empty section or
2161 // 2. if the paragraph is the last paragraph in the section and
2162 // there is no paragraph in front of the paragraph:
2163 if ( ( 2 == pTxtNd->EndOfSectionIndex() - pTxtNd->StartOfSectionIndex() ) ||
2164 ( 1 == pTxtNd->EndOfSectionIndex() - pTxtNd->GetIndex() &&
2165 !GetNodes()[ pTxtNd->GetIndex() - 1 ]->GetTxtNode() ) )
2167 DeleteRange( aPam );
2169 else
2171 aPam.DeleteMark();
2172 DelFullPara( aPam );
2178 // Remove any hidden paragraph (hidden text attribute)
2179 for( sal_uLong n = GetNodes().Count(); n; )
2181 SwTxtNode* pTxtNd = GetNodes()[ --n ]->GetTxtNode();
2182 if ( pTxtNd )
2184 bool bRemoved = false;
2185 SwPaM aPam(*pTxtNd, 0, *pTxtNd, pTxtNd->GetTxt().getLength());
2186 if ( pTxtNd->HasHiddenCharAttribute( true ) )
2188 bRemoved = sal_True;
2189 bRet = true;
2191 // Remove hidden paragraph or delete contents:
2192 // Delete contents if
2193 // 1. removing the paragraph would result in an empty section or
2194 // 2. if the paragraph is the last paragraph in the section and
2195 // there is no paragraph in front of the paragraph:
2197 if ( ( 2 == pTxtNd->EndOfSectionIndex() - pTxtNd->StartOfSectionIndex() ) ||
2198 ( 1 == pTxtNd->EndOfSectionIndex() - pTxtNd->GetIndex() &&
2199 !GetNodes()[ pTxtNd->GetIndex() - 1 ]->GetTxtNode() ) )
2201 DeleteRange( aPam );
2203 else
2205 aPam.DeleteMark();
2206 DelFullPara( aPam );
2209 else if ( pTxtNd->HasHiddenCharAttribute( false ) )
2211 bRemoved = sal_True;
2212 bRet = true;
2213 SwScriptInfo::DeleteHiddenRanges( *pTxtNd );
2216 // Footnotes/Frames may have been removed, therefore we have
2217 // to reset n:
2218 if ( bRemoved )
2219 n = aPam.GetPoint()->nNode.GetIndex();
2224 // Delete/empty all hidden areas
2225 SwSectionFmts aSectFmts;
2226 SwSectionFmts& rSectFmts = GetSections();
2227 sal_uInt16 n;
2229 for( n = rSectFmts.size(); n; )
2231 SwSectionFmt* pSectFmt = rSectFmts[ --n ];
2232 // don't add sections in Undo/Redo
2233 if( !pSectFmt->IsInNodesArr())
2234 continue;
2235 SwSection* pSect = pSectFmt->GetSection();
2236 if( pSect->CalcHiddenFlag() )
2238 SwSection* pParent = pSect, *pTmp;
2239 while( 0 != (pTmp = pParent->GetParent() ))
2241 if( pTmp->IsHiddenFlag() )
2242 pSect = pTmp;
2243 pParent = pTmp;
2246 SwSectionFmts::iterator it = std::find(
2247 aSectFmts.begin(), aSectFmts.end(), pSect->GetFmt() );
2248 if (it == aSectFmts.end())
2249 aSectFmts.insert( aSectFmts.begin(), pSect->GetFmt() );
2251 if( pSect->GetCondition().Len() )
2253 SwSectionData aSectionData( *pSect );
2254 aSectionData.SetCondition( aEmptyStr );
2255 aSectionData.SetHidden( false );
2256 UpdateSection( n, aSectionData );
2260 if( 0 != ( n = aSectFmts.size() ))
2262 while( n )
2264 SwSectionFmt* pSectFmt = aSectFmts[ --n ];
2265 SwSectionNode* pSectNd = pSectFmt->GetSectionNode();
2266 if( pSectNd )
2268 bRet = true;
2269 SwPaM aPam( *pSectNd );
2271 if( pSectNd->StartOfSectionNode()->StartOfSectionIndex() ==
2272 pSectNd->GetIndex() - 1 &&
2273 pSectNd->StartOfSectionNode()->EndOfSectionIndex() ==
2274 pSectNd->EndOfSectionIndex() + 1 )
2276 // only delete the content
2277 SwCntntNode* pCNd = GetNodes().GoNext(
2278 &aPam.GetPoint()->nNode );
2279 aPam.GetPoint()->nContent.Assign( pCNd, 0 );
2280 aPam.SetMark();
2281 aPam.GetPoint()->nNode = *pSectNd->EndOfSectionNode();
2282 pCNd = GetNodes().GoPrevious(
2283 &aPam.GetPoint()->nNode );
2284 aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
2286 DeleteRange( aPam );
2288 else
2290 // delete the whole section
2291 aPam.SetMark();
2292 aPam.GetPoint()->nNode = *pSectNd->EndOfSectionNode();
2293 DelFullPara( aPam );
2298 aSectFmts.clear();
2302 if( bRet )
2303 SetModified();
2304 GetIDocumentUndoRedo().EndUndo( UNDO_UI_DELETE_INVISIBLECNTNT, NULL );
2305 return bRet;
2308 bool SwDoc::HasInvisibleContent() const
2310 bool bRet = false;
2312 SwClientIter aIter( *GetSysFldType( RES_HIDDENPARAFLD ) );
2313 if( aIter.First( TYPE( SwFmtFld ) ) )
2314 bRet = true;
2316 // Search for any hidden paragraph (hidden text attribute)
2317 if( ! bRet )
2319 for( sal_uLong n = GetNodes().Count(); !bRet && (n > 0); )
2321 SwTxtNode* pTxtNd = GetNodes()[ --n ]->GetTxtNode();
2322 if ( pTxtNd )
2324 SwPaM aPam(*pTxtNd, 0, *pTxtNd, pTxtNd->GetTxt().getLength());
2325 if( pTxtNd->HasHiddenCharAttribute( true ) || ( pTxtNd->HasHiddenCharAttribute( false ) ) )
2327 bRet = true;
2333 if( ! bRet )
2335 const SwSectionFmts& rSectFmts = GetSections();
2336 sal_uInt16 n;
2338 for( n = rSectFmts.size(); !bRet && (n > 0); )
2340 SwSectionFmt* pSectFmt = rSectFmts[ --n ];
2341 // don't add sections in Undo/Redo
2342 if( !pSectFmt->IsInNodesArr())
2343 continue;
2344 SwSection* pSect = pSectFmt->GetSection();
2345 if( pSect->IsHidden() )
2346 bRet = true;
2349 return bRet;
2352 bool SwDoc::RestoreInvisibleContent()
2354 bool bRet = false;
2355 SwUndoId nLastUndoId(UNDO_EMPTY);
2356 if (GetIDocumentUndoRedo().GetLastUndoInfo(0, & nLastUndoId)
2357 && (UNDO_UI_DELETE_INVISIBLECNTNT == nLastUndoId))
2359 GetIDocumentUndoRedo().Undo();
2360 GetIDocumentUndoRedo().ClearRedo();
2361 bRet = true;
2363 return bRet;
2367 bool SwDoc::ConvertFieldsToText()
2369 bool bRet = false;
2370 LockExpFlds();
2371 GetIDocumentUndoRedo().StartUndo( UNDO_UI_REPLACE, NULL );
2373 const SwFldTypes* pMyFldTypes = GetFldTypes();
2374 sal_uInt16 nCount = pMyFldTypes->size();
2375 //go backward, field types are removed
2376 for(sal_uInt16 nType = nCount; nType > 0; --nType)
2378 const SwFieldType *pCurType = (*pMyFldTypes)[nType - 1];
2380 if ( RES_POSTITFLD == pCurType->Which() )
2381 continue;
2383 SwIterator<SwFmtFld,SwFieldType> aIter( *pCurType );
2384 ::std::vector<const SwFmtFld*> aFieldFmts;
2385 for( SwFmtFld* pCurFldFmt = aIter.First(); pCurFldFmt; pCurFldFmt = aIter.Next() )
2386 aFieldFmts.push_back(pCurFldFmt);
2388 ::std::vector<const SwFmtFld*>::iterator aBegin = aFieldFmts.begin();
2389 ::std::vector<const SwFmtFld*>::iterator aEnd = aFieldFmts.end();
2390 while(aBegin != aEnd)
2392 const SwTxtFld *pTxtFld = (*aBegin)->GetTxtFld();
2393 // skip fields that are currently not in the document
2394 // e.g. fields in undo or redo array
2396 bool bSkip = !pTxtFld ||
2397 !pTxtFld->GetpTxtNode()->GetNodes().IsDocNodes();
2399 if (!bSkip)
2401 bool bInHeaderFooter = IsInHeaderFooter(SwNodeIndex(*pTxtFld->GetpTxtNode()));
2402 const SwFmtFld& rFmtFld = pTxtFld->GetFld();
2403 const SwField* pField = rFmtFld.GetFld();
2405 //#i55595# some fields have to be excluded in headers/footers
2406 sal_uInt16 nWhich = pField->GetTyp()->Which();
2407 if(!bInHeaderFooter ||
2408 (nWhich != RES_PAGENUMBERFLD &&
2409 nWhich != RES_CHAPTERFLD &&
2410 nWhich != RES_GETEXPFLD&&
2411 nWhich != RES_SETEXPFLD&&
2412 nWhich != RES_INPUTFLD&&
2413 nWhich != RES_REFPAGEGETFLD&&
2414 nWhich != RES_REFPAGESETFLD))
2416 String sText = pField->ExpandField(true);
2417 //database fields should not convert their command into text
2418 if( RES_DBFLD == pCurType->Which() && !static_cast<const SwDBField*>(pField)->IsInitialized())
2419 sText.Erase();
2421 //now remove the field and insert the string
2422 SwPaM aPam1(*pTxtFld->GetpTxtNode(), *pTxtFld->GetStart());
2423 aPam1.Move();
2424 //insert first to keep the field's attributes
2425 InsertString( aPam1, sText );
2426 SwPaM aPam2(*pTxtFld->GetpTxtNode(), *pTxtFld->GetStart());
2427 aPam2.SetMark();
2428 aPam2.Move();
2429 DeleteAndJoin(aPam2);//remove the field
2430 bRet=true;
2433 ++aBegin;
2437 if( bRet )
2438 SetModified();
2439 GetIDocumentUndoRedo().EndUndo( UNDO_UI_REPLACE, NULL );
2440 UnlockExpFlds();
2441 return bRet;
2445 bool SwDoc::IsVisibleLinks() const
2447 return mbVisibleLinks;
2450 void SwDoc::SetVisibleLinks(bool bFlag)
2452 mbVisibleLinks = bFlag;
2455 sfx2::LinkManager& SwDoc::GetLinkManager()
2457 return *mpLinkMgr;
2460 const sfx2::LinkManager& SwDoc::GetLinkManager() const
2462 return *mpLinkMgr;
2465 void SwDoc::SetLinksUpdated(const bool bNewLinksUpdated)
2467 mbLinksUpdated = bNewLinksUpdated;
2470 bool SwDoc::LinksUpdated() const
2472 return mbLinksUpdated;
2475 static ::sfx2::SvBaseLink* lcl_FindNextRemovableLink( const ::sfx2::SvBaseLinks& rLinks, sfx2::LinkManager& rLnkMgr )
2477 for( sal_uInt16 n = 0; n < rLinks.size(); ++n )
2479 ::sfx2::SvBaseLink* pLnk = &(*rLinks[ n ]);
2480 if( pLnk &&
2481 ( OBJECT_CLIENT_GRF == pLnk->GetObjType() ||
2482 OBJECT_CLIENT_FILE == pLnk->GetObjType() ) &&
2483 pLnk->ISA( SwBaseLink ) )
2485 ::sfx2::SvBaseLinkRef xLink = pLnk;
2487 String sFName;
2488 rLnkMgr.GetDisplayNames( xLink, 0, &sFName, 0, 0 );
2490 INetURLObject aURL( sFName );
2491 if( INET_PROT_FILE == aURL.GetProtocol() ||
2492 INET_PROT_CID == aURL.GetProtocol() )
2493 return pLnk;
2496 return 0;
2499 /// embedded all local links (Areas/Graphics)
2500 bool SwDoc::EmbedAllLinks()
2502 bool bRet = false;
2503 sfx2::LinkManager& rLnkMgr = GetLinkManager();
2504 const ::sfx2::SvBaseLinks& rLinks = rLnkMgr.GetLinks();
2505 if( !rLinks.empty() )
2507 ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
2509 ::sfx2::SvBaseLink* pLnk = 0;
2510 while( 0 != (pLnk = lcl_FindNextRemovableLink( rLinks, rLnkMgr ) ) )
2512 ::sfx2::SvBaseLinkRef xLink = pLnk;
2513 // Tell the link that it's being destroyed!
2514 xLink->Closed();
2516 // if one forgot to remove itself
2517 if( xLink.Is() )
2518 rLnkMgr.Remove( xLink );
2520 bRet = true;
2523 GetIDocumentUndoRedo().DelAllUndoObj();
2524 SetModified();
2526 return bRet;
2529 sal_Bool SwDoc::IsInsTblFormatNum() const
2531 return SW_MOD()->IsInsTblFormatNum(get(IDocumentSettingAccess::HTML_MODE));
2534 sal_Bool SwDoc::IsInsTblChangeNumFormat() const
2536 return SW_MOD()->IsInsTblChangeNumFormat(get(IDocumentSettingAccess::HTML_MODE));
2539 sal_Bool SwDoc::IsInsTblAlignNum() const
2541 return SW_MOD()->IsInsTblAlignNum(get(IDocumentSettingAccess::HTML_MODE));
2544 /// Set up the InsertDB as Undo table
2545 void SwDoc::AppendUndoForInsertFromDB( const SwPaM& rPam, sal_Bool bIsTable )
2547 if( bIsTable )
2549 const SwTableNode* pTblNd = rPam.GetPoint()->nNode.GetNode().FindTableNode();
2550 if( pTblNd )
2552 SwUndoCpyTbl* pUndo = new SwUndoCpyTbl;
2553 pUndo->SetTableSttIdx( pTblNd->GetIndex() );
2554 GetIDocumentUndoRedo().AppendUndo( pUndo );
2557 else if( rPam.HasMark() )
2559 SwUndoCpyDoc* pUndo = new SwUndoCpyDoc( rPam );
2560 pUndo->SetInsertRange( rPam, sal_False );
2561 GetIDocumentUndoRedo().AppendUndo( pUndo );
2565 void SwDoc::ChgTOX(SwTOXBase & rTOX, const SwTOXBase & rNew)
2567 if (GetIDocumentUndoRedo().DoesUndo())
2569 GetIDocumentUndoRedo().DelAllUndoObj();
2571 SwUndo * pUndo = new SwUndoTOXChange(&rTOX, rNew);
2573 GetIDocumentUndoRedo().AppendUndo(pUndo);
2576 rTOX = rNew;
2578 if (rTOX.ISA(SwTOXBaseSection))
2580 static_cast<SwTOXBaseSection &>(rTOX).Update();
2581 static_cast<SwTOXBaseSection &>(rTOX).UpdatePageNum();
2585 String SwDoc::GetPaMDescr(const SwPaM & rPam) const
2587 String aResult;
2588 bool bOK = false;
2590 if (rPam.GetNode(sal_True) == rPam.GetNode(sal_False))
2592 SwTxtNode * pTxtNode = rPam.GetNode(sal_True)->GetTxtNode();
2594 if (0 != pTxtNode)
2596 xub_StrLen nStart = rPam.Start()->nContent.GetIndex();
2597 xub_StrLen nEnd = rPam.End()->nContent.GetIndex();
2599 aResult += String(SW_RES(STR_START_QUOTE));
2600 aResult += ShortenString(pTxtNode->GetTxt().
2601 copy(nStart, nEnd - nStart),
2602 nUndoStringLength,
2603 String(SW_RES(STR_LDOTS)));
2604 aResult += String(SW_RES(STR_END_QUOTE));
2606 bOK = true;
2609 else if (0 != rPam.GetNode(sal_True))
2611 if (0 != rPam.GetNode(sal_False))
2612 aResult += String(SW_RES(STR_PARAGRAPHS));
2614 bOK = true;
2617 if (! bOK)
2618 aResult += String("??", RTL_TEXTENCODING_ASCII_US);
2620 return aResult;
2623 SwField * SwDoc::GetField(const SwPosition & rPos)
2625 SwTxtFld * const pAttr = GetTxtFld(rPos);
2627 return (pAttr) ? const_cast<SwField *>( pAttr->GetFld().GetFld() ) : 0;
2630 SwTxtFld * SwDoc::GetTxtFld(const SwPosition & rPos)
2632 SwTxtNode * const pNode = rPos.nNode.GetNode().GetTxtNode();
2634 return (pNode)
2635 ? static_cast<SwTxtFld*>( pNode->GetTxtAttrForCharAt(
2636 rPos.nContent.GetIndex(), RES_TXTATR_FIELD) )
2637 : 0;
2640 bool SwDoc::ContainsHiddenChars() const
2642 for( sal_uLong n = GetNodes().Count(); n; )
2644 SwNode* pNd = GetNodes()[ --n ];
2645 if ( pNd->IsTxtNode() &&
2646 ((SwTxtNode*)pNd)->HasHiddenCharAttribute( false ) )
2647 return true;
2650 return false;
2653 SwUnoCrsr* SwDoc::CreateUnoCrsr( const SwPosition& rPos, bool bTblCrsr )
2655 SwUnoCrsr* pNew;
2656 if( bTblCrsr )
2657 pNew = new SwUnoTableCrsr( rPos );
2658 else
2659 pNew = new SwUnoCrsr( rPos );
2661 mpUnoCrsrTbl->insert( pNew );
2662 return pNew;
2665 void SwDoc::ChkCondColls()
2667 for (sal_uInt16 n = 0; n < mpTxtFmtCollTbl->size(); n++)
2669 SwTxtFmtColl *pColl = (*mpTxtFmtCollTbl)[n];
2670 if (RES_CONDTXTFMTCOLL == pColl->Which())
2671 pColl->CallSwClientNotify( SwAttrHint(RES_CONDTXTFMTCOLL) );
2675 uno::Reference< script::vba::XVBAEventProcessor >
2676 SwDoc::GetVbaEventProcessor()
2678 #ifndef DISABLE_SCRIPTING
2679 if( !mxVbaEvents.is() && mpDocShell && ooo::vba::isAlienWordDoc( *mpDocShell ) )
2683 uno::Reference< frame::XModel > xModel( mpDocShell->GetModel(), uno::UNO_SET_THROW );
2684 uno::Sequence< uno::Any > aArgs(1);
2685 aArgs[0] <<= xModel;
2686 mxVbaEvents.set( ooo::vba::createVBAUnoAPIServiceWithArgs( mpDocShell, "com.sun.star.script.vba.VBATextEventProcessor" , aArgs ), uno::UNO_QUERY_THROW );
2688 catch( uno::Exception& )
2692 #endif
2693 return mxVbaEvents;
2696 void SwDoc::setExternalData(::sw::tExternalDataType eType,
2697 ::sw::tExternalDataPointer pPayload)
2699 m_externalData[eType] = pPayload;
2702 ::sw::tExternalDataPointer SwDoc::getExternalData(::sw::tExternalDataType eType)
2704 return m_externalData[eType];
2707 sal_uInt16 SwNumRuleTbl::GetPos(const SwNumRule* pRule) const
2709 const_iterator it = std::find(begin(), end(), pRule);
2710 return it == end() ? USHRT_MAX : it - begin();
2713 SwNumRuleTbl::~SwNumRuleTbl()
2715 for(const_iterator it = begin(); it != end(); ++it)
2716 delete *it;
2719 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */