1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sw.hxx" 26 27 #include <hintids.hxx> 28 #include <rtl/random.h> 29 #include <tools/resid.hxx> 30 #include <editeng/lrspitem.hxx> 31 #include <ftninfo.hxx> 32 #include <ftnidx.hxx> 33 #include <doc.hxx> 34 #include <IDocumentUndoRedo.hxx> 35 #include <pam.hxx> 36 #include <ndtxt.hxx> 37 #include <doctxm.hxx> // pTOXBaseRing 38 #include <poolfmt.hxx> 39 #include <UndoCore.hxx> 40 #include <UndoRedline.hxx> 41 #include <UndoNumbering.hxx> 42 #include <swundo.hxx> 43 #include <SwUndoFmt.hxx> 44 #include <rolbck.hxx> 45 #include <paratr.hxx> 46 #include <docary.hxx> 47 #include <mvsave.hxx> 48 #include <txtfrm.hxx> 49 #include <pamtyp.hxx> 50 #include <redline.hxx> 51 #include <comcore.hrc> 52 #include <editeng/adjitem.hxx> 53 #include <editeng/frmdiritem.hxx> 54 #include <frmatr.hxx> 55 #include <SwStyleNameMapper.hxx> 56 #include <SwNodeNum.hxx> 57 #include <list.hxx> 58 #include <listfunc.hxx> 59 #include <switerator.hxx> 60 61 #include <map> 62 63 inline sal_uInt8 GetUpperLvlChg( sal_uInt8 nCurLvl, sal_uInt8 nLevel, sal_uInt16 nMask ) 64 { 65 if( 1 < nLevel ) 66 { 67 if( nCurLvl + 1 >= nLevel ) 68 nCurLvl -= nLevel - 1; 69 else 70 nCurLvl = 0; 71 } 72 return static_cast<sal_uInt8>((nMask - 1) & ~(( 1 << nCurLvl ) - 1)); 73 } 74 75 void SwDoc::SetOutlineNumRule( const SwNumRule& rRule ) 76 { 77 if( pOutlineRule ) 78 (*pOutlineRule) = rRule; 79 else 80 { 81 pOutlineRule = new SwNumRule( rRule ); 82 83 AddNumRule(pOutlineRule); // #i36749# 84 } 85 86 pOutlineRule->SetRuleType( OUTLINE_RULE ); 87 // --> OD 2008-07-08 #i91400# 88 pOutlineRule->SetName( String::CreateFromAscii( 89 SwNumRule::GetOutlineRuleName() ), 90 *this); 91 // <-- 92 // --> OD 2006-09-21 #i69522# 93 // assure that the outline numbering rule is an automatic rule 94 pOutlineRule->SetAutoRule( sal_True ); 95 // <-- 96 97 // teste ob die evt. gesetzen CharFormate in diesem Document 98 // definiert sind 99 pOutlineRule->CheckCharFmts( this ); 100 101 // --> OD 2008-05-13 #refactorlists# 102 // notify text nodes, which are registered at the outline style, about the 103 // changed outline style 104 SwNumRule::tTxtNodeList aTxtNodeList; 105 pOutlineRule->GetTxtNodeList( aTxtNodeList ); 106 for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin(); 107 aIter != aTxtNodeList.end(); ++aIter ) 108 { 109 SwTxtNode* pTxtNd = *aIter; 110 pTxtNd->NumRuleChgd(); 111 // --> OD 2009-01-20 #i94152# 112 // assure that list level corresponds to outline level 113 if ( pTxtNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle() && 114 pTxtNd->GetAttrListLevel() != pTxtNd->GetTxtColl()->GetAssignedOutlineStyleLevel() ) 115 { 116 pTxtNd->SetAttrListLevel( pTxtNd->GetTxtColl()->GetAssignedOutlineStyleLevel() ); 117 } 118 // <-- 119 } 120 // <-- 121 122 PropagateOutlineRule(); 123 pOutlineRule->SetInvalidRule(sal_True); 124 UpdateNumRule(); 125 126 // gibt es Fussnoten && gilt Kapitelweises Nummerieren, dann updaten 127 if( GetFtnIdxs().Count() && FTNNUM_CHAPTER == GetFtnInfo().eNum ) 128 GetFtnIdxs().UpdateAllFtn(); 129 130 UpdateExpFlds(NULL, true); 131 132 SetModified(); 133 } 134 135 void SwDoc::PropagateOutlineRule() 136 { 137 for (sal_uInt16 n = 0; n < pTxtFmtCollTbl->Count(); n++) 138 { 139 SwTxtFmtColl *pColl = (*pTxtFmtCollTbl)[n]; 140 141 // if (NO_NUMBERING != pColl->GetOutlineLevel())//#outline level,zhaojianwei 142 if(pColl->IsAssignedToListLevelOfOutlineStyle())//<-end,zhaojianwei 143 { 144 // --> OD 2006-11-20 #i71764# 145 // Check only the list style, which is set at the paragraph style 146 const SwNumRuleItem & rCollRuleItem = pColl->GetNumRule( sal_False ); 147 // <-- 148 149 // --> OD 2006-11-20 #i71764# 150 // Check on document setting OUTLINE_LEVEL_YIELDS_OUTLINE_RULE no longer needed. 151 if ( rCollRuleItem.GetValue().Len() == 0 ) 152 // <-- 153 { 154 SwNumRule * pMyOutlineRule = GetOutlineNumRule(); 155 156 if (pMyOutlineRule) 157 { 158 SwNumRuleItem aNumItem( pMyOutlineRule->GetName() ); 159 160 pColl->SetFmtAttr(aNumItem); 161 } 162 } 163 } 164 } 165 } 166 167 // Hoch-/Runterstufen 168 sal_Bool SwDoc::OutlineUpDown( const SwPaM& rPam, short nOffset ) 169 { 170 if( !GetNodes().GetOutLineNds().Count() || !nOffset ) 171 return sal_False; 172 173 // den Bereich feststellen 174 const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds(); 175 const SwNodePtr pSttNd = (SwNodePtr)&rPam.Start()->nNode.GetNode(); 176 const SwNodePtr pEndNd = (SwNodePtr)&rPam.End()->nNode.GetNode(); 177 sal_uInt16 nSttPos, nEndPos; 178 179 if( !rOutlNds.Seek_Entry( pSttNd, &nSttPos ) && 180 !nSttPos-- ) 181 // wir stehen in keiner "Outline-Section" 182 return sal_False; 183 184 if( rOutlNds.Seek_Entry( pEndNd, &nEndPos ) ) 185 ++nEndPos; 186 187 // jetzt haben wir unseren Bereich im OutlineNodes-Array 188 // dann prufe ersmal, ob nicht unterebenen aufgehoben werden 189 // (Stufung ueber die Grenzen) 190 sal_uInt16 n; 191 192 // so, dann koennen wir: 193 // 1. Vorlagen-Array anlegen 194 SwTxtFmtColl* aCollArr[ MAXLEVEL ]; 195 memset( aCollArr, 0, sizeof( SwTxtFmtColl* ) * MAXLEVEL ); 196 197 for( n = 0; n < pTxtFmtCollTbl->Count(); ++n ) 198 { 199 //sal_uInt8 nLevel = (*pTxtFmtCollTbl)[ n ]->GetOutlineLevel();//#outline level,zhaojianwei 200 //if( nLevel < MAXLEVEL ) 201 // aCollArr[ nLevel ] = (*pTxtFmtCollTbl)[ n ]; 202 if((*pTxtFmtCollTbl)[ n ]->IsAssignedToListLevelOfOutlineStyle()) 203 { 204 const int nLevel = (*pTxtFmtCollTbl)[ n ]->GetAssignedOutlineStyleLevel(); 205 aCollArr[ nLevel ] = (*pTxtFmtCollTbl)[ n ]; 206 }//<-end,zhaojianwei 207 } 208 209 /* --> #111107# */ 210 /* Find the last occupied level (backward). */ 211 for (n = MAXLEVEL - 1; n > 0; n--) 212 { 213 if (aCollArr[n] != 0) 214 break; 215 } 216 217 /* If an occupied level is found, choose next level (which IS 218 unoccupied) until a valid level is found. If no occupied level 219 was found n is 0 and aCollArr[0] is 0. In this case no demoting 220 is possible. */ 221 if (aCollArr[n] != 0) 222 { 223 while (n < MAXLEVEL - 1) 224 { 225 n++; 226 227 SwTxtFmtColl *aTmpColl = 228 GetTxtCollFromPool(static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + n)); 229 230 //if (aTmpColl->GetOutlineLevel() == n)//#outline level,zhaojianwei 231 if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() && 232 aTmpColl->GetAssignedOutlineStyleLevel() == n )//<-end,zhaojianwei 233 { 234 aCollArr[n] = aTmpColl; 235 break; 236 } 237 } 238 } 239 240 /* Find the first occupied level (forward). */ 241 for (n = 0; n < MAXLEVEL - 1; n++) 242 { 243 if (aCollArr[n] != 0) 244 break; 245 } 246 247 /* If an occupied level is found, choose previous level (which IS 248 unoccupied) until a valid level is found. If no occupied level 249 was found n is MAXLEVEL - 1 and aCollArr[MAXLEVEL - 1] is 0. In 250 this case no demoting is possible. */ 251 if (aCollArr[n] != 0) 252 { 253 while (n > 0) 254 { 255 n--; 256 257 SwTxtFmtColl *aTmpColl = 258 GetTxtCollFromPool(static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + n)); 259 260 //if (aTmpColl->GetOutlineLevel() == n)//#outline level,zhaojianwei 261 if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() && 262 aTmpColl->GetAssignedOutlineStyleLevel() == n )//<-end,zhaojianwei 263 { 264 aCollArr[n] = aTmpColl; 265 break; 266 } 267 } 268 } 269 /* <-- #111107# */ 270 271 /* --> #i13747# 272 273 Build a move table that states from which level an outline will 274 275 be moved to which other level. */ 276 277 /* the move table 278 279 aMoveArr[n] = m: replace aCollArr[n] with aCollArr[m] 280 */ 281 int aMoveArr[MAXLEVEL]; 282 int nStep; // step size for searching in aCollArr: -1 or 1 283 int nNum; // amount of steps for stepping in aCollArr 284 285 if (nOffset < 0) 286 { 287 nStep = -1; 288 nNum = -nOffset; 289 } 290 else 291 { 292 nStep = 1; 293 nNum = nOffset; 294 } 295 296 /* traverse aCollArr */ 297 for (n = 0; n < MAXLEVEL; n++) 298 { 299 /* If outline level n has an assigned paragraph style step 300 nNum steps forwards (nStep == 1) or backwards (nStep == 301 -1). One step is to go to the next non-null entry in 302 aCollArr in the selected direction. If nNum steps were 303 possible write the index of the entry found to aCollArr[n], 304 i.e. outline level n will be replaced by outline level 305 aCollArr[n]. 306 307 If outline level n has no assigned paragraph style 308 aMoveArr[n] is set to -1. 309 */ 310 if (aCollArr[n] != NULL) 311 { 312 sal_uInt16 m = n; 313 int nCount = nNum; 314 315 while (nCount > 0 && m + nStep >= 0 && m + nStep < MAXLEVEL) 316 { 317 m = static_cast<sal_uInt16>(m + nStep); 318 319 if (aCollArr[m] != NULL) 320 nCount--; 321 } 322 323 if (nCount == 0) 324 aMoveArr[n] = m; 325 else 326 aMoveArr[n] = -1; 327 328 } 329 else 330 aMoveArr[n] = -1; 331 } 332 333 /* If moving of the outline levels is applicable, i.e. for all 334 outline levels occuring in the document there has to be a valid 335 target outline level implied by aMoveArr. */ 336 bool bMoveApplicable = true; 337 for (n = nSttPos; n < nEndPos; n++) 338 { 339 SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode(); 340 SwTxtFmtColl* pColl = pTxtNd->GetTxtColl(); 341 // int nLevel = pColl->GetOutlineLevel();//#outline level,zhaojianwei 342 // if (aMoveArr[nLevel] == -1) 343 // bMoveApplicable = false; 344 if( pColl->IsAssignedToListLevelOfOutlineStyle() ) 345 { 346 const int nLevel = pColl->GetAssignedOutlineStyleLevel(); 347 if (aMoveArr[nLevel] == -1) 348 bMoveApplicable = false; 349 }//<-end,zhaojianwei 350 // --> OD 2008-12-16 #i70748# 351 // Check on outline level attribute of text node, if text node is 352 // not an outline via a to outline style assigned paragraph style. 353 else 354 { 355 const int nNewOutlineLevel = pTxtNd->GetAttrOutlineLevel() + nOffset; 356 if ( nNewOutlineLevel < 1 || nNewOutlineLevel > MAXLEVEL ) 357 { 358 bMoveApplicable = false; 359 } 360 } 361 // <-- 362 } 363 364 if (! bMoveApplicable ) 365 return sal_False; 366 367 /* <-- #i13747 # */ 368 if (GetIDocumentUndoRedo().DoesUndo()) 369 { 370 GetIDocumentUndoRedo().StartUndo(UNDO_OUTLINE_LR, NULL); 371 SwUndo *const pUndoOLR( new SwUndoOutlineLeftRight( rPam, nOffset ) ); 372 GetIDocumentUndoRedo().AppendUndo(pUndoOLR); 373 } 374 375 // 2. allen Nodes die neue Vorlage zuweisen 376 377 n = nSttPos; 378 while( n < nEndPos) 379 { 380 SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode(); 381 SwTxtFmtColl* pColl = pTxtNd->GetTxtColl(); 382 383 if( pColl->IsAssignedToListLevelOfOutlineStyle() ) 384 { 385 // ASSERT(pColl->GetOutlineLevel() < MAXLEVEL, //#outline level,removed by zhaojianwei 386 // "non outline node in outline nodes?"); 387 //int nLevel = pColl->GetOutlineLevel(); 388 const int nLevel = pColl->GetAssignedOutlineStyleLevel();//#outline level,add by zhaojianwei 389 390 ASSERT(aMoveArr[nLevel] >= 0, 391 "move table: current TxtColl not found when building table!"); 392 393 394 if (nLevel < MAXLEVEL && aMoveArr[nLevel] >= 0) 395 { 396 pColl = aCollArr[ aMoveArr[nLevel] ]; 397 398 if (pColl != NULL) 399 pColl = (SwTxtFmtColl*)pTxtNd->ChgFmtColl( pColl ); 400 } 401 402 } 403 else if( pTxtNd->GetAttrOutlineLevel() > 0) //#outline level,add by zhaojianwei 404 { 405 int nLevel = pTxtNd->GetAttrOutlineLevel() + nOffset; 406 if( 0 <= nLevel && nLevel <= MAXLEVEL) 407 pTxtNd->SetAttrOutlineLevel( nLevel ); 408 409 }//<-end,zhaojianwei 410 411 n++; 412 // Undo ??? 413 } 414 if (GetIDocumentUndoRedo().DoesUndo()) 415 { 416 GetIDocumentUndoRedo().EndUndo(UNDO_OUTLINE_LR, NULL); 417 } 418 419 ChkCondColls(); 420 SetModified(); 421 422 return sal_True; 423 } 424 425 426 427 // Hoch-/Runter - Verschieben ! 428 sal_Bool SwDoc::MoveOutlinePara( const SwPaM& rPam, short nOffset ) 429 { 430 // kein Verschiebung in den Sonderbereichen 431 const SwPosition& rStt = *rPam.Start(), 432 & rEnd = &rStt == rPam.GetPoint() ? *rPam.GetMark() 433 : *rPam.GetPoint(); 434 if( !GetNodes().GetOutLineNds().Count() || !nOffset || 435 (rStt.nNode.GetIndex() < GetNodes().GetEndOfExtras().GetIndex()) || 436 (rEnd.nNode.GetIndex() < GetNodes().GetEndOfExtras().GetIndex())) 437 { 438 return sal_False; 439 } 440 441 sal_uInt16 nAktPos = 0; 442 SwNodeIndex aSttRg( rStt.nNode ), aEndRg( rEnd.nNode ); 443 444 //sal_uInt8 nOutLineLevel = NO_NUMBERING; //#outline level,zhaojianwei 445 int nOutLineLevel = MAXLEVEL; //<-end,zhaojianwei 446 SwNode* pSrch = &aSttRg.GetNode(); 447 //if( pSrch->IsTxtNode() ) //#outline level,zhaojianwei 448 // nOutLineLevel = static_cast<sal_uInt8>(((SwTxtNode*)pSrch)->GetOutlineLevel()); 449 if( pSrch->IsTxtNode()) 450 nOutLineLevel = static_cast<sal_uInt8>(((SwTxtNode*)pSrch)->GetAttrOutlineLevel()-1);//<-end,zhaojianwei 451 SwNode* pEndSrch = &aEndRg.GetNode(); 452 if( !GetNodes().GetOutLineNds().Seek_Entry( pSrch, &nAktPos ) ) 453 { 454 if( !nAktPos ) 455 return sal_False; // Promoting or demoting before the first outline => no. 456 if( --nAktPos ) 457 aSttRg = *GetNodes().GetOutLineNds()[ nAktPos ]; 458 else if( 0 > nOffset ) 459 return sal_False; // Promoting at the top of document?! 460 else 461 aSttRg = *GetNodes().GetEndOfContent().StartOfSectionNode(); 462 } 463 sal_uInt16 nTmpPos = 0; 464 // If the given range ends at an outlined text node we have to decide if it has to be a part of 465 // the moving range or not. Normally it will be a sub outline of our chapter 466 // and has to be moved, too. But if the chapter ends with a table(or a section end), 467 // the next text node will be choosen and this could be the next outline of the same level. 468 // The criteria has to be the outline level: sub level => incorporate, same/higher level => no. 469 if( GetNodes().GetOutLineNds().Seek_Entry( pEndSrch, &nTmpPos ) ) 470 { 471 if( !pEndSrch->IsTxtNode() || pEndSrch == pSrch || 472 //nOutLineLevel < ((SwTxtNode*)pEndSrch)->GetOutlineLevel() )//#outline level,zhaojianwei 473 nOutLineLevel < ((SwTxtNode*)pEndSrch)->GetAttrOutlineLevel()-1 )//<-end,zhaojianwei 474 ++nTmpPos; // For sub outlines only! 475 } 476 477 aEndRg = nTmpPos < GetNodes().GetOutLineNds().Count() 478 ? *GetNodes().GetOutLineNds()[ nTmpPos ] 479 : GetNodes().GetEndOfContent(); 480 if( nOffset >= 0 ) 481 nAktPos = nTmpPos; 482 if( aEndRg == aSttRg ) 483 { 484 ASSERT( false, "Moving outlines: Surprising selection" ); 485 aEndRg++; 486 } 487 488 const SwNode* pNd; 489 // The following code corrects the range to handle sections (start/end nodes) 490 // The range will be extended if the least node before the range is a start node 491 // which ends inside the range => The complete section will be moved. 492 // The range will be shrinked if the last position is a start node. 493 // The range will be shrinked if the last node is an end node which starts before the range. 494 aSttRg--; 495 while( aSttRg.GetNode().IsStartNode() ) 496 { 497 pNd = aSttRg.GetNode().EndOfSectionNode(); 498 if( pNd->GetIndex() >= aEndRg.GetIndex() ) 499 break; 500 aSttRg--; 501 } 502 aSttRg++; 503 504 aEndRg--; 505 while( aEndRg.GetNode().IsStartNode() ) 506 aEndRg--; 507 while( aEndRg.GetNode().IsEndNode() ) 508 { 509 pNd = aEndRg.GetNode().StartOfSectionNode(); 510 if( pNd->GetIndex() >= aSttRg.GetIndex() ) 511 break; 512 aEndRg--; 513 } 514 aEndRg++; 515 516 // calculation of the new position 517 if( nOffset < 0 && nAktPos < sal_uInt16(-nOffset) ) 518 pNd = GetNodes().GetEndOfContent().StartOfSectionNode(); 519 else if( nAktPos + nOffset >= GetNodes().GetOutLineNds().Count() ) 520 pNd = &GetNodes().GetEndOfContent(); 521 else 522 pNd = GetNodes().GetOutLineNds()[ nAktPos + nOffset ]; 523 524 sal_uLong nNewPos = pNd->GetIndex(); 525 526 // And now a correction of the insert position if necessary... 527 SwNodeIndex aInsertPos( *pNd, -1 ); 528 while( aInsertPos.GetNode().IsStartNode() ) 529 { 530 // Just before the insert position starts a section: 531 // when I'm moving forward I do not want to enter the section, 532 // when I'm moving backward I want to stay in the section if I'm already a part of, 533 // I want to stay outside if I was outside before. 534 if( nOffset < 0 ) 535 { 536 pNd = aInsertPos.GetNode().EndOfSectionNode(); 537 if( pNd->GetIndex() >= aEndRg.GetIndex() ) 538 break; 539 } 540 aInsertPos--; 541 --nNewPos; 542 } 543 if( nOffset >= 0 ) 544 { 545 // When just before the insert position a section ends, it is okay when I'm moving backward 546 // because I want to stay outside the section. 547 // When moving forward I've to check if I started inside or outside the section 548 // because I don't want to enter of leave such a section 549 while( aInsertPos.GetNode().IsEndNode() ) 550 { 551 pNd = aInsertPos.GetNode().StartOfSectionNode(); 552 if( pNd->GetIndex() >= aSttRg.GetIndex() ) 553 break; 554 aInsertPos--; 555 --nNewPos; 556 } 557 } 558 // We do not want to move into tables (at the moment) 559 aInsertPos++; 560 pNd = &aInsertPos.GetNode(); 561 if( pNd->IsTableNode() ) 562 pNd = pNd->StartOfSectionNode(); 563 if( pNd->FindTableNode() ) 564 return sal_False; 565 566 ASSERT( aSttRg.GetIndex() > nNewPos || nNewPos >= aEndRg.GetIndex(), 567 "Position liegt im MoveBereich" ); 568 569 // wurde ein Position in den Sonderbereichen errechnet, dann 570 // setze die Position auf den Dokumentanfang. 571 // Sollten da Bereiche oder Tabellen stehen, so werden sie nach 572 // hinten verschoben. 573 nNewPos = Max( nNewPos, GetNodes().GetEndOfExtras().GetIndex() + 2 ); 574 575 long nOffs = nNewPos - ( 0 < nOffset ? aEndRg.GetIndex() : aSttRg.GetIndex()); 576 SwPaM aPam( aSttRg, aEndRg, 0, -1 ); 577 return MoveParagraph( aPam, nOffs, sal_True ); 578 } 579 580 581 sal_uInt16 lcl_FindOutlineName( const SwNodes& rNds, const String& rName, 582 sal_Bool bExact ) 583 { 584 sal_uInt16 nSavePos = USHRT_MAX; 585 const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds(); 586 for( sal_uInt16 n = 0; n < rOutlNds.Count(); ++n ) 587 { 588 SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode(); 589 String sTxt( pTxtNd->GetExpandTxt() ); 590 if( sTxt.Equals( rName ) ) 591 { 592 // "exact" gefunden, setze Pos auf den Node 593 nSavePos = n; 594 break; 595 } 596 else if( !bExact && USHRT_MAX == nSavePos && 597 COMPARE_EQUAL == sTxt.CompareTo( rName, rName.Len()) ) 598 { 599 // dann vielleicht nur den den 1.Teil vom Text gefunden 600 nSavePos = n; 601 } 602 } 603 604 return nSavePos; 605 } 606 607 608 609 sal_uInt16 lcl_FindOutlineNum( const SwNodes& rNds, String& rName ) 610 { 611 // Gueltig Nummern sind (immer nur Offsets!!!): 612 // ([Nummer]+\.)+ (als regulaerer Ausdruck!) 613 // (Nummer gefolgt von Punkt, zum 5 Wiederholungen) 614 // also: "1.1.", "1.", "1.1.1." 615 xub_StrLen nPos = 0; 616 String sNum = rName.GetToken( 0, '.', nPos ); 617 if( STRING_NOTFOUND == nPos ) 618 return USHRT_MAX; // ungueltige Nummer!!! 619 620 sal_uInt16 nLevelVal[ MAXLEVEL ]; // Nummern aller Levels 621 memset( nLevelVal, 0, MAXLEVEL * sizeof( nLevelVal[0] )); 622 sal_uInt8 nLevel = 0; 623 String sName( rName ); 624 625 while( STRING_NOTFOUND != nPos ) 626 { 627 sal_uInt16 nVal = 0; 628 sal_Unicode c; 629 for( sal_uInt16 n = 0; n < sNum.Len(); ++n ) 630 if( '0' <= ( c = sNum.GetChar( n )) && c <= '9' ) 631 { 632 nVal *= 10; nVal += c - '0'; 633 } 634 else if( nLevel ) 635 break; // "fast" gueltige Nummer 636 else 637 return USHRT_MAX; // ungueltige Nummer!!! 638 639 if( MAXLEVEL > nLevel ) 640 nLevelVal[ nLevel++ ] = nVal; 641 642 sName.Erase( 0, nPos ); 643 nPos = 0; 644 sNum = sName.GetToken( 0, '.', nPos ); 645 // #i4533# without this check all parts delimited by a dot are treated as outline numbers 646 if(!ByteString(sNum, gsl_getSystemTextEncoding()).IsNumericAscii()) 647 nPos = STRING_NOTFOUND; 648 } 649 rName = sName; // das ist der nachfolgende Text. 650 651 // alle Levels gelesen, dann suche mal im Document nach dieser 652 // Gliederung: 653 const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds(); 654 // OS: ohne OutlineNodes lohnt die Suche nicht 655 // und man spart sich einen Absturz #42958# 656 if(!rOutlNds.Count()) 657 return USHRT_MAX; 658 SwTxtNode* pNd; 659 nPos = 0; 660 //search in the existing outline nodes for the required outline num array 661 for( ; nPos < rOutlNds.Count(); ++nPos ) 662 { 663 pNd = rOutlNds[ nPos ]->GetTxtNode(); 664 //sal_uInt8 nLvl = pNd->GetTxtColl()->GetOutlineLevel(); //#outline level,zhaojianwei 665 const int nLvl = pNd->GetAttrOutlineLevel()-1; //<-end,zhaojianwei 666 if( nLvl == nLevel - 1) 667 { 668 // check for the outline num 669 // --> OD 2005-11-02 #i51089 - TUNING# 670 // --> OD 2006-09-22 #i68289# 671 // Assure, that text node has the correct numbering level. Otherwise, 672 // its number vector will not fit to the searched level. 673 // if ( pNd->GetNum() ) 674 if ( pNd->GetNum() && 675 pNd->GetActualListLevel() == ( nLevel - 1 ) ) 676 // <-- 677 { 678 const SwNodeNum & rNdNum = *(pNd->GetNum()); 679 SwNumberTree::tNumberVector aLevelVal = rNdNum.GetNumberVector(); 680 //now compare with the one searched for 681 bool bEqual = true; 682 for( sal_uInt8 n = 0; (n < nLevel) && bEqual; ++n ) 683 { 684 bEqual = aLevelVal[n] == nLevelVal[n]; 685 } 686 if(bEqual) 687 { 688 break; 689 } 690 } 691 else 692 { 693 // --> OD 2006-01-12 #126588# 694 // A text node, which has an outline paragraph style applied and 695 // has as hard attribute 'no numbering' set, has an outline level, 696 // but no numbering tree node. Thus, consider this situation in 697 // the assertion condition. 698 ASSERT( !pNd->GetNumRule(), 699 "<lcl_FindOutlineNum(..)> - text node with outline level and numbering rule, but without numbering tree node. This is a serious defect -> inform OD" ); 700 } 701 } 702 } 703 if( nPos >= rOutlNds.Count() ) 704 nPos = USHRT_MAX; 705 return nPos; 706 } 707 708 // zu diesem Gliederungspunkt 709 710 711 // JP 13.06.96: 712 // im Namen kann eine Nummer oder/und der Text stehen. 713 // zuerst wird ueber die Nummer versucht den richtigen Eintrag zu finden. 714 // Gibt es diesen, dann wird ueber den Text verglichen, od es der 715 // gewuenschte ist. Ist das nicht der Fall, wird noch mal nur ueber den 716 // Text gesucht. Wird dieser gefunden ist es der Eintrag. Ansonsten der, 717 // der ueber die Nummer gefunden wurde. 718 // Ist keine Nummer angegeben, dann nur den Text suchen. 719 720 sal_Bool SwDoc::GotoOutline( SwPosition& rPos, const String& rName ) const 721 { 722 if( rName.Len() ) 723 { 724 const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds(); 725 726 // 1. Schritt: ueber die Nummer: 727 String sName( rName ); 728 sal_uInt16 nFndPos = ::lcl_FindOutlineNum( GetNodes(), sName ); 729 if( USHRT_MAX != nFndPos ) 730 { 731 SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode(); 732 String sExpandedText = pNd->GetExpandTxt(); 733 //#i4533# leading numbers followed by a dot have been remove while 734 //searching for the outline position 735 //to compensate this they must be removed from the paragraphs text content, too 736 sal_uInt16 nPos = 0; 737 String sTempNum; 738 while(sExpandedText.Len() && (sTempNum = sExpandedText.GetToken(0, '.', nPos)).Len() && 739 STRING_NOTFOUND != nPos && 740 ByteString(sTempNum, gsl_getSystemTextEncoding()).IsNumericAscii()) 741 { 742 sExpandedText.Erase(0, nPos); 743 nPos = 0; 744 } 745 746 if( !sExpandedText.Equals( sName ) ) 747 { 748 sal_uInt16 nTmp = ::lcl_FindOutlineName( GetNodes(), sName, sal_True ); 749 if( USHRT_MAX != nTmp ) // ueber den Namen gefunden 750 { 751 nFndPos = nTmp; 752 pNd = rOutlNds[ nFndPos ]->GetTxtNode(); 753 } 754 } 755 rPos.nNode = *pNd; 756 rPos.nContent.Assign( pNd, 0 ); 757 return sal_True; 758 } 759 760 nFndPos = ::lcl_FindOutlineName( GetNodes(), rName, sal_False ); 761 if( USHRT_MAX != nFndPos ) 762 { 763 SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode(); 764 rPos.nNode = *pNd; 765 rPos.nContent.Assign( pNd, 0 ); 766 return sal_True; 767 } 768 769 // --> OD 2006-09-22 #i68289# 770 // additional search on hyperlink URL without its outline numbering part 771 if ( !sName.Equals( rName ) ) 772 { 773 nFndPos = ::lcl_FindOutlineName( GetNodes(), sName, sal_False ); 774 if( USHRT_MAX != nFndPos ) 775 { 776 SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode(); 777 rPos.nNode = *pNd; 778 rPos.nContent.Assign( pNd, 0 ); 779 return sal_True; 780 } 781 } 782 // <-- 783 } 784 return sal_False; 785 } 786 787 /* */ 788 789 // --- Nummerierung ----------------------------------------- 790 791 // --> OD 2008-02-19 #refactorlists# 792 //void SwNumRuleInfo::MakeList( SwDoc& rDoc, sal_Bool ) 793 //{ 794 // SwNumRule* pRule = rDoc.FindNumRulePtr(rName); 795 796 // // no rule, no fun. 797 // if ( !pRule ) 798 // return; 799 800 // // 801 // // 1. Case: Information already available at pRule: 802 // // 803 // if (pRule->GetTxtNodeList()) 804 // { 805 // // copy list to own pList pointer: 806 // aList = *pRule->GetTxtNodeList(); 807 // return; 808 // } 809 810 // // 811 // // 2. Case: Information has to be generated from scratch: 812 // // 813 814 // if (pRule->IsOutlineRule()) 815 // { 816 // const SwOutlineNodes & rOutlineNodes = rDoc.GetNodes().GetOutLineNds(); 817 818 // for (sal_uInt16 i = 0; i < rOutlineNodes.Count(); ++i) 819 // { 820 // SwTxtNode & aNode = *((SwTxtNode *) rOutlineNodes[i]); 821 822 // if (pRule == aNode.GetNumRule()) 823 // AddNode(aNode); 824 // } 825 // } 826 // { 827 // SwModify* pMod; 828 // const SfxPoolItem* pItem; 829 // sal_uInt16 i, nMaxItems = rDoc.GetAttrPool().GetItemCount 830 // ( RES_PARATR_NUMRULE); 831 // for( i = 0; i < nMaxItems; ++i ) 832 // { 833 // pItem = rDoc.GetAttrPool().GetItem( RES_PARATR_NUMRULE, i ); 834 // if( 0 != pItem) 835 // { 836 // pMod = (SwModify*)((SwNumRuleItem*)pItem)->GetDefinedIn(); 837 // if (0 != pMod && 838 // ((SwNumRuleItem*)pItem)->GetValue().Len() && 839 // ((SwNumRuleItem*)pItem)->GetValue() == rName ) 840 // { 841 // if( pMod->IsA( TYPE( SwFmt )) ) 842 // pMod->GetInfo( *this ); 843 // else 844 // { 845 // SwTxtNode* pModTxtNode = (SwTxtNode*)pMod; 846 847 // // #115901# 848 // if( pModTxtNode->GetNodes().IsDocNodes()) 849 // { 850 // AddNode( *pModTxtNode ); 851 // } 852 // } 853 // } 854 // } 855 // } 856 // } 857 858 // // --> FME 2004-11-03 #i36571# The numrule and this info structure should 859 // // have different instances of the list: 860 // // --> OD 2006-09-12 #i69145# 861 // // method <SwNumRule::SetList(..)> copies content of list provided by the parameter 862 // pRule->SetTxtNodeList( aList ); 863 // // <-- 864 //} 865 // <-- 866 867 868 void lcl_ChgNumRule( SwDoc& rDoc, const SwNumRule& rRule ) 869 { 870 SwNumRule* pOld = rDoc.FindNumRulePtr( rRule.GetName() ); 871 ASSERT( pOld, "ohne die alte NumRule geht gar nichts" ); 872 873 sal_uInt16 nChgFmtLevel = 0, nMask = 1; 874 sal_uInt8 n; 875 876 for( n = 0; n < MAXLEVEL; ++n, nMask <<= 1 ) 877 { 878 const SwNumFmt& rOldFmt = pOld->Get( n ), 879 & rNewFmt = rRule.Get( n ); 880 881 if( rOldFmt != rNewFmt ) 882 { 883 nChgFmtLevel |= nMask; 884 } 885 else if( SVX_NUM_NUMBER_NONE > rNewFmt.GetNumberingType() && 1 < rNewFmt.GetIncludeUpperLevels() && 886 0 != (nChgFmtLevel & GetUpperLvlChg( n, rNewFmt.GetIncludeUpperLevels(),nMask )) ) 887 nChgFmtLevel |= nMask; 888 } 889 890 if( !nChgFmtLevel ) // es wurde nichts veraendert? 891 { 892 // --> OD 2006-04-27 #i64311# 893 const bool bInvalidateNumRule( pOld->IsContinusNum() != rRule.IsContinusNum() ); 894 // <-- 895 pOld->CheckCharFmts( &rDoc ); 896 pOld->SetContinusNum( rRule.IsContinusNum() ); 897 // --> OD 2008-06-17 #i87166# 898 // Do NOT change list style type 899 // pOld->SetRuleType( rRule.GetRuleType() ); 900 // <-- 901 // --> OD 2006-04-27 #i64311# 902 if ( bInvalidateNumRule ) 903 { 904 pOld->SetInvalidRule(sal_True); 905 } 906 // <-- 907 return ; 908 } 909 910 // --> OD 2008-02-19 #refactorlists# 911 // SwNumRuleInfo* pUpd = new SwNumRuleInfo( rRule.GetName() ); 912 // pUpd->MakeList( rDoc ); 913 914 // sal_uInt8 nLvl; 915 // for( sal_uLong nFirst = 0, nLast = pUpd->GetList().Count(); 916 // nFirst < nLast; ++nFirst ) 917 // { 918 // SwTxtNode* pTxtNd = pUpd->GetList().GetObject( nFirst ); 919 // nLvl = static_cast<sal_uInt8>(pTxtNd->GetLevel()); 920 921 // if( nLvl < MAXLEVEL ) 922 // { 923 // if( nChgFmtLevel & ( 1 << nLvl )) 924 // { 925 // pTxtNd->NumRuleChgd(); 926 // } 927 // } 928 // } 929 SwNumRule::tTxtNodeList aTxtNodeList; 930 pOld->GetTxtNodeList( aTxtNodeList ); 931 sal_uInt8 nLvl( 0 ); 932 for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin(); 933 aIter != aTxtNodeList.end(); ++aIter ) 934 { 935 SwTxtNode* pTxtNd = *aIter; 936 nLvl = static_cast<sal_uInt8>(pTxtNd->GetActualListLevel()); 937 938 if( nLvl < MAXLEVEL ) 939 { 940 if( nChgFmtLevel & ( 1 << nLvl )) 941 { 942 pTxtNd->NumRuleChgd(); 943 } 944 } 945 } 946 // <-- 947 948 for( n = 0; n < MAXLEVEL; ++n ) 949 if( nChgFmtLevel & ( 1 << n )) 950 pOld->Set( n, rRule.GetNumFmt( n )); 951 952 pOld->CheckCharFmts( &rDoc ); 953 pOld->SetInvalidRule(sal_True); 954 pOld->SetContinusNum( rRule.IsContinusNum() ); 955 // --> OD 2008-06-17 #i87166# 956 // Do NOT change list style type 957 // pOld->SetRuleType( rRule.GetRuleType() ); 958 // <-- 959 960 // --> OD 2008-02-19 #refactorlists# 961 // delete pUpd; 962 // <-- 963 964 rDoc.UpdateNumRule(); 965 } 966 967 // OD 2008-02-08 #newlistlevelattrs# - add handling of parameter <bResetIndentAttrs> 968 // --> OD 2008-03-17 #refactorlists# 969 void SwDoc::SetNumRule( const SwPaM& rPam, 970 const SwNumRule& rRule, 971 const bool bCreateNewList, 972 const String sContinuedListId, 973 sal_Bool bSetItem, 974 const bool bResetIndentAttrs ) 975 { 976 SwUndoInsNum * pUndo = NULL; 977 if (GetIDocumentUndoRedo().DoesUndo()) 978 { 979 // Start/End for attributes! 980 GetIDocumentUndoRedo().StartUndo( UNDO_INSNUM, NULL ); 981 pUndo = new SwUndoInsNum( rPam, rRule ); 982 GetIDocumentUndoRedo().AppendUndo(pUndo); 983 } 984 985 SwNumRule * pNew = FindNumRulePtr( rRule.GetName() ); 986 bool bUpdateRule = false; 987 988 if( !pNew ) 989 { 990 pNew = (*pNumRuleTbl)[ MakeNumRule( rRule.GetName(), &rRule ) ]; 991 } 992 else if (rRule != *pNew) 993 { 994 bUpdateRule = true; 995 } 996 997 if (bUpdateRule) 998 { 999 if( pUndo ) 1000 { 1001 pUndo->SaveOldNumRule( *pNew ); 1002 ::lcl_ChgNumRule( *this, rRule ); 1003 pUndo->SetLRSpaceEndPos(); 1004 } 1005 else 1006 { 1007 ::lcl_ChgNumRule( *this, rRule ); 1008 } 1009 } 1010 1011 // --> OD 2008-03-17 #refactorlists# 1012 if ( bSetItem ) 1013 { 1014 if ( bCreateNewList ) 1015 { 1016 String sListId; 1017 if ( !bUpdateRule ) 1018 { 1019 // apply list id of list, which has been created for the new list style 1020 sListId = pNew->GetDefaultListId(); 1021 } 1022 else 1023 { 1024 // create new list and apply its list id 1025 SwList* pNewList = createList( String(), pNew->GetName() ); 1026 ASSERT( pNewList, 1027 "<SwDoc::SetNumRule(..)> - could not create new list. Serious defect -> please inform OD." ); 1028 sListId = pNewList->GetListId(); 1029 } 1030 InsertPoolItem( rPam, 1031 SfxStringItem( RES_PARATR_LIST_ID, sListId ), 0 ); 1032 } 1033 else if ( sContinuedListId.Len() > 0 ) 1034 { 1035 // apply given list id 1036 InsertPoolItem( rPam, 1037 SfxStringItem( RES_PARATR_LIST_ID, sContinuedListId ), 0 ); 1038 } 1039 } 1040 // <-- 1041 1042 if ( ! rPam.HasMark()) 1043 { 1044 SwTxtNode * pTxtNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode(); 1045 // --> OD 2006-10-19 #134160# 1046 // consider case that the PaM doesn't denote a text node - e.g. it denotes a graphic node 1047 if ( pTxtNd ) 1048 { 1049 SwNumRule * pRule = pTxtNd->GetNumRule(); 1050 1051 if (pRule && pRule->GetName() == pNew->GetName()) 1052 { 1053 bSetItem = sal_False; 1054 // --> OD 2008-06-02 #refactorlists# 1055 if ( !pTxtNd->IsInList() ) 1056 { 1057 pTxtNd->AddToList(); 1058 } 1059 // <-- 1060 } 1061 // --> OD 2005-10-26 #b6340308# - only clear numbering attribute at 1062 // text node, if at paragraph style the new numbering rule is found. 1063 else if ( !pRule ) 1064 { 1065 SwTxtFmtColl* pColl = pTxtNd->GetTxtColl(); 1066 if ( pColl ) 1067 { 1068 SwNumRule* pCollRule = FindNumRulePtr(pColl->GetNumRule().GetValue()); 1069 if ( pCollRule && pCollRule->GetName() == pNew->GetName() ) 1070 { 1071 pTxtNd->ResetAttr( RES_PARATR_NUMRULE ); 1072 bSetItem = sal_False; 1073 } 1074 } 1075 } 1076 // <-- 1077 } 1078 // <-- 1079 } 1080 1081 // --> OD 2009-08-18 #i103817# 1082 if ( bSetItem ) 1083 // <-- 1084 { 1085 InsertPoolItem( rPam, SwNumRuleItem( pNew->GetName() ), 0 ); 1086 } 1087 1088 // --> OD 2008-02-08 #newlistlevelattrs# 1089 if ( bResetIndentAttrs && 1090 pNew && pNew->Get( 0 ).GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 1091 { 1092 SvUShortsSort aResetAttrsArray; 1093 aResetAttrsArray.Insert( RES_LR_SPACE ); 1094 // --> OD 2010-10-05 #i114929# 1095 // On a selection setup a corresponding Point-and-Mark in order to get 1096 // the indentation attribute reset on all paragraphs touched by the selection 1097 if ( rPam.HasMark() && 1098 rPam.End()->nNode.GetNode().GetTxtNode() ) 1099 { 1100 SwPaM aPam( rPam.Start()->nNode, 1101 rPam.End()->nNode ); 1102 aPam.Start()->nContent = 0; 1103 aPam.End()->nContent = rPam.End()->nNode.GetNode().GetTxtNode()->Len(); 1104 ResetAttrs( aPam, sal_False, &aResetAttrsArray ); 1105 } 1106 else 1107 { 1108 ResetAttrs( rPam, sal_False, &aResetAttrsArray ); 1109 } 1110 // <-- 1111 } 1112 // <-- 1113 1114 if (GetIDocumentUndoRedo().DoesUndo()) 1115 { 1116 GetIDocumentUndoRedo().EndUndo( UNDO_INSNUM, NULL ); 1117 } 1118 1119 SetModified(); 1120 } 1121 1122 void SwDoc::SetCounted(const SwPaM & rPam, bool bCounted) 1123 { 1124 if ( bCounted ) 1125 { 1126 SvUShortsSort aResetAttrsArray; 1127 aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED ); 1128 // --> OD 2010-10-05 #i114929# 1129 // On a selection setup a corresponding Point-and-Mark in order to get 1130 // the list-is-counted attribute reset on all paragraphs touched by the selection 1131 if ( rPam.HasMark() && 1132 rPam.End()->nNode.GetNode().GetTxtNode() ) 1133 { 1134 SwPaM aPam( rPam.Start()->nNode, 1135 rPam.End()->nNode ); 1136 aPam.Start()->nContent = 0; 1137 aPam.End()->nContent = rPam.End()->nNode.GetNode().GetTxtNode()->Len(); 1138 ResetAttrs( aPam, sal_False, &aResetAttrsArray ); 1139 } 1140 else 1141 { 1142 ResetAttrs( rPam, sal_False, &aResetAttrsArray ); 1143 } 1144 // <-- 1145 } 1146 else 1147 { 1148 InsertPoolItem( rPam, 1149 SfxBoolItem( RES_PARATR_LIST_ISCOUNTED, sal_False ), 0 ); 1150 } 1151 } 1152 1153 void SwDoc::SetNumRuleStart( const SwPosition& rPos, sal_Bool bFlag ) 1154 { 1155 SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode(); 1156 1157 if (pTxtNd) 1158 { 1159 const SwNumRule* pRule = pTxtNd->GetNumRule(); 1160 if( pRule && !bFlag != !pTxtNd->IsListRestart()) 1161 { 1162 if (GetIDocumentUndoRedo().DoesUndo()) 1163 { 1164 SwUndo *const pUndo( new SwUndoNumRuleStart(rPos, bFlag) ); 1165 GetIDocumentUndoRedo().AppendUndo(pUndo); 1166 } 1167 1168 pTxtNd->SetListRestart(bFlag ? true : false); 1169 1170 SetModified(); 1171 } 1172 } 1173 } 1174 1175 void SwDoc::SetNodeNumStart( const SwPosition& rPos, sal_uInt16 nStt ) 1176 { 1177 SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode(); 1178 1179 if (pTxtNd) 1180 { 1181 // --> OD 2008-02-27 #refactorlists# 1182 // const SwNumRule* pRule = pTxtNd->GetNumRule(); 1183 // if( pRule && nStt != pTxtNd->GetListRestartValue() ) 1184 // { 1185 // if( DoesUndo() ) 1186 // { 1187 // ClearRedo(); 1188 // AppendUndo( new SwUndoNumRuleStart( rPos, nStt )); 1189 // } 1190 // } 1191 // pTxtNd->SetListRestartValue(nStt); 1192 1193 // SetModified(); 1194 if ( !pTxtNd->HasAttrListRestartValue() || 1195 pTxtNd->GetAttrListRestartValue() != nStt ) 1196 { 1197 if (GetIDocumentUndoRedo().DoesUndo()) 1198 { 1199 SwUndo *const pUndo( new SwUndoNumRuleStart(rPos, nStt) ); 1200 GetIDocumentUndoRedo().AppendUndo(pUndo); 1201 } 1202 pTxtNd->SetAttrListRestartValue( nStt ); 1203 1204 SetModified(); 1205 } 1206 // <-- 1207 } 1208 } 1209 1210 // loeschen geht nur, wenn die Rule niemand benutzt! 1211 sal_Bool SwDoc::DelNumRule( const String& rName, sal_Bool bBroadcast ) 1212 { 1213 sal_uInt16 nPos = FindNumRule( rName ); 1214 1215 // --> OD 2007-12-17 #151213# 1216 if ( (*pNumRuleTbl)[ nPos ] == GetOutlineNumRule() ) 1217 { 1218 ASSERT( false, 1219 "<SwDoc::DelNumRule(..)> - No deletion of outline list style. This is serious defect - please inform OD" ); 1220 return sal_False; 1221 } 1222 // <-- 1223 1224 if( USHRT_MAX != nPos && !IsUsed( *(*pNumRuleTbl)[ nPos ] )) 1225 { 1226 if (GetIDocumentUndoRedo().DoesUndo()) 1227 { 1228 SwUndo * pUndo = 1229 new SwUndoNumruleDelete(*(*pNumRuleTbl)[nPos], this); 1230 GetIDocumentUndoRedo().AppendUndo(pUndo); 1231 } 1232 1233 if (bBroadcast) 1234 BroadcastStyleOperation(rName, SFX_STYLE_FAMILY_PSEUDO, 1235 SFX_STYLESHEET_ERASED); 1236 1237 // --> OD 2008-04-02 #refactorlists# 1238 deleteListForListStyle( rName ); 1239 { 1240 // delete further list, which have the deleted list style as default list style 1241 std::vector< SwList* > aListsForDeletion; 1242 tHashMapForLists::iterator aListIter = maLists.begin(); 1243 while ( aListIter != maLists.end() ) 1244 { 1245 SwList* pList = (*aListIter).second; 1246 if ( pList->GetDefaultListStyleName() == rName ) 1247 { 1248 aListsForDeletion.push_back( pList ); 1249 } 1250 1251 ++aListIter; 1252 } 1253 while ( aListsForDeletion.size() > 0 ) 1254 { 1255 SwList* pList = aListsForDeletion.back(); 1256 aListsForDeletion.pop_back(); 1257 deleteList( pList->GetListId() ); 1258 } 1259 } 1260 // <-- 1261 // --> FME 2004-11-02 #i34097# DeleteAndDestroy deletes rName if 1262 // rName is directly taken from the numrule. 1263 const String aTmpName( rName ); 1264 // <-- 1265 pNumRuleTbl->DeleteAndDestroy( nPos ); 1266 maNumRuleMap.erase(aTmpName); 1267 1268 SetModified(); 1269 return sal_True; 1270 } 1271 return sal_False; 1272 } 1273 1274 // #106897# 1275 void SwDoc::ChgNumRuleFmts( const SwNumRule& rRule, const String * pName ) 1276 { 1277 // #106897# 1278 SwNumRule* pRule = FindNumRulePtr( pName ? *pName : rRule.GetName() ); 1279 if( pRule ) 1280 { 1281 SwUndoInsNum* pUndo = 0; 1282 if (GetIDocumentUndoRedo().DoesUndo()) 1283 { 1284 pUndo = new SwUndoInsNum( *pRule, rRule ); 1285 pUndo->GetHistory(); 1286 GetIDocumentUndoRedo().AppendUndo( pUndo ); 1287 } 1288 ::lcl_ChgNumRule( *this, rRule ); 1289 1290 if( pUndo ) 1291 pUndo->SetLRSpaceEndPos(); 1292 1293 SetModified(); 1294 } 1295 } 1296 1297 sal_Bool SwDoc::RenameNumRule(const String & rOldName, const String & rNewName, 1298 sal_Bool bBroadcast) 1299 { 1300 sal_Bool bResult = sal_False; 1301 SwNumRule * pNumRule = FindNumRulePtr(rOldName); 1302 1303 if (pNumRule) 1304 { 1305 if (GetIDocumentUndoRedo().DoesUndo()) 1306 { 1307 SwUndo * pUndo = new SwUndoNumruleRename(rOldName, rNewName, this); 1308 GetIDocumentUndoRedo().AppendUndo(pUndo); 1309 } 1310 1311 // --> OD 2008-02-19 #refactorlists# 1312 // SwNumRuleInfo aInfo(rOldName); 1313 // aInfo.MakeList(*this); 1314 SwNumRule::tTxtNodeList aTxtNodeList; 1315 pNumRule->GetTxtNodeList( aTxtNodeList ); 1316 // <-- 1317 1318 // --> OD 2008-07-08 #i91400# 1319 pNumRule->SetName( rNewName, *this ); 1320 // <-- 1321 1322 SwNumRuleItem aItem(rNewName); 1323 // --> OD 2008-02-19 #refactorlists# 1324 // for (sal_uLong nI = 0; nI < aInfo.GetList().Count(); ++nI) 1325 // { 1326 // SwTxtNode * pTxtNd = aInfo.GetList().GetObject(nI); 1327 // pTxtNd->SwCntntNode::SetAttr(aItem); 1328 // } 1329 for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin(); 1330 aIter != aTxtNodeList.end(); ++aIter ) 1331 { 1332 SwTxtNode * pTxtNd = *aIter; 1333 pTxtNd->SetAttr(aItem); 1334 } 1335 // <-- 1336 1337 bResult = sal_True; 1338 1339 if (bBroadcast) 1340 BroadcastStyleOperation(rOldName, SFX_STYLE_FAMILY_PSEUDO, 1341 SFX_STYLESHEET_MODIFIED); 1342 } 1343 1344 return bResult; 1345 } 1346 1347 void SwDoc::StopNumRuleAnimations( OutputDevice* pOut ) 1348 { 1349 for( sal_uInt16 n = GetNumRuleTbl().Count(); n; ) 1350 { 1351 SwNumRule::tTxtNodeList aTxtNodeList; 1352 GetNumRuleTbl()[ --n ]->GetTxtNodeList( aTxtNodeList ); 1353 for ( SwNumRule::tTxtNodeList::iterator aTxtNodeIter = aTxtNodeList.begin(); 1354 aTxtNodeIter != aTxtNodeList.end(); ++aTxtNodeIter ) 1355 { 1356 SwTxtNode* pTNd = *aTxtNodeIter; 1357 SwIterator<SwTxtFrm,SwTxtNode> aIter(*pTNd); 1358 for(SwTxtFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() ) 1359 if( pFrm->HasAnimation() ) 1360 pFrm->StopAnimation( pOut ); 1361 } 1362 } 1363 } 1364 1365 sal_Bool SwDoc::ReplaceNumRule( const SwPosition& rPos, 1366 const String& rOldRule, const String& rNewRule ) 1367 { 1368 sal_Bool bRet = sal_False; 1369 SwNumRule *pOldRule = FindNumRulePtr( rOldRule ), 1370 *pNewRule = FindNumRulePtr( rNewRule ); 1371 if( pOldRule && pNewRule && pOldRule != pNewRule ) 1372 { 1373 // --> OD 2008-02-19 #refactorlists# 1374 SwUndoInsNum* pUndo = 0; 1375 if (GetIDocumentUndoRedo().DoesUndo()) 1376 { 1377 // Start/End for attributes! 1378 GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL ); 1379 pUndo = new SwUndoInsNum( rPos, *pNewRule, rOldRule ); 1380 GetIDocumentUndoRedo().AppendUndo(pUndo); 1381 } 1382 1383 // --> OD 2008-02-19 #refactorlists# 1384 // apply new list style <pNewRule> to all text nodes, which have the 1385 // old list style <pOldNRule> applied and belong to the same list as 1386 // the text node of the given <SwPosition>. 1387 // SwNumRuleInfo aUpd( rOldRule ); 1388 // aUpd.MakeList( *this ); 1389 1390 // if (aUpd.GetList().Count() > 0) // #106897# 1391 SwNumRule::tTxtNodeList aTxtNodeList; 1392 pOldRule->GetTxtNodeList( aTxtNodeList ); 1393 if ( aTxtNodeList.size() > 0 ) 1394 { 1395 // // Position suchen und bestimme ob ein Node davor oder dahinter 1396 // // einen Start erzwingt 1397 // SwTxtNode* pTxtNd; 1398 // sal_uLong nFndPos, nFirst, nLast; 1399 1400 // if( TABLE_ENTRY_NOTFOUND != aUpd.GetList().SearchKey( 1401 // rPos.nNode.GetIndex(), &nFndPos )) 1402 // ++nFndPos; 1403 1404 // for( nLast = nFndPos; nLast < aUpd.GetList().Count(); ++nLast ) 1405 // { 1406 // pTxtNd = aUpd.GetList().GetObject( nLast ); 1407 // if(pTxtNd->IsRestart()) 1408 // break; 1409 // } 1410 // for( nFirst = nFndPos; nFirst; ) 1411 // { 1412 // pTxtNd = aUpd.GetList().GetObject( --nFirst ); 1413 // if( pTxtNd->IsRestart() ) 1414 // break; 1415 // } 1416 // // dann neue Numerierung ueber diesen Bereich 1417 // // definieren und den Start am Anfang/Ende zurueck setzen 1418 // pTxtNd = aUpd.GetList().GetObject( nFirst ); 1419 // if( pTxtNd->IsRestart() ) 1420 // { 1421 // pTxtNd->SetRestart(false); 1422 // if( pUndo ) 1423 // pUndo->SetSttNum( pTxtNd->GetIndex() ); 1424 // } 1425 1426 SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 ); 1427 sal_uInt16 nChgFmtLevel = 0; 1428 for( sal_uInt8 n = 0; n < MAXLEVEL; ++n ) 1429 { 1430 const SwNumFmt& rOldFmt = pOldRule->Get( n ), 1431 & rNewFmt = pNewRule->Get( n ); 1432 1433 if( rOldFmt.GetAbsLSpace() != rNewFmt.GetAbsLSpace() || 1434 rOldFmt.GetFirstLineOffset() != rNewFmt.GetFirstLineOffset() ) 1435 nChgFmtLevel |= ( 1 << n ); 1436 } 1437 1438 const SwTxtNode* pGivenTxtNode = rPos.nNode.GetNode().GetTxtNode(); 1439 SwNumRuleItem aRule( rNewRule ); 1440 // for( ; nFirst < nLast; ++nFirst ) 1441 // { 1442 // pTxtNd = aUpd.GetList().GetObject( nFirst ); 1443 1444 // aRegH.RegisterInModify( pTxtNd, *pTxtNd ); 1445 1446 // pTxtNd->SwCntntNode::SetAttr( aRule ); 1447 // pTxtNd->NumRuleChgd(); 1448 // } 1449 for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin(); 1450 aIter != aTxtNodeList.end(); ++aIter ) 1451 { 1452 SwTxtNode* pTxtNd = *aIter; 1453 1454 if ( pGivenTxtNode && 1455 pGivenTxtNode->GetListId() == pTxtNd->GetListId() ) 1456 { 1457 aRegH.RegisterInModify( pTxtNd, *pTxtNd ); 1458 1459 pTxtNd->SetAttr( aRule ); 1460 pTxtNd->NumRuleChgd(); 1461 } 1462 } 1463 GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL ); 1464 SetModified(); 1465 1466 bRet = sal_True; // #106897# 1467 } 1468 } 1469 1470 return bRet; 1471 } 1472 1473 // --> OD 2008-03-18 #refactorlists# 1474 namespace 1475 { 1476 struct ListStyleData 1477 { 1478 SwNumRule* pReplaceNumRule; 1479 bool bCreateNewList; 1480 String sListId; 1481 1482 ListStyleData() 1483 : pReplaceNumRule( 0 ), 1484 bCreateNewList( false ), 1485 sListId() 1486 {} 1487 }; 1488 } 1489 // <-- 1490 1491 void SwDoc::MakeUniqueNumRules(const SwPaM & rPaM) 1492 { 1493 ASSERT( rPaM.GetDoc() == this, "need same doc" ); 1494 1495 // --> OD 2008-03-18 #refactorlists# 1496 // map<SwNumRule *, SwNumRule *> aMyNumRuleMap; 1497 ::std::map<SwNumRule *, ListStyleData> aMyNumRuleMap; 1498 // <-- 1499 1500 sal_uLong nStt = rPaM.Start()->nNode.GetIndex(); 1501 sal_uLong nEnd = rPaM.End()->nNode.GetIndex(); 1502 1503 bool bFirst = true; 1504 1505 for (sal_uLong n = nStt; n <= nEnd; n++) 1506 { 1507 SwTxtNode * pCNd = GetNodes()[n]->GetTxtNode(); 1508 1509 if (pCNd) 1510 { 1511 SwNumRule * pRule = pCNd->GetNumRule(); 1512 1513 if (pRule && pRule->IsAutoRule() && ! pRule->IsOutlineRule()) 1514 { 1515 // --> OD 2008-03-18 #refactorlists# 1516 // SwNumRule * pReplaceNumRule = aMyNumRuleMap[pRule]; 1517 ListStyleData aListStyleData = aMyNumRuleMap[pRule]; 1518 1519 // if (! pReplaceNumRule) 1520 if ( aListStyleData.pReplaceNumRule == 0 ) 1521 { 1522 if (bFirst) 1523 { 1524 SwPosition aPos(*pCNd); 1525 aListStyleData.pReplaceNumRule = 1526 const_cast<SwNumRule *> 1527 (SearchNumRule( aPos, false, pCNd->HasNumber(), 1528 false, 0, 1529 aListStyleData.sListId, true )); 1530 } 1531 1532 // if (! pReplaceNumRule) 1533 if ( aListStyleData.pReplaceNumRule == 0 ) 1534 { 1535 // pReplaceNumRule = new SwNumRule(*pRule); 1536 // pReplaceNumRule->SetName(GetUniqueNumRuleName()); 1537 aListStyleData.pReplaceNumRule = new SwNumRule(*pRule); 1538 // --> OD 2008-07-08 #i91400# 1539 aListStyleData.pReplaceNumRule->SetName( 1540 GetUniqueNumRuleName(), *this ); 1541 // <-- 1542 aListStyleData.bCreateNewList = true; 1543 } 1544 1545 // aMyNumRuleMap[pRule] = pReplaceNumRule; 1546 aMyNumRuleMap[pRule] = aListStyleData; 1547 } 1548 1549 SwPaM aPam(*pCNd); 1550 1551 SetNumRule( aPam, *aListStyleData.pReplaceNumRule, 1552 aListStyleData.bCreateNewList, 1553 aListStyleData.sListId ); 1554 if ( aListStyleData.bCreateNewList ) 1555 { 1556 aListStyleData.bCreateNewList = false; 1557 aListStyleData.sListId = pCNd->GetListId(); 1558 aMyNumRuleMap[pRule] = aListStyleData; 1559 } 1560 // <-- 1561 1562 bFirst = false; 1563 } 1564 } 1565 } 1566 } 1567 1568 sal_Bool SwDoc::NoNum( const SwPaM& rPam ) 1569 { 1570 1571 sal_Bool bRet = SplitNode( *rPam.GetPoint(), false ); 1572 // ist ueberhaupt Nummerierung im Spiel ? 1573 if( bRet ) 1574 { 1575 // NoNum setzen und Upaten 1576 const SwNodeIndex& rIdx = rPam.GetPoint()->nNode; 1577 SwTxtNode* pNd = rIdx.GetNode().GetTxtNode(); 1578 const SwNumRule* pRule = pNd->GetNumRule(); 1579 if( pRule ) 1580 { 1581 pNd->SetCountedInList(false); 1582 1583 SetModified(); 1584 } 1585 else 1586 bRet = sal_False; // keine Nummerierung , ?? oder immer sal_True ?? 1587 } 1588 return bRet; 1589 } 1590 1591 void SwDoc::DelNumRules( const SwPaM& rPam ) 1592 { 1593 sal_uLong nStt = rPam.GetPoint()->nNode.GetIndex(), 1594 nEnd = rPam.GetMark()->nNode.GetIndex(); 1595 if( nStt > nEnd ) 1596 { 1597 sal_uLong nTmp = nStt; nStt = nEnd; nEnd = nTmp; 1598 } 1599 1600 SwUndoDelNum* pUndo; 1601 if (GetIDocumentUndoRedo().DoesUndo()) 1602 { 1603 pUndo = new SwUndoDelNum( rPam ); 1604 GetIDocumentUndoRedo().AppendUndo(pUndo); 1605 } 1606 else 1607 pUndo = 0; 1608 1609 SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 ); 1610 1611 SwNumRuleItem aEmptyRule( aEmptyStr ); 1612 const SwNode* pOutlNd = 0; 1613 for( ; nStt <= nEnd; ++nStt ) 1614 { 1615 SwTxtNode* pTNd = GetNodes()[ nStt ]->GetTxtNode(); 1616 // --> OD 2008-03-13 #refactorlists# 1617 // if( pTNd && 0 != ( pItem = pTNd->GetNoCondAttr( 1618 // RES_PARATR_NUMRULE, sal_True ) ) && 1619 // ( pName = &((SwNumRuleItem*)pItem)->GetValue())->Len() ) 1620 SwNumRule* pNumRuleOfTxtNode = pTNd ? pTNd->GetNumRule() : 0; 1621 if ( pTNd && pNumRuleOfTxtNode ) 1622 // <-- 1623 { 1624 // recognize changes of attribute for undo 1625 aRegH.RegisterInModify( pTNd, *pTNd ); 1626 1627 if( pUndo ) 1628 pUndo->AddNode( *pTNd, sal_False ); 1629 1630 // directly set list style attribute is reset, otherwise empty 1631 // list style is applied 1632 const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet(); 1633 if ( pAttrSet && 1634 pAttrSet->GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET ) 1635 pTNd->ResetAttr( RES_PARATR_NUMRULE ); 1636 else 1637 pTNd->SetAttr( aEmptyRule ); 1638 1639 // --> OD 2008-03-26 #refactorlists# 1640 pTNd->ResetAttr( RES_PARATR_LIST_ID ); 1641 pTNd->ResetAttr( RES_PARATR_LIST_LEVEL ); 1642 pTNd->ResetAttr( RES_PARATR_LIST_ISRESTART ); 1643 pTNd->ResetAttr( RES_PARATR_LIST_RESTARTVALUE ); 1644 pTNd->ResetAttr( RES_PARATR_LIST_ISCOUNTED ); 1645 // <-- 1646 1647 if( RES_CONDTXTFMTCOLL == pTNd->GetFmtColl()->Which() ) 1648 pTNd->ChkCondColl(); 1649 //else if( !pOutlNd && NO_NUMBERING != //#outline level,zhaojianwei 1650 // ((SwTxtFmtColl*)pTNd->GetFmtColl())->GetOutlineLevel() ) 1651 else if( !pOutlNd && 1652 ((SwTxtFmtColl*)pTNd->GetFmtColl())->IsAssignedToListLevelOfOutlineStyle() )//<-end,zhaojianwei 1653 pOutlNd = pTNd; 1654 } 1655 } 1656 1657 // dann noch alle Updaten 1658 UpdateNumRule(); 1659 1660 if( pOutlNd ) 1661 GetNodes().UpdtOutlineIdx( *pOutlNd ); 1662 } 1663 1664 void SwDoc::InvalidateNumRules() 1665 { 1666 for (sal_uInt16 n = 0; n < pNumRuleTbl->Count(); ++n) 1667 (*pNumRuleTbl)[n]->SetInvalidRule(sal_True); 1668 } 1669 1670 // zum naechsten/vorhergehenden Punkt auf gleicher Ebene 1671 1672 sal_Bool lcl_IsNumOk( sal_uInt8 nSrchNum, sal_uInt8& rLower, sal_uInt8& rUpper, 1673 sal_Bool bOverUpper, sal_uInt8 nNumber ) 1674 { 1675 // --> OD 2008-04-02 #refactorlists# 1676 ASSERT( nNumber < MAXLEVEL, 1677 "<lcl_IsNumOk(..)> - misusage of method" ); 1678 // <-- 1679 1680 sal_Bool bRet = sal_False; 1681 { 1682 if( bOverUpper ? nSrchNum == nNumber : nSrchNum >= nNumber ) 1683 bRet = sal_True; 1684 else if( nNumber > rLower ) 1685 rLower = nNumber; 1686 else if( nNumber < rUpper ) 1687 rUpper = nNumber; 1688 } 1689 return bRet; 1690 } 1691 1692 sal_Bool lcl_IsValidPrevNextNumNode( const SwNodeIndex& rIdx ) 1693 { 1694 sal_Bool bRet = sal_False; 1695 const SwNode& rNd = rIdx.GetNode(); 1696 switch( rNd.GetNodeType() ) 1697 { 1698 case ND_ENDNODE: 1699 bRet = SwTableBoxStartNode == rNd.StartOfSectionNode()->GetStartNodeType() || 1700 rNd.StartOfSectionNode()->IsSectionNode(); 1701 break; 1702 1703 case ND_STARTNODE: 1704 bRet = SwTableBoxStartNode == ((SwStartNode&)rNd).GetStartNodeType(); 1705 break; 1706 1707 case ND_SECTIONNODE: // der ist erlaubt, also weiter 1708 bRet = sal_True; 1709 break; 1710 } 1711 return bRet; 1712 } 1713 1714 sal_Bool lcl_GotoNextPrevNum( SwPosition& rPos, sal_Bool bNext, 1715 sal_Bool bOverUpper, sal_uInt8* pUpper, sal_uInt8* pLower ) 1716 { 1717 const SwTxtNode* pNd = rPos.nNode.GetNode().GetTxtNode(); 1718 const SwNumRule* pRule; 1719 if( !pNd || 0 == ( pRule = pNd->GetNumRule())) 1720 return sal_False; 1721 1722 sal_uInt8 nSrchNum = static_cast<sal_uInt8>(pNd->GetActualListLevel()); 1723 1724 SwNodeIndex aIdx( rPos.nNode ); 1725 if( ! pNd->IsCountedInList() ) 1726 { 1727 // falls gerade mal NO_NUMLEVEL an ist, so such den vorherigen Node 1728 // mit Nummerierung 1729 sal_Bool bError = sal_False; 1730 do { 1731 aIdx--; 1732 if( aIdx.GetNode().IsTxtNode() ) 1733 { 1734 pNd = aIdx.GetNode().GetTxtNode(); 1735 pRule = pNd->GetNumRule(); 1736 1737 sal_uInt8 nTmpNum; 1738 1739 if( pRule ) 1740 { 1741 nTmpNum = static_cast<sal_uInt8>(pNd->GetActualListLevel()); 1742 if( !( ! pNd->IsCountedInList() && 1743 (nTmpNum >= nSrchNum )) ) 1744 break; // gefunden 1745 } 1746 else 1747 bError = sal_True; 1748 } 1749 else 1750 bError = !lcl_IsValidPrevNextNumNode( aIdx ); 1751 1752 } while( !bError ); 1753 if( bError ) 1754 return sal_False; 1755 } 1756 1757 sal_uInt8 nLower = nSrchNum, nUpper = nSrchNum; 1758 sal_Bool bRet = sal_False; 1759 1760 const SwTxtNode* pLast; 1761 if( bNext ) 1762 aIdx++, pLast = pNd; 1763 else 1764 aIdx--, pLast = 0; 1765 1766 while( bNext ? ( aIdx.GetIndex() < aIdx.GetNodes().Count() - 1 ) 1767 : aIdx.GetIndex() ) 1768 { 1769 if( aIdx.GetNode().IsTxtNode() ) 1770 { 1771 pNd = aIdx.GetNode().GetTxtNode(); 1772 pRule = pNd->GetNumRule(); 1773 if( pRule ) 1774 { 1775 if( ::lcl_IsNumOk( nSrchNum, nLower, nUpper, bOverUpper, 1776 static_cast<sal_uInt8>(pNd->GetActualListLevel()) )) 1777 { 1778 rPos.nNode = aIdx; 1779 rPos.nContent.Assign( (SwTxtNode*)pNd, 0 ); 1780 bRet = sal_True; 1781 break; 1782 } 1783 else 1784 pLast = pNd; 1785 } 1786 else 1787 break; 1788 } 1789 else if( !lcl_IsValidPrevNextNumNode( aIdx )) 1790 break; 1791 1792 if( bNext ) 1793 aIdx++; 1794 else 1795 aIdx--; 1796 } 1797 1798 if( !bRet && !bOverUpper && pLast ) // nicht ueber hoehere Nummmern, aber bis Ende 1799 { 1800 if( bNext ) 1801 { 1802 rPos.nNode = aIdx; 1803 if( aIdx.GetNode().IsCntntNode() ) 1804 rPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), 0 ); 1805 } 1806 else 1807 { 1808 rPos.nNode.Assign( *pLast ); 1809 rPos.nContent.Assign( (SwTxtNode*)pLast, 0 ); 1810 } 1811 bRet = sal_True; 1812 } 1813 1814 if( bRet ) 1815 { 1816 if( pUpper ) 1817 *pUpper = nUpper; 1818 if( pLower ) 1819 *pLower = nLower; 1820 } 1821 return bRet; 1822 } 1823 1824 sal_Bool SwDoc::GotoNextNum( SwPosition& rPos, sal_Bool bOverUpper, 1825 sal_uInt8* pUpper, sal_uInt8* pLower ) 1826 { 1827 return ::lcl_GotoNextPrevNum( rPos, sal_True, bOverUpper, pUpper, pLower ); 1828 } 1829 1830 // -> #i23731# 1831 // --> OD 2008-03-18 #refactorlists# - add output parameter <sListId> 1832 const SwNumRule * SwDoc::SearchNumRule(const SwPosition & rPos, 1833 const bool bForward, 1834 const bool bNum, 1835 const bool bOutline, 1836 int nNonEmptyAllowed, 1837 String& sListId, 1838 const bool bInvestigateStartNode) 1839 { 1840 const SwNumRule * pResult = NULL; 1841 SwTxtNode * pTxtNd = rPos.nNode.GetNode().GetTxtNode(); 1842 SwNode * pStartFromNode = pTxtNd; 1843 1844 if (pTxtNd) 1845 { 1846 SwNodeIndex aIdx(rPos.nNode); 1847 1848 // --> OD 2005-10-20 #i55391# 1849 // - the start node has also been investigated, if requested. 1850 const SwNode * pNode = NULL; 1851 do 1852 { 1853 // --> OD 2005-10-20 #i55391# 1854 if ( !bInvestigateStartNode ) 1855 { 1856 if (bForward) 1857 aIdx++; 1858 else 1859 aIdx--; 1860 } 1861 // <-- 1862 if (aIdx.GetNode().IsTxtNode()) 1863 { 1864 pTxtNd = aIdx.GetNode().GetTxtNode(); 1865 1866 const SwNumRule * pNumRule = pTxtNd->GetNumRule(); 1867 if (pNumRule) 1868 { 1869 if ( ( pNumRule->IsOutlineRule() == ( bOutline ? sal_True : sal_False ) ) && // #115901# 1870 ( ( bNum && pNumRule->Get(0).IsEnumeration()) || 1871 ( !bNum && pNumRule->Get(0).IsItemize() ) ) ) // #i22362#, #i29560# 1872 { 1873 pResult = pTxtNd->GetNumRule(); 1874 // --> OD 2008-03-18 #refactorlists# 1875 // provide also the list id, to which the text node belongs. 1876 sListId = pTxtNd->GetListId(); 1877 } 1878 1879 break; 1880 } 1881 else if (pTxtNd->Len() > 0 || NULL != pTxtNd->GetNumRule()) 1882 { 1883 if (nNonEmptyAllowed == 0) 1884 break; 1885 1886 nNonEmptyAllowed--; 1887 1888 if (nNonEmptyAllowed < 0) 1889 nNonEmptyAllowed = -1; 1890 } 1891 } 1892 1893 // --> OD 2005-10-20 #i55391# 1894 if ( bInvestigateStartNode ) 1895 { 1896 if (bForward) 1897 aIdx++; 1898 else 1899 aIdx--; 1900 } 1901 // <-- 1902 1903 pNode = &aIdx.GetNode(); 1904 } 1905 while (!(pNode == GetNodes().DocumentSectionStartNode(pStartFromNode) || 1906 pNode == GetNodes().DocumentSectionEndNode(pStartFromNode))); 1907 // <-- 1908 } 1909 1910 return pResult; 1911 } 1912 // <- #i23731# 1913 1914 sal_Bool SwDoc::GotoPrevNum( SwPosition& rPos, sal_Bool bOverUpper, 1915 sal_uInt8* pUpper, sal_uInt8* pLower ) 1916 { 1917 return ::lcl_GotoNextPrevNum( rPos, sal_False, bOverUpper, pUpper, pLower ); 1918 } 1919 1920 sal_Bool SwDoc::NumUpDown( const SwPaM& rPam, sal_Bool bDown ) 1921 { 1922 sal_uLong nStt = rPam.GetPoint()->nNode.GetIndex(), 1923 nEnd = rPam.GetMark()->nNode.GetIndex(); 1924 if( nStt > nEnd ) 1925 { 1926 sal_uLong nTmp = nStt; nStt = nEnd; nEnd = nTmp; 1927 } 1928 1929 // -> #115901# outline nodes are promoted or demoted differently 1930 bool bOnlyOutline = true; 1931 bool bOnlyNonOutline = true; 1932 for (sal_uLong n = nStt; n <= nEnd; n++) 1933 { 1934 SwTxtNode * pTxtNd = GetNodes()[n]->GetTxtNode(); 1935 1936 if (pTxtNd) 1937 { 1938 SwNumRule * pRule = pTxtNd->GetNumRule(); 1939 1940 if (pRule) 1941 { 1942 if (pRule->IsOutlineRule()) 1943 bOnlyNonOutline = false; 1944 else 1945 bOnlyOutline = false; 1946 } 1947 } 1948 } 1949 // <- #115901# 1950 1951 sal_Bool bRet = sal_True; 1952 char nDiff = bDown ? 1 : -1; 1953 1954 // ->#115901# 1955 if (bOnlyOutline) 1956 bRet = OutlineUpDown(rPam, nDiff); 1957 else if (bOnlyNonOutline) 1958 { 1959 /* --> #i24560# 1960 1961 Only promote or demote if all selected paragraphs are 1962 promotable resp. demotable. 1963 1964 */ 1965 for (sal_uLong nTmp = nStt; nTmp <= nEnd; ++nTmp) 1966 { 1967 SwTxtNode* pTNd = GetNodes()[ nTmp ]->GetTxtNode(); 1968 1969 // --> OD 2006-10-19 #134160# - make code robust: 1970 // consider case that the node doesn't denote a text node. 1971 if ( pTNd ) 1972 { 1973 SwNumRule * pRule = pTNd->GetNumRule(); 1974 1975 if (pRule) 1976 { 1977 sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel()); 1978 if( (-1 == nDiff && 0 >= nLevel) || 1979 (1 == nDiff && MAXLEVEL - 1 <= nLevel)) 1980 bRet = sal_False; 1981 } 1982 } 1983 // <-- 1984 } 1985 1986 if( bRet ) 1987 { 1988 /* <-- #i24560# */ 1989 if (GetIDocumentUndoRedo().DoesUndo()) 1990 { 1991 SwUndo *const pUndo( new SwUndoNumUpDown(rPam, nDiff) ); 1992 GetIDocumentUndoRedo().AppendUndo(pUndo); 1993 } 1994 1995 String sNumRule; 1996 1997 for(sal_uLong nTmp = nStt; nTmp <= nEnd; ++nTmp ) 1998 { 1999 SwTxtNode* pTNd = GetNodes()[ nTmp ]->GetTxtNode(); 2000 2001 if( pTNd) 2002 { 2003 SwNumRule * pRule = pTNd->GetNumRule(); 2004 2005 if (pRule) 2006 { 2007 sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel()); 2008 nLevel = nLevel + nDiff; 2009 2010 pTNd->SetAttrListLevel(nLevel); 2011 } 2012 } 2013 } 2014 2015 ChkCondColls(); 2016 SetModified(); 2017 } 2018 } 2019 2020 return bRet; 2021 } 2022 2023 sal_Bool SwDoc::MoveParagraph( const SwPaM& rPam, long nOffset, sal_Bool bIsOutlMv ) 2024 { 2025 const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End(); 2026 2027 sal_uLong nStIdx = pStt->nNode.GetIndex(); 2028 sal_uLong nEndIdx = pEnd->nNode.GetIndex(); 2029 2030 // Here are some sophisticated checks whether the wished PaM will be moved or not. 2031 // For moving outlines (bIsOutlMv) I've already done some checks, so here are two different 2032 // checks... 2033 SwNode *pTmp1; 2034 SwNode *pTmp2; 2035 if( bIsOutlMv ) 2036 { 2037 // For moving chapters (outline) the following reason will deny the move: 2038 // if a start node is inside the moved area and its end node outside or vice versa. 2039 // If a start node is the first moved paragraph, its end node has to be within the moved 2040 // area, too (e.g. as last node). 2041 // If an end node is the last node of the moved area, its start node has to be a part of 2042 // the moved section, too. 2043 pTmp1 = GetNodes()[ nStIdx ]; 2044 if( pTmp1->IsStartNode() ) 2045 { // First is a start node 2046 pTmp2 = pTmp1->EndOfSectionNode(); 2047 if( pTmp2->GetIndex() > nEndIdx ) 2048 return sal_False; // Its end node is behind the moved range 2049 } 2050 pTmp1 = pTmp1->StartOfSectionNode()->EndOfSectionNode(); 2051 if( pTmp1->GetIndex() <= nEndIdx ) 2052 return sal_False; // End node inside but start node before moved range => no. 2053 pTmp1 = GetNodes()[ nEndIdx ]; 2054 if( pTmp1->IsEndNode() ) 2055 { // The last one is an end node 2056 pTmp1 = pTmp1->StartOfSectionNode(); 2057 if( pTmp1->GetIndex() < nStIdx ) 2058 return sal_False; // Its start node is before the moved range. 2059 } 2060 pTmp1 = pTmp1->StartOfSectionNode(); 2061 if( pTmp1->GetIndex() >= nStIdx ) 2062 return sal_False; // A start node which ends behind the moved area => no. 2063 } 2064 2065 sal_uLong nInStIdx, nInEndIdx; 2066 long nOffs = nOffset; 2067 if( nOffset > 0 ) 2068 { 2069 nInEndIdx = nEndIdx; 2070 nEndIdx += nOffset; 2071 ++nOffs; 2072 } 2073 else 2074 { 2075 //Impossible to move to negative index 2076 if( sal_uLong(abs( nOffset )) > nStIdx) 2077 return sal_False; 2078 2079 nInEndIdx = nStIdx - 1; 2080 nStIdx += nOffset; 2081 } 2082 nInStIdx = nInEndIdx + 1; 2083 // Folgende Absatzbloecke sollen vertauscht werden: 2084 // [ nStIdx, nInEndIdx ] mit [ nInStIdx, nEndIdx ] 2085 2086 if( nEndIdx >= GetNodes().GetEndOfContent().GetIndex() ) 2087 return sal_False; 2088 2089 if( !bIsOutlMv ) 2090 { // And here the restrictions for moving paragraphs other than chapters (outlines) 2091 // The plan is to exchange [nStIdx,nInEndIdx] and [nStartIdx,nEndIdx] 2092 // It will checked if the both "start" nodes as well as the both "end" notes belongs to 2093 // the same start-end-section. This is more restrictive than the conditions checked above. 2094 // E.g. a paragraph will not escape from a section or be inserted to another section. 2095 pTmp1 = GetNodes()[ nStIdx ]->StartOfSectionNode(); 2096 pTmp2 = GetNodes()[ nInStIdx ]->StartOfSectionNode(); 2097 if( pTmp1 != pTmp2 ) 2098 return sal_False; // "start" nodes in different sections 2099 pTmp1 = GetNodes()[ nEndIdx ]; 2100 bool bIsEndNode = pTmp1->IsEndNode(); 2101 if( !pTmp1->IsStartNode() ) 2102 { 2103 pTmp1 = pTmp1->StartOfSectionNode(); 2104 if( bIsEndNode ) // For end nodes the first start node is of course inside the range, 2105 pTmp1 = pTmp1->StartOfSectionNode(); // I've to check the start node of the start node. 2106 } 2107 pTmp1 = pTmp1->EndOfSectionNode(); 2108 pTmp2 = GetNodes()[ nInEndIdx ]; 2109 if( !pTmp2->IsStartNode() ) 2110 { 2111 bIsEndNode = pTmp2->IsEndNode(); 2112 pTmp2 = pTmp2->StartOfSectionNode(); 2113 if( bIsEndNode ) 2114 pTmp2 = pTmp2->StartOfSectionNode(); 2115 } 2116 pTmp2 = pTmp2->EndOfSectionNode(); 2117 if( pTmp1 != pTmp2 ) 2118 return sal_False; // The "end" notes are in different sections 2119 } 2120 2121 // auf Redlining testen - darf die Selektion ueberhaupt verschoben 2122 // werden? 2123 if( !IsIgnoreRedline() ) 2124 { 2125 sal_uInt16 nRedlPos = GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_DELETE ); 2126 if( USHRT_MAX != nRedlPos ) 2127 { 2128 SwPosition aStPos( *pStt ), aEndPos( *pEnd ); 2129 aStPos.nContent = 0; 2130 SwCntntNode* pCNd = pEnd->nNode.GetNode().GetCntntNode(); 2131 aEndPos.nContent = pCNd ? pCNd->Len() : 1; 2132 sal_Bool bCheckDel = sal_True; 2133 2134 // es existiert fuer den Bereich irgendein Redline-Delete-Object 2135 for( ; nRedlPos < GetRedlineTbl().Count(); ++nRedlPos ) 2136 { 2137 const SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ]; 2138 if( !bCheckDel || nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() ) 2139 { 2140 const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End(); 2141 switch( ComparePosition( *pRStt, *pREnd, aStPos, aEndPos )) 2142 { 2143 case POS_COLLIDE_START: 2144 case POS_BEHIND: // Pos1 liegt hinter Pos2 2145 nRedlPos = GetRedlineTbl().Count(); 2146 break; 2147 2148 case POS_COLLIDE_END: 2149 case POS_BEFORE: // Pos1 liegt vor Pos2 2150 break; 2151 case POS_INSIDE: // Pos1 liegt vollstaendig in Pos2 2152 // ist erlaubt, aber checke dann alle nachfolgenden 2153 // auf Ueberlappungen 2154 bCheckDel = sal_False; 2155 break; 2156 2157 case POS_OUTSIDE: // Pos2 liegt vollstaendig in Pos1 2158 case POS_EQUAL: // Pos1 ist genauso gross wie Pos2 2159 case POS_OVERLAP_BEFORE: // Pos1 ueberlappt Pos2 am Anfang 2160 case POS_OVERLAP_BEHIND: // Pos1 ueberlappt Pos2 am Ende 2161 return sal_False; 2162 } 2163 } 2164 } 2165 } 2166 } 2167 2168 { 2169 // DataChanged vorm verschieben verschicken, dann bekommt 2170 // man noch mit, welche Objecte sich im Bereich befinden. 2171 // Danach koennen sie vor/hinter der Position befinden. 2172 SwDataChanged aTmp( rPam, 0 ); 2173 } 2174 2175 SwNodeIndex aIdx( nOffset > 0 ? pEnd->nNode : pStt->nNode, nOffs ); 2176 SwNodeRange aMvRg( pStt->nNode, 0, pEnd->nNode, +1 ); 2177 2178 SwRedline* pOwnRedl = 0; 2179 if( IsRedlineOn() ) 2180 { 2181 // wenn der Bereich komplett im eigenen Redline liegt, kann es 2182 // verschoben werden! 2183 sal_uInt16 nRedlPos = GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_INSERT ); 2184 if( USHRT_MAX != nRedlPos ) 2185 { 2186 SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ]; 2187 const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End(); 2188 SwRedline aTmpRedl( nsRedlineType_t::REDLINE_INSERT, rPam ); 2189 const SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode(); 2190 // liegt komplett im Bereich, und ist auch der eigene Redline? 2191 if( aTmpRedl.IsOwnRedline( *pTmp ) && 2192 (pRStt->nNode < pStt->nNode || 2193 (pRStt->nNode == pStt->nNode && !pRStt->nContent.GetIndex()) ) && 2194 (pEnd->nNode < pREnd->nNode || 2195 (pEnd->nNode == pREnd->nNode && 2196 pCEndNd ? pREnd->nContent.GetIndex() == pCEndNd->Len() 2197 : !pREnd->nContent.GetIndex() )) ) 2198 { 2199 pOwnRedl = pTmp; 2200 if( nRedlPos + 1 < GetRedlineTbl().Count() ) 2201 { 2202 pTmp = GetRedlineTbl()[ nRedlPos+1 ]; 2203 if( *pTmp->Start() == *pREnd ) 2204 // dann doch nicht! 2205 pOwnRedl = 0; 2206 } 2207 2208 if( pOwnRedl && 2209 !( pRStt->nNode <= aIdx && aIdx <= pREnd->nNode )) 2210 { 2211 // nicht in sich selbst, dann auch nicht moven 2212 pOwnRedl = 0; 2213 } 2214 } 2215 } 2216 2217 if( !pOwnRedl ) 2218 { 2219 GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL ); 2220 2221 // zuerst das Insert, dann das Loeschen 2222 SwPosition aInsPos( aIdx ); 2223 aInsPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), 0 ); 2224 2225 SwPaM aPam( pStt->nNode, aMvRg.aEnd ); 2226 2227 SwPaM& rOrigPam = (SwPaM&)rPam; 2228 rOrigPam.DeleteMark(); 2229 rOrigPam.GetPoint()->nNode = aIdx.GetIndex() - 1; 2230 2231 sal_Bool bDelLastPara = !aInsPos.nNode.GetNode().IsCntntNode(); 2232 2233 /* #101076# When copying to a non-content node Copy will 2234 insert a paragraph before that node and insert before 2235 that inserted node. Copy creates an SwUndoInserts that 2236 does not cover the extra paragraph. Thus we insert the 2237 extra paragraph ourselves, _with_ correct undo 2238 information. */ 2239 if (bDelLastPara) 2240 { 2241 /* aInsPos points to the non-content node. Move it to 2242 the previous content node. */ 2243 SwPaM aInsPam(aInsPos); 2244 sal_Bool bMoved = aInsPam.Move(fnMoveBackward); 2245 ASSERT(bMoved, "No content node found!"); 2246 2247 if (bMoved) 2248 { 2249 /* Append the new node after the content node 2250 found. The new position to insert the moved 2251 paragraph at is before the inserted 2252 paragraph. */ 2253 AppendTxtNode(*aInsPam.GetPoint()); 2254 aInsPos = *aInsPam.GetPoint(); 2255 } 2256 } 2257 2258 CopyRange( aPam, aInsPos, false ); 2259 if( bDelLastPara ) 2260 { 2261 // dann muss der letzte leere Node wieder entfernt werden 2262 aIdx = aInsPos.nNode; 2263 SwCntntNode* pCNd = GetNodes().GoPrevious( &aInsPos.nNode ); 2264 xub_StrLen nCLen = 0; if( pCNd ) nCLen = pCNd->Len(); 2265 aInsPos.nContent.Assign( pCNd, nCLen ); 2266 2267 // alle die im zu loeschenden Node stehen, mussen auf den 2268 // naechsten umgestezt werden 2269 SwPosition* pPos; 2270 for( sal_uInt16 n = 0; n < GetRedlineTbl().Count(); ++n ) 2271 { 2272 SwRedline* pTmp = GetRedlineTbl()[ n ]; 2273 if( ( pPos = &pTmp->GetBound(sal_True))->nNode == aIdx ) 2274 { 2275 pPos->nNode++; 2276 pPos->nContent.Assign( pPos->nNode.GetNode().GetCntntNode(),0); 2277 } 2278 if( ( pPos = &pTmp->GetBound(sal_False))->nNode == aIdx ) 2279 { 2280 pPos->nNode++; 2281 pPos->nContent.Assign( pPos->nNode.GetNode().GetCntntNode(),0); 2282 } 2283 } 2284 CorrRel( aIdx, aInsPos, 0, sal_False ); 2285 2286 pCNd->JoinNext(); 2287 } 2288 2289 rOrigPam.GetPoint()->nNode++; 2290 rOrigPam.GetPoint()->nContent.Assign( rOrigPam.GetCntntNode(), 0 ); 2291 2292 RedlineMode_t eOld = GetRedlineMode(); 2293 checkRedlining(eOld); 2294 if (GetIDocumentUndoRedo().DoesUndo()) 2295 { 2296 //JP 06.01.98: MUSS noch optimiert werden!!! 2297 SetRedlineMode( 2298 (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE)); 2299 SwUndo *const pUndo(new SwUndoRedlineDelete(aPam, UNDO_DELETE)); 2300 GetIDocumentUndoRedo().AppendUndo(pUndo); 2301 } 2302 2303 SwRedline* pNewRedline = new SwRedline( nsRedlineType_t::REDLINE_DELETE, aPam ); 2304 2305 // #101654# prevent assertion from aPam's target being deleted 2306 // (Alternatively, one could just let aPam go out of scope, but 2307 // that requires touching a lot of code.) 2308 aPam.GetBound(sal_True).nContent.Assign( NULL, 0 ); 2309 aPam.GetBound(sal_False).nContent.Assign( NULL, 0 ); 2310 2311 AppendRedline( pNewRedline, true ); 2312 2313 //JP 06.01.98: MUSS noch optimiert werden!!! 2314 SetRedlineMode( eOld ); 2315 GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL ); 2316 SetModified(); 2317 2318 return sal_True; 2319 } 2320 } 2321 2322 if( !pOwnRedl && !IsIgnoreRedline() && GetRedlineTbl().Count() ) 2323 { 2324 SwPaM aTemp(aIdx); 2325 SplitRedline(aTemp); 2326 } 2327 2328 sal_uLong nRedlSttNd(0), nRedlEndNd(0); 2329 if( pOwnRedl ) 2330 { 2331 const SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End(); 2332 nRedlSttNd = pRStt->nNode.GetIndex(); 2333 nRedlEndNd = pREnd->nNode.GetIndex(); 2334 } 2335 2336 SwUndoMoveNum* pUndo = 0; 2337 sal_uLong nMoved = 0; 2338 if (GetIDocumentUndoRedo().DoesUndo()) 2339 { 2340 pUndo = new SwUndoMoveNum( rPam, nOffset, bIsOutlMv ); 2341 nMoved = rPam.End()->nNode.GetIndex() - rPam.Start()->nNode.GetIndex() + 1; 2342 } 2343 2344 2345 MoveNodeRange( aMvRg, aIdx, DOC_MOVEREDLINES ); 2346 2347 if( pUndo ) 2348 { 2349 // i57907: Under circumstances (sections at the end of a chapter) 2350 // the rPam.Start() is not moved to the new position. 2351 // But aIdx should be at the new end position and as long as the number of moved paragraphs 2352 // is nMoved, I know, where the new position is. 2353 pUndo->SetStartNode( aIdx.GetIndex() - nMoved ); 2354 GetIDocumentUndoRedo().AppendUndo(pUndo); 2355 } 2356 2357 if( pOwnRedl ) 2358 { 2359 SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End(); 2360 if( pRStt->nNode.GetIndex() != nRedlSttNd ) 2361 { 2362 pRStt->nNode = nRedlSttNd; 2363 pRStt->nContent.Assign( pRStt->nNode.GetNode().GetCntntNode(),0); 2364 } 2365 if( pREnd->nNode.GetIndex() != nRedlEndNd ) 2366 { 2367 pREnd->nNode = nRedlEndNd; 2368 SwCntntNode* pCNd = pREnd->nNode.GetNode().GetCntntNode(); 2369 xub_StrLen nL = 0; if( pCNd ) nL = pCNd->Len(); 2370 pREnd->nContent.Assign( pCNd, nL ); 2371 } 2372 } 2373 2374 SetModified(); 2375 return sal_True; 2376 } 2377 2378 sal_Bool SwDoc::NumOrNoNum( const SwNodeIndex& rIdx, sal_Bool bDel ) 2379 { 2380 sal_Bool bResult = sal_False; 2381 SwTxtNode * pTxtNd = rIdx.GetNode().GetTxtNode(); 2382 2383 if (pTxtNd && pTxtNd->GetNumRule() != NULL && 2384 (pTxtNd->HasNumber() || pTxtNd->HasBullet())) 2385 { 2386 if ( !pTxtNd->IsCountedInList() == !bDel) 2387 { 2388 sal_Bool bOldNum = bDel; // == pTxtNd->IsCounted(); 2389 sal_Bool bNewNum = bDel ? sal_False : sal_True; 2390 pTxtNd->SetCountedInList(bNewNum ? true : false); 2391 2392 SetModified(); 2393 2394 bResult = sal_True; 2395 2396 if (GetIDocumentUndoRedo().DoesUndo()) 2397 { 2398 SwUndoNumOrNoNum * pUndo = 2399 new SwUndoNumOrNoNum(rIdx, bOldNum, bNewNum); 2400 2401 GetIDocumentUndoRedo().AppendUndo(pUndo); 2402 } 2403 } 2404 else if (bDel && pTxtNd->GetNumRule(sal_False) && 2405 pTxtNd->GetActualListLevel() >= 0 && 2406 pTxtNd->GetActualListLevel() < MAXLEVEL) 2407 { 2408 SwPaM aPam(*pTxtNd); 2409 2410 DelNumRules(aPam); 2411 2412 bResult = sal_True; 2413 } 2414 } 2415 2416 return bResult; 2417 } 2418 2419 SwNumRule* SwDoc::GetCurrNumRule( const SwPosition& rPos ) const 2420 { 2421 SwNumRule* pRet = 0; 2422 SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode(); 2423 2424 if( pTNd ) 2425 { 2426 // --> OD 2008-02-20 #refactorlists# 2427 // pTNd->SyncNumberAndNumRule(); 2428 // <-- 2429 pRet = pTNd->GetNumRule(); 2430 } 2431 2432 return pRet; 2433 } 2434 2435 sal_uInt16 SwDoc::FindNumRule( const String& rName ) const 2436 { 2437 for( sal_uInt16 n = pNumRuleTbl->Count(); n; ) 2438 if( (*pNumRuleTbl)[ --n ]->GetName() == rName ) 2439 return n; 2440 2441 return USHRT_MAX; 2442 } 2443 2444 SwNumRule* SwDoc::FindNumRulePtr( const String& rName ) const 2445 { 2446 SwNumRule * pResult = 0; 2447 2448 pResult = maNumRuleMap[rName]; 2449 2450 if ( !pResult ) 2451 { 2452 for (sal_uInt16 n = 0; n < pNumRuleTbl->Count(); ++n) 2453 { 2454 if ((*pNumRuleTbl)[n]->GetName() == rName) 2455 { 2456 pResult = (*pNumRuleTbl)[n]; 2457 2458 break; 2459 } 2460 } 2461 } 2462 2463 return pResult; 2464 } 2465 2466 // #i36749# 2467 void SwDoc::AddNumRule(SwNumRule * pRule) 2468 { 2469 pNumRuleTbl->Insert(pRule, pNumRuleTbl->Count()); 2470 maNumRuleMap[pRule->GetName()] = pRule; 2471 pRule->SetNumRuleMap(&maNumRuleMap); 2472 2473 // --> OD 2008-03-26 #refactorlists# 2474 createListForListStyle( pRule->GetName() ); 2475 // <-- 2476 } 2477 2478 // --> OD 2008-02-11 #newlistlevelattrs# 2479 sal_uInt16 SwDoc::MakeNumRule( const String &rName, 2480 const SwNumRule* pCpy, 2481 sal_Bool bBroadcast, 2482 const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode ) 2483 { 2484 SwNumRule* pNew; 2485 if( pCpy ) 2486 { 2487 pNew = new SwNumRule( *pCpy ); 2488 2489 // --> OD 2008-07-08 #i91400# 2490 pNew->SetName( GetUniqueNumRuleName( &rName ), *this ); 2491 // <-- 2492 if( pNew->GetName() != rName ) 2493 { 2494 pNew->SetPoolFmtId( USHRT_MAX ); 2495 pNew->SetPoolHelpId( USHRT_MAX ); 2496 pNew->SetPoolHlpFileId( UCHAR_MAX ); 2497 // --> OD 2008-04-03 #refactorlists# 2498 pNew->SetDefaultListId( String() ); 2499 // <-- 2500 } 2501 pNew->CheckCharFmts( this ); 2502 } 2503 else 2504 { 2505 // --> OD 2008-02-11 #newlistlevelattrs# 2506 pNew = new SwNumRule( GetUniqueNumRuleName( &rName ), 2507 eDefaultNumberFormatPositionAndSpaceMode ); 2508 // <-- 2509 } 2510 2511 sal_uInt16 nRet = pNumRuleTbl->Count(); 2512 2513 AddNumRule(pNew); // #i36749# 2514 2515 if (GetIDocumentUndoRedo().DoesUndo()) 2516 { 2517 SwUndo * pUndo = new SwUndoNumruleCreate(pNew, this); 2518 GetIDocumentUndoRedo().AppendUndo(pUndo); 2519 } 2520 2521 if (bBroadcast) 2522 BroadcastStyleOperation(pNew->GetName(), SFX_STYLE_FAMILY_PSEUDO, 2523 SFX_STYLESHEET_CREATED); 2524 2525 return nRet; 2526 } 2527 2528 String SwDoc::GetUniqueNumRuleName( const String* pChkStr, sal_Bool bAutoNum ) const 2529 { 2530 String aName; 2531 if( bAutoNum ) 2532 { 2533 // --> OD #o12311627# 2534 static rtlRandomPool s_RandomPool( rtl_random_createPool() ); 2535 sal_Int64 n; 2536 rtl_random_getBytes( s_RandomPool, &n, sizeof(n) ); 2537 aName = String::CreateFromInt64( (n < 0 ? -n : n) ); 2538 // <-- 2539 if( pChkStr && !pChkStr->Len() ) 2540 pChkStr = 0; 2541 } 2542 else if( pChkStr && pChkStr->Len() ) 2543 aName = *pChkStr; 2544 else 2545 { 2546 pChkStr = 0; 2547 aName = SW_RESSTR( STR_NUMRULE_DEFNAME ); 2548 } 2549 2550 sal_uInt16 nNum(0), nTmp, nFlagSize = ( pNumRuleTbl->Count() / 8 ) +2; 2551 sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ]; 2552 memset( pSetFlags, 0, nFlagSize ); 2553 2554 xub_StrLen nNmLen = aName.Len(); 2555 if( !bAutoNum && pChkStr ) 2556 { 2557 while( nNmLen-- && '0' <= aName.GetChar( nNmLen ) && 2558 '9' >= aName.GetChar( nNmLen ) ) 2559 ; //nop 2560 2561 if( ++nNmLen < aName.Len() ) 2562 { 2563 aName.Erase( nNmLen ); 2564 pChkStr = 0; 2565 } 2566 } 2567 2568 const SwNumRule* pNumRule; 2569 sal_uInt16 n; 2570 2571 for( n = 0; n < pNumRuleTbl->Count(); ++n ) 2572 if( 0 != ( pNumRule = (*pNumRuleTbl)[ n ] ) ) 2573 { 2574 const String& rNm = pNumRule->GetName(); 2575 if( rNm.Match( aName ) == nNmLen ) 2576 { 2577 // Nummer bestimmen und das Flag setzen 2578 nNum = (sal_uInt16)rNm.Copy( nNmLen ).ToInt32(); 2579 if( nNum-- && nNum < pNumRuleTbl->Count() ) 2580 pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 )); 2581 } 2582 if( pChkStr && pChkStr->Equals( rNm ) ) 2583 pChkStr = 0; 2584 } 2585 2586 if( !pChkStr ) 2587 { 2588 // alle Nummern entsprechend geflag, also bestimme die richtige Nummer 2589 nNum = pNumRuleTbl->Count(); 2590 for( n = 0; n < nFlagSize; ++n ) 2591 if( 0xff != ( nTmp = pSetFlags[ n ] )) 2592 { 2593 // also die Nummer bestimmen 2594 nNum = n * 8; 2595 while( nTmp & 1 ) 2596 ++nNum, nTmp >>= 1; 2597 break; 2598 } 2599 2600 } 2601 delete [] pSetFlags; 2602 if( pChkStr && pChkStr->Len() ) 2603 return *pChkStr; 2604 return aName += String::CreateFromInt32( ++nNum ); 2605 } 2606 2607 void SwDoc::UpdateNumRule() 2608 { 2609 const SwNumRuleTbl& rNmTbl = GetNumRuleTbl(); 2610 for( sal_uInt16 n = 0; n < rNmTbl.Count(); ++n ) 2611 if( rNmTbl[ n ]->IsInvalidRule() ) 2612 rNmTbl[ n ]->Validate(); 2613 } 2614 2615 // --> OD 2008-04-02 #refactorlists# 2616 void SwDoc::MarkListLevel( const String& sListId, 2617 const int nListLevel, 2618 const sal_Bool bValue ) 2619 { 2620 SwList* pList = getListByName( sListId ); 2621 2622 if ( pList ) 2623 { 2624 MarkListLevel( *pList, nListLevel, bValue ); 2625 } 2626 } 2627 2628 void SwDoc::MarkListLevel( SwList& rList, 2629 const int nListLevel, 2630 const sal_Bool bValue ) 2631 { 2632 // Set new marked list level and notify all affected nodes of the changed mark. 2633 rList.MarkListLevel( nListLevel, bValue ); 2634 } 2635 // <- #i27615# 2636 // <-- 2637 2638 // #i23726# 2639 sal_Bool SwDoc::IsFirstOfNumRule(SwPosition & rPos) 2640 { 2641 sal_Bool bResult = sal_False; 2642 SwTxtNode * pTxtNode = rPos.nNode.GetNode().GetTxtNode(); 2643 2644 if (pTxtNode) 2645 { 2646 SwNumRule * pNumRule = pTxtNode->GetNumRule(); 2647 2648 if (pNumRule) 2649 bResult = pTxtNode->IsFirstOfNumRule(); 2650 } 2651 2652 return bResult; 2653 } 2654 2655 // --> OD 2007-10-26 #i83479# 2656 // implementation for interface <IDocumentListItems> 2657 bool SwDoc::lessThanNodeNum::operator()( const SwNodeNum* pNodeNumOne, 2658 const SwNodeNum* pNodeNumTwo ) const 2659 { 2660 return pNodeNumOne->LessThan( *pNodeNumTwo ); 2661 } 2662 2663 void SwDoc::addListItem( const SwNodeNum& rNodeNum ) 2664 { 2665 if ( mpListItemsList == 0 ) 2666 { 2667 return; 2668 } 2669 2670 const bool bAlreadyInserted( 2671 mpListItemsList->find( &rNodeNum ) != mpListItemsList->end() ); 2672 ASSERT( !bAlreadyInserted, 2673 "<SwDoc::InsertListItem(..)> - <SwNodeNum> instance already registered as numbered item!" ); 2674 if ( !bAlreadyInserted ) 2675 { 2676 mpListItemsList->insert( &rNodeNum ); 2677 } 2678 } 2679 2680 void SwDoc::removeListItem( const SwNodeNum& rNodeNum ) 2681 { 2682 if ( mpListItemsList == 0 ) 2683 { 2684 return; 2685 } 2686 2687 const tImplSortedNodeNumList::size_type nDeleted = mpListItemsList->erase( &rNodeNum ); 2688 if ( nDeleted > 1 ) 2689 { 2690 ASSERT( false, 2691 "<SwDoc::RemoveListItem(..)> - <SwNodeNum> was registered more than once as numbered item!" ); 2692 } 2693 } 2694 2695 String SwDoc::getListItemText( const SwNodeNum& rNodeNum, 2696 const bool bWithNumber, 2697 const bool bWithSpacesForLevel ) const 2698 { 2699 return rNodeNum.GetTxtNode() 2700 ? rNodeNum.GetTxtNode()->GetExpandTxt( 0, STRING_LEN, bWithNumber, 2701 bWithNumber, bWithSpacesForLevel ) 2702 : String(); 2703 } 2704 2705 void SwDoc::getListItems( tSortedNodeNumList& orNodeNumList ) const 2706 { 2707 orNodeNumList.clear(); 2708 orNodeNumList.reserve( mpListItemsList->size() ); 2709 2710 tImplSortedNodeNumList::iterator aIter; 2711 tImplSortedNodeNumList::iterator aEndIter = mpListItemsList->end(); 2712 for ( aIter = mpListItemsList->begin(); aIter != aEndIter; ++aIter ) 2713 { 2714 orNodeNumList.push_back( (*aIter) ); 2715 } 2716 } 2717 2718 void SwDoc::getNumItems( tSortedNodeNumList& orNodeNumList ) const 2719 { 2720 orNodeNumList.clear(); 2721 orNodeNumList.reserve( mpListItemsList->size() ); 2722 2723 tImplSortedNodeNumList::iterator aIter; 2724 tImplSortedNodeNumList::iterator aEndIter = mpListItemsList->end(); 2725 for ( aIter = mpListItemsList->begin(); aIter != aEndIter; ++aIter ) 2726 { 2727 const SwNodeNum* pNodeNum = (*aIter); 2728 if ( pNodeNum->IsCounted() && 2729 pNodeNum->GetTxtNode() && pNodeNum->GetTxtNode()->HasNumber() ) 2730 { 2731 orNodeNumList.push_back( pNodeNum ); 2732 } 2733 } 2734 } 2735 // <-- 2736 2737 // --> OD 2007-11-15 #i83479# 2738 // implementation for interface <IDocumentOutlineNodes> 2739 sal_Int32 SwDoc::getOutlineNodesCount() const 2740 { 2741 return GetNodes().GetOutLineNds().Count(); 2742 } 2743 2744 int SwDoc::getOutlineLevel( const sal_Int32 nIdx ) const 2745 { 2746 return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]-> 2747 // GetTxtNode()->GetOutlineLevel(); //#outline level,zhaojianwei 2748 GetTxtNode()->GetAttrOutlineLevel()-1; //<-end,zhaojianwei 2749 } 2750 2751 String SwDoc::getOutlineText( const sal_Int32 nIdx, 2752 const bool bWithNumber, 2753 const bool bWithSpacesForLevel ) const 2754 { 2755 return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]-> 2756 GetTxtNode()->GetExpandTxt( 0, STRING_LEN, bWithNumber, 2757 bWithNumber, bWithSpacesForLevel ); 2758 } 2759 2760 SwTxtNode* SwDoc::getOutlineNode( const sal_Int32 nIdx ) const 2761 { 2762 return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->GetTxtNode(); 2763 } 2764 2765 void SwDoc::getOutlineNodes( IDocumentOutlineNodes::tSortedOutlineNodeList& orOutlineNodeList ) const 2766 { 2767 orOutlineNodeList.clear(); 2768 orOutlineNodeList.reserve( getOutlineNodesCount() ); 2769 2770 const sal_uInt16 nOutlCount( static_cast<sal_uInt16>(getOutlineNodesCount()) ); 2771 for ( sal_uInt16 i = 0; i < nOutlCount; ++i ) 2772 { 2773 orOutlineNodeList.push_back( 2774 GetNodes().GetOutLineNds()[i]->GetTxtNode() ); 2775 } 2776 } 2777 // <-- 2778 2779 // --> OD 2008-03-26 #refactorlists# 2780 // implementation of interface IDocumentListsAccess 2781 SwList* SwDoc::createList( String sListId, 2782 const String sDefaultListStyleName ) 2783 { 2784 if ( sListId.Len() == 0 ) 2785 { 2786 sListId = listfunc::CreateUniqueListId( *this ); 2787 } 2788 2789 if ( getListByName( sListId ) ) 2790 { 2791 ASSERT( false, 2792 "<SwDoc::createList(..)> - provided list id already used. Serious defect -> please inform OD." ); 2793 return 0; 2794 } 2795 2796 SwNumRule* pDefaultNumRuleForNewList = FindNumRulePtr( sDefaultListStyleName ); 2797 if ( !pDefaultNumRuleForNewList ) 2798 { 2799 ASSERT( false, 2800 "<SwDoc::createList(..)> - for provided default list style name no list style is found. Serious defect -> please inform OD." ); 2801 return 0; 2802 } 2803 2804 SwList* pNewList = new SwList( sListId, *pDefaultNumRuleForNewList, GetNodes() ); 2805 maLists[sListId] = pNewList; 2806 2807 return pNewList; 2808 } 2809 2810 void SwDoc::deleteList( const String sListId ) 2811 { 2812 SwList* pList = getListByName( sListId ); 2813 if ( pList ) 2814 { 2815 maLists.erase( sListId ); 2816 delete pList; 2817 } 2818 } 2819 2820 SwList* SwDoc::getListByName( const String sListId ) const 2821 { 2822 SwList* pList = 0; 2823 2824 std::hash_map< String, SwList*, StringHash >::const_iterator 2825 aListIter = maLists.find( sListId ); 2826 if ( aListIter != maLists.end() ) 2827 { 2828 pList = (*aListIter).second; 2829 } 2830 2831 return pList; 2832 } 2833 2834 SwList* SwDoc::createListForListStyle( const String sListStyleName ) 2835 { 2836 if ( sListStyleName.Len() == 0 ) 2837 { 2838 ASSERT( false, 2839 "<SwDoc::createListForListStyle(..)> - no list style name provided. Serious defect -> please inform OD." ); 2840 return 0; 2841 } 2842 2843 if ( getListForListStyle( sListStyleName ) ) 2844 { 2845 ASSERT( false, 2846 "<SwDoc::createListForListStyle(..)> - a list for the provided list style name already exists. Serious defect -> please inform OD." ); 2847 return 0; 2848 } 2849 2850 SwNumRule* pNumRule = FindNumRulePtr( sListStyleName ); 2851 if ( !pNumRule ) 2852 { 2853 ASSERT( false, 2854 "<SwDoc::createListForListStyle(..)> - for provided list style name no list style is found. Serious defect -> please inform OD." ); 2855 return 0; 2856 } 2857 2858 String sListId( pNumRule->GetDefaultListId() ); // can be empty String 2859 if ( getListByName( sListId ) ) 2860 { 2861 sListId = String(); 2862 } 2863 SwList* pNewList = createList( sListId, sListStyleName ); 2864 maListStyleLists[sListStyleName] = pNewList; 2865 pNumRule->SetDefaultListId( pNewList->GetListId() ); 2866 2867 return pNewList; 2868 } 2869 2870 SwList* SwDoc::getListForListStyle( const String sListStyleName ) const 2871 { 2872 SwList* pList = 0; 2873 2874 std::hash_map< String, SwList*, StringHash >::const_iterator 2875 aListIter = maListStyleLists.find( sListStyleName ); 2876 if ( aListIter != maListStyleLists.end() ) 2877 { 2878 pList = (*aListIter).second; 2879 } 2880 2881 return pList; 2882 } 2883 2884 void SwDoc::deleteListForListStyle( const String sListStyleName ) 2885 { 2886 String sListId; 2887 { 2888 SwList* pList = getListForListStyle( sListStyleName ); 2889 ASSERT( pList, 2890 "<SwDoc::deleteListForListStyle(..)> - misusage of method: no list found for given list style name" ); 2891 if ( pList ) 2892 { 2893 sListId = pList->GetListId(); 2894 } 2895 } 2896 if ( sListId.Len() > 0 ) 2897 { 2898 maListStyleLists.erase( sListStyleName ); 2899 deleteList( sListId ); 2900 } 2901 } 2902 // <-- 2903 // --> OD 2008-07-08 #i91400# 2904 void SwDoc::trackChangeOfListStyleName( const String sListStyleName, 2905 const String sNewListStyleName ) 2906 { 2907 SwList* pList = getListForListStyle( sListStyleName ); 2908 ASSERT( pList, 2909 "<SwDoc::changeOfListStyleName(..)> - misusage of method: no list found for given list style name" ); 2910 2911 if ( pList != 0 ) 2912 { 2913 maListStyleLists.erase( sListStyleName ); 2914 maListStyleLists[sNewListStyleName] = pList; 2915 } 2916 } 2917 // <-- 2918 2919 // --> OD 2008-03-13 #refactorlists# 2920 namespace listfunc 2921 { 2922 const String MakeListIdUnique( const SwDoc& rDoc, 2923 const String aSuggestedUniqueListId ) 2924 { 2925 long nHitCount = 0; 2926 String aTmpStr = aSuggestedUniqueListId; 2927 while ( rDoc.getListByName( aTmpStr ) ) 2928 { 2929 ++nHitCount; 2930 aTmpStr = aSuggestedUniqueListId; 2931 aTmpStr += String::CreateFromInt32( nHitCount ); 2932 } 2933 2934 return aTmpStr; 2935 } 2936 const String CreateUniqueListId( const SwDoc& rDoc ) 2937 { 2938 // --> OD 2008-08-06 #i92478# 2939 String aNewListId = String::CreateFromAscii( "list" ); 2940 // <-- 2941 // --> OD #o12311627# 2942 static rtlRandomPool s_RandomPool( rtl_random_createPool() ); 2943 sal_Int64 n; 2944 rtl_random_getBytes( s_RandomPool, &n, sizeof(n) ); 2945 aNewListId += String::CreateFromInt64( (n < 0 ? -n : n) ); 2946 // <-- 2947 2948 return MakeListIdUnique( rDoc, aNewListId ); 2949 } 2950 } 2951 // <-- 2952