xref: /trunk/main/basic/source/sbx/sbxbase.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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