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 <editeng/svxenum.hxx> 32 #include <numrule.hxx> 33 #include <SwNodeNum.hxx> 34 #include <ndtxt.hxx> 35 #include <pam.hxx> 36 #include <stdio.h> 37 // --> OD 2007-10-31 #i83479# 38 #include <IDocumentListItems.hxx> 39 // <-- 40 // --> OD 2010-01-13 #b6912256# 41 //#include <svtools/svstdarr.hxx> 42 #include <doc.hxx> 43 // <-- 44 45 // --> OD 2008-02-19 #refactorlists# 46 SwNodeNum::SwNodeNum( SwTxtNode* pTxtNode ) 47 : SwNumberTreeNode(), 48 mpTxtNode( pTxtNode ), 49 mpNumRule( 0 ) 50 { 51 } 52 53 SwNodeNum::SwNodeNum( SwNumRule* pNumRule ) 54 : SwNumberTreeNode(), 55 mpTxtNode( 0 ), 56 mpNumRule( pNumRule ) 57 { 58 } 59 // <-- 60 61 SwNodeNum::~SwNodeNum() 62 { 63 } 64 65 SwTxtNode * SwNodeNum::GetTxtNode() const 66 { 67 return mpTxtNode; 68 } 69 70 SwNumRule * SwNodeNum::GetNumRule() const 71 { 72 return mpNumRule; 73 } 74 75 void SwNodeNum::ChangeNumRule( SwNumRule& rNumRule ) 76 { 77 ASSERT( GetNumRule() && GetTxtNode(), 78 "<SwNodeNum::ChangeNumRule(..)> - missing list style and/or text node. Serious defect -> please informm OD." ); 79 if ( GetNumRule() && GetTxtNode() ) 80 { 81 GetNumRule()->RemoveTxtNode( *(GetTxtNode()) ); 82 } 83 84 mpNumRule = &rNumRule; 85 86 if ( GetNumRule() && GetTxtNode() ) 87 { 88 GetNumRule()->AddTxtNode( *(GetTxtNode()) ); 89 } 90 } 91 92 SwPosition SwNodeNum::GetPosition() const 93 { 94 ASSERT( GetTxtNode(), 95 "<SwNodeNum::GetPosition()> - no text node set at <SwNodeNum> instance" ); 96 return SwPosition(*mpTxtNode); 97 } 98 99 SwNumberTreeNode * SwNodeNum::Create() const 100 { 101 // --> OD 2008-02-19 #refactorlists# 102 // SwNodeNum * pResult = new SwNodeNum(); 103 // pResult->SetNumRule(mpNumRule); 104 SwNodeNum * pResult = new SwNodeNum( GetNumRule() ); 105 // <-- 106 107 return pResult; 108 } 109 110 // --> OD 2008-02-19 #refactorlists# 111 void SwNodeNum::PreAdd() 112 { 113 ASSERT( GetTxtNode(), 114 "<SwNodeNum::PreAdd()> - no text node set at <SwNodeNum> instance" ); 115 if ( !GetNumRule() && GetTxtNode() ) 116 { 117 mpNumRule = GetTxtNode()->GetNumRule(); 118 } 119 ASSERT( GetNumRule(), 120 "<SwNodeNum::PreAdd()> - no list style set at <SwNodeNum> instance" ); 121 if ( GetNumRule() && GetTxtNode() ) 122 { 123 GetNumRule()->AddTxtNode( *(GetTxtNode()) ); 124 } 125 126 127 { 128 if ( GetTxtNode() && 129 GetTxtNode()->GetNodes().IsDocNodes() ) 130 { 131 GetTxtNode()->getIDocumentListItems().addListItem( *this ); 132 } 133 } 134 } 135 136 void SwNodeNum::PostRemove() 137 { 138 ASSERT( GetTxtNode(), 139 "<SwNodeNum::PostRemove()> - no text node set at <SwNodeNum> instance" ); 140 ASSERT( GetNumRule(), 141 "<SwNodeNum::PostRemove()> - no list style set at <SwNodeNum> instance" ); 142 143 if ( GetTxtNode() ) 144 { 145 GetTxtNode()->getIDocumentListItems().removeListItem( *this ); 146 } 147 148 if ( GetNumRule() ) 149 { 150 if ( GetTxtNode() ) 151 { 152 GetNumRule()->RemoveTxtNode( *(GetTxtNode()) ); 153 } 154 mpNumRule = 0; 155 } 156 } 157 // <-- 158 159 bool SwNodeNum::IsNotifiable() const 160 { 161 bool aResult = true; 162 163 if ( GetTxtNode() ) 164 aResult = GetTxtNode()->IsNotifiable(); 165 166 return aResult; 167 } 168 169 bool SwNodeNum::IsNotificationEnabled() const 170 { 171 bool aResult = true; 172 173 if ( GetTxtNode() ) 174 aResult = GetTxtNode()->IsNotificationEnabled(); 175 176 return aResult; 177 } 178 179 bool SwNodeNum::IsContinuous() const 180 { 181 bool aResult = false; 182 183 // --> OD 2006-04-21 #i64311# 184 if ( GetNumRule() ) 185 { 186 aResult = mpNumRule->IsContinusNum(); 187 } 188 else if ( GetParent() ) 189 { 190 aResult = GetParent()->IsContinuous(); 191 } 192 else 193 { 194 ASSERT( false, "<SwNodeNum::IsContinuous()> - OD debug" ); 195 } 196 // <-- 197 198 return aResult; 199 } 200 201 bool SwNodeNum::IsCounted() const 202 { 203 bool aResult = false; 204 205 if ( GetTxtNode() ) 206 { 207 // --> OD 2006-01-25 #i59559# 208 // <SwTxtNode::IsCounted()> determines, if a text node is counted for numbering 209 // const SwNumFmt * pNumFmt = GetNumFmt(); 210 // if (pNumFmt) 211 // { 212 // sal_Int16 nType = pNumFmt->GetNumberingType(); 213 // if ( nType != SVX_NUM_NUMBER_NONE) 214 // aResult = mpTxtNode->IsCounted(); 215 // } 216 aResult = GetTxtNode()->IsCountedInList(); 217 // <-- 218 } 219 else 220 aResult = SwNumberTreeNode::IsCounted(); 221 222 return aResult; 223 } 224 225 // --> OD 2006-04-26 #i64010# 226 bool SwNodeNum::HasCountedChildren() const 227 { 228 bool bResult = false; 229 230 tSwNumberTreeChildren::iterator aIt; 231 232 for (aIt = mChildren.begin(); aIt != mChildren.end(); aIt++) 233 { 234 SwNodeNum* pChild( dynamic_cast<SwNodeNum*>(*aIt) ); 235 ASSERT( pChild, 236 "<SwNodeNum::HasCountedChildren()> - unexcepted type of child -> please inform OD" ); 237 if ( pChild && 238 ( pChild->IsCountedForNumbering() || 239 pChild->HasCountedChildren() ) ) 240 { 241 bResult = true; 242 243 break; 244 } 245 } 246 247 return bResult; 248 } 249 // <-- 250 // --> OD 2006-04-26 #i64010# 251 bool SwNodeNum::IsCountedForNumbering() const 252 { 253 return IsCounted() && 254 ( IsPhantom() || // phantoms 255 !GetTxtNode() || // root node 256 GetTxtNode()->HasNumber() || // text node 257 GetTxtNode()->HasBullet() ); // text node 258 } 259 // <-- 260 261 262 void SwNodeNum::NotifyNode() 263 { 264 ValidateMe(); 265 266 if (mpTxtNode) 267 { 268 mpTxtNode->NumRuleChgd(); 269 } 270 } 271 272 bool SwNodeNum::LessThan(const SwNumberTreeNode & rNode) const 273 { 274 bool bResult = false; 275 const SwNodeNum & rTmpNode = static_cast<const SwNodeNum &>(rNode); 276 277 if (mpTxtNode == NULL && rTmpNode.mpTxtNode != NULL) 278 bResult = true; 279 else if (mpTxtNode != NULL && rTmpNode.mpTxtNode != NULL) 280 { 281 // --> OD 2007-10-31 #i83479# - refactoring 282 // simplify comparison by comparing the indexes of the text nodes 283 // SwPosition aMyPos(*mpTxtNode); 284 // SwPosition aHisPos(*rTmpNode.mpTxtNode); 285 // bResult = (aMyPos < aHisPos) ? true : false; 286 bResult = ( mpTxtNode->GetIndex() < rTmpNode.mpTxtNode->GetIndex() ) ? true : false; 287 // <-- 288 } 289 290 return bResult; 291 } 292 293 //void SwNodeNum::SetRestart(bool bRestart) 294 //{ 295 // // --> OD 2005-10-19 #126009# 296 // // - improvement: invalidation only, if <IsRestart()> state changes. 297 // const bool bInvalidate( mbRestart != bRestart ); 298 // // <-- 299 // mbRestart = bRestart; 300 301 // // --> OD 2005-10-19 #126009# 302 // if ( bInvalidate ) 303 // { 304 // InvalidateMe(); 305 // NotifyInvalidSiblings(); 306 // } 307 // // <-- 308 //} 309 310 // --> OD 2008-02-25 #refactorlists# 311 bool SwNodeNum::IsRestart() const 312 { 313 bool bIsRestart = false; 314 315 if ( GetTxtNode() ) 316 { 317 bIsRestart = GetTxtNode()->IsListRestart(); 318 } 319 320 return bIsRestart; 321 } 322 // <-- 323 324 //void SwNodeNum::SetStart(SwNumberTree::tSwNumTreeNumber nStart) 325 //{ 326 // // --> OD 2005-10-19 #126009# 327 // // - improvement: invalidation only, if <IsRestart()> state changes. 328 // const bool bInvalidate( mnStart != nStart ); 329 // // <-- 330 // mnStart = nStart; 331 332 // // --> OD 2005-10-19 #126009# 333 // if ( bInvalidate ) 334 // { 335 // InvalidateMe(); 336 // NotifyInvalidSiblings(); 337 // } 338 //} 339 340 bool SwNodeNum::IsCountPhantoms() const 341 { 342 bool bResult = true; 343 344 // --> OD 2006-04-21 #i64311# 345 // phantoms aren't counted in consecutive numbering rules 346 if ( mpNumRule ) 347 bResult = !mpNumRule->IsContinusNum() && 348 mpNumRule->IsCountPhantoms(); 349 else 350 { 351 ASSERT( false, 352 "<SwNodeNum::IsCountPhantoms(): missing numbering rule - please inform OD" ); 353 } 354 // <-- 355 356 return bResult; 357 } 358 359 // --> OD 2008-02-25 #refactorlists# 360 SwNumberTree::tSwNumTreeNumber SwNodeNum::GetStartValue() const 361 //SwNumberTree::tSwNumTreeNumber SwNodeNum::GetStart() const 362 { 363 SwNumberTree::tSwNumTreeNumber aResult = 1; 364 365 if ( IsRestart() && GetTxtNode() ) 366 { 367 aResult = GetTxtNode()->GetActualListStartValue(); 368 } 369 else 370 { 371 SwNumRule * pRule = GetNumRule(); 372 373 if (pRule) 374 { 375 int nLevel = GetParent() ? GetLevelInListTree() : 0; 376 377 if (nLevel >= 0 && nLevel < MAXLEVEL) 378 { 379 const SwNumFmt * pFmt = pRule->GetNumFmt( static_cast<sal_uInt16>(nLevel)); 380 381 if (pFmt) 382 aResult = pFmt->GetStart(); 383 } 384 } 385 } 386 387 return aResult; 388 } 389 390 //String SwNodeNum::ToString() const 391 //{ 392 // String aResult("[ ", RTL_TEXTENCODING_ASCII_US); 393 394 // if (GetTxtNode()) 395 // { 396 // char aBuffer[256]; 397 398 // sprintf(aBuffer, "%p ", GetTxtNode()); 399 400 // aResult += String(aBuffer, RTL_TEXTENCODING_ASCII_US); 401 // aResult += String::CreateFromInt32(GetPosition().nNode.GetIndex()); 402 // } 403 // else 404 // aResult += String("*", RTL_TEXTENCODING_ASCII_US); 405 406 // aResult += String(" ", RTL_TEXTENCODING_ASCII_US); 407 408 // unsigned int nLvl = GetLevel(); 409 // aResult += String::CreateFromInt32(nLvl); 410 411 // aResult += String(": ", RTL_TEXTENCODING_ASCII_US); 412 413 // tNumberVector aNumVector; 414 415 // _GetNumberVector(aNumVector, false); 416 417 // for (unsigned int n = 0; n < aNumVector.size(); n++) 418 // { 419 // if (n > 0) 420 // aResult += String(", ", RTL_TEXTENCODING_ASCII_US); 421 422 // aResult += String::CreateFromInt32(aNumVector[n]); 423 // } 424 425 // if (IsCounted()) 426 //// aResult += String(" counted", RTL_TEXTENCODING_ASCII_US); 427 // aResult += String(" C", RTL_TEXTENCODING_ASCII_US); 428 429 // if (IsRestart()) 430 // { 431 //// aResult += String(" restart(", RTL_TEXTENCODING_ASCII_US); 432 // aResult += String(" R(", RTL_TEXTENCODING_ASCII_US); 433 // aResult += String::CreateFromInt32(GetStart()); 434 // aResult += String(")", RTL_TEXTENCODING_ASCII_US); 435 // } 436 437 // if (! IsValid()) 438 //// aResult += String(" invalid", RTL_TEXTENCODING_ASCII_US); 439 // aResult += String(" I", RTL_TEXTENCODING_ASCII_US); 440 441 // aResult += String(" ]", RTL_TEXTENCODING_ASCII_US); 442 443 // return aResult; 444 //} 445 446 // --> OD 2006-03-07 #131436# 447 void SwNodeNum::HandleNumberTreeRootNodeDelete( SwNodeNum& rNodeNum ) 448 { 449 SwNodeNum* pRootNode = rNodeNum.GetParent() 450 ? dynamic_cast<SwNodeNum*>(rNodeNum.GetRoot()) 451 : &rNodeNum; 452 if ( !pRootNode ) 453 { 454 // no root node -> nothing do. 455 return; 456 } 457 458 // unregister all number tree node entries, which correspond to a text node, 459 // about the deletion of the number tree root node. 460 _UnregisterMeAndChildrenDueToRootDelete( *pRootNode ); 461 } 462 463 void SwNodeNum::_UnregisterMeAndChildrenDueToRootDelete( SwNodeNum& rNodeNum ) 464 { 465 const bool bIsPhantom( rNodeNum.IsPhantom() ); 466 tSwNumberTreeChildren::size_type nAllowedChildCount( 0 ); 467 bool bDone( false ); 468 while ( !bDone && 469 rNodeNum.GetChildCount() > nAllowedChildCount ) 470 { 471 SwNodeNum* pChildNode( dynamic_cast<SwNodeNum*>((*rNodeNum.mChildren.begin())) ); 472 if ( !pChildNode ) 473 { 474 ASSERT( false, 475 "<SwNodeNum::_UnregisterMeAndChildrenDueToRootDelete(..)> - unknown number tree node child" ); 476 ++nAllowedChildCount; 477 continue; 478 } 479 480 // Unregistering the last child of a phantom will destroy the phantom. 481 // Thus <rNodeNum> will be destroyed and access on <rNodeNum> has to 482 // be suppressed. 483 if ( bIsPhantom && rNodeNum.GetChildCount() == 1 ) 484 { 485 bDone = true; 486 } 487 488 _UnregisterMeAndChildrenDueToRootDelete( *pChildNode ); 489 } 490 491 if ( !bIsPhantom ) 492 { 493 SwTxtNode* pTxtNode( rNodeNum.GetTxtNode() ); 494 if ( pTxtNode ) 495 { 496 pTxtNode->RemoveFromList(); 497 // --> OD 2010-01-13 #b6912256# 498 // clear all list attributes and the list style 499 SvUShortsSort aResetAttrsArray; 500 aResetAttrsArray.Insert( RES_PARATR_LIST_ID ); 501 aResetAttrsArray.Insert( RES_PARATR_LIST_LEVEL ); 502 aResetAttrsArray.Insert( RES_PARATR_LIST_ISRESTART ); 503 aResetAttrsArray.Insert( RES_PARATR_LIST_RESTARTVALUE ); 504 aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED ); 505 aResetAttrsArray.Insert( RES_PARATR_NUMRULE ); 506 SwPaM aPam( *pTxtNode ); 507 pTxtNode->GetDoc()->ResetAttrs( aPam, sal_False, 508 &aResetAttrsArray, 509 false ); 510 // <-- 511 } 512 } 513 } 514 // <-- 515 516 // --> OD 2007-09-06 #i81002# 517 const SwNodeNum* SwNodeNum::GetPrecedingNodeNumOf( const SwTxtNode& rTxtNode ) const 518 { 519 const SwNodeNum* pPrecedingNodeNum( 0 ); 520 521 // --> OD 2007-10-31 #i83479# 522 // SwNodeNum aNodeNumForTxtNode; 523 // aNodeNumForTxtNode.SetTxtNode( const_cast<SwTxtNode*>(&rTxtNode) ); 524 SwNodeNum aNodeNumForTxtNode( const_cast<SwTxtNode*>(&rTxtNode) ); 525 // <-- 526 527 pPrecedingNodeNum = dynamic_cast<const SwNodeNum*>( 528 GetRoot() 529 ? GetRoot()->GetPrecedingNodeOf( aNodeNumForTxtNode ) 530 : GetPrecedingNodeOf( aNodeNumForTxtNode ) ); 531 532 return pPrecedingNodeNum; 533 } 534 // <-- 535