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