1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sw.hxx" 30 31 #include <hintids.hxx> 32 #include <editeng/frmdiritem.hxx> 33 #include <editeng/protitem.hxx> 34 #include <com/sun/star/i18n/CharacterIteratorMode.hdl> 35 #include <fmtcntnt.hxx> 36 #include <fmtanchr.hxx> 37 #include <frmfmt.hxx> 38 #include <txtftn.hxx> 39 #include <ftnfrm.hxx> 40 #include <doc.hxx> 41 #include <docary.hxx> 42 #include <node.hxx> 43 #include <ndindex.hxx> 44 #include <numrule.hxx> 45 #include <swtable.hxx> 46 #include <ndtxt.hxx> 47 #include <pam.hxx> 48 #include <swcache.hxx> 49 #include <section.hxx> 50 #include <cntfrm.hxx> 51 #include <flyfrm.hxx> 52 #include <txtfrm.hxx> 53 #include <tabfrm.hxx> // SwTabFrm 54 #include <viewsh.hxx> 55 #include <paratr.hxx> 56 #include <ftnidx.hxx> 57 #include <fmtftn.hxx> 58 #include <fmthdft.hxx> 59 #include <frmatr.hxx> 60 #include <fmtautofmt.hxx> 61 #include <frmtool.hxx> 62 #include <pagefrm.hxx> 63 #include <node2lay.hxx> 64 #include <pagedesc.hxx> 65 #include <fmtpdsc.hxx> 66 #include <breakit.hxx> 67 #include <crsskip.hxx> 68 #include <SwStyleNameMapper.hxx> 69 #include <scriptinfo.hxx> 70 #include <rootfrm.hxx> 71 #include <istyleaccess.hxx> 72 #include <IDocumentListItems.hxx> 73 #include <switerator.hxx> 74 #include "ndole.hxx" 75 76 using namespace ::com::sun::star::i18n; 77 78 TYPEINIT2( SwCntntNode, SwModify, SwIndexReg ) 79 80 /* 81 * Some local helper functions for the attribute set handle of a content node. 82 * Since the attribute set of a content node may not be modified directly, 83 * we always have to create a new SwAttrSet, do the modifications, and get 84 * a new handle from the style access 85 */ 86 87 namespace AttrSetHandleHelper 88 { 89 90 void GetNewAutoStyle( boost::shared_ptr<const SfxItemSet>& mrpAttrSet, 91 const SwCntntNode& rNode, 92 SwAttrSet& rNewAttrSet ) 93 { 94 const SwAttrSet* pAttrSet = static_cast<const SwAttrSet*>(mrpAttrSet.get()); 95 if( rNode.GetModifyAtAttr() ) 96 const_cast<SwAttrSet*>(pAttrSet)->SetModifyAtAttr( 0 ); 97 IStyleAccess& rSA = pAttrSet->GetPool()->GetDoc()->GetIStyleAccess(); 98 mrpAttrSet = rSA.getAutomaticStyle( rNewAttrSet, rNode.IsTxtNode() ? 99 IStyleAccess::AUTO_STYLE_PARA : 100 IStyleAccess::AUTO_STYLE_NOTXT ); 101 const bool bSetModifyAtAttr = ((SwAttrSet*)mrpAttrSet.get())->SetModifyAtAttr( &rNode ); 102 rNode.SetModifyAtAttr( bSetModifyAtAttr ); 103 } 104 105 106 void SetParent( boost::shared_ptr<const SfxItemSet>& mrpAttrSet, 107 const SwCntntNode& rNode, 108 const SwFmt* pParentFmt, 109 const SwFmt* pConditionalFmt ) 110 { 111 const SwAttrSet* pAttrSet = static_cast<const SwAttrSet*>(mrpAttrSet.get()); 112 ASSERT( pAttrSet, "no SwAttrSet" ) 113 ASSERT( pParentFmt || !pConditionalFmt, "ConditionalFmt without ParentFmt?" ) 114 115 const SwAttrSet* pParentSet = pParentFmt ? &pParentFmt->GetAttrSet() : 0; 116 117 if ( pParentSet != pAttrSet->GetParent() ) 118 { 119 SwAttrSet aNewSet( *pAttrSet ); 120 aNewSet.SetParent( pParentSet ); 121 aNewSet.ClearItem( RES_FRMATR_STYLE_NAME ); 122 aNewSet.ClearItem( RES_FRMATR_CONDITIONAL_STYLE_NAME ); 123 String sVal; 124 125 if ( pParentFmt ) 126 { 127 SwStyleNameMapper::FillProgName( pParentFmt->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True ); 128 const SfxStringItem aAnyFmtColl( RES_FRMATR_STYLE_NAME, sVal ); 129 aNewSet.Put( aAnyFmtColl ); 130 131 if ( pConditionalFmt != pParentFmt ) 132 SwStyleNameMapper::FillProgName( pConditionalFmt->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True ); 133 134 const SfxStringItem aFmtColl( RES_FRMATR_CONDITIONAL_STYLE_NAME, sVal ); 135 aNewSet.Put( aFmtColl ); 136 } 137 138 GetNewAutoStyle( mrpAttrSet, rNode, aNewSet ); 139 } 140 } 141 142 const SfxPoolItem* Put( boost::shared_ptr<const SfxItemSet>& mrpAttrSet, 143 const SwCntntNode& rNode, 144 const SfxPoolItem& rAttr ) 145 { 146 SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet ); 147 const SfxPoolItem* pRet = aNewSet.Put( rAttr ); 148 if ( pRet ) 149 GetNewAutoStyle( mrpAttrSet, rNode, aNewSet ); 150 return pRet; 151 } 152 153 int Put( boost::shared_ptr<const SfxItemSet>& mrpAttrSet, const SwCntntNode& rNode, 154 const SfxItemSet& rSet ) 155 { 156 SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet ); 157 158 // --> FME 2007-4-12 #i76273# Robust: Save the style name items: 159 SfxItemSet* pStyleNames = 0; 160 if ( SFX_ITEM_SET == rSet.GetItemState( RES_FRMATR_STYLE_NAME, sal_False ) ) 161 { 162 pStyleNames = new SfxItemSet( *aNewSet.GetPool(), RES_FRMATR_STYLE_NAME, RES_FRMATR_CONDITIONAL_STYLE_NAME ); 163 pStyleNames->Put( aNewSet ); 164 } 165 // <-- 166 167 const int nRet = aNewSet.Put( rSet ); 168 169 // --> FME 2007-4-12 #i76273# Robust: Save the style name items: 170 if ( pStyleNames ) 171 { 172 aNewSet.Put( *pStyleNames ); 173 delete pStyleNames; 174 } 175 // <-- 176 177 if ( nRet ) 178 GetNewAutoStyle( mrpAttrSet, rNode, aNewSet ); 179 180 return nRet; 181 } 182 183 int Put_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet, 184 const SwCntntNode& rNode, const SfxPoolItem& rAttr, 185 SwAttrSet* pOld, SwAttrSet* pNew ) 186 { 187 SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet ); 188 189 // for a correct broadcast, we need to do a SetModifyAtAttr with the items 190 // from aNewSet. The 'regular' SetModifyAtAttr is done in GetNewAutoStyle 191 if( rNode.GetModifyAtAttr() ) 192 aNewSet.SetModifyAtAttr( &rNode ); 193 194 const int nRet = aNewSet.Put_BC( rAttr, pOld, pNew ); 195 196 if ( nRet ) 197 GetNewAutoStyle( mrpAttrSet, rNode, aNewSet ); 198 199 return nRet; 200 } 201 202 int Put_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet, 203 const SwCntntNode& rNode, const SfxItemSet& rSet, 204 SwAttrSet* pOld, SwAttrSet* pNew ) 205 { 206 SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet ); 207 208 // --> FME 2007-4-12 #i76273# Robust: Save the style name items: 209 SfxItemSet* pStyleNames = 0; 210 if ( SFX_ITEM_SET == rSet.GetItemState( RES_FRMATR_STYLE_NAME, sal_False ) ) 211 { 212 pStyleNames = new SfxItemSet( *aNewSet.GetPool(), RES_FRMATR_STYLE_NAME, RES_FRMATR_CONDITIONAL_STYLE_NAME ); 213 pStyleNames->Put( aNewSet ); 214 } 215 // <-- 216 217 // for a correct broadcast, we need to do a SetModifyAtAttr with the items 218 // from aNewSet. The 'regular' SetModifyAtAttr is done in GetNewAutoStyle 219 if( rNode.GetModifyAtAttr() ) 220 aNewSet.SetModifyAtAttr( &rNode ); 221 222 const int nRet = aNewSet.Put_BC( rSet, pOld, pNew ); 223 224 // --> FME 2007-4-12 #i76273# Robust: Save the style name items: 225 if ( pStyleNames ) 226 { 227 aNewSet.Put( *pStyleNames ); 228 delete pStyleNames; 229 } 230 // <-- 231 232 if ( nRet ) 233 GetNewAutoStyle( mrpAttrSet, rNode, aNewSet ); 234 235 return nRet; 236 } 237 238 sal_uInt16 ClearItem_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet, 239 const SwCntntNode& rNode, sal_uInt16 nWhich, 240 SwAttrSet* pOld, SwAttrSet* pNew ) 241 { 242 SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet ); 243 if( rNode.GetModifyAtAttr() ) 244 aNewSet.SetModifyAtAttr( &rNode ); 245 const sal_uInt16 nRet = aNewSet.ClearItem_BC( nWhich, pOld, pNew ); 246 if ( nRet ) 247 GetNewAutoStyle( mrpAttrSet, rNode, aNewSet ); 248 return nRet; 249 } 250 251 sal_uInt16 ClearItem_BC( boost::shared_ptr<const SfxItemSet>& mrpAttrSet, 252 const SwCntntNode& rNode, 253 sal_uInt16 nWhich1, sal_uInt16 nWhich2, 254 SwAttrSet* pOld, SwAttrSet* pNew ) 255 { 256 SwAttrSet aNewSet( (SwAttrSet&)*mrpAttrSet ); 257 if( rNode.GetModifyAtAttr() ) 258 aNewSet.SetModifyAtAttr( &rNode ); 259 const sal_uInt16 nRet = aNewSet.ClearItem_BC( nWhich1, nWhich2, pOld, pNew ); 260 if ( nRet ) 261 GetNewAutoStyle( mrpAttrSet, rNode, aNewSet ); 262 return nRet; 263 } 264 265 } 266 267 /******************************************************************* 268 |* 269 |* SwNode::GetSectionLevel 270 |* 271 |* Beschreibung 272 |* Die Funktion liefert den Sectionlevel an der durch 273 |* aIndex bezeichneten Position. 274 |* 275 |* Die Logik ist wie folgt: ( S -> Start, E -> End, C -> CntntNode) 276 |* Level 0 E 277 |* 1 S E 278 |* 2 SC 279 |* 280 |* alle EndNodes der GrundSection haben den Level 0 281 |* alle StartNodes der GrundSection haben den Level 1 282 |* 283 |* Ersterstellung 284 |* VER0100 vb 901214 285 |* 286 |* Aenderung: JP 11.08.93 287 |* keine Rekursion mehr !! 288 |* 289 *******************************************************************/ 290 291 292 sal_uInt16 SwNode::GetSectionLevel() const 293 { 294 // EndNode einer Grund-Section ?? diese sind immer 0 !! 295 if( IsEndNode() && 0 == pStartOfSection->StartOfSectionIndex() ) 296 return 0; 297 298 sal_uInt16 nLevel; 299 const SwNode* pNode = IsStartNode() ? this : pStartOfSection; 300 for( nLevel = 1; 0 != pNode->StartOfSectionIndex(); ++nLevel ) 301 pNode = pNode->pStartOfSection; 302 return IsEndNode() ? nLevel-1 : nLevel; 303 } 304 305 /******************************************************************* 306 |* 307 |* SwNode::SwNode 308 |* 309 |* Beschreibung 310 |* Konstruktor; dieser fuegt einen Node in das Array rNodes 311 |* an der Position rWhere ein. Dieser bekommt als 312 |* theEndOfSection den EndOfSection-Index des Nodes 313 |* unmittelbar vor ihm. Falls er sich an der Position 0 314 |* innerhalb des variablen Arrays befindet, wird 315 |* theEndOfSection 0 (der neue selbst). 316 |* 317 |* Parameter 318 |* IN 319 |* rNodes bezeichnet das variable Array, in das der Node 320 |* eingefuegt werden soll 321 |* IN 322 |* rWhere bezeichnet die Position innerhalb dieses Arrays, 323 |* an der der Node eingefuegt werden soll 324 |* 325 |* Ersterstellung 326 |* VER0100 vb 901214 327 |* 328 |* Stand 329 |* VER0100 vb 901214 330 |* 331 *******************************************************************/ 332 333 #ifdef DBG_UTIL 334 long SwNode::nSerial = 0; 335 #endif 336 337 SwNode::SwNode( const SwNodeIndex &rWhere, const sal_uInt8 nNdType ) 338 : nNodeType( nNdType ), pStartOfSection( 0 ) 339 { 340 bSetNumLSpace = bIgnoreDontExpand = sal_False; 341 nAFmtNumLvl = 0; 342 343 SwNodes& rNodes = (SwNodes&)rWhere.GetNodes(); 344 SwNode* pInsNd = this; // der MAC kann this nicht einfuegen !! 345 if( rWhere.GetIndex() ) 346 { 347 SwNode* pNd = rNodes[ rWhere.GetIndex() -1 ]; 348 rNodes.InsertNode( pInsNd, rWhere ); 349 if( 0 == ( pStartOfSection = pNd->GetStartNode()) ) 350 { 351 pStartOfSection = pNd->pStartOfSection; 352 if( pNd->GetEndNode() ) // EndNode ? Section ueberspringen! 353 { 354 pNd = pStartOfSection; 355 pStartOfSection = pNd->pStartOfSection; 356 } 357 } 358 } 359 else 360 { 361 rNodes.InsertNode( pInsNd, rWhere ); 362 pStartOfSection = (SwStartNode*)this; 363 } 364 365 #ifdef DBG_UTIL 366 nMySerial = nSerial; 367 nSerial++; 368 #endif 369 } 370 371 SwNode::SwNode( SwNodes& rNodes, sal_uLong nPos, const sal_uInt8 nNdType ) 372 : nNodeType( nNdType ), pStartOfSection( 0 ) 373 { 374 bSetNumLSpace = bIgnoreDontExpand = sal_False; 375 nAFmtNumLvl = 0; 376 377 SwNode* pInsNd = this; // der MAC kann this nicht einfuegen !! 378 if( nPos ) 379 { 380 SwNode* pNd = rNodes[ nPos - 1 ]; 381 rNodes.InsertNode( pInsNd, nPos ); 382 if( 0 == ( pStartOfSection = pNd->GetStartNode()) ) 383 { 384 pStartOfSection = pNd->pStartOfSection; 385 if( pNd->GetEndNode() ) // EndNode ? Section ueberspringen! 386 { 387 pNd = pStartOfSection; 388 pStartOfSection = pNd->pStartOfSection; 389 } 390 } 391 } 392 else 393 { 394 rNodes.InsertNode( pInsNd, nPos ); 395 pStartOfSection = (SwStartNode*)this; 396 } 397 398 #ifdef DBG_UTIL 399 nMySerial = nSerial; 400 nSerial++; 401 #endif 402 } 403 404 SwNode::~SwNode() 405 { 406 } 407 408 // suche den TabellenNode, in dem dieser steht. Wenn in keiner 409 // Tabelle wird 0 returnt. 410 411 412 SwTableNode* SwNode::FindTableNode() 413 { 414 if( IsTableNode() ) 415 return GetTableNode(); 416 SwStartNode* pTmp = pStartOfSection; 417 while( !pTmp->IsTableNode() && pTmp->GetIndex() ) 418 #if defined( ALPHA ) && defined( UNX ) 419 pTmp = ((SwNode*)pTmp)->pStartOfSection; 420 #else 421 pTmp = pTmp->pStartOfSection; 422 #endif 423 return pTmp->GetTableNode(); 424 } 425 426 427 // liegt der Node im Sichtbarenbereich der Shell ? 428 sal_Bool SwNode::IsInVisibleArea( ViewShell* pSh ) const 429 { 430 sal_Bool bRet = sal_False; 431 const SwCntntNode* pNd; 432 433 if( ND_STARTNODE & nNodeType ) 434 { 435 SwNodeIndex aIdx( *this ); 436 pNd = GetNodes().GoNext( &aIdx ); 437 } 438 else if( ND_ENDNODE & nNodeType ) 439 { 440 SwNodeIndex aIdx( *EndOfSectionNode() ); 441 pNd = GetNodes().GoPrevious( &aIdx ); 442 } 443 else 444 pNd = GetCntntNode(); 445 446 if( !pSh ) 447 // dann die Shell vom Doc besorgen: 448 GetDoc()->GetEditShell( &pSh ); 449 450 if( pSh ) 451 { 452 const SwFrm* pFrm; 453 if( pNd && 0 != ( pFrm = pNd->getLayoutFrm( pSh->GetLayout(), 0, 0, sal_False ) ) ) 454 { 455 456 if ( pFrm->IsInTab() ) 457 pFrm = pFrm->FindTabFrm(); 458 459 if( !pFrm->IsValid() ) 460 do 461 { pFrm = pFrm->FindPrev(); 462 } while ( pFrm && !pFrm->IsValid() ); 463 464 if( !pFrm || pSh->VisArea().IsOver( pFrm->Frm() ) ) 465 bRet = sal_True; 466 } 467 } 468 469 return bRet; 470 } 471 472 sal_Bool SwNode::IsInProtectSect() const 473 { 474 const SwNode* pNd = ND_SECTIONNODE == nNodeType ? pStartOfSection : this; 475 const SwSectionNode* pSectNd = pNd->FindSectionNode(); 476 return pSectNd && pSectNd->GetSection().IsProtectFlag(); 477 } 478 479 // befindet sich der Node in irgendetwas geschuetzten ? 480 // (Bereich/Rahmen/Tabellenzellen/... incl. des Ankers bei 481 // Rahmen/Fussnoten/..) 482 sal_Bool SwNode::IsProtect() const 483 { 484 const SwNode* pNd = ND_SECTIONNODE == nNodeType ? pStartOfSection : this; 485 const SwStartNode* pSttNd = pNd->FindSectionNode(); 486 if( pSttNd && ((SwSectionNode*)pSttNd)->GetSection().IsProtectFlag() ) 487 return sal_True; 488 489 if( 0 != ( pSttNd = FindTableBoxStartNode() ) ) 490 { 491 SwCntntFrm* pCFrm; 492 if( IsCntntNode() && 0 != (pCFrm = ((SwCntntNode*)this)->getLayoutFrm( GetDoc()->GetCurrentLayout() ) )) 493 return pCFrm->IsProtected(); 494 495 const SwTableBox* pBox = pSttNd->FindTableNode()->GetTable(). 496 GetTblBox( pSttNd->GetIndex() ); 497 //Robust #149568 498 if( pBox && pBox->GetFrmFmt()->GetProtect().IsCntntProtected() ) 499 return sal_True; 500 } 501 502 SwFrmFmt* pFlyFmt = GetFlyFmt(); 503 if( pFlyFmt ) 504 { 505 if( pFlyFmt->GetProtect().IsCntntProtected() ) 506 return sal_True; 507 const SwFmtAnchor& rAnchor = pFlyFmt->GetAnchor(); 508 return rAnchor.GetCntntAnchor() 509 ? rAnchor.GetCntntAnchor()->nNode.GetNode().IsProtect() 510 : sal_False; 511 } 512 513 if( 0 != ( pSttNd = FindFootnoteStartNode() ) ) 514 { 515 const SwTxtFtn* pTFtn = GetDoc()->GetFtnIdxs().SeekEntry( 516 SwNodeIndex( *pSttNd ) ); 517 if( pTFtn ) 518 return pTFtn->GetTxtNode().IsProtect(); 519 } 520 521 return sal_False; 522 } 523 524 // suche den PageDesc, mit dem dieser Node formatiert ist. Wenn das 525 // Layout vorhanden ist wird ueber das gesucht, ansonsten gibt es nur 526 // die harte Tour ueber die Nodes nach vorne suchen!! 527 const SwPageDesc* SwNode::FindPageDesc( sal_Bool bCalcLay, 528 sal_uInt32* pPgDescNdIdx ) const 529 { 530 // OD 18.03.2003 #106329# 531 if ( !GetNodes().IsDocNodes() ) 532 { 533 return 0; 534 } 535 536 const SwPageDesc* pPgDesc = 0; 537 538 const SwCntntNode* pNode; 539 if( ND_STARTNODE & nNodeType ) 540 { 541 SwNodeIndex aIdx( *this ); 542 pNode = GetNodes().GoNext( &aIdx ); 543 } 544 else if( ND_ENDNODE & nNodeType ) 545 { 546 SwNodeIndex aIdx( *EndOfSectionNode() ); 547 pNode = GetNodes().GoPrevious( &aIdx ); 548 } 549 else 550 { 551 pNode = GetCntntNode(); 552 if( pNode ) 553 pPgDesc = ((SwFmtPageDesc&)pNode->GetAttr( RES_PAGEDESC )).GetPageDesc(); 554 } 555 556 // geht es uebers Layout? 557 if( !pPgDesc ) 558 { 559 const SwFrm* pFrm; 560 const SwPageFrm* pPage; 561 if( pNode && 0 != ( pFrm = pNode->getLayoutFrm( pNode->GetDoc()->GetCurrentLayout(), 0, 0, bCalcLay ) ) && 562 0 != ( pPage = pFrm->FindPageFrm() ) ) 563 { 564 pPgDesc = pPage->GetPageDesc(); 565 // OD 18.03.2003 #106329# 566 if ( pPgDescNdIdx ) 567 { 568 *pPgDescNdIdx = pNode->GetIndex(); 569 } 570 } 571 } 572 573 if( !pPgDesc ) 574 { 575 // dann also uebers Nodes-Array 576 const SwDoc* pDoc = GetDoc(); 577 const SwNode* pNd = this; 578 const SwStartNode* pSttNd; 579 if( pNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() && 580 0 != ( pSttNd = pNd->FindFlyStartNode() ) ) 581 { 582 // dann erstmal den richtigen Anker finden 583 const SwFrmFmt* pFmt = 0; 584 const SwSpzFrmFmts& rFmts = *pDoc->GetSpzFrmFmts(); 585 sal_uInt16 n; 586 587 for( n = 0; n < rFmts.Count(); ++n ) 588 { 589 SwFrmFmt* pFrmFmt = rFmts[ n ]; 590 const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt(); 591 if( rCntnt.GetCntntIdx() && 592 &rCntnt.GetCntntIdx()->GetNode() == (SwNode*)pSttNd ) 593 { 594 pFmt = pFrmFmt; 595 break; 596 } 597 } 598 599 if( pFmt ) 600 { 601 const SwFmtAnchor* pAnchor = &pFmt->GetAnchor(); 602 if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) && 603 pAnchor->GetCntntAnchor() ) 604 { 605 pNd = &pAnchor->GetCntntAnchor()->nNode.GetNode(); 606 const SwNode* pFlyNd = pNd->FindFlyStartNode(); 607 while( pFlyNd ) 608 { 609 // dann ueber den Anker nach oben "hangeln" 610 for( n = 0; n < rFmts.Count(); ++n ) 611 { 612 const SwFrmFmt* pFrmFmt = rFmts[ n ]; 613 const SwNodeIndex* pIdx = pFrmFmt->GetCntnt(). 614 GetCntntIdx(); 615 if( pIdx && pFlyNd == &pIdx->GetNode() ) 616 { 617 if( pFmt == pFrmFmt ) 618 { 619 pNd = pFlyNd; 620 pFlyNd = 0; 621 break; 622 } 623 pAnchor = &pFrmFmt->GetAnchor(); 624 if ((FLY_AT_PAGE == pAnchor->GetAnchorId()) || 625 !pAnchor->GetCntntAnchor() ) 626 { 627 pFlyNd = 0; 628 break; 629 } 630 631 pFlyNd = pAnchor->GetCntntAnchor()->nNode. 632 GetNode().FindFlyStartNode(); 633 break; 634 } 635 } 636 if( n >= rFmts.Count() ) 637 { 638 ASSERT( !this, "Fly-Section aber kein Format gefunden" ); 639 return sal_False; 640 } 641 } 642 } 643 } 644 // in pNd sollte jetzt der richtige Anker Node stehen oder 645 // immer noch der this 646 } 647 648 if( pNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() ) 649 { 650 if( pNd->GetIndex() > GetNodes().GetEndOfAutotext().GetIndex() ) 651 { 652 pPgDesc = &pDoc->GetPageDesc( 0 ); 653 pNd = 0; 654 } 655 else 656 { 657 // suche den Body Textnode 658 if( 0 != ( pSttNd = pNd->FindHeaderStartNode() ) || 659 0 != ( pSttNd = pNd->FindFooterStartNode() )) 660 { 661 // dann in den PageDescs diesen StartNode suchen 662 sal_uInt16 nId; 663 UseOnPage eAskUse; 664 if( SwHeaderStartNode == pSttNd->GetStartNodeType()) 665 { 666 nId = RES_HEADER; 667 eAskUse = nsUseOnPage::PD_HEADERSHARE; 668 } 669 else 670 { 671 nId = RES_FOOTER; 672 eAskUse = nsUseOnPage::PD_FOOTERSHARE; 673 } 674 675 for( sal_uInt16 n = pDoc->GetPageDescCnt(); n && !pPgDesc; ) 676 { 677 const SwPageDesc& rPgDsc = pDoc->GetPageDesc( --n ); 678 const SwFrmFmt* pFmt = &rPgDsc.GetMaster(); 679 int nStt = 0, nLast = 1; 680 if( !( eAskUse & rPgDsc.ReadUseOn() )) ++nLast; 681 682 for( ; nStt < nLast; ++nStt, pFmt = &rPgDsc.GetLeft() ) 683 { 684 const SwFmtHeader& rHdFt = (SwFmtHeader&) 685 pFmt->GetFmtAttr( nId ); 686 if( rHdFt.GetHeaderFmt() ) 687 { 688 const SwFmtCntnt& rCntnt = 689 rHdFt.GetHeaderFmt()->GetCntnt(); 690 if( rCntnt.GetCntntIdx() && 691 &rCntnt.GetCntntIdx()->GetNode() == 692 (SwNode*)pSttNd ) 693 { 694 pPgDesc = &rPgDsc; 695 break; 696 } 697 } 698 } 699 } 700 701 if( !pPgDesc ) 702 pPgDesc = &pDoc->GetPageDesc( 0 ); 703 pNd = 0; 704 } 705 else if( 0 != ( pSttNd = pNd->FindFootnoteStartNode() )) 706 { 707 // der Anker kann nur im Bodytext sein 708 const SwTxtFtn* pTxtFtn; 709 const SwFtnIdxs& rFtnArr = pDoc->GetFtnIdxs(); 710 for( sal_uInt16 n = 0; n < rFtnArr.Count(); ++n ) 711 if( 0 != ( pTxtFtn = rFtnArr[ n ])->GetStartNode() && 712 (SwNode*)pSttNd == 713 &pTxtFtn->GetStartNode()->GetNode() ) 714 { 715 pNd = &pTxtFtn->GetTxtNode(); 716 break; 717 } 718 } 719 else 720 { 721 // kann jetzt nur noch ein Seitengebundener Fly sein 722 // oder irgendetwas neueres. 723 // Hier koennen wir nur noch den Standard returnen 724 ASSERT( pNd->FindFlyStartNode(), 725 "wo befindet sich dieser Node?" ); 726 727 pPgDesc = &pDoc->GetPageDesc( 0 ); 728 pNd = 0; 729 } 730 } 731 } 732 733 if( pNd ) 734 { 735 SwFindNearestNode aInfo( *pNd ); 736 // dann ueber alle Nodes aller PageDesc 737 const SfxPoolItem* pItem; 738 sal_uInt32 i, nMaxItems = pDoc->GetAttrPool().GetItemCount2( RES_PAGEDESC ); 739 for( i = 0; i < nMaxItems; ++i ) 740 if( 0 != (pItem = pDoc->GetAttrPool().GetItem2( RES_PAGEDESC, i ) ) && 741 ((SwFmtPageDesc*)pItem)->GetDefinedIn() ) 742 { 743 const SwModify* pMod = ((SwFmtPageDesc*)pItem)->GetDefinedIn(); 744 if( pMod->ISA( SwCntntNode ) ) 745 aInfo.CheckNode( *(SwCntntNode*)pMod ); 746 else if( pMod->ISA( SwFmt )) 747 ((SwFmt*)pMod)->GetInfo( aInfo ); 748 } 749 750 if( 0 != ( pNd = aInfo.GetFoundNode() )) 751 { 752 if( pNd->IsCntntNode() ) 753 pPgDesc = ((SwFmtPageDesc&)pNd->GetCntntNode()-> 754 GetAttr( RES_PAGEDESC )).GetPageDesc(); 755 else if( pNd->IsTableNode() ) 756 pPgDesc = pNd->GetTableNode()->GetTable(). 757 GetFrmFmt()->GetPageDesc().GetPageDesc(); 758 else if( pNd->IsSectionNode() ) 759 pPgDesc = pNd->GetSectionNode()->GetSection(). 760 GetFmt()->GetPageDesc().GetPageDesc(); 761 // OD 18.03.2003 #106329# 762 if ( pPgDescNdIdx ) 763 { 764 *pPgDescNdIdx = pNd->GetIndex(); 765 } 766 } 767 if( !pPgDesc ) 768 pPgDesc = &pDoc->GetPageDesc( 0 ); 769 } 770 } 771 return pPgDesc; 772 } 773 774 775 // falls der Node in einem Fly steht, dann wird das entsprechende Format 776 // returnt 777 SwFrmFmt* SwNode::GetFlyFmt() const 778 { 779 SwFrmFmt* pRet = 0; 780 const SwNode* pSttNd = FindFlyStartNode(); 781 if( pSttNd ) 782 { 783 if( IsCntntNode() ) 784 { 785 SwCntntFrm* pFrm = SwIterator<SwCntntFrm,SwCntntNode>::FirstElement( *(SwCntntNode*)this ); 786 if( pFrm ) 787 pRet = pFrm->FindFlyFrm()->GetFmt(); 788 } 789 if( !pRet ) 790 { 791 // dann gibts noch harten steinigen Weg uebers Dokument: 792 const SwSpzFrmFmts& rFrmFmtTbl = *GetDoc()->GetSpzFrmFmts(); 793 for( sal_uInt16 n = 0; n < rFrmFmtTbl.Count(); ++n ) 794 { 795 SwFrmFmt* pFmt = rFrmFmtTbl[n]; 796 const SwFmtCntnt& rCntnt = pFmt->GetCntnt(); 797 if( rCntnt.GetCntntIdx() && 798 &rCntnt.GetCntntIdx()->GetNode() == pSttNd ) 799 { 800 pRet = pFmt; 801 break; 802 } 803 } 804 } 805 } 806 return pRet; 807 } 808 809 SwTableBox* SwNode::GetTblBox() const 810 { 811 SwTableBox* pBox = 0; 812 const SwNode* pSttNd = FindTableBoxStartNode(); 813 if( pSttNd ) 814 pBox = (SwTableBox*)pSttNd->FindTableNode()->GetTable().GetTblBox( 815 pSttNd->GetIndex() ); 816 return pBox; 817 } 818 819 SwStartNode* SwNode::FindSttNodeByType( SwStartNodeType eTyp ) 820 { 821 SwStartNode* pTmp = IsStartNode() ? (SwStartNode*)this : pStartOfSection; 822 823 while( eTyp != pTmp->GetStartNodeType() && pTmp->GetIndex() ) 824 #if defined( ALPHA ) && defined( UNX ) 825 pTmp = ((SwNode*)pTmp)->pStartOfSection; 826 #else 827 pTmp = pTmp->pStartOfSection; 828 #endif 829 return eTyp == pTmp->GetStartNodeType() ? pTmp : 0; 830 } 831 832 const SwTxtNode* SwNode::FindOutlineNodeOfLevel( sal_uInt8 nLvl ) const 833 { 834 const SwTxtNode* pRet = 0; 835 const SwOutlineNodes& rONds = GetNodes().GetOutLineNds(); 836 if( MAXLEVEL > nLvl && rONds.Count() ) 837 { 838 sal_uInt16 nPos; 839 SwNode* pNd = (SwNode*)this; 840 sal_Bool bCheckFirst = sal_False; 841 if( !rONds.Seek_Entry( pNd, &nPos )) 842 { 843 if( nPos ) 844 nPos = nPos-1; 845 else 846 bCheckFirst = sal_True; 847 } 848 849 if( bCheckFirst ) 850 { 851 // der 1.GliederungsNode liegt hinter dem Fragenden. Dann 852 // teste mal, ob dieser auf der gleichen Seite steht. Wenn 853 // nicht, ist das ein ungueltiger. Bug 61865 854 pRet = rONds[0]->GetTxtNode(); 855 856 const SwCntntNode* pCNd = GetCntntNode(); 857 858 Point aPt( 0, 0 ); 859 const SwFrm* pFrm = pRet->getLayoutFrm( pRet->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False ), 860 * pMyFrm = pCNd ? pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False ) : 0; 861 const SwPageFrm* pPgFrm = pFrm ? pFrm->FindPageFrm() : 0; 862 if( pPgFrm && pMyFrm && 863 pPgFrm->Frm().Top() > pMyFrm->Frm().Top() ) 864 { 865 // der Fragende liegt vor der Seite, also ist er ungueltig 866 pRet = 0; 867 } 868 } 869 else 870 { 871 // oder ans Feld und von dort holen !! 872 while( nPos && 873 nLvl < ( pRet = rONds[nPos]->GetTxtNode() ) 874 //->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei 875 ->GetAttrOutlineLevel() - 1 ) //<-end,zhaojianwei 876 --nPos; 877 878 if( !nPos ) // bei 0 gesondert holen !! 879 pRet = rONds[0]->GetTxtNode(); 880 } 881 } 882 return pRet; 883 } 884 885 inline sal_Bool IsValidNextPrevNd( const SwNode& rNd ) 886 { 887 return ND_TABLENODE == rNd.GetNodeType() || 888 ( ND_CONTENTNODE & rNd.GetNodeType() ) || 889 ( ND_ENDNODE == rNd.GetNodeType() && rNd.StartOfSectionNode() && 890 ND_TABLENODE == rNd.StartOfSectionNode()->GetNodeType() ); 891 } 892 893 sal_uInt8 SwNode::HasPrevNextLayNode() const 894 { 895 // assumption: <this> node is a node inside the document nodes array section. 896 897 sal_uInt8 nRet = 0; 898 if( IsValidNextPrevNd( *this )) 899 { 900 SwNodeIndex aIdx( *this, -1 ); 901 // --> OD 2007-06-04 #i77805# 902 // skip section start and end nodes 903 while ( aIdx.GetNode().IsSectionNode() || 904 ( aIdx.GetNode().IsEndNode() && 905 aIdx.GetNode().StartOfSectionNode()->IsSectionNode() ) ) 906 { 907 --aIdx; 908 } 909 // <-- 910 if( IsValidNextPrevNd( aIdx.GetNode() )) 911 nRet |= ND_HAS_PREV_LAYNODE; 912 // --> OD 2007-06-04 #i77805# 913 // skip section start and end nodes 914 // aIdx += 2; 915 aIdx = SwNodeIndex( *this, +1 ); 916 while ( aIdx.GetNode().IsSectionNode() || 917 ( aIdx.GetNode().IsEndNode() && 918 aIdx.GetNode().StartOfSectionNode()->IsSectionNode() ) ) 919 { 920 ++aIdx; 921 } 922 // <-- 923 if( IsValidNextPrevNd( aIdx.GetNode() )) 924 nRet |= ND_HAS_NEXT_LAYNODE; 925 } 926 return nRet; 927 } 928 929 /******************************************************************* 930 |* 931 |* SwNode::StartOfSection 932 |* 933 |* Beschreibung 934 |* Die Funktion liefert die StartOfSection des Nodes. 935 |* 936 |* Parameter 937 |* IN 938 |* rNodes bezeichnet das variable Array, in dem sich der Node 939 |* befindet 940 |* Ersterstellung 941 |* VER0100 vb 901214 942 |* 943 |* Stand 944 |* VER0100 vb 901214 945 |* 946 *******************************************************************/ 947 948 949 SwStartNode::SwStartNode( const SwNodeIndex &rWhere, const sal_uInt8 nNdType, 950 SwStartNodeType eSttNd ) 951 : SwNode( rWhere, nNdType ), eSttNdTyp( eSttNd ) 952 { 953 // erstmal temporaer, bis der EndNode eingefuegt wird. 954 pEndOfSection = (SwEndNode*)this; 955 } 956 957 SwStartNode::SwStartNode( SwNodes& rNodes, sal_uLong nPos ) 958 : SwNode( rNodes, nPos, ND_STARTNODE ), eSttNdTyp( SwNormalStartNode ) 959 { 960 // erstmal temporaer, bis der EndNode eingefuegt wird. 961 pEndOfSection = (SwEndNode*)this; 962 } 963 964 965 void SwStartNode::CheckSectionCondColl() const 966 { 967 //FEATURE::CONDCOLL 968 SwNodeIndex aIdx( *this ); 969 sal_uLong nEndIdx = EndOfSectionIndex(); 970 const SwNodes& rNds = GetNodes(); 971 SwCntntNode* pCNd; 972 while( 0 != ( pCNd = rNds.GoNext( &aIdx )) && pCNd->GetIndex() < nEndIdx ) 973 pCNd->ChkCondColl(); 974 //FEATURE::CONDCOLL 975 } 976 977 /******************************************************************* 978 |* 979 |* SwEndNode::SwEndNode 980 |* 981 |* Beschreibung 982 |* Konstruktor; dieser fuegt einen Node in das Array rNodes 983 |* an der Position aWhere ein. Der 984 |* theStartOfSection-Pointer wird entsprechend gesetzt, 985 |* und der EndOfSection-Pointer des zugehoerigen 986 |* Startnodes -- durch rStartOfSection bezeichnet -- 987 |* wird auf diesen Node gesetzt. 988 |* 989 |* Parameter 990 |* IN 991 |* rNodes bezeichnet das variable Array, in das der Node 992 |* eingefuegt werden soll 993 |* IN 994 |* aWhere bezeichnet die Position innerhalb dieses Arrays, 995 |* an der der Node eingefuegt werden soll 996 |* !!!!!!!!!!!! 997 |* Es wird eine Kopie uebergeben! 998 |* 999 |* Ersterstellung 1000 |* VER0100 vb 901214 1001 |* 1002 |* Stand 1003 |* VER0100 vb 901214 1004 |* 1005 *******************************************************************/ 1006 1007 1008 SwEndNode::SwEndNode( const SwNodeIndex &rWhere, SwStartNode& rSttNd ) 1009 : SwNode( rWhere, ND_ENDNODE ) 1010 { 1011 pStartOfSection = &rSttNd; 1012 pStartOfSection->pEndOfSection = this; 1013 } 1014 1015 SwEndNode::SwEndNode( SwNodes& rNds, sal_uLong nPos, SwStartNode& rSttNd ) 1016 : SwNode( rNds, nPos, ND_ENDNODE ) 1017 { 1018 pStartOfSection = &rSttNd; 1019 pStartOfSection->pEndOfSection = this; 1020 } 1021 1022 1023 1024 // -------------------- 1025 // SwCntntNode 1026 // -------------------- 1027 1028 1029 SwCntntNode::SwCntntNode( const SwNodeIndex &rWhere, const sal_uInt8 nNdType, 1030 SwFmtColl *pColl ) 1031 : SwModify( pColl ), // CrsrsShell, FrameFmt, 1032 SwNode( rWhere, nNdType ), 1033 pCondColl( 0 ), 1034 mbSetModifyAtAttr( false ) 1035 #ifdef OLD_INDEX 1036 ,SwIndexReg(2) 1037 #endif 1038 { 1039 } 1040 1041 1042 SwCntntNode::~SwCntntNode() 1043 { 1044 // Die Basisklasse SwClient vom SwFrm nimmt sich aus 1045 // der Abhaengikeitsliste raus! 1046 // Daher muessen alle Frames in der Abhaengigkeitsliste geloescht werden. 1047 if( GetDepends() ) 1048 DelFrms(); 1049 1050 if( pCondColl ) 1051 delete pCondColl; 1052 1053 if ( mpAttrSet.get() && mbSetModifyAtAttr ) 1054 ((SwAttrSet*)mpAttrSet.get())->SetModifyAtAttr( 0 ); 1055 } 1056 1057 void SwCntntNode::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue ) 1058 { 1059 sal_uInt16 nWhich = pOldValue ? pOldValue->Which() : 1060 pNewValue ? pNewValue->Which() : 0 ; 1061 1062 switch( nWhich ) 1063 { 1064 case RES_OBJECTDYING : 1065 { 1066 SwFmt * pFmt = (SwFmt *) ((SwPtrMsgPoolItem *)pNewValue)->pObject; 1067 1068 // nicht umhaengen wenn dieses das oberste Format ist !! 1069 if( GetRegisteredIn() == pFmt ) 1070 { 1071 if( pFmt->GetRegisteredIn() ) 1072 { 1073 // wenn Parent, dann im neuen Parent wieder anmelden 1074 ((SwModify*)pFmt->GetRegisteredIn())->Add( this ); 1075 if ( GetpSwAttrSet() ) 1076 AttrSetHandleHelper::SetParent( mpAttrSet, *this, GetFmtColl(), GetFmtColl() ); 1077 } 1078 else 1079 { 1080 // sonst auf jeden Fall beim sterbenden abmelden 1081 ((SwModify*)GetRegisteredIn())->Remove( this ); 1082 if ( GetpSwAttrSet() ) 1083 AttrSetHandleHelper::SetParent( mpAttrSet, *this, 0, 0 ); 1084 } 1085 } 1086 } 1087 break; 1088 1089 1090 case RES_FMT_CHG: 1091 // falls mein Format Parent umgesetzt wird, dann melde ich 1092 // meinen Attrset beim Neuen an. 1093 1094 // sein eigenes Modify ueberspringen !! 1095 if( GetpSwAttrSet() && 1096 ((SwFmtChg*)pNewValue)->pChangedFmt == GetRegisteredIn() ) 1097 { 1098 // den Set an den neuen Parent haengen 1099 AttrSetHandleHelper::SetParent( mpAttrSet, *this, GetFmtColl(), GetFmtColl() ); 1100 } 1101 break; 1102 //FEATURE::CONDCOLL 1103 case RES_CONDCOLL_CONDCHG: 1104 if( ((SwCondCollCondChg*)pNewValue)->pChangedFmt == GetRegisteredIn() && 1105 &GetNodes() == &GetDoc()->GetNodes() ) 1106 { 1107 ChkCondColl(); 1108 } 1109 return ; // nicht an die Basisklasse / Frames weitergeben 1110 //FEATURE::CONDCOLL 1111 1112 case RES_ATTRSET_CHG: 1113 if( GetNodes().IsDocNodes() && IsTxtNode() ) 1114 { 1115 if( SFX_ITEM_SET == ((SwAttrSetChg*)pOldValue)->GetChgSet()->GetItemState( 1116 RES_CHRATR_HIDDEN, sal_False ) ) 1117 { 1118 ((SwTxtNode*)this)->SetCalcHiddenCharFlags(); 1119 } 1120 } 1121 break; 1122 1123 case RES_UPDATE_ATTR: 1124 if( GetNodes().IsDocNodes() && IsTxtNode() ) 1125 { 1126 const sal_uInt16 nTmp = ((SwUpdateAttr*)pNewValue)->nWhichAttr; 1127 if ( RES_ATTRSET_CHG == nTmp ) 1128 { 1129 // anybody wants to do some optimization here? 1130 ((SwTxtNode*)this)->SetCalcHiddenCharFlags(); 1131 } 1132 } 1133 break; 1134 } 1135 1136 NotifyClients( pOldValue, pNewValue ); 1137 } 1138 1139 sal_Bool SwCntntNode::InvalidateNumRule() 1140 { 1141 SwNumRule* pRule = 0; 1142 const SfxPoolItem* pItem; 1143 if( GetNodes().IsDocNodes() && 1144 0 != ( pItem = GetNoCondAttr( RES_PARATR_NUMRULE, sal_True )) && 1145 ((SwNumRuleItem*)pItem)->GetValue().Len() && 1146 0 != (pRule = GetDoc()->FindNumRulePtr( 1147 ((SwNumRuleItem*)pItem)->GetValue() ) ) ) 1148 { 1149 pRule->SetInvalidRule( sal_True ); 1150 } 1151 return 0 != pRule; 1152 } 1153 1154 SwCntntFrm *SwCntntNode::getLayoutFrm( const SwRootFrm* _pRoot, 1155 const Point* pPoint, const SwPosition *pPos, const sal_Bool bCalcFrm ) const 1156 { 1157 return (SwCntntFrm*) ::GetFrmOfModify( _pRoot, *(SwModify*)this, FRM_CNTNT, 1158 pPoint, pPos, bCalcFrm ); 1159 } 1160 1161 SwRect SwCntntNode::FindLayoutRect( const sal_Bool bPrtArea, const Point* pPoint, 1162 const sal_Bool bCalcFrm ) const 1163 { 1164 SwRect aRet; 1165 SwCntntFrm* pFrm = (SwCntntFrm*)::GetFrmOfModify( 0, *(SwModify*)this, 1166 FRM_CNTNT, pPoint, 0, bCalcFrm ); 1167 if( pFrm ) 1168 aRet = bPrtArea ? pFrm->Prt() : pFrm->Frm(); 1169 return aRet; 1170 } 1171 1172 SwRect SwCntntNode::FindPageFrmRect( const sal_Bool bPrtArea, const Point* pPoint, 1173 const sal_Bool bCalcFrm ) const 1174 { 1175 SwRect aRet; 1176 SwFrm* pFrm = ::GetFrmOfModify( 0, *(SwModify*)this, 1177 FRM_CNTNT, pPoint, 0, bCalcFrm ); 1178 if( pFrm && 0 != ( pFrm = pFrm->FindPageFrm() )) 1179 aRet = bPrtArea ? pFrm->Prt() : pFrm->Frm(); 1180 return aRet; 1181 } 1182 1183 xub_StrLen SwCntntNode::Len() const { return 0; } 1184 1185 1186 1187 SwFmtColl *SwCntntNode::ChgFmtColl( SwFmtColl *pNewColl ) 1188 { 1189 ASSERT( pNewColl, "Collectionpointer ist 0." ); 1190 SwFmtColl *pOldColl = GetFmtColl(); 1191 1192 if( pNewColl != pOldColl ) 1193 { 1194 pNewColl->Add( this ); 1195 1196 // setze den Parent von unseren Auto-Attributen auf die neue 1197 // Collection: 1198 if( GetpSwAttrSet() ) 1199 AttrSetHandleHelper::SetParent( mpAttrSet, *this, pNewColl, pNewColl ); 1200 1201 //FEATURE::CONDCOLL 1202 // HACK: hier muss die entsprechend der neuen Vorlage die Bedingungen 1203 // neu ueberprueft werden! 1204 if( sal_True /*pNewColl */ ) 1205 { 1206 SetCondFmtColl( 0 ); 1207 } 1208 //FEATURE::CONDCOLL 1209 1210 if( !IsModifyLocked() ) 1211 { 1212 SwFmtChg aTmp1( pOldColl ); 1213 SwFmtChg aTmp2( pNewColl ); 1214 SwCntntNode::Modify( &aTmp1, &aTmp2 ); 1215 } 1216 } 1217 if ( IsInCache() ) 1218 { 1219 SwFrm::GetCache().Delete( this ); 1220 SetInCache( sal_False ); 1221 } 1222 return pOldColl; 1223 } 1224 1225 1226 sal_Bool SwCntntNode::GoNext(SwIndex * pIdx, sal_uInt16 nMode ) const 1227 { 1228 sal_Bool bRet = sal_True; 1229 if( pIdx->GetIndex() < Len() ) 1230 { 1231 if( !IsTxtNode() ) 1232 (*pIdx)++; 1233 else 1234 { 1235 const SwTxtNode& rTNd = *GetTxtNode(); 1236 xub_StrLen nPos = pIdx->GetIndex(); 1237 if( pBreakIt->GetBreakIter().is() ) 1238 { 1239 sal_Int32 nDone = 0; 1240 sal_uInt16 nItrMode = ( CRSR_SKIP_CELLS & nMode ) ? 1241 CharacterIteratorMode::SKIPCELL : 1242 CharacterIteratorMode::SKIPCONTROLCHARACTER; 1243 nPos = (xub_StrLen)pBreakIt->GetBreakIter()->nextCharacters( rTNd.GetTxt(), nPos, 1244 pBreakIt->GetLocale( rTNd.GetLang( nPos ) ), 1245 nItrMode, 1, nDone ); 1246 1247 // Check if nPos is inside hidden text range: 1248 if ( CRSR_SKIP_HIDDEN & nMode ) 1249 { 1250 xub_StrLen nHiddenStart; 1251 xub_StrLen nHiddenEnd; 1252 SwScriptInfo::GetBoundsOfHiddenRange( rTNd, nPos, nHiddenStart, nHiddenEnd ); 1253 if ( nHiddenStart != STRING_LEN && nHiddenStart != nPos ) 1254 nPos = nHiddenEnd; 1255 } 1256 1257 if( 1 == nDone ) 1258 *pIdx = nPos; 1259 else 1260 bRet = sal_False; 1261 } 1262 else if( nPos < rTNd.GetTxt().Len() ) 1263 (*pIdx)++; 1264 else 1265 bRet = sal_False; 1266 } 1267 } 1268 else 1269 bRet = sal_False; 1270 return bRet; 1271 } 1272 1273 1274 sal_Bool SwCntntNode::GoPrevious(SwIndex * pIdx, sal_uInt16 nMode ) const 1275 { 1276 sal_Bool bRet = sal_True; 1277 if( pIdx->GetIndex() > 0 ) 1278 { 1279 if( !IsTxtNode() ) 1280 (*pIdx)--; 1281 else 1282 { 1283 const SwTxtNode& rTNd = *GetTxtNode(); 1284 xub_StrLen nPos = pIdx->GetIndex(); 1285 if( pBreakIt->GetBreakIter().is() ) 1286 { 1287 sal_Int32 nDone = 0; 1288 sal_uInt16 nItrMode = ( CRSR_SKIP_CELLS & nMode ) ? 1289 CharacterIteratorMode::SKIPCELL : 1290 CharacterIteratorMode::SKIPCONTROLCHARACTER; 1291 nPos = (xub_StrLen)pBreakIt->GetBreakIter()->previousCharacters( rTNd.GetTxt(), nPos, 1292 pBreakIt->GetLocale( rTNd.GetLang( nPos ) ), 1293 nItrMode, 1, nDone ); 1294 1295 // Check if nPos is inside hidden text range: 1296 if ( CRSR_SKIP_HIDDEN & nMode ) 1297 { 1298 xub_StrLen nHiddenStart; 1299 xub_StrLen nHiddenEnd; 1300 SwScriptInfo::GetBoundsOfHiddenRange( rTNd, nPos, nHiddenStart, nHiddenEnd ); 1301 if ( nHiddenStart != STRING_LEN ) 1302 nPos = nHiddenStart; 1303 } 1304 1305 if( 1 == nDone ) 1306 *pIdx = nPos; 1307 else 1308 bRet = sal_False; 1309 } 1310 else if( nPos ) 1311 (*pIdx)--; 1312 else 1313 bRet = sal_False; 1314 } 1315 } 1316 else 1317 bRet = sal_False; 1318 return bRet; 1319 } 1320 1321 1322 /* 1323 * Methode erzeugt fuer den vorhergehenden Node alle Ansichten vom 1324 * Dokument. Die erzeugten Contentframes werden in das entsprechende 1325 * Layout gehaengt. 1326 */ 1327 1328 1329 void SwCntntNode::MakeFrms( SwCntntNode& rNode ) 1330 { 1331 ASSERT( &rNode != this, 1332 "Kein Contentnode oder Copy-Node und neuer Node identisch." ); 1333 1334 if( !GetDepends() || &rNode == this ) // gibt es ueberhaupt Frames ?? 1335 return; 1336 1337 SwFrm *pFrm, *pNew; 1338 SwLayoutFrm *pUpper; 1339 // Frames anlegen fuer Nodes, die vor oder hinter der Tabelle stehen ?? 1340 ASSERT( FindTableNode() == rNode.FindTableNode(), "Table confusion" ) 1341 1342 SwNode2Layout aNode2Layout( *this, rNode.GetIndex() ); 1343 1344 while( 0 != (pUpper = aNode2Layout.UpperFrm( pFrm, rNode )) ) 1345 { 1346 pNew = rNode.MakeFrm( pUpper ); 1347 pNew->Paste( pUpper, pFrm ); 1348 // --> OD 2005-12-01 #i27138# 1349 // notify accessibility paragraphs objects about changed 1350 // CONTENT_FLOWS_FROM/_TO relation. 1351 // Relation CONTENT_FLOWS_FROM for next paragraph will change 1352 // and relation CONTENT_FLOWS_TO for previous paragraph will change. 1353 if ( pNew->IsTxtFrm() ) 1354 { 1355 ViewShell* pViewShell( pNew->getRootFrm()->GetCurrShell() ); 1356 if ( pViewShell && pViewShell->GetLayout() && 1357 pViewShell->GetLayout()->IsAnyShellAccessible() ) 1358 { 1359 pViewShell->InvalidateAccessibleParaFlowRelation( 1360 dynamic_cast<SwTxtFrm*>(pNew->FindNextCnt( true )), 1361 dynamic_cast<SwTxtFrm*>(pNew->FindPrevCnt( true )) ); 1362 } 1363 } 1364 // <-- 1365 } 1366 } 1367 1368 /* 1369 * Methode loescht fuer den Node alle Ansichten vom 1370 * Dokument. Die Contentframes werden aus dem entsprechenden 1371 * Layout ausgehaengt. 1372 */ 1373 1374 1375 void SwCntntNode::DelFrms() 1376 { 1377 if( !GetDepends() ) 1378 return; 1379 1380 SwCntntFrm::DelFrms(*this); 1381 if( IsTxtNode() ) 1382 { 1383 ((SwTxtNode*)this)->SetWrong( NULL ); 1384 ((SwTxtNode*)this)->SetWrongDirty( true ); 1385 1386 ((SwTxtNode*)this)->SetGrammarCheck( NULL ); 1387 ((SwTxtNode*)this)->SetGrammarCheckDirty( true ); 1388 // SMARTTAGS 1389 ((SwTxtNode*)this)->SetSmartTags( NULL ); 1390 ((SwTxtNode*)this)->SetSmartTagDirty( true ); 1391 1392 ((SwTxtNode*)this)->SetWordCountDirty( true ); 1393 ((SwTxtNode*)this)->SetAutoCompleteWordDirty( true ); 1394 } 1395 } 1396 1397 1398 SwCntntNode *SwCntntNode::JoinNext() 1399 { 1400 return this; 1401 } 1402 1403 1404 SwCntntNode *SwCntntNode::JoinPrev() 1405 { 1406 return this; 1407 } 1408 1409 1410 1411 // erfrage vom Modify Informationen 1412 sal_Bool SwCntntNode::GetInfo( SfxPoolItem& rInfo ) const 1413 { 1414 switch( rInfo.Which() ) 1415 { 1416 case RES_AUTOFMT_DOCNODE: 1417 if( &GetNodes() == ((SwAutoFmtGetDocNode&)rInfo).pNodes ) 1418 { 1419 ((SwAutoFmtGetDocNode&)rInfo).pCntntNode = this; 1420 return sal_False; 1421 } 1422 break; 1423 // --> OD 2008-02-19 #refactorlists# 1424 // case RES_GETNUMNODES: 1425 // // #111955# only numbered nodes in rInfo 1426 // if( IsTxtNode()) 1427 // { 1428 // SwTxtNode * pTxtNode = (SwTxtNode*)this; 1429 // pItem = (SwNumRuleItem*)GetNoCondAttr(RES_PARATR_NUMRULE, sal_True ); 1430 1431 // if (0 != pItem && 1432 // pItem->GetValue().Len() && 1433 // pItem->GetValue() == ((SwNumRuleInfo&)rInfo).GetName() && 1434 // GetNodes().IsDocNodes()) 1435 // { 1436 // ((SwNumRuleInfo&)rInfo).AddNode( *pTxtNode ); 1437 // } 1438 // } 1439 1440 // return sal_True; 1441 // <-- 1442 1443 case RES_FINDNEARESTNODE: 1444 if( ((SwFmtPageDesc&)GetAttr( RES_PAGEDESC )).GetPageDesc() ) 1445 ((SwFindNearestNode&)rInfo).CheckNode( *this ); 1446 return sal_True; 1447 1448 case RES_CONTENT_VISIBLE: 1449 { 1450 ((SwPtrMsgPoolItem&)rInfo).pObject = 1451 SwIterator<SwFrm,SwCntntNode>::FirstElement(*this); 1452 } 1453 return sal_False; 1454 } 1455 1456 return SwModify::GetInfo( rInfo ); 1457 } 1458 1459 1460 // setze ein Attribut 1461 sal_Bool SwCntntNode::SetAttr(const SfxPoolItem& rAttr ) 1462 { 1463 if( !GetpSwAttrSet() ) // lasse von den entsprechenden Nodes die 1464 NewAttrSet( GetDoc()->GetAttrPool() ); // AttrSets anlegen 1465 1466 ASSERT( GetpSwAttrSet(), "warum wurde kein AttrSet angelegt?" ); 1467 1468 if ( IsInCache() ) 1469 { 1470 SwFrm::GetCache().Delete( this ); 1471 SetInCache( sal_False ); 1472 } 1473 1474 sal_Bool bRet = sal_False; 1475 // wenn Modify gelockt ist, werden keine Modifies verschickt 1476 if( IsModifyLocked() || 1477 ( !GetDepends() && RES_PARATR_NUMRULE != rAttr.Which() )) 1478 { 1479 bRet = 0 != AttrSetHandleHelper::Put( mpAttrSet, *this, rAttr ); 1480 } 1481 else 1482 { 1483 SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ), 1484 aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ); 1485 if( 0 != ( bRet = 0 != AttrSetHandleHelper::Put_BC( mpAttrSet, *this, rAttr, &aOld, &aNew ) )) 1486 { 1487 SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld ); 1488 SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew ); 1489 ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt 1490 } 1491 } 1492 return bRet; 1493 } 1494 #include <svl/itemiter.hxx> 1495 1496 sal_Bool SwCntntNode::SetAttr( const SfxItemSet& rSet ) 1497 { 1498 if ( IsInCache() ) 1499 { 1500 SwFrm::GetCache().Delete( this ); 1501 SetInCache( sal_False ); 1502 } 1503 1504 const SfxPoolItem* pFnd = 0; 1505 if( SFX_ITEM_SET == rSet.GetItemState( RES_AUTO_STYLE, sal_False, &pFnd ) ) 1506 { 1507 ASSERT( rSet.Count() == 1, "SetAutoStyle mixed with other attributes?!" ); 1508 const SwFmtAutoFmt* pTmp = static_cast<const SwFmtAutoFmt*>(pFnd); 1509 1510 // If there already is an attribute set (usually containing a numbering 1511 // item), we have to merge the attribute of the new set into the old set: 1512 bool bSetParent = true; 1513 if ( GetpSwAttrSet() ) 1514 { 1515 bSetParent = false; 1516 AttrSetHandleHelper::Put( mpAttrSet, *this, *pTmp->GetStyleHandle() ); 1517 } 1518 else 1519 { 1520 mpAttrSet = pTmp->GetStyleHandle(); 1521 } 1522 1523 if ( bSetParent ) 1524 { 1525 // If the content node has a conditional style, we have to set the 1526 // string item containing the correct conditional style name (the 1527 // style name property has already been set during the import!) 1528 // In case we do not have a conditional style, we make use of the 1529 // fact that nobody else uses the attribute set behind the handle. 1530 // FME 2007-07-10 #i78124# If autostyle does not have a parent, 1531 // the string is empty. 1532 const SfxPoolItem* pNameItem = 0; 1533 if ( 0 != GetCondFmtColl() || 1534 SFX_ITEM_SET != mpAttrSet->GetItemState( RES_FRMATR_STYLE_NAME, sal_False, &pNameItem ) || 1535 0 == static_cast<const SfxStringItem*>(pNameItem)->GetValue().Len() ) 1536 AttrSetHandleHelper::SetParent( mpAttrSet, *this, &GetAnyFmtColl(), GetFmtColl() ); 1537 else 1538 const_cast<SfxItemSet*>(mpAttrSet.get())->SetParent( &GetFmtColl()->GetAttrSet() ); 1539 } 1540 1541 return sal_True; 1542 } 1543 1544 if( !GetpSwAttrSet() ) // lasse von den entsprechenden Nodes die 1545 NewAttrSet( GetDoc()->GetAttrPool() ); // AttrSets anlegen 1546 1547 sal_Bool bRet = sal_False; 1548 // wenn Modify gelockt ist, werden keine Modifies verschickt 1549 if ( IsModifyLocked() || 1550 ( !GetDepends() && 1551 SFX_ITEM_SET != rSet.GetItemState( RES_PARATR_NUMRULE, sal_False ) ) ) 1552 { 1553 // einige Sonderbehandlungen fuer Attribute 1554 bRet = 0 != AttrSetHandleHelper::Put( mpAttrSet, *this, rSet ); 1555 } 1556 else 1557 { 1558 SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ), 1559 aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ); 1560 if( 0 != (bRet = 0 != AttrSetHandleHelper::Put_BC( mpAttrSet, *this, rSet, &aOld, &aNew )) ) 1561 { 1562 // einige Sonderbehandlungen fuer Attribute 1563 SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld ); 1564 SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew ); 1565 ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt 1566 } 1567 } 1568 return bRet; 1569 } 1570 1571 // Nimmt den Hint mit nWhich aus dem Delta-Array 1572 1573 1574 sal_Bool SwCntntNode::ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 ) 1575 { 1576 if( !GetpSwAttrSet() ) 1577 return sal_False; 1578 1579 if ( IsInCache() ) 1580 { 1581 SwFrm::GetCache().Delete( this ); 1582 SetInCache( sal_False ); 1583 } 1584 1585 // wenn Modify gelockt ist, werden keine Modifies verschickt 1586 if( IsModifyLocked() ) 1587 { 1588 sal_uInt16 nDel = 0; 1589 if ( !nWhich2 || nWhich2 < nWhich1 ) 1590 { 1591 std::vector<sal_uInt16> aClearWhichIds; 1592 aClearWhichIds.push_back( nWhich1 ); 1593 nDel = ClearItemsFromAttrSet( aClearWhichIds ); 1594 } 1595 else 1596 nDel = AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, nWhich1, nWhich2, 0, 0 ); 1597 1598 if( !GetpSwAttrSet()->Count() ) // leer, dann loeschen 1599 mpAttrSet.reset();//DELETEZ( mpAttrSet ); 1600 return 0 != nDel; 1601 } 1602 1603 // sollte kein gueltiger Bereich definiert sein ? 1604 if( !nWhich2 || nWhich2 < nWhich1 ) 1605 nWhich2 = nWhich1; // dann setze auf 1. Id, nur dieses Item 1606 1607 SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ), 1608 aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ); 1609 sal_Bool bRet = 0 != AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, nWhich1, nWhich2, &aOld, &aNew ); 1610 1611 if( bRet ) 1612 { 1613 SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld ); 1614 SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew ); 1615 ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt 1616 1617 if( !GetpSwAttrSet()->Count() ) // leer, dann loeschen 1618 mpAttrSet.reset();//DELETEZ( mpAttrSet ); 1619 } 1620 return bRet; 1621 } 1622 sal_Bool SwCntntNode::ResetAttr( const SvUShorts& rWhichArr ) 1623 { 1624 if( !GetpSwAttrSet() ) 1625 return sal_False; 1626 1627 if ( IsInCache() ) 1628 { 1629 SwFrm::GetCache().Delete( this ); 1630 SetInCache( sal_False ); 1631 } 1632 1633 // wenn Modify gelockt ist, werden keine Modifies verschickt 1634 sal_uInt16 nDel = 0; 1635 if( IsModifyLocked() ) 1636 { 1637 std::vector<sal_uInt16> aClearWhichIds; 1638 for( sal_uInt16 n = 0, nEnd = rWhichArr.Count(); n < nEnd; ++n ) 1639 aClearWhichIds.push_back( rWhichArr[ n ] ); 1640 1641 nDel = ClearItemsFromAttrSet( aClearWhichIds ); 1642 } 1643 else 1644 { 1645 SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ), 1646 aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ); 1647 1648 for( sal_uInt16 n = 0, nEnd = rWhichArr.Count(); n < nEnd; ++n ) 1649 if( AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, rWhichArr[ n ], &aOld, &aNew )) 1650 ++nDel; 1651 1652 if( nDel ) 1653 { 1654 SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld ); 1655 SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew ); 1656 ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt 1657 } 1658 } 1659 if( !GetpSwAttrSet()->Count() ) // leer, dann loeschen 1660 mpAttrSet.reset();//DELETEZ( mpAttrSet ); 1661 return 0 != nDel ; 1662 } 1663 1664 1665 sal_uInt16 SwCntntNode::ResetAllAttr() 1666 { 1667 if( !GetpSwAttrSet() ) 1668 return 0; 1669 1670 if ( IsInCache() ) 1671 { 1672 SwFrm::GetCache().Delete( this ); 1673 SetInCache( sal_False ); 1674 } 1675 1676 // wenn Modify gelockt ist, werden keine Modifies verschickt 1677 if( IsModifyLocked() ) 1678 { 1679 std::vector<sal_uInt16> aClearWhichIds; 1680 aClearWhichIds.push_back(0); 1681 sal_uInt16 nDel = ClearItemsFromAttrSet( aClearWhichIds ); 1682 if( !GetpSwAttrSet()->Count() ) // leer, dann loeschen 1683 mpAttrSet.reset(); // DELETEZ( mpAttrSet ); 1684 return nDel; 1685 } 1686 1687 SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ), 1688 aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ); 1689 sal_Bool bRet = 0 != AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, 0, &aOld, &aNew ); 1690 1691 if( bRet ) 1692 { 1693 SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld ); 1694 SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew ); 1695 ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt 1696 1697 if( !GetpSwAttrSet()->Count() ) // leer, dann loeschen 1698 mpAttrSet.reset();//DELETEZ( mpAttrSet ); 1699 } 1700 return aNew.Count(); 1701 } 1702 1703 1704 sal_Bool SwCntntNode::GetAttr( SfxItemSet& rSet, sal_Bool bInParent ) const 1705 { 1706 if( rSet.Count() ) 1707 rSet.ClearItem(); 1708 1709 const SwAttrSet& rAttrSet = GetSwAttrSet(); 1710 if( bInParent ) 1711 return rSet.Set( rAttrSet, sal_True ) ? sal_True : sal_False; 1712 1713 rSet.Put( rAttrSet ); 1714 return rSet.Count() ? sal_True : sal_False; 1715 } 1716 1717 sal_uInt16 SwCntntNode::ClearItemsFromAttrSet( const std::vector<sal_uInt16>& rWhichIds ) 1718 { 1719 sal_uInt16 nRet = 0; 1720 if ( 0 == rWhichIds.size() ) 1721 return nRet; 1722 1723 ASSERT( GetpSwAttrSet(), "no item set" ) 1724 SwAttrSet aNewAttrSet( *GetpSwAttrSet() ); 1725 for ( std::vector<sal_uInt16>::const_iterator aIter = rWhichIds.begin(); 1726 aIter != rWhichIds.end(); 1727 ++aIter ) 1728 { 1729 nRet = nRet + aNewAttrSet.ClearItem( *aIter ); 1730 } 1731 if ( nRet ) 1732 AttrSetHandleHelper::GetNewAutoStyle( mpAttrSet, *this, aNewAttrSet ); 1733 1734 return nRet; 1735 } 1736 1737 const SfxPoolItem* SwCntntNode::GetNoCondAttr( sal_uInt16 nWhich, 1738 sal_Bool bInParents ) const 1739 { 1740 const SfxPoolItem* pFnd = 0; 1741 if( pCondColl && pCondColl->GetRegisteredIn() ) 1742 { 1743 if( !GetpSwAttrSet() || ( SFX_ITEM_SET != GetpSwAttrSet()->GetItemState( 1744 nWhich, sal_False, &pFnd ) && bInParents )) 1745 ((SwFmt*)GetRegisteredIn())->GetItemState( nWhich, bInParents, &pFnd ); 1746 } 1747 // --> OD 2005-10-25 #126347# - undo change of issue #i51029# 1748 // Note: <GetSwAttrSet()> returns <mpAttrSet>, if set, otherwise it returns 1749 // the attribute set of the paragraph style, which is valid for the 1750 // content node - see file <node.hxx> 1751 else 1752 // <-- 1753 { 1754 GetSwAttrSet().GetItemState( nWhich, bInParents, &pFnd ); 1755 } 1756 return pFnd; 1757 } 1758 1759 // koennen 2 Nodes zusammengefasst werden ? 1760 // in pIdx kann die 2. Position returnt werden. 1761 int SwCntntNode::CanJoinNext( SwNodeIndex* pIdx ) const 1762 { 1763 const SwNodes& rNds = GetNodes(); 1764 sal_uInt8 nNdType = GetNodeType(); 1765 SwNodeIndex aIdx( *this, 1 ); 1766 1767 const SwNode* pNd = this; 1768 while( aIdx < rNds.Count()-1 && 1769 (( pNd = &aIdx.GetNode())->IsSectionNode() || 1770 ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() ))) 1771 aIdx++; 1772 1773 if( pNd->GetNodeType() != nNdType || rNds.Count()-1 == aIdx.GetIndex() ) 1774 return sal_False; 1775 if( IsTxtNode() ) 1776 { // Do not merge strings if the result exceeds the allowed string length 1777 const SwTxtNode* pTxtNd = static_cast<const SwTxtNode*>(this); 1778 sal_uInt64 nSum = pTxtNd->GetTxt().Len(); 1779 pTxtNd = static_cast<const SwTxtNode*>(pNd); 1780 nSum += pTxtNd->GetTxt().Len(); 1781 if( nSum > STRING_LEN ) 1782 return sal_False; 1783 } 1784 if( pIdx ) 1785 *pIdx = aIdx; 1786 return sal_True; 1787 } 1788 1789 1790 // koennen 2 Nodes zusammengefasst werden ? 1791 // in pIdx kann die 2. Position returnt werden. 1792 int SwCntntNode::CanJoinPrev( SwNodeIndex* pIdx ) const 1793 { 1794 sal_uInt8 nNdType = GetNodeType(); 1795 SwNodeIndex aIdx( *this, -1 ); 1796 1797 const SwNode* pNd = this; 1798 while( aIdx.GetIndex() && 1799 (( pNd = &aIdx.GetNode())->IsSectionNode() || 1800 ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() ))) 1801 aIdx--; 1802 1803 if( pNd->GetNodeType() != nNdType || 0 == aIdx.GetIndex() ) 1804 return sal_False; 1805 if( pIdx ) 1806 *pIdx = aIdx; 1807 return sal_True; 1808 } 1809 1810 1811 //FEATURE::CONDCOLL 1812 1813 1814 void SwCntntNode::SetCondFmtColl( SwFmtColl* pColl ) 1815 { 1816 if( (!pColl && pCondColl) || ( pColl && !pCondColl ) || 1817 ( pColl && pColl != pCondColl->GetRegisteredIn() ) ) 1818 { 1819 SwFmtColl* pOldColl = GetCondFmtColl(); 1820 delete pCondColl; 1821 if( pColl ) 1822 pCondColl = new SwDepend( this, pColl ); 1823 else 1824 pCondColl = 0; 1825 1826 if( GetpSwAttrSet() ) 1827 { 1828 AttrSetHandleHelper::SetParent( mpAttrSet, *this, &GetAnyFmtColl(), GetFmtColl() ); 1829 } 1830 1831 if( !IsModifyLocked() ) 1832 { 1833 SwFmtChg aTmp1( pOldColl ? pOldColl : GetFmtColl() ); 1834 SwFmtChg aTmp2( pColl ? pColl : GetFmtColl() ); 1835 NotifyClients( &aTmp1, &aTmp2 ); 1836 } 1837 if( IsInCache() ) 1838 { 1839 SwFrm::GetCache().Delete( this ); 1840 SetInCache( sal_False ); 1841 } 1842 } 1843 } 1844 1845 1846 sal_Bool SwCntntNode::IsAnyCondition( SwCollCondition& rTmp ) const 1847 { 1848 const SwNodes& rNds = GetNodes(); 1849 { 1850 int nCond = 0; 1851 const SwStartNode* pSttNd = StartOfSectionNode(); 1852 while( pSttNd ) 1853 { 1854 switch( pSttNd->GetNodeType() ) 1855 { 1856 case ND_TABLENODE: nCond = PARA_IN_TABLEBODY; break; 1857 case ND_SECTIONNODE: nCond = PARA_IN_SECTION; break; 1858 1859 default: 1860 switch( pSttNd->GetStartNodeType() ) 1861 { 1862 case SwTableBoxStartNode: 1863 { 1864 nCond = PARA_IN_TABLEBODY; 1865 const SwTableNode* pTblNd = pSttNd->FindTableNode(); 1866 const SwTableBox* pBox; 1867 if( pTblNd && 0 != ( pBox = pTblNd->GetTable(). 1868 GetTblBox( pSttNd->GetIndex() ) ) && pBox && 1869 pBox->IsInHeadline( &pTblNd->GetTable() ) ) 1870 nCond = PARA_IN_TABLEHEAD; 1871 } 1872 break; 1873 case SwFlyStartNode: nCond = PARA_IN_FRAME; break; 1874 case SwFootnoteStartNode: 1875 { 1876 nCond = PARA_IN_FOOTENOTE; 1877 const SwFtnIdxs& rFtnArr = rNds.GetDoc()->GetFtnIdxs(); 1878 const SwTxtFtn* pTxtFtn; 1879 const SwNode* pSrchNd = pSttNd; 1880 1881 for( sal_uInt16 n = 0; n < rFtnArr.Count(); ++n ) 1882 if( 0 != ( pTxtFtn = rFtnArr[ n ])->GetStartNode() && 1883 pSrchNd == &pTxtFtn->GetStartNode()->GetNode() ) 1884 { 1885 if( pTxtFtn->GetFtn().IsEndNote() ) 1886 nCond = PARA_IN_ENDNOTE; 1887 break; 1888 } 1889 } 1890 break; 1891 case SwHeaderStartNode: nCond = PARA_IN_HEADER; break; 1892 case SwFooterStartNode: nCond = PARA_IN_FOOTER; break; 1893 case SwNormalStartNode: break; 1894 } 1895 } 1896 1897 if( nCond ) 1898 { 1899 rTmp.SetCondition( (Master_CollConditions)nCond, 0 ); 1900 return sal_True; 1901 } 1902 pSttNd = pSttNd->GetIndex() 1903 ? pSttNd->StartOfSectionNode() 1904 : 0; 1905 } 1906 } 1907 1908 { 1909 sal_uInt16 nPos; 1910 const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds(); 1911 if( rOutlNds.Count() ) 1912 { 1913 if( !rOutlNds.Seek_Entry( (SwCntntNode*)this, &nPos ) && nPos ) 1914 --nPos; 1915 if( nPos < rOutlNds.Count() && 1916 rOutlNds[ nPos ]->GetIndex() < GetIndex() ) 1917 { 1918 SwTxtNode* pOutlNd = rOutlNds[ nPos ]->GetTxtNode(); 1919 1920 if( pOutlNd->IsOutline()) 1921 { 1922 rTmp.SetCondition( PARA_IN_OUTLINE, pOutlNd->GetAttrOutlineLevel() - 1 ); 1923 return sal_True; 1924 } 1925 } 1926 } 1927 } 1928 1929 return sal_False; 1930 } 1931 1932 1933 void SwCntntNode::ChkCondColl() 1934 { 1935 // zur Sicherheit abfragen 1936 if( RES_CONDTXTFMTCOLL == GetFmtColl()->Which() ) 1937 { 1938 SwCollCondition aTmp( 0, 0, 0 ); 1939 const SwCollCondition* pCColl; 1940 1941 bool bDone = false; 1942 1943 if( IsAnyCondition( aTmp )) 1944 { 1945 pCColl = static_cast<SwConditionTxtFmtColl*>(GetFmtColl()) 1946 ->HasCondition( aTmp ); 1947 1948 if (pCColl) 1949 { 1950 SetCondFmtColl( pCColl->GetTxtFmtColl() ); 1951 bDone = true; 1952 } 1953 } 1954 1955 if (!bDone) 1956 { 1957 if( IsTxtNode() && ((SwTxtNode*)this)->GetNumRule()) 1958 { 1959 // steht in einer Numerierung 1960 // welcher Level? 1961 aTmp.SetCondition( PARA_IN_LIST, 1962 ((SwTxtNode*)this)->GetActualListLevel() ); 1963 pCColl = ((SwConditionTxtFmtColl*)GetFmtColl())-> 1964 HasCondition( aTmp ); 1965 } 1966 else 1967 pCColl = 0; 1968 1969 if( pCColl ) 1970 SetCondFmtColl( pCColl->GetTxtFmtColl() ); 1971 else if( pCondColl ) 1972 SetCondFmtColl( 0 ); 1973 } 1974 } 1975 } 1976 1977 // --> OD 2005-02-21 #i42921# 1978 short SwCntntNode::GetTextDirection( const SwPosition& rPos, 1979 const Point* pPt ) const 1980 { 1981 short nRet = -1; 1982 1983 Point aPt; 1984 if( pPt ) 1985 aPt = *pPt; 1986 1987 // --> OD 2007-01-10 #i72024# 1988 // No format of the frame, because this can cause recursive layout actions 1989 SwFrm* pFrm = getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, &rPos, sal_False ); 1990 // <-- 1991 1992 if ( pFrm ) 1993 { 1994 if ( pFrm->IsVertical() ) 1995 { 1996 if ( pFrm->IsRightToLeft() ) 1997 nRet = FRMDIR_VERT_TOP_LEFT; 1998 else 1999 nRet = FRMDIR_VERT_TOP_RIGHT; 2000 } 2001 else 2002 { 2003 if ( pFrm->IsRightToLeft() ) 2004 nRet = FRMDIR_HORI_RIGHT_TOP; 2005 else 2006 nRet = FRMDIR_HORI_LEFT_TOP; 2007 } 2008 } 2009 2010 2011 return nRet; 2012 } 2013 // <-- 2014 2015 SwOLENodes* SwCntntNode::CreateOLENodesArray( const SwFmtColl& rColl, bool bOnlyWithInvalidSize ) 2016 { 2017 SwOLENodes *pNodes = 0; 2018 SwIterator<SwCntntNode,SwFmtColl> aIter( rColl ); 2019 for( SwCntntNode* pNd = aIter.First(); pNd; pNd = aIter.Next() ) 2020 { 2021 SwOLENode *pONd = pNd->GetOLENode(); 2022 if ( pONd && (!bOnlyWithInvalidSize || pONd->IsOLESizeInvalid()) ) 2023 { 2024 if ( !pNodes ) 2025 pNodes = new SwOLENodes; 2026 pNodes->Insert( pONd, pNodes->Count() ); 2027 } 2028 } 2029 2030 return pNodes; 2031 } 2032 2033 //FEATURE::CONDCOLL 2034 // Metoden aus Node.hxx - erst hier ist der TxtNode bekannt !! 2035 // os: nur fuer ICC, da der zum optimieren zu dumm ist 2036 #ifdef ICC 2037 SwTxtNode *SwNode::GetTxtNode() 2038 { 2039 return ND_TEXTNODE == nNodeType ? (SwTxtNode*)this : 0; 2040 } 2041 const SwTxtNode *SwNode::GetTxtNode() const 2042 { 2043 return ND_TEXTNODE == nNodeType ? (const SwTxtNode*)this : 0; 2044 } 2045 #endif 2046 2047 /* 2048 * Document Interface Access 2049 */ 2050 const IDocumentSettingAccess* SwNode::getIDocumentSettingAccess() const { return GetDoc(); } 2051 const IDocumentDeviceAccess* SwNode::getIDocumentDeviceAccess() const { return GetDoc(); } 2052 const IDocumentMarkAccess* SwNode::getIDocumentMarkAccess() const { return GetDoc()->getIDocumentMarkAccess(); } 2053 const IDocumentRedlineAccess* SwNode::getIDocumentRedlineAccess() const { return GetDoc(); } 2054 const IDocumentStylePoolAccess* SwNode::getIDocumentStylePoolAccess() const { return GetDoc(); } 2055 const IDocumentLineNumberAccess* SwNode::getIDocumentLineNumberAccess() const { return GetDoc(); } 2056 const IDocumentDrawModelAccess* SwNode::getIDocumentDrawModelAccess() const { return GetDoc(); } 2057 const IDocumentLayoutAccess* SwNode::getIDocumentLayoutAccess() const { return GetDoc(); } 2058 IDocumentLayoutAccess* SwNode::getIDocumentLayoutAccess() { return GetDoc(); } 2059 const IDocumentLinksAdministration* SwNode::getIDocumentLinksAdministration() const { return GetDoc(); } 2060 IDocumentLinksAdministration* SwNode::getIDocumentLinksAdministration() { return GetDoc(); } 2061 const IDocumentFieldsAccess* SwNode::getIDocumentFieldsAccess() const { return GetDoc(); } 2062 IDocumentFieldsAccess* SwNode::getIDocumentFieldsAccess() { return GetDoc(); } 2063 IDocumentContentOperations* SwNode::getIDocumentContentOperations() { return GetDoc(); } 2064 IStyleAccess& SwNode::getIDocumentStyleAccess() { return GetDoc()->GetIStyleAccess(); } 2065 // --> OD 2007-10-31 #i83479# 2066 IDocumentListItems& SwNode::getIDocumentListItems() 2067 { 2068 return *GetDoc(); 2069 } 2070 // <-- 2071 2072 sal_Bool SwNode::IsInRedlines() const 2073 { 2074 const SwDoc * pDoc = GetDoc(); 2075 sal_Bool bResult = sal_False; 2076 2077 if (pDoc != NULL) 2078 bResult = pDoc->IsInRedlines(*this); 2079 2080 return bResult; 2081 } 2082