Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / basic / source / sbx / sbxbase.cxx
blobe56172275a04a67ce145886e7e059c5d00ab2096
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <tools/shl.hxx>
21 #include <tools/stream.hxx>
23 #include <basic/sbx.hxx>
24 #include <basic/sbxfac.hxx>
25 #include <basic/sbxbase.hxx>
27 #include <rtl/instance.hxx>
28 #include <rtl/ustring.hxx>
29 #include <boost/foreach.hpp>
31 // AppData-Structure for SBX:
33 TYPEINIT0(SbxBase)
35 namespace
37 class theSbxAppData : public rtl::Static<SbxAppData, theSbxAppData> {};
40 SbxAppData& GetSbxData_Impl()
42 return theSbxAppData::get();
45 SbxAppData::~SbxAppData()
47 delete pBasicFormater;
51 //////////////////////////////// SbxBase /////////////////////////////////
53 DBG_NAME(SbxBase);
55 SbxBase::SbxBase()
57 DBG_CTOR( SbxBase, 0 );
58 nFlags = SBX_READWRITE;
61 SbxBase::SbxBase( const SbxBase& r )
62 : SvRefBase( r )
64 DBG_CTOR( SbxBase, 0 );
65 nFlags = r.nFlags;
68 SbxBase::~SbxBase()
70 DBG_DTOR(SbxBase,0);
73 SbxBase& SbxBase::operator=( const SbxBase& r )
75 DBG_CHKTHIS( SbxBase, 0 );
76 nFlags = r.nFlags;
77 return *this;
80 SbxDataType SbxBase::GetType() const
82 DBG_CHKTHIS( SbxBase, 0 );
83 return SbxEMPTY;
86 SbxClassType SbxBase::GetClass() const
88 DBG_CHKTHIS( SbxBase, 0 );
89 return SbxCLASS_DONTCARE;
92 void SbxBase::Clear()
94 DBG_CHKTHIS( SbxBase, 0 );
97 sal_Bool SbxBase::IsFixed() const
99 DBG_CHKTHIS( SbxBase, 0 );
100 return IsSet( SBX_FIXED );
103 void SbxBase::SetModified( sal_Bool b )
105 DBG_CHKTHIS( SbxBase, 0 );
106 if( IsSet( SBX_NO_MODIFY ) )
107 return;
108 if( b )
109 SetFlag( SBX_MODIFIED );
110 else
111 ResetFlag( SBX_MODIFIED );
114 SbxError SbxBase::GetError()
116 return GetSbxData_Impl().eSbxError;
119 void SbxBase::SetError( SbxError e )
121 SbxAppData& r = GetSbxData_Impl();
122 if( e && r.eSbxError == SbxERR_OK )
123 r.eSbxError = e;
126 sal_Bool SbxBase::IsError()
128 return sal_Bool( GetSbxData_Impl().eSbxError != SbxERR_OK );
131 void SbxBase::ResetError()
133 GetSbxData_Impl().eSbxError = SbxERR_OK;
136 void SbxBase::AddFactory( SbxFactory* pFac )
138 SbxAppData& r = GetSbxData_Impl();
140 // From 1996-03-06: take the HandleLast-Flag into account
141 sal_uInt16 nPos = r.aFacs.size(); // Insert position
142 if( !pFac->IsHandleLast() ) // Only if not self HandleLast
144 // Rank new factory in front of factories with HandleLast
145 while( nPos > 0 &&
146 r.aFacs[ nPos-1 ].IsHandleLast() )
147 nPos--;
149 r.aFacs.insert( r.aFacs.begin() + nPos, pFac );
152 void SbxBase::RemoveFactory( SbxFactory* pFac )
154 SbxAppData& r = GetSbxData_Impl();
155 for(SbxFacs::iterator it = r.aFacs.begin(); it != r.aFacs.end(); ++it)
157 if( &(*it) == pFac )
159 r.aFacs.release( it ).release(); break;
165 SbxBase* SbxBase::Create( sal_uInt16 nSbxId, sal_uInt32 nCreator )
167 // #91626: Hack to skip old Basic dialogs
168 // Problem: There does not exist a factory any more,
169 // so we have to create a dummy SbxVariable instead
170 if( nSbxId == 0x65 ) // Dialog Id
171 return new SbxVariable;
173 rtl::OUString aEmptyStr;
174 if( nCreator == SBXCR_SBX )
175 switch( nSbxId )
177 case SBXID_VALUE: return new SbxValue;
178 case SBXID_VARIABLE: return new SbxVariable;
179 case SBXID_ARRAY: return new SbxArray;
180 case SBXID_DIMARRAY: return new SbxDimArray;
181 case SBXID_OBJECT: return new SbxObject( aEmptyStr );
182 case SBXID_COLLECTION: return new SbxCollection( aEmptyStr );
183 case SBXID_FIXCOLLECTION:
184 return new SbxStdCollection( aEmptyStr, aEmptyStr );
185 case SBXID_METHOD: return new SbxMethod( aEmptyStr, SbxEMPTY );
186 case SBXID_PROPERTY: return new SbxProperty( aEmptyStr, SbxEMPTY );
188 // Unknown type: go over the factories!
189 SbxAppData& r = GetSbxData_Impl();
190 SbxBase* pNew = NULL;
191 BOOST_FOREACH(SbxFactory& rFac, r.aFacs)
193 pNew = rFac.Create( nSbxId, nCreator );
194 if( pNew )
195 break;
197 SAL_WARN_IF(!pNew, "basic", "No factory for SBX ID " << nSbxId);
198 return pNew;
201 SbxObject* SbxBase::CreateObject( const rtl::OUString& rClass )
203 SbxAppData& r = GetSbxData_Impl();
204 SbxObject* pNew = NULL;
205 BOOST_FOREACH(SbxFactory& rFac, r.aFacs)
207 pNew = rFac.CreateObject( rClass );
208 if( pNew )
209 break;
211 SAL_WARN_IF(!pNew, "basic", "No factory for object class " << rClass);
212 return pNew;
215 SbxBase* SbxBase::Load( SvStream& rStrm )
217 sal_uInt16 nSbxId, nFlags, nVer;
218 sal_uInt32 nCreator, nSize;
219 rStrm >> nCreator >> nSbxId >> nFlags >> nVer;
221 // Correcting a foolishness of mine:
222 if( nFlags & SBX_RESERVED )
223 nFlags = ( nFlags & ~SBX_RESERVED ) | SBX_GBLSEARCH;
225 sal_uIntPtr nOldPos = rStrm.Tell();
226 rStrm >> nSize;
227 SbxBase* p = Create( nSbxId, nCreator );
228 if( p )
230 p->nFlags = nFlags;
231 if( p->LoadData( rStrm, nVer ) )
233 sal_uIntPtr nNewPos = rStrm.Tell();
234 nOldPos += nSize;
235 DBG_ASSERT( nOldPos >= nNewPos, "SBX: Zu viele Daten eingelesen" );
236 if( nOldPos != nNewPos )
237 rStrm.Seek( nOldPos );
238 if( !p->LoadCompleted() )
240 // Deleting of the object
241 SbxBaseRef aRef( p );
242 p = NULL;
245 else
247 rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR );
248 // Deleting of the object
249 SbxBaseRef aRef( p );
250 p = NULL;
253 else
254 rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR );
255 return p;
258 // Skip the Sbx-Object inside the stream
259 void SbxBase::Skip( SvStream& rStrm )
261 sal_uInt16 nSbxId, nFlags, nVer;
262 sal_uInt32 nCreator, nSize;
263 rStrm >> nCreator >> nSbxId >> nFlags >> nVer;
265 sal_uIntPtr nStartPos = rStrm.Tell();
266 rStrm >> nSize;
268 rStrm.Seek( nStartPos + nSize );
271 sal_Bool SbxBase::Store( SvStream& rStrm )
273 DBG_CHKTHIS( SbxBase, 0 );
274 if( !( nFlags & SBX_DONTSTORE ) )
276 rStrm << (sal_uInt32) GetCreator()
277 << (sal_uInt16) GetSbxId()
278 << (sal_uInt16) GetFlags()
279 << (sal_uInt16) GetVersion();
280 sal_uIntPtr nOldPos = rStrm.Tell();
281 rStrm << (sal_uInt32) 0L;
282 sal_Bool bRes = StoreData( rStrm );
283 sal_uIntPtr nNewPos = rStrm.Tell();
284 rStrm.Seek( nOldPos );
285 rStrm << (sal_uInt32) ( nNewPos - nOldPos );
286 rStrm.Seek( nNewPos );
287 if( rStrm.GetError() != SVSTREAM_OK )
288 bRes = sal_False;
289 if( bRes )
290 bRes = StoreCompleted();
291 return bRes;
293 else
294 return sal_True;
297 sal_Bool SbxBase::LoadData( SvStream&, sal_uInt16 )
299 DBG_CHKTHIS( SbxBase, 0 );
300 return sal_False;
303 sal_Bool SbxBase::StoreData( SvStream& ) const
305 DBG_CHKTHIS( SbxBase, 0 );
306 return sal_False;
309 sal_Bool SbxBase::LoadPrivateData( SvStream&, sal_uInt16 )
311 DBG_CHKTHIS( SbxBase, 0 );
312 return sal_True;
315 sal_Bool SbxBase::StorePrivateData( SvStream& ) const
317 DBG_CHKTHIS( SbxBase, 0 );
318 return sal_True;
321 sal_Bool SbxBase::LoadCompleted()
323 DBG_CHKTHIS( SbxBase, 0 );
324 return sal_True;
327 sal_Bool SbxBase::StoreCompleted()
329 DBG_CHKTHIS( SbxBase, 0 );
330 return sal_True;
333 //////////////////////////////// SbxFactory ////////////////////////////////
335 SbxFactory::~SbxFactory()
339 SbxBase* SbxFactory::Create( sal_uInt16, sal_uInt32 )
341 return NULL;
344 SbxObject* SbxFactory::CreateObject( const rtl::OUString& )
346 return NULL;
349 ///////////////////////////////// SbxInfo //////////////////////////////////
351 SbxInfo::~SbxInfo()
354 void SbxInfo::AddParam(const rtl::OUString& rName, SbxDataType eType, sal_uInt16 nFlags)
356 aParams.push_back(new SbxParamInfo(rName, eType, nFlags));
359 const SbxParamInfo* SbxInfo::GetParam( sal_uInt16 n ) const
361 if( n < 1 || n > aParams.size() )
362 return NULL;
363 else
364 return &(aParams[n - 1]);
367 sal_Bool SbxInfo::LoadData( SvStream& rStrm, sal_uInt16 nVer )
369 aParams.clear();
370 sal_uInt16 nParam;
371 aComment = read_lenPrefixed_uInt8s_ToOUString<sal_uInt16>(rStrm,
372 RTL_TEXTENCODING_ASCII_US);
373 aHelpFile = read_lenPrefixed_uInt8s_ToOUString<sal_uInt16>(rStrm,
374 RTL_TEXTENCODING_ASCII_US);
375 rStrm >> nHelpId >> nParam;
376 while( nParam-- )
378 sal_uInt16 nType, nFlags;
379 sal_uInt32 nUserData = 0;
380 rtl::OUString aName = read_lenPrefixed_uInt8s_ToOUString<sal_uInt16>(rStrm,
381 RTL_TEXTENCODING_ASCII_US);
382 rStrm >> nType >> nFlags;
383 if( nVer > 1 )
384 rStrm >> nUserData;
385 AddParam( aName, (SbxDataType) nType, nFlags );
386 SbxParamInfo& p(aParams.back());
387 p.nUserData = nUserData;
389 return sal_True;
392 sal_Bool SbxInfo::StoreData( SvStream& rStrm ) const
394 write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(rStrm, aComment,
395 RTL_TEXTENCODING_ASCII_US );
396 write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(rStrm, aHelpFile,
397 RTL_TEXTENCODING_ASCII_US);
398 rStrm << nHelpId << static_cast<sal_uInt16>(aParams.size());
399 for(SbxParams::const_iterator i = aParams.begin(); i != aParams.end(); ++i)
401 write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(rStrm, i->aName,
402 RTL_TEXTENCODING_ASCII_US);
403 rStrm << (sal_uInt16) i->eType
404 << (sal_uInt16) i->nFlags
405 << (sal_uInt32) i->nUserData;
407 return sal_True;
410 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */