1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: itemset.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
36 #if STLPORT_VERSION>=321
43 #define _SVSTDARR_USHORTS
44 #define _SVSTDARR_ULONGS
46 #include <svtools/svstdarr.hxx>
47 #include <svtools/itemset.hxx>
48 #include <svtools/itempool.hxx>
49 #include <svtools/itemiter.hxx>
51 #include <svtools/nranges.hxx>
52 #include "whassert.hxx"
54 #include <tools/stream.hxx>
55 #include <tools/solar.h>
57 // STATIC DATA -----------------------------------------------------------
59 static const USHORT nInitCount
= 10; // einzelne USHORTs => 5 Paare ohne '0'
61 static ULONG nRangesCopyCount
= 0; // wie oft wurden Ranges kopiert
66 //========================================================================
68 #define NUMTYPE USHORT
69 #define SvNums SvUShorts
70 #define SfxNumRanges SfxUShortRanges
71 #include "nranges.cxx"
77 #define SvNums SvULongs
78 #define SfxNumRanges SfxULongRanges
79 #include "nranges.cxx"
84 //========================================================================
89 const sal_Char
*DbgCheckItemSet( const void* pVoid
)
91 const SfxItemSet
*pSet
= (const SfxItemSet
*) pVoid
;
92 SfxWhichIter
aIter( *pSet
);
93 USHORT nCount
= 0, n
= 0;
94 for ( USHORT nWh
= aIter
.FirstWhich(); nWh
; nWh
= aIter
.NextWhich(), ++n
)
96 const SfxPoolItem
*pItem
= pSet
->_aItems
[n
];
100 DBG_ASSERT( IsInvalidItem(pItem
) ||
101 pItem
->Which() == 0 || pItem
->Which() == nWh
,
102 "SfxItemSet: invalid which-id" );
103 DBG_ASSERT( IsInvalidItem(pItem
) || !pItem
->Which() ||
104 !SfxItemPool::IsWhich(pItem
->Which()) ||
105 pSet
->GetPool()->IsItemFlag(nWh
, SFX_ITEM_NOT_POOLABLE
) ||
106 SFX_ITEMS_NULL
!= pSet
->GetPool()->GetSurrogate(pItem
),
107 "SfxItemSet: item in set which is not in pool" );
111 DBG_ASSERT( pSet
->_nCount
== nCount
, "wrong SfxItemSet::nCount detected" );
117 // -----------------------------------------------------------------------
119 SfxItemSet::SfxItemSet
121 SfxItemPool
& rPool
, /* der Pool, in dem die SfxPoolItems,
122 welche in dieses SfxItemSet gelangen,
123 aufgenommen werden sollen */
126 #ifdef SFX_ITEMSET_NO_DEFAULT_CTOR
128 bTotalRanges
/* komplette Pool-Ranges uebernehmen,
129 muss auf TRUE gesetzt werden */
135 Konstruktor fuer ein SfxItemSet mit genau den Which-Bereichen, welche
136 dem angegebenen <SfxItemPool> bekannt sind.
141 F"ur Sfx-Programmierer ein derart konstruiertes SfxItemSet kann
142 keinerlei Items mit Slot-Ids als Which-Werte aufnehmen!
149 DBG_CTOR(SfxItemSet
, DbgCheckItemSet
);
150 DBG_ASSERTWARNING( _pPool
== _pPool
->GetMasterPool(), "kein Master-Pool" );
151 DBG( _pChildCountCtor
; *_pChildCount(this) = 0 );
152 // DBG_ASSERT( bTotalRanges || abs( &bTotalRanges - this ) < 1000,
153 // "please use suitable ranges" );
155 #ifdef SFX_ITEMSET_NO_DEFAULT_CTOR
161 _pWhichRanges
= (USHORT
*) _pPool
->GetFrozenIdRanges();
162 DBG_ASSERT( _pWhichRanges
, "don't create ItemSets with full range before FreezeIdRanges()" );
163 if ( !_pWhichRanges
)
164 _pPool
->FillItemIdRanges_Impl( _pWhichRanges
);
166 const USHORT nSize
= TotalCount();
167 _aItems
= new const SfxPoolItem
* [ nSize
];
168 memset( (void*) _aItems
, 0, nSize
* sizeof( SfxPoolItem
* ) );
171 // -----------------------------------------------------------------------
173 SfxItemSet::SfxItemSet( SfxItemPool
& rPool
, USHORT nWhich1
, USHORT nWhich2
):
178 DBG_CTOR(SfxItemSet
, DbgCheckItemSet
);
179 DBG_ASSERT( nWhich1
<= nWhich2
, "Ungueltiger Bereich" );
180 DBG_ASSERTWARNING( _pPool
== _pPool
->GetMasterPool(), "kein Master-Pool" );
181 DBG( _pChildCountCtor
; *_pChildCount(this) = 0 );
183 InitRanges_Impl(nWhich1
, nWhich2
);
186 // -----------------------------------------------------------------------
188 void SfxItemSet::InitRanges_Impl(USHORT nWh1
, USHORT nWh2
)
190 DBG_CHKTHIS(SfxItemSet
, 0);
191 _pWhichRanges
= new USHORT
[ 3 ];
192 *(_pWhichRanges
+0) = nWh1
;
193 *(_pWhichRanges
+1) = nWh2
;
194 *(_pWhichRanges
+2) = 0;
195 const USHORT nRg
= nWh2
- nWh1
+ 1;
196 _aItems
= new const SfxPoolItem
* [ nRg
];
197 memset( (void*) _aItems
, 0, nRg
* sizeof( SfxPoolItem
* ) );
200 // -----------------------------------------------------------------------
202 void SfxItemSet::InitRanges_Impl(va_list pArgs
, USHORT nWh1
, USHORT nWh2
, USHORT nNull
)
204 DBG_CHKTHIS(SfxItemSet
, 0);
206 USHORT nSize
= InitializeRanges_Impl( _pWhichRanges
, pArgs
, nWh1
, nWh2
, nNull
);
207 _aItems
= new const SfxPoolItem
* [ nSize
];
208 memset( (void*) _aItems
, 0, sizeof( SfxPoolItem
* ) * nSize
);
211 // -----------------------------------------------------------------------
213 SfxItemSet::SfxItemSet( SfxItemPool
& rPool
,
214 USHORT_ARG nWh1
, USHORT_ARG nWh2
, USHORT_ARG nNull
, ... ):
220 DBG_CTOR(SfxItemSet
, DbgCheckItemSet
);
221 DBG_ASSERT( nWh1
<= nWh2
, "Ungueltiger Bereich" );
222 DBG_ASSERTWARNING( _pPool
== _pPool
->GetMasterPool(), "kein Master-Pool" );
223 DBG( _pChildCountCtor
; *_pChildCount(this) = 0 );
227 sal::static_int_cast
< USHORT
>(nWh1
),
228 sal::static_int_cast
< USHORT
>(nWh2
));
231 va_start( pArgs
, nNull
);
233 pArgs
, sal::static_int_cast
< USHORT
>(nWh1
),
234 sal::static_int_cast
< USHORT
>(nWh2
),
235 sal::static_int_cast
< USHORT
>(nNull
));
239 // -----------------------------------------------------------------------
241 void SfxItemSet::InitRanges_Impl(const USHORT
*pWhichPairTable
)
243 DBG_CHKTHIS(SfxItemSet
, 0);
244 DBG_TRACE1("SfxItemSet: Ranges-CopyCount==%ul", ++nRangesCopyCount
);
247 const USHORT
* pPtr
= pWhichPairTable
;
250 nCnt
+= ( *(pPtr
+1) - *pPtr
) + 1;
254 _aItems
= new const SfxPoolItem
* [ nCnt
];
255 memset( (void*) _aItems
, 0, sizeof( SfxPoolItem
* ) * nCnt
);
257 std::ptrdiff_t cnt
= pPtr
- pWhichPairTable
+1;
258 _pWhichRanges
= new USHORT
[ cnt
];
259 memcpy( _pWhichRanges
, pWhichPairTable
, sizeof( USHORT
) * cnt
);
263 // -----------------------------------------------------------------------
265 SfxItemSet::SfxItemSet( SfxItemPool
& rPool
, const USHORT
* pWhichPairTable
):
271 DBG_CTOR(SfxItemSet
, 0);
272 DBG_ASSERTWARNING( _pPool
== _pPool
->GetMasterPool(), "kein Master-Pool" );
273 DBG( _pChildCountCtor
; *_pChildCount(this) = 0 );
275 // pWhichPairTable == 0 ist f"ur das SfxAllEnumItemSet
276 if ( pWhichPairTable
)
277 InitRanges_Impl(pWhichPairTable
);
280 // -----------------------------------------------------------------------
282 SfxItemSet::SfxItemSet( const SfxItemSet
& rASet
):
283 _pPool( rASet
._pPool
),
284 _pParent( rASet
._pParent
),
285 _nCount( rASet
._nCount
)
287 DBG_CTOR(SfxItemSet
, DbgCheckItemSet
);
288 DBG_ASSERTWARNING( _pPool
== _pPool
->GetMasterPool(), "kein Master-Pool" );
289 DBG( _pChildCountCtor
; *_pChildCount(this) = 0 );
290 DBG( ++*_pChildCount(_pParent
) );
292 // errechne die Anzahl von Attributen
294 USHORT
* pPtr
= rASet
._pWhichRanges
;
297 nCnt
+= ( *(pPtr
+1) - *pPtr
) + 1;
301 _aItems
= new const SfxPoolItem
* [ nCnt
];
303 // Attribute kopieren
304 SfxItemArray ppDst
= _aItems
, ppSrc
= rASet
._aItems
;
305 for( USHORT n
= nCnt
; n
; --n
, ++ppDst
, ++ppSrc
)
306 if ( 0 == *ppSrc
|| // aktueller Default?
307 IsInvalidItem(*ppSrc
) || // Dont Care?
308 IsStaticDefaultItem(*ppSrc
) ) // nicht zu poolende Defaults
309 // einfach Pointer kopieren
311 else if ( _pPool
->IsItemFlag( **ppSrc
, SFX_ITEM_POOLABLE
) )
313 // einfach Pointer kopieren und Ref-Count erh"ohen
315 ( (SfxPoolItem
*) (*ppDst
) )->AddRef();
317 else if ( !(*ppSrc
)->Which() )
318 *ppDst
= (*ppSrc
)->Clone();
320 // !IsPoolable() => via Pool zuweisen
321 *ppDst
= &_pPool
->Put( **ppSrc
);
323 // dann noch die Which Ranges kopieren
324 DBG_TRACE1("SfxItemSet: Ranges-CopyCount==%ul", ++nRangesCopyCount
);
325 std::ptrdiff_t cnt
= pPtr
- rASet
._pWhichRanges
+1;
326 _pWhichRanges
= new USHORT
[ cnt
];
327 memcpy( _pWhichRanges
, rASet
._pWhichRanges
, sizeof( USHORT
) * cnt
);
330 // -----------------------------------------------------------------------
332 SfxItemSet::~SfxItemSet()
334 DBG_DTOR(SfxItemSet
, DbgCheckItemSet
);
336 DBG( DBG_ASSERT( 0 == *_pChildCount(this), "SfxItemSet: deleting parent-itemset" ) )
339 USHORT nCount
= TotalCount();
342 SfxItemArray ppFnd
= _aItems
;
343 for( USHORT nCnt
= nCount
; nCnt
; --nCnt
, ++ppFnd
)
344 if( *ppFnd
&& !IsInvalidItem(*ppFnd
) )
346 if( !(*ppFnd
)->Which() )
347 delete (SfxPoolItem
*) *ppFnd
;
349 // noch mehrer Referenzen vorhanden, also nur den
350 // ReferenzCounter manipulieren
351 if ( 1 < (*ppFnd
)->GetRefCount() && !IsDefaultItem(*ppFnd
) )
352 (*ppFnd
)->ReleaseRef();
354 if ( !IsDefaultItem(*ppFnd
) )
355 // aus dem Pool loeschen
356 _pPool
->Remove( **ppFnd
);
361 // FIXME: could be delete[] (SfxPoolItem **)_aItems;
363 if ( _pWhichRanges
!= _pPool
->GetFrozenIdRanges() )
364 delete[] _pWhichRanges
;
365 _pWhichRanges
= 0; // for invariant-testing
367 DBG( --*_pChildCount(_pParent
) );
368 DBG( delete _pChildCount(this); _pChildCountDtor
);
371 // -----------------------------------------------------------------------
373 USHORT
SfxItemSet::ClearItem( USHORT nWhich
)
375 // einzelnes Item oder alle Items (nWhich==0) l"oschen
378 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
383 SfxItemArray ppFnd
= _aItems
;
387 const USHORT
* pPtr
= _pWhichRanges
;
390 // in diesem Bereich?
391 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
393 // "uberhaupt gesetzt?
394 ppFnd
+= nWhich
- *pPtr
;
397 // wegen der Assertions ins Sub-Calls mu\s das hier sein
399 const SfxPoolItem
*pItemToClear
= *ppFnd
;
402 if ( !IsInvalidItem(pItemToClear
) )
404 if ( nWhich
<= SFX_WHICH_MAX
)
406 const SfxPoolItem
& rNew
= _pParent
407 ? _pParent
->Get( nWhich
, TRUE
)
408 : _pPool
->GetDefaultItem( nWhich
);
410 Changed( *pItemToClear
, rNew
);
412 if ( pItemToClear
->Which() )
413 _pPool
->Remove( *pItemToClear
);
421 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
429 USHORT
* pPtr
= _pWhichRanges
;
432 for( nWhich
= *pPtr
; nWhich
<= *(pPtr
+1); ++nWhich
, ++ppFnd
)
435 // wegen der Assertions ins Sub-Calls mu\s das hier sein
437 const SfxPoolItem
*pItemToClear
= *ppFnd
;
440 if ( !IsInvalidItem(pItemToClear
) )
442 if ( nWhich
<= SFX_WHICH_MAX
)
444 const SfxPoolItem
& rNew
= _pParent
445 ? _pParent
->Get( nWhich
, TRUE
)
446 : _pPool
->GetDefaultItem( nWhich
);
448 Changed( *pItemToClear
, rNew
);
452 // Take care of disabled items, too.
453 if(!pItemToClear
->nWhich
)
455 // item is disabled, delete it
460 // remove item from pool
461 _pPool
->Remove( *pItemToClear
);
471 // -----------------------------------------------------------------------
473 void SfxItemSet::ClearInvalidItems( BOOL bHardDefault
)
475 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
476 USHORT
* pPtr
= _pWhichRanges
;
477 SfxItemArray ppFnd
= _aItems
;
481 for ( USHORT nWhich
= *pPtr
; nWhich
<= *(pPtr
+1); ++nWhich
, ++ppFnd
)
482 if ( IsInvalidItem(*ppFnd
) )
483 *ppFnd
= &_pPool
->Put( _pPool
->GetDefaultItem(nWhich
) );
489 for( USHORT nWhich
= *pPtr
; nWhich
<= *(pPtr
+1); ++nWhich
, ++ppFnd
)
490 if( IsInvalidItem(*ppFnd
) )
499 //------------------------------------------------------------------------
502 void SfxItemSet::InvalidateAllItems()
504 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
505 DBG_ASSERT( !_nCount
, "Es sind noch Items gesetzt" );
507 memset( (void*)_aItems
, -1, ( _nCount
= TotalCount() ) * sizeof( SfxPoolItem
*) );
510 // -----------------------------------------------------------------------
512 SfxItemState
SfxItemSet::GetItemState( USHORT nWhich
,
514 const SfxPoolItem
**ppItem
) const
516 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
517 // suche den Bereich in dem das Which steht:
518 const SfxItemSet
* pAktSet
= this;
519 SfxItemState eRet
= SFX_ITEM_UNKNOWN
;
522 SfxItemArray ppFnd
= pAktSet
->_aItems
;
523 const USHORT
* pPtr
= pAktSet
->_pWhichRanges
;
528 if ( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
531 ppFnd
+= nWhich
- *pPtr
;
534 eRet
= SFX_ITEM_DEFAULT
;
536 return eRet
; // nicht vorhanden
537 break; // JP: in den Parents weitersuchen !!!
540 if ( (SfxPoolItem
*) -1 == *ppFnd
)
541 // Unterschiedlich vorhanden
542 return SFX_ITEM_DONTCARE
;
544 if ( (*ppFnd
)->Type() == TYPE(SfxVoidItem
) )
545 return SFX_ITEM_DISABLED
;
550 const SfxPoolItem
*pItem
= *ppFnd
;
551 DBG_ASSERT( !pItem
->ISA(SfxSetItem
) ||
552 0 != &((const SfxSetItem
*)pItem
)->GetItemSet(),
553 "SetItem without ItemSet" );
559 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
563 } while( bSrchInParent
&& 0 != ( pAktSet
= pAktSet
->_pParent
));
567 // -----------------------------------------------------------------------
569 const SfxPoolItem
* SfxItemSet::Put( const SfxPoolItem
& rItem
, USHORT nWhich
)
571 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
572 DBG_ASSERT( !rItem
.ISA(SfxSetItem
) ||
573 0 != &((const SfxSetItem
&)rItem
).GetItemSet(),
574 "SetItem without ItemSet" );
576 return 0; //! nur wegen Outliner-Bug
577 SfxItemArray ppFnd
= _aItems
;
578 const USHORT
* pPtr
= _pWhichRanges
;
581 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
584 ppFnd
+= nWhich
- *pPtr
;
585 if( *ppFnd
) // schon einer vorhanden
587 // selbes Item bereits vorhanden?
588 if ( *ppFnd
== &rItem
)
591 // wird dontcare oder disabled mit was echtem ueberschrieben?
592 if ( rItem
.Which() && ( IsInvalidItem(*ppFnd
) || !(*ppFnd
)->Which() ) )
594 *ppFnd
= &_pPool
->Put( rItem
, nWhich
);
601 *ppFnd
= rItem
.Clone(_pPool
);
606 // selber Wert bereits vorhanden?
607 if ( rItem
== **ppFnd
)
610 // den neuen eintragen, den alten austragen
611 const SfxPoolItem
& rNew
= _pPool
->Put( rItem
, nWhich
);
612 const SfxPoolItem
* pOld
= *ppFnd
;
614 if(nWhich
<= SFX_WHICH_MAX
)
615 Changed( *pOld
, rNew
);
616 _pPool
->Remove( *pOld
);
623 *ppFnd
= rItem
.Clone(_pPool
);
625 const SfxPoolItem
& rNew
= _pPool
->Put( rItem
, nWhich
);
627 if (nWhich
<= SFX_WHICH_MAX
)
629 const SfxPoolItem
& rOld
= _pParent
630 ? _pParent
->Get( nWhich
, TRUE
)
631 : _pPool
->GetDefaultItem( nWhich
);
632 Changed( rOld
, rNew
);
636 SFX_ASSERT( !_pPool
->IsItemFlag(nWhich
, SFX_ITEM_POOLABLE
) ||
637 rItem
.ISA(SfxSetItem
) || **ppFnd
== rItem
,
638 nWhich
, "putted Item unequal" );
641 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
647 // -----------------------------------------------------------------------
649 int SfxItemSet::Put( const SfxItemSet
& rSet
, BOOL bInvalidAsDefault
)
651 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
655 SfxItemArray ppFnd
= rSet
._aItems
;
656 const USHORT
* pPtr
= rSet
._pWhichRanges
;
659 for ( USHORT nWhich
= *pPtr
; nWhich
<= *(pPtr
+1); ++nWhich
, ++ppFnd
)
662 if ( IsInvalidItem( *ppFnd
) )
664 if ( bInvalidAsDefault
)
665 bRet
|= 0 != ClearItem( nWhich
);
666 // gab GPF bei non.WIDs:
667 // bRet |= 0 != Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich );
669 InvalidateItem( nWhich
);
672 bRet
|= 0 != Put( **ppFnd
, nWhich
);
680 // -----------------------------------------------------------------------
682 void SfxItemSet::PutExtended
684 const SfxItemSet
& rSet
, // Quelle der zu puttenden Items
685 SfxItemState eDontCareAs
, // was mit DontCare-Items passiert
686 SfxItemState eDefaultAs
// was mit Default-Items passiert
691 Diese Methode "ubernimmt die Items aus 'rSet' in '*this'. Die
692 Which-Bereiche in '*this', die in 'rSet' nicht vorkommen bleiben unver-
693 "andert. Der Which-Bereich von '*this' bleibt auch unver"andert.
695 In 'rSet' gesetzte Items werden auch in '*this*' gesetzt. Default-
696 (0 Pointer) und Invalid- (-1 Pointer) Items werden je nach Parameter
697 ('eDontCareAs' und 'eDefaultAs' behandelt:
699 SFX_ITEM_SET: hart auf Default des Pools gesetzt
700 SFX_ITEM_DEFAULT: gel"oscht (0 Pointer)
701 SFX_ITEM_DONTCARE: invalidiert (-1 Pointer)
703 Alle anderen Werte f"ur 'eDontCareAs' und 'eDefaultAs' sind ung"ultig.
707 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
709 // don't "optimize" with "if( rSet.Count()" because of dont-care + defaults
710 SfxItemArray ppFnd
= rSet
._aItems
;
711 const USHORT
* pPtr
= rSet
._pWhichRanges
;
714 for ( USHORT nWhich
= *pPtr
; nWhich
<= *(pPtr
+1); ++nWhich
, ++ppFnd
)
717 if ( IsInvalidItem( *ppFnd
) )
719 // Item ist DontCare:
720 switch ( eDontCareAs
)
723 Put( rSet
.GetPool()->GetDefaultItem(nWhich
), nWhich
);
726 case SFX_ITEM_DEFAULT
:
730 case SFX_ITEM_DONTCARE
:
731 InvalidateItem( nWhich
);
735 DBG_ERROR( "invalid Argument for eDontCareAs" );
740 Put( **ppFnd
, nWhich
);
745 switch ( eDefaultAs
)
748 Put( rSet
.GetPool()->GetDefaultItem(nWhich
), nWhich
);
751 case SFX_ITEM_DEFAULT
:
755 case SFX_ITEM_DONTCARE
:
756 InvalidateItem( nWhich
);
760 DBG_ERROR( "invalid Argument for eDefaultAs" );
767 // -----------------------------------------------------------------------
769 void SfxItemSet::MergeRange( USHORT nFrom
, USHORT nTo
)
770 /** <H3>Description</H3>
772 Expands the ranges of settable items by 'nFrom' to 'nTo'. Keeps state of
773 items which are new ranges too.
777 // special case: exactly one USHORT which is already included?
778 if ( nFrom
== nTo
&& SFX_ITEM_AVAILABLE
<= GetItemState(nFrom
, FALSE
) )
782 SfxUShortRanges
aRanges( _pWhichRanges
);
783 aRanges
+= SfxUShortRanges( nFrom
, nTo
);
784 SetRanges( aRanges
);
787 // -----------------------------------------------------------------------
789 void SfxItemSet::SetRanges( const USHORT
*pNewRanges
)
791 /** <H3>Description</H3>
793 Modifies the ranges of settable items. Keeps state of items which
798 // identische Ranges?
799 if ( _pWhichRanges
== pNewRanges
)
801 const USHORT
* pOld
= _pWhichRanges
;
802 const USHORT
* pNew
= pNewRanges
;
803 while ( *pOld
== *pNew
)
805 if ( !*pOld
&& !*pNew
)
810 // create new item-array (by iterating through all new ranges)
811 ULONG nSize
= Capacity_Impl(pNewRanges
);
812 SfxItemArray aNewItems
= new const SfxPoolItem
* [ nSize
];
813 USHORT n
= 0, nNewCount
= 0;
815 memset( aNewItems
, 0, nSize
* sizeof( SfxPoolItem
* ) );
818 for ( const USHORT
*pRange
= pNewRanges
; *pRange
; pRange
+= 2 )
820 // iterate through all ids in the range
821 for ( USHORT nWID
= *pRange
; nWID
<= pRange
[1]; ++nWID
, ++n
)
823 // direct move of pointer (not via pool)
824 SfxItemState eState
= GetItemState( nWID
, FALSE
, aNewItems
+n
);
825 if ( SFX_ITEM_SET
== eState
)
827 // increment new item count and possibly increment ref count
829 aNewItems
[n
]->AddRef();
831 else if ( SFX_ITEM_DISABLED
== eState
)
833 // put "disabled" item
835 aNewItems
[n
] = new SfxVoidItem(0);
837 else if ( SFX_ITEM_DONTCARE
== eState
)
840 aNewItems
[n
] = (SfxPoolItem
*)-1;
850 USHORT nOldTotalCount
= TotalCount();
851 for ( USHORT nItem
= 0; nItem
< nOldTotalCount
; ++nItem
)
853 const SfxPoolItem
*pItem
= _aItems
[nItem
];
854 if ( pItem
&& !IsInvalidItem(pItem
) && pItem
->Which() )
855 _pPool
->Remove(*pItem
);
859 // replace old items-array and ranges
864 if( pNewRanges
== GetPool()->GetFrozenIdRanges() )
866 delete[] _pWhichRanges
;
867 _pWhichRanges
= ( USHORT
* ) pNewRanges
;
871 USHORT nCount
= Count_Impl(pNewRanges
) + 1;
872 if ( _pWhichRanges
!= _pPool
->GetFrozenIdRanges() )
873 delete[] _pWhichRanges
;
874 _pWhichRanges
= new USHORT
[ nCount
];
875 memcpy( _pWhichRanges
, pNewRanges
, sizeof( USHORT
) * nCount
);
879 // -----------------------------------------------------------------------
883 const SfxItemSet
& rSet
, /* das SfxItemSet, dessen SfxPoolItems
884 "ubernommen werden sollen */
886 BOOL bDeep
/* TRUE (default)
887 auch die SfxPoolItems aus den ggf. an
888 rSet vorhandenen Parents werden direkt
889 in das SfxItemSet "ubernommen
892 die SfxPoolItems aus den Parents von
893 rSet werden nicht ber"ucksichtigt */
898 Das SfxItemSet nimmt genau die SfxPoolItems an, die auch in
899 rSet gesetzt sind und im eigenen <Which-Bereich> liegen. Alle
900 anderen werden entfernt. Der SfxItemPool wird dabei beibehalten,
901 so da"s die "ubernommenen SfxPoolItems dabei ggf. vom SfxItemPool
902 von rSet in den SfxItemPool von *this "ubernommen werden.
904 SfxPoolItems, f"ur die in rSet IsInvalidItem() == TRUE gilt,
905 werden als Invalid-Item "ubernommen.
911 es wurden SfxPoolItems "ubernommen
914 es wurden keine SfxPoolItems "ubernommen,
915 da z.B. die Which-Bereiche der SfxItemSets
916 keine Schnittmenge haben oder in der
917 Schnittmenge keine SfxPoolItems in rSet
923 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
929 SfxWhichIter
aIter(*this);
930 USHORT nWhich
= aIter
.FirstWhich();
933 const SfxPoolItem
* pItem
;
934 if( SFX_ITEM_SET
== rSet
.GetItemState( nWhich
, TRUE
, &pItem
) )
935 bRet
|= 0 != Put( *pItem
, pItem
->Which() );
936 nWhich
= aIter
.NextWhich();
940 bRet
= Put(rSet
, FALSE
);
945 //------------------------------------------------------------------------
947 const SfxPoolItem
* SfxItemSet::GetItem
949 USHORT nId
, // Slot-Id oder Which-Id des Items
950 BOOL bSrchInParent
, // TRUE: auch in Parent-ItemSets suchen
951 TypeId aItemType
// != 0 => RTTI Pruefung mit Assertion
956 Mit dieser Methode wird der Zugriff auf einzelne Items im
957 SfxItemSet wesentlich vereinfacht. Insbesondere wird die Typpr"ufung
958 (per Assertion) durchgef"uhrt, wodurch die Applikations-Sourcen
959 wesentlich "ubersichtlicher werden. In der PRODUCT-Version wird
960 eine 0 zur"uckgegeben, wenn das gefundene Item nicht von der
961 angegebenen Klasse ist. Ist kein Item mit der Id 'nWhich' in dem ItemSet,
962 so wird 0 zurueckgegeben.
966 // ggf. in Which-Id umrechnen
967 USHORT nWhich
= GetPool()->GetWhich(nId
);
969 // ist das Item gesetzt oder bei bDeep==TRUE verf"ugbar?
970 const SfxPoolItem
*pItem
= 0;
971 SfxItemState eState
= GetItemState( nWhich
, bSrchInParent
, &pItem
);
972 if ( bSrchInParent
&& SFX_ITEM_AVAILABLE
== eState
&&
973 nWhich
<= SFX_WHICH_MAX
)
974 pItem
= &_pPool
->GetDefaultItem(nWhich
);
977 // stimmt der Typ "uberein?
978 if ( !aItemType
|| pItem
->IsA(aItemType
) )
981 // sonst Fehler melden
982 DBG_ERROR( "invalid argument type" );
985 // kein Item gefunden oder falschen Typ gefunden
990 //------------------------------------------------------------------------
993 const SfxPoolItem
& SfxItemSet::Get( USHORT nWhich
, BOOL bSrchInParent
) const
995 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
996 // suche den Bereich in dem das Which steht:
997 const SfxItemSet
* pAktSet
= this;
1000 if( pAktSet
->Count() )
1002 SfxItemArray ppFnd
= pAktSet
->_aItems
;
1003 const USHORT
* pPtr
= pAktSet
->_pWhichRanges
;
1006 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
1008 // in diesem Bereich
1009 ppFnd
+= nWhich
- *pPtr
;
1012 if( (SfxPoolItem
*)-1 == *ppFnd
) {
1013 //?MI: folgender code ist Doppelt (unten)
1014 SFX_ASSERT(_pPool
, nWhich
, "kein Pool, aber Status uneindeutig");
1015 //!((SfxAllItemSet *)this)->aDefault.SetWhich(nWhich);
1017 return _pPool
->GetDefaultItem( nWhich
);
1020 const SfxPoolItem
*pItem
= *ppFnd
;
1021 DBG_ASSERT( !pItem
->ISA(SfxSetItem
) ||
1022 0 != &((const SfxSetItem
*)pItem
)->GetItemSet(),
1023 "SetItem without ItemSet" );
1024 if ( pItem
->ISA(SfxVoidItem
) || !pItem
->Which() )
1025 DBG_WARNING( "SFX_WARNING: Getting disabled Item" );
1029 break; // dann beim Parent suchen
1031 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
1035 // bis zum Ende vom Such-Bereich: was nun ? zum Parent, oder Default ??
1036 // if( !*pPtr ) // bis zum Ende vom Such-Bereich ?
1038 } while( bSrchInParent
&& 0 != ( pAktSet
= pAktSet
->_pParent
));
1040 // dann das Default vom Pool holen und returnen
1041 SFX_ASSERT(_pPool
, nWhich
, "kein Pool, aber Status uneindeutig");
1042 const SfxPoolItem
*pItem
= &_pPool
->GetDefaultItem( nWhich
);
1043 DBG_ASSERT( !pItem
->ISA(SfxSetItem
) ||
1044 0 != &((const SfxSetItem
*)pItem
)->GetItemSet(),
1045 "SetItem without ItemSet" );
1049 // Notification-Callback
1050 // -----------------------------------------------------------------------
1052 void SfxItemSet::Changed( const SfxPoolItem
&, const SfxPoolItem
& )
1054 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
1057 // -----------------------------------------------------------------------
1059 USHORT
SfxItemSet::TotalCount() const
1061 DBG_CHKTHIS(SfxItemSet
, 0); // wird im Ctor benutzt bevor vollst. init.
1063 USHORT
* pPtr
= _pWhichRanges
;
1066 nRet
+= ( *(pPtr
+1) - *pPtr
) + 1;
1071 // -----------------------------------------------------------------------
1073 // behalte nur die Items, die auch in rSet enthalten sein (Wert egal)
1075 void SfxItemSet::Intersect( const SfxItemSet
& rSet
)
1077 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
1078 DBG_ASSERT(_pPool
, "nicht implementiert ohne Pool");
1079 if( !Count() ) // gar keine gesetzt ?
1082 // loesche alle Items, die im rSet nicht mehr vorhanden sind
1085 ClearItem(); // alles loeschen
1089 // teste mal, ob sich die Which-Bereiche unterscheiden.
1091 USHORT
* pWh1
= _pWhichRanges
;
1092 USHORT
* pWh2
= rSet
._pWhichRanges
;
1095 for( USHORT n
= 0; *pWh1
&& *pWh2
; ++pWh1
, ++pWh2
, ++n
)
1097 if( *pWh1
!= *pWh2
)
1103 nSize
+= ( *(pWh1
) - *(pWh1
-1) ) + 1;
1105 bEqual
= *pWh1
== *pWh2
; // auch die 0 abpruefen
1107 // sind die Bereiche identisch, ist es einfacher zu handhaben !
1110 SfxItemArray ppFnd1
= _aItems
;
1111 SfxItemArray ppFnd2
= rSet
._aItems
;
1113 for( ; nSize
; --nSize
, ++ppFnd1
, ++ppFnd2
)
1114 if( *ppFnd1
&& !*ppFnd2
)
1116 // aus dem Pool loeschen
1117 if( !IsInvalidItem( *ppFnd1
) )
1119 USHORT nWhich
= (*ppFnd1
)->Which();
1120 if(nWhich
<= SFX_WHICH_MAX
)
1122 const SfxPoolItem
& rNew
= _pParent
1123 ? _pParent
->Get( nWhich
, TRUE
)
1124 : _pPool
->GetDefaultItem( nWhich
);
1126 Changed( **ppFnd1
, rNew
);
1128 _pPool
->Remove( **ppFnd1
);
1136 SfxItemIter
aIter( *this );
1137 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
1140 USHORT nWhich
= IsInvalidItem( pItem
)
1141 ? GetWhichByPos( aIter
.GetCurPos() )
1143 if( 0 == rSet
.GetItemState( nWhich
, FALSE
) )
1144 ClearItem( nWhich
); // loeschen
1145 if( aIter
.IsAtEnd() )
1147 pItem
= aIter
.NextItem();
1152 // -----------------------------------------------------------------------
1154 void SfxItemSet::Differentiate( const SfxItemSet
& rSet
)
1156 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
1157 if( !Count() || !rSet
.Count() ) // gar keine gesetzt ?
1160 // teste mal, ob sich die Which-Bereiche unterscheiden.
1162 USHORT
* pWh1
= _pWhichRanges
;
1163 USHORT
* pWh2
= rSet
._pWhichRanges
;
1166 for( USHORT n
= 0; *pWh1
&& *pWh2
; ++pWh1
, ++pWh2
, ++n
)
1168 if( *pWh1
!= *pWh2
)
1174 nSize
+= ( *(pWh1
) - *(pWh1
-1) ) + 1;
1176 bEqual
= *pWh1
== *pWh2
; // auch die 0 abpruefen
1178 // sind die Bereiche identisch, ist es einfacher zu handhaben !
1181 SfxItemArray ppFnd1
= _aItems
;
1182 SfxItemArray ppFnd2
= rSet
._aItems
;
1184 for( ; nSize
; --nSize
, ++ppFnd1
, ++ppFnd2
)
1185 if( *ppFnd1
&& *ppFnd2
)
1187 // aus dem Pool loeschen
1188 if( !IsInvalidItem( *ppFnd1
) )
1190 USHORT nWhich
= (*ppFnd1
)->Which();
1191 if(nWhich
<= SFX_WHICH_MAX
)
1193 const SfxPoolItem
& rNew
= _pParent
1194 ? _pParent
->Get( nWhich
, TRUE
)
1195 : _pPool
->GetDefaultItem( nWhich
);
1197 Changed( **ppFnd1
, rNew
);
1199 _pPool
->Remove( **ppFnd1
);
1207 SfxItemIter
aIter( *this );
1208 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
1211 USHORT nWhich
= IsInvalidItem( pItem
)
1212 ? GetWhichByPos( aIter
.GetCurPos() )
1214 if( SFX_ITEM_SET
== rSet
.GetItemState( nWhich
, FALSE
) )
1215 ClearItem( nWhich
); // loeschen
1216 if( aIter
.IsAtEnd() )
1218 pItem
= aIter
.NextItem();
1224 // -----------------------------------------------------------------------
1225 /* Entscheidungstabelle fuer MergeValue[s]
1228 1. Ist der Which-Wert im 1.Set "unknown", dann folgt niemals eine Aktion.
1229 2. Ist der Which-Wert im 2.Set "unknown", dann gilt er als "default".
1230 3. Es gelten fuer Vergleiche die Werte der "default"-Items.
1232 1.-Item 2.-Item Values bIgnoreDefs Remove Assign Add
1234 set set == FALSE - - -
1235 default set == FALSE - - -
1236 dontcare set == FALSE - - -
1237 unknown set == FALSE - - -
1238 set default == FALSE - - -
1239 default default == FALSE - - -
1240 dontcare default == FALSE - - -
1241 unknown default == FALSE - - -
1242 set dontcare == FALSE 1.-Item -1 -
1243 default dontcare == FALSE - -1 -
1244 dontcare dontcare == FALSE - - -
1245 unknown dontcare == FALSE - - -
1246 set unknown == FALSE 1.-Item -1 -
1247 default unknown == FALSE - - -
1248 dontcare unknown == FALSE - - -
1249 unknown unknown == FALSE - - -
1251 set set != FALSE 1.-Item -1 -
1252 default set != FALSE - -1 -
1253 dontcare set != FALSE - - -
1254 unknown set != FALSE - - -
1255 set default != FALSE 1.-Item -1 -
1256 default default != FALSE - - -
1257 dontcare default != FALSE - - -
1258 unknown default != FALSE - - -
1259 set dontcare != FALSE 1.-Item -1 -
1260 default dontcare != FALSE - -1 -
1261 dontcare dontcare != FALSE - - -
1262 unknown dontcare != FALSE - - -
1263 set unknown != FALSE 1.-Item -1 -
1264 default unknown != FALSE - - -
1265 dontcare unknown != FALSE - - -
1266 unknown unknown != FALSE - - -
1268 set set == TRUE - - -
1269 default set == TRUE - 2.-Item 2.-Item
1270 dontcare set == TRUE - - -
1271 unknown set == TRUE - - -
1272 set default == TRUE - - -
1273 default default == TRUE - - -
1274 dontcare default == TRUE - - -
1275 unknown default == TRUE - - -
1276 set dontcare == TRUE - - -
1277 default dontcare == TRUE - -1 -
1278 dontcare dontcare == TRUE - - -
1279 unknown dontcare == TRUE - - -
1280 set unknown == TRUE - - -
1281 default unknown == TRUE - - -
1282 dontcare unknown == TRUE - - -
1283 unknown unknown == TRUE - - -
1285 set set != TRUE 1.-Item -1 -
1286 default set != TRUE - 2.-Item 2.-Item
1287 dontcare set != TRUE - - -
1288 unknown set != TRUE - - -
1289 set default != TRUE - - -
1290 default default != TRUE - - -
1291 dontcare default != TRUE - - -
1292 unknown default != TRUE - - -
1293 set dontcare != TRUE 1.-Item -1 -
1294 default dontcare != TRUE - -1 -
1295 dontcare dontcare != TRUE - - -
1296 unknown dontcare != TRUE - - -
1297 set unknown != TRUE - - -
1298 default unknown != TRUE - - -
1299 dontcare unknown != TRUE - - -
1300 unknown unknown != TRUE - - -
1304 static void MergeItem_Impl( SfxItemPool
*_pPool
, USHORT
&rCount
,
1305 const SfxPoolItem
**ppFnd1
, const SfxPoolItem
*pFnd2
,
1306 BOOL bIgnoreDefaults
)
1308 DBG_ASSERT( ppFnd1
!= 0, "Merging to 0-Item" );
1310 // 1. Item ist default?
1313 if ( IsInvalidItem(pFnd2
) )
1314 // Entscheidungstabelle: default, dontcare, egal, egal
1315 *ppFnd1
= (SfxPoolItem
*) -1;
1317 else if ( pFnd2
&& !bIgnoreDefaults
&&
1318 _pPool
->GetDefaultItem(pFnd2
->Which()) != *pFnd2
)
1319 // Entscheidungstabelle: default, set, !=, FALSE
1320 *ppFnd1
= (SfxPoolItem
*) -1;
1322 else if ( pFnd2
&& bIgnoreDefaults
)
1323 // Entscheidungstabelle: default, set, egal, TRUE
1324 *ppFnd1
= &_pPool
->Put( *pFnd2
);
1330 // 1. Item ist gesetzt?
1331 else if ( !IsInvalidItem(*ppFnd1
) )
1335 // 2. Item ist default
1336 if ( !bIgnoreDefaults
&&
1337 **ppFnd1
!= _pPool
->GetDefaultItem((*ppFnd1
)->Which()) )
1339 // Entscheidungstabelle: set, default, !=, FALSE
1340 _pPool
->Remove( **ppFnd1
);
1341 *ppFnd1
= (SfxPoolItem
*) -1;
1344 else if ( IsInvalidItem(pFnd2
) )
1346 // 2. Item ist dontcare
1347 if ( !bIgnoreDefaults
||
1348 **ppFnd1
!= _pPool
->GetDefaultItem( (*ppFnd1
)->Which()) )
1350 // Entscheidungstabelle: set, dontcare, egal, FALSE
1351 // oder: set, dontcare, !=, TRUE
1352 _pPool
->Remove( **ppFnd1
);
1353 *ppFnd1
= (SfxPoolItem
*) -1;
1358 // 2. Item ist gesetzt
1359 if ( **ppFnd1
!= *pFnd2
)
1361 // Entscheidungstabelle: set, set, !=, egal
1362 _pPool
->Remove( **ppFnd1
);
1363 *ppFnd1
= (SfxPoolItem
*) -1;
1369 // -----------------------------------------------------------------------
1371 void SfxItemSet::MergeValues( const SfxItemSet
& rSet
, BOOL bIgnoreDefaults
)
1373 // Achtung!!! Bei Aenderungen/Bugfixes immer obenstehende Tabelle pflegen!
1374 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
1375 DBG_ASSERT( GetPool() == rSet
.GetPool(), "MergeValues mit verschiedenen Pools" );
1377 // teste mal, ob sich die Which-Bereiche unterscheiden.
1379 USHORT
* pWh1
= _pWhichRanges
;
1380 USHORT
* pWh2
= rSet
._pWhichRanges
;
1383 for( USHORT n
= 0; *pWh1
&& *pWh2
; ++pWh1
, ++pWh2
, ++n
)
1385 if( *pWh1
!= *pWh2
)
1391 nSize
+= ( *(pWh1
) - *(pWh1
-1) ) + 1;
1393 bEqual
= *pWh1
== *pWh2
; // auch die 0 abpruefen
1395 // sind die Bereiche identisch, ist es effizieter zu handhaben !
1398 SfxItemArray ppFnd1
= _aItems
;
1399 SfxItemArray ppFnd2
= rSet
._aItems
;
1401 for( ; nSize
; --nSize
, ++ppFnd1
, ++ppFnd2
)
1402 MergeItem_Impl( _pPool
, _nCount
, ppFnd1
, *ppFnd2
, bIgnoreDefaults
);
1406 SfxWhichIter
aIter( rSet
);
1407 register USHORT nWhich
;
1408 while( 0 != ( nWhich
= aIter
.NextWhich() ) )
1410 const SfxPoolItem
* pItem
= 0;
1411 rSet
.GetItemState( nWhich
, TRUE
, &pItem
);
1414 // nicht gesetzt, also default
1415 if ( !bIgnoreDefaults
)
1416 MergeValue( rSet
.GetPool()->GetDefaultItem( nWhich
), bIgnoreDefaults
);
1418 else if( IsInvalidItem( pItem
) )
1420 InvalidateItem( nWhich
);
1422 MergeValue( *pItem
, bIgnoreDefaults
);
1427 // -----------------------------------------------------------------------
1429 void SfxItemSet::MergeValue( const SfxPoolItem
& rAttr
, BOOL bIgnoreDefaults
)
1431 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
1432 SfxItemArray ppFnd
= _aItems
;
1433 const USHORT
* pPtr
= _pWhichRanges
;
1434 const USHORT nWhich
= rAttr
.Which();
1437 // in diesem Bereich?
1438 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
1440 ppFnd
+= nWhich
- *pPtr
;
1441 MergeItem_Impl( _pPool
, _nCount
, ppFnd
, &rAttr
, bIgnoreDefaults
);
1444 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
1449 // -----------------------------------------------------------------------
1451 void SfxItemSet::InvalidateItem( USHORT nWhich
)
1453 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
1454 SfxItemArray ppFnd
= _aItems
;
1455 const USHORT
* pPtr
= _pWhichRanges
;
1458 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
1460 // in diesem Bereich
1461 ppFnd
+= nWhich
- *pPtr
;
1463 if( *ppFnd
) // bei mir gesetzt
1465 if( (SfxPoolItem
*)-1 != *ppFnd
) // noch nicht dontcare !
1467 _pPool
->Remove( **ppFnd
);
1468 *ppFnd
= (SfxPoolItem
*)-1;
1473 *ppFnd
= (SfxPoolItem
*)-1;
1478 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
1483 // -----------------------------------------------------------------------
1485 USHORT
SfxItemSet::GetWhichByPos( USHORT nPos
) const
1487 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
1489 USHORT
* pPtr
= _pWhichRanges
;
1492 n
= ( *(pPtr
+1) - *pPtr
) + 1;
1494 return *(pPtr
)+nPos
;
1498 DBG_ASSERT( FALSE
, "Hier sind wir falsch" );
1502 // -----------------------------------------------------------------------
1504 SvStream
&SfxItemSet::Store
1506 SvStream
& rStream
, // Zielstream f"ur normale Items
1507 FASTBOOL bDirect
// TRUE: Items direkt speicher, FALSE: Surrogate
1512 Speichert die <SfxItemSet>-Instanz in den angegebenen Stream. Dabei
1513 werden die Surrorage der gesetzten <SfxPoolItem>s bzw. ('bDirect==TRUE')
1514 die gesetzten Items selbst wie folgt im Stream abgelegt:
1516 USHORT (Count) Anzahl der gesetzten Items
1517 Count* _pPool->StoreItem() siehe <SfxItemPool::StoreItem()const>
1522 <SfxItemSet::Load(SvStream&,BOOL,const SfxItemPool*)>
1526 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
1527 DBG_ASSERT( _pPool
, "Kein Pool" );
1528 DBG_ASSERTWARNING( _pPool
== _pPool
->GetMasterPool(), "kein Master-Pool" );
1530 // Position des Counts merken, um ggf. zu korrigieren
1531 ULONG nCountPos
= rStream
.Tell();
1534 // wenn nichts zu speichern ist, auch keinen ItemIter aufsetzen!
1537 // mitz"ahlen wieviel Items tats"achlich gespeichert werden
1538 USHORT nWrittenCount
= 0; // Anzahl in 'rStream' gestreamter Items
1540 // "uber alle gesetzten Items iterieren
1541 SfxItemIter
aIter(*this);
1542 for ( const SfxPoolItem
*pItem
= aIter
.FirstItem();
1544 pItem
= aIter
.NextItem() )
1546 // Item (ggf. als Surrogat) via Pool speichern lassen
1547 DBG_ASSERT( !IsInvalidItem(pItem
), "can't store invalid items" );
1548 if ( !IsInvalidItem(pItem
) &&
1549 _pPool
->StoreItem( rStream
, *pItem
, bDirect
) )
1550 // Item wurde in 'rStream' gestreamt
1554 // weniger geschrieben als enthalten (z.B. altes Format)
1555 if ( nWrittenCount
!= _nCount
)
1557 // tats"achlichen Count im Stream ablegen
1558 ULONG nPos
= rStream
.Tell();
1559 rStream
.Seek( nCountPos
);
1560 rStream
<< nWrittenCount
;
1561 rStream
.Seek( nPos
);
1568 // -----------------------------------------------------------------------
1570 SvStream
&SfxItemSet::Load
1572 SvStream
& rStream
, // Stream, aus dem geladen werden soll
1574 FASTBOOL bDirect
, /* TRUE
1575 Items werden direkt aus dem Stream
1576 gelesen, nicht "uber Surrogate
1579 Items werden "uber Surrogate gelesen */
1581 const SfxItemPool
* pRefPool
/* Pool, der die Surrogate aufl"osen kann
1582 (z.B. zum Einf"ugen von Dokumenten) */
1587 Diese Methode l"adt ein <SfxItemSet> aus einem Stream. Falls der
1588 <SfxItemPool> ohne Ref-Counts geladen wurde, werden die geladenen
1589 Item-Referenzen in den Items hochgez"ahlt, ansonsten wird vorausgesetzt,
1590 da\s sie schon beim Laden des SfxItemPools ber"ucksichtigt waren.
1594 <SfxItemSet::Store(Stream&,BOOL)const>
1598 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
1599 DBG_ASSERT( _pPool
, "Kein Pool");
1600 DBG_ASSERTWARNING( _pPool
== _pPool
->GetMasterPool(), "Kein Master-Pool");
1602 // kein Ref-Pool => Surrogate mit Pool des ItemSets aufl"osen
1606 // Anzahl der zu ladenden Items laden und dann ebensoviele Items
1609 for ( USHORT i
= 0; i
< nCount
; ++i
)
1611 // Surrogat/Item laden und (Surrogat) aufl"osen lassen
1612 const SfxPoolItem
*pItem
=
1613 _pPool
->LoadItem( rStream
, bDirect
, pRefPool
);
1615 // konnte ein Item geladen oder via Surrogat aufgel"ost werden?
1618 // Position f"ur Item-Pointer im Set suchen
1619 USHORT nWhich
= pItem
->Which();
1620 SfxItemArray ppFnd
= _aItems
;
1621 const USHORT
* pPtr
= _pWhichRanges
;
1624 // in diesem Bereich?
1625 if ( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
1627 // Item-Pointer im Set merken
1628 ppFnd
+= nWhich
- *pPtr
;
1629 SFX_ASSERT( !*ppFnd
, nWhich
, "Item doppelt eingetragen");
1635 // im Range-Array und Item-Array zum n"achsten Which-Range
1636 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
1645 // -----------------------------------------------------------------------
1647 int SfxItemSet::operator==(const SfxItemSet
&rCmp
) const
1649 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
1650 DBG_CHKOBJ(&rCmp
, SfxItemSet
, DbgCheckItemSet
);
1652 // besonders schnell zu ermittelnde Werte muessen gleich sein
1653 if ( _pParent
!= rCmp
._pParent
||
1654 _pPool
!= rCmp
._pPool
||
1655 Count() != rCmp
.Count() )
1658 // Ranges durchzaehlen lassen dauert laenger, muss aber auch gleich sein
1659 USHORT nCount1
= TotalCount();
1660 USHORT nCount2
= rCmp
.TotalCount();
1661 if ( nCount1
!= nCount2
)
1664 // sind die Ranges selbst ungleich?
1665 for ( USHORT nRange
= 0; _pWhichRanges
[nRange
]; nRange
+= 2 )
1666 if ( _pWhichRanges
[nRange
] != rCmp
._pWhichRanges
[nRange
] ||
1667 _pWhichRanges
[nRange
+1] != rCmp
._pWhichRanges
[nRange
+1] )
1669 // dann m"ussen wir die langsame Methode verwenden
1670 SfxWhichIter
aIter( *this );
1671 for ( USHORT nWh
= aIter
.FirstWhich();
1673 nWh
= aIter
.NextWhich() )
1675 // wenn die Pointer von poolable Items ungleich sind,
1676 // muessen die Items gleich sein
1677 const SfxPoolItem
*pItem1
= 0, *pItem2
= 0;
1678 if ( GetItemState( nWh
, FALSE
, &pItem1
) !=
1679 rCmp
.GetItemState( nWh
, FALSE
, &pItem2
) ||
1680 ( pItem1
!= pItem2
&&
1681 ( !pItem1
|| IsInvalidItem(pItem1
) ||
1682 ( _pPool
->IsItemFlag(*pItem1
, SFX_ITEM_POOLABLE
) &&
1683 *pItem1
!= *pItem2
) ) ) )
1690 // Pointer alle gleich?
1691 if ( 0 == memcmp( _aItems
, rCmp
._aItems
, nCount1
* sizeof(_aItems
[0]) ) )
1694 // dann werden wir wohl alle einzeln vergleichen muessen
1695 const SfxPoolItem
**ppItem1
= (const SfxPoolItem
**) _aItems
;
1696 const SfxPoolItem
**ppItem2
= (const SfxPoolItem
**) rCmp
._aItems
;
1697 for ( USHORT nPos
= 0; nPos
< nCount1
; ++nPos
)
1699 // wenn die Pointer von poolable Items ungleich sind,
1700 // muessen die Items gleich sein
1701 if ( *ppItem1
!= *ppItem2
&&
1702 ( ( !*ppItem1
|| !*ppItem2
) ||
1703 ( IsInvalidItem(*ppItem1
) || IsInvalidItem(*ppItem2
) ) ||
1704 ( _pPool
->IsItemFlag(**ppItem1
, SFX_ITEM_POOLABLE
) ) ||
1705 **ppItem1
!= **ppItem2
) )
1715 // -----------------------------------------------------------------------
1717 SfxItemSet
*SfxItemSet::Clone(BOOL bItems
, SfxItemPool
*pToPool
) const
1719 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
1720 if ( pToPool
&& pToPool
!= _pPool
)
1722 SfxItemSet
*pNewSet
= new SfxItemSet( *pToPool
, _pWhichRanges
);
1725 SfxWhichIter
aIter(*pNewSet
);
1726 USHORT nWhich
= aIter
.FirstWhich();
1729 const SfxPoolItem
* pItem
;
1730 if ( SFX_ITEM_SET
== GetItemState( nWhich
, FALSE
, &pItem
) )
1731 pNewSet
->Put( *pItem
, pItem
->Which() );
1732 nWhich
= aIter
.NextWhich();
1739 ? new SfxItemSet(*this)
1740 : new SfxItemSet(*_pPool
, _pWhichRanges
);
1743 // -----------------------------------------------------------------------
1745 int SfxItemSet::PutDirect(const SfxPoolItem
&rItem
)
1747 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
1748 SfxItemArray ppFnd
= _aItems
;
1749 const USHORT
* pPtr
= _pWhichRanges
;
1750 const USHORT nWhich
= rItem
.Which();
1752 IsPoolDefaultItem(&rItem
) || _pPool
->GetSurrogate(&rItem
);
1753 // nur Assertion in den callees provozieren
1757 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
1759 // in diesem Bereich
1760 ppFnd
+= nWhich
- *pPtr
;
1761 const SfxPoolItem
* pOld
= *ppFnd
;
1762 if( pOld
) // schon einer vorhanden
1764 if( rItem
== **ppFnd
)
1765 return FALSE
; // schon vorhanden !
1766 _pPool
->Remove( *pOld
);
1771 // den neuen eintragen
1772 if( IsPoolDefaultItem(&rItem
) )
1773 *ppFnd
= &_pPool
->Put( rItem
);
1777 if( !IsStaticDefaultItem( &rItem
) )
1783 ppFnd
+= *(pPtr
+1) - *pPtr
+ 1;
1789 // -----------------------------------------------------------------------
1791 SfxAllItemSet::SfxAllItemSet( SfxItemPool
&rPool
)
1792 : SfxItemSet(rPool
, (const USHORT
*) 0),
1796 // initial keine Items
1799 // nInitCount Paare an USHORTs fuer Ranges allozieren
1800 _pWhichRanges
= new USHORT
[ nInitCount
+ 1 ];
1801 memset( _pWhichRanges
, 0, ( nInitCount
+ 1 ) * sizeof(USHORT
) );
1805 // -----------------------------------------------------------------------
1808 SfxAllItemSet::SfxAllItemSet(const SfxItemSet
&rCopy
)
1809 : SfxItemSet(rCopy
),
1815 // -----------------------------------------------------------------------
1819 SfxAllItemSet::SfxAllItemSet(const SfxAllItemSet
&rCopy
)
1820 : SfxItemSet(rCopy
),
1825 Der mu\s sein, da sonst vom Compiler einer generiert wird, er nimmt
1826 nicht den Ctor mit der 'const SfxItemSet&'!
1831 // -----------------------------------------------------------------------
1833 static USHORT
*AddRanges_Impl(
1834 USHORT
*pUS
, std::ptrdiff_t nOldSize
, USHORT nIncr
)
1836 /* Diese interne Funktion erzeugt ein neues Which-Range-Array, welches von
1837 dem 'nOldSize'-USHORTs langen 'pUS' kopiert wird und hinten an Platz
1838 f"ur 'nIncr' neue USHORTs hat. Das terminierende USHORT mit der '0'
1839 wird weder in 'nOldSize' noch in 'nIncr' mitgez"ahlt, sondern implizit
1842 Das neue Which-Range-Array wird als Returnwert zur"uckgegeben, das alte
1847 // neues Which-Range-Array anlegen
1848 USHORT
*pNew
= new USHORT
[ nOldSize
+ nIncr
+ 1 ];
1850 // die alten Ranges "ubernehmen
1851 memcpy( pNew
, pUS
, nOldSize
* sizeof(USHORT
) );
1853 // die neuen auf 0 initialisieren
1854 memset( pNew
+ nOldSize
, 0, ( nIncr
+ 1 ) * sizeof(USHORT
) );
1856 // das alte Array freigeben
1862 // -----------------------------------------------------------------------
1864 static SfxItemArray
AddItem_Impl(SfxItemArray pItems
, USHORT nOldSize
, USHORT nPos
)
1866 /* Diese interne Funktion erzeugt ein neues ItemArray, welches von 'pItems'
1867 kopiert wird, an der Position 'nPos' jedoch Platz f"ur einen neuen
1870 Das neue ItemArray wird als Returnwert zur"uckgegeben, das alte 'pItems'
1875 // neues ItemArray anlegen
1876 SfxItemArray pNew
= new const SfxPoolItem
*[nOldSize
+1];
1878 // war schon vorher eins da?
1881 // alte Items vor nPos kopieren
1883 memcpy( (void*) pNew
, pItems
, nPos
* sizeof(SfxPoolItem
**) );
1885 // alte Items hinter nPos kopieren
1886 if ( nPos
< nOldSize
)
1887 memcpy( (void*) (pNew
+ nPos
+ 1), pItems
+ nPos
,
1888 (nOldSize
-nPos
) * sizeof(SfxPoolItem
**) );
1891 // neues Item initialisieren
1894 // altes ItemArray freigeben
1900 // -----------------------------------------------------------------------
1902 const SfxPoolItem
* SfxAllItemSet::Put( const SfxPoolItem
& rItem
, USHORT nWhich
)
1904 // Putten mit automatischer Erweiterung der Whichs-Ids um die ID
1908 USHORT nPos
= 0; // Position f"ur 'rItem' in '_aItems'
1909 const USHORT nItemCount
= TotalCount();
1911 // erstmal sehen, ob es schon einen passenden Bereich gibt
1912 USHORT
*pPtr
= _pWhichRanges
;
1915 // Which-Id liegt in diesem Bereich?
1916 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
1919 nPos
+= nWhich
- *pPtr
;
1923 // Position des Items in _aItems mitf"uhren
1924 nPos
+= *(pPtr
+1) - *pPtr
+ 1;
1926 // zum n"achsten Bereich
1930 // Which-Id noch nicht vorhanden?
1933 // suchen, ob man sie irgendwo dranpacken kann
1934 pPtr
= _pWhichRanges
;
1938 // Which-Id liegt exakt vor diesem Bereich?
1939 if ( (nWhich
+1) == *pPtr
)
1941 // Bereich waechst nach unten
1944 // vor erstem Item dieses Bereichs Platz schaffen
1945 _aItems
= AddItem_Impl(_aItems
, nItemCount
, nPos
);
1949 // Which-Id liegt exakt hinter diesem Bereich?
1950 else if ( (nWhich
-1) == *(pPtr
+1) )
1952 // Bereich waechst nach oben
1955 // hinter letztem Item dieses Bereichs Platz schaffen
1956 nPos
+= nWhich
- *pPtr
;
1957 _aItems
= AddItem_Impl(_aItems
, nItemCount
, nPos
);
1961 // Position des Items in _aItems mitf"uhren
1962 nPos
+= *(pPtr
+1) - *pPtr
+ 1;
1964 // zum n"achsten Bereich
1969 // keinen erweiterbaren Bereich gefunden?
1972 // kein Platz mehr in _pWhichRanges => erweitern
1973 std::ptrdiff_t nSize
= pPtr
- _pWhichRanges
;
1976 _pWhichRanges
= AddRanges_Impl(_pWhichRanges
, nSize
, nInitCount
);
1977 nFree
+= nInitCount
;
1980 // neuen Which-Range anh"angen
1981 pPtr
= _pWhichRanges
+ nSize
;
1986 // Itemarray vergroessern
1988 _aItems
= AddItem_Impl(_aItems
, nItemCount
, nPos
);
1991 // neues Item in Pool aufnehmen
1992 const SfxPoolItem
& rNew
= _pPool
->Put( rItem
, nWhich
);
1994 // altes Item merken
1995 BOOL bIncrementCount
= FALSE
;
1996 const SfxPoolItem
* pOld
= *( _aItems
+ nPos
);
1997 if ( reinterpret_cast< SfxPoolItem
* >( -1 ) == pOld
) // state "dontcare"
2001 bIncrementCount
= TRUE
;
2003 &_pParent
->Get( nWhich
, TRUE
)
2004 : nWhich
<= SFX_WHICH_MAX
? &_pPool
->GetDefaultItem( nWhich
) : 0;
2007 // neue Item in ItemSet aufnehmen
2008 *(_aItems
+ nPos
) = &rNew
;
2010 // Changed Notification versenden
2013 Changed( *pOld
, rNew
);
2014 if ( !IsDefaultItem(pOld
) )
2015 _pPool
->Remove( *pOld
);
2018 if ( bIncrementCount
)
2024 // -----------------------------------------------------------------------
2027 /* Diese Methode wird forwarded, damit sie nicht durch die anderen
2028 Put-Methoden dieser SubClass gehided wird.
2031 int SfxAllItemSet::Put( const SfxItemSet
& rSet
, BOOL bInvalidAsDefault
)
2033 //? pruefen, ob Which-Ranges erweitert werden
2034 return SfxItemSet::Put( rSet
, bInvalidAsDefault
);
2037 // -----------------------------------------------------------------------
2038 // Item disablen, wenn durch ein VoidItem mit dem Which-Wert 0 ausgedrueckt
2040 void SfxItemSet::DisableItem(USHORT nWhich
)
2042 DBG_CHKTHIS(SfxItemSet
, 0);
2043 Put( SfxVoidItem(0), nWhich
);
2046 // -----------------------------------------------------------------------
2049 BOOL
SfxAllItemSet::Remove(USHORT nWhich
)
2051 DBG_CHKTHIS(SfxAllItemSet
, 0);
2052 USHORT
*pPtr
= _pWhichRanges
;
2056 if( *pPtr
<= nWhich
&& nWhich
<= *(pPtr
+1) )
2058 USHORT
*pTmp
= pPtr
;
2063 nRest
= *pTmp
- *(pTmp
-1) + 1;
2067 // in diesem Bereich
2068 nPos
+= nWhich
- *pPtr
;
2069 nRest
-= nWhich
- *pPtr
;
2071 if(*pPtr
== nWhich
&& *(pPtr
+1) == nWhich
) {
2072 memmove(pPtr
, pPtr
+ 2, nLeft
* sizeof(USHORT
));
2076 else if(*pPtr
== nWhich
)
2079 else if(*(pPtr
+1) == nWhich
)
2082 if(nPos
+ nRest
+ 2 > nFree
) {
2083 USHORT nOf
= pPtr
- _pWhichRanges
;
2084 _pWhichRanges
= IncrSize(_pWhichRanges
, nPos
+ nRest
, nInitCount
);
2085 nFree
+= nInitCount
;
2086 pPtr
= _pWhichRanges
+ nOf
;
2088 memmove(pPtr
+2, pPtr
, (nLeft
+2) * sizeof(USHORT
));
2093 SfxPoolItem
* pItem
= *( _aItems
+ nPos
);
2097 _pPool
->Remove(*pItem
);
2102 memmove(_aItems
+ nPos
+1, _aItems
+ nPos
,
2103 sizeof(SfxPoolItem
*) * (nRest
- 1));
2104 break; // dann beim Parent suchen
2106 nPos
+= *(pPtr
+1) - *pPtr
+ 1;
2109 return *pPtr
? TRUE
: FALSE
;
2113 // -----------------------------------------------------------------------
2115 SfxItemSet
*SfxAllItemSet::Clone(BOOL bItems
, SfxItemPool
*pToPool
) const
2117 DBG_CHKTHIS(SfxItemSet
, DbgCheckItemSet
);
2118 if ( pToPool
&& pToPool
!= _pPool
)
2120 SfxAllItemSet
*pNewSet
= new SfxAllItemSet( *pToPool
);
2122 pNewSet
->Set( *this );
2126 return bItems
? new SfxAllItemSet(*this) : new SfxAllItemSet(*_pPool
);