xref: /AOO41X/main/sw/source/core/bastyp/index.cxx (revision 5b9fe260567c89ea63ab4f5a3401a5cdea677aab)
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 
28 #include <stdlib.h>             // fuer qsort
29 #include <tools/solar.h>
30 
31 #include "errhdl.hxx"           // fuers ASSERT
32 #include "index.hxx"
33 #include "error.h"              // fuers ASSERT
34 
35 #ifdef DBG_UTIL
36 int SwIndex::nSerial = 0;
37 #endif
38 
39 
40 TYPEINIT0(SwIndexReg);  // rtti
41 
42 
43 #ifdef CHK
44 
45 #define IDX_CHK_ARRAY       pArray->ChkArr();
46 #define AR R_CHK_ARRAY       ChkArr();
47 
ChkArr()48 void SwIndexReg::ChkArr()
49 {
50     if ( ! ((pFirst && pLast) || (!pFirst && !pLast)))
51     {
52         ASSERT(false, "array not correctly indexed");
53     }
54 
55     if( !pFirst )
56         return;
57 
58     xub_StrLen nVal = 0;
59     const SwIndex* pIdx = pFirst, *pPrev = 0;
60     if ( ! (!pIdx->pPrev))
61     {
62         ASSERT(false, "array-pFirst not at beginning");
63     }
64 
65     while( pIdx != pLast )
66     {
67         if ( ! (pIdx->pPrev != pIdx && pIdx->pNext != pIdx))
68         {
69             ASSERT(false, "index points to itself");
70         }
71 
72         if ( ! (pIdx->nIndex >= nVal))
73         {
74             ASSERT(false, "wrong order");
75         }
76         if ( ! (pPrev == pIdx->pPrev))
77         {
78             ASSERT(false, "wrong array pointers");
79         }
80         if ( ! (this == pIdx->pArray))
81         {
82             ASSERT(false, "wrong array/child relationship");
83         }
84         pPrev = pIdx;
85         pIdx = pIdx->pNext;
86         nVal = pPrev->nIndex;
87     }
88 }
89 
90 #else                                   // CHK
91 
92 #define IDX_CHK_ARRAY
93 #define ARR_CHK_ARRAY
94 
95 #endif                                  // CHK
96 
97 
98 
SwIndex(SwIndexReg * const pArr,xub_StrLen const nIdx)99 SwIndex::SwIndex(SwIndexReg *const pArr, xub_StrLen const nIdx)
100     : nIndex( nIdx ), pArray( pArr ), pNext( 0 ), pPrev( 0 )
101 {
102     if( !pArray )
103     {
104         pArray = SwIndexReg::pEmptyIndexArray;
105         nIndex = 0;     // steht immer auf 0 !!!
106     }
107 
108     if( !pArray->pFirst )         // 1. Index ??
109         pArray->pFirst = pArray->pLast = this;
110     else if( nIdx > ((pArray->pLast->nIndex - pArray->pFirst->nIndex) / 2) )
111         ChgValue( *pArray->pLast, nIdx );
112     else
113         ChgValue( *pArray->pFirst, nIdx );
114 
115 #ifdef DBG_UTIL
116     MySerial = ++nSerial;       // nur in der nicht PRODUCT-Version
117 #endif
118 IDX_CHK_ARRAY
119 }
120 
121 
SwIndex(const SwIndex & rIdx,short nIdx)122 SwIndex::SwIndex( const SwIndex& rIdx, short nIdx )
123     : pArray( rIdx.pArray ), pNext( 0 ), pPrev( 0 )
124 {
125     ChgValue( rIdx, rIdx.nIndex + nIdx );
126 
127 #ifdef DBG_UTIL
128     MySerial = ++nSerial;       // nur in der nicht PRODUCT-Version
129 #endif
130 IDX_CHK_ARRAY
131 }
132 
133 
SwIndex(const SwIndex & rIdx)134 SwIndex::SwIndex( const SwIndex& rIdx )
135     : nIndex( rIdx.nIndex ), pArray( rIdx.pArray ), pNext( 0 ), pPrev( 0 )
136 {
137     ChgValue( rIdx, rIdx.nIndex );
138 #ifdef DBG_UTIL
139     MySerial = ++nSerial;       // nur in der nicht PRODUCT-Version
140 #endif
141 IDX_CHK_ARRAY
142 }
143 
144 
ChgValue(const SwIndex & rIdx,xub_StrLen nNewValue)145 SwIndex& SwIndex::ChgValue( const SwIndex& rIdx, xub_StrLen nNewValue )
146 {
147     SwIndex* pFnd = (SwIndex*)&rIdx;
148     if( rIdx.nIndex > nNewValue )               // nach vorne versuchen
149     {
150         SwIndex* pPrv;
151         while( 0 != ( pPrv = pFnd->pPrev ) && pPrv->nIndex > nNewValue )
152             pFnd = pPrv;
153 
154         if( pFnd != this )
155         {
156             // an alter Position ausketten
157             // erstmal an alter Position ausketten
158             if( pPrev )
159                 pPrev->pNext = pNext;
160             else if( pArray->pFirst == this )
161                 pArray->pFirst = pNext;
162 
163             if( pNext )
164                 pNext->pPrev = pPrev;
165             else if( pArray->pLast == this )
166                 pArray->pLast = pPrev;
167 
168             pNext = pFnd;
169             pPrev = pFnd->pPrev;
170             if( pPrev )
171                 pPrev->pNext = this;
172             else
173                 pArray->pFirst = this;
174             pFnd->pPrev = this;
175         }
176     }
177     else if( rIdx.nIndex < nNewValue )
178     {
179         SwIndex* pNxt;
180         while( 0 != ( pNxt = pFnd->pNext ) && pNxt->nIndex < nNewValue )
181             pFnd = pNxt;
182 
183         if( pFnd != this )
184         {
185             // erstmal an alter Position ausketten
186             if( pPrev )
187                 pPrev->pNext = pNext;
188             else if( pArray->pFirst == this )
189                 pArray->pFirst = pNext;
190 
191             if( pNext )
192                 pNext->pPrev = pPrev;
193             else if( pArray->pLast == this )
194                 pArray->pLast = pPrev;
195 
196             pPrev = pFnd;
197             pNext = pFnd->pNext;
198             if( pNext )
199                 pNext->pPrev = this;
200             else
201                 pArray->pLast = this;
202             pFnd->pNext = this;
203         }
204     }
205     else if( pFnd != this )
206     {
207         // erstmal an alter Position ausketten
208         if( pPrev )
209             pPrev->pNext = pNext;
210         else if( pArray->pFirst == this )
211             pArray->pFirst = pNext;
212 
213         if( pNext )
214             pNext->pPrev = pPrev;
215         else if( pArray->pLast == this )
216             pArray->pLast = pPrev;
217 
218         pPrev = (SwIndex*)&rIdx;
219         pNext = rIdx.pNext;
220         pPrev->pNext = this;
221 
222         if( !pNext )            // im IndexArray als letzes
223             pArray->pLast = this;
224         else
225             pNext->pPrev = this;
226     }
227     pArray = rIdx.pArray;
228 
229     if( pArray->pFirst == pNext )
230         pArray->pFirst = this;
231     if( pArray->pLast == pPrev )
232         pArray->pLast = this;
233 
234     nIndex = nNewValue;
235 
236 IDX_CHK_ARRAY
237 
238     return *this; }
239 
240 
Remove()241 void SwIndex::Remove()
242 {
243     if (pArray->pFirst==NULL && pArray->pLast==NULL)
244     {
245         // The index object is not a member of its list and therefore
246         // can not be removed.
247         return;
248     }
249 
250     if (pPrev==NULL && pNext==NULL)
251     {
252         // Removing last element in list.
253         pArray->pFirst = NULL;
254         pArray->pLast = NULL;
255     }
256     else
257     {
258         if( !pPrev )
259         {
260             OSL_ASSERT(pNext!=NULL);
261             pArray->pFirst = pNext;
262         }
263         else
264             pPrev->pNext = pNext;
265 
266         if( !pNext )
267         {
268             OSL_ASSERT(pPrev!=NULL);
269             pArray->pLast = pPrev;
270         }
271         else
272             pNext->pPrev = pPrev;
273     }
274 IDX_CHK_ARRAY
275 }
276 
277 /*************************************************************************
278 |*
279 |*    SwIndex & SwIndex::operator=( const SwIndex & aSwIndex )
280 |*
281 |*    Beschreibung
282 |*    Ersterstellung    JP 07.11.90
283 |*    Letzte Aenderung  JP 07.03.94
284 |*
285 *************************************************************************/
286 
287 
operator =(const SwIndex & rIdx)288 SwIndex& SwIndex::operator=( const SwIndex& rIdx )
289 {
290     int bEqual;
291     if( rIdx.pArray != pArray )         // im alten abmelden !!
292     {
293         Remove();
294         pArray = rIdx.pArray;
295         pNext = pPrev = 0;
296         bEqual = sal_False;
297     }
298     else
299         bEqual = rIdx.nIndex == nIndex;
300 
301     if( !bEqual )
302         ChgValue( rIdx, rIdx.nIndex );
303     return *this;
304 }
305 
306 /*************************************************************************
307 |*
308 |*    SwIndex &SwIndex::Assign
309 |*
310 |*    Beschreibung
311 |*    Ersterstellung    VB 25.03.91
312 |*    Letzte Aenderung  JP 07.03.94
313 |*
314 *************************************************************************/
315 
316 
Assign(SwIndexReg * pArr,xub_StrLen nIdx)317 SwIndex& SwIndex::Assign( SwIndexReg* pArr, xub_StrLen nIdx )
318 {
319     if( !pArr )
320     {
321         pArr = SwIndexReg::pEmptyIndexArray;
322         nIdx = 0;       // steht immer auf 0 !!!
323     }
324 
325     if( pArr != pArray )            // im alten abmelden !!
326     {
327         Remove();
328         pArray = pArr;
329         pNext = pPrev = 0;
330         if( !pArr->pFirst )         // 1. Index ??
331         {
332             pArr->pFirst = pArr->pLast = this;
333             nIndex = nIdx;
334         }
335         else if( pArr->pLast && (nIdx > ((pArr->pLast->nIndex - pArr->pFirst->nIndex) / 2)) )
336             ChgValue( *pArr->pLast, nIdx );
337         else
338             ChgValue( *pArr->pFirst, nIdx );
339     }
340     else if( nIndex != nIdx )
341         ChgValue( *this, nIdx );
342 IDX_CHK_ARRAY
343     return *this;
344 }
345 
346 
SwIndexReg()347 SwIndexReg::SwIndexReg()
348     : pFirst( 0 ), pLast( 0 )
349 {
350 }
351 
352 
353 
~SwIndexReg()354 SwIndexReg::~SwIndexReg()
355 {
356     ASSERT( !pFirst || !pLast, "Es sind noch Indizies angemeldet" );
357 }
358 
359 
Update(SwIndex const & rIdx,const xub_StrLen nDiff,const bool bNeg,const bool)360 void SwIndexReg::Update(
361     SwIndex const & rIdx,
362     const xub_StrLen nDiff,
363     const bool bNeg,
364     const bool /* argument is only used in derived class*/ )
365 {
366     SwIndex* pStt = const_cast<SwIndex*>(&rIdx);
367     const xub_StrLen nNewVal = rIdx.nIndex;
368     if( bNeg )
369     {
370         const xub_StrLen nLast = rIdx.GetIndex() + nDiff;
371         while( pStt && pStt->nIndex == nNewVal )
372         {
373             pStt->nIndex = nNewVal;
374             pStt = pStt->pPrev;
375         }
376         pStt = rIdx.pNext;
377         while( pStt && pStt->nIndex >= nNewVal &&
378                 pStt->nIndex <= nLast )
379         {
380             pStt->nIndex = nNewVal;
381             pStt = pStt->pNext;
382         }
383         while( pStt )
384         {
385             pStt->nIndex = pStt->nIndex - nDiff;
386             pStt = pStt->pNext;
387         }
388     }
389     else
390     {
391         while( pStt && pStt->nIndex == nNewVal )
392         {
393             pStt->nIndex = pStt->nIndex + nDiff;
394             pStt = pStt->pPrev;
395         }
396         pStt = rIdx.pNext;
397         while( pStt )
398         {
399             pStt->nIndex = pStt->nIndex + nDiff;
400             pStt = pStt->pNext;
401         }
402     }
403 ARR_CHK_ARRAY
404 }
405 
406 #ifdef DBG_UTIL
407 #ifndef CFRONT
408 
409 /*************************************************************************
410 |*
411 |*    SwIndex::operator++()
412 |*
413 |*    Beschreibung
414 |*    Ersterstellung    JP 07.11.90
415 |*    Letzte Aenderung  JP 07.03.94
416 |*
417 *************************************************************************/
operator ++(int)418 xub_StrLen SwIndex::operator++(int)
419 {
420     ASSERT_ID( nIndex < INVALID_INDEX, ERR_OUTOFSCOPE );
421 
422     xub_StrLen nOldIndex = nIndex;
423     ChgValue( *this, nIndex+1 );
424     return nOldIndex;
425 }
426 
427 #endif
428 
operator ++()429 xub_StrLen SwIndex::operator++()
430 {
431     ASSERT_ID( nIndex < INVALID_INDEX, ERR_OUTOFSCOPE );
432 
433     ChgValue( *this, nIndex+1 );
434     return nIndex;
435 }
436 
437 /*************************************************************************
438 |*
439 |*    SwIndex::operator--()
440 |*
441 |*    Beschreibung
442 |*    Ersterstellung    JP 07.11.90
443 |*    Letzte Aenderung  JP 07.03.94
444 |*
445 *************************************************************************/
446 
447 #ifndef CFRONT
448 
operator --(int)449 xub_StrLen SwIndex::operator--(int)
450 {
451     ASSERT_ID( nIndex, ERR_OUTOFSCOPE );
452 
453     xub_StrLen nOldIndex = nIndex;
454     ChgValue( *this, nIndex-1 );
455     return nOldIndex;
456 }
457 
458 #endif
459 
operator --()460 xub_StrLen SwIndex::operator--()
461 {
462     ASSERT_ID( nIndex, ERR_OUTOFSCOPE );
463     return ChgValue( *this, nIndex-1 ).nIndex;
464 }
465 
466 /*************************************************************************
467 |*
468 |*    SwIndex::operator+=( xub_StrLen )
469 |*
470 |*    Beschreibung
471 |*    Ersterstellung    JP 07.11.90
472 |*    Letzte Aenderung  JP 07.03.94
473 |*
474 *************************************************************************/
475 
operator +=(xub_StrLen nWert)476 xub_StrLen SwIndex::operator+=( xub_StrLen nWert )
477 {
478     ASSERT_ID( nIndex < INVALID_INDEX - nWert, ERR_OUTOFSCOPE);
479     return ChgValue( *this, nIndex + nWert ).nIndex;
480 }
481 
482 /*************************************************************************
483 |*
484 |*    SwIndex::operator-=( xub_StrLen )
485 |*
486 |*    Beschreibung
487 |*    Ersterstellung    JP 07.11.90
488 |*    Letzte Aenderung  JP 07.03.94
489 |*
490 *************************************************************************/
491 
operator -=(xub_StrLen nWert)492 xub_StrLen SwIndex::operator-=( xub_StrLen nWert )
493 {
494     ASSERT_ID( nIndex >= nWert, ERR_OUTOFSCOPE );
495     return ChgValue( *this, nIndex - nWert ).nIndex;
496 }
497 
498 /*************************************************************************
499 |*
500 |*    SwIndex::operator+=( const SwIndex & )
501 |*
502 |*    Beschreibung
503 |*    Ersterstellung    JP 07.11.90
504 |*    Letzte Aenderung  JP 07.03.94
505 |*
506 *************************************************************************/
507 
operator +=(const SwIndex & rIndex)508 xub_StrLen SwIndex::operator+=( const SwIndex & rIndex )
509 {
510     ASSERT_ID( nIndex < INVALID_INDEX - rIndex.nIndex, ERR_OUTOFSCOPE );
511     return ChgValue( *this, nIndex + rIndex.nIndex ).nIndex;
512 }
513 
514 /*************************************************************************
515 |*
516 |*    SwIndex::operator-=( const SwIndex & )
517 |*
518 |*    Beschreibung
519 |*    Ersterstellung    JP 07.11.90
520 |*    Letzte Aenderung  JP 07.03.94
521 |*
522 *************************************************************************/
523 
operator -=(const SwIndex & rIndex)524 xub_StrLen SwIndex::operator-=( const SwIndex & rIndex )
525 {
526     ASSERT_ID( nIndex >= rIndex.nIndex, ERR_OUTOFSCOPE );
527     return ChgValue( *this, nIndex - rIndex.nIndex ).nIndex;
528 }
529 
530 /*************************************************************************
531 |*
532 |*    SwIndex::operator<( const SwIndex & )
533 |*
534 |*    Beschreibung
535 |*    Ersterstellung    JP 07.11.90
536 |*    Letzte Aenderung  JP 07.03.94
537 |*
538 *************************************************************************/
539 
operator <(const SwIndex & rIndex) const540 sal_Bool SwIndex::operator<( const SwIndex & rIndex ) const
541 {
542     ASSERT( pArray == rIndex.pArray, "Attempt to compare indices into different arrays.");
543     return nIndex < rIndex.nIndex;
544 }
545 
546 /*************************************************************************
547 |*
548 |*    SwIndex::operator<=( const SwIndex & )
549 |*
550 |*    Beschreibung
551 |*    Ersterstellung    JP 07.11.90
552 |*    Letzte Aenderung  JP 04.06.92
553 |*
554 *************************************************************************/
555 
operator <=(const SwIndex & rIndex) const556 sal_Bool SwIndex::operator<=( const SwIndex & rIndex ) const
557 {
558     ASSERT( pArray == rIndex.pArray, "Attempt to compare indices into different arrays.");
559     return nIndex <= rIndex.nIndex;
560 }
561 
562 /*************************************************************************
563 |*
564 |*    SwIndex::operator>( const SwIndex & )
565 |*
566 |*    Beschreibung
567 |*    Ersterstellung    JP 07.11.90
568 |*    Letzte Aenderung  JP 04.06.92
569 |*
570 *************************************************************************/
571 
operator >(const SwIndex & rIndex) const572 sal_Bool SwIndex::operator>( const SwIndex & rIndex ) const
573 {
574     ASSERT( pArray == rIndex.pArray, "Attempt to compare indices into different arrays.");
575     return nIndex > rIndex.nIndex;
576 }
577 
578 /*************************************************************************
579 |*
580 |*    SwIndex::operator>=( const SwIndex & )
581 |*
582 |*    Beschreibung
583 |*    Ersterstellung    JP 07.11.90
584 |*    Letzte Aenderung  JP 04.06.92
585 |*
586 *************************************************************************/
587 
operator >=(const SwIndex & rIndex) const588 sal_Bool SwIndex::operator>=( const SwIndex & rIndex ) const
589 {
590     ASSERT( pArray == rIndex.pArray, "Attempt to compare indices into different arrays.");
591     return nIndex >= rIndex.nIndex;
592 }
593 
594 /*************************************************************************
595 |*
596 |*    SwIndex & SwIndex::operator=( xub_StrLen )
597 |*
598 |*    Beschreibung
599 |*    Ersterstellung    JP 10.12.90
600 |*    Letzte Aenderung  JP 07.03.94
601 |*
602 *************************************************************************/
603 
operator =(xub_StrLen nWert)604 SwIndex& SwIndex::operator=( xub_StrLen nWert )
605 {
606     // Werte kopieren und im neuen Array anmelden
607     if( nIndex != nWert )
608         ChgValue( *this, nWert );
609 
610     return *this;
611 }
612 
613 #endif // ifndef PRODUCT
614 
MoveTo(SwIndexReg & rArr)615 void SwIndexReg::MoveTo( SwIndexReg& rArr )
616 {
617     if( this != &rArr && pFirst )
618     {
619         SwIndex* pIdx = (SwIndex*)pFirst, *pNext;
620         while( pIdx )
621         {
622             pNext = pIdx->pNext;
623             pIdx->Assign( &rArr, pIdx->GetIndex() );
624             pIdx = pNext;
625         }
626         pFirst = 0, pLast = 0;
627     }
628 }
629