xref: /trunk/main/sw/source/core/bastyp/index.cxx (revision edfeb9b7)
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