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