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 : #include <sal/config.h>
21 :
22 : #include <iomanip>
23 :
24 : #include <tools/debug.hxx>
25 : #include <tools/stream.hxx>
26 : #include <basic/sbx.hxx>
27 : #include <svl/SfxBroadcaster.hxx>
28 : #include "sbxres.hxx"
29 :
30 207664 : TYPEINIT1(SbxMethod,SbxVariable)
31 136098 : TYPEINIT1(SbxProperty,SbxVariable)
32 518548 : TYPEINIT2(SbxObject,SbxVariable,SfxListener)
33 :
34 401 : static OUString pNameProp; // Name-Property
35 401 : static OUString pParentProp; // Parent-Property
36 :
37 : static sal_uInt16 nNameHash = 0, nParentHash = 0;
38 :
39 :
40 :
41 63968 : SbxObject::SbxObject( const OUString& rClass )
42 63968 : : SbxVariable( SbxOBJECT ), aClassName( rClass )
43 : {
44 63968 : aData.pObj = this;
45 63968 : if( !nNameHash )
46 : {
47 176 : pNameProp = OUString::createFromAscii(GetSbxRes( STRING_NAMEPROP ));
48 176 : pParentProp = OUString::createFromAscii(GetSbxRes( STRING_PARENTPROP ));
49 176 : nNameHash = MakeHashCode( pNameProp );
50 176 : nParentHash = MakeHashCode( pParentProp );
51 : }
52 63968 : SbxObject::Clear();
53 63968 : SbxObject::SetName( rClass );
54 63968 : }
55 :
56 4 : SbxObject::SbxObject( const SbxObject& rObj )
57 4 : : SvRefBase( rObj ), SbxVariable( rObj.GetType() ),
58 8 : SfxListener( rObj )
59 : {
60 4 : *this = rObj;
61 4 : }
62 :
63 4 : SbxObject& SbxObject::operator=( const SbxObject& r )
64 : {
65 4 : if( &r != this )
66 : {
67 4 : SbxVariable::operator=( r );
68 4 : aClassName = r.aClassName;
69 4 : pMethods = new SbxArray;
70 4 : pProps = new SbxArray;
71 4 : pObjs = new SbxArray( SbxOBJECT );
72 : // The arrays were copied, the content taken over
73 4 : *pMethods = *r.pMethods;
74 4 : *pProps = *r.pProps;
75 4 : *pObjs = *r.pObjs;
76 : // Because the variables were taken over, this is OK
77 4 : pDfltProp = r.pDfltProp;
78 4 : SetName( r.GetName() );
79 4 : SetFlags( r.GetFlags() );
80 4 : SetModified( true );
81 : }
82 4 : return *this;
83 : }
84 :
85 180870 : static void CheckParentsOnDelete( SbxObject* pObj, SbxArray* p )
86 : {
87 257830 : for( sal_uInt16 i = 0; i < p->Count(); i++ )
88 : {
89 76960 : SbxVariableRef& rRef = p->GetRef( i );
90 76960 : if( rRef->IsBroadcaster() )
91 : {
92 76948 : pObj->EndListening( rRef->GetBroadcaster(), true );
93 : }
94 : // does the element have more than one reference and still a Listener?
95 76960 : if( rRef->GetRefCount() > 1 )
96 : {
97 696 : rRef->SetParent( NULL );
98 : DBG_ASSERT( !rRef->IsBroadcaster() || rRef->GetBroadcaster().GetListenerCount(), "Object element with dangling parent" );
99 : }
100 : }
101 180870 : }
102 :
103 124426 : SbxObject::~SbxObject()
104 : {
105 60290 : CheckParentsOnDelete( this, pProps );
106 60290 : CheckParentsOnDelete( this, pMethods );
107 60290 : CheckParentsOnDelete( this, pObjs );
108 :
109 : // avoid handling in ~SbxVariable as SBX_DIM_AS_NEW == SBX_GBLSEARCH
110 60290 : ResetFlag( SBX_DIM_AS_NEW );
111 64136 : }
112 :
113 40564 : SbxDataType SbxObject::GetType() const
114 : {
115 40564 : return SbxOBJECT;
116 : }
117 :
118 1177690 : SbxClassType SbxObject::GetClass() const
119 : {
120 1177690 : return SbxCLASS_OBJECT;
121 : }
122 :
123 63968 : void SbxObject::Clear()
124 : {
125 63968 : pMethods = new SbxArray;
126 63968 : pProps = new SbxArray;
127 63968 : pObjs = new SbxArray( SbxOBJECT );
128 : SbxVariable* p;
129 63968 : p = Make( pNameProp, SbxCLASS_PROPERTY, SbxSTRING );
130 63968 : p->SetFlag( SBX_DONTSTORE );
131 63968 : p = Make( pParentProp, SbxCLASS_PROPERTY, SbxOBJECT );
132 63968 : p->ResetFlag( SBX_WRITE );
133 63968 : p->SetFlag( SBX_DONTSTORE );
134 63968 : pDfltProp = NULL;
135 63968 : SetModified( false );
136 63968 : }
137 :
138 149958 : void SbxObject::SFX_NOTIFY( SfxBroadcaster&, const TypeId&,
139 : const SfxHint& rHint, const TypeId& )
140 : {
141 149958 : const SbxHint* p = dynamic_cast<const SbxHint*>(&rHint);
142 149958 : if( p )
143 : {
144 149958 : sal_uLong nId = p->GetId();
145 149958 : bool bRead = ( nId == SBX_HINT_DATAWANTED );
146 149958 : bool bWrite = ( nId == SBX_HINT_DATACHANGED );
147 149958 : SbxVariable* pVar = p->GetVar();
148 149958 : if( bRead || bWrite )
149 : {
150 148822 : OUString aVarName( pVar->GetName() );
151 148822 : sal_uInt16 nHash_ = MakeHashCode( aVarName );
152 148822 : if( nHash_ == nNameHash && aVarName.equalsIgnoreAsciiCase( pNameProp ) )
153 : {
154 0 : if( bRead )
155 : {
156 0 : pVar->PutString( GetName() );
157 : }
158 : else
159 : {
160 0 : SetName( pVar->GetOUString() );
161 : }
162 : }
163 148822 : else if( nHash_ == nParentHash && aVarName.equalsIgnoreAsciiCase( pParentProp ) )
164 : {
165 0 : SbxObject* p_ = GetParent();
166 0 : if( !p_ )
167 : {
168 0 : p_ = this;
169 : }
170 0 : pVar->PutObject( p_ );
171 148822 : }
172 : }
173 : }
174 149958 : }
175 :
176 296 : bool SbxObject::IsClass( const OUString& rName ) const
177 : {
178 296 : return aClassName.equalsIgnoreAsciiCase( rName );
179 : }
180 :
181 0 : SbxVariable* SbxObject::FindUserData( sal_uInt32 nData )
182 : {
183 0 : if( !GetAll( SbxCLASS_DONTCARE ) )
184 : {
185 0 : return NULL;
186 : }
187 0 : SbxVariable* pRes = pMethods->FindUserData( nData );
188 0 : if( !pRes )
189 : {
190 0 : pRes = pProps->FindUserData( nData );
191 : }
192 0 : if( !pRes )
193 : {
194 0 : pRes = pObjs->FindUserData( nData );
195 : }
196 : // Search in the parents?
197 0 : if( !pRes && IsSet( SBX_GBLSEARCH ) )
198 : {
199 0 : SbxObject* pCur = this;
200 0 : while( !pRes && pCur->pParent )
201 : {
202 : // I myself was already searched!
203 0 : SbxFlagBits nOwn = pCur->GetFlags();
204 0 : pCur->ResetFlag( SBX_EXTSEARCH );
205 : // I search already global!
206 0 : SbxFlagBits nPar = pCur->pParent->GetFlags();
207 0 : pCur->pParent->ResetFlag( SBX_GBLSEARCH );
208 0 : pRes = pCur->pParent->FindUserData( nData );
209 0 : pCur->SetFlags( nOwn );
210 0 : pCur->pParent->SetFlags( nPar );
211 0 : pCur = pCur->pParent;
212 : }
213 : }
214 0 : return pRes;
215 : }
216 :
217 2430032 : SbxVariable* SbxObject::Find( const OUString& rName, SbxClassType t )
218 : {
219 : #ifdef DBG_UTIL
220 : static int nLvl = 1;
221 : static const char* pCls[] = { "DontCare","Array","Value","Variable","Method","Property","Object" };
222 : SAL_INFO(
223 : "basic.sbx",
224 : "search" << std::setw(nLvl) << " "
225 : << (t >= SbxCLASS_DONTCARE && t <= SbxCLASS_OBJECT
226 : ? pCls[t - 1] : "Unknown class")
227 : << " " << rName << " in " << SbxVariable::GetName());
228 : ++nLvl;
229 : #endif
230 :
231 2430032 : if( !GetAll( t ) )
232 : {
233 0 : return NULL;
234 : }
235 2430032 : SbxVariable* pRes = NULL;
236 2430032 : pObjs->SetFlag( SBX_EXTSEARCH );
237 2430032 : if( t == SbxCLASS_DONTCARE )
238 : {
239 1547034 : pRes = pMethods->Find( rName, SbxCLASS_METHOD );
240 1547034 : if( !pRes )
241 : {
242 1542544 : pRes = pProps->Find( rName, SbxCLASS_PROPERTY );
243 : }
244 1547034 : if( !pRes )
245 : {
246 1435216 : pRes = pObjs->Find( rName, t );
247 : }
248 : }
249 : else
250 : {
251 882998 : SbxArray* pArray = NULL;
252 882998 : switch( t )
253 : {
254 : case SbxCLASS_VARIABLE:
255 18430 : case SbxCLASS_PROPERTY: pArray = pProps; break;
256 5796 : case SbxCLASS_METHOD: pArray = pMethods; break;
257 858772 : case SbxCLASS_OBJECT: pArray = pObjs; break;
258 0 : default: DBG_ASSERT( false, "Invalid SBX-Class" ); break;
259 : }
260 882998 : if( pArray )
261 : {
262 882998 : pRes = pArray->Find( rName, t );
263 : }
264 : }
265 : // Extended Search in the Object-Array?
266 : // For objects and DontCare the array of objects has already been searched
267 2430032 : if( !pRes && ( t == SbxCLASS_METHOD || t == SbxCLASS_PROPERTY ) )
268 16502 : pRes = pObjs->Find( rName, t );
269 : // Search in the parents?
270 2430032 : if( !pRes && IsSet( SBX_GBLSEARCH ) )
271 : {
272 80736 : SbxObject* pCur = this;
273 243684 : while( !pRes && pCur->pParent )
274 : {
275 : // I myself was already searched!
276 82212 : SbxFlagBits nOwn = pCur->GetFlags();
277 82212 : pCur->ResetFlag( SBX_EXTSEARCH );
278 : // I search already global!
279 82212 : SbxFlagBits nPar = pCur->pParent->GetFlags();
280 82212 : pCur->pParent->ResetFlag( SBX_GBLSEARCH );
281 82212 : pRes = pCur->pParent->Find( rName, t );
282 82212 : pCur->SetFlags( nOwn );
283 82212 : pCur->pParent->SetFlags( nPar );
284 82212 : pCur = pCur->pParent;
285 : }
286 : }
287 : #ifdef DBG_UTIL
288 : --nLvl;
289 : SAL_INFO_IF(
290 : pRes, "basic.sbx",
291 : "found" << std::setw(nLvl) << " " << rName << " in "
292 : << SbxVariable::GetName());
293 : #endif
294 2430032 : return pRes;
295 : }
296 :
297 : // Abbreviated version: The parent-string will be searched
298 : // The whole thing recursive, because Call() might be overloaded
299 : // Qualified names are allowed
300 :
301 36 : bool SbxObject::Call( const OUString& rName, SbxArray* pParam )
302 : {
303 36 : SbxVariable* pMeth = FindQualified( rName, SbxCLASS_DONTCARE);
304 36 : if( pMeth && pMeth->ISA(SbxMethod) )
305 : {
306 : // FindQualified() might have struck already!
307 36 : if( pParam )
308 : {
309 36 : pMeth->SetParameters( pParam );
310 : }
311 36 : pMeth->Broadcast( SBX_HINT_DATAWANTED );
312 36 : pMeth->SetParameters( NULL );
313 36 : return true;
314 : }
315 0 : SetError( SbxERR_NO_METHOD );
316 0 : return false;
317 : }
318 :
319 200 : SbxProperty* SbxObject::GetDfltProperty()
320 : {
321 200 : if ( !pDfltProp && !aDfltPropName.isEmpty() )
322 : {
323 176 : pDfltProp = static_cast<SbxProperty*>( Find( aDfltPropName, SbxCLASS_PROPERTY ) );
324 176 : if( !pDfltProp )
325 : {
326 0 : pDfltProp = static_cast<SbxProperty*>( Make( aDfltPropName, SbxCLASS_PROPERTY, SbxVARIANT ) );
327 : }
328 : }
329 200 : return pDfltProp;
330 : }
331 2426 : void SbxObject::SetDfltProperty( const OUString& rName )
332 : {
333 2426 : if ( rName != aDfltPropName )
334 : {
335 2426 : pDfltProp = NULL;
336 : }
337 2426 : aDfltPropName = rName;
338 2426 : SetModified( true );
339 2426 : }
340 :
341 : // Search of an already available variable. If it was located,
342 : // the index will be set, otherwise the Count of the Array will be returned.
343 : // In any case the correct Array will be returned.
344 :
345 142224 : SbxArray* SbxObject::FindVar( SbxVariable* pVar, sal_uInt16& nArrayIdx )
346 : {
347 142224 : SbxArray* pArray = NULL;
348 142224 : if( pVar ) switch( pVar->GetClass() )
349 : {
350 : case SbxCLASS_VARIABLE:
351 96592 : case SbxCLASS_PROPERTY: pArray = pProps; break;
352 0 : case SbxCLASS_METHOD: pArray = pMethods; break;
353 45632 : case SbxCLASS_OBJECT: pArray = pObjs; break;
354 0 : default: DBG_ASSERT( false, "Invalid SBX-Class" ); break;
355 : }
356 142224 : if( pArray )
357 : {
358 142224 : nArrayIdx = pArray->Count();
359 : // Is the variable per name available?
360 142224 : pArray->ResetFlag( SBX_EXTSEARCH );
361 142224 : SbxVariable* pOld = pArray->Find( pVar->GetName(), pVar->GetClass() );
362 142224 : if( pOld )
363 : {
364 451532 : for( sal_uInt16 i = 0; i < pArray->Count(); i++ )
365 : {
366 451532 : SbxVariableRef& rRef = pArray->GetRef( i );
367 451532 : if( (SbxVariable*) rRef == pOld )
368 : {
369 122958 : nArrayIdx = i; break;
370 : }
371 : }
372 : }
373 : }
374 142224 : return pArray;
375 : }
376 :
377 : // If a new object will be established, this object will be indexed,
378 : // if an object of this name exists already.
379 :
380 162072 : SbxVariable* SbxObject::Make( const OUString& rName, SbxClassType ct, SbxDataType dt )
381 : {
382 : // Is the object already available?
383 162072 : SbxArray* pArray = NULL;
384 162072 : switch( ct )
385 : {
386 : case SbxCLASS_VARIABLE:
387 128328 : case SbxCLASS_PROPERTY: pArray = pProps; break;
388 33744 : case SbxCLASS_METHOD: pArray = pMethods; break;
389 0 : case SbxCLASS_OBJECT: pArray = pObjs; break;
390 0 : default: DBG_ASSERT( false, "Invalid SBX-Class" ); break;
391 : }
392 162072 : if( !pArray )
393 : {
394 0 : return NULL;
395 : }
396 : // Collections may contain objects of the same name
397 162072 : if( !( ct == SbxCLASS_OBJECT && ISA(SbxCollection) ) )
398 : {
399 162072 : SbxVariable* pRes = pArray->Find( rName, ct );
400 162072 : if( pRes )
401 : {
402 0 : return pRes;
403 : }
404 : }
405 162072 : SbxVariable* pVar = NULL;
406 162072 : switch( ct )
407 : {
408 : case SbxCLASS_VARIABLE:
409 : case SbxCLASS_PROPERTY:
410 128328 : pVar = new SbxProperty( rName, dt );
411 128328 : break;
412 : case SbxCLASS_METHOD:
413 33744 : pVar = new SbxMethod( rName, dt );
414 33744 : break;
415 : case SbxCLASS_OBJECT:
416 0 : pVar = CreateObject( rName );
417 0 : break;
418 : default:
419 0 : break;
420 : }
421 162072 : pVar->SetParent( this );
422 162072 : pArray->Put( pVar, pArray->Count() );
423 162072 : SetModified( true );
424 : // The object listen always
425 162072 : StartListening( pVar->GetBroadcaster(), true );
426 162072 : Broadcast( SBX_HINT_OBJECTCHANGED );
427 162072 : return pVar;
428 : }
429 :
430 0 : SbxObject* SbxObject::MakeObject( const OUString& rName, const OUString& rClass )
431 : {
432 : // Is the object already available?
433 0 : if( !ISA(SbxCollection) )
434 : {
435 0 : SbxVariable* pRes = pObjs->Find( rName, SbxCLASS_OBJECT );
436 0 : if( pRes )
437 : {
438 0 : return PTR_CAST(SbxObject,pRes);
439 : }
440 : }
441 0 : SbxObject* pVar = CreateObject( rClass );
442 0 : if( pVar )
443 : {
444 0 : pVar->SetName( rName );
445 0 : pVar->SetParent( this );
446 0 : pObjs->Put( pVar, pObjs->Count() );
447 0 : SetModified( true );
448 : // The object listen always
449 0 : StartListening( pVar->GetBroadcaster(), true );
450 0 : Broadcast( SBX_HINT_OBJECTCHANGED );
451 : }
452 0 : return pVar;
453 : }
454 :
455 45284 : void SbxObject::Insert( SbxVariable* pVar )
456 : {
457 : sal_uInt16 nIdx;
458 45284 : SbxArray* pArray = FindVar( pVar, nIdx );
459 45284 : if( pArray )
460 : {
461 : // Into with it. But you should pay attention at the Pointer!
462 45284 : if( nIdx < pArray->Count() )
463 : {
464 : // Then this element exists already
465 : // There are objects of the same name allowed at collections
466 26366 : if( pArray == pObjs && ISA(SbxCollection) )
467 : {
468 0 : nIdx = pArray->Count();
469 : }
470 : else
471 : {
472 26366 : SbxVariable* pOld = pArray->Get( nIdx );
473 : // already inside: overwrite
474 26366 : if( pOld == pVar )
475 : {
476 0 : return;
477 : }
478 26366 : EndListening( pOld->GetBroadcaster(), true );
479 26366 : if( pVar->GetClass() == SbxCLASS_PROPERTY )
480 : {
481 0 : if( pOld == pDfltProp )
482 : {
483 0 : pDfltProp = static_cast<SbxProperty*>(pVar);
484 : }
485 : }
486 : }
487 : }
488 45284 : StartListening( pVar->GetBroadcaster(), true );
489 45284 : pArray->Put( pVar, nIdx );
490 45284 : if( pVar->GetParent() != this )
491 : {
492 43726 : pVar->SetParent( this );
493 : }
494 45284 : SetModified( true );
495 45284 : Broadcast( SBX_HINT_OBJECTCHANGED );
496 : #ifdef DBG_UTIL
497 : static const char* pCls[] =
498 : { "DontCare","Array","Value","Variable","Method","Property","Object" };
499 : OUString aVarName( pVar->GetName() );
500 : if ( aVarName.isEmpty() && pVar->ISA(SbxObject) )
501 : {
502 : aVarName = PTR_CAST(SbxObject,pVar)->GetClassName();
503 : }
504 : SAL_INFO(
505 : "basic.sbx",
506 : "insert "
507 : << ((pVar->GetClass() >= SbxCLASS_DONTCARE
508 : && pVar->GetClass() <= SbxCLASS_OBJECT)
509 : ? pCls[pVar->GetClass() - 1] : "Unknown class")
510 : << " " << aVarName << " in " << SbxVariable::GetName());
511 : #endif
512 : }
513 : }
514 :
515 : // Optimisation, Insertion without checking about
516 : // double entry and without broadcasts, will only be used in SO2/auto.cxx
517 4440 : void SbxObject::QuickInsert( SbxVariable* pVar )
518 : {
519 4440 : SbxArray* pArray = NULL;
520 4440 : if( pVar )
521 : {
522 4440 : switch( pVar->GetClass() )
523 : {
524 : case SbxCLASS_VARIABLE:
525 2460 : case SbxCLASS_PROPERTY: pArray = pProps; break;
526 1980 : case SbxCLASS_METHOD: pArray = pMethods; break;
527 0 : case SbxCLASS_OBJECT: pArray = pObjs; break;
528 0 : default: DBG_ASSERT( false, "Invalid SBX-Class" ); break;
529 : }
530 : }
531 4440 : if( pArray )
532 : {
533 4440 : StartListening( pVar->GetBroadcaster(), true );
534 4440 : pArray->Put( pVar, pArray->Count() );
535 4440 : if( pVar->GetParent() != this )
536 : {
537 4440 : pVar->SetParent( this );
538 : }
539 4440 : SetModified( true );
540 : #ifdef DBG_UTIL
541 : static const char* pCls[] =
542 : { "DontCare","Array","Value","Variable","Method","Property","Object" };
543 : OUString aVarName( pVar->GetName() );
544 : if ( aVarName.isEmpty() && pVar->ISA(SbxObject) )
545 : {
546 : aVarName = PTR_CAST(SbxObject,pVar)->GetClassName();
547 : }
548 : SAL_INFO(
549 : "basic.sbx",
550 : "insert "
551 : << ((pVar->GetClass() >= SbxCLASS_DONTCARE
552 : && pVar->GetClass() <= SbxCLASS_OBJECT)
553 : ? pCls[pVar->GetClass() - 1] : "Unknown class")
554 : << " " << aVarName << " in " << SbxVariable::GetName());
555 : #endif
556 : }
557 4440 : }
558 :
559 96592 : void SbxObject::Remove( const OUString& rName, SbxClassType t )
560 : {
561 96592 : Remove( SbxObject::Find( rName, t ) );
562 96592 : }
563 :
564 96940 : void SbxObject::Remove( SbxVariable* pVar )
565 : {
566 : sal_uInt16 nIdx;
567 96940 : SbxArray* pArray = FindVar( pVar, nIdx );
568 96940 : if( pArray && nIdx < pArray->Count() )
569 : {
570 : #ifdef DBG_UTIL
571 : OUString aVarName( pVar->GetName() );
572 : if ( aVarName.isEmpty() && pVar->ISA(SbxObject) )
573 : {
574 : aVarName = PTR_CAST(SbxObject,pVar)->GetClassName();
575 : }
576 : SAL_INFO(
577 : "basic.sbx",
578 : "remove " << aVarName << " in " << SbxVariable::GetName());
579 : #endif
580 96592 : SbxVariableRef pVar_ = pArray->Get( nIdx );
581 96592 : if( pVar_->IsBroadcaster() )
582 : {
583 96592 : EndListening( pVar_->GetBroadcaster(), true );
584 : }
585 96592 : if( (SbxVariable*) pVar_ == pDfltProp )
586 : {
587 0 : pDfltProp = NULL;
588 : }
589 96592 : pArray->Remove( nIdx );
590 96592 : if( pVar_->GetParent() == this )
591 : {
592 96592 : pVar_->SetParent( NULL );
593 : }
594 96592 : SetModified( true );
595 96592 : Broadcast( SBX_HINT_OBJECTCHANGED );
596 : }
597 96940 : }
598 :
599 0 : static bool LoadArray( SvStream& rStrm, SbxObject* pThis, SbxArray* pArray )
600 : {
601 0 : SbxArrayRef p = static_cast<SbxArray*>( SbxBase::Load( rStrm ) );
602 0 : if( !p.Is() )
603 : {
604 0 : return false;
605 : }
606 0 : for( sal_uInt16 i = 0; i < p->Count(); i++ )
607 : {
608 0 : SbxVariableRef& r = p->GetRef( i );
609 0 : SbxVariable* pVar = r;
610 0 : if( pVar )
611 : {
612 0 : pVar->SetParent( pThis );
613 0 : pThis->StartListening( pVar->GetBroadcaster(), true );
614 : }
615 : }
616 0 : pArray->Merge( p );
617 0 : return true;
618 : }
619 :
620 : // The load of an object is additive!
621 :
622 0 : bool SbxObject::LoadData( SvStream& rStrm, sal_uInt16 nVer )
623 : {
624 : // Help for the read in of old objects: just return TRUE,
625 : // LoadPrivateData() has to set the default status up
626 0 : if( !nVer )
627 : {
628 0 : return true;
629 : }
630 0 : pDfltProp = NULL;
631 0 : if( !SbxVariable::LoadData( rStrm, nVer ) )
632 : {
633 0 : return false;
634 : }
635 : // If it contains no alien object, insert ourselves
636 0 : if( aData.eType == SbxOBJECT && !aData.pObj )
637 : {
638 0 : aData.pObj = this;
639 : }
640 : sal_uInt32 nSize;
641 0 : OUString aDfltProp;
642 0 : aClassName = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm, RTL_TEXTENCODING_ASCII_US);
643 0 : aDfltProp = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm, RTL_TEXTENCODING_ASCII_US);
644 0 : sal_Size nPos = rStrm.Tell();
645 0 : rStrm.ReadUInt32( nSize );
646 0 : if( !LoadPrivateData( rStrm, nVer ) )
647 : {
648 0 : return false;
649 : }
650 0 : sal_Size nNewPos = rStrm.Tell();
651 0 : nPos += nSize;
652 : DBG_ASSERT( nPos >= nNewPos, "SBX: Loaded too much data" );
653 0 : if( nPos != nNewPos )
654 : {
655 0 : rStrm.Seek( nPos );
656 : }
657 0 : if( !LoadArray( rStrm, this, pMethods ) ||
658 0 : !LoadArray( rStrm, this, pProps ) ||
659 0 : !LoadArray( rStrm, this, pObjs ) )
660 : {
661 0 : return false;
662 : }
663 : // Set properties
664 0 : if( !aDfltProp.isEmpty() )
665 : {
666 0 : pDfltProp = static_cast<SbxProperty*>( pProps->Find( aDfltProp, SbxCLASS_PROPERTY ) );
667 : }
668 0 : SetModified( false );
669 0 : return true;
670 : }
671 :
672 0 : bool SbxObject::StoreData( SvStream& rStrm ) const
673 : {
674 0 : if( !SbxVariable::StoreData( rStrm ) )
675 : {
676 0 : return false;
677 : }
678 0 : OUString aDfltProp;
679 0 : if( pDfltProp )
680 : {
681 0 : aDfltProp = pDfltProp->GetName();
682 : }
683 0 : write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, aClassName, RTL_TEXTENCODING_ASCII_US);
684 0 : write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, aDfltProp, RTL_TEXTENCODING_ASCII_US);
685 0 : sal_Size nPos = rStrm.Tell();
686 0 : rStrm.WriteUInt32( 0L );
687 0 : if( !StorePrivateData( rStrm ) )
688 : {
689 0 : return false;
690 : }
691 0 : sal_Size nNew = rStrm.Tell();
692 0 : rStrm.Seek( nPos );
693 0 : rStrm.WriteUInt32( ( nNew - nPos ) );
694 0 : rStrm.Seek( nNew );
695 0 : if( !pMethods->Store( rStrm ) )
696 : {
697 0 : return false;
698 : }
699 0 : if( !pProps->Store( rStrm ) )
700 : {
701 0 : return false;
702 : }
703 0 : if( !pObjs->Store( rStrm ) )
704 : {
705 0 : return false;
706 : }
707 0 : ((SbxObject*) this)->SetModified( false );
708 0 : return true;
709 : }
710 :
711 0 : OUString SbxObject::GenerateSource( const OUString &rLinePrefix,
712 : const SbxObject* )
713 : {
714 : // Collect the properties in a String
715 0 : OUString aSource;
716 0 : SbxArrayRef xProps( GetProperties() );
717 0 : bool bLineFeed = false;
718 0 : for ( sal_uInt16 nProp = 0; nProp < xProps->Count(); ++nProp )
719 : {
720 0 : SbxPropertyRef xProp = static_cast<SbxProperty*>( xProps->Get(nProp) );
721 0 : OUString aPropName( xProp->GetName() );
722 0 : if ( xProp->CanWrite() &&
723 0 : !( xProp->GetHashCode() == nNameHash &&
724 0 : aPropName.equalsIgnoreAsciiCase(pNameProp)))
725 : {
726 : // Insert a break except in front of the first property
727 0 : if ( bLineFeed )
728 : {
729 0 : aSource += "\n";
730 : }
731 : else
732 : {
733 0 : bLineFeed = true;
734 : }
735 0 : aSource += rLinePrefix;
736 0 : aSource += ".";
737 0 : aSource += aPropName;
738 0 : aSource += " = ";
739 :
740 : // convert the property value to text
741 0 : switch ( xProp->GetType() )
742 : {
743 : case SbxEMPTY:
744 : case SbxNULL:
745 : // no value
746 0 : break;
747 :
748 : case SbxSTRING:
749 : // Strings in quotation mark
750 0 : aSource += "\"";
751 0 : aSource += xProp->GetOUString();
752 0 : aSource += "\"";
753 0 : break;
754 :
755 : default:
756 : // miscellaneous, such as e.g. numbers directly
757 0 : aSource += xProp->GetOUString();
758 0 : break;
759 : }
760 : }
761 0 : }
762 0 : return aSource;
763 : }
764 :
765 0 : static bool CollectAttrs( const SbxBase* p, OUString& rRes )
766 : {
767 0 : OUString aAttrs;
768 0 : if( p->IsHidden() )
769 : {
770 0 : aAttrs = "Hidden";
771 : }
772 0 : if( p->IsSet( SBX_EXTSEARCH ) )
773 : {
774 0 : if( !aAttrs.isEmpty() )
775 : {
776 0 : aAttrs += ",";
777 : }
778 0 : aAttrs += "ExtSearch";
779 : }
780 0 : if( !p->IsVisible() )
781 : {
782 0 : if( !aAttrs.isEmpty() )
783 : {
784 0 : aAttrs += ",";
785 : }
786 0 : aAttrs += "Invisible";
787 : }
788 0 : if( p->IsSet( SBX_DONTSTORE ) )
789 : {
790 0 : if( !aAttrs.isEmpty() )
791 : {
792 0 : aAttrs += ",";
793 : }
794 0 : aAttrs += "DontStore";
795 : }
796 0 : if( !aAttrs.isEmpty() )
797 : {
798 0 : rRes = " (";
799 0 : rRes += aAttrs;
800 0 : rRes += ")";
801 0 : return true;
802 : }
803 : else
804 : {
805 0 : rRes = "";
806 0 : return false;
807 0 : }
808 : }
809 :
810 0 : void SbxObject::Dump( SvStream& rStrm, bool bFill )
811 : {
812 : // Shifting
813 : static sal_uInt16 nLevel = 0;
814 0 : if ( nLevel > 10 )
815 : {
816 0 : rStrm.WriteCharPtr( "<too deep>" ) << endl;
817 0 : return;
818 : }
819 0 : ++nLevel;
820 0 : OUString aIndent("");
821 0 : for ( sal_uInt16 n = 1; n < nLevel; ++n )
822 : {
823 0 : aIndent += " ";
824 : }
825 : // if necessary complete the object
826 0 : if ( bFill )
827 : {
828 0 : GetAll( SbxCLASS_DONTCARE );
829 : }
830 : // Output the data of the object itself
831 0 : OString aNameStr(OUStringToOString(GetName(), RTL_TEXTENCODING_ASCII_US));
832 0 : OString aClassNameStr(OUStringToOString(aClassName, RTL_TEXTENCODING_ASCII_US));
833 0 : rStrm.WriteCharPtr( "Object( " )
834 0 : .WriteCharPtr( OString::number(reinterpret_cast<sal_Int64>(this)).getStr() ).WriteCharPtr( "=='" )
835 0 : .WriteCharPtr( aNameStr.isEmpty() ? "<unnamed>" : aNameStr.getStr() ).WriteCharPtr( "', " )
836 0 : .WriteCharPtr( "of class '" ).WriteCharPtr( aClassNameStr.getStr() ).WriteCharPtr( "', " )
837 0 : .WriteCharPtr( "counts " )
838 0 : .WriteCharPtr( OString::number(GetRefCount()).getStr() )
839 0 : .WriteCharPtr( " refs, " );
840 0 : if ( GetParent() )
841 : {
842 0 : OString aParentNameStr(OUStringToOString(GetName(), RTL_TEXTENCODING_ASCII_US));
843 0 : rStrm.WriteCharPtr( "in parent " )
844 0 : .WriteCharPtr( OString::number(reinterpret_cast<sal_Int64>(GetParent())).getStr() )
845 0 : .WriteCharPtr( "=='" ).WriteCharPtr( aParentNameStr.isEmpty() ? "<unnamed>" : aParentNameStr.getStr() ).WriteCharPtr( "'" );
846 : }
847 : else
848 : {
849 0 : rStrm.WriteCharPtr( "no parent " );
850 : }
851 0 : rStrm.WriteCharPtr( " )" ) << endl;
852 0 : OString aIndentNameStr(OUStringToOString(aIndent, RTL_TEXTENCODING_ASCII_US));
853 0 : rStrm.WriteCharPtr( aIndentNameStr.getStr() ).WriteCharPtr( "{" ) << endl;
854 :
855 : // Flags
856 0 : OUString aAttrs;
857 0 : if( CollectAttrs( this, aAttrs ) )
858 : {
859 0 : OString aAttrStr(OUStringToOString(aAttrs, RTL_TEXTENCODING_ASCII_US));
860 0 : rStrm.WriteCharPtr( aIndentNameStr.getStr() ).WriteCharPtr( "- Flags: " ).WriteCharPtr( aAttrStr.getStr() ) << endl;
861 : }
862 :
863 : // Methods
864 0 : rStrm.WriteCharPtr( aIndentNameStr.getStr() ).WriteCharPtr( "- Methods:" ) << endl;
865 0 : for( sal_uInt16 i = 0; i < pMethods->Count(); i++ )
866 : {
867 0 : SbxVariableRef& r = pMethods->GetRef( i );
868 0 : SbxVariable* pVar = r;
869 0 : if( pVar )
870 : {
871 0 : OUString aLine( aIndent );
872 0 : aLine += " - ";
873 0 : aLine += pVar->GetName( SbxNAME_SHORT_TYPES );
874 0 : OUString aAttrs2;
875 0 : if( CollectAttrs( pVar, aAttrs2 ) )
876 : {
877 0 : aLine += aAttrs2;
878 : }
879 0 : if( !pVar->IsA( TYPE(SbxMethod) ) )
880 : {
881 0 : aLine += " !! Not a Method !!";
882 : }
883 0 : write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, aLine, RTL_TEXTENCODING_ASCII_US);
884 :
885 : // Output also the object at object-methods
886 0 : if ( pVar->GetValues_Impl().eType == SbxOBJECT &&
887 0 : pVar->GetValues_Impl().pObj &&
888 0 : pVar->GetValues_Impl().pObj != this &&
889 0 : pVar->GetValues_Impl().pObj != GetParent() )
890 : {
891 0 : rStrm.WriteCharPtr( " contains " );
892 0 : static_cast<SbxObject*>(pVar->GetValues_Impl().pObj)->Dump( rStrm, bFill );
893 : }
894 : else
895 : {
896 0 : rStrm << endl;
897 0 : }
898 : }
899 : }
900 :
901 : // Properties
902 0 : rStrm.WriteCharPtr( aIndentNameStr.getStr() ).WriteCharPtr( "- Properties:" ) << endl;
903 : {
904 0 : for( sal_uInt16 i = 0; i < pProps->Count(); i++ )
905 : {
906 0 : SbxVariableRef& r = pProps->GetRef( i );
907 0 : SbxVariable* pVar = r;
908 0 : if( pVar )
909 : {
910 0 : OUString aLine( aIndent );
911 0 : aLine += " - ";
912 0 : aLine += pVar->GetName( SbxNAME_SHORT_TYPES );
913 0 : OUString aAttrs3;
914 0 : if( CollectAttrs( pVar, aAttrs3 ) )
915 : {
916 0 : aLine += aAttrs3;
917 : }
918 0 : if( !pVar->IsA( TYPE(SbxProperty) ) )
919 : {
920 0 : aLine += " !! Not a Property !!";
921 : }
922 0 : write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, aLine, RTL_TEXTENCODING_ASCII_US);
923 :
924 : // output also the object at object properties
925 0 : if ( pVar->GetValues_Impl().eType == SbxOBJECT &&
926 0 : pVar->GetValues_Impl().pObj &&
927 0 : pVar->GetValues_Impl().pObj != this &&
928 0 : pVar->GetValues_Impl().pObj != GetParent() )
929 : {
930 0 : rStrm.WriteCharPtr( " contains " );
931 0 : static_cast<SbxObject*>(pVar->GetValues_Impl().pObj)->Dump( rStrm, bFill );
932 : }
933 : else
934 : {
935 0 : rStrm << endl;
936 0 : }
937 : }
938 : }
939 : }
940 :
941 : // Objects
942 0 : rStrm.WriteCharPtr( aIndentNameStr.getStr() ).WriteCharPtr( "- Objects:" ) << endl;
943 : {
944 0 : for( sal_uInt16 i = 0; i < pObjs->Count(); i++ )
945 : {
946 0 : SbxVariableRef& r = pObjs->GetRef( i );
947 0 : SbxVariable* pVar = r;
948 0 : if ( pVar )
949 : {
950 0 : rStrm.WriteCharPtr( aIndentNameStr.getStr() ).WriteCharPtr( " - Sub" );
951 0 : if ( pVar->ISA(SbxObject) )
952 : {
953 0 : static_cast<SbxObject*>(pVar)->Dump( rStrm, bFill );
954 : }
955 0 : else if ( pVar->ISA(SbxVariable) )
956 : {
957 0 : static_cast<SbxVariable*>(pVar)->Dump( rStrm, bFill );
958 : }
959 : }
960 : }
961 : }
962 :
963 0 : rStrm.WriteCharPtr( aIndentNameStr.getStr() ).WriteCharPtr( "}" ) << endl << endl;
964 0 : --nLevel;
965 : }
966 :
967 36620 : SbxMethod::SbxMethod( const OUString& r, SbxDataType t )
968 36620 : : SbxVariable( t )
969 : {
970 36620 : SetName( r );
971 36620 : }
972 :
973 10636 : SbxMethod::SbxMethod( const SbxMethod& r )
974 10636 : : SvRefBase( r ), SbxVariable( r )
975 : {
976 10636 : }
977 :
978 76302 : SbxMethod::~SbxMethod()
979 : {
980 76302 : }
981 :
982 26670 : SbxClassType SbxMethod::GetClass() const
983 : {
984 26670 : return SbxCLASS_METHOD;
985 : }
986 :
987 131034 : SbxProperty::SbxProperty( const OUString& r, SbxDataType t )
988 131034 : : SbxVariable( t )
989 : {
990 131034 : SetName( r );
991 131034 : }
992 :
993 250774 : SbxProperty::~SbxProperty()
994 : {
995 250774 : }
996 :
997 406930 : SbxClassType SbxProperty::GetClass() const
998 : {
999 406930 : return SbxCLASS_PROPERTY;
1000 1203 : }
1001 :
1002 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|