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