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