xref: /aoo41x/main/basic/source/sbx/sbxbase.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basic.hxx"
30 
31 
32 #include <tools/shl.hxx>
33 #include <tools/stream.hxx>
34 
35 #include <basic/sbx.hxx>
36 #include <basic/sbxfac.hxx>
37 #include <basic/sbxbase.hxx>
38 
39 // AppData-Struktur fuer SBX:
40 
41 SV_IMPL_PTRARR(SbxParams,SbxParamInfo*);
42 SV_IMPL_PTRARR(SbxFacs,SbxFactory*);
43 
44 TYPEINIT0(SbxBase)
45 
46 // SBX-Daten anfordern oder ggf. anlegen
47 // wir legen den Bereich einfach an und verzichten auf die Freigabe!
48 
49 SbxAppData* GetSbxData_Impl()
50 {
51 	SbxAppData** ppData = (SbxAppData**) ::GetAppData( SHL_SBX );
52 	SbxAppData* p = *ppData;
53 	if( !p )
54 		p = *ppData  = new SbxAppData;
55 	return p;
56 }
57 
58 SbxAppData::~SbxAppData()
59 {
60 	if( pBasicFormater )
61 		delete pBasicFormater;
62 }
63 
64 
65 //////////////////////////////// SbxBase /////////////////////////////////
66 
67 DBG_NAME(SbxBase);
68 
69 SbxBase::SbxBase()
70 {
71 	DBG_CTOR( SbxBase, 0 );
72 	nFlags  = SBX_READWRITE;
73 }
74 
75 SbxBase::SbxBase( const SbxBase& r )
76     : SvRefBase( r )
77 {
78 	DBG_CTOR( SbxBase, 0 );
79 	nFlags  = r.nFlags;
80 }
81 
82 SbxBase::~SbxBase()
83 {
84 	DBG_DTOR(SbxBase,0);
85 }
86 
87 SbxBase& SbxBase::operator=( const SbxBase& r )
88 {
89 	DBG_CHKTHIS( SbxBase, 0 );
90 	nFlags = r.nFlags;
91 	return *this;
92 }
93 
94 SbxDataType SbxBase::GetType() const
95 {
96 	DBG_CHKTHIS( SbxBase, 0 );
97 	return SbxEMPTY;
98 }
99 
100 SbxClassType SbxBase::GetClass() const
101 {
102 	DBG_CHKTHIS( SbxBase, 0 );
103 	return SbxCLASS_DONTCARE;
104 }
105 
106 void SbxBase::Clear()
107 {
108 	DBG_CHKTHIS( SbxBase, 0 );
109 }
110 
111 sal_Bool SbxBase::IsFixed() const
112 {
113 	DBG_CHKTHIS( SbxBase, 0 );
114 	return IsSet( SBX_FIXED );
115 }
116 
117 void SbxBase::SetModified( sal_Bool b )
118 {
119 	DBG_CHKTHIS( SbxBase, 0 );
120 	if( IsSet( SBX_NO_MODIFY ) )
121 		return;
122 	if( b )
123 		SetFlag( SBX_MODIFIED );
124 	else
125 		ResetFlag( SBX_MODIFIED );
126 }
127 
128 SbxError SbxBase::GetError()
129 {
130 	return GetSbxData_Impl()->eSbxError;
131 }
132 
133 void SbxBase::SetError( SbxError e )
134 {
135 	SbxAppData* p = GetSbxData_Impl();
136 	if( e && p->eSbxError == SbxERR_OK )
137 		p->eSbxError = e;
138 }
139 
140 sal_Bool SbxBase::IsError()
141 {
142 	return sal_Bool( GetSbxData_Impl()->eSbxError != SbxERR_OK );
143 }
144 
145 void SbxBase::ResetError()
146 {
147 	GetSbxData_Impl()->eSbxError = SbxERR_OK;
148 }
149 
150 void SbxBase::AddFactory( SbxFactory* pFac )
151 {
152 	SbxAppData* p = GetSbxData_Impl();
153 	const SbxFactory* pTemp = pFac;
154 
155 	// AB, 6.3.96: HandleLast-Flag beruecksichtigen
156 	sal_uInt16 nPos = p->aFacs.Count();		// Einfuege-Position
157 	if( !pFac->IsHandleLast() )			// Nur, wenn nicht selbst HandleLast
158 	{
159 		// Neue Factory vor Factories mit HandleLast einordnen
160 		while( nPos > 0 &&
161 				(static_cast<SbxFactory*>(p->aFacs.GetObject( nPos-1 )))->IsHandleLast() )
162 			nPos--;
163 	}
164 	p->aFacs.Insert( pTemp, nPos );
165 }
166 
167 void SbxBase::RemoveFactory( SbxFactory* pFac )
168 {
169 	SbxAppData* p = GetSbxData_Impl();
170 	for( sal_uInt16 i = 0; i < p->aFacs.Count(); i++ )
171 	{
172 		if( p->aFacs.GetObject( i ) == pFac )
173 		{
174 			p->aFacs.Remove( i, 1 ); break;
175 		}
176 	}
177 }
178 
179 
180 SbxBase* SbxBase::Create( sal_uInt16 nSbxId, sal_uInt32 nCreator )
181 {
182     // #91626: Hack to skip old Basic dialogs
183     // Problem: There does not exist a factory any more,
184     // so we have to create a dummy SbxVariable instead
185 	if( nSbxId == 0x65 )    // Dialog Id
186         return new SbxVariable;
187 
188 	XubString aEmptyStr;
189 	if( nCreator == SBXCR_SBX )
190 	  switch( nSbxId )
191 	{
192 		case SBXID_VALUE:		return new SbxValue;
193 		case SBXID_VARIABLE:	return new SbxVariable;
194 		case SBXID_ARRAY:  		return new SbxArray;
195 		case SBXID_DIMARRAY:	return new SbxDimArray;
196 		case SBXID_OBJECT:		return new SbxObject( aEmptyStr );
197 		case SBXID_COLLECTION:	return new SbxCollection( aEmptyStr );
198 		case SBXID_FIXCOLLECTION:
199 								return new SbxStdCollection( aEmptyStr, aEmptyStr );
200 		case SBXID_METHOD:		return new SbxMethod( aEmptyStr, SbxEMPTY );
201 		case SBXID_PROPERTY:	return new SbxProperty( aEmptyStr, SbxEMPTY );
202 	}
203 	// Unbekanter Typ: �ber die Factories gehen!
204 	SbxAppData* p = GetSbxData_Impl();
205 	SbxBase* pNew = NULL;
206 	for( sal_uInt16 i = 0; i < p->aFacs.Count(); i++ )
207 	{
208 		SbxFactory* pFac = p->aFacs.GetObject( i );
209 		pNew = pFac->Create( nSbxId, nCreator );
210 		if( pNew )
211 			break;
212 	}
213 #ifdef DBG_UTIL
214 	if( !pNew )
215 	{
216 		ByteString aMsg( "SBX: Keine Factory fuer SBX-ID " );
217 		aMsg += ByteString::CreateFromInt32(nSbxId);
218 		DbgError( aMsg.GetBuffer() );
219 	}
220 #endif
221 	return pNew;
222 }
223 
224 SbxObject* SbxBase::CreateObject( const XubString& rClass )
225 {
226 	SbxAppData* p = GetSbxData_Impl();
227 	SbxObject* pNew = NULL;
228 	for( sal_uInt16 i = 0; i < p->aFacs.Count(); i++ )
229 	{
230 		pNew = p->aFacs.GetObject( i )->CreateObject( rClass );
231 		if( pNew )
232 			break;
233 	}
234 #ifdef DBG_UTIL
235 	if( !pNew )
236 	{
237 		ByteString aMsg( "SBX: Keine Factory fuer Objektklasse " );
238 		ByteString aClassStr( (const UniString&)rClass, RTL_TEXTENCODING_ASCII_US );
239 		aMsg += aClassStr;
240 		DbgError( (const char*)aMsg.GetBuffer() );
241 	}
242 #endif
243 	return pNew;
244 }
245 
246 static sal_Bool bStaticEnableBroadcasting = sal_True;
247 
248 // Sbx-Loesung als Ersatz fuer SfxBroadcaster::Enable()
249 void SbxBase::StaticEnableBroadcasting( sal_Bool bEnable )
250 {
251 	bStaticEnableBroadcasting = bEnable;
252 }
253 
254 sal_Bool SbxBase::StaticIsEnabledBroadcasting( void )
255 {
256 	return bStaticEnableBroadcasting;
257 }
258 
259 
260 SbxBase* SbxBase::Load( SvStream& rStrm )
261 {
262 	sal_uInt16 nSbxId, nFlags, nVer;
263 	sal_uInt32 nCreator, nSize;
264 	rStrm >> nCreator >> nSbxId >> nFlags >> nVer;
265 
266 	// Eine Dummheit meinerseits korrigieren:
267 	if( nFlags & SBX_RESERVED )
268 		nFlags = ( nFlags & ~SBX_RESERVED ) | SBX_GBLSEARCH;
269 
270 	sal_uIntPtr nOldPos = rStrm.Tell();
271 	rStrm >> nSize;
272 	SbxBase* p = Create( nSbxId, nCreator );
273 	if( p )
274 	{
275 		p->nFlags = nFlags;
276 		if( p->LoadData( rStrm, nVer ) )
277 		{
278 			sal_uIntPtr nNewPos = rStrm.Tell();
279 			nOldPos += nSize;
280 			DBG_ASSERT( nOldPos >= nNewPos, "SBX: Zu viele Daten eingelesen" );
281 			if( nOldPos != nNewPos )
282 				rStrm.Seek( nOldPos );
283 			if( !p->LoadCompleted() )
284 			{
285 				// Loeschen des Objekts
286 				SbxBaseRef aRef( p );
287 				p = NULL;
288 			}
289 		}
290 		else
291 		{
292 			rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR );
293 			// Loeschen des Objekts
294 			SbxBaseRef aRef( p );
295 			p = NULL;
296 		}
297 	}
298 	else
299 		rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR );
300 	return p;
301 }
302 
303 // Sbx-Objekt im Stream ueberspringen
304 void SbxBase::Skip( SvStream& rStrm )
305 {
306 	sal_uInt16 nSbxId, nFlags, nVer;
307 	sal_uInt32 nCreator, nSize;
308 	rStrm >> nCreator >> nSbxId >> nFlags >> nVer;
309 
310 	sal_uIntPtr nStartPos = rStrm.Tell();
311 	rStrm >> nSize;
312 
313 	rStrm.Seek( nStartPos + nSize );
314 }
315 
316 sal_Bool SbxBase::Store( SvStream& rStrm )
317 {
318 	DBG_CHKTHIS( SbxBase, 0 );
319 	if( !( nFlags & SBX_DONTSTORE ) )
320 	{
321 		rStrm << (sal_uInt32) GetCreator()
322 			  << (sal_uInt16) GetSbxId()
323 			  << (sal_uInt16) GetFlags()
324 			  << (sal_uInt16) GetVersion();
325 		sal_uIntPtr nOldPos = rStrm.Tell();
326 		rStrm << (sal_uInt32) 0L;
327 		sal_Bool bRes = StoreData( rStrm );
328 		sal_uIntPtr nNewPos = rStrm.Tell();
329 		rStrm.Seek( nOldPos );
330 		rStrm << (sal_uInt32) ( nNewPos - nOldPos );
331 		rStrm.Seek( nNewPos );
332 		if( rStrm.GetError() != SVSTREAM_OK )
333 			bRes = sal_False;
334 		if( bRes )
335 			bRes = StoreCompleted();
336 		return bRes;
337 	}
338 	else
339 		return sal_True;
340 }
341 
342 sal_Bool SbxBase::LoadData( SvStream&, sal_uInt16 )
343 {
344 	DBG_CHKTHIS( SbxBase, 0 );
345 	return sal_False;
346 }
347 
348 sal_Bool SbxBase::StoreData( SvStream& ) const
349 {
350 	DBG_CHKTHIS( SbxBase, 0 );
351 	return sal_False;
352 }
353 
354 sal_Bool SbxBase::LoadPrivateData( SvStream&, sal_uInt16 )
355 {
356 	DBG_CHKTHIS( SbxBase, 0 );
357 	return sal_True;
358 }
359 
360 sal_Bool SbxBase::StorePrivateData( SvStream& ) const
361 {
362 	DBG_CHKTHIS( SbxBase, 0 );
363 	return sal_True;
364 }
365 
366 sal_Bool SbxBase::LoadCompleted()
367 {
368 	DBG_CHKTHIS( SbxBase, 0 );
369 	return sal_True;
370 }
371 
372 sal_Bool SbxBase::StoreCompleted()
373 {
374 	DBG_CHKTHIS( SbxBase, 0 );
375 	return sal_True;
376 }
377 
378 //////////////////////////////// SbxFactory ////////////////////////////////
379 
380 SbxBase* SbxFactory::Create( sal_uInt16, sal_uInt32 )
381 {
382 	return NULL;
383 }
384 
385 SbxObject* SbxFactory::CreateObject( const XubString& )
386 {
387 	return NULL;
388 }
389 
390 ///////////////////////////////// SbxInfo //////////////////////////////////
391 
392 SbxInfo::~SbxInfo()
393 {}
394 
395 void SbxInfo::AddParam
396 		( const XubString& rName, SbxDataType eType, sal_uInt16 nFlags )
397 {
398 	const SbxParamInfo* p = new SbxParamInfo( rName, eType, nFlags );
399 	aParams.Insert( p, aParams.Count() );
400 }
401 
402 void SbxInfo::AddParam( const SbxParamInfo& r )
403 {
404 	const SbxParamInfo* p = new SbxParamInfo
405 		( r.aName, r.eType, r.nFlags, r.aTypeRef );
406 	aParams.Insert( p, aParams.Count() );
407 }
408 
409 const SbxParamInfo* SbxInfo::GetParam( sal_uInt16 n ) const
410 {
411 	if( n < 1 || n > aParams.Count() )
412 		return NULL;
413 	else
414 		return aParams.GetObject( n-1 );
415 }
416 
417 sal_Bool SbxInfo::LoadData( SvStream& rStrm, sal_uInt16 nVer )
418 {
419 	aParams.Remove( 0, aParams.Count() );
420 	sal_uInt16 nParam;
421 	rStrm.ReadByteString( aComment, RTL_TEXTENCODING_ASCII_US );
422 	rStrm.ReadByteString( aHelpFile, RTL_TEXTENCODING_ASCII_US );
423 	rStrm >> nHelpId >> nParam;
424 	while( nParam-- )
425 	{
426 		XubString aName;
427 		sal_uInt16 nType, nFlags;
428 		sal_uInt32 nUserData = 0;
429 		rStrm.ReadByteString( aName, RTL_TEXTENCODING_ASCII_US );
430 		rStrm >> nType >> nFlags;
431 		if( nVer > 1 )
432 			rStrm >> nUserData;
433 		AddParam( aName, (SbxDataType) nType, nFlags );
434 		SbxParamInfo* p = aParams.GetObject( aParams.Count() - 1 );
435 		p->nUserData = nUserData;
436 	}
437 	return sal_True;
438 }
439 
440 sal_Bool SbxInfo::StoreData( SvStream& rStrm ) const
441 {
442 	rStrm.WriteByteString( aComment, RTL_TEXTENCODING_ASCII_US );
443 	rStrm.WriteByteString( aHelpFile, RTL_TEXTENCODING_ASCII_US );
444 	rStrm << nHelpId << aParams.Count();
445 	for( sal_uInt16 i = 0; i < aParams.Count(); i++ )
446 	{
447 		SbxParamInfo* p = aParams.GetObject( i );
448 		rStrm.WriteByteString( p->aName, RTL_TEXTENCODING_ASCII_US );
449 		rStrm << (sal_uInt16) p->eType
450 			  << (sal_uInt16) p->nFlags
451 			  << (sal_uInt32) p->nUserData;
452 	}
453 	return sal_True;
454 }
455 
456