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