xref: /AOO41X/main/svl/source/items/itemset.cxx (revision 54628ca40d27d15cc98fe861da7fff7e60c2f7d6)
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_svl.hxx"
26 
27 #include <string.h>
28 
29 #if STLPORT_VERSION>=321
30 #include <cstdarg>
31 #endif
32 
33 #define _SVSTDARR_USHORTS
34 #define _SVSTDARR_ULONGS
35 
36 #include <svl/svstdarr.hxx>
37 #include <svl/itemset.hxx>
38 #include <svl/itempool.hxx>
39 #include <svl/itemiter.hxx>
40 #include <svl/whiter.hxx>
41 #include <svl/nranges.hxx>
42 #include "whassert.hxx"
43 
44 #include <tools/stream.hxx>
45 #include <tools/solar.h>
46 
47 // STATIC DATA -----------------------------------------------------------
48 
49 static const sal_uInt16 nInitCount = 10; // einzelne USHORTs => 5 Paare ohne '0'
50 #ifdef DBG_UTIL
51 static sal_uLong nRangesCopyCount = 0;   // wie oft wurden Ranges kopiert
52 #endif
53 
54 DBG_NAME(SfxItemSet)
55 
56 //========================================================================
57 
58 #define NUMTYPE         sal_uInt16
59 #define SvNums          SvUShorts
60 #define SfxNumRanges    SfxUShortRanges
61 #include "nranges.cxx"
62 #undef NUMTYPE
63 #undef SvNums
64 #undef SfxNumRanges
65 
66 #define NUMTYPE         sal_uLong
67 #define SvNums          SvULongs
68 #define SfxNumRanges    SfxULongRanges
69 #include "nranges.cxx"
70 #undef NUMTYPE
71 #undef SvNums
72 #undef SfxNumRanges
73 
74 //========================================================================
75 
76 #ifdef DBG_UTIL
77 
78 
79 const sal_Char *DbgCheckItemSet( const void* pVoid )
80 {
81     const SfxItemSet *pSet = (const SfxItemSet*) pVoid;
82     SfxWhichIter aIter( *pSet );
83     sal_uInt16 nCount = 0, n = 0;
84     for ( sal_uInt16 nWh = aIter.FirstWhich(); nWh; nWh = aIter.NextWhich(), ++n )
85     {
86         const SfxPoolItem *pItem = pSet->_aItems[n];
87         if ( pItem )
88         {
89             ++nCount;
90             DBG_ASSERT( IsInvalidItem(pItem) ||
91                         pItem->Which() == 0 || pItem->Which() == nWh,
92                         "SfxItemSet: invalid which-id" );
93             DBG_ASSERT( IsInvalidItem(pItem) || !pItem->Which() ||
94                     !SfxItemPool::IsWhich(pItem->Which()) ||
95                     pSet->GetPool()->IsItemFlag(nWh, SFX_ITEM_NOT_POOLABLE) ||
96                     SFX_ITEMS_NULL != pSet->GetPool()->GetSurrogate(pItem),
97                     "SfxItemSet: item in set which is not in pool" );
98         }
99 
100     }
101     DBG_ASSERT( pSet->_nCount == nCount, "wrong SfxItemSet::nCount detected" );
102 
103     return 0;
104 }
105 
106 #endif
107 // -----------------------------------------------------------------------
108 
109 SfxItemSet::SfxItemSet
110 (
111     SfxItemPool&    rPool,          /* der Pool, in dem die SfxPoolItems,
112                                        welche in dieses SfxItemSet gelangen,
113                                        aufgenommen werden sollen */
114     sal_Bool
115 #ifdef DBG_UTIL
116 #ifdef SFX_ITEMSET_NO_DEFAULT_CTOR
117 
118                     bTotalRanges    /* komplette Pool-Ranges uebernehmen,
119                                        muss auf sal_True gesetzt werden */
120 #endif
121 #endif
122 )
123 /*  [Beschreibung]
124 
125     Konstruktor fuer ein SfxItemSet mit genau den Which-Bereichen, welche
126     dem angegebenen <SfxItemPool> bekannt sind.
127 
128 
129     [Anmerkung]
130 
131     F"ur Sfx-Programmierer ein derart konstruiertes SfxItemSet kann
132     keinerlei Items mit Slot-Ids als Which-Werte aufnehmen!
133 */
134 
135 :   _pPool( &rPool ),
136     _pParent( 0 ),
137     _nCount( 0 ),
138     _aHashKey( 0 ) //i120575
139 {
140     DBG_CTOR(SfxItemSet, DbgCheckItemSet);
141     DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
142     DBG( _pChildCountCtor; *_pChildCount(this) = 0 );
143 //  DBG_ASSERT( bTotalRanges || abs( &bTotalRanges - this ) < 1000,
144 //              "please use suitable ranges" );
145 #ifdef DBG_UTIL
146 #ifdef SFX_ITEMSET_NO_DEFAULT_CTOR
147     if ( !bTotalRanges )
148         *(int*)0 = 0; // GPF
149 #endif
150 #endif
151 
152     _pWhichRanges = (sal_uInt16*) _pPool->GetFrozenIdRanges();
153     DBG_ASSERT( _pWhichRanges, "don't create ItemSets with full range before FreezeIdRanges()" );
154     if ( !_pWhichRanges )
155         _pPool->FillItemIdRanges_Impl( _pWhichRanges );
156 
157     const sal_uInt16 nSize = TotalCount();
158     _aItems = new const SfxPoolItem* [ nSize ];
159     memset( (void*) _aItems, 0, nSize * sizeof( SfxPoolItem* ) );
160 }
161 
162 // -----------------------------------------------------------------------
163 
164 SfxItemSet::SfxItemSet( SfxItemPool& rPool, sal_uInt16 nWhich1, sal_uInt16 nWhich2 ):
165     _pPool( &rPool ),
166     _pParent( 0 ),
167     _nCount( 0 ),
168     _aHashKey( 0 ) //i120575
169 {
170     DBG_CTOR(SfxItemSet, DbgCheckItemSet);
171     DBG_ASSERT( nWhich1 <= nWhich2, "Ungueltiger Bereich" );
172     DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
173     DBG( _pChildCountCtor; *_pChildCount(this) = 0 );
174 
175     InitRanges_Impl(nWhich1, nWhich2);
176 }
177 
178 // -----------------------------------------------------------------------
179 
180 void SfxItemSet::InitRanges_Impl(sal_uInt16 nWh1, sal_uInt16 nWh2)
181 {
182     DBG_CHKTHIS(SfxItemSet, 0);
183     _pWhichRanges = new sal_uInt16[ 3 ];
184     *(_pWhichRanges+0) = nWh1;
185     *(_pWhichRanges+1) = nWh2;
186     *(_pWhichRanges+2) = 0;
187     const sal_uInt16 nRg = nWh2 - nWh1 + 1;
188     _aItems = new const SfxPoolItem* [ nRg ];
189     memset( (void*) _aItems, 0, nRg * sizeof( SfxPoolItem* ) );
190 }
191 
192 // -----------------------------------------------------------------------
193 
194 void SfxItemSet::InitRanges_Impl(va_list pArgs, sal_uInt16 nWh1, sal_uInt16 nWh2, sal_uInt16 nNull)
195 {
196     DBG_CHKTHIS(SfxItemSet, 0);
197 
198     sal_uInt16 nSize = InitializeRanges_Impl( _pWhichRanges, pArgs, nWh1, nWh2, nNull );
199     _aItems = new const SfxPoolItem* [ nSize ];
200     memset( (void*) _aItems, 0, sizeof( SfxPoolItem* ) * nSize );
201 }
202 
203 // -----------------------------------------------------------------------
204 
205 SfxItemSet::SfxItemSet( SfxItemPool& rPool,
206                         USHORT_ARG nWh1, USHORT_ARG nWh2, USHORT_ARG nNull, ... ):
207     _pPool( &rPool ),
208     _pParent( 0 ),
209     _pWhichRanges( 0 ),
210     _nCount( 0 ),
211     _aHashKey( 0 ) //i120575
212 {
213     DBG_CTOR(SfxItemSet, DbgCheckItemSet);
214     DBG_ASSERT( nWh1 <= nWh2, "Ungueltiger Bereich" );
215     DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
216     DBG( _pChildCountCtor; *_pChildCount(this) = 0 );
217 
218     if(!nNull)
219         InitRanges_Impl(
220             sal::static_int_cast< sal_uInt16 >(nWh1),
221             sal::static_int_cast< sal_uInt16 >(nWh2));
222     else {
223         va_list pArgs;
224         va_start( pArgs, nNull );
225         InitRanges_Impl(
226             pArgs, sal::static_int_cast< sal_uInt16 >(nWh1),
227             sal::static_int_cast< sal_uInt16 >(nWh2),
228             sal::static_int_cast< sal_uInt16 >(nNull));
229     }
230 }
231 
232 // -----------------------------------------------------------------------
233 
234 void SfxItemSet::InitRanges_Impl(const sal_uInt16 *pWhichPairTable)
235 {
236     DBG_CHKTHIS(SfxItemSet, 0);
237     DBG_TRACE1("SfxItemSet: Ranges-CopyCount==%ul", ++nRangesCopyCount);
238 
239     sal_uInt16 nCnt = 0;
240     const sal_uInt16* pPtr = pWhichPairTable;
241     while( *pPtr )
242     {
243         nCnt += ( *(pPtr+1) - *pPtr ) + 1;
244         pPtr += 2;
245     }
246 
247     _aItems = new const SfxPoolItem* [ nCnt ];
248     memset( (void*) _aItems, 0, sizeof( SfxPoolItem* ) * nCnt );
249 
250     std::ptrdiff_t cnt = pPtr - pWhichPairTable +1;
251     _pWhichRanges = new sal_uInt16[ cnt ];
252     memcpy( _pWhichRanges, pWhichPairTable, sizeof( sal_uInt16 ) * cnt );
253 }
254 
255 
256 // -----------------------------------------------------------------------
257 
258 SfxItemSet::SfxItemSet( SfxItemPool& rPool, const sal_uInt16* pWhichPairTable ):
259     _pPool( &rPool ),
260     _pParent( 0 ),
261     _pWhichRanges(0),
262     _nCount( 0 ),
263     _aHashKey( 0 ) //i120575
264 {
265     DBG_CTOR(SfxItemSet, 0);
266     DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
267     DBG( _pChildCountCtor; *_pChildCount(this) = 0 );
268 
269     // pWhichPairTable == 0 ist f"ur das SfxAllEnumItemSet
270     if ( pWhichPairTable )
271         InitRanges_Impl(pWhichPairTable);
272 }
273 
274 // -----------------------------------------------------------------------
275 
276 SfxItemSet::SfxItemSet( const SfxItemSet& rASet ):
277     _pPool( rASet._pPool ),
278     _pParent( rASet._pParent ),
279     _nCount( rASet._nCount ),
280     _aHashKey( 0 ) //i120575
281 {
282     DBG_CTOR(SfxItemSet, DbgCheckItemSet);
283     DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
284     DBG( _pChildCountCtor; *_pChildCount(this) = 0 );
285     DBG( ++*_pChildCount(_pParent) );
286 
287     // errechne die Anzahl von Attributen
288     sal_uInt16 nCnt = 0;
289     sal_uInt16* pPtr = rASet._pWhichRanges;
290     while( *pPtr )
291     {
292         nCnt += ( *(pPtr+1) - *pPtr ) + 1;
293         pPtr += 2;
294     }
295 
296     _aItems = new const SfxPoolItem* [ nCnt ];
297 
298     // Attribute kopieren
299     SfxItemArray ppDst = _aItems, ppSrc = rASet._aItems;
300     for( sal_uInt16 n = nCnt; n; --n, ++ppDst, ++ppSrc )
301         if ( 0 == *ppSrc ||                 // aktueller Default?
302              IsInvalidItem(*ppSrc) ||       // Dont Care?
303              IsStaticDefaultItem(*ppSrc) )  // nicht zu poolende Defaults
304             // einfach Pointer kopieren
305             *ppDst = *ppSrc;
306         else if ( _pPool->IsItemFlag( **ppSrc, SFX_ITEM_POOLABLE ) )
307         {
308             // einfach Pointer kopieren und Ref-Count erh"ohen
309             *ppDst = *ppSrc;
310             ( (SfxPoolItem*) (*ppDst) )->AddRef();
311         }
312         else if ( !(*ppSrc)->Which() )
313             *ppDst = (*ppSrc)->Clone();
314         else
315             // !IsPoolable() => via Pool zuweisen
316             *ppDst = &_pPool->Put( **ppSrc );
317 
318     // dann noch die Which Ranges kopieren
319     DBG_TRACE1("SfxItemSet: Ranges-CopyCount==%ul", ++nRangesCopyCount);
320     std::ptrdiff_t cnt = pPtr - rASet._pWhichRanges+1;
321     _pWhichRanges = new sal_uInt16[ cnt ];
322     memcpy( _pWhichRanges, rASet._pWhichRanges, sizeof( sal_uInt16 ) * cnt);
323 }
324 
325 // -----------------------------------------------------------------------
326 
327 SfxItemSet::~SfxItemSet()
328 {
329     DBG_DTOR(SfxItemSet, DbgCheckItemSet);
330 #ifdef DBG_UTIL
331     DBG( DBG_ASSERT( 0 == *_pChildCount(this), "SfxItemSet: deleting parent-itemset" ) )
332 #endif
333 
334     sal_uInt16 nCount = TotalCount();
335     if( Count() )
336     {
337         SfxItemArray ppFnd = _aItems;
338         for( sal_uInt16 nCnt = nCount; nCnt; --nCnt, ++ppFnd )
339             if( *ppFnd && !IsInvalidItem(*ppFnd) )
340             {
341                 if( !(*ppFnd)->Which() )
342                     delete (SfxPoolItem*) *ppFnd;
343                 else {
344                     // noch mehrer Referenzen vorhanden, also nur den
345                     // ReferenzCounter manipulieren
346                     if ( 1 < (*ppFnd)->GetRefCount() && !IsDefaultItem(*ppFnd) )
347                         (*ppFnd)->ReleaseRef();
348                     else
349                         if ( !IsDefaultItem(*ppFnd) )
350                             // aus dem Pool loeschen
351                             _pPool->Remove( **ppFnd );
352                 }
353             }
354     }
355 
356     // FIXME: could be delete[] (SfxPoolItem **)_aItems;
357     delete[] _aItems;
358     if ( _pWhichRanges != _pPool->GetFrozenIdRanges() )
359         delete[] _pWhichRanges;
360     _pWhichRanges = 0; // for invariant-testing
361 
362     DBG( --*_pChildCount(_pParent) );
363     DBG( delete _pChildCount(this); _pChildCountDtor );
364 }
365 
366 // -----------------------------------------------------------------------
367 
368 sal_uInt16 SfxItemSet::ClearItem( sal_uInt16 nWhich )
369 
370 // einzelnes Item oder alle Items (nWhich==0) l"oschen
371 
372 {
373     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
374     if( !Count() )
375         return 0;
376 
377     sal_uInt16 nDel = 0;
378     SfxItemArray ppFnd = _aItems;
379 
380     if( nWhich )
381     {
382         const sal_uInt16* pPtr = _pWhichRanges;
383         while( *pPtr )
384         {
385             // in diesem Bereich?
386             if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
387             {
388                 // "uberhaupt gesetzt?
389                 ppFnd += nWhich - *pPtr;
390                 if( *ppFnd )
391                 {
392                     // wegen der Assertions ins Sub-Calls mu\s das hier sein
393                     --_nCount;
394                     const SfxPoolItem *pItemToClear = *ppFnd;
395                     *ppFnd = 0;
396 
397                     if ( !IsInvalidItem(pItemToClear) )
398                     {
399                         if ( nWhich <= SFX_WHICH_MAX )
400                         {
401                             const SfxPoolItem& rNew = _pParent
402                                     ? _pParent->Get( nWhich, sal_True )
403                                     : _pPool->GetDefaultItem( nWhich );
404 
405                             Changed( *pItemToClear, rNew );
406                         }
407                         if ( pItemToClear->Which() )
408                             _pPool->Remove( *pItemToClear );
409                     }
410                     ++nDel;
411                 }
412 
413                 // gefunden => raus
414                 break;
415             }
416             ppFnd += *(pPtr+1) - *pPtr + 1;
417             pPtr += 2;
418         }
419     }
420     else
421     {
422         nDel = _nCount;
423 
424         sal_uInt16* pPtr = _pWhichRanges;
425         while( *pPtr )
426         {
427             for( nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
428                 if( *ppFnd )
429                 {
430                     // wegen der Assertions ins Sub-Calls mu\s das hier sein
431                     --_nCount;
432                     const SfxPoolItem *pItemToClear = *ppFnd;
433                     *ppFnd = 0;
434 
435                     if ( !IsInvalidItem(pItemToClear) )
436                     {
437                         if ( nWhich <= SFX_WHICH_MAX )
438                         {
439                             const SfxPoolItem& rNew = _pParent
440                                     ? _pParent->Get( nWhich, sal_True )
441                                     : _pPool->GetDefaultItem( nWhich );
442 
443                             Changed( *pItemToClear, rNew );
444                         }
445 
446                         // #i32448#
447                         // Take care of disabled items, too.
448                         if(!pItemToClear->nWhich)
449                         {
450                             // item is disabled, delete it
451                             delete pItemToClear;
452                         }
453                         else
454                         {
455                             // remove item from pool
456                             _pPool->Remove( *pItemToClear );
457                         }
458                     }
459                 }
460             pPtr += 2;
461         }
462     }
463     InvalidateHashKey();    //i120575
464     return nDel;
465 }
466 
467 // -----------------------------------------------------------------------
468 
469 void SfxItemSet::ClearInvalidItems( sal_Bool bHardDefault )
470 {
471     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
472     sal_uInt16* pPtr = _pWhichRanges;
473     SfxItemArray ppFnd = _aItems;
474     if ( bHardDefault )
475         while( *pPtr )
476         {
477             for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
478                 if ( IsInvalidItem(*ppFnd) )
479                      *ppFnd = &_pPool->Put( _pPool->GetDefaultItem(nWhich) );
480             pPtr += 2;
481         }
482     else
483         while( *pPtr )
484         {
485             for( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
486                 if( IsInvalidItem(*ppFnd) )
487                 {
488                     *ppFnd = 0;
489                     --_nCount;
490                 }
491             pPtr += 2;
492         }
493     InvalidateHashKey();    //i120575
494 }
495 
496 //------------------------------------------------------------------------
497 
498 
499 void SfxItemSet::InvalidateAllItems()
500 {
501     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
502     DBG_ASSERT( !_nCount, "Es sind noch Items gesetzt" );
503 
504     memset( (void*)_aItems, -1, ( _nCount = TotalCount() ) * sizeof( SfxPoolItem*) );
505     InvalidateHashKey();    //i120575
506 }
507 
508 // -----------------------------------------------------------------------
509 
510 SfxItemState SfxItemSet::GetItemState( sal_uInt16 nWhich,
511                                         sal_Bool bSrchInParent,
512                                         const SfxPoolItem **ppItem ) const
513 {
514     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
515     // suche den Bereich in dem das Which steht:
516     const SfxItemSet* pAktSet = this;
517     SfxItemState eRet = SFX_ITEM_UNKNOWN;
518     do
519     {
520         SfxItemArray ppFnd = pAktSet->_aItems;
521         const sal_uInt16* pPtr = pAktSet->_pWhichRanges;
522         if (pPtr)
523         {
524             while ( *pPtr )
525             {
526                 if ( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
527                 {
528                     // in diesem Bereich
529                     ppFnd += nWhich - *pPtr;
530                     if ( !*ppFnd )
531                     {
532                         eRet = SFX_ITEM_DEFAULT;
533                         if( !bSrchInParent )
534                             return eRet;  // nicht vorhanden
535                         break; // JP: in den Parents weitersuchen !!!
536                     }
537 
538                     if ( (SfxPoolItem*) -1 == *ppFnd )
539                         // Unterschiedlich vorhanden
540                         return SFX_ITEM_DONTCARE;
541 
542                     if ( (*ppFnd)->Type() == TYPE(SfxVoidItem) )
543                         return SFX_ITEM_DISABLED;
544 
545                     if (ppItem)
546                     {
547                         #ifdef DBG_UTIL
548                         const SfxPoolItem *pItem = *ppFnd;
549                         DBG_ASSERT( !pItem->ISA(SfxSetItem) ||
550                                 0 != &((const SfxSetItem*)pItem)->GetItemSet(),
551                                 "SetItem without ItemSet" );
552                         #endif
553                         *ppItem = *ppFnd;
554                     }
555                     return SFX_ITEM_SET;
556                 }
557                 ppFnd += *(pPtr+1) - *pPtr + 1;
558                 pPtr += 2;
559             }
560         }
561     } while( bSrchInParent && 0 != ( pAktSet = pAktSet->_pParent ));
562     return eRet;
563 }
564 
565 // -----------------------------------------------------------------------
566 
567 const SfxPoolItem* SfxItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich )
568 {
569     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
570     DBG_ASSERT( !rItem.ISA(SfxSetItem) ||
571             0 != &((const SfxSetItem&)rItem).GetItemSet(),
572             "SetItem without ItemSet" );
573     if ( !nWhich )
574         return 0; //! nur wegen Outliner-Bug
575     SfxItemArray ppFnd = _aItems;
576     const sal_uInt16* pPtr = _pWhichRanges;
577     while( *pPtr )
578     {
579         if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
580         {
581             // in diesem Bereich
582             ppFnd += nWhich - *pPtr;
583             if( *ppFnd )        // schon einer vorhanden
584             {
585                 // selbes Item bereits vorhanden?
586                 if ( *ppFnd == &rItem )
587                     return 0;
588 
589                 // wird dontcare oder disabled mit was echtem ueberschrieben?
590                 if ( rItem.Which() && ( IsInvalidItem(*ppFnd) || !(*ppFnd)->Which() ) )
591                 {
592                     *ppFnd = &_pPool->Put( rItem, nWhich );
593                     InvalidateHashKey();    //i120575
594                     return *ppFnd;
595                 }
596 
597                 // wird disabled?
598                 if( !rItem.Which() )
599                 {
600                     *ppFnd = rItem.Clone(_pPool);
601                     InvalidateHashKey();    //i120575
602                     return 0;
603                 }
604                 else
605                 {
606                     // selber Wert bereits vorhanden?
607                     if ( rItem == **ppFnd )
608                         return 0;
609 
610                     // den neuen eintragen, den alten austragen
611                     const SfxPoolItem& rNew = _pPool->Put( rItem, nWhich );
612                     const SfxPoolItem* pOld = *ppFnd;
613                     *ppFnd = &rNew;
614                     if(nWhich <= SFX_WHICH_MAX)
615                         Changed( *pOld, rNew );
616                     _pPool->Remove( *pOld );
617                 }
618             }
619             else
620             {
621                 ++_nCount;
622                 if( !rItem.Which() )
623                     *ppFnd = rItem.Clone(_pPool);
624                 else {
625                     const SfxPoolItem& rNew = _pPool->Put( rItem, nWhich );
626                     *ppFnd = &rNew;
627                     if (nWhich <= SFX_WHICH_MAX )
628                     {
629                         const SfxPoolItem& rOld = _pParent
630                             ? _pParent->Get( nWhich, sal_True )
631                             : _pPool->GetDefaultItem( nWhich );
632                         Changed( rOld, rNew );
633                     }
634                 }
635             }
636             SFX_ASSERT( !_pPool->IsItemFlag(nWhich, SFX_ITEM_POOLABLE) ||
637                         rItem.ISA(SfxSetItem) || **ppFnd == rItem,
638                         nWhich, "putted Item unequal" );
639 
640             InvalidateHashKey();    //i120575
641             return *ppFnd;
642         }
643         ppFnd += *(pPtr+1) - *pPtr + 1;
644         pPtr += 2;
645     }
646     InvalidateHashKey();    //i120575
647     return 0;
648 }
649 
650 // -----------------------------------------------------------------------
651 
652 int SfxItemSet::Put( const SfxItemSet& rSet, sal_Bool bInvalidAsDefault )
653 {
654     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
655     sal_Bool bRet = sal_False;
656     if( rSet.Count() )
657     {
658         SfxItemArray ppFnd = rSet._aItems;
659         const sal_uInt16* pPtr = rSet._pWhichRanges;
660         while ( *pPtr )
661         {
662             for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
663                 if( *ppFnd )
664                 {
665                     if ( IsInvalidItem( *ppFnd ) )
666                     {
667                         if ( bInvalidAsDefault )
668                             bRet |= 0 != ClearItem( nWhich );
669                             // gab GPF bei non.WIDs:
670                             // bRet |= 0 != Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
671                         else
672                             InvalidateItem( nWhich );
673                     }
674                     else
675                         bRet |= 0 != Put( **ppFnd, nWhich );
676                 }
677             pPtr += 2;
678         }
679     }
680     return bRet;
681 }
682 
683 // -----------------------------------------------------------------------
684 
685 void SfxItemSet::PutExtended
686 (
687     const SfxItemSet&   rSet,           // Quelle der zu puttenden Items
688     SfxItemState        eDontCareAs,    // was mit DontCare-Items passiert
689     SfxItemState        eDefaultAs      // was mit Default-Items passiert
690 )
691 
692 /*  [Beschreibung]
693 
694     Diese Methode "ubernimmt die Items aus 'rSet' in '*this'. Die
695     Which-Bereiche in '*this', die in 'rSet' nicht vorkommen bleiben unver-
696     "andert. Der Which-Bereich von '*this' bleibt auch unver"andert.
697 
698     In 'rSet' gesetzte Items werden auch in '*this*' gesetzt. Default-
699     (0 Pointer) und Invalid- (-1 Pointer) Items werden je nach Parameter
700     ('eDontCareAs' und 'eDefaultAs' behandelt:
701 
702     SFX_ITEM_SET:       hart auf Default des Pools gesetzt
703     SFX_ITEM_DEFAULT:   gel"oscht (0 Pointer)
704     SFX_ITEM_DONTCARE:  invalidiert (-1 Pointer)
705 
706     Alle anderen Werte f"ur 'eDontCareAs' und 'eDefaultAs' sind ung"ultig.
707 */
708 
709 {
710     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
711 
712     // don't "optimize" with "if( rSet.Count()" because of dont-care + defaults
713     SfxItemArray ppFnd = rSet._aItems;
714     const sal_uInt16* pPtr = rSet._pWhichRanges;
715     while ( *pPtr )
716     {
717         for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd )
718             if( *ppFnd )
719             {
720                 if ( IsInvalidItem( *ppFnd ) )
721                 {
722                     // Item ist DontCare:
723                     switch ( eDontCareAs )
724                     {
725                         case SFX_ITEM_SET:
726                             Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
727                             break;
728 
729                         case SFX_ITEM_DEFAULT:
730                             ClearItem( nWhich );
731                             break;
732 
733                         case SFX_ITEM_DONTCARE:
734                             InvalidateItem( nWhich );
735                             break;
736 
737                         default:
738                             DBG_ERROR( "invalid Argument for eDontCareAs" );
739                     }
740                 }
741                 else
742                     // Item ist gesetzt:
743                     Put( **ppFnd, nWhich );
744             }
745             else
746             {
747                 // Item ist Default:
748                 switch ( eDefaultAs )
749                 {
750                     case SFX_ITEM_SET:
751                         Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
752                         break;
753 
754                     case SFX_ITEM_DEFAULT:
755                         ClearItem( nWhich );
756                         break;
757 
758                     case SFX_ITEM_DONTCARE:
759                         InvalidateItem( nWhich );
760                         break;
761 
762                     default:
763                         DBG_ERROR( "invalid Argument for eDefaultAs" );
764                 }
765             }
766         pPtr += 2;
767     }
768 }
769 
770 // -----------------------------------------------------------------------
771 
772 void SfxItemSet::MergeRange( sal_uInt16 nFrom, sal_uInt16 nTo )
773 /** <H3>Description</H3>
774 
775     Expands the ranges of settable items by 'nFrom' to 'nTo'. Keeps state of
776     items which are new ranges too.
777 */
778 
779 {
780     // special case: exactly one sal_uInt16 which is already included?
781     if ( nFrom == nTo && SFX_ITEM_AVAILABLE <= GetItemState(nFrom, sal_False) )
782         return;
783 
784     // merge new range
785     SfxUShortRanges aRanges( _pWhichRanges );
786     aRanges += SfxUShortRanges( nFrom, nTo );
787     SetRanges( aRanges );
788 }
789 
790 // -----------------------------------------------------------------------
791 
792 void SfxItemSet::SetRanges( const sal_uInt16 *pNewRanges )
793 
794 /** <H3>Description</H3>
795 
796     Modifies the ranges of settable items. Keeps state of items which
797     are new ranges too.
798 */
799 
800 {
801     // identische Ranges?
802     if ( _pWhichRanges == pNewRanges )
803         return;
804     const sal_uInt16* pOld = _pWhichRanges;
805     const sal_uInt16* pNew = pNewRanges;
806     while ( *pOld == *pNew )
807     {
808         if ( !*pOld && !*pNew )
809             return;
810         ++pOld, ++pNew;
811     }
812 
813     // create new item-array (by iterating through all new ranges)
814     sal_uLong        nSize = Capacity_Impl(pNewRanges);
815     SfxItemArray aNewItems = new const SfxPoolItem* [ nSize ];
816     sal_uInt16       n = 0, nNewCount = 0;
817     if ( _nCount == 0 )
818         memset( aNewItems, 0, nSize * sizeof( SfxPoolItem* ) );
819     else
820     {
821         for ( const sal_uInt16 *pRange = pNewRanges; *pRange; pRange += 2 )
822         {
823             // iterate through all ids in the range
824             for ( sal_uInt16 nWID = *pRange; nWID <= pRange[1]; ++nWID, ++n )
825             {
826                 // direct move of pointer (not via pool)
827                 SfxItemState eState = GetItemState( nWID, sal_False, aNewItems+n );
828                 if ( SFX_ITEM_SET == eState )
829                 {
830                     // increment new item count and possibly increment ref count
831                     ++nNewCount;
832                     aNewItems[n]->AddRef();
833                 }
834                 else if ( SFX_ITEM_DISABLED == eState )
835                 {
836                     // put "disabled" item
837                     ++nNewCount;
838                     aNewItems[n] = new SfxVoidItem(0);
839                 }
840                 else if ( SFX_ITEM_DONTCARE == eState )
841                 {
842                     ++nNewCount;
843                     aNewItems[n] = (SfxPoolItem*)-1;
844                 }
845                 else
846                 {
847                     // default
848                     aNewItems[n] = 0;
849                 }
850             }
851         }
852         // free old items
853         sal_uInt16 nOldTotalCount = TotalCount();
854         for ( sal_uInt16 nItem = 0; nItem < nOldTotalCount; ++nItem )
855         {
856             const SfxPoolItem *pItem = _aItems[nItem];
857             if ( pItem && !IsInvalidItem(pItem) && pItem->Which() )
858                 _pPool->Remove(*pItem);
859         }
860     }
861 
862     // replace old items-array and ranges
863     delete[] _aItems;
864     _aItems = aNewItems;
865     _nCount = nNewCount;
866 
867     if( pNewRanges == GetPool()->GetFrozenIdRanges() )
868     {
869         delete[] _pWhichRanges;
870         _pWhichRanges = ( sal_uInt16* ) pNewRanges;
871     }
872     else
873     {
874         sal_uInt16 nCount = Count_Impl(pNewRanges) + 1;
875         if ( _pWhichRanges != _pPool->GetFrozenIdRanges() )
876             delete[] _pWhichRanges;
877         _pWhichRanges = new sal_uInt16[ nCount ];
878         memcpy( _pWhichRanges, pNewRanges, sizeof( sal_uInt16 ) * nCount );
879     }
880     InvalidateHashKey();    //i120575
881 }
882 
883 // -----------------------------------------------------------------------
884 
885 int SfxItemSet::Set
886 (
887     const SfxItemSet&   rSet,   /*  das SfxItemSet, dessen SfxPoolItems
888                                     "ubernommen werden sollen */
889 
890     sal_Bool                bDeep   /*  sal_True (default)
891                                     auch die SfxPoolItems aus den ggf. an
892                                     rSet vorhandenen Parents werden direkt
893                                     in das SfxItemSet "ubernommen
894 
895                                     sal_False
896                                     die SfxPoolItems aus den Parents von
897                                     rSet werden nicht ber"ucksichtigt */
898 )
899 
900 /*  [Beschreibung]
901 
902     Das SfxItemSet nimmt genau die SfxPoolItems an, die auch in
903     rSet gesetzt sind und im eigenen <Which-Bereich> liegen. Alle
904     anderen werden entfernt. Der SfxItemPool wird dabei beibehalten,
905     so da"s die "ubernommenen SfxPoolItems dabei ggf. vom SfxItemPool
906     von rSet in den SfxItemPool von *this "ubernommen werden.
907 
908     SfxPoolItems, f"ur die in rSet IsInvalidItem() == sal_True gilt,
909     werden als Invalid-Item "ubernommen.
910 
911 
912     [R"uckgabewert]
913 
914     int                             sal_True
915                                     es wurden SfxPoolItems "ubernommen
916 
917                                     sal_False
918                                     es wurden keine SfxPoolItems "ubernommen,
919                                     da z.B. die Which-Bereiche der SfxItemSets
920                                     keine Schnittmenge haben oder in der
921                                     Schnittmenge keine SfxPoolItems in rSet
922                                     gesetzt sind
923 
924 */
925 
926 {
927     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
928     int bRet = sal_False;
929     if ( _nCount )
930         ClearItem();
931     if ( bDeep )
932     {
933         SfxWhichIter aIter(*this);
934         sal_uInt16 nWhich = aIter.FirstWhich();
935         while ( nWhich )
936         {
937             const SfxPoolItem* pItem;
938             if( SFX_ITEM_SET == rSet.GetItemState( nWhich, sal_True, &pItem ) )
939                 bRet |= 0 != Put( *pItem, pItem->Which() );
940             nWhich = aIter.NextWhich();
941         }
942     }
943     else
944         bRet = Put(rSet, sal_False);
945 
946     return bRet;
947 }
948 
949 //------------------------------------------------------------------------
950 
951 const SfxPoolItem* SfxItemSet::GetItem
952 (
953     sal_uInt16              nId,            // Slot-Id oder Which-Id des Items
954     sal_Bool                bSrchInParent,  // sal_True: auch in Parent-ItemSets suchen
955     TypeId              aItemType       // != 0 =>  RTTI Pruefung mit Assertion
956 )   const
957 
958 /*  [Beschreibung]
959 
960     Mit dieser Methode wird der Zugriff auf einzelne Items im
961     SfxItemSet wesentlich vereinfacht. Insbesondere wird die Typpr"ufung
962     (per Assertion) durchgef"uhrt, wodurch die Applikations-Sourcen
963     wesentlich "ubersichtlicher werden. In der PRODUCT-Version wird
964     eine 0 zur"uckgegeben, wenn das gefundene Item nicht von der
965     angegebenen Klasse ist. Ist kein Item mit der Id 'nWhich' in dem ItemSet,
966     so wird 0 zurueckgegeben.
967 */
968 
969 {
970     // ggf. in Which-Id umrechnen
971     sal_uInt16 nWhich = GetPool()->GetWhich(nId);
972 
973     // ist das Item gesetzt oder bei bDeep==sal_True verf"ugbar?
974     const SfxPoolItem *pItem = 0;
975     SfxItemState eState = GetItemState( nWhich, bSrchInParent, &pItem );
976     if ( bSrchInParent && SFX_ITEM_AVAILABLE == eState &&
977          nWhich <= SFX_WHICH_MAX )
978         pItem = &_pPool->GetDefaultItem(nWhich);
979     if ( pItem )
980     {
981         // stimmt der Typ "uberein?
982         if ( !aItemType || pItem->IsA(aItemType) )
983             return pItem;
984 
985         // sonst Fehler melden
986         DBG_ERROR( "invalid argument type" );
987     }
988 
989     // kein Item gefunden oder falschen Typ gefunden
990     return 0;
991 }
992 
993 
994 //------------------------------------------------------------------------
995 
996 
997 const SfxPoolItem& SfxItemSet::Get( sal_uInt16 nWhich, sal_Bool bSrchInParent) const
998 {
999     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1000     // suche den Bereich in dem das Which steht:
1001     const SfxItemSet* pAktSet = this;
1002     do
1003     {
1004         if( pAktSet->Count() )
1005         {
1006             SfxItemArray ppFnd = pAktSet->_aItems;
1007             const sal_uInt16* pPtr = pAktSet->_pWhichRanges;
1008             while( *pPtr )
1009             {
1010                 if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1011                 {
1012                     // in diesem Bereich
1013                     ppFnd += nWhich - *pPtr;
1014                     if( *ppFnd )
1015                     {
1016                         if( (SfxPoolItem*)-1 == *ppFnd ) {
1017                             //?MI: folgender code ist Doppelt (unten)
1018                             SFX_ASSERT(_pPool, nWhich, "kein Pool, aber Status uneindeutig");
1019                             //!((SfxAllItemSet *)this)->aDefault.SetWhich(nWhich);
1020                             //!return aDefault;
1021                             return _pPool->GetDefaultItem( nWhich );
1022                         }
1023 #ifdef DBG_UTIL
1024                         const SfxPoolItem *pItem = *ppFnd;
1025                         DBG_ASSERT( !pItem->ISA(SfxSetItem) ||
1026                                 0 != &((const SfxSetItem*)pItem)->GetItemSet(),
1027                                 "SetItem without ItemSet" );
1028                         if ( pItem->ISA(SfxVoidItem) || !pItem->Which() )
1029                             DBG_WARNING( "SFX_WARNING: Getting disabled Item" );
1030 #endif
1031                         return **ppFnd;
1032                     }
1033                     break;          // dann beim Parent suchen
1034                 }
1035                 ppFnd += *(pPtr+1) - *pPtr + 1;
1036                 pPtr += 2;
1037             }
1038         }
1039 // bis zum Ende vom Such-Bereich: was nun ? zum Parent, oder Default ??
1040 //      if( !*pPtr )            // bis zum Ende vom Such-Bereich ?
1041 //      break;
1042     } while( bSrchInParent && 0 != ( pAktSet = pAktSet->_pParent ));
1043 
1044     // dann das Default vom Pool holen und returnen
1045     SFX_ASSERT(_pPool, nWhich, "kein Pool, aber Status uneindeutig");
1046     const SfxPoolItem *pItem = &_pPool->GetDefaultItem( nWhich );
1047     DBG_ASSERT( !pItem->ISA(SfxSetItem) ||
1048             0 != &((const SfxSetItem*)pItem)->GetItemSet(),
1049             "SetItem without ItemSet" );
1050     return *pItem;
1051 }
1052 
1053     // Notification-Callback
1054 // -----------------------------------------------------------------------
1055 
1056 void SfxItemSet::Changed( const SfxPoolItem&, const SfxPoolItem& )
1057 {
1058     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1059 }
1060 
1061 // -----------------------------------------------------------------------
1062 
1063 sal_uInt16 SfxItemSet::TotalCount() const
1064 {
1065     DBG_CHKTHIS(SfxItemSet, 0); // wird im Ctor benutzt bevor vollst. init.
1066     sal_uInt16 nRet = 0;
1067     sal_uInt16* pPtr = _pWhichRanges;
1068     while( *pPtr )
1069     {
1070         nRet += ( *(pPtr+1) - *pPtr ) + 1;
1071         pPtr += 2;
1072     }
1073     return nRet;
1074 }
1075 // -----------------------------------------------------------------------
1076 
1077 // behalte nur die Items, die auch in rSet enthalten sein (Wert egal)
1078 
1079 void SfxItemSet::Intersect( const SfxItemSet& rSet )
1080 {
1081     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1082     DBG_ASSERT(_pPool, "nicht implementiert ohne Pool");
1083     if( !Count() )       // gar keine gesetzt ?
1084         return;
1085 
1086     // loesche alle Items, die im rSet nicht mehr vorhanden sind
1087     if( !rSet.Count() )
1088     {
1089         ClearItem();        // alles loeschen
1090         return;
1091     }
1092 
1093     // teste mal, ob sich die Which-Bereiche unterscheiden.
1094     sal_Bool bEqual = sal_True;
1095     sal_uInt16* pWh1 = _pWhichRanges;
1096     sal_uInt16* pWh2 = rSet._pWhichRanges;
1097     sal_uInt16 nSize = 0;
1098 
1099     for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n )
1100     {
1101         if( *pWh1 != *pWh2 )
1102         {
1103             bEqual = sal_False;
1104             break;
1105         }
1106         if( n & 1 )
1107             nSize += ( *(pWh1) - *(pWh1-1) ) + 1;
1108     }
1109     bEqual = *pWh1 == *pWh2;        // auch die 0 abpruefen
1110 
1111     // sind die Bereiche identisch, ist es einfacher zu handhaben !
1112     if( bEqual )
1113     {
1114         SfxItemArray ppFnd1 = _aItems;
1115         SfxItemArray ppFnd2 = rSet._aItems;
1116 
1117         for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
1118             if( *ppFnd1 && !*ppFnd2 )
1119             {
1120                 // aus dem Pool loeschen
1121                 if( !IsInvalidItem( *ppFnd1 ) )
1122                 {
1123                     sal_uInt16 nWhich = (*ppFnd1)->Which();
1124                     if(nWhich <= SFX_WHICH_MAX)
1125                     {
1126                         const SfxPoolItem& rNew = _pParent
1127                             ? _pParent->Get( nWhich, sal_True )
1128                             : _pPool->GetDefaultItem( nWhich );
1129 
1130                         Changed( **ppFnd1, rNew );
1131                     }
1132                     _pPool->Remove( **ppFnd1 );
1133                 }
1134                 *ppFnd1 = 0;
1135                 --_nCount;
1136             }
1137     }
1138     else
1139     {
1140         SfxItemIter aIter( *this );
1141         const SfxPoolItem* pItem = aIter.GetCurItem();
1142         while( sal_True )
1143         {
1144             sal_uInt16 nWhich = IsInvalidItem( pItem )
1145                                 ? GetWhichByPos( aIter.GetCurPos() )
1146                                 : pItem->Which();
1147             if( 0 == rSet.GetItemState( nWhich, sal_False ) )
1148                 ClearItem( nWhich );        // loeschen
1149             if( aIter.IsAtEnd() )
1150                 break;
1151             pItem = aIter.NextItem();
1152         }
1153     }
1154     InvalidateHashKey();    //i120575
1155 }
1156 
1157 // -----------------------------------------------------------------------
1158 
1159 void SfxItemSet::Differentiate( const SfxItemSet& rSet )
1160 {
1161     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1162     if( !Count() || !rSet.Count() )  // gar keine gesetzt ?
1163         return;
1164 
1165     // teste mal, ob sich die Which-Bereiche unterscheiden.
1166     sal_Bool bEqual = sal_True;
1167     sal_uInt16* pWh1 = _pWhichRanges;
1168     sal_uInt16* pWh2 = rSet._pWhichRanges;
1169     sal_uInt16 nSize = 0;
1170 
1171     for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n )
1172     {
1173         if( *pWh1 != *pWh2 )
1174         {
1175             bEqual = sal_False;
1176             break;
1177         }
1178         if( n & 1 )
1179             nSize += ( *(pWh1) - *(pWh1-1) ) + 1;
1180     }
1181     bEqual = *pWh1 == *pWh2;        // auch die 0 abpruefen
1182 
1183     // sind die Bereiche identisch, ist es einfacher zu handhaben !
1184     if( bEqual )
1185     {
1186         SfxItemArray ppFnd1 = _aItems;
1187         SfxItemArray ppFnd2 = rSet._aItems;
1188 
1189         for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
1190             if( *ppFnd1 && *ppFnd2 )
1191             {
1192                 // aus dem Pool loeschen
1193                 if( !IsInvalidItem( *ppFnd1 ) )
1194                 {
1195                     sal_uInt16 nWhich = (*ppFnd1)->Which();
1196                     if(nWhich <= SFX_WHICH_MAX)
1197                     {
1198                         const SfxPoolItem& rNew = _pParent
1199                             ? _pParent->Get( nWhich, sal_True )
1200                             : _pPool->GetDefaultItem( nWhich );
1201 
1202                         Changed( **ppFnd1, rNew );
1203                     }
1204                     _pPool->Remove( **ppFnd1 );
1205                 }
1206                 *ppFnd1 = 0;
1207                 --_nCount;
1208             }
1209     }
1210     else
1211     {
1212         SfxItemIter aIter( *this );
1213         const SfxPoolItem* pItem = aIter.GetCurItem();
1214         while( sal_True )
1215         {
1216             sal_uInt16 nWhich = IsInvalidItem( pItem )
1217                                 ? GetWhichByPos( aIter.GetCurPos() )
1218                                 : pItem->Which();
1219             if( SFX_ITEM_SET == rSet.GetItemState( nWhich, sal_False ) )
1220                 ClearItem( nWhich );        // loeschen
1221             if( aIter.IsAtEnd() )
1222                 break;
1223             pItem = aIter.NextItem();
1224         }
1225 
1226     }
1227     InvalidateHashKey();    //i120575
1228 }
1229 
1230 // -----------------------------------------------------------------------
1231 /* Entscheidungstabelle fuer MergeValue[s]
1232 
1233 Grundsaetze:
1234     1. Ist der Which-Wert im 1.Set "unknown", dann folgt niemals eine Aktion.
1235     2. Ist der Which-Wert im 2.Set "unknown", dann gilt er als "default".
1236     3. Es gelten fuer Vergleiche die Werte der "default"-Items.
1237 
1238 1.-Item     2.-Item     Values  bIgnoreDefs     Remove      Assign      Add
1239 
1240 set         set         ==      sal_False           -           -           -
1241 default     set         ==      sal_False           -           -           -
1242 dontcare    set         ==      sal_False           -           -           -
1243 unknown     set         ==      sal_False           -           -           -
1244 set         default     ==      sal_False           -           -           -
1245 default     default     ==      sal_False           -           -           -
1246 dontcare    default     ==      sal_False           -           -           -
1247 unknown     default     ==      sal_False           -           -           -
1248 set         dontcare    ==      sal_False           1.-Item     -1          -
1249 default     dontcare    ==      sal_False           -           -1          -
1250 dontcare    dontcare    ==      sal_False           -           -           -
1251 unknown     dontcare    ==      sal_False           -           -           -
1252 set         unknown     ==      sal_False           1.-Item     -1          -
1253 default     unknown     ==      sal_False           -           -           -
1254 dontcare    unknown     ==      sal_False           -           -           -
1255 unknown     unknown     ==      sal_False           -           -           -
1256 
1257 set         set         !=      sal_False           1.-Item     -1          -
1258 default     set         !=      sal_False           -           -1          -
1259 dontcare    set         !=      sal_False           -           -           -
1260 unknown     set         !=      sal_False           -           -           -
1261 set         default     !=      sal_False           1.-Item     -1          -
1262 default     default     !=      sal_False           -           -           -
1263 dontcare    default     !=      sal_False           -           -           -
1264 unknown     default     !=      sal_False           -           -           -
1265 set         dontcare    !=      sal_False           1.-Item     -1          -
1266 default     dontcare    !=      sal_False           -           -1          -
1267 dontcare    dontcare    !=      sal_False           -           -           -
1268 unknown     dontcare    !=      sal_False           -           -           -
1269 set         unknown     !=      sal_False           1.-Item     -1          -
1270 default     unknown     !=      sal_False           -           -           -
1271 dontcare    unknown     !=      sal_False           -           -           -
1272 unknown     unknown     !=      sal_False           -           -           -
1273 
1274 set         set         ==      sal_True            -           -           -
1275 default     set         ==      sal_True            -           2.-Item     2.-Item
1276 dontcare    set         ==      sal_True            -           -           -
1277 unknown     set         ==      sal_True            -           -           -
1278 set         default     ==      sal_True            -           -           -
1279 default     default     ==      sal_True            -           -           -
1280 dontcare    default     ==      sal_True            -           -           -
1281 unknown     default     ==      sal_True            -           -           -
1282 set         dontcare    ==      sal_True            -           -           -
1283 default     dontcare    ==      sal_True            -           -1          -
1284 dontcare    dontcare    ==      sal_True            -           -           -
1285 unknown     dontcare    ==      sal_True            -           -           -
1286 set         unknown     ==      sal_True            -           -           -
1287 default     unknown     ==      sal_True            -           -           -
1288 dontcare    unknown     ==      sal_True            -           -           -
1289 unknown     unknown     ==      sal_True            -           -           -
1290 
1291 set         set         !=      sal_True            1.-Item     -1          -
1292 default     set         !=      sal_True            -           2.-Item     2.-Item
1293 dontcare    set         !=      sal_True            -           -           -
1294 unknown     set         !=      sal_True            -           -           -
1295 set         default     !=      sal_True            -           -           -
1296 default     default     !=      sal_True            -           -           -
1297 dontcare    default     !=      sal_True            -           -           -
1298 unknown     default     !=      sal_True            -           -           -
1299 set         dontcare    !=      sal_True            1.-Item     -1          -
1300 default     dontcare    !=      sal_True            -           -1          -
1301 dontcare    dontcare    !=      sal_True            -           -           -
1302 unknown     dontcare    !=      sal_True            -           -           -
1303 set         unknown     !=      sal_True            -           -           -
1304 default     unknown     !=      sal_True            -           -           -
1305 dontcare    unknown     !=      sal_True            -           -           -
1306 unknown     unknown     !=      sal_True            -           -           -
1307 */
1308 
1309 
1310 static void MergeItem_Impl( SfxItemPool *_pPool, sal_uInt16 &rCount,
1311                             const SfxPoolItem **ppFnd1, const SfxPoolItem *pFnd2,
1312                             sal_Bool bIgnoreDefaults )
1313 {
1314     DBG_ASSERT( ppFnd1 != 0, "Merging to 0-Item" );
1315 
1316     // 1. Item ist default?
1317     if ( !*ppFnd1 )
1318     {
1319         if ( IsInvalidItem(pFnd2) )
1320             // Entscheidungstabelle: default, dontcare, egal, egal
1321             *ppFnd1 = (SfxPoolItem*) -1;
1322 
1323         else if ( pFnd2 && !bIgnoreDefaults &&
1324                   _pPool->GetDefaultItem(pFnd2->Which()) != *pFnd2 )
1325             // Entscheidungstabelle: default, set, !=, sal_False
1326             *ppFnd1 = (SfxPoolItem*) -1;
1327 
1328         else if ( pFnd2 && bIgnoreDefaults )
1329             // Entscheidungstabelle: default, set, egal, sal_True
1330             *ppFnd1 = &_pPool->Put( *pFnd2 );
1331 
1332         if ( *ppFnd1 )
1333             ++rCount;
1334     }
1335 
1336     // 1. Item ist gesetzt?
1337     else if ( !IsInvalidItem(*ppFnd1) )
1338     {
1339         if ( !pFnd2 )
1340         {
1341             // 2. Item ist default
1342             if ( !bIgnoreDefaults &&
1343                  **ppFnd1 != _pPool->GetDefaultItem((*ppFnd1)->Which()) )
1344             {
1345                 // Entscheidungstabelle: set, default, !=, sal_False
1346                 _pPool->Remove( **ppFnd1 );
1347                 *ppFnd1 = (SfxPoolItem*) -1;
1348             }
1349         }
1350         else if ( IsInvalidItem(pFnd2) )
1351         {
1352             // 2. Item ist dontcare
1353             if ( !bIgnoreDefaults ||
1354                  **ppFnd1 != _pPool->GetDefaultItem( (*ppFnd1)->Which()) )
1355             {
1356                 // Entscheidungstabelle: set, dontcare, egal, sal_False
1357                 // oder:                 set, dontcare, !=, sal_True
1358                 _pPool->Remove( **ppFnd1 );
1359                 *ppFnd1 = (SfxPoolItem*) -1;
1360             }
1361         }
1362         else
1363         {
1364             // 2. Item ist gesetzt
1365             if ( **ppFnd1 != *pFnd2 )
1366             {
1367                 // Entscheidungstabelle: set, set, !=, egal
1368                 _pPool->Remove( **ppFnd1 );
1369                 *ppFnd1 = (SfxPoolItem*) -1;
1370             }
1371         }
1372     }
1373 }
1374 
1375 // -----------------------------------------------------------------------
1376 
1377 void SfxItemSet::MergeValues( const SfxItemSet& rSet, sal_Bool bIgnoreDefaults )
1378 {
1379     // Achtung!!! Bei Aenderungen/Bugfixes immer obenstehende Tabelle pflegen!
1380     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1381     DBG_ASSERT( GetPool() == rSet.GetPool(), "MergeValues mit verschiedenen Pools" );
1382 
1383     // teste mal, ob sich die Which-Bereiche unterscheiden.
1384     sal_Bool bEqual = sal_True;
1385     sal_uInt16* pWh1 = _pWhichRanges;
1386     sal_uInt16* pWh2 = rSet._pWhichRanges;
1387     sal_uInt16 nSize = 0;
1388 
1389     for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n )
1390     {
1391         if( *pWh1 != *pWh2 )
1392         {
1393             bEqual = sal_False;
1394             break;
1395         }
1396         if( n & 1 )
1397             nSize += ( *(pWh1) - *(pWh1-1) ) + 1;
1398     }
1399     bEqual = *pWh1 == *pWh2; // auch die 0 abpruefen
1400 
1401     // sind die Bereiche identisch, ist es effizieter zu handhaben !
1402     if( bEqual )
1403     {
1404         SfxItemArray ppFnd1 = _aItems;
1405         SfxItemArray ppFnd2 = rSet._aItems;
1406 
1407         for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 )
1408             MergeItem_Impl( _pPool, _nCount, ppFnd1, *ppFnd2, bIgnoreDefaults );
1409     }
1410     else
1411     {
1412         SfxWhichIter aIter( rSet );
1413         register sal_uInt16 nWhich;
1414         while( 0 != ( nWhich = aIter.NextWhich() ) )
1415         {
1416             const SfxPoolItem* pItem = 0;
1417             rSet.GetItemState( nWhich, sal_True, &pItem );
1418             if( !pItem )
1419             {
1420                 // nicht gesetzt, also default
1421                 if ( !bIgnoreDefaults )
1422                     MergeValue( rSet.GetPool()->GetDefaultItem( nWhich ), bIgnoreDefaults );
1423             }
1424             else if( IsInvalidItem( pItem ) )
1425                 // dont care
1426                 InvalidateItem( nWhich );
1427             else
1428                 MergeValue( *pItem, bIgnoreDefaults );
1429         }
1430     }
1431     InvalidateHashKey();    //i120575
1432 }
1433 
1434 // -----------------------------------------------------------------------
1435 
1436 void SfxItemSet::MergeValue( const SfxPoolItem& rAttr, sal_Bool bIgnoreDefaults )
1437 {
1438     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1439     SfxItemArray ppFnd = _aItems;
1440     const sal_uInt16* pPtr = _pWhichRanges;
1441     const sal_uInt16 nWhich = rAttr.Which();
1442     while( *pPtr )
1443     {
1444         // in diesem Bereich?
1445         if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1446         {
1447             ppFnd += nWhich - *pPtr;
1448             MergeItem_Impl( _pPool, _nCount, ppFnd, &rAttr, bIgnoreDefaults );
1449             break;
1450         }
1451         ppFnd += *(pPtr+1) - *pPtr + 1;
1452         pPtr += 2;
1453     }
1454     InvalidateHashKey();    //i120575
1455 }
1456 
1457 // -----------------------------------------------------------------------
1458 
1459 void SfxItemSet::InvalidateItem( sal_uInt16 nWhich )
1460 {
1461     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1462     SfxItemArray ppFnd = _aItems;
1463     const sal_uInt16* pPtr = _pWhichRanges;
1464     while( *pPtr )
1465     {
1466         if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1467         {
1468             // in diesem Bereich
1469             ppFnd += nWhich - *pPtr;
1470 
1471             if( *ppFnd )    // bei mir gesetzt
1472             {
1473                 if( (SfxPoolItem*)-1 != *ppFnd )        // noch nicht dontcare !
1474                 {
1475                     _pPool->Remove( **ppFnd );
1476                     *ppFnd = (SfxPoolItem*)-1;
1477                 }
1478             }
1479             else
1480             {
1481                 *ppFnd = (SfxPoolItem*)-1;
1482                 ++_nCount;
1483             }
1484             break;
1485         }
1486         ppFnd += *(pPtr+1) - *pPtr + 1;
1487         pPtr += 2;
1488     }
1489     InvalidateHashKey();    //i120575
1490 }
1491 
1492 // -----------------------------------------------------------------------
1493 
1494 sal_uInt16 SfxItemSet::GetWhichByPos( sal_uInt16 nPos ) const
1495 {
1496     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1497     sal_uInt16 n = 0;
1498     sal_uInt16* pPtr  = _pWhichRanges;
1499     while( *pPtr )
1500     {
1501         n = ( *(pPtr+1) - *pPtr ) + 1;
1502         if( nPos < n )
1503             return *(pPtr)+nPos;
1504         nPos = nPos - n;
1505         pPtr += 2;
1506     }
1507     DBG_ASSERT( sal_False, "Hier sind wir falsch" );
1508     return 0;
1509 }
1510 
1511 // -----------------------------------------------------------------------
1512 
1513 SvStream &SfxItemSet::Store
1514 (
1515     SvStream&   rStream,        // Zielstream f"ur normale Items
1516     FASTBOOL    bDirect         // sal_True: Items direkt speicher, sal_False: Surrogate
1517 )   const
1518 
1519 /*  [Beschreibung]
1520 
1521     Speichert die <SfxItemSet>-Instanz in den angegebenen Stream. Dabei
1522     werden die Surrorage der gesetzten <SfxPoolItem>s bzw. ('bDirect==sal_True')
1523     die gesetzten Items selbst wie folgt im Stream abgelegt:
1524 
1525             sal_uInt16              (Count) Anzahl der gesetzten Items
1526     Count*  _pPool->StoreItem()  siehe <SfxItemPool::StoreItem()const>
1527 
1528 
1529     [Querverweise]
1530 
1531     <SfxItemSet::Load(SvStream&,sal_Bool,const SfxItemPool*)>
1532 */
1533 
1534 {
1535     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1536     DBG_ASSERT( _pPool, "Kein Pool" );
1537     DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" );
1538 
1539     // Position des Counts merken, um ggf. zu korrigieren
1540     sal_uLong nCountPos = rStream.Tell();
1541     rStream << _nCount;
1542 
1543     // wenn nichts zu speichern ist, auch keinen ItemIter aufsetzen!
1544     if ( _nCount )
1545     {
1546         // mitz"ahlen wieviel Items tats"achlich gespeichert werden
1547         sal_uInt16 nWrittenCount = 0;  // Anzahl in 'rStream' gestreamter Items
1548 
1549         // "uber alle gesetzten Items iterieren
1550         SfxItemIter aIter(*this);
1551         for ( const SfxPoolItem *pItem = aIter.FirstItem();
1552               pItem;
1553               pItem = aIter.NextItem() )
1554         {
1555             // Item (ggf. als Surrogat) via Pool speichern lassen
1556             DBG_ASSERT( !IsInvalidItem(pItem), "can't store invalid items" );
1557             if ( !IsInvalidItem(pItem) &&
1558                  _pPool->StoreItem( rStream, *pItem, bDirect ) )
1559                 // Item wurde in 'rStream' gestreamt
1560                 ++nWrittenCount;
1561         };
1562 
1563         // weniger geschrieben als enthalten (z.B. altes Format)
1564         if ( nWrittenCount != _nCount )
1565         {
1566             // tats"achlichen Count im Stream ablegen
1567             sal_uLong nPos = rStream.Tell();
1568             rStream.Seek( nCountPos );
1569             rStream << nWrittenCount;
1570             rStream.Seek( nPos );
1571         }
1572     }
1573 
1574     return rStream;
1575 }
1576 
1577 // -----------------------------------------------------------------------
1578 
1579 SvStream &SfxItemSet::Load
1580 (
1581     SvStream&           rStream,    //  Stream, aus dem geladen werden soll
1582 
1583     FASTBOOL            bDirect,    /*  sal_True
1584                                         Items werden direkt aus dem Stream
1585                                         gelesen, nicht "uber Surrogate
1586 
1587                                         sal_False (default)
1588                                         Items werden "uber Surrogate gelesen */
1589 
1590     const SfxItemPool*  pRefPool    /*  Pool, der die Surrogate aufl"osen kann
1591                                         (z.B. zum Einf"ugen von Dokumenten) */
1592 )
1593 
1594 /*  [Beschreibung]
1595 
1596     Diese Methode l"adt ein <SfxItemSet> aus einem Stream. Falls der
1597     <SfxItemPool> ohne Ref-Counts geladen wurde, werden die geladenen
1598     Item-Referenzen in den Items hochgez"ahlt, ansonsten wird vorausgesetzt,
1599     da\s sie schon beim Laden des SfxItemPools ber"ucksichtigt waren.
1600 
1601     [Querverweise]
1602 
1603     <SfxItemSet::Store(Stream&,sal_Bool)const>
1604 */
1605 
1606 {
1607     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1608     DBG_ASSERT( _pPool, "Kein Pool");
1609     DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "Kein Master-Pool");
1610 
1611     // kein Ref-Pool => Surrogate mit Pool des ItemSets aufl"osen
1612     if ( !pRefPool )
1613         pRefPool = _pPool;
1614 
1615     // Anzahl der zu ladenden Items laden und dann ebensoviele Items
1616     sal_uInt16 nCount = 0;
1617     rStream >> nCount;
1618     for ( sal_uInt16 i = 0; i < nCount; ++i )
1619     {
1620         // Surrogat/Item laden und (Surrogat) aufl"osen lassen
1621         const SfxPoolItem *pItem =
1622                 _pPool->LoadItem( rStream, bDirect, pRefPool );
1623 
1624         // konnte ein Item geladen oder via Surrogat aufgel"ost werden?
1625         if ( pItem )
1626         {
1627             // Position f"ur Item-Pointer im Set suchen
1628             sal_uInt16 nWhich = pItem->Which();
1629             SfxItemArray ppFnd = _aItems;
1630             const sal_uInt16* pPtr = _pWhichRanges;
1631             while ( *pPtr )
1632             {
1633                 // in diesem Bereich?
1634                 if ( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1635                 {
1636                     // Item-Pointer im Set merken
1637                     ppFnd += nWhich - *pPtr;
1638                     SFX_ASSERT( !*ppFnd, nWhich, "Item doppelt eingetragen");
1639                     *ppFnd = pItem;
1640                     ++_nCount;
1641                     break;
1642                 }
1643 
1644                 // im Range-Array und Item-Array zum n"achsten Which-Range
1645                 ppFnd += *(pPtr+1) - *pPtr + 1;
1646                 pPtr += 2;
1647             }
1648         }
1649     }
1650 
1651 
1652     InvalidateHashKey();    //i120575
1653     return rStream;
1654 }
1655 
1656 // -----------------------------------------------------------------------
1657 
1658 int SfxItemSet::operator==(const SfxItemSet &rCmp) const
1659 {
1660     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1661     DBG_CHKOBJ(&rCmp, SfxItemSet, DbgCheckItemSet);
1662 
1663     // besonders schnell zu ermittelnde Werte muessen gleich sein
1664     if ( _pParent != rCmp._pParent ||
1665          _pPool != rCmp._pPool ||
1666          Count() != rCmp.Count() )
1667         return sal_False;
1668 
1669     // Ranges durchzaehlen lassen dauert laenger, muss aber auch gleich sein
1670     sal_uInt16 nCount1 = TotalCount();
1671     sal_uInt16 nCount2 = rCmp.TotalCount();
1672     if ( nCount1 != nCount2 )
1673         return sal_False;
1674 
1675     // sind die Ranges selbst ungleich?
1676     for ( sal_uInt16 nRange = 0; _pWhichRanges[nRange]; nRange += 2 )
1677         if ( _pWhichRanges[nRange] != rCmp._pWhichRanges[nRange] ||
1678              _pWhichRanges[nRange+1] != rCmp._pWhichRanges[nRange+1] )
1679         {
1680             // dann m"ussen wir die langsame Methode verwenden
1681             SfxWhichIter aIter( *this );
1682             for ( sal_uInt16 nWh = aIter.FirstWhich();
1683                   nWh;
1684                   nWh = aIter.NextWhich() )
1685             {
1686                 // wenn die Pointer von poolable Items ungleich sind,
1687                 // muessen die Items gleich sein
1688                 const SfxPoolItem *pItem1 = 0, *pItem2 = 0;
1689                 if ( GetItemState( nWh, sal_False, &pItem1 ) !=
1690                         rCmp.GetItemState( nWh, sal_False, &pItem2 ) ||
1691                      ( pItem1 != pItem2 &&
1692                         ( !pItem1 || IsInvalidItem(pItem1) ||
1693                           ( _pPool->IsItemFlag(*pItem1, SFX_ITEM_POOLABLE) &&
1694                             *pItem1 != *pItem2 ) ) ) )
1695                     return sal_False;
1696             }
1697 
1698             return sal_True;
1699         }
1700 
1701     // Pointer alle gleich?
1702     if ( 0 == memcmp( _aItems, rCmp._aItems, nCount1 * sizeof(_aItems[0]) ) )
1703         return sal_True;
1704 
1705     // dann werden wir wohl alle einzeln vergleichen muessen
1706     const SfxPoolItem **ppItem1 = (const SfxPoolItem**) _aItems;
1707     const SfxPoolItem **ppItem2 = (const SfxPoolItem**) rCmp._aItems;
1708     for ( sal_uInt16 nPos = 0; nPos < nCount1; ++nPos )
1709     {
1710         // wenn die Pointer von poolable Items ungleich sind,
1711         // muessen die Items gleich sein
1712         if ( *ppItem1 != *ppItem2 &&
1713              ( ( !*ppItem1 || !*ppItem2 ) ||
1714                ( IsInvalidItem(*ppItem1) || IsInvalidItem(*ppItem2) ) ||
1715                ( _pPool->IsItemFlag(**ppItem1, SFX_ITEM_POOLABLE) ) ||
1716                  **ppItem1 != **ppItem2 ) )
1717             return sal_False;
1718 
1719         ++ppItem1;
1720         ++ppItem2;
1721     }
1722 
1723     return sal_True;
1724 }
1725 
1726 // -----------------------------------------------------------------------
1727 
1728 SfxItemSet *SfxItemSet::Clone(sal_Bool bItems, SfxItemPool *pToPool ) const
1729 {
1730     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1731     if ( pToPool && pToPool != _pPool )
1732     {
1733         SfxItemSet *pNewSet = new SfxItemSet( *pToPool, _pWhichRanges );
1734         if ( bItems )
1735         {
1736             SfxWhichIter aIter(*pNewSet);
1737             sal_uInt16 nWhich = aIter.FirstWhich();
1738             while ( nWhich )
1739             {
1740                 const SfxPoolItem* pItem;
1741                 if ( SFX_ITEM_SET == GetItemState( nWhich, sal_False, &pItem ) )
1742                     pNewSet->Put( *pItem, pItem->Which() );
1743                 nWhich = aIter.NextWhich();
1744             }
1745         }
1746         return pNewSet;
1747     }
1748     else
1749         return bItems
1750                 ? new SfxItemSet(*this)
1751                 : new SfxItemSet(*_pPool, _pWhichRanges);
1752 }
1753 
1754 // -----------------------------------------------------------------------
1755 
1756 int SfxItemSet::PutDirect(const SfxPoolItem &rItem)
1757 {
1758     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
1759     SfxItemArray ppFnd = _aItems;
1760     const sal_uInt16* pPtr = _pWhichRanges;
1761     const sal_uInt16 nWhich = rItem.Which();
1762 #ifdef DBG_UTIL
1763     IsPoolDefaultItem(&rItem) || _pPool->GetSurrogate(&rItem);
1764         // nur Assertion in den callees provozieren
1765 #endif
1766     while( *pPtr )
1767     {
1768         if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1769         {
1770             // in diesem Bereich
1771             ppFnd += nWhich - *pPtr;
1772             const SfxPoolItem* pOld = *ppFnd;
1773             if( pOld )      // schon einer vorhanden
1774             {
1775                 if( rItem == **ppFnd )
1776                     return sal_False;       // schon vorhanden !
1777                 _pPool->Remove( *pOld );
1778             }
1779             else
1780                 ++_nCount;
1781 
1782             // den neuen eintragen
1783             if( IsPoolDefaultItem(&rItem) )
1784                 *ppFnd = &_pPool->Put( rItem );
1785             else
1786             {
1787                 *ppFnd = &rItem;
1788                 if( !IsStaticDefaultItem( &rItem ) )
1789                     rItem.AddRef();
1790             }
1791 
1792             InvalidateHashKey();    //i120575
1793             return sal_True;
1794         }
1795         ppFnd += *(pPtr+1) - *pPtr + 1;
1796         pPtr += 2;
1797     }
1798     return sal_False;
1799 }
1800 
1801 // -----------------------------------------------------------------------
1802 
1803 SfxAllItemSet::SfxAllItemSet( SfxItemPool &rPool )
1804 :   SfxItemSet(rPool, (const sal_uInt16*) 0),
1805     aDefault(0),
1806     nFree(nInitCount)
1807 {
1808     // initial keine Items
1809     _aItems = 0;
1810 
1811     // nInitCount Paare an USHORTs fuer Ranges allozieren
1812     _pWhichRanges = new sal_uInt16[ nInitCount + 1 ];
1813     memset( _pWhichRanges, 0, ( nInitCount + 1 ) * sizeof(sal_uInt16) );
1814 }
1815 
1816 
1817 // -----------------------------------------------------------------------
1818 
1819 
1820 SfxAllItemSet::SfxAllItemSet(const SfxItemSet &rCopy)
1821 :   SfxItemSet(rCopy),
1822     aDefault(0),
1823     nFree(0)
1824 {
1825 }
1826 
1827 // -----------------------------------------------------------------------
1828 
1829 
1830 
1831 SfxAllItemSet::SfxAllItemSet(const SfxAllItemSet &rCopy)
1832 :   SfxItemSet(rCopy),
1833     aDefault(0),
1834     nFree(0)
1835 /*  [Anmerkung]
1836 
1837     Der mu\s sein, da sonst vom Compiler einer generiert wird, er nimmt
1838     nicht den Ctor mit der 'const SfxItemSet&'!
1839 */
1840 {
1841 }
1842 
1843 // -----------------------------------------------------------------------
1844 
1845 static sal_uInt16 *AddRanges_Impl(
1846     sal_uInt16 *pUS, std::ptrdiff_t nOldSize, sal_uInt16 nIncr)
1847 
1848 /*  Diese interne Funktion erzeugt ein neues Which-Range-Array, welches von
1849     dem 'nOldSize'-USHORTs langen 'pUS' kopiert wird und hinten an Platz
1850     f"ur 'nIncr' neue USHORTs hat. Das terminierende sal_uInt16 mit der '0'
1851     wird weder in 'nOldSize' noch in 'nIncr' mitgez"ahlt, sondern implizit
1852     hinzugerechnet.
1853 
1854     Das neue Which-Range-Array wird als Returnwert zur"uckgegeben, das alte
1855     'pUS' freigegeben.
1856 */
1857 
1858 {
1859     // neues Which-Range-Array anlegen
1860     sal_uInt16 *pNew = new sal_uInt16[ nOldSize + nIncr + 1 ];
1861 
1862     // die alten Ranges "ubernehmen
1863     memcpy( pNew, pUS, nOldSize * sizeof(sal_uInt16) );
1864 
1865     // die neuen auf 0 initialisieren
1866     memset( pNew + nOldSize, 0, ( nIncr + 1 ) * sizeof(sal_uInt16) );
1867 
1868     // das alte Array freigeben
1869     delete[] pUS;
1870 
1871     return pNew;
1872 }
1873 
1874 // -----------------------------------------------------------------------
1875 
1876 static SfxItemArray AddItem_Impl(SfxItemArray pItems, sal_uInt16 nOldSize, sal_uInt16 nPos)
1877 
1878 /*  Diese interne Funktion erzeugt ein neues ItemArray, welches von 'pItems'
1879     kopiert wird, an der Position 'nPos' jedoch Platz f"ur einen neuen
1880     ItemPointer hat.
1881 
1882     Das neue ItemArray wird als Returnwert zur"uckgegeben, das alte 'pItems'
1883     wird freigegeben.
1884 */
1885 
1886 {
1887     // neues ItemArray anlegen
1888     SfxItemArray pNew = new const SfxPoolItem*[nOldSize+1];
1889 
1890     // war schon vorher eins da?
1891     if ( pItems )
1892     {
1893         // alte Items vor nPos kopieren
1894         if ( nPos )
1895             memcpy( (void*) pNew, pItems, nPos * sizeof(SfxPoolItem **) );
1896 
1897         // alte Items hinter nPos kopieren
1898         if ( nPos < nOldSize )
1899             memcpy( (void*) (pNew + nPos + 1), pItems + nPos,
1900                     (nOldSize-nPos) * sizeof(SfxPoolItem **) );
1901     }
1902 
1903     // neues Item initialisieren
1904     *(pNew + nPos) = 0;
1905 
1906     // altes ItemArray freigeben
1907     delete[] pItems;
1908 
1909     return pNew;
1910 }
1911 
1912 // -----------------------------------------------------------------------
1913 
1914 const SfxPoolItem* SfxAllItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich )
1915 
1916 // Putten mit automatischer Erweiterung der Whichs-Ids um die ID
1917 // des Items.
1918 
1919 {
1920     sal_uInt16 nPos = 0; // Position f"ur 'rItem' in '_aItems'
1921     const sal_uInt16 nItemCount = TotalCount();
1922 
1923     // erstmal sehen, ob es schon einen passenden Bereich gibt
1924     sal_uInt16 *pPtr = _pWhichRanges;
1925     while ( *pPtr )
1926     {
1927         // Which-Id liegt in diesem Bereich?
1928         if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
1929         {
1930             // Einfuegen
1931             nPos += nWhich - *pPtr;
1932             break;
1933         }
1934 
1935         // Position des Items in _aItems mitf"uhren
1936         nPos += *(pPtr+1) - *pPtr + 1;
1937 
1938         // zum n"achsten Bereich
1939         pPtr += 2;
1940     }
1941 
1942     // Which-Id noch nicht vorhanden?
1943     if ( !*pPtr )
1944     {
1945         // suchen, ob man sie irgendwo dranpacken kann
1946         pPtr = _pWhichRanges;
1947         nPos = 0;
1948         while ( *pPtr )
1949         {
1950             // Which-Id liegt exakt vor diesem Bereich?
1951             if ( (nWhich+1) == *pPtr )
1952             {
1953                 // Bereich waechst nach unten
1954                 (*pPtr)--;
1955 
1956                 // vor erstem Item dieses Bereichs Platz schaffen
1957                 _aItems = AddItem_Impl(_aItems, nItemCount, nPos);
1958                 break;
1959             }
1960 
1961             // Which-Id liegt exakt hinter diesem Bereich?
1962             else if ( (nWhich-1) == *(pPtr+1) )
1963             {
1964                 // Bereich waechst nach oben
1965                 (*(pPtr+1))++;
1966 
1967                 // hinter letztem Item dieses Bereichs Platz schaffen
1968                 nPos += nWhich - *pPtr;
1969                 _aItems = AddItem_Impl(_aItems, nItemCount, nPos);
1970                 break;
1971             }
1972 
1973             // Position des Items in _aItems mitf"uhren
1974             nPos += *(pPtr+1) - *pPtr + 1;
1975 
1976             // zum n"achsten Bereich
1977             pPtr += 2;
1978         }
1979     }
1980 
1981     // keinen erweiterbaren Bereich gefunden?
1982     if ( !*pPtr )
1983     {
1984         // kein Platz mehr in _pWhichRanges => erweitern
1985         std::ptrdiff_t nSize = pPtr - _pWhichRanges;
1986         if( !nFree )
1987         {
1988             _pWhichRanges = AddRanges_Impl(_pWhichRanges, nSize, nInitCount);
1989             nFree += nInitCount;
1990         }
1991 
1992         // neuen Which-Range anh"angen
1993         pPtr = _pWhichRanges + nSize;
1994         *pPtr++ = nWhich;
1995         *pPtr = nWhich;
1996         nFree -= 2;
1997 
1998         // Itemarray vergroessern
1999         nPos = nItemCount;
2000         _aItems = AddItem_Impl(_aItems, nItemCount, nPos);
2001     }
2002 
2003     // neues Item in Pool aufnehmen
2004     const SfxPoolItem& rNew = _pPool->Put( rItem, nWhich );
2005 
2006     // altes Item merken
2007     sal_Bool bIncrementCount = sal_False;
2008     const SfxPoolItem* pOld = *( _aItems + nPos );
2009     if ( reinterpret_cast< SfxPoolItem* >( -1 ) == pOld )   // state "dontcare"
2010         pOld = NULL;
2011     if ( !pOld )
2012     {
2013         bIncrementCount = sal_True;
2014         pOld = _pParent ?
2015                 &_pParent->Get( nWhich, sal_True )
2016                 : nWhich <= SFX_WHICH_MAX ? &_pPool->GetDefaultItem( nWhich ) : 0;
2017     }
2018 
2019     // neue Item in ItemSet aufnehmen
2020     *(_aItems + nPos) = &rNew;
2021 
2022     // Changed Notification versenden
2023     if ( pOld )
2024     {
2025         Changed( *pOld, rNew );
2026         if ( !IsDefaultItem(pOld) )
2027             _pPool->Remove( *pOld );
2028     }
2029 
2030     if ( bIncrementCount )
2031         ++_nCount;
2032 
2033     InvalidateHashKey();    //i120575
2034 
2035     return &rNew;
2036 }
2037 
2038 // -----------------------------------------------------------------------
2039 
2040 
2041 /*  Diese Methode wird forwarded, damit sie nicht durch die anderen
2042     Put-Methoden dieser SubClass gehided wird.
2043 */
2044 
2045 int SfxAllItemSet::Put( const SfxItemSet& rSet, sal_Bool bInvalidAsDefault )
2046 {
2047     //? pruefen, ob Which-Ranges erweitert werden
2048     return SfxItemSet::Put( rSet, bInvalidAsDefault );
2049 }
2050 
2051 // -----------------------------------------------------------------------
2052 // Item disablen, wenn durch ein VoidItem mit dem Which-Wert 0 ausgedrueckt
2053 
2054 void SfxItemSet::DisableItem(sal_uInt16 nWhich)
2055 {
2056     DBG_CHKTHIS(SfxItemSet, 0);
2057     Put( SfxVoidItem(0), nWhich );
2058 }
2059 
2060 // -----------------------------------------------------------------------
2061 
2062 #if 0
2063 sal_Bool SfxAllItemSet::Remove(sal_uInt16 nWhich)
2064 {
2065     DBG_CHKTHIS(SfxAllItemSet, 0);
2066     sal_uInt16 *pPtr = _pWhichRanges;
2067     sal_uInt16 nPos = 0;
2068     while( *pPtr )
2069     {
2070         if( *pPtr <= nWhich && nWhich <= *(pPtr+1) )
2071         {
2072             sal_uInt16 *pTmp = pPtr;
2073             sal_uInt16 nLeft = 0;
2074             sal_uInt16 nRest = 0;
2075             while(*++pTmp){
2076                 if( nLeft & 1 )
2077                     nRest = *pTmp - *(pTmp-1) + 1;
2078                 ++nLeft;
2079             }
2080 
2081             // in diesem Bereich
2082             nPos += nWhich - *pPtr;
2083             nRest -= nWhich - *pPtr;
2084             // 3,3
2085             if(*pPtr == nWhich && *(pPtr+1) == nWhich) {
2086                 memmove(pPtr, pPtr + 2, nLeft * sizeof(sal_uInt16));
2087                 nFree += 2;
2088             }
2089                 // Anfang
2090             else if(*pPtr == nWhich)
2091                 (*pPtr)++;
2092                 // Ende
2093             else if(*(pPtr+1) == nWhich)
2094                 (*(pPtr+1))--;
2095             else {
2096                 if(nPos + nRest + 2 > nFree) {
2097                     sal_uInt16 nOf = pPtr - _pWhichRanges;
2098                     _pWhichRanges = IncrSize(_pWhichRanges, nPos + nRest, nInitCount);
2099                     nFree += nInitCount;
2100                     pPtr = _pWhichRanges + nOf;
2101                 }
2102                 memmove(pPtr +2, pPtr, (nLeft+2) * sizeof(sal_uInt16));
2103                 *++pPtr  = nWhich-1;
2104                 *++pPtr = nWhich+1;
2105                 nFree -= 2;
2106             }
2107             SfxPoolItem* pItem = *( _aItems + nPos );
2108             if( pItem )
2109             {
2110                 if(_pPool)
2111                     _pPool->Remove(*pItem );
2112                 else
2113                     delete pItem;
2114                 --_nCount;
2115             }
2116             memmove(_aItems + nPos +1, _aItems + nPos,
2117                     sizeof(SfxPoolItem *) * (nRest - 1));
2118             break;          // dann beim Parent suchen
2119         }
2120         nPos += *(pPtr+1) - *pPtr + 1;
2121         pPtr += 2;
2122     }
2123     return *pPtr? sal_True: sal_False;
2124 }
2125 #endif
2126 
2127 // -----------------------------------------------------------------------
2128 
2129 SfxItemSet *SfxAllItemSet::Clone(sal_Bool bItems, SfxItemPool *pToPool ) const
2130 {
2131     DBG_CHKTHIS(SfxItemSet, DbgCheckItemSet);
2132     if ( pToPool && pToPool != _pPool )
2133     {
2134         SfxAllItemSet *pNewSet = new SfxAllItemSet( *pToPool );
2135         if ( bItems )
2136             pNewSet->Set( *this );
2137         return pNewSet;
2138     }
2139     else
2140         return bItems ? new SfxAllItemSet(*this) : new SfxAllItemSet(*_pPool);
2141 }
2142 
2143 //for i120575
2144 //align with the rtl_hash, return signed int result and input len limited to 2G.
2145 //can be replaced with other hash function in future for better performance, e.g. fnv hash.
2146 inline sal_Int32 myhash(void * buf, sal_Int32 buf_len)
2147 {
2148     return rtl_str_hashCode_WithLength( reinterpret_cast<const sal_Char *>(buf), buf_len);
2149 }
2150 
2151 inline void SfxItemSet::UpdateHashKey()
2152 {
2153     _aHashKey= myhash(_aItems,TotalCount()* sizeof(_aItems[0]));
2154 
2155     //always treat '0' as invalidate hash key, not using addtional bool data field for saving space.
2156     if (!IsValidateHashKey() )
2157     {
2158         _aHashKey = 1;
2159     }
2160 }
2161 
2162 sal_Bool SfxItemSet::QuickCompare( SfxItemSet & rCmp)
2163 {
2164     if ( _pParent != rCmp._pParent ||
2165          _pPool != rCmp._pPool ||
2166          Count() != rCmp.Count() )
2167         return sal_False;
2168 
2169     if ((0==Count())&&(0==rCmp.Count()))
2170         return sal_True;
2171 
2172     if (!IsValidateHashKey())
2173     {
2174         UpdateHashKey();
2175     }
2176     if (!rCmp.IsValidateHashKey())
2177     {
2178         rCmp.UpdateHashKey();
2179     }
2180 
2181     //improved performance here, in most cases, the hashkey is not equal.
2182     if (GetHashKey() != rCmp.GetHashKey())
2183         return sal_False;
2184 
2185     if ( 0 == memcmp( _aItems, rCmp._aItems,  TotalCount() * sizeof(_aItems[0]) ) )
2186         return sal_True;
2187     else
2188         return sal_False;
2189 }
2190 //end: i120575
2191