merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / doc / docnum.cxx
bloba3bca434cc3af2698ff7bacc28273622e5745e4e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: docnum.cxx,v $
10 * $Revision: 1.78 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include <hintids.hxx>
34 #include <tools/date.hxx>
35 #include <tools/time.hxx>
36 #include <tools/resid.hxx>
37 #include <svx/lrspitem.hxx>
38 #include <ftninfo.hxx>
39 #include <ftnidx.hxx>
40 #include <doc.hxx>
41 #include <pam.hxx>
42 #include <ndtxt.hxx>
43 #include <doctxm.hxx> // pTOXBaseRing
44 #include <poolfmt.hxx>
45 #include <undobj.hxx>
46 #include <swundo.hxx>
47 #include <SwUndoFmt.hxx>
48 #include <rolbck.hxx>
49 #include <paratr.hxx>
50 #include <docary.hxx>
51 #include <mvsave.hxx>
52 #include <txtfrm.hxx>
53 #include <pamtyp.hxx>
54 #include <redline.hxx>
55 #ifndef _COMCORE_HRC
56 #include <comcore.hrc>
57 #endif
58 #include <svx/adjitem.hxx>
59 #include <svx/frmdiritem.hxx>
60 #include <frmatr.hxx>
61 #include <SwStyleNameMapper.hxx>
62 #include <SwNodeNum.hxx>
63 // --> OD 2008-03-13 #refactorlists#
64 #include <list.hxx>
65 #include <listfunc.hxx>
66 // <--
68 #include <map>
70 inline BYTE GetUpperLvlChg( BYTE nCurLvl, BYTE nLevel, USHORT nMask )
72 if( 1 < nLevel )
74 if( nCurLvl + 1 >= nLevel )
75 nCurLvl -= nLevel - 1;
76 else
77 nCurLvl = 0;
79 return static_cast<BYTE>((nMask - 1) & ~(( 1 << nCurLvl ) - 1));
82 void SwDoc::SetOutlineNumRule( const SwNumRule& rRule )
84 if( pOutlineRule )
85 (*pOutlineRule) = rRule;
86 else
88 pOutlineRule = new SwNumRule( rRule );
90 AddNumRule(pOutlineRule); // #i36749#
93 pOutlineRule->SetRuleType( OUTLINE_RULE );
94 // --> OD 2008-07-08 #i91400#
95 pOutlineRule->SetName( String::CreateFromAscii(
96 SwNumRule::GetOutlineRuleName() ),
97 *this);
98 // <--
99 // --> OD 2006-09-21 #i69522#
100 // assure that the outline numbering rule is an automatic rule
101 pOutlineRule->SetAutoRule( TRUE );
102 // <--
104 // teste ob die evt. gesetzen CharFormate in diesem Document
105 // definiert sind
106 pOutlineRule->CheckCharFmts( this );
108 // --> OD 2008-05-13 #refactorlists#
109 // notify text nodes, which are registered at the outline style, about the
110 // changed outline style
111 SwNumRule::tTxtNodeList aTxtNodeList;
112 pOutlineRule->GetTxtNodeList( aTxtNodeList );
113 for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
114 aIter != aTxtNodeList.end(); ++aIter )
116 SwTxtNode* pTxtNd = *aIter;
117 pTxtNd->NumRuleChgd();
118 // --> OD 2009-01-20 #i94152#
119 // assure that list level corresponds to outline level
120 if ( pTxtNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle() &&
121 pTxtNd->GetAttrListLevel() != pTxtNd->GetTxtColl()->GetAssignedOutlineStyleLevel() )
123 pTxtNd->SetAttrListLevel( pTxtNd->GetTxtColl()->GetAssignedOutlineStyleLevel() );
125 // <--
127 // <--
129 PropagateOutlineRule();
130 pOutlineRule->SetInvalidRule(TRUE);
131 UpdateNumRule();
133 // gibt es Fussnoten && gilt Kapitelweises Nummerieren, dann updaten
134 if( GetFtnIdxs().Count() && FTNNUM_CHAPTER == GetFtnInfo().eNum )
135 GetFtnIdxs().UpdateAllFtn();
137 UpdateExpFlds(NULL, true);
139 SetModified();
142 void SwDoc::PropagateOutlineRule()
144 for (USHORT n = 0; n < pTxtFmtCollTbl->Count(); n++)
146 SwTxtFmtColl *pColl = (*pTxtFmtCollTbl)[n];
148 // if (NO_NUMBERING != pColl->GetOutlineLevel())//#outline level,zhaojianwei
149 if(pColl->IsAssignedToListLevelOfOutlineStyle())//<-end,zhaojianwei
151 SwClientIter aIter(*pColl);
153 // --> OD 2006-11-20 #i71764#
154 // Check only the list style, which is set at the paragraph style
155 const SwNumRuleItem & rCollRuleItem = pColl->GetNumRule( FALSE );
156 // <--
158 // --> OD 2006-11-20 #i71764#
159 // Check on document setting OUTLINE_LEVEL_YIELDS_OUTLINE_RULE no longer needed.
160 if ( rCollRuleItem.GetValue().Len() == 0 )
161 // <--
163 SwNumRule * pMyOutlineRule = GetOutlineNumRule();
165 if (pMyOutlineRule)
167 SwNumRuleItem aNumItem( pMyOutlineRule->GetName() );
169 pColl->SetFmtAttr(aNumItem);
176 // Hoch-/Runterstufen
177 BOOL SwDoc::OutlineUpDown( const SwPaM& rPam, short nOffset )
179 if( !GetNodes().GetOutLineNds().Count() || !nOffset )
180 return FALSE;
182 // den Bereich feststellen
183 const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
184 const SwNodePtr pSttNd = (SwNodePtr)&rPam.Start()->nNode.GetNode();
185 const SwNodePtr pEndNd = (SwNodePtr)&rPam.End()->nNode.GetNode();
186 USHORT nSttPos, nEndPos;
188 if( !rOutlNds.Seek_Entry( pSttNd, &nSttPos ) &&
189 !nSttPos-- )
190 // wir stehen in keiner "Outline-Section"
191 return FALSE;
193 if( rOutlNds.Seek_Entry( pEndNd, &nEndPos ) )
194 ++nEndPos;
196 // jetzt haben wir unseren Bereich im OutlineNodes-Array
197 // dann prufe ersmal, ob nicht unterebenen aufgehoben werden
198 // (Stufung ueber die Grenzen)
199 USHORT n;
201 // so, dann koennen wir:
202 // 1. Vorlagen-Array anlegen
203 SwTxtFmtColl* aCollArr[ MAXLEVEL ];
204 memset( aCollArr, 0, sizeof( SwTxtFmtColl* ) * MAXLEVEL );
206 for( n = 0; n < pTxtFmtCollTbl->Count(); ++n )
208 //BYTE nLevel = (*pTxtFmtCollTbl)[ n ]->GetOutlineLevel();//#outline level,zhaojianwei
209 //if( nLevel < MAXLEVEL )
210 // aCollArr[ nLevel ] = (*pTxtFmtCollTbl)[ n ];
211 if((*pTxtFmtCollTbl)[ n ]->IsAssignedToListLevelOfOutlineStyle())
213 const int nLevel = (*pTxtFmtCollTbl)[ n ]->GetAssignedOutlineStyleLevel();
214 aCollArr[ nLevel ] = (*pTxtFmtCollTbl)[ n ];
215 }//<-end,zhaojianwei
218 /* --> #111107# */
219 /* Find the last occupied level (backward). */
220 for (n = MAXLEVEL - 1; n > 0; n--)
222 if (aCollArr[n] != 0)
223 break;
226 /* If an occupied level is found, choose next level (which IS
227 unoccupied) until a valid level is found. If no occupied level
228 was found n is 0 and aCollArr[0] is 0. In this case no demoting
229 is possible. */
230 if (aCollArr[n] != 0)
232 while (n < MAXLEVEL - 1)
234 n++;
236 SwTxtFmtColl *aTmpColl =
237 GetTxtCollFromPool(static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + n));
239 //if (aTmpColl->GetOutlineLevel() == n)//#outline level,zhaojianwei
240 if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() &&
241 aTmpColl->GetAssignedOutlineStyleLevel() == n )//<-end,zhaojianwei
243 aCollArr[n] = aTmpColl;
244 break;
249 /* Find the first occupied level (forward). */
250 for (n = 0; n < MAXLEVEL - 1; n++)
252 if (aCollArr[n] != 0)
253 break;
256 /* If an occupied level is found, choose previous level (which IS
257 unoccupied) until a valid level is found. If no occupied level
258 was found n is MAXLEVEL - 1 and aCollArr[MAXLEVEL - 1] is 0. In
259 this case no demoting is possible. */
260 if (aCollArr[n] != 0)
262 while (n > 0)
264 n--;
266 SwTxtFmtColl *aTmpColl =
267 GetTxtCollFromPool(static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + n));
269 //if (aTmpColl->GetOutlineLevel() == n)//#outline level,zhaojianwei
270 if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() &&
271 aTmpColl->GetAssignedOutlineStyleLevel() == n )//<-end,zhaojianwei
273 aCollArr[n] = aTmpColl;
274 break;
278 /* <-- #111107# */
280 /* --> #i13747#
282 Build a move table that states from which level an outline will
284 be moved to which other level. */
286 /* the move table
288 aMoveArr[n] = m: replace aCollArr[n] with aCollArr[m]
290 int aMoveArr[MAXLEVEL];
291 int nStep; // step size for searching in aCollArr: -1 or 1
292 int nNum; // amount of steps for stepping in aCollArr
294 if (nOffset < 0)
296 nStep = -1;
297 nNum = -nOffset;
299 else
301 nStep = 1;
302 nNum = nOffset;
305 /* traverse aCollArr */
306 for (n = 0; n < MAXLEVEL; n++)
308 /* If outline level n has an assigned paragraph style step
309 nNum steps forwards (nStep == 1) or backwards (nStep ==
310 -1). One step is to go to the next non-null entry in
311 aCollArr in the selected direction. If nNum steps were
312 possible write the index of the entry found to aCollArr[n],
313 i.e. outline level n will be replaced by outline level
314 aCollArr[n].
316 If outline level n has no assigned paragraph style
317 aMoveArr[n] is set to -1.
319 if (aCollArr[n] != NULL)
321 USHORT m = n;
322 int nCount = nNum;
324 while (nCount > 0 && m + nStep >= 0 && m + nStep < MAXLEVEL)
326 m = static_cast<USHORT>(m + nStep);
328 if (aCollArr[m] != NULL)
329 nCount--;
332 if (nCount == 0)
333 aMoveArr[n] = m;
334 else
335 aMoveArr[n] = -1;
338 else
339 aMoveArr[n] = -1;
342 /* If moving of the outline levels is applicable, i.e. for all
343 outline levels occuring in the document there has to be a valid
344 target outline level implied by aMoveArr. */
345 bool bMoveApplicable = true;
346 for (n = nSttPos; n < nEndPos; n++)
348 SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
349 SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
350 // int nLevel = pColl->GetOutlineLevel();//#outline level,zhaojianwei
351 // if (aMoveArr[nLevel] == -1)
352 // bMoveApplicable = false;
353 if( pColl->IsAssignedToListLevelOfOutlineStyle() )
355 const int nLevel = pColl->GetAssignedOutlineStyleLevel();
356 if (aMoveArr[nLevel] == -1)
357 bMoveApplicable = false;
358 }//<-end,zhaojianwei
359 // --> OD 2008-12-16 #i70748#
360 // Check on outline level attribute of text node, if text node is
361 // not an outline via a to outline style assigned paragraph style.
362 else
364 const int nNewOutlineLevel = pTxtNd->GetAttrOutlineLevel() + nOffset;
365 if ( nNewOutlineLevel < 1 || nNewOutlineLevel > MAXLEVEL )
367 bMoveApplicable = false;
370 // <--
373 if (! bMoveApplicable )
374 return FALSE;
376 /* <-- #i13747 # */
377 if( DoesUndo() )
379 ClearRedo();
380 StartUndo(UNDO_OUTLINE_LR, NULL);
381 AppendUndo( new SwUndoOutlineLeftRight( rPam, nOffset ) );
384 // 2. allen Nodes die neue Vorlage zuweisen
386 n = nSttPos;
387 while( n < nEndPos)
389 SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
390 SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
392 if( pColl->IsAssignedToListLevelOfOutlineStyle() )
394 // ASSERT(pColl->GetOutlineLevel() < MAXLEVEL, //#outline level,removed by zhaojianwei
395 // "non outline node in outline nodes?");
396 //int nLevel = pColl->GetOutlineLevel();
397 const int nLevel = pColl->GetAssignedOutlineStyleLevel();//#outline level,add by zhaojianwei
399 ASSERT(aMoveArr[nLevel] >= 0,
400 "move table: current TxtColl not found when building table!");
403 if (nLevel < MAXLEVEL && aMoveArr[nLevel] >= 0)
405 pColl = aCollArr[ aMoveArr[nLevel] ];
407 if (pColl != NULL)
408 pColl = (SwTxtFmtColl*)pTxtNd->ChgFmtColl( pColl );
412 else if( pTxtNd->GetAttrOutlineLevel() > 0) //#outline level,add by zhaojianwei
414 int nLevel = pTxtNd->GetAttrOutlineLevel() + nOffset;
415 if( 0 <= nLevel && nLevel <= MAXLEVEL)
416 pTxtNd->SetAttrOutlineLevel( nLevel );
418 }//<-end,zhaojianwei
420 n++;
421 // Undo ???
423 if (DoesUndo())
424 EndUndo(UNDO_OUTLINE_LR, NULL);
426 ChkCondColls();
427 SetModified();
429 return TRUE;
434 // Hoch-/Runter - Verschieben !
435 BOOL SwDoc::MoveOutlinePara( const SwPaM& rPam, short nOffset )
437 // kein Verschiebung in den Sonderbereichen
438 const SwPosition& rStt = *rPam.Start(),
439 & rEnd = &rStt == rPam.GetPoint() ? *rPam.GetMark()
440 : *rPam.GetPoint();
441 if( !GetNodes().GetOutLineNds().Count() || !nOffset ||
442 rStt.nNode.GetIndex() < aNodes.GetEndOfExtras().GetIndex() ||
443 rEnd.nNode.GetIndex() < aNodes.GetEndOfExtras().GetIndex() )
444 return FALSE;
446 USHORT nAktPos = 0;
447 SwNodeIndex aSttRg( rStt.nNode ), aEndRg( rEnd.nNode );
449 //BYTE nOutLineLevel = NO_NUMBERING; //#outline level,zhaojianwei
450 int nOutLineLevel = MAXLEVEL; //<-end,zhaojianwei
451 SwNode* pSrch = &aSttRg.GetNode();
452 //if( pSrch->IsTxtNode() ) //#outline level,zhaojianwei
453 // nOutLineLevel = static_cast<BYTE>(((SwTxtNode*)pSrch)->GetOutlineLevel());
454 if( pSrch->IsTxtNode())
455 nOutLineLevel = static_cast<BYTE>(((SwTxtNode*)pSrch)->GetAttrOutlineLevel()-1);//<-end,zhaojianwei
456 SwNode* pEndSrch = &aEndRg.GetNode();
457 if( !GetNodes().GetOutLineNds().Seek_Entry( pSrch, &nAktPos ) )
459 if( !nAktPos )
460 return FALSE; // Promoting or demoting before the first outline => no.
461 if( --nAktPos )
462 aSttRg = *GetNodes().GetOutLineNds()[ nAktPos ];
463 else if( 0 > nOffset )
464 return FALSE; // Promoting at the top of document?!
465 else
466 aSttRg = *GetNodes().GetEndOfContent().StartOfSectionNode();
468 USHORT nTmpPos = 0;
469 // If the given range ends at an outlined text node we have to decide if it has to be a part of
470 // the moving range or not. Normally it will be a sub outline of our chapter
471 // and has to be moved, too. But if the chapter ends with a table(or a section end),
472 // the next text node will be choosen and this could be the next outline of the same level.
473 // The criteria has to be the outline level: sub level => incorporate, same/higher level => no.
474 if( GetNodes().GetOutLineNds().Seek_Entry( pEndSrch, &nTmpPos ) )
476 if( !pEndSrch->IsTxtNode() || pEndSrch == pSrch ||
477 //nOutLineLevel < ((SwTxtNode*)pEndSrch)->GetOutlineLevel() )//#outline level,zhaojianwei
478 nOutLineLevel < ((SwTxtNode*)pEndSrch)->GetAttrOutlineLevel()-1 )//<-end,zhaojianwei
479 ++nTmpPos; // For sub outlines only!
482 aEndRg = nTmpPos < GetNodes().GetOutLineNds().Count()
483 ? *GetNodes().GetOutLineNds()[ nTmpPos ]
484 : GetNodes().GetEndOfContent();
485 if( nOffset >= 0 )
486 nAktPos = nTmpPos;
487 if( aEndRg == aSttRg )
489 ASSERT( false, "Moving outlines: Surprising selection" );
490 aEndRg++;
493 const SwNode* pNd;
494 // The following code corrects the range to handle sections (start/end nodes)
495 // The range will be extended if the least node before the range is a start node
496 // which ends inside the range => The complete section will be moved.
497 // The range will be shrinked if the last position is a start node.
498 // The range will be shrinked if the last node is an end node which starts before the range.
499 aSttRg--;
500 while( aSttRg.GetNode().IsStartNode() )
502 pNd = aSttRg.GetNode().EndOfSectionNode();
503 if( pNd->GetIndex() >= aEndRg.GetIndex() )
504 break;
505 aSttRg--;
507 aSttRg++;
509 aEndRg--;
510 while( aEndRg.GetNode().IsStartNode() )
511 aEndRg--;
512 while( aEndRg.GetNode().IsEndNode() )
514 pNd = aEndRg.GetNode().StartOfSectionNode();
515 if( pNd->GetIndex() >= aSttRg.GetIndex() )
516 break;
517 aEndRg--;
519 aEndRg++;
521 // calculation of the new position
522 if( nOffset < 0 && nAktPos < USHORT(-nOffset) )
523 pNd = GetNodes().GetEndOfContent().StartOfSectionNode();
524 else if( nAktPos + nOffset >= GetNodes().GetOutLineNds().Count() )
525 pNd = &GetNodes().GetEndOfContent();
526 else
527 pNd = GetNodes().GetOutLineNds()[ nAktPos + nOffset ];
529 ULONG nNewPos = pNd->GetIndex();
531 // And now a correction of the insert position if necessary...
532 SwNodeIndex aInsertPos( *pNd, -1 );
533 while( aInsertPos.GetNode().IsStartNode() )
535 // Just before the insert position starts a section:
536 // when I'm moving forward I do not want to enter the section,
537 // when I'm moving backward I want to stay in the section if I'm already a part of,
538 // I want to stay outside if I was outside before.
539 if( nOffset < 0 )
541 pNd = aInsertPos.GetNode().EndOfSectionNode();
542 if( pNd->GetIndex() >= aEndRg.GetIndex() )
543 break;
545 aInsertPos--;
546 --nNewPos;
548 if( nOffset >= 0 )
550 // When just before the insert position a section ends, it is okay when I'm moving backward
551 // because I want to stay outside the section.
552 // When moving forward I've to check if I started inside or outside the section
553 // because I don't want to enter of leave such a section
554 while( aInsertPos.GetNode().IsEndNode() )
556 pNd = aInsertPos.GetNode().StartOfSectionNode();
557 if( pNd->GetIndex() >= aSttRg.GetIndex() )
558 break;
559 aInsertPos--;
560 --nNewPos;
563 // We do not want to move into tables (at the moment)
564 aInsertPos++;
565 pNd = &aInsertPos.GetNode();
566 if( pNd->IsTableNode() )
567 pNd = pNd->StartOfSectionNode();
568 if( pNd->FindTableNode() )
569 return FALSE;
571 ASSERT( aSttRg.GetIndex() > nNewPos || nNewPos >= aEndRg.GetIndex(),
572 "Position liegt im MoveBereich" );
574 // wurde ein Position in den Sonderbereichen errechnet, dann
575 // setze die Position auf den Dokumentanfang.
576 // Sollten da Bereiche oder Tabellen stehen, so werden sie nach
577 // hinten verschoben.
578 nNewPos = Max( nNewPos, aNodes.GetEndOfExtras().GetIndex() + 2 );
580 long nOffs = nNewPos - ( 0 < nOffset ? aEndRg.GetIndex() : aSttRg.GetIndex());
581 SwPaM aPam( aSttRg, aEndRg, 0, -1 );
582 return MoveParagraph( aPam, nOffs, TRUE );
586 USHORT lcl_FindOutlineName( const SwNodes& rNds, const String& rName,
587 BOOL bExact )
589 USHORT nSavePos = USHRT_MAX;
590 const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
591 for( USHORT n = 0; n < rOutlNds.Count(); ++n )
593 SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
594 String sTxt( pTxtNd->GetExpandTxt() );
595 if( sTxt.Equals( rName ) )
597 // "exact" gefunden, setze Pos auf den Node
598 nSavePos = n;
599 break;
601 else if( !bExact && USHRT_MAX == nSavePos &&
602 COMPARE_EQUAL == sTxt.CompareTo( rName, rName.Len()) )
604 // dann vielleicht nur den den 1.Teil vom Text gefunden
605 nSavePos = n;
609 return nSavePos;
614 USHORT lcl_FindOutlineNum( const SwNodes& rNds, String& rName )
616 // Gueltig Nummern sind (immer nur Offsets!!!):
617 // ([Nummer]+\.)+ (als regulaerer Ausdruck!)
618 // (Nummer gefolgt von Punkt, zum 5 Wiederholungen)
619 // also: "1.1.", "1.", "1.1.1."
620 xub_StrLen nPos = 0;
621 String sNum = rName.GetToken( 0, '.', nPos );
622 if( STRING_NOTFOUND == nPos )
623 return USHRT_MAX; // ungueltige Nummer!!!
625 USHORT nLevelVal[ MAXLEVEL ]; // Nummern aller Levels
626 memset( nLevelVal, 0, MAXLEVEL * sizeof( nLevelVal[0] ));
627 BYTE nLevel = 0;
628 String sName( rName );
630 while( STRING_NOTFOUND != nPos )
632 USHORT nVal = 0;
633 sal_Unicode c;
634 for( USHORT n = 0; n < sNum.Len(); ++n )
635 if( '0' <= ( c = sNum.GetChar( n )) && c <= '9' )
637 nVal *= 10; nVal += c - '0';
639 else if( nLevel )
640 break; // "fast" gueltige Nummer
641 else
642 return USHRT_MAX; // ungueltige Nummer!!!
644 if( MAXLEVEL > nLevel )
645 nLevelVal[ nLevel++ ] = nVal;
647 sName.Erase( 0, nPos );
648 nPos = 0;
649 sNum = sName.GetToken( 0, '.', nPos );
650 // #i4533# without this check all parts delimited by a dot are treated as outline numbers
651 if(!ByteString(sNum, gsl_getSystemTextEncoding()).IsNumericAscii())
652 nPos = STRING_NOTFOUND;
654 rName = sName; // das ist der nachfolgende Text.
656 // alle Levels gelesen, dann suche mal im Document nach dieser
657 // Gliederung:
658 const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
659 // OS: ohne OutlineNodes lohnt die Suche nicht
660 // und man spart sich einen Absturz #42958#
661 if(!rOutlNds.Count())
662 return USHRT_MAX;
663 SwTxtNode* pNd;
664 nPos = 0;
665 //search in the existing outline nodes for the required outline num array
666 for( ; nPos < rOutlNds.Count(); ++nPos )
668 pNd = rOutlNds[ nPos ]->GetTxtNode();
669 //BYTE nLvl = pNd->GetTxtColl()->GetOutlineLevel(); //#outline level,zhaojianwei
670 const int nLvl = pNd->GetAttrOutlineLevel()-1; //<-end,zhaojianwei
671 if( nLvl == nLevel - 1)
673 // check for the outline num
674 // --> OD 2005-11-02 #i51089 - TUNING#
675 // --> OD 2006-09-22 #i68289#
676 // Assure, that text node has the correct numbering level. Otherwise,
677 // its number vector will not fit to the searched level.
678 // if ( pNd->GetNum() )
679 if ( pNd->GetNum() &&
680 pNd->GetActualListLevel() == ( nLevel - 1 ) )
681 // <--
683 const SwNodeNum & rNdNum = *(pNd->GetNum());
684 SwNumberTree::tNumberVector aLevelVal = rNdNum.GetNumberVector();
685 //now compare with the one searched for
686 bool bEqual = true;
687 for( BYTE n = 0; (n < nLevel) && bEqual; ++n )
689 bEqual = aLevelVal[n] == nLevelVal[n];
691 if(bEqual)
693 break;
696 else
698 // --> OD 2006-01-12 #126588#
699 // A text node, which has an outline paragraph style applied and
700 // has as hard attribute 'no numbering' set, has an outline level,
701 // but no numbering tree node. Thus, consider this situation in
702 // the assertion condition.
703 ASSERT( !pNd->GetNumRule(),
704 "<lcl_FindOutlineNum(..)> - text node with outline level and numbering rule, but without numbering tree node. This is a serious defect -> inform OD" );
708 if( nPos >= rOutlNds.Count() )
709 nPos = USHRT_MAX;
710 return nPos;
713 // zu diesem Gliederungspunkt
716 // JP 13.06.96:
717 // im Namen kann eine Nummer oder/und der Text stehen.
718 // zuerst wird ueber die Nummer versucht den richtigen Eintrag zu finden.
719 // Gibt es diesen, dann wird ueber den Text verglichen, od es der
720 // gewuenschte ist. Ist das nicht der Fall, wird noch mal nur ueber den
721 // Text gesucht. Wird dieser gefunden ist es der Eintrag. Ansonsten der,
722 // der ueber die Nummer gefunden wurde.
723 // Ist keine Nummer angegeben, dann nur den Text suchen.
725 BOOL SwDoc::GotoOutline( SwPosition& rPos, const String& rName ) const
727 if( rName.Len() )
729 const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
731 // 1. Schritt: ueber die Nummer:
732 String sName( rName );
733 USHORT nFndPos = ::lcl_FindOutlineNum( GetNodes(), sName );
734 if( USHRT_MAX != nFndPos )
736 SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode();
737 String sExpandedText = pNd->GetExpandTxt();
738 //#i4533# leading numbers followed by a dot have been remove while
739 //searching for the outline position
740 //to compensate this they must be removed from the paragraphs text content, too
741 USHORT nPos = 0;
742 String sTempNum;
743 while(sExpandedText.Len() && (sTempNum = sExpandedText.GetToken(0, '.', nPos)).Len() &&
744 STRING_NOTFOUND != nPos &&
745 ByteString(sTempNum, gsl_getSystemTextEncoding()).IsNumericAscii())
747 sExpandedText.Erase(0, nPos);
748 nPos = 0;
751 if( !sExpandedText.Equals( sName ) )
753 USHORT nTmp = ::lcl_FindOutlineName( GetNodes(), sName, TRUE );
754 if( USHRT_MAX != nTmp ) // ueber den Namen gefunden
756 nFndPos = nTmp;
757 pNd = rOutlNds[ nFndPos ]->GetTxtNode();
760 rPos.nNode = *pNd;
761 rPos.nContent.Assign( pNd, 0 );
762 return TRUE;
765 nFndPos = ::lcl_FindOutlineName( GetNodes(), rName, FALSE );
766 if( USHRT_MAX != nFndPos )
768 SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode();
769 rPos.nNode = *pNd;
770 rPos.nContent.Assign( pNd, 0 );
771 return TRUE;
774 // --> OD 2006-09-22 #i68289#
775 // additional search on hyperlink URL without its outline numbering part
776 if ( !sName.Equals( rName ) )
778 nFndPos = ::lcl_FindOutlineName( GetNodes(), sName, FALSE );
779 if( USHRT_MAX != nFndPos )
781 SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode();
782 rPos.nNode = *pNd;
783 rPos.nContent.Assign( pNd, 0 );
784 return TRUE;
787 // <--
789 return FALSE;
792 /* \f */
794 // --- Nummerierung -----------------------------------------
796 // --> OD 2008-02-19 #refactorlists#
797 //void SwNumRuleInfo::MakeList( SwDoc& rDoc, BOOL )
799 // SwNumRule* pRule = rDoc.FindNumRulePtr(rName);
801 // // no rule, no fun.
802 // if ( !pRule )
803 // return;
805 // //
806 // // 1. Case: Information already available at pRule:
807 // //
808 // if (pRule->GetTxtNodeList())
809 // {
810 // // copy list to own pList pointer:
811 // aList = *pRule->GetTxtNodeList();
812 // return;
813 // }
815 // //
816 // // 2. Case: Information has to be generated from scratch:
817 // //
819 // if (pRule->IsOutlineRule())
820 // {
821 // const SwOutlineNodes & rOutlineNodes = rDoc.GetNodes().GetOutLineNds();
823 // for (USHORT i = 0; i < rOutlineNodes.Count(); ++i)
824 // {
825 // SwTxtNode & aNode = *((SwTxtNode *) rOutlineNodes[i]);
827 // if (pRule == aNode.GetNumRule())
828 // AddNode(aNode);
829 // }
830 // }
831 // {
832 // SwModify* pMod;
833 // const SfxPoolItem* pItem;
834 // USHORT i, nMaxItems = rDoc.GetAttrPool().GetItemCount
835 // ( RES_PARATR_NUMRULE);
836 // for( i = 0; i < nMaxItems; ++i )
837 // {
838 // pItem = rDoc.GetAttrPool().GetItem( RES_PARATR_NUMRULE, i );
839 // if( 0 != pItem)
840 // {
841 // pMod = (SwModify*)((SwNumRuleItem*)pItem)->GetDefinedIn();
842 // if (0 != pMod &&
843 // ((SwNumRuleItem*)pItem)->GetValue().Len() &&
844 // ((SwNumRuleItem*)pItem)->GetValue() == rName )
845 // {
846 // if( pMod->IsA( TYPE( SwFmt )) )
847 // pMod->GetInfo( *this );
848 // else
849 // {
850 // SwTxtNode* pModTxtNode = (SwTxtNode*)pMod;
852 // // #115901#
853 // if( pModTxtNode->GetNodes().IsDocNodes())
854 // {
855 // AddNode( *pModTxtNode );
856 // }
857 // }
858 // }
859 // }
860 // }
861 // }
863 // // --> FME 2004-11-03 #i36571# The numrule and this info structure should
864 // // have different instances of the list:
865 // // --> OD 2006-09-12 #i69145#
866 // // method <SwNumRule::SetList(..)> copies content of list provided by the parameter
867 // pRule->SetTxtNodeList( aList );
868 // // <--
870 // <--
873 void lcl_ChgNumRule( SwDoc& rDoc, const SwNumRule& rRule )
875 SwNumRule* pOld = rDoc.FindNumRulePtr( rRule.GetName() );
876 ASSERT( pOld, "ohne die alte NumRule geht gar nichts" );
878 USHORT nChgFmtLevel = 0, nMask = 1;
879 BYTE n;
881 for( n = 0; n < MAXLEVEL; ++n, nMask <<= 1 )
883 const SwNumFmt& rOldFmt = pOld->Get( n ),
884 & rNewFmt = rRule.Get( n );
886 if( rOldFmt != rNewFmt )
888 nChgFmtLevel |= nMask;
890 else if( SVX_NUM_NUMBER_NONE > rNewFmt.GetNumberingType() && 1 < rNewFmt.GetIncludeUpperLevels() &&
891 0 != (nChgFmtLevel & GetUpperLvlChg( n, rNewFmt.GetIncludeUpperLevels(),nMask )) )
892 nChgFmtLevel |= nMask;
895 if( !nChgFmtLevel ) // es wurde nichts veraendert?
897 // --> OD 2006-04-27 #i64311#
898 const bool bInvalidateNumRule( pOld->IsContinusNum() != rRule.IsContinusNum() );
899 // <--
900 pOld->CheckCharFmts( &rDoc );
901 pOld->SetContinusNum( rRule.IsContinusNum() );
902 // --> OD 2008-06-17 #i87166#
903 // Do NOT change list style type
904 // pOld->SetRuleType( rRule.GetRuleType() );
905 // <--
906 // --> OD 2006-04-27 #i64311#
907 if ( bInvalidateNumRule )
909 pOld->SetInvalidRule(TRUE);
911 // <--
912 return ;
915 // --> OD 2008-02-19 #refactorlists#
916 // SwNumRuleInfo* pUpd = new SwNumRuleInfo( rRule.GetName() );
917 // pUpd->MakeList( rDoc );
919 // BYTE nLvl;
920 // for( ULONG nFirst = 0, nLast = pUpd->GetList().Count();
921 // nFirst < nLast; ++nFirst )
922 // {
923 // SwTxtNode* pTxtNd = pUpd->GetList().GetObject( nFirst );
924 // nLvl = static_cast<BYTE>(pTxtNd->GetLevel());
926 // if( nLvl < MAXLEVEL )
927 // {
928 // if( nChgFmtLevel & ( 1 << nLvl ))
929 // {
930 // pTxtNd->NumRuleChgd();
931 // }
932 // }
933 // }
934 SwNumRule::tTxtNodeList aTxtNodeList;
935 pOld->GetTxtNodeList( aTxtNodeList );
936 BYTE nLvl( 0 );
937 for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
938 aIter != aTxtNodeList.end(); ++aIter )
940 SwTxtNode* pTxtNd = *aIter;
941 nLvl = static_cast<BYTE>(pTxtNd->GetActualListLevel());
943 if( nLvl < MAXLEVEL )
945 if( nChgFmtLevel & ( 1 << nLvl ))
947 pTxtNd->NumRuleChgd();
951 // <--
953 for( n = 0; n < MAXLEVEL; ++n )
954 if( nChgFmtLevel & ( 1 << n ))
955 pOld->Set( n, rRule.GetNumFmt( n ));
957 pOld->CheckCharFmts( &rDoc );
958 pOld->SetInvalidRule(TRUE);
959 pOld->SetContinusNum( rRule.IsContinusNum() );
960 // --> OD 2008-06-17 #i87166#
961 // Do NOT change list style type
962 // pOld->SetRuleType( rRule.GetRuleType() );
963 // <--
965 // --> OD 2008-02-19 #refactorlists#
966 // delete pUpd;
967 // <--
969 rDoc.UpdateNumRule();
972 // OD 2008-02-08 #newlistlevelattrs# - add handling of parameter <bResetIndentAttrs>
973 // --> OD 2008-03-17 #refactorlists#
974 void SwDoc::SetNumRule( const SwPaM& rPam,
975 const SwNumRule& rRule,
976 const bool bCreateNewList,
977 const String sContinuedListId,
978 sal_Bool bSetItem,
979 const bool bResetIndentAttrs )
981 SwUndoInsNum * pUndo = NULL;
982 if (DoesUndo())
984 ClearRedo();
985 StartUndo( UNDO_INSNUM, NULL ); // Klammerung fuer die Attribute!
986 AppendUndo( pUndo = new SwUndoInsNum( rPam, rRule ) );
989 SwNumRule * pNew = FindNumRulePtr( rRule.GetName() );
990 bool bUpdateRule = false;
992 if( !pNew )
994 pNew = (*pNumRuleTbl)[ MakeNumRule( rRule.GetName(), &rRule ) ];
996 else if (rRule != *pNew)
998 bUpdateRule = true;
1001 if (bUpdateRule)
1003 if( pUndo )
1005 pUndo->SaveOldNumRule( *pNew );
1006 ::lcl_ChgNumRule( *this, rRule );
1007 pUndo->SetLRSpaceEndPos();
1009 else
1011 ::lcl_ChgNumRule( *this, rRule );
1015 // --> OD 2008-03-17 #refactorlists#
1016 if ( bSetItem )
1018 if ( bCreateNewList )
1020 String sListId;
1021 if ( !bUpdateRule )
1023 // apply list id of list, which has been created for the new list style
1024 sListId = pNew->GetDefaultListId();
1026 else
1028 // create new list and apply its list id
1029 SwList* pNewList = createList( String(), pNew->GetName() );
1030 ASSERT( pNewList,
1031 "<SwDoc::SetNumRule(..)> - could not create new list. Serious defect -> please inform OD." );
1032 sListId = pNewList->GetListId();
1034 InsertPoolItem( rPam,
1035 SfxStringItem( RES_PARATR_LIST_ID, sListId ), 0 );
1037 else if ( sContinuedListId.Len() > 0 )
1039 // apply given list id
1040 InsertPoolItem( rPam,
1041 SfxStringItem( RES_PARATR_LIST_ID, sContinuedListId ), 0 );
1044 // <--
1046 if ( ! rPam.HasMark())
1048 SwTxtNode * pTxtNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
1049 // --> OD 2006-10-19 #134160#
1050 // consider case that the PaM doesn't denote a text node - e.g. it denotes a graphic node
1051 if ( pTxtNd )
1053 SwNumRule * pRule = pTxtNd->GetNumRule();
1055 if (pRule && pRule->GetName() == pNew->GetName())
1057 bSetItem = sal_False;
1058 // --> OD 2008-06-02 #refactorlists#
1059 if ( !pTxtNd->IsInList() )
1061 pTxtNd->AddToList();
1063 // <--
1065 // --> OD 2005-10-26 #b6340308# - only clear numbering attribute at
1066 // text node, if at paragraph style the new numbering rule is found.
1067 else if ( !pRule )
1069 SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
1070 if ( pColl )
1072 SwNumRule* pCollRule = FindNumRulePtr(pColl->GetNumRule().GetValue());
1073 if ( pCollRule && pCollRule->GetName() == pNew->GetName() )
1075 pTxtNd->ResetAttr( RES_PARATR_NUMRULE );
1076 bSetItem = sal_False;
1080 // <--
1082 // <--
1085 // --> OD 2009-08-18 #i103817#
1086 if ( bSetItem )
1087 // <--
1089 InsertPoolItem( rPam, SwNumRuleItem( pNew->GetName() ), 0 );
1092 // --> OD 2008-02-08 #newlistlevelattrs#
1093 if ( bResetIndentAttrs &&
1094 pNew && pNew->Get( 0 ).GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
1096 SvUShortsSort aResetAttrsArray;
1097 aResetAttrsArray.Insert( RES_LR_SPACE );
1098 ResetAttrs( rPam, sal_True, &aResetAttrsArray );
1100 // <--
1102 if (DoesUndo())
1103 EndUndo( UNDO_INSNUM, NULL );
1105 SetModified();
1108 void SwDoc::SetCounted(const SwPaM & rPam, bool bCounted)
1110 // --> OD 2008-04-03 #refactorlists#
1111 // ULONG nStartPos = rPam.Start()->nNode.GetIndex();
1112 // ULONG nEndPos = rPam.End()->nNode.GetIndex();
1114 // for (ULONG n = nStartPos; n <= nEndPos; n++)
1115 // {
1116 // SwTxtNode * pNd = GetNodes()[n]->GetTxtNode();
1118 // if (pNd)
1119 // pNd->SetCountedInList(bCounted);
1120 // }
1121 if ( bCounted )
1123 SvUShortsSort aResetAttrsArray;
1124 aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
1125 ResetAttrs( rPam, sal_True, &aResetAttrsArray );
1127 else
1129 InsertPoolItem( rPam,
1130 SfxBoolItem( RES_PARATR_LIST_ISCOUNTED, FALSE ), 0 );
1134 //void SwDoc::ReplaceNumRule(const SwPaM & rPaM, const SwNumRule & rNumRule)
1136 // if (DoesUndo())
1137 // StartUndo(UNDO_START, NULL);
1139 // ULONG nStt = rPaM.Start()->nNode.GetIndex();
1140 // ULONG nEnd = rPaM.End()->nNode.GetIndex();
1142 // for (ULONG n = nStt; n <= nEnd; n++)
1143 // {
1144 // SwTxtNode * pCNd = GetNodes()[n]->GetTxtNode();
1146 // if (pCNd && NULL != pCNd->GetNumRule())
1147 // {
1148 // SwPaM aPam(*pCNd);
1150 // InsertPoolItem(aPam, SwNumRuleItem(rNumRule.GetName()), 0);
1151 // }
1152 // }
1154 // if (DoesUndo())
1155 // EndUndo(UNDO_START, NULL);
1158 void SwDoc::SetNumRuleStart( const SwPosition& rPos, BOOL bFlag )
1160 SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
1162 if (pTxtNd)
1164 const SwNumRule* pRule = pTxtNd->GetNumRule();
1165 if( pRule && !bFlag != !pTxtNd->IsListRestart())
1167 if( DoesUndo() )
1169 ClearRedo();
1170 AppendUndo( new SwUndoNumRuleStart( rPos, bFlag ));
1173 pTxtNd->SetListRestart(bFlag ? true : false);
1175 SetModified();
1180 void SwDoc::SetNodeNumStart( const SwPosition& rPos, USHORT nStt )
1182 SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
1184 if (pTxtNd)
1186 // --> OD 2008-02-27 #refactorlists#
1187 // const SwNumRule* pRule = pTxtNd->GetNumRule();
1188 // if( pRule && nStt != pTxtNd->GetListRestartValue() )
1189 // {
1190 // if( DoesUndo() )
1191 // {
1192 // ClearRedo();
1193 // AppendUndo( new SwUndoNumRuleStart( rPos, nStt ));
1194 // }
1195 // }
1196 // pTxtNd->SetListRestartValue(nStt);
1198 // SetModified();
1199 if ( !pTxtNd->HasAttrListRestartValue() ||
1200 pTxtNd->GetAttrListRestartValue() != nStt )
1202 if( DoesUndo() )
1204 ClearRedo();
1205 AppendUndo( new SwUndoNumRuleStart( rPos, nStt ));
1207 pTxtNd->SetAttrListRestartValue( nStt );
1209 SetModified();
1211 // <--
1215 // loeschen geht nur, wenn die Rule niemand benutzt!
1216 BOOL SwDoc::DelNumRule( const String& rName, BOOL bBroadcast )
1218 USHORT nPos = FindNumRule( rName );
1220 // --> OD 2007-12-17 #151213#
1221 if ( (*pNumRuleTbl)[ nPos ] == GetOutlineNumRule() )
1223 ASSERT( false,
1224 "<SwDoc::DelNumRule(..)> - No deletion of outline list style. This is serious defect - please inform OD" );
1225 return FALSE;
1227 // <--
1229 if( USHRT_MAX != nPos && !IsUsed( *(*pNumRuleTbl)[ nPos ] ))
1231 if (DoesUndo())
1233 SwUndo * pUndo =
1234 new SwUndoNumruleDelete(*(*pNumRuleTbl)[nPos], this);
1236 AppendUndo(pUndo);
1239 if (bBroadcast)
1240 BroadcastStyleOperation(rName, SFX_STYLE_FAMILY_PSEUDO,
1241 SFX_STYLESHEET_ERASED);
1243 // --> OD 2008-04-02 #refactorlists#
1244 deleteListForListStyle( rName );
1246 // delete further list, which have the deleted list style as default list style
1247 std::vector< SwList* > aListsForDeletion;
1248 tHashMapForLists::iterator aListIter = maLists.begin();
1249 while ( aListIter != maLists.end() )
1251 SwList* pList = (*aListIter).second;
1252 if ( pList->GetDefaultListStyleName() == rName )
1254 aListsForDeletion.push_back( pList );
1257 ++aListIter;
1259 while ( aListsForDeletion.size() > 0 )
1261 SwList* pList = aListsForDeletion.back();
1262 aListsForDeletion.pop_back();
1263 deleteList( pList->GetListId() );
1266 // <--
1267 // --> FME 2004-11-02 #i34097# DeleteAndDestroy deletes rName if
1268 // rName is directly taken from the numrule.
1269 const String aTmpName( rName );
1270 // <--
1271 pNumRuleTbl->DeleteAndDestroy( nPos );
1272 maNumRuleMap.erase(aTmpName);
1274 SetModified();
1275 return TRUE;
1277 return FALSE;
1280 // #106897#
1281 void SwDoc::ChgNumRuleFmts( const SwNumRule& rRule, const String * pName )
1283 // #106897#
1284 SwNumRule* pRule = FindNumRulePtr( pName ? *pName : rRule.GetName() );
1285 if( pRule )
1287 SwUndoInsNum* pUndo = 0;
1288 if( DoesUndo() )
1290 ClearRedo();
1291 pUndo = new SwUndoInsNum( *pRule, rRule );
1292 pUndo->GetHistory();
1293 AppendUndo( pUndo );
1295 ::lcl_ChgNumRule( *this, rRule );
1297 if( pUndo )
1298 pUndo->SetLRSpaceEndPos();
1300 SetModified();
1304 sal_Bool SwDoc::RenameNumRule(const String & rOldName, const String & rNewName,
1305 BOOL bBroadcast)
1307 sal_Bool bResult = sal_False;
1308 SwNumRule * pNumRule = FindNumRulePtr(rOldName);
1310 if (pNumRule)
1312 if (DoesUndo())
1314 SwUndo * pUndo = new SwUndoNumruleRename(rOldName, rNewName, this);
1316 AppendUndo(pUndo);
1319 // --> OD 2008-02-19 #refactorlists#
1320 // SwNumRuleInfo aInfo(rOldName);
1321 // aInfo.MakeList(*this);
1322 SwNumRule::tTxtNodeList aTxtNodeList;
1323 pNumRule->GetTxtNodeList( aTxtNodeList );
1324 // <--
1326 // --> OD 2008-07-08 #i91400#
1327 pNumRule->SetName( rNewName, *this );
1328 // <--
1330 SwNumRuleItem aItem(rNewName);
1331 // --> OD 2008-02-19 #refactorlists#
1332 // for (ULONG nI = 0; nI < aInfo.GetList().Count(); ++nI)
1333 // {
1334 // SwTxtNode * pTxtNd = aInfo.GetList().GetObject(nI);
1335 // pTxtNd->SwCntntNode::SetAttr(aItem);
1336 // }
1337 for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
1338 aIter != aTxtNodeList.end(); ++aIter )
1340 SwTxtNode * pTxtNd = *aIter;
1341 pTxtNd->SetAttr(aItem);
1343 // <--
1345 bResult = sal_True;
1347 if (bBroadcast)
1348 BroadcastStyleOperation(rOldName, SFX_STYLE_FAMILY_PSEUDO,
1349 SFX_STYLESHEET_MODIFIED);
1352 return bResult;
1355 void SwDoc::StopNumRuleAnimations( OutputDevice* pOut )
1357 for( USHORT n = GetNumRuleTbl().Count(); n; )
1359 // --> OD 2008-02-19 #refactorlists#
1360 // SwNumRuleInfo aUpd( GetNumRuleTbl()[ --n ]->GetName() );
1361 // aUpd.MakeList( *this );
1363 // for( ULONG nFirst = 0, nLast = aUpd.GetList().Count();
1364 // nFirst < nLast; ++nFirst )
1365 // {
1366 // SwTxtNode* pTNd = aUpd.GetList().GetObject( nFirst );
1367 // SwClientIter aIter( *pTNd );
1368 // for( SwFrm* pFrm = (SwFrm*)aIter.First( TYPE(SwFrm) );
1369 // pFrm; pFrm = (SwFrm*)aIter.Next() )
1370 // if( ((SwTxtFrm*)pFrm)->HasAnimation() )
1371 // ((SwTxtFrm*)pFrm)->StopAnimation( pOut );
1372 // }
1373 SwNumRule::tTxtNodeList aTxtNodeList;
1374 GetNumRuleTbl()[ --n ]->GetTxtNodeList( aTxtNodeList );
1375 for ( SwNumRule::tTxtNodeList::iterator aTxtNodeIter = aTxtNodeList.begin();
1376 aTxtNodeIter != aTxtNodeList.end(); ++aTxtNodeIter )
1378 SwTxtNode* pTNd = *aTxtNodeIter;
1379 SwClientIter aIter( *pTNd );
1380 for( SwFrm* pFrm = (SwFrm*)aIter.First( TYPE(SwFrm) );
1381 pFrm; pFrm = (SwFrm*)aIter.Next() )
1382 if( ((SwTxtFrm*)pFrm)->HasAnimation() )
1383 ((SwTxtFrm*)pFrm)->StopAnimation( pOut );
1385 // <--
1389 BOOL SwDoc::ReplaceNumRule( const SwPosition& rPos,
1390 const String& rOldRule, const String& rNewRule )
1392 BOOL bRet = FALSE;
1393 SwNumRule *pOldRule = FindNumRulePtr( rOldRule ),
1394 *pNewRule = FindNumRulePtr( rNewRule );
1395 if( pOldRule && pNewRule && pOldRule != pNewRule )
1397 // --> OD 2008-02-19 #refactorlists#
1398 SwUndoInsNum* pUndo = 0;
1399 if( DoesUndo() )
1401 ClearRedo();
1402 StartUndo( UNDO_START, NULL ); // Klammerung fuer die Attribute!
1403 AppendUndo( pUndo = new SwUndoInsNum( rPos, *pNewRule, rOldRule ) );
1406 // --> OD 2008-02-19 #refactorlists#
1407 // apply new list style <pNewRule> to all text nodes, which have the
1408 // old list style <pOldNRule> applied and belong to the same list as
1409 // the text node of the given <SwPosition>.
1410 // SwNumRuleInfo aUpd( rOldRule );
1411 // aUpd.MakeList( *this );
1413 // if (aUpd.GetList().Count() > 0) // #106897#
1414 SwNumRule::tTxtNodeList aTxtNodeList;
1415 pOldRule->GetTxtNodeList( aTxtNodeList );
1416 if ( aTxtNodeList.size() > 0 )
1418 // // Position suchen und bestimme ob ein Node davor oder dahinter
1419 // // einen Start erzwingt
1420 // SwTxtNode* pTxtNd;
1421 // ULONG nFndPos, nFirst, nLast;
1423 // if( TABLE_ENTRY_NOTFOUND != aUpd.GetList().SearchKey(
1424 // rPos.nNode.GetIndex(), &nFndPos ))
1425 // ++nFndPos;
1427 // for( nLast = nFndPos; nLast < aUpd.GetList().Count(); ++nLast )
1428 // {
1429 // pTxtNd = aUpd.GetList().GetObject( nLast );
1430 // if(pTxtNd->IsRestart())
1431 // break;
1432 // }
1433 // for( nFirst = nFndPos; nFirst; )
1434 // {
1435 // pTxtNd = aUpd.GetList().GetObject( --nFirst );
1436 // if( pTxtNd->IsRestart() )
1437 // break;
1438 // }
1439 // // dann neue Numerierung ueber diesen Bereich
1440 // // definieren und den Start am Anfang/Ende zurueck setzen
1441 // pTxtNd = aUpd.GetList().GetObject( nFirst );
1442 // if( pTxtNd->IsRestart() )
1443 // {
1444 // pTxtNd->SetRestart(false);
1445 // if( pUndo )
1446 // pUndo->SetSttNum( pTxtNd->GetIndex() );
1447 // }
1449 SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
1450 USHORT nChgFmtLevel = 0;
1451 for( BYTE n = 0; n < MAXLEVEL; ++n )
1453 const SwNumFmt& rOldFmt = pOldRule->Get( n ),
1454 & rNewFmt = pNewRule->Get( n );
1456 if( rOldFmt.GetAbsLSpace() != rNewFmt.GetAbsLSpace() ||
1457 rOldFmt.GetFirstLineOffset() != rNewFmt.GetFirstLineOffset() )
1458 nChgFmtLevel |= ( 1 << n );
1461 const SwTxtNode* pGivenTxtNode = rPos.nNode.GetNode().GetTxtNode();
1462 SwNumRuleItem aRule( rNewRule );
1463 // for( ; nFirst < nLast; ++nFirst )
1464 // {
1465 // pTxtNd = aUpd.GetList().GetObject( nFirst );
1467 // aRegH.RegisterInModify( pTxtNd, *pTxtNd );
1469 // pTxtNd->SwCntntNode::SetAttr( aRule );
1470 // pTxtNd->NumRuleChgd();
1471 // }
1472 for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
1473 aIter != aTxtNodeList.end(); ++aIter )
1475 SwTxtNode* pTxtNd = *aIter;
1477 if ( pGivenTxtNode &&
1478 pGivenTxtNode->GetListId() == pTxtNd->GetListId() )
1480 aRegH.RegisterInModify( pTxtNd, *pTxtNd );
1482 pTxtNd->SetAttr( aRule );
1483 pTxtNd->NumRuleChgd();
1486 EndUndo( UNDO_END, NULL );
1487 SetModified();
1489 bRet = TRUE; // #106897#
1493 return bRet;
1496 // --> OD 2008-03-18 #refactorlists#
1497 namespace
1499 struct ListStyleData
1501 SwNumRule* pReplaceNumRule;
1502 bool bCreateNewList;
1503 String sListId;
1505 ListStyleData()
1506 : pReplaceNumRule( 0 ),
1507 bCreateNewList( false ),
1508 sListId()
1512 // <--
1514 void SwDoc::MakeUniqueNumRules(const SwPaM & rPaM)
1516 ASSERT( rPaM.GetDoc() == this, "need same doc" );
1518 // --> OD 2008-03-18 #refactorlists#
1519 // map<SwNumRule *, SwNumRule *> aMyNumRuleMap;
1520 ::std::map<SwNumRule *, ListStyleData> aMyNumRuleMap;
1521 // <--
1523 ULONG nStt = rPaM.Start()->nNode.GetIndex();
1524 ULONG nEnd = rPaM.End()->nNode.GetIndex();
1526 bool bFirst = true;
1528 for (ULONG n = nStt; n <= nEnd; n++)
1530 SwTxtNode * pCNd = GetNodes()[n]->GetTxtNode();
1532 if (pCNd)
1534 SwNumRule * pRule = pCNd->GetNumRule();
1536 if (pRule && pRule->IsAutoRule() && ! pRule->IsOutlineRule())
1538 // --> OD 2008-03-18 #refactorlists#
1539 // SwNumRule * pReplaceNumRule = aMyNumRuleMap[pRule];
1540 ListStyleData aListStyleData = aMyNumRuleMap[pRule];
1542 // if (! pReplaceNumRule)
1543 if ( aListStyleData.pReplaceNumRule == 0 )
1545 if (bFirst)
1547 SwPosition aPos(*pCNd);
1548 aListStyleData.pReplaceNumRule =
1549 const_cast<SwNumRule *>
1550 (SearchNumRule( aPos, false, pCNd->HasNumber(),
1551 false, 0,
1552 aListStyleData.sListId, true ));
1555 // if (! pReplaceNumRule)
1556 if ( aListStyleData.pReplaceNumRule == 0 )
1558 // pReplaceNumRule = new SwNumRule(*pRule);
1559 // pReplaceNumRule->SetName(GetUniqueNumRuleName());
1560 aListStyleData.pReplaceNumRule = new SwNumRule(*pRule);
1561 // --> OD 2008-07-08 #i91400#
1562 aListStyleData.pReplaceNumRule->SetName(
1563 GetUniqueNumRuleName(), *this );
1564 // <--
1565 aListStyleData.bCreateNewList = true;
1568 // aMyNumRuleMap[pRule] = pReplaceNumRule;
1569 aMyNumRuleMap[pRule] = aListStyleData;
1572 SwPaM aPam(*pCNd);
1574 SetNumRule( aPam, *aListStyleData.pReplaceNumRule,
1575 aListStyleData.bCreateNewList,
1576 aListStyleData.sListId );
1577 if ( aListStyleData.bCreateNewList )
1579 aListStyleData.bCreateNewList = false;
1580 aListStyleData.sListId = pCNd->GetListId();
1581 aMyNumRuleMap[pRule] = aListStyleData;
1583 // <--
1585 bFirst = false;
1591 BOOL SwDoc::NoNum( const SwPaM& rPam )
1594 BOOL bRet = SplitNode( *rPam.GetPoint(), false );
1595 // ist ueberhaupt Nummerierung im Spiel ?
1596 if( bRet )
1598 // NoNum setzen und Upaten
1599 const SwNodeIndex& rIdx = rPam.GetPoint()->nNode;
1600 SwTxtNode* pNd = rIdx.GetNode().GetTxtNode();
1601 const SwNumRule* pRule = pNd->GetNumRule();
1602 if( pRule )
1604 pNd->SetCountedInList(false);
1606 SetModified();
1608 else
1609 bRet = FALSE; // keine Nummerierung , ?? oder immer TRUE ??
1611 return bRet;
1614 void SwDoc::DelNumRules( const SwPaM& rPam )
1616 ULONG nStt = rPam.GetPoint()->nNode.GetIndex(),
1617 nEnd = rPam.GetMark()->nNode.GetIndex();
1618 if( nStt > nEnd )
1620 ULONG nTmp = nStt; nStt = nEnd; nEnd = nTmp;
1623 SwUndoDelNum* pUndo;
1624 if( DoesUndo() )
1626 ClearRedo();
1627 AppendUndo( pUndo = new SwUndoDelNum( rPam ) );
1629 else
1630 pUndo = 0;
1632 SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
1634 SwNumRuleItem aEmptyRule( aEmptyStr );
1635 const SwNode* pOutlNd = 0;
1636 for( ; nStt <= nEnd; ++nStt )
1638 SwTxtNode* pTNd = GetNodes()[ nStt ]->GetTxtNode();
1639 // --> OD 2008-03-13 #refactorlists#
1640 // if( pTNd && 0 != ( pItem = pTNd->GetNoCondAttr(
1641 // RES_PARATR_NUMRULE, TRUE ) ) &&
1642 // ( pName = &((SwNumRuleItem*)pItem)->GetValue())->Len() )
1643 SwNumRule* pNumRuleOfTxtNode = pTNd ? pTNd->GetNumRule() : 0;
1644 if ( pTNd && pNumRuleOfTxtNode )
1645 // <--
1647 // recognize changes of attribute for undo
1648 aRegH.RegisterInModify( pTNd, *pTNd );
1650 if( pUndo )
1651 pUndo->AddNode( *pTNd, FALSE );
1653 // directly set list style attribute is reset, otherwise empty
1654 // list style is applied
1655 const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet();
1656 if ( pAttrSet &&
1657 pAttrSet->GetItemState( RES_PARATR_NUMRULE, FALSE ) == SFX_ITEM_SET )
1658 pTNd->ResetAttr( RES_PARATR_NUMRULE );
1659 else
1660 pTNd->SetAttr( aEmptyRule );
1662 // --> OD 2008-03-26 #refactorlists#
1663 pTNd->ResetAttr( RES_PARATR_LIST_ID );
1664 pTNd->ResetAttr( RES_PARATR_LIST_LEVEL );
1665 pTNd->ResetAttr( RES_PARATR_LIST_ISRESTART );
1666 pTNd->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
1667 pTNd->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
1668 // <--
1670 if( RES_CONDTXTFMTCOLL == pTNd->GetFmtColl()->Which() )
1671 pTNd->ChkCondColl();
1672 //else if( !pOutlNd && NO_NUMBERING != //#outline level,zhaojianwei
1673 // ((SwTxtFmtColl*)pTNd->GetFmtColl())->GetOutlineLevel() )
1674 else if( !pOutlNd &&
1675 ((SwTxtFmtColl*)pTNd->GetFmtColl())->IsAssignedToListLevelOfOutlineStyle() )//<-end,zhaojianwei
1676 pOutlNd = pTNd;
1680 // dann noch alle Updaten
1681 UpdateNumRule();
1683 if( pOutlNd )
1684 GetNodes().UpdtOutlineIdx( *pOutlNd );
1687 void SwDoc::InvalidateNumRules()
1689 for (USHORT n = 0; n < pNumRuleTbl->Count(); ++n)
1690 (*pNumRuleTbl)[n]->SetInvalidRule(TRUE);
1693 // zum naechsten/vorhergehenden Punkt auf gleicher Ebene
1695 BOOL lcl_IsNumOk( BYTE nSrchNum, BYTE& rLower, BYTE& rUpper,
1696 BOOL bOverUpper, BYTE nNumber )
1698 // --> OD 2008-04-02 #refactorlists#
1699 ASSERT( nNumber < MAXLEVEL,
1700 "<lcl_IsNumOk(..)> - misusage of method" );
1701 // <--
1703 BOOL bRet = FALSE;
1705 if( bOverUpper ? nSrchNum == nNumber : nSrchNum >= nNumber )
1706 bRet = TRUE;
1707 else if( nNumber > rLower )
1708 rLower = nNumber;
1709 else if( nNumber < rUpper )
1710 rUpper = nNumber;
1712 return bRet;
1715 BOOL lcl_IsValidPrevNextNumNode( const SwNodeIndex& rIdx )
1717 BOOL bRet = FALSE;
1718 const SwNode& rNd = rIdx.GetNode();
1719 switch( rNd.GetNodeType() )
1721 case ND_ENDNODE:
1722 bRet = SwTableBoxStartNode == rNd.StartOfSectionNode()->GetStartNodeType() ||
1723 rNd.StartOfSectionNode()->IsSectionNode();
1724 break;
1726 case ND_STARTNODE:
1727 bRet = SwTableBoxStartNode == ((SwStartNode&)rNd).GetStartNodeType();
1728 break;
1730 case ND_SECTIONNODE: // der ist erlaubt, also weiter
1731 bRet = TRUE;
1732 break;
1734 return bRet;
1737 BOOL lcl_GotoNextPrevNum( SwPosition& rPos, BOOL bNext,
1738 BOOL bOverUpper, BYTE* pUpper, BYTE* pLower )
1740 const SwTxtNode* pNd = rPos.nNode.GetNode().GetTxtNode();
1741 const SwNumRule* pRule;
1742 if( !pNd || 0 == ( pRule = pNd->GetNumRule()))
1743 return FALSE;
1745 BYTE nSrchNum = static_cast<BYTE>(pNd->GetActualListLevel());
1747 SwNodeIndex aIdx( rPos.nNode );
1748 if( ! pNd->IsCountedInList() )
1750 // falls gerade mal NO_NUMLEVEL an ist, so such den vorherigen Node
1751 // mit Nummerierung
1752 BOOL bError = FALSE;
1753 do {
1754 aIdx--;
1755 if( aIdx.GetNode().IsTxtNode() )
1757 pNd = aIdx.GetNode().GetTxtNode();
1758 pRule = pNd->GetNumRule();
1760 BYTE nTmpNum;
1762 if( pRule )
1764 nTmpNum = static_cast<BYTE>(pNd->GetActualListLevel());
1765 if( !( ! pNd->IsCountedInList() &&
1766 (nTmpNum >= nSrchNum )) )
1767 break; // gefunden
1769 else
1770 bError = TRUE;
1772 else
1773 bError = !lcl_IsValidPrevNextNumNode( aIdx );
1775 } while( !bError );
1776 if( bError )
1777 return FALSE;
1780 BYTE nLower = nSrchNum, nUpper = nSrchNum;
1781 BOOL bRet = FALSE;
1783 const SwTxtNode* pLast;
1784 if( bNext )
1785 aIdx++, pLast = pNd;
1786 else
1787 aIdx--, pLast = 0;
1789 while( bNext ? ( aIdx.GetIndex() < aIdx.GetNodes().Count() - 1 )
1790 : aIdx.GetIndex() )
1792 if( aIdx.GetNode().IsTxtNode() )
1794 pNd = aIdx.GetNode().GetTxtNode();
1795 pRule = pNd->GetNumRule();
1796 if( pRule )
1798 if( ::lcl_IsNumOk( nSrchNum, nLower, nUpper, bOverUpper,
1799 static_cast<BYTE>(pNd->GetActualListLevel()) ))
1801 rPos.nNode = aIdx;
1802 rPos.nContent.Assign( (SwTxtNode*)pNd, 0 );
1803 bRet = TRUE;
1804 break;
1806 else
1807 pLast = pNd;
1809 else
1810 break;
1812 else if( !lcl_IsValidPrevNextNumNode( aIdx ))
1813 break;
1815 if( bNext )
1816 aIdx++;
1817 else
1818 aIdx--;
1821 if( !bRet && !bOverUpper && pLast ) // nicht ueber hoehere Nummmern, aber bis Ende
1823 if( bNext )
1825 rPos.nNode = aIdx;
1826 if( aIdx.GetNode().IsCntntNode() )
1827 rPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), 0 );
1829 else
1831 rPos.nNode.Assign( *pLast );
1832 rPos.nContent.Assign( (SwTxtNode*)pLast, 0 );
1834 bRet = TRUE;
1837 if( bRet )
1839 if( pUpper )
1840 *pUpper = nUpper;
1841 if( pLower )
1842 *pLower = nLower;
1844 return bRet;
1847 BOOL SwDoc::GotoNextNum( SwPosition& rPos, BOOL bOverUpper,
1848 BYTE* pUpper, BYTE* pLower )
1850 return ::lcl_GotoNextPrevNum( rPos, TRUE, bOverUpper, pUpper, pLower );
1853 // -> #i23731#
1854 // --> OD 2008-03-18 #refactorlists# - add output parameter <sListId>
1855 const SwNumRule * SwDoc::SearchNumRule(const SwPosition & rPos,
1856 const bool bForward,
1857 const bool bNum,
1858 const bool bOutline,
1859 int nNonEmptyAllowed,
1860 String& sListId,
1861 const bool bInvestigateStartNode)
1863 const SwNumRule * pResult = NULL;
1864 SwTxtNode * pTxtNd = rPos.nNode.GetNode().GetTxtNode();
1865 SwNode * pStartFromNode = pTxtNd;
1867 if (pTxtNd)
1869 SwNodeIndex aIdx(rPos.nNode);
1871 // --> OD 2005-10-20 #i55391#
1872 // - the start node has also been investigated, if requested.
1873 const SwNode * pNode = NULL;
1876 // --> OD 2005-10-20 #i55391#
1877 if ( !bInvestigateStartNode )
1879 if (bForward)
1880 aIdx++;
1881 else
1882 aIdx--;
1884 // <--
1885 if (aIdx.GetNode().IsTxtNode())
1887 pTxtNd = aIdx.GetNode().GetTxtNode();
1889 const SwNumRule * pNumRule = pTxtNd->GetNumRule();
1890 if (pNumRule)
1892 if ( ( pNumRule->IsOutlineRule() == ( bOutline ? TRUE : FALSE ) ) && // #115901#
1893 ( ( bNum && pNumRule->Get(0).IsEnumeration()) ||
1894 ( !bNum && pNumRule->Get(0).IsItemize() ) ) ) // #i22362#, #i29560#
1896 pResult = pTxtNd->GetNumRule();
1897 // --> OD 2008-03-18 #refactorlists#
1898 // provide also the list id, to which the text node belongs.
1899 sListId = pTxtNd->GetListId();
1902 break;
1904 else if (pTxtNd->Len() > 0 || NULL != pTxtNd->GetNumRule())
1906 if (nNonEmptyAllowed == 0)
1907 break;
1909 nNonEmptyAllowed--;
1911 if (nNonEmptyAllowed < 0)
1912 nNonEmptyAllowed = -1;
1916 // --> OD 2005-10-20 #i55391#
1917 if ( bInvestigateStartNode )
1919 if (bForward)
1920 aIdx++;
1921 else
1922 aIdx--;
1924 // <--
1926 pNode = &aIdx.GetNode();
1928 while (! (pNode == aNodes.DocumentSectionStartNode(pStartFromNode) ||
1929 pNode == aNodes.DocumentSectionEndNode(pStartFromNode)));
1930 // <--
1933 return pResult;
1935 // <- #i23731#
1937 BOOL SwDoc::GotoPrevNum( SwPosition& rPos, BOOL bOverUpper,
1938 BYTE* pUpper, BYTE* pLower )
1940 return ::lcl_GotoNextPrevNum( rPos, FALSE, bOverUpper, pUpper, pLower );
1943 BOOL SwDoc::NumUpDown( const SwPaM& rPam, BOOL bDown )
1945 ULONG nStt = rPam.GetPoint()->nNode.GetIndex(),
1946 nEnd = rPam.GetMark()->nNode.GetIndex();
1947 if( nStt > nEnd )
1949 ULONG nTmp = nStt; nStt = nEnd; nEnd = nTmp;
1952 // -> #115901# outline nodes are promoted or demoted differently
1953 bool bOnlyOutline = true;
1954 bool bOnlyNonOutline = true;
1955 for (ULONG n = nStt; n <= nEnd; n++)
1957 SwTxtNode * pTxtNd = GetNodes()[n]->GetTxtNode();
1959 if (pTxtNd)
1961 SwNumRule * pRule = pTxtNd->GetNumRule();
1963 if (pRule)
1965 if (pRule->IsOutlineRule())
1966 bOnlyNonOutline = false;
1967 else
1968 bOnlyOutline = false;
1972 // <- #115901#
1974 BOOL bRet = TRUE;
1975 char nDiff = bDown ? 1 : -1;
1977 // ->#115901#
1978 if (bOnlyOutline)
1979 bRet = OutlineUpDown(rPam, nDiff);
1980 else if (bOnlyNonOutline)
1982 /* --> #i24560#
1984 Only promote or demote if all selected paragraphs are
1985 promotable resp. demotable.
1988 for (ULONG nTmp = nStt; nTmp <= nEnd; ++nTmp)
1990 SwTxtNode* pTNd = GetNodes()[ nTmp ]->GetTxtNode();
1992 // --> OD 2006-10-19 #134160# - make code robust:
1993 // consider case that the node doesn't denote a text node.
1994 if ( pTNd )
1996 SwNumRule * pRule = pTNd->GetNumRule();
1998 if (pRule)
2000 BYTE nLevel = static_cast<BYTE>(pTNd->GetActualListLevel());
2001 if( (-1 == nDiff && 0 >= nLevel) ||
2002 (1 == nDiff && MAXLEVEL - 1 <= nLevel))
2003 bRet = FALSE;
2006 // <--
2009 if( bRet )
2011 /* <-- #i24560# */
2012 if( DoesUndo() )
2014 ClearRedo();
2015 AppendUndo( new SwUndoNumUpDown( rPam, nDiff ) );
2018 String sNumRule;
2020 for(ULONG nTmp = nStt; nTmp <= nEnd; ++nTmp )
2022 SwTxtNode* pTNd = GetNodes()[ nTmp ]->GetTxtNode();
2024 if( pTNd)
2026 SwNumRule * pRule = pTNd->GetNumRule();
2028 if (pRule)
2030 BYTE nLevel = static_cast<BYTE>(pTNd->GetActualListLevel());
2031 nLevel = nLevel + nDiff;
2033 pTNd->SetAttrListLevel(nLevel);
2038 ChkCondColls();
2039 SetModified();
2043 return bRet;
2046 BOOL SwDoc::MoveParagraph( const SwPaM& rPam, long nOffset, BOOL bIsOutlMv )
2048 const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
2050 ULONG nStIdx = pStt->nNode.GetIndex();
2051 ULONG nEndIdx = pEnd->nNode.GetIndex();
2053 // Here are some sophisticated checks whether the wished PaM will be moved or not.
2054 // For moving outlines (bIsOutlMv) I've already done some checks, so here are two different
2055 // checks...
2056 SwNode *pTmp1;
2057 SwNode *pTmp2;
2058 if( bIsOutlMv )
2060 // For moving chapters (outline) the following reason will deny the move:
2061 // if a start node is inside the moved area and its end node outside or vice versa.
2062 // If a start node is the first moved paragraph, its end node has to be within the moved
2063 // area, too (e.g. as last node).
2064 // If an end node is the last node of the moved area, its start node has to be a part of
2065 // the moved section, too.
2066 pTmp1 = GetNodes()[ nStIdx ];
2067 if( pTmp1->IsStartNode() )
2068 { // First is a start node
2069 pTmp2 = pTmp1->EndOfSectionNode();
2070 if( pTmp2->GetIndex() > nEndIdx )
2071 return FALSE; // Its end node is behind the moved range
2073 pTmp1 = pTmp1->StartOfSectionNode()->EndOfSectionNode();
2074 if( pTmp1->GetIndex() <= nEndIdx )
2075 return FALSE; // End node inside but start node before moved range => no.
2076 pTmp1 = GetNodes()[ nEndIdx ];
2077 if( pTmp1->IsEndNode() )
2078 { // The last one is an end node
2079 pTmp1 = pTmp1->StartOfSectionNode();
2080 if( pTmp1->GetIndex() < nStIdx )
2081 return FALSE; // Its start node is before the moved range.
2083 pTmp1 = pTmp1->StartOfSectionNode();
2084 if( pTmp1->GetIndex() >= nStIdx )
2085 return FALSE; // A start node which ends behind the moved area => no.
2088 ULONG nInStIdx, nInEndIdx;
2089 long nOffs = nOffset;
2090 if( nOffset > 0 )
2092 nInEndIdx = nEndIdx;
2093 nEndIdx += nOffset;
2094 ++nOffs;
2096 else
2098 //Impossible to move to negative index
2099 if( ULONG(abs( nOffset )) > nStIdx)
2100 return FALSE;
2102 nInEndIdx = nStIdx - 1;
2103 nStIdx += nOffset;
2105 nInStIdx = nInEndIdx + 1;
2106 // Folgende Absatzbloecke sollen vertauscht werden:
2107 // [ nStIdx, nInEndIdx ] mit [ nInStIdx, nEndIdx ]
2109 if( nEndIdx >= GetNodes().GetEndOfContent().GetIndex() )
2110 return FALSE;
2112 if( !bIsOutlMv )
2113 { // And here the restrictions for moving paragraphs other than chapters (outlines)
2114 // The plan is to exchange [nStIdx,nInEndIdx] and [nStartIdx,nEndIdx]
2115 // It will checked if the both "start" nodes as well as the both "end" notes belongs to
2116 // the same start-end-section. This is more restrictive than the conditions checked above.
2117 // E.g. a paragraph will not escape from a section or be inserted to another section.
2118 pTmp1 = GetNodes()[ nStIdx ]->StartOfSectionNode();
2119 pTmp2 = GetNodes()[ nInStIdx ]->StartOfSectionNode();
2120 if( pTmp1 != pTmp2 )
2121 return FALSE; // "start" nodes in different sections
2122 pTmp1 = GetNodes()[ nEndIdx ];
2123 bool bIsEndNode = pTmp1->IsEndNode();
2124 if( !pTmp1->IsStartNode() )
2126 pTmp1 = pTmp1->StartOfSectionNode();
2127 if( bIsEndNode ) // For end nodes the first start node is of course inside the range,
2128 pTmp1 = pTmp1->StartOfSectionNode(); // I've to check the start node of the start node.
2130 pTmp1 = pTmp1->EndOfSectionNode();
2131 pTmp2 = GetNodes()[ nInEndIdx ];
2132 if( !pTmp2->IsStartNode() )
2134 bIsEndNode = pTmp2->IsEndNode();
2135 pTmp2 = pTmp2->StartOfSectionNode();
2136 if( bIsEndNode )
2137 pTmp2 = pTmp2->StartOfSectionNode();
2139 pTmp2 = pTmp2->EndOfSectionNode();
2140 if( pTmp1 != pTmp2 )
2141 return FALSE; // The "end" notes are in different sections
2144 // auf Redlining testen - darf die Selektion ueberhaupt verschoben
2145 // werden?
2146 if( !IsIgnoreRedline() )
2148 USHORT nRedlPos = GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_DELETE );
2149 if( USHRT_MAX != nRedlPos )
2151 SwPosition aStPos( *pStt ), aEndPos( *pEnd );
2152 aStPos.nContent = 0;
2153 SwCntntNode* pCNd = pEnd->nNode.GetNode().GetCntntNode();
2154 aEndPos.nContent = pCNd ? pCNd->Len() : 1;
2155 BOOL bCheckDel = TRUE;
2157 // es existiert fuer den Bereich irgendein Redline-Delete-Object
2158 for( ; nRedlPos < GetRedlineTbl().Count(); ++nRedlPos )
2160 const SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
2161 if( !bCheckDel || nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() )
2163 const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
2164 switch( ComparePosition( *pRStt, *pREnd, aStPos, aEndPos ))
2166 case POS_COLLIDE_START:
2167 case POS_BEHIND: // Pos1 liegt hinter Pos2
2168 nRedlPos = GetRedlineTbl().Count();
2169 break;
2171 case POS_COLLIDE_END:
2172 case POS_BEFORE: // Pos1 liegt vor Pos2
2173 break;
2174 case POS_INSIDE: // Pos1 liegt vollstaendig in Pos2
2175 // ist erlaubt, aber checke dann alle nachfolgenden
2176 // auf Ueberlappungen
2177 bCheckDel = FALSE;
2178 break;
2180 case POS_OUTSIDE: // Pos2 liegt vollstaendig in Pos1
2181 case POS_EQUAL: // Pos1 ist genauso gross wie Pos2
2182 case POS_OVERLAP_BEFORE: // Pos1 ueberlappt Pos2 am Anfang
2183 case POS_OVERLAP_BEHIND: // Pos1 ueberlappt Pos2 am Ende
2184 return FALSE;
2192 // DataChanged vorm verschieben verschicken, dann bekommt
2193 // man noch mit, welche Objecte sich im Bereich befinden.
2194 // Danach koennen sie vor/hinter der Position befinden.
2195 SwDataChanged aTmp( rPam, 0 );
2198 SwNodeIndex aIdx( nOffset > 0 ? pEnd->nNode : pStt->nNode, nOffs );
2199 SwNodeRange aMvRg( pStt->nNode, 0, pEnd->nNode, +1 );
2201 SwRedline* pOwnRedl = 0;
2202 if( IsRedlineOn() )
2204 // wenn der Bereich komplett im eigenen Redline liegt, kann es
2205 // verschoben werden!
2206 USHORT nRedlPos = GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_INSERT );
2207 if( USHRT_MAX != nRedlPos )
2209 SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
2210 const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
2211 SwRedline aTmpRedl( nsRedlineType_t::REDLINE_INSERT, rPam );
2212 const SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
2213 // liegt komplett im Bereich, und ist auch der eigene Redline?
2214 if( aTmpRedl.IsOwnRedline( *pTmp ) &&
2215 (pRStt->nNode < pStt->nNode ||
2216 (pRStt->nNode == pStt->nNode && !pRStt->nContent.GetIndex()) ) &&
2217 (pEnd->nNode < pREnd->nNode ||
2218 (pEnd->nNode == pREnd->nNode &&
2219 pCEndNd ? pREnd->nContent.GetIndex() == pCEndNd->Len()
2220 : !pREnd->nContent.GetIndex() )) )
2222 pOwnRedl = pTmp;
2223 if( nRedlPos + 1 < GetRedlineTbl().Count() )
2225 pTmp = GetRedlineTbl()[ nRedlPos+1 ];
2226 if( *pTmp->Start() == *pREnd )
2227 // dann doch nicht!
2228 pOwnRedl = 0;
2231 if( pOwnRedl &&
2232 !( pRStt->nNode <= aIdx && aIdx <= pREnd->nNode ))
2234 // nicht in sich selbst, dann auch nicht moven
2235 pOwnRedl = 0;
2240 if( !pOwnRedl )
2242 StartUndo( UNDO_START, NULL );
2244 // zuerst das Insert, dann das Loeschen
2245 SwPosition aInsPos( aIdx );
2246 aInsPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), 0 );
2248 SwPaM aPam( pStt->nNode, aMvRg.aEnd );
2250 SwPaM& rOrigPam = (SwPaM&)rPam;
2251 rOrigPam.DeleteMark();
2252 rOrigPam.GetPoint()->nNode = aIdx.GetIndex() - 1;
2254 BOOL bDelLastPara = !aInsPos.nNode.GetNode().IsCntntNode();
2256 /* #101076# When copying to a non-content node Copy will
2257 insert a paragraph before that node and insert before
2258 that inserted node. Copy creates an SwUndoInserts that
2259 does not cover the extra paragraph. Thus we insert the
2260 extra paragraph ourselves, _with_ correct undo
2261 information. */
2262 if (bDelLastPara)
2264 /* aInsPos points to the non-content node. Move it to
2265 the previous content node. */
2266 SwPaM aInsPam(aInsPos);
2267 BOOL bMoved = aInsPam.Move(fnMoveBackward);
2268 ASSERT(bMoved, "No content node found!");
2270 if (bMoved)
2272 /* Append the new node after the content node
2273 found. The new position to insert the moved
2274 paragraph at is before the inserted
2275 paragraph. */
2276 AppendTxtNode(*aInsPam.GetPoint());
2277 aInsPos = *aInsPam.GetPoint();
2281 CopyRange( aPam, aInsPos, false );
2282 if( bDelLastPara )
2284 // dann muss der letzte leere Node wieder entfernt werden
2285 aIdx = aInsPos.nNode;
2286 SwCntntNode* pCNd = GetNodes().GoPrevious( &aInsPos.nNode );
2287 xub_StrLen nCLen = 0; if( pCNd ) nCLen = pCNd->Len();
2288 aInsPos.nContent.Assign( pCNd, nCLen );
2290 // alle die im zu loeschenden Node stehen, mussen auf den
2291 // naechsten umgestezt werden
2292 SwPosition* pPos;
2293 for( USHORT n = 0; n < GetRedlineTbl().Count(); ++n )
2295 SwRedline* pTmp = GetRedlineTbl()[ n ];
2296 if( ( pPos = &pTmp->GetBound(TRUE))->nNode == aIdx )
2298 pPos->nNode++;
2299 pPos->nContent.Assign( pPos->nNode.GetNode().GetCntntNode(),0);
2301 if( ( pPos = &pTmp->GetBound(FALSE))->nNode == aIdx )
2303 pPos->nNode++;
2304 pPos->nContent.Assign( pPos->nNode.GetNode().GetCntntNode(),0);
2307 CorrRel( aIdx, aInsPos, 0, FALSE );
2309 pCNd->JoinNext();
2312 rOrigPam.GetPoint()->nNode++;
2313 rOrigPam.GetPoint()->nContent.Assign( rOrigPam.GetCntntNode(), 0 );
2315 RedlineMode_t eOld = GetRedlineMode();
2316 checkRedlining(eOld);
2317 if( DoesUndo() )
2319 //JP 06.01.98: MUSS noch optimiert werden!!!
2320 SetRedlineMode(
2321 (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE));
2322 AppendUndo( new SwUndoRedlineDelete( aPam, UNDO_DELETE ));
2325 SwRedline* pNewRedline = new SwRedline( nsRedlineType_t::REDLINE_DELETE, aPam );
2327 // #101654# prevent assertion from aPam's target being deleted
2328 // (Alternatively, one could just let aPam go out of scope, but
2329 // that requires touching a lot of code.)
2330 aPam.GetBound(TRUE).nContent.Assign( NULL, 0 );
2331 aPam.GetBound(FALSE).nContent.Assign( NULL, 0 );
2333 AppendRedline( pNewRedline, true );
2335 //JP 06.01.98: MUSS noch optimiert werden!!!
2336 SetRedlineMode( eOld );
2337 EndUndo( UNDO_END, NULL );
2338 SetModified();
2340 return TRUE;
2344 if( !pOwnRedl && !IsIgnoreRedline() && GetRedlineTbl().Count() )
2346 SwPaM aTemp(aIdx);
2347 SplitRedline(aTemp);
2350 ULONG nRedlSttNd(0), nRedlEndNd(0);
2351 if( pOwnRedl )
2353 const SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
2354 nRedlSttNd = pRStt->nNode.GetIndex();
2355 nRedlEndNd = pREnd->nNode.GetIndex();
2358 SwUndoMoveNum* pUndo = 0;
2359 ULONG nMoved = 0;
2360 if( DoesUndo() )
2362 pUndo = new SwUndoMoveNum( rPam, nOffset, bIsOutlMv );
2363 nMoved = rPam.End()->nNode.GetIndex() - rPam.Start()->nNode.GetIndex() + 1;
2367 MoveNodeRange( aMvRg, aIdx, DOC_MOVEREDLINES );
2369 if( pUndo )
2371 ClearRedo();
2372 // i57907: Under circumstances (sections at the end of a chapter)
2373 // the rPam.Start() is not moved to the new position.
2374 // But aIdx should be at the new end position and as long as the number of moved paragraphs
2375 // is nMoved, I know, where the new position is.
2376 pUndo->SetStartNode( aIdx.GetIndex() - nMoved );
2377 AppendUndo( pUndo );
2380 if( pOwnRedl )
2382 SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
2383 if( pRStt->nNode.GetIndex() != nRedlSttNd )
2385 pRStt->nNode = nRedlSttNd;
2386 pRStt->nContent.Assign( pRStt->nNode.GetNode().GetCntntNode(),0);
2388 if( pREnd->nNode.GetIndex() != nRedlEndNd )
2390 pREnd->nNode = nRedlEndNd;
2391 SwCntntNode* pCNd = pREnd->nNode.GetNode().GetCntntNode();
2392 xub_StrLen nL = 0; if( pCNd ) nL = pCNd->Len();
2393 pREnd->nContent.Assign( pCNd, nL );
2397 SetModified();
2398 return TRUE;
2401 BOOL SwDoc::NumOrNoNum( const SwNodeIndex& rIdx, BOOL bDel )
2403 BOOL bResult = FALSE;
2404 SwTxtNode * pTxtNd = rIdx.GetNode().GetTxtNode();
2406 if (pTxtNd && pTxtNd->GetNumRule() != NULL &&
2407 (pTxtNd->HasNumber() || pTxtNd->HasBullet()))
2409 if ( !pTxtNd->IsCountedInList() == !bDel)
2411 BOOL bOldNum = bDel; // == pTxtNd->IsCounted();
2412 BOOL bNewNum = bDel ? FALSE : TRUE;
2413 pTxtNd->SetCountedInList(bNewNum ? true : false);
2415 SetModified();
2417 bResult = TRUE;
2419 if (DoesUndo())
2421 SwUndoNumOrNoNum * pUndo =
2422 new SwUndoNumOrNoNum(rIdx, bOldNum, bNewNum);
2424 AppendUndo(pUndo);
2427 else if (bDel && pTxtNd->GetNumRule(FALSE) &&
2428 pTxtNd->GetActualListLevel() >= 0 &&
2429 pTxtNd->GetActualListLevel() < MAXLEVEL)
2431 SwPaM aPam(*pTxtNd);
2433 DelNumRules(aPam);
2435 bResult = TRUE;
2439 return bResult;
2442 SwNumRule* SwDoc::GetCurrNumRule( const SwPosition& rPos ) const
2444 SwNumRule* pRet = 0;
2445 SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
2447 if( pTNd )
2449 // --> OD 2008-02-20 #refactorlists#
2450 // pTNd->SyncNumberAndNumRule();
2451 // <--
2452 pRet = pTNd->GetNumRule();
2455 return pRet;
2458 USHORT SwDoc::FindNumRule( const String& rName ) const
2460 for( USHORT n = pNumRuleTbl->Count(); n; )
2461 if( (*pNumRuleTbl)[ --n ]->GetName() == rName )
2462 return n;
2464 return USHRT_MAX;
2467 SwNumRule* SwDoc::FindNumRulePtr( const String& rName ) const
2469 SwNumRule * pResult = 0;
2471 pResult = maNumRuleMap[rName];
2473 if ( !pResult )
2475 for (USHORT n = 0; n < pNumRuleTbl->Count(); ++n)
2477 if ((*pNumRuleTbl)[n]->GetName() == rName)
2479 pResult = (*pNumRuleTbl)[n];
2481 break;
2486 return pResult;
2489 // #i36749#
2490 void SwDoc::AddNumRule(SwNumRule * pRule)
2492 pNumRuleTbl->Insert(pRule, pNumRuleTbl->Count());
2493 maNumRuleMap[pRule->GetName()] = pRule;
2494 pRule->SetNumRuleMap(&maNumRuleMap);
2496 // --> OD 2008-03-26 #refactorlists#
2497 createListForListStyle( pRule->GetName() );
2498 // <--
2501 // --> OD 2008-02-11 #newlistlevelattrs#
2502 USHORT SwDoc::MakeNumRule( const String &rName,
2503 const SwNumRule* pCpy,
2504 BOOL bBroadcast,
2505 const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode )
2507 SwNumRule* pNew;
2508 if( pCpy )
2510 pNew = new SwNumRule( *pCpy );
2512 // --> OD 2008-07-08 #i91400#
2513 pNew->SetName( GetUniqueNumRuleName( &rName ), *this );
2514 // <--
2515 if( pNew->GetName() != rName )
2517 pNew->SetPoolFmtId( USHRT_MAX );
2518 pNew->SetPoolHelpId( USHRT_MAX );
2519 pNew->SetPoolHlpFileId( UCHAR_MAX );
2520 // --> OD 2008-04-03 #refactorlists#
2521 pNew->SetDefaultListId( String() );
2522 // <--
2524 pNew->CheckCharFmts( this );
2526 else
2528 // --> OD 2008-02-11 #newlistlevelattrs#
2529 pNew = new SwNumRule( GetUniqueNumRuleName( &rName ),
2530 eDefaultNumberFormatPositionAndSpaceMode );
2531 // <--
2534 USHORT nRet = pNumRuleTbl->Count();
2536 AddNumRule(pNew); // #i36749#
2538 if (DoesUndo())
2540 SwUndo * pUndo = new SwUndoNumruleCreate(pNew, this);
2542 AppendUndo(pUndo);
2545 if (bBroadcast)
2546 BroadcastStyleOperation(pNew->GetName(), SFX_STYLE_FAMILY_PSEUDO,
2547 SFX_STYLESHEET_CREATED);
2549 return nRet;
2552 String SwDoc::GetUniqueNumRuleName( const String* pChkStr, BOOL bAutoNum ) const
2554 String aName;
2555 if( bAutoNum )
2557 long n = Time().GetTime();
2558 n += Date().GetDate();
2559 aName = String::CreateFromInt32( n );
2560 if( pChkStr && !pChkStr->Len() )
2561 pChkStr = 0;
2563 else if( pChkStr && pChkStr->Len() )
2564 aName = *pChkStr;
2565 else
2567 pChkStr = 0;
2568 aName = SW_RESSTR( STR_NUMRULE_DEFNAME );
2571 USHORT nNum(0), nTmp, nFlagSize = ( pNumRuleTbl->Count() / 8 ) +2;
2572 BYTE* pSetFlags = new BYTE[ nFlagSize ];
2573 memset( pSetFlags, 0, nFlagSize );
2575 xub_StrLen nNmLen = aName.Len();
2576 if( !bAutoNum && pChkStr )
2578 while( nNmLen-- && '0' <= aName.GetChar( nNmLen ) &&
2579 '9' >= aName.GetChar( nNmLen ) )
2580 ; //nop
2582 if( ++nNmLen < aName.Len() )
2584 aName.Erase( nNmLen );
2585 pChkStr = 0;
2589 const SwNumRule* pNumRule;
2590 USHORT n;
2592 for( n = 0; n < pNumRuleTbl->Count(); ++n )
2593 if( 0 != ( pNumRule = (*pNumRuleTbl)[ n ] ) )
2595 const String& rNm = pNumRule->GetName();
2596 if( rNm.Match( aName ) == nNmLen )
2598 // Nummer bestimmen und das Flag setzen
2599 nNum = (USHORT)rNm.Copy( nNmLen ).ToInt32();
2600 if( nNum-- && nNum < pNumRuleTbl->Count() )
2601 pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
2603 if( pChkStr && pChkStr->Equals( rNm ) )
2604 pChkStr = 0;
2607 if( !pChkStr )
2609 // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
2610 nNum = pNumRuleTbl->Count();
2611 for( n = 0; n < nFlagSize; ++n )
2612 if( 0xff != ( nTmp = pSetFlags[ n ] ))
2614 // also die Nummer bestimmen
2615 nNum = n * 8;
2616 while( nTmp & 1 )
2617 ++nNum, nTmp >>= 1;
2618 break;
2622 delete [] pSetFlags;
2623 if( pChkStr && pChkStr->Len() )
2624 return *pChkStr;
2625 return aName += String::CreateFromInt32( ++nNum );
2628 void SwDoc::UpdateNumRule()
2630 const SwNumRuleTbl& rNmTbl = GetNumRuleTbl();
2631 for( USHORT n = 0; n < rNmTbl.Count(); ++n )
2632 if( rNmTbl[ n ]->IsInvalidRule() )
2633 rNmTbl[ n ]->Validate();
2636 // --> OD 2008-04-02 #refactorlists#
2637 void SwDoc::MarkListLevel( const String& sListId,
2638 const int nListLevel,
2639 const BOOL bValue )
2641 SwList* pList = getListByName( sListId );
2643 if ( pList )
2645 MarkListLevel( *pList, nListLevel, bValue );
2649 void SwDoc::MarkListLevel( SwList& rList,
2650 const int nListLevel,
2651 const BOOL bValue )
2653 // Set new marked list level and notify all affected nodes of the changed mark.
2654 rList.MarkListLevel( nListLevel, bValue );
2656 // <- #i27615#
2657 // <--
2659 // #i23726#
2660 BOOL SwDoc::IsFirstOfNumRule(SwPosition & rPos)
2662 BOOL bResult = FALSE;
2663 SwTxtNode * pTxtNode = rPos.nNode.GetNode().GetTxtNode();
2665 if (pTxtNode)
2667 SwNumRule * pNumRule = pTxtNode->GetNumRule();
2669 if (pNumRule)
2670 bResult = pTxtNode->IsFirstOfNumRule();
2673 return bResult;
2676 // --> OD 2007-10-26 #i83479#
2677 // implementation for interface <IDocumentListItems>
2678 bool SwDoc::lessThanNodeNum::operator()( const SwNodeNum* pNodeNumOne,
2679 const SwNodeNum* pNodeNumTwo ) const
2681 return pNodeNumOne->LessThan( *pNodeNumTwo );
2684 void SwDoc::addListItem( const SwNodeNum& rNodeNum )
2686 if ( mpListItemsList == 0 )
2688 return;
2691 const bool bAlreadyInserted(
2692 mpListItemsList->find( &rNodeNum ) != mpListItemsList->end() );
2693 ASSERT( !bAlreadyInserted,
2694 "<SwDoc::InsertListItem(..)> - <SwNodeNum> instance already registered as numbered item!" );
2695 if ( !bAlreadyInserted )
2697 mpListItemsList->insert( &rNodeNum );
2701 void SwDoc::removeListItem( const SwNodeNum& rNodeNum )
2703 if ( mpListItemsList == 0 )
2705 return;
2708 const tImplSortedNodeNumList::size_type nDeleted = mpListItemsList->erase( &rNodeNum );
2709 if ( nDeleted > 1 )
2711 ASSERT( false,
2712 "<SwDoc::RemoveListItem(..)> - <SwNodeNum> was registered more than once as numbered item!" );
2716 String SwDoc::getListItemText( const SwNodeNum& rNodeNum,
2717 const bool bWithNumber,
2718 const bool bWithSpacesForLevel ) const
2720 return rNodeNum.GetTxtNode()
2721 ? rNodeNum.GetTxtNode()->GetExpandTxt( 0, STRING_LEN, bWithNumber,
2722 bWithNumber, bWithSpacesForLevel )
2723 : String();
2726 void SwDoc::getListItems( tSortedNodeNumList& orNodeNumList ) const
2728 orNodeNumList.clear();
2729 orNodeNumList.reserve( mpListItemsList->size() );
2731 tImplSortedNodeNumList::iterator aIter;
2732 tImplSortedNodeNumList::iterator aEndIter = mpListItemsList->end();
2733 for ( aIter = mpListItemsList->begin(); aIter != aEndIter; ++aIter )
2735 orNodeNumList.push_back( (*aIter) );
2739 void SwDoc::getNumItems( tSortedNodeNumList& orNodeNumList ) const
2741 orNodeNumList.clear();
2742 orNodeNumList.reserve( mpListItemsList->size() );
2744 tImplSortedNodeNumList::iterator aIter;
2745 tImplSortedNodeNumList::iterator aEndIter = mpListItemsList->end();
2746 for ( aIter = mpListItemsList->begin(); aIter != aEndIter; ++aIter )
2748 const SwNodeNum* pNodeNum = (*aIter);
2749 if ( pNodeNum->IsCounted() &&
2750 pNodeNum->GetTxtNode() && pNodeNum->GetTxtNode()->HasNumber() )
2752 orNodeNumList.push_back( pNodeNum );
2756 // <--
2758 // --> OD 2007-11-15 #i83479#
2759 // implementation for interface <IDocumentOutlineNodes>
2760 sal_Int32 SwDoc::getOutlineNodesCount() const
2762 return GetNodes().GetOutLineNds().Count();
2765 int SwDoc::getOutlineLevel( const sal_Int32 nIdx ) const
2767 return GetNodes().GetOutLineNds()[ static_cast<USHORT>(nIdx) ]->
2768 // GetTxtNode()->GetOutlineLevel(); //#outline level,zhaojianwei
2769 GetTxtNode()->GetAttrOutlineLevel()-1; //<-end,zhaojianwei
2772 String SwDoc::getOutlineText( const sal_Int32 nIdx,
2773 const bool bWithNumber,
2774 const bool bWithSpacesForLevel ) const
2776 return GetNodes().GetOutLineNds()[ static_cast<USHORT>(nIdx) ]->
2777 GetTxtNode()->GetExpandTxt( 0, STRING_LEN, bWithNumber,
2778 bWithNumber, bWithSpacesForLevel );
2781 SwTxtNode* SwDoc::getOutlineNode( const sal_Int32 nIdx ) const
2783 return GetNodes().GetOutLineNds()[ static_cast<USHORT>(nIdx) ]->GetTxtNode();
2786 void SwDoc::getOutlineNodes( IDocumentOutlineNodes::tSortedOutlineNodeList& orOutlineNodeList ) const
2788 orOutlineNodeList.clear();
2789 orOutlineNodeList.reserve( getOutlineNodesCount() );
2791 const USHORT nOutlCount( static_cast<USHORT>(getOutlineNodesCount()) );
2792 for ( USHORT i = 0; i < nOutlCount; ++i )
2794 orOutlineNodeList.push_back(
2795 GetNodes().GetOutLineNds()[i]->GetTxtNode() );
2798 // <--
2800 // --> OD 2008-03-26 #refactorlists#
2801 // implementation of interface IDocumentListsAccess
2802 SwList* SwDoc::createList( String sListId,
2803 const String sDefaultListStyleName )
2805 if ( sListId.Len() == 0 )
2807 sListId = listfunc::CreateUniqueListId( *this );
2810 if ( getListByName( sListId ) )
2812 ASSERT( false,
2813 "<SwDoc::createList(..)> - provided list id already used. Serious defect -> please inform OD." );
2814 return 0;
2817 SwNumRule* pDefaultNumRuleForNewList = FindNumRulePtr( sDefaultListStyleName );
2818 if ( !pDefaultNumRuleForNewList )
2820 ASSERT( false,
2821 "<SwDoc::createList(..)> - for provided default list style name no list style is found. Serious defect -> please inform OD." );
2822 return 0;
2825 SwList* pNewList = new SwList( sListId, *pDefaultNumRuleForNewList, GetNodes() );
2826 maLists[sListId] = pNewList;
2828 return pNewList;
2831 void SwDoc::deleteList( const String sListId )
2833 SwList* pList = getListByName( sListId );
2834 if ( pList )
2836 maLists.erase( sListId );
2837 delete pList;
2841 SwList* SwDoc::getListByName( const String sListId ) const
2843 SwList* pList = 0;
2845 std::hash_map< String, SwList*, StringHash >::const_iterator
2846 aListIter = maLists.find( sListId );
2847 if ( aListIter != maLists.end() )
2849 pList = (*aListIter).second;
2852 return pList;
2855 SwList* SwDoc::createListForListStyle( const String sListStyleName )
2857 if ( sListStyleName.Len() == 0 )
2859 ASSERT( false,
2860 "<SwDoc::createListForListStyle(..)> - no list style name provided. Serious defect -> please inform OD." );
2861 return 0;
2864 if ( getListForListStyle( sListStyleName ) )
2866 ASSERT( false,
2867 "<SwDoc::createListForListStyle(..)> - a list for the provided list style name already exists. Serious defect -> please inform OD." );
2868 return 0;
2871 SwNumRule* pNumRule = FindNumRulePtr( sListStyleName );
2872 if ( !pNumRule )
2874 ASSERT( false,
2875 "<SwDoc::createListForListStyle(..)> - for provided list style name no list style is found. Serious defect -> please inform OD." );
2876 return 0;
2879 String sListId( pNumRule->GetDefaultListId() ); // can be empty String
2880 if ( getListByName( sListId ) )
2882 sListId = String();
2884 SwList* pNewList = createList( sListId, sListStyleName );
2885 maListStyleLists[sListStyleName] = pNewList;
2886 pNumRule->SetDefaultListId( pNewList->GetListId() );
2888 return pNewList;
2891 SwList* SwDoc::getListForListStyle( const String sListStyleName ) const
2893 SwList* pList = 0;
2895 std::hash_map< String, SwList*, StringHash >::const_iterator
2896 aListIter = maListStyleLists.find( sListStyleName );
2897 if ( aListIter != maListStyleLists.end() )
2899 pList = (*aListIter).second;
2902 return pList;
2905 void SwDoc::deleteListForListStyle( const String sListStyleName )
2907 String sListId;
2909 SwList* pList = getListForListStyle( sListStyleName );
2910 ASSERT( pList,
2911 "<SwDoc::deleteListForListStyle(..)> - misusage of method: no list found for given list style name" );
2912 if ( pList )
2914 sListId = pList->GetListId();
2917 if ( sListId.Len() > 0 )
2919 maListStyleLists.erase( sListStyleName );
2920 deleteList( sListId );
2923 // <--
2924 // --> OD 2008-07-08 #i91400#
2925 void SwDoc::trackChangeOfListStyleName( const String sListStyleName,
2926 const String sNewListStyleName )
2928 SwList* pList = getListForListStyle( sListStyleName );
2929 ASSERT( pList,
2930 "<SwDoc::changeOfListStyleName(..)> - misusage of method: no list found for given list style name" );
2932 if ( pList != 0 )
2934 maListStyleLists.erase( sListStyleName );
2935 maListStyleLists[sNewListStyleName] = pList;
2938 // <--
2940 // --> OD 2008-03-13 #refactorlists#
2941 namespace listfunc
2943 const String MakeListIdUnique( const SwDoc& rDoc,
2944 const String aSuggestedUniqueListId )
2946 long nHitCount = 0;
2947 String aTmpStr = aSuggestedUniqueListId;
2948 while ( rDoc.getListByName( aTmpStr ) )
2950 ++nHitCount;
2951 aTmpStr = aSuggestedUniqueListId;
2952 aTmpStr += String::CreateFromInt32( nHitCount );
2955 return aTmpStr;
2957 const String CreateUniqueListId( const SwDoc& rDoc )
2959 // --> OD 2008-08-06 #i92478#
2960 String aNewListId = String::CreateFromAscii( "list" );
2961 // <--
2962 sal_Int64 n = Time().GetTime();
2963 n += Date().GetDate();
2964 n += rand();
2965 // --> OD 2008-08-06 #i92478#
2966 aNewListId += String::CreateFromInt64( n );
2967 // <--
2969 return MakeListIdUnique( rDoc, aNewListId );
2972 // <--