xref: /aoo41x/main/sw/source/core/bastyp/index.cxx (revision c7a723bd)
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 
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 
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 
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 
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 
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 
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 
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 
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 
347 SwIndexReg::SwIndexReg()
348     : pFirst( 0 ), pLast( 0 )
349 {
350 }
351 
352 
353 
354 SwIndexReg::~SwIndexReg()
355 {
356 	ASSERT( !pFirst || !pLast, "Es sind noch Indizies angemeldet" );
357 }
358 
359 
360 
361 void SwIndexReg::Update( SwIndex const & rIdx, const xub_StrLen nDiff,
362     const bool bNeg, const bool /* argument is only used in derived class*/ )
363 {
364     SwIndex* pStt = const_cast<SwIndex*>(&rIdx);
365 	xub_StrLen nNewVal = rIdx.nIndex;
366 	if( bNeg )
367 	{
368 		xub_StrLen nLast = rIdx.GetIndex() + nDiff;
369 		while( pStt && pStt->nIndex == nNewVal )
370 		{
371 			pStt->nIndex = nNewVal;
372 			pStt = pStt->pPrev;
373 		}
374 		pStt = rIdx.pNext;
375 		while( pStt && pStt->nIndex >= nNewVal &&
376 				pStt->nIndex <= nLast )
377 		{
378 			pStt->nIndex = nNewVal;
379 			pStt = pStt->pNext;
380 		}
381 		while( pStt )
382 		{
383 			pStt->nIndex = pStt->nIndex - nDiff;
384 			pStt = pStt->pNext;
385 		}
386 	}
387 	else
388 	{
389 		while( pStt && pStt->nIndex == nNewVal )
390 		{
391 			pStt->nIndex = pStt->nIndex + nDiff;
392 			pStt = pStt->pPrev;
393 		}
394 		pStt = rIdx.pNext;
395 		while( pStt )
396 		{
397 			pStt->nIndex = pStt->nIndex + nDiff;
398 			pStt = pStt->pNext;
399 		}
400 	}
401 ARR_CHK_ARRAY
402 }
403 
404 #ifdef DBG_UTIL
405 #ifndef CFRONT
406 
407 /*************************************************************************
408 |*
409 |*    SwIndex::operator++()
410 |*
411 |*    Beschreibung
412 |*    Ersterstellung    JP 07.11.90
413 |*    Letzte Aenderung  JP 07.03.94
414 |*
415 *************************************************************************/
416 xub_StrLen SwIndex::operator++(int)
417 {
418     ASSERT_ID( nIndex < INVALID_INDEX, ERR_OUTOFSCOPE );
419 
420     xub_StrLen nOldIndex = nIndex;
421     ChgValue( *this, nIndex+1 );
422     return nOldIndex;
423 }
424 
425 #endif
426 
427 xub_StrLen SwIndex::operator++()
428 {
429     ASSERT_ID( nIndex < INVALID_INDEX, ERR_OUTOFSCOPE );
430 
431     ChgValue( *this, nIndex+1 );
432     return nIndex;
433 }
434 
435 /*************************************************************************
436 |*
437 |*    SwIndex::operator--()
438 |*
439 |*    Beschreibung
440 |*    Ersterstellung    JP 07.11.90
441 |*    Letzte Aenderung  JP 07.03.94
442 |*
443 *************************************************************************/
444 
445 #ifndef CFRONT
446 
447 xub_StrLen SwIndex::operator--(int)
448 {
449     ASSERT_ID( nIndex, ERR_OUTOFSCOPE );
450 
451     xub_StrLen nOldIndex = nIndex;
452     ChgValue( *this, nIndex-1 );
453     return nOldIndex;
454 }
455 
456 #endif
457 
458 xub_StrLen SwIndex::operator--()
459 {
460     ASSERT_ID( nIndex, ERR_OUTOFSCOPE );
461     return ChgValue( *this, nIndex-1 ).nIndex;
462 }
463 
464 /*************************************************************************
465 |*
466 |*    SwIndex::operator+=( xub_StrLen )
467 |*
468 |*    Beschreibung
469 |*    Ersterstellung    JP 07.11.90
470 |*    Letzte Aenderung  JP 07.03.94
471 |*
472 *************************************************************************/
473 
474 xub_StrLen SwIndex::operator+=( xub_StrLen nWert )
475 {
476     ASSERT_ID( nIndex < INVALID_INDEX - nWert, ERR_OUTOFSCOPE);
477     return ChgValue( *this, nIndex + nWert ).nIndex;
478 }
479 
480 /*************************************************************************
481 |*
482 |*    SwIndex::operator-=( xub_StrLen )
483 |*
484 |*    Beschreibung
485 |*    Ersterstellung    JP 07.11.90
486 |*    Letzte Aenderung  JP 07.03.94
487 |*
488 *************************************************************************/
489 
490 xub_StrLen SwIndex::operator-=( xub_StrLen nWert )
491 {
492     ASSERT_ID( nIndex >= nWert, ERR_OUTOFSCOPE );
493     return ChgValue( *this, nIndex - nWert ).nIndex;
494 }
495 
496 /*************************************************************************
497 |*
498 |*    SwIndex::operator+=( const SwIndex & )
499 |*
500 |*    Beschreibung
501 |*    Ersterstellung    JP 07.11.90
502 |*    Letzte Aenderung  JP 07.03.94
503 |*
504 *************************************************************************/
505 
506 xub_StrLen SwIndex::operator+=( const SwIndex & rIndex )
507 {
508     ASSERT_ID( nIndex < INVALID_INDEX - rIndex.nIndex, ERR_OUTOFSCOPE );
509     return ChgValue( *this, nIndex + rIndex.nIndex ).nIndex;
510 }
511 
512 /*************************************************************************
513 |*
514 |*    SwIndex::operator-=( const SwIndex & )
515 |*
516 |*    Beschreibung
517 |*    Ersterstellung    JP 07.11.90
518 |*    Letzte Aenderung  JP 07.03.94
519 |*
520 *************************************************************************/
521 
522 xub_StrLen SwIndex::operator-=( const SwIndex & rIndex )
523 {
524     ASSERT_ID( nIndex >= rIndex.nIndex, ERR_OUTOFSCOPE );
525     return ChgValue( *this, nIndex - rIndex.nIndex ).nIndex;
526 }
527 
528 /*************************************************************************
529 |*
530 |*    SwIndex::operator<( const SwIndex & )
531 |*
532 |*    Beschreibung
533 |*    Ersterstellung    JP 07.11.90
534 |*    Letzte Aenderung  JP 07.03.94
535 |*
536 *************************************************************************/
537 
538 sal_Bool SwIndex::operator<( const SwIndex & rIndex ) const
539 {
540     ASSERT( pArray == rIndex.pArray, "Attempt to compare indices into different arrays.");
541     return nIndex < rIndex.nIndex;
542 }
543 
544 /*************************************************************************
545 |*
546 |*    SwIndex::operator<=( const SwIndex & )
547 |*
548 |*    Beschreibung
549 |*    Ersterstellung    JP 07.11.90
550 |*    Letzte Aenderung  JP 04.06.92
551 |*
552 *************************************************************************/
553 
554 sal_Bool SwIndex::operator<=( const SwIndex & rIndex ) const
555 {
556     ASSERT( pArray == rIndex.pArray, "Attempt to compare indices into different arrays.");
557     return nIndex <= rIndex.nIndex;
558 }
559 
560 /*************************************************************************
561 |*
562 |*    SwIndex::operator>( const SwIndex & )
563 |*
564 |*    Beschreibung
565 |*    Ersterstellung    JP 07.11.90
566 |*    Letzte Aenderung  JP 04.06.92
567 |*
568 *************************************************************************/
569 
570 sal_Bool SwIndex::operator>( const SwIndex & rIndex ) const
571 {
572     ASSERT( pArray == rIndex.pArray, "Attempt to compare indices into different arrays.");
573     return nIndex > rIndex.nIndex;
574 }
575 
576 /*************************************************************************
577 |*
578 |*    SwIndex::operator>=( const SwIndex & )
579 |*
580 |*    Beschreibung
581 |*    Ersterstellung    JP 07.11.90
582 |*    Letzte Aenderung  JP 04.06.92
583 |*
584 *************************************************************************/
585 
586 sal_Bool SwIndex::operator>=( const SwIndex & rIndex ) const
587 {
588     ASSERT( pArray == rIndex.pArray, "Attempt to compare indices into different arrays.");
589     return nIndex >= rIndex.nIndex;
590 }
591 
592 /*************************************************************************
593 |*
594 |*    SwIndex & SwIndex::operator=( xub_StrLen )
595 |*
596 |*    Beschreibung
597 |*    Ersterstellung    JP 10.12.90
598 |*    Letzte Aenderung  JP 07.03.94
599 |*
600 *************************************************************************/
601 
602 SwIndex& SwIndex::operator=( xub_StrLen nWert )
603 {
604     // Werte kopieren und im neuen Array anmelden
605     if( nIndex != nWert )
606         ChgValue( *this, nWert );
607 
608     return *this;
609 }
610 
611 #endif // ifndef PRODUCT
612 
613 void SwIndexReg::MoveTo( SwIndexReg& rArr )
614 {
615 	if( this != &rArr && pFirst )
616 	{
617 		SwIndex* pIdx = (SwIndex*)pFirst, *pNext;
618 		while( pIdx )
619 		{
620 			pNext = pIdx->pNext;
621 			pIdx->Assign( &rArr, pIdx->GetIndex() );
622 			pIdx = pNext;
623 		}
624         pFirst = 0, pLast = 0;
625 	}
626 }
627