Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / basic / source / sbx / sbxbase.cxx
blobd1b17d4fa2884eb3a01e243be8ae61223976832c
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 <memory>
21 #include <tools/debug.hxx>
22 #include <tools/stream.hxx>
23 #include <vcl/svapp.hxx>
25 #include <basic/sbx.hxx>
26 #include <basic/sbxfac.hxx>
27 #include <basic/sbxform.hxx>
28 #include <basic/sbxmeth.hxx>
29 #include <basic/sbxprop.hxx>
30 #include <sbxbase.hxx>
32 #include <rtl/ustring.hxx>
33 #include <sal/log.hxx>
35 // AppData-Structure for SBX:
38 SbxAppData::SbxAppData()
39 : eErrCode(ERRCODE_NONE)
40 , eBasicFormaterLangType(LANGUAGE_DONTKNOW)
44 SbxAppData::~SbxAppData()
46 SolarMutexGuard g;
48 pBasicFormater.reset();
49 m_Factories.clear();
52 SbxBase::SbxBase()
54 nFlags = SbxFlagBits::ReadWrite;
57 SbxBase::SbxBase( const SbxBase& r )
58 : SvRefBase( r )
60 nFlags = r.nFlags;
63 SbxBase::~SbxBase()
67 SbxBase& SbxBase::operator=( const SbxBase& r )
69 nFlags = r.nFlags;
70 return *this;
73 SbxDataType SbxBase::GetType() const
75 return SbxEMPTY;
78 bool SbxBase::IsFixed() const
80 return IsSet( SbxFlagBits::Fixed );
83 void SbxBase::SetModified( bool b )
85 if( IsSet( SbxFlagBits::NoModify ) )
86 return;
87 if( b )
88 SetFlag( SbxFlagBits::Modified );
89 else
90 ResetFlag( SbxFlagBits::Modified );
93 ErrCode const & SbxBase::GetError()
95 return GetSbxData_Impl().eErrCode;
98 void SbxBase::SetError( ErrCode e )
100 SbxAppData& r = GetSbxData_Impl();
101 if( e && r.eErrCode == ERRCODE_NONE )
102 r.eErrCode = e;
105 bool SbxBase::IsError()
107 return GetSbxData_Impl().eErrCode != ERRCODE_NONE;
110 void SbxBase::ResetError()
112 GetSbxData_Impl().eErrCode = ERRCODE_NONE;
115 void SbxBase::AddFactory( SbxFactory* pFac )
117 GetSbxData_Impl().m_Factories.emplace_back(pFac);
120 void SbxBase::RemoveFactory( SbxFactory const * pFac )
122 SbxAppData& r = GetSbxData_Impl();
123 auto it = std::find_if(r.m_Factories.begin(), r.m_Factories.end(),
124 [&pFac](const std::unique_ptr<SbxFactory>& rxFactory) { return rxFactory.get() == pFac; });
125 if (it != r.m_Factories.end())
127 std::unique_ptr<SbxFactory> tmp(std::move(*it));
128 r.m_Factories.erase( it );
129 (void)tmp.release();
134 SbxBase* SbxBase::Create( sal_uInt16 nSbxId, sal_uInt32 nCreator )
136 // #91626: Hack to skip old Basic dialogs
137 // Problem: There does not exist a factory any more,
138 // so we have to create a dummy SbxVariable instead
139 if( nSbxId == 0x65 ) // Dialog Id
140 return new SbxVariable;
142 if( nCreator == SBXCR_SBX )
143 switch( nSbxId )
145 case SBXID_VALUE: return new SbxValue;
146 case SBXID_VARIABLE: return new SbxVariable;
147 case SBXID_ARRAY: return new SbxArray;
148 case SBXID_DIMARRAY: return new SbxDimArray;
149 case SBXID_OBJECT: return new SbxObject( "" );
150 case SBXID_COLLECTION: return new SbxCollection;
151 case SBXID_FIXCOLLECTION:
152 return new SbxStdCollection;
153 case SBXID_METHOD: return new SbxMethod( "", SbxEMPTY );
154 case SBXID_PROPERTY: return new SbxProperty( "", SbxEMPTY );
156 // Unknown type: go over the factories!
157 SbxAppData& r = GetSbxData_Impl();
158 SbxBase* pNew = nullptr;
159 for (auto const& rpFac : r.m_Factories)
161 pNew = rpFac->Create( nSbxId, nCreator );
162 if( pNew )
163 break;
165 SAL_WARN_IF(!pNew, "basic", "No factory for SBX ID " << nSbxId);
166 return pNew;
169 SbxObject* SbxBase::CreateObject( const OUString& rClass )
171 SbxAppData& r = GetSbxData_Impl();
172 SbxObject* pNew = nullptr;
173 for (auto const& rpFac : r.m_Factories)
175 pNew = rpFac->CreateObject( rClass );
176 if( pNew )
177 break;
179 SAL_WARN_IF(!pNew, "basic", "No factory for object class " << rClass);
180 return pNew;
183 SbxBase* SbxBase::Load( SvStream& rStrm )
185 sal_uInt16 nSbxId, nFlagsTmp, nVer;
186 sal_uInt32 nCreator, nSize;
187 rStrm.ReadUInt32( nCreator ).ReadUInt16( nSbxId ).ReadUInt16( nFlagsTmp ).ReadUInt16( nVer );
188 SbxFlagBits nFlags = static_cast<SbxFlagBits>(nFlagsTmp);
190 // Correcting a foolishness of mine:
191 if( nFlags & SbxFlagBits::Reserved )
192 nFlags = ( nFlags & ~SbxFlagBits::Reserved ) | SbxFlagBits::GlobalSearch;
194 sal_uInt64 nOldPos = rStrm.Tell();
195 rStrm.ReadUInt32( nSize );
196 SbxBase* p = Create( nSbxId, nCreator );
197 if( p )
199 p->nFlags = nFlags;
200 if( p->LoadData( rStrm, nVer ) )
202 sal_uInt64 const nNewPos = rStrm.Tell();
203 nOldPos += nSize;
204 DBG_ASSERT( nOldPos >= nNewPos, "SBX: Too much data loaded" );
205 if( nOldPos != nNewPos )
206 rStrm.Seek( nOldPos );
207 if( !p->LoadCompleted() )
209 // Deleting of the object
210 SbxBaseRef aRef( p );
211 p = nullptr;
214 else
216 rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR );
217 // Deleting of the object
218 SbxBaseRef aRef( p );
219 p = nullptr;
222 else
223 rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR );
224 return p;
227 bool SbxBase::Store( SvStream& rStrm )
229 if( ( nFlags & SbxFlagBits::DontStore ) == SbxFlagBits::NONE )
231 rStrm.WriteUInt32( SBXCR_SBX )
232 .WriteUInt16( GetSbxId() )
233 .WriteUInt16( static_cast<sal_uInt16>(GetFlags()) )
234 .WriteUInt16( GetVersion() );
235 sal_uInt64 const nOldPos = rStrm.Tell();
236 rStrm.WriteUInt32( 0 );
237 bool bRes = StoreData( rStrm );
238 sal_uInt64 const nNewPos = rStrm.Tell();
239 rStrm.Seek( nOldPos );
240 rStrm.WriteUInt32( nNewPos - nOldPos );
241 rStrm.Seek( nNewPos );
242 if( rStrm.GetError() != ERRCODE_NONE )
243 bRes = false;
244 if( bRes )
245 bRes = true;
246 return bRes;
248 else
249 return true;
252 bool SbxBase::LoadCompleted()
254 return true;
257 //////////////////////////////// SbxFactory
259 SbxFactory::~SbxFactory()
263 SbxBase* SbxFactory::Create( sal_uInt16, sal_uInt32 )
265 return nullptr;
268 SbxObject* SbxFactory::CreateObject( const OUString& )
270 return nullptr;
273 ///////////////////////////////// SbxInfo
275 SbxInfo::~SbxInfo()
278 void SbxInfo::AddParam(const OUString& rName, SbxDataType eType, SbxFlagBits nFlags)
280 m_Params.push_back(std::make_unique<SbxParamInfo>(rName, eType, nFlags));
283 const SbxParamInfo* SbxInfo::GetParam( sal_uInt16 n ) const
285 if (n < 1 || n > m_Params.size())
286 return nullptr;
287 else
288 return m_Params[n - 1].get();
291 void SbxInfo::LoadData( SvStream& rStrm, sal_uInt16 nVer )
293 m_Params.clear();
294 sal_uInt16 nParam;
295 aComment = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
296 RTL_TEXTENCODING_ASCII_US);
297 aHelpFile = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
298 RTL_TEXTENCODING_ASCII_US);
299 rStrm.ReadUInt32( nHelpId ).ReadUInt16( nParam );
300 while( nParam-- )
302 sal_uInt16 nType, nFlagsTmp;
303 sal_uInt32 nUserData = 0;
304 OUString aName = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
305 RTL_TEXTENCODING_ASCII_US);
306 rStrm.ReadUInt16( nType ).ReadUInt16( nFlagsTmp );
307 SbxFlagBits nFlags = static_cast<SbxFlagBits>(nFlagsTmp);
308 if( nVer > 1 )
309 rStrm.ReadUInt32( nUserData );
310 AddParam( aName, static_cast<SbxDataType>(nType), nFlags );
311 SbxParamInfo& p(*m_Params.back());
312 p.nUserData = nUserData;
316 void SbxInfo::StoreData( SvStream& rStrm ) const
318 write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, aComment,
319 RTL_TEXTENCODING_ASCII_US );
320 write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, aHelpFile,
321 RTL_TEXTENCODING_ASCII_US);
322 rStrm.WriteUInt32( nHelpId ).WriteUInt16( m_Params.size() );
323 for (auto const& i : m_Params)
325 write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, i->aName,
326 RTL_TEXTENCODING_ASCII_US);
327 rStrm.WriteUInt16( i->eType )
328 .WriteUInt16( static_cast<sal_uInt16>(i->nFlags) )
329 .WriteUInt32( i->nUserData );
333 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */