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