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 $
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>
43 #include <doctxm.hxx> // pTOXBaseRing
44 #include <poolfmt.hxx>
47 #include <SwUndoFmt.hxx>
54 #include <redline.hxx>
56 #include <comcore.hrc>
58 #include <svx/adjitem.hxx>
59 #include <svx/frmdiritem.hxx>
61 #include <SwStyleNameMapper.hxx>
62 #include <SwNodeNum.hxx>
63 // --> OD 2008-03-13 #refactorlists#
65 #include <listfunc.hxx>
70 inline BYTE
GetUpperLvlChg( BYTE nCurLvl
, BYTE nLevel
, USHORT nMask
)
74 if( nCurLvl
+ 1 >= nLevel
)
75 nCurLvl
-= nLevel
- 1;
79 return static_cast<BYTE
>((nMask
- 1) & ~(( 1 << nCurLvl
) - 1));
82 void SwDoc::SetOutlineNumRule( const SwNumRule
& rRule
)
85 (*pOutlineRule
) = rRule
;
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() ),
99 // --> OD 2006-09-21 #i69522#
100 // assure that the outline numbering rule is an automatic rule
101 pOutlineRule
->SetAutoRule( TRUE
);
104 // teste ob die evt. gesetzen CharFormate in diesem Document
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() );
129 PropagateOutlineRule();
130 pOutlineRule
->SetInvalidRule(TRUE
);
133 // gibt es Fussnoten && gilt Kapitelweises Nummerieren, dann updaten
134 if( GetFtnIdxs().Count() && FTNNUM_CHAPTER
== GetFtnInfo().eNum
)
135 GetFtnIdxs().UpdateAllFtn();
137 UpdateExpFlds(NULL
, true);
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
);
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 )
163 SwNumRule
* pMyOutlineRule
= GetOutlineNumRule();
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
)
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
) &&
190 // wir stehen in keiner "Outline-Section"
193 if( rOutlNds
.Seek_Entry( pEndNd
, &nEndPos
) )
196 // jetzt haben wir unseren Bereich im OutlineNodes-Array
197 // dann prufe ersmal, ob nicht unterebenen aufgehoben werden
198 // (Stufung ueber die Grenzen)
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
];
219 /* Find the last occupied level (backward). */
220 for (n
= MAXLEVEL
- 1; n
> 0; n
--)
222 if (aCollArr
[n
] != 0)
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
230 if (aCollArr
[n
] != 0)
232 while (n
< MAXLEVEL
- 1)
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
;
249 /* Find the first occupied level (forward). */
250 for (n
= 0; n
< MAXLEVEL
- 1; n
++)
252 if (aCollArr
[n
] != 0)
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)
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
;
282 Build a move table that states from which level an outline will
284 be moved to which other level. */
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
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
316 If outline level n has no assigned paragraph style
317 aMoveArr[n] is set to -1.
319 if (aCollArr
[n
] != NULL
)
324 while (nCount
> 0 && m
+ nStep
>= 0 && m
+ nStep
< MAXLEVEL
)
326 m
= static_cast<USHORT
>(m
+ nStep
);
328 if (aCollArr
[m
] != NULL
)
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;
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.
364 const int nNewOutlineLevel
= pTxtNd
->GetAttrOutlineLevel() + nOffset
;
365 if ( nNewOutlineLevel
< 1 || nNewOutlineLevel
> MAXLEVEL
)
367 bMoveApplicable
= false;
373 if (! bMoveApplicable
)
380 StartUndo(UNDO_OUTLINE_LR
, NULL
);
381 AppendUndo( new SwUndoOutlineLeftRight( rPam
, nOffset
) );
384 // 2. allen Nodes die neue Vorlage zuweisen
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
] ];
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
);
424 EndUndo(UNDO_OUTLINE_LR
, NULL
);
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()
441 if( !GetNodes().GetOutLineNds().Count() || !nOffset
||
442 rStt
.nNode
.GetIndex() < aNodes
.GetEndOfExtras().GetIndex() ||
443 rEnd
.nNode
.GetIndex() < aNodes
.GetEndOfExtras().GetIndex() )
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
) )
460 return FALSE
; // Promoting or demoting before the first outline => no.
462 aSttRg
= *GetNodes().GetOutLineNds()[ nAktPos
];
463 else if( 0 > nOffset
)
464 return FALSE
; // Promoting at the top of document?!
466 aSttRg
= *GetNodes().GetEndOfContent().StartOfSectionNode();
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();
487 if( aEndRg
== aSttRg
)
489 ASSERT( false, "Moving outlines: Surprising selection" );
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.
500 while( aSttRg
.GetNode().IsStartNode() )
502 pNd
= aSttRg
.GetNode().EndOfSectionNode();
503 if( pNd
->GetIndex() >= aEndRg
.GetIndex() )
510 while( aEndRg
.GetNode().IsStartNode() )
512 while( aEndRg
.GetNode().IsEndNode() )
514 pNd
= aEndRg
.GetNode().StartOfSectionNode();
515 if( pNd
->GetIndex() >= aSttRg
.GetIndex() )
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();
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.
541 pNd
= aInsertPos
.GetNode().EndOfSectionNode();
542 if( pNd
->GetIndex() >= aEndRg
.GetIndex() )
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() )
563 // We do not want to move into tables (at the moment)
565 pNd
= &aInsertPos
.GetNode();
566 if( pNd
->IsTableNode() )
567 pNd
= pNd
->StartOfSectionNode();
568 if( pNd
->FindTableNode() )
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
,
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
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
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."
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] ));
628 String
sName( rName
);
630 while( STRING_NOTFOUND
!= nPos
)
634 for( USHORT n
= 0; n
< sNum
.Len(); ++n
)
635 if( '0' <= ( c
= sNum
.GetChar( n
)) && c
<= '9' )
637 nVal
*= 10; nVal
+= c
- '0';
640 break; // "fast" gueltige Nummer
642 return USHRT_MAX
; // ungueltige Nummer!!!
644 if( MAXLEVEL
> nLevel
)
645 nLevelVal
[ nLevel
++ ] = nVal
;
647 sName
.Erase( 0, nPos
);
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
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())
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 ) )
683 const SwNodeNum
& rNdNum
= *(pNd
->GetNum());
684 SwNumberTree::tNumberVector aLevelVal
= rNdNum
.GetNumberVector();
685 //now compare with the one searched for
687 for( BYTE n
= 0; (n
< nLevel
) && bEqual
; ++n
)
689 bEqual
= aLevelVal
[n
] == nLevelVal
[n
];
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() )
713 // zu diesem Gliederungspunkt
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
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
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
);
751 if( !sExpandedText
.Equals( sName
) )
753 USHORT nTmp
= ::lcl_FindOutlineName( GetNodes(), sName
, TRUE
);
754 if( USHRT_MAX
!= nTmp
) // ueber den Namen gefunden
757 pNd
= rOutlNds
[ nFndPos
]->GetTxtNode();
761 rPos
.nContent
.Assign( pNd
, 0 );
765 nFndPos
= ::lcl_FindOutlineName( GetNodes(), rName
, FALSE
);
766 if( USHRT_MAX
!= nFndPos
)
768 SwTxtNode
* pNd
= rOutlNds
[ nFndPos
]->GetTxtNode();
770 rPos
.nContent
.Assign( pNd
, 0 );
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();
783 rPos
.nContent
.Assign( pNd
, 0 );
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.
806 // // 1. Case: Information already available at pRule:
808 // if (pRule->GetTxtNodeList())
810 // // copy list to own pList pointer:
811 // aList = *pRule->GetTxtNodeList();
816 // // 2. Case: Information has to be generated from scratch:
819 // if (pRule->IsOutlineRule())
821 // const SwOutlineNodes & rOutlineNodes = rDoc.GetNodes().GetOutLineNds();
823 // for (USHORT i = 0; i < rOutlineNodes.Count(); ++i)
825 // SwTxtNode & aNode = *((SwTxtNode *) rOutlineNodes[i]);
827 // if (pRule == aNode.GetNumRule())
833 // const SfxPoolItem* pItem;
834 // USHORT i, nMaxItems = rDoc.GetAttrPool().GetItemCount
835 // ( RES_PARATR_NUMRULE);
836 // for( i = 0; i < nMaxItems; ++i )
838 // pItem = rDoc.GetAttrPool().GetItem( RES_PARATR_NUMRULE, i );
841 // pMod = (SwModify*)((SwNumRuleItem*)pItem)->GetDefinedIn();
843 // ((SwNumRuleItem*)pItem)->GetValue().Len() &&
844 // ((SwNumRuleItem*)pItem)->GetValue() == rName )
846 // if( pMod->IsA( TYPE( SwFmt )) )
847 // pMod->GetInfo( *this );
850 // SwTxtNode* pModTxtNode = (SwTxtNode*)pMod;
853 // if( pModTxtNode->GetNodes().IsDocNodes())
855 // AddNode( *pModTxtNode );
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 );
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;
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() );
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() );
906 // --> OD 2006-04-27 #i64311#
907 if ( bInvalidateNumRule
)
909 pOld
->SetInvalidRule(TRUE
);
915 // --> OD 2008-02-19 #refactorlists#
916 // SwNumRuleInfo* pUpd = new SwNumRuleInfo( rRule.GetName() );
917 // pUpd->MakeList( rDoc );
920 // for( ULONG nFirst = 0, nLast = pUpd->GetList().Count();
921 // nFirst < nLast; ++nFirst )
923 // SwTxtNode* pTxtNd = pUpd->GetList().GetObject( nFirst );
924 // nLvl = static_cast<BYTE>(pTxtNd->GetLevel());
926 // if( nLvl < MAXLEVEL )
928 // if( nChgFmtLevel & ( 1 << nLvl ))
930 // pTxtNd->NumRuleChgd();
934 SwNumRule::tTxtNodeList aTxtNodeList
;
935 pOld
->GetTxtNodeList( aTxtNodeList
);
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();
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() );
965 // --> OD 2008-02-19 #refactorlists#
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
,
979 const bool bResetIndentAttrs
)
981 SwUndoInsNum
* pUndo
= NULL
;
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;
994 pNew
= (*pNumRuleTbl
)[ MakeNumRule( rRule
.GetName(), &rRule
) ];
996 else if (rRule
!= *pNew
)
1005 pUndo
->SaveOldNumRule( *pNew
);
1006 ::lcl_ChgNumRule( *this, rRule
);
1007 pUndo
->SetLRSpaceEndPos();
1011 ::lcl_ChgNumRule( *this, rRule
);
1015 // --> OD 2008-03-17 #refactorlists#
1018 if ( bCreateNewList
)
1023 // apply list id of list, which has been created for the new list style
1024 sListId
= pNew
->GetDefaultListId();
1028 // create new list and apply its list id
1029 SwList
* pNewList
= createList( String(), pNew
->GetName() );
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 );
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
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();
1065 // --> OD 2005-10-26 #b6340308# - only clear numbering attribute at
1066 // text node, if at paragraph style the new numbering rule is found.
1069 SwTxtFmtColl
* pColl
= pTxtNd
->GetTxtColl();
1072 SwNumRule
* pCollRule
= FindNumRulePtr(pColl
->GetNumRule().GetValue());
1073 if ( pCollRule
&& pCollRule
->GetName() == pNew
->GetName() )
1075 pTxtNd
->ResetAttr( RES_PARATR_NUMRULE
);
1076 bSetItem
= sal_False
;
1085 // --> OD 2009-08-18 #i103817#
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
);
1103 EndUndo( UNDO_INSNUM
, NULL
);
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++)
1116 // SwTxtNode * pNd = GetNodes()[n]->GetTxtNode();
1119 // pNd->SetCountedInList(bCounted);
1123 SvUShortsSort aResetAttrsArray
;
1124 aResetAttrsArray
.Insert( RES_PARATR_LIST_ISCOUNTED
);
1125 ResetAttrs( rPam
, sal_True
, &aResetAttrsArray
);
1129 InsertPoolItem( rPam
,
1130 SfxBoolItem( RES_PARATR_LIST_ISCOUNTED
, FALSE
), 0 );
1134 //void SwDoc::ReplaceNumRule(const SwPaM & rPaM, const SwNumRule & rNumRule)
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++)
1144 // SwTxtNode * pCNd = GetNodes()[n]->GetTxtNode();
1146 // if (pCNd && NULL != pCNd->GetNumRule())
1148 // SwPaM aPam(*pCNd);
1150 // InsertPoolItem(aPam, SwNumRuleItem(rNumRule.GetName()), 0);
1155 // EndUndo(UNDO_START, NULL);
1158 void SwDoc::SetNumRuleStart( const SwPosition
& rPos
, BOOL bFlag
)
1160 SwTxtNode
* pTxtNd
= rPos
.nNode
.GetNode().GetTxtNode();
1164 const SwNumRule
* pRule
= pTxtNd
->GetNumRule();
1165 if( pRule
&& !bFlag
!= !pTxtNd
->IsListRestart())
1170 AppendUndo( new SwUndoNumRuleStart( rPos
, bFlag
));
1173 pTxtNd
->SetListRestart(bFlag
? true : false);
1180 void SwDoc::SetNodeNumStart( const SwPosition
& rPos
, USHORT nStt
)
1182 SwTxtNode
* pTxtNd
= rPos
.nNode
.GetNode().GetTxtNode();
1186 // --> OD 2008-02-27 #refactorlists#
1187 // const SwNumRule* pRule = pTxtNd->GetNumRule();
1188 // if( pRule && nStt != pTxtNd->GetListRestartValue() )
1193 // AppendUndo( new SwUndoNumRuleStart( rPos, nStt ));
1196 // pTxtNd->SetListRestartValue(nStt);
1199 if ( !pTxtNd
->HasAttrListRestartValue() ||
1200 pTxtNd
->GetAttrListRestartValue() != nStt
)
1205 AppendUndo( new SwUndoNumRuleStart( rPos
, nStt
));
1207 pTxtNd
->SetAttrListRestartValue( nStt
);
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() )
1224 "<SwDoc::DelNumRule(..)> - No deletion of outline list style. This is serious defect - please inform OD" );
1229 if( USHRT_MAX
!= nPos
&& !IsUsed( *(*pNumRuleTbl
)[ nPos
] ))
1234 new SwUndoNumruleDelete(*(*pNumRuleTbl
)[nPos
], this);
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
);
1259 while ( aListsForDeletion
.size() > 0 )
1261 SwList
* pList
= aListsForDeletion
.back();
1262 aListsForDeletion
.pop_back();
1263 deleteList( pList
->GetListId() );
1267 // --> FME 2004-11-02 #i34097# DeleteAndDestroy deletes rName if
1268 // rName is directly taken from the numrule.
1269 const String
aTmpName( rName
);
1271 pNumRuleTbl
->DeleteAndDestroy( nPos
);
1272 maNumRuleMap
.erase(aTmpName
);
1281 void SwDoc::ChgNumRuleFmts( const SwNumRule
& rRule
, const String
* pName
)
1284 SwNumRule
* pRule
= FindNumRulePtr( pName
? *pName
: rRule
.GetName() );
1287 SwUndoInsNum
* pUndo
= 0;
1291 pUndo
= new SwUndoInsNum( *pRule
, rRule
);
1292 pUndo
->GetHistory();
1293 AppendUndo( pUndo
);
1295 ::lcl_ChgNumRule( *this, rRule
);
1298 pUndo
->SetLRSpaceEndPos();
1304 sal_Bool
SwDoc::RenameNumRule(const String
& rOldName
, const String
& rNewName
,
1307 sal_Bool bResult
= sal_False
;
1308 SwNumRule
* pNumRule
= FindNumRulePtr(rOldName
);
1314 SwUndo
* pUndo
= new SwUndoNumruleRename(rOldName
, rNewName
, this);
1319 // --> OD 2008-02-19 #refactorlists#
1320 // SwNumRuleInfo aInfo(rOldName);
1321 // aInfo.MakeList(*this);
1322 SwNumRule::tTxtNodeList aTxtNodeList
;
1323 pNumRule
->GetTxtNodeList( aTxtNodeList
);
1326 // --> OD 2008-07-08 #i91400#
1327 pNumRule
->SetName( rNewName
, *this );
1330 SwNumRuleItem
aItem(rNewName
);
1331 // --> OD 2008-02-19 #refactorlists#
1332 // for (ULONG nI = 0; nI < aInfo.GetList().Count(); ++nI)
1334 // SwTxtNode * pTxtNd = aInfo.GetList().GetObject(nI);
1335 // pTxtNd->SwCntntNode::SetAttr(aItem);
1337 for ( SwNumRule::tTxtNodeList::iterator aIter
= aTxtNodeList
.begin();
1338 aIter
!= aTxtNodeList
.end(); ++aIter
)
1340 SwTxtNode
* pTxtNd
= *aIter
;
1341 pTxtNd
->SetAttr(aItem
);
1348 BroadcastStyleOperation(rOldName
, SFX_STYLE_FAMILY_PSEUDO
,
1349 SFX_STYLESHEET_MODIFIED
);
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 )
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 );
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
);
1389 BOOL
SwDoc::ReplaceNumRule( const SwPosition
& rPos
,
1390 const String
& rOldRule
, const String
& rNewRule
)
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;
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 ))
1427 // for( nLast = nFndPos; nLast < aUpd.GetList().Count(); ++nLast )
1429 // pTxtNd = aUpd.GetList().GetObject( nLast );
1430 // if(pTxtNd->IsRestart())
1433 // for( nFirst = nFndPos; nFirst; )
1435 // pTxtNd = aUpd.GetList().GetObject( --nFirst );
1436 // if( pTxtNd->IsRestart() )
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() )
1444 // pTxtNd->SetRestart(false);
1446 // pUndo->SetSttNum( pTxtNd->GetIndex() );
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 )
1465 // pTxtNd = aUpd.GetList().GetObject( nFirst );
1467 // aRegH.RegisterInModify( pTxtNd, *pTxtNd );
1469 // pTxtNd->SwCntntNode::SetAttr( aRule );
1470 // pTxtNd->NumRuleChgd();
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
);
1489 bRet
= TRUE
; // #106897#
1496 // --> OD 2008-03-18 #refactorlists#
1499 struct ListStyleData
1501 SwNumRule
* pReplaceNumRule
;
1502 bool bCreateNewList
;
1506 : pReplaceNumRule( 0 ),
1507 bCreateNewList( false ),
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
;
1523 ULONG nStt
= rPaM
.Start()->nNode
.GetIndex();
1524 ULONG nEnd
= rPaM
.End()->nNode
.GetIndex();
1528 for (ULONG n
= nStt
; n
<= nEnd
; n
++)
1530 SwTxtNode
* pCNd
= GetNodes()[n
]->GetTxtNode();
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 )
1547 SwPosition
aPos(*pCNd
);
1548 aListStyleData
.pReplaceNumRule
=
1549 const_cast<SwNumRule
*>
1550 (SearchNumRule( aPos
, false, pCNd
->HasNumber(),
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 );
1565 aListStyleData
.bCreateNewList
= true;
1568 // aMyNumRuleMap[pRule] = pReplaceNumRule;
1569 aMyNumRuleMap
[pRule
] = aListStyleData
;
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
;
1591 BOOL
SwDoc::NoNum( const SwPaM
& rPam
)
1594 BOOL bRet
= SplitNode( *rPam
.GetPoint(), false );
1595 // ist ueberhaupt Nummerierung im Spiel ?
1598 // NoNum setzen und Upaten
1599 const SwNodeIndex
& rIdx
= rPam
.GetPoint()->nNode
;
1600 SwTxtNode
* pNd
= rIdx
.GetNode().GetTxtNode();
1601 const SwNumRule
* pRule
= pNd
->GetNumRule();
1604 pNd
->SetCountedInList(false);
1609 bRet
= FALSE
; // keine Nummerierung , ?? oder immer TRUE ??
1614 void SwDoc::DelNumRules( const SwPaM
& rPam
)
1616 ULONG nStt
= rPam
.GetPoint()->nNode
.GetIndex(),
1617 nEnd
= rPam
.GetMark()->nNode
.GetIndex();
1620 ULONG nTmp
= nStt
; nStt
= nEnd
; nEnd
= nTmp
;
1623 SwUndoDelNum
* pUndo
;
1627 AppendUndo( pUndo
= new SwUndoDelNum( rPam
) );
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
)
1647 // recognize changes of attribute for undo
1648 aRegH
.RegisterInModify( pTNd
, *pTNd
);
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();
1657 pAttrSet
->GetItemState( RES_PARATR_NUMRULE
, FALSE
) == SFX_ITEM_SET
)
1658 pTNd
->ResetAttr( RES_PARATR_NUMRULE
);
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
);
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
1680 // dann noch alle Updaten
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" );
1705 if( bOverUpper
? nSrchNum
== nNumber
: nSrchNum
>= nNumber
)
1707 else if( nNumber
> rLower
)
1709 else if( nNumber
< rUpper
)
1715 BOOL
lcl_IsValidPrevNextNumNode( const SwNodeIndex
& rIdx
)
1718 const SwNode
& rNd
= rIdx
.GetNode();
1719 switch( rNd
.GetNodeType() )
1722 bRet
= SwTableBoxStartNode
== rNd
.StartOfSectionNode()->GetStartNodeType() ||
1723 rNd
.StartOfSectionNode()->IsSectionNode();
1727 bRet
= SwTableBoxStartNode
== ((SwStartNode
&)rNd
).GetStartNodeType();
1730 case ND_SECTIONNODE
: // der ist erlaubt, also weiter
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()))
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
1752 BOOL bError
= FALSE
;
1755 if( aIdx
.GetNode().IsTxtNode() )
1757 pNd
= aIdx
.GetNode().GetTxtNode();
1758 pRule
= pNd
->GetNumRule();
1764 nTmpNum
= static_cast<BYTE
>(pNd
->GetActualListLevel());
1765 if( !( ! pNd
->IsCountedInList() &&
1766 (nTmpNum
>= nSrchNum
)) )
1773 bError
= !lcl_IsValidPrevNextNumNode( aIdx
);
1780 BYTE nLower
= nSrchNum
, nUpper
= nSrchNum
;
1783 const SwTxtNode
* pLast
;
1785 aIdx
++, pLast
= pNd
;
1789 while( bNext
? ( aIdx
.GetIndex() < aIdx
.GetNodes().Count() - 1 )
1792 if( aIdx
.GetNode().IsTxtNode() )
1794 pNd
= aIdx
.GetNode().GetTxtNode();
1795 pRule
= pNd
->GetNumRule();
1798 if( ::lcl_IsNumOk( nSrchNum
, nLower
, nUpper
, bOverUpper
,
1799 static_cast<BYTE
>(pNd
->GetActualListLevel()) ))
1802 rPos
.nContent
.Assign( (SwTxtNode
*)pNd
, 0 );
1812 else if( !lcl_IsValidPrevNextNumNode( aIdx
))
1821 if( !bRet
&& !bOverUpper
&& pLast
) // nicht ueber hoehere Nummmern, aber bis Ende
1826 if( aIdx
.GetNode().IsCntntNode() )
1827 rPos
.nContent
.Assign( aIdx
.GetNode().GetCntntNode(), 0 );
1831 rPos
.nNode
.Assign( *pLast
);
1832 rPos
.nContent
.Assign( (SwTxtNode
*)pLast
, 0 );
1847 BOOL
SwDoc::GotoNextNum( SwPosition
& rPos
, BOOL bOverUpper
,
1848 BYTE
* pUpper
, BYTE
* pLower
)
1850 return ::lcl_GotoNextPrevNum( rPos
, TRUE
, bOverUpper
, pUpper
, pLower
);
1854 // --> OD 2008-03-18 #refactorlists# - add output parameter <sListId>
1855 const SwNumRule
* SwDoc::SearchNumRule(const SwPosition
& rPos
,
1856 const bool bForward
,
1858 const bool bOutline
,
1859 int nNonEmptyAllowed
,
1861 const bool bInvestigateStartNode
)
1863 const SwNumRule
* pResult
= NULL
;
1864 SwTxtNode
* pTxtNd
= rPos
.nNode
.GetNode().GetTxtNode();
1865 SwNode
* pStartFromNode
= 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
)
1885 if (aIdx
.GetNode().IsTxtNode())
1887 pTxtNd
= aIdx
.GetNode().GetTxtNode();
1889 const SwNumRule
* pNumRule
= pTxtNd
->GetNumRule();
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();
1904 else if (pTxtNd
->Len() > 0 || NULL
!= pTxtNd
->GetNumRule())
1906 if (nNonEmptyAllowed
== 0)
1911 if (nNonEmptyAllowed
< 0)
1912 nNonEmptyAllowed
= -1;
1916 // --> OD 2005-10-20 #i55391#
1917 if ( bInvestigateStartNode
)
1926 pNode
= &aIdx
.GetNode();
1928 while (! (pNode
== aNodes
.DocumentSectionStartNode(pStartFromNode
) ||
1929 pNode
== aNodes
.DocumentSectionEndNode(pStartFromNode
)));
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();
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();
1961 SwNumRule
* pRule
= pTxtNd
->GetNumRule();
1965 if (pRule
->IsOutlineRule())
1966 bOnlyNonOutline
= false;
1968 bOnlyOutline
= false;
1975 char nDiff
= bDown
? 1 : -1;
1979 bRet
= OutlineUpDown(rPam
, nDiff
);
1980 else if (bOnlyNonOutline
)
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.
1996 SwNumRule
* pRule
= pTNd
->GetNumRule();
2000 BYTE nLevel
= static_cast<BYTE
>(pTNd
->GetActualListLevel());
2001 if( (-1 == nDiff
&& 0 >= nLevel
) ||
2002 (1 == nDiff
&& MAXLEVEL
- 1 <= nLevel
))
2015 AppendUndo( new SwUndoNumUpDown( rPam
, nDiff
) );
2020 for(ULONG nTmp
= nStt
; nTmp
<= nEnd
; ++nTmp
)
2022 SwTxtNode
* pTNd
= GetNodes()[ nTmp
]->GetTxtNode();
2026 SwNumRule
* pRule
= pTNd
->GetNumRule();
2030 BYTE nLevel
= static_cast<BYTE
>(pTNd
->GetActualListLevel());
2031 nLevel
= nLevel
+ nDiff
;
2033 pTNd
->SetAttrListLevel(nLevel
);
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
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
;
2092 nInEndIdx
= nEndIdx
;
2098 //Impossible to move to negative index
2099 if( ULONG(abs( nOffset
)) > nStIdx
)
2102 nInEndIdx
= nStIdx
- 1;
2105 nInStIdx
= nInEndIdx
+ 1;
2106 // Folgende Absatzbloecke sollen vertauscht werden:
2107 // [ nStIdx, nInEndIdx ] mit [ nInStIdx, nEndIdx ]
2109 if( nEndIdx
>= GetNodes().GetEndOfContent().GetIndex() )
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();
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
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();
2171 case POS_COLLIDE_END
:
2172 case POS_BEFORE
: // Pos1 liegt vor Pos2
2174 case POS_INSIDE
: // Pos1 liegt vollstaendig in Pos2
2175 // ist erlaubt, aber checke dann alle nachfolgenden
2176 // auf Ueberlappungen
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
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;
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() )) )
2223 if( nRedlPos
+ 1 < GetRedlineTbl().Count() )
2225 pTmp
= GetRedlineTbl()[ nRedlPos
+1 ];
2226 if( *pTmp
->Start() == *pREnd
)
2232 !( pRStt
->nNode
<= aIdx
&& aIdx
<= pREnd
->nNode
))
2234 // nicht in sich selbst, dann auch nicht moven
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
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!");
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
2276 AppendTxtNode(*aInsPam
.GetPoint());
2277 aInsPos
= *aInsPam
.GetPoint();
2281 CopyRange( aPam
, aInsPos
, false );
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
2293 for( USHORT n
= 0; n
< GetRedlineTbl().Count(); ++n
)
2295 SwRedline
* pTmp
= GetRedlineTbl()[ n
];
2296 if( ( pPos
= &pTmp
->GetBound(TRUE
))->nNode
== aIdx
)
2299 pPos
->nContent
.Assign( pPos
->nNode
.GetNode().GetCntntNode(),0);
2301 if( ( pPos
= &pTmp
->GetBound(FALSE
))->nNode
== aIdx
)
2304 pPos
->nContent
.Assign( pPos
->nNode
.GetNode().GetCntntNode(),0);
2307 CorrRel( aIdx
, aInsPos
, 0, FALSE
);
2312 rOrigPam
.GetPoint()->nNode
++;
2313 rOrigPam
.GetPoint()->nContent
.Assign( rOrigPam
.GetCntntNode(), 0 );
2315 RedlineMode_t eOld
= GetRedlineMode();
2316 checkRedlining(eOld
);
2319 //JP 06.01.98: MUSS noch optimiert werden!!!
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
);
2344 if( !pOwnRedl
&& !IsIgnoreRedline() && GetRedlineTbl().Count() )
2347 SplitRedline(aTemp
);
2350 ULONG
nRedlSttNd(0), nRedlEndNd(0);
2353 const SwPosition
*pRStt
= pOwnRedl
->Start(), *pREnd
= pOwnRedl
->End();
2354 nRedlSttNd
= pRStt
->nNode
.GetIndex();
2355 nRedlEndNd
= pREnd
->nNode
.GetIndex();
2358 SwUndoMoveNum
* pUndo
= 0;
2362 pUndo
= new SwUndoMoveNum( rPam
, nOffset
, bIsOutlMv
);
2363 nMoved
= rPam
.End()->nNode
.GetIndex() - rPam
.Start()->nNode
.GetIndex() + 1;
2367 MoveNodeRange( aMvRg
, aIdx
, DOC_MOVEREDLINES
);
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
);
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
);
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);
2421 SwUndoNumOrNoNum
* pUndo
=
2422 new SwUndoNumOrNoNum(rIdx
, bOldNum
, bNewNum
);
2427 else if (bDel
&& pTxtNd
->GetNumRule(FALSE
) &&
2428 pTxtNd
->GetActualListLevel() >= 0 &&
2429 pTxtNd
->GetActualListLevel() < MAXLEVEL
)
2431 SwPaM
aPam(*pTxtNd
);
2442 SwNumRule
* SwDoc::GetCurrNumRule( const SwPosition
& rPos
) const
2444 SwNumRule
* pRet
= 0;
2445 SwTxtNode
* pTNd
= rPos
.nNode
.GetNode().GetTxtNode();
2449 // --> OD 2008-02-20 #refactorlists#
2450 // pTNd->SyncNumberAndNumRule();
2452 pRet
= pTNd
->GetNumRule();
2458 USHORT
SwDoc::FindNumRule( const String
& rName
) const
2460 for( USHORT n
= pNumRuleTbl
->Count(); n
; )
2461 if( (*pNumRuleTbl
)[ --n
]->GetName() == rName
)
2467 SwNumRule
* SwDoc::FindNumRulePtr( const String
& rName
) const
2469 SwNumRule
* pResult
= 0;
2471 pResult
= maNumRuleMap
[rName
];
2475 for (USHORT n
= 0; n
< pNumRuleTbl
->Count(); ++n
)
2477 if ((*pNumRuleTbl
)[n
]->GetName() == rName
)
2479 pResult
= (*pNumRuleTbl
)[n
];
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() );
2501 // --> OD 2008-02-11 #newlistlevelattrs#
2502 USHORT
SwDoc::MakeNumRule( const String
&rName
,
2503 const SwNumRule
* pCpy
,
2505 const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode
)
2510 pNew
= new SwNumRule( *pCpy
);
2512 // --> OD 2008-07-08 #i91400#
2513 pNew
->SetName( GetUniqueNumRuleName( &rName
), *this );
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() );
2524 pNew
->CheckCharFmts( this );
2528 // --> OD 2008-02-11 #newlistlevelattrs#
2529 pNew
= new SwNumRule( GetUniqueNumRuleName( &rName
),
2530 eDefaultNumberFormatPositionAndSpaceMode
);
2534 USHORT nRet
= pNumRuleTbl
->Count();
2536 AddNumRule(pNew
); // #i36749#
2540 SwUndo
* pUndo
= new SwUndoNumruleCreate(pNew
, this);
2546 BroadcastStyleOperation(pNew
->GetName(), SFX_STYLE_FAMILY_PSEUDO
,
2547 SFX_STYLESHEET_CREATED
);
2552 String
SwDoc::GetUniqueNumRuleName( const String
* pChkStr
, BOOL bAutoNum
) const
2557 long n
= Time().GetTime();
2558 n
+= Date().GetDate();
2559 aName
= String::CreateFromInt32( n
);
2560 if( pChkStr
&& !pChkStr
->Len() )
2563 else if( pChkStr
&& pChkStr
->Len() )
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
) )
2582 if( ++nNmLen
< aName
.Len() )
2584 aName
.Erase( nNmLen
);
2589 const SwNumRule
* pNumRule
;
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
) )
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
2622 delete [] pSetFlags
;
2623 if( pChkStr
&& pChkStr
->Len() )
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
,
2641 SwList
* pList
= getListByName( sListId
);
2645 MarkListLevel( *pList
, nListLevel
, bValue
);
2649 void SwDoc::MarkListLevel( SwList
& rList
,
2650 const int nListLevel
,
2653 // Set new marked list level and notify all affected nodes of the changed mark.
2654 rList
.MarkListLevel( nListLevel
, bValue
);
2660 BOOL
SwDoc::IsFirstOfNumRule(SwPosition
& rPos
)
2662 BOOL bResult
= FALSE
;
2663 SwTxtNode
* pTxtNode
= rPos
.nNode
.GetNode().GetTxtNode();
2667 SwNumRule
* pNumRule
= pTxtNode
->GetNumRule();
2670 bResult
= pTxtNode
->IsFirstOfNumRule();
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 )
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 )
2708 const tImplSortedNodeNumList::size_type nDeleted
= mpListItemsList
->erase( &rNodeNum
);
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
)
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
);
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() );
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
) )
2813 "<SwDoc::createList(..)> - provided list id already used. Serious defect -> please inform OD." );
2817 SwNumRule
* pDefaultNumRuleForNewList
= FindNumRulePtr( sDefaultListStyleName
);
2818 if ( !pDefaultNumRuleForNewList
)
2821 "<SwDoc::createList(..)> - for provided default list style name no list style is found. Serious defect -> please inform OD." );
2825 SwList
* pNewList
= new SwList( sListId
, *pDefaultNumRuleForNewList
, GetNodes() );
2826 maLists
[sListId
] = pNewList
;
2831 void SwDoc::deleteList( const String sListId
)
2833 SwList
* pList
= getListByName( sListId
);
2836 maLists
.erase( sListId
);
2841 SwList
* SwDoc::getListByName( const String sListId
) const
2845 std::hash_map
< String
, SwList
*, StringHash
>::const_iterator
2846 aListIter
= maLists
.find( sListId
);
2847 if ( aListIter
!= maLists
.end() )
2849 pList
= (*aListIter
).second
;
2855 SwList
* SwDoc::createListForListStyle( const String sListStyleName
)
2857 if ( sListStyleName
.Len() == 0 )
2860 "<SwDoc::createListForListStyle(..)> - no list style name provided. Serious defect -> please inform OD." );
2864 if ( getListForListStyle( sListStyleName
) )
2867 "<SwDoc::createListForListStyle(..)> - a list for the provided list style name already exists. Serious defect -> please inform OD." );
2871 SwNumRule
* pNumRule
= FindNumRulePtr( sListStyleName
);
2875 "<SwDoc::createListForListStyle(..)> - for provided list style name no list style is found. Serious defect -> please inform OD." );
2879 String
sListId( pNumRule
->GetDefaultListId() ); // can be empty String
2880 if ( getListByName( sListId
) )
2884 SwList
* pNewList
= createList( sListId
, sListStyleName
);
2885 maListStyleLists
[sListStyleName
] = pNewList
;
2886 pNumRule
->SetDefaultListId( pNewList
->GetListId() );
2891 SwList
* SwDoc::getListForListStyle( const String sListStyleName
) const
2895 std::hash_map
< String
, SwList
*, StringHash
>::const_iterator
2896 aListIter
= maListStyleLists
.find( sListStyleName
);
2897 if ( aListIter
!= maListStyleLists
.end() )
2899 pList
= (*aListIter
).second
;
2905 void SwDoc::deleteListForListStyle( const String sListStyleName
)
2909 SwList
* pList
= getListForListStyle( sListStyleName
);
2911 "<SwDoc::deleteListForListStyle(..)> - misusage of method: no list found for given list style name" );
2914 sListId
= pList
->GetListId();
2917 if ( sListId
.Len() > 0 )
2919 maListStyleLists
.erase( sListStyleName
);
2920 deleteList( sListId
);
2924 // --> OD 2008-07-08 #i91400#
2925 void SwDoc::trackChangeOfListStyleName( const String sListStyleName
,
2926 const String sNewListStyleName
)
2928 SwList
* pList
= getListForListStyle( sListStyleName
);
2930 "<SwDoc::changeOfListStyleName(..)> - misusage of method: no list found for given list style name" );
2934 maListStyleLists
.erase( sListStyleName
);
2935 maListStyleLists
[sNewListStyleName
] = pList
;
2940 // --> OD 2008-03-13 #refactorlists#
2943 const String
MakeListIdUnique( const SwDoc
& rDoc
,
2944 const String aSuggestedUniqueListId
)
2947 String aTmpStr
= aSuggestedUniqueListId
;
2948 while ( rDoc
.getListByName( aTmpStr
) )
2951 aTmpStr
= aSuggestedUniqueListId
;
2952 aTmpStr
+= String::CreateFromInt32( nHitCount
);
2957 const String
CreateUniqueListId( const SwDoc
& rDoc
)
2959 // --> OD 2008-08-06 #i92478#
2960 String aNewListId
= String::CreateFromAscii( "list" );
2962 sal_Int64 n
= Time().GetTime();
2963 n
+= Date().GetDate();
2965 // --> OD 2008-08-06 #i92478#
2966 aNewListId
+= String::CreateFromInt64( n
);
2969 return MakeListIdUnique( rDoc
, aNewListId
);