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