tdf#164627 docx export: consolidate getWordCompatibilityMode()
[LibreOffice.git] / basic / source / sbx / sbxbase.cxx
blob1d34683aea196224270e0a20d615a579feb65724
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 <sbxfac.hxx>
27 #include <sbxform.hxx>
28 #include <basic/sbxmeth.hxx>
29 #include <sbxprop.hxx>
30 #include <sbxbase.hxx>
32 #include <rtl/ustring.hxx>
33 #include <sal/log.hxx>
34 #include <filefmt.hxx>
36 // AppData-Structure for SBX:
39 SbxAppData::SbxAppData()
40 : eErrCode(ERRCODE_NONE)
41 , aErrorMsg(OUString())
42 , eBasicFormaterLangType(LANGUAGE_DONTKNOW)
46 SbxAppData::~SbxAppData()
48 SolarMutexGuard g;
50 pBasicFormater.reset();
51 // basic manager repository must be destroyed before factories
52 mrImplRepository.clear();
55 SbxBase::SbxBase()
57 nFlags = SbxFlagBits::ReadWrite;
60 SbxBase::SbxBase(const SbxBase& r) = default;
62 SbxBase::~SbxBase()
66 SbxBase& SbxBase::operator=( const SbxBase& r )
68 nFlags = r.nFlags;
69 return *this;
72 SbxDataType SbxBase::GetType() const
74 return SbxEMPTY;
77 bool SbxBase::IsFixed() const
79 return IsSet( SbxFlagBits::Fixed );
82 void SbxBase::SetModified( bool b )
84 if( IsSet( SbxFlagBits::NoModify ) )
85 return;
86 if( b )
87 SetFlag( SbxFlagBits::Modified );
88 else
89 ResetFlag( SbxFlagBits::Modified );
92 ErrCode const & SbxBase::GetError()
94 return GetSbxData_Impl().eErrCode;
97 OUString const & SbxBase::GetErrorMsg()
99 return GetSbxData_Impl().aErrorMsg;
102 void SbxBase::SetError(ErrCode e, const OUString& rMsg)
104 SbxAppData& r = GetSbxData_Impl();
105 if (e && r.eErrCode == ERRCODE_NONE)
107 r.eErrCode = e;
108 r.aErrorMsg = rMsg;
112 void SbxBase::SetError( ErrCode e )
114 SbxAppData& r = GetSbxData_Impl();
115 if( e && r.eErrCode == ERRCODE_NONE )
116 r.eErrCode = e;
119 bool SbxBase::IsError()
121 return GetSbxData_Impl().eErrCode != ERRCODE_NONE;
124 void SbxBase::ResetError()
126 GetSbxData_Impl().eErrCode = ERRCODE_NONE;
127 GetSbxData_Impl().aErrorMsg = OUString();
130 void SbxBase::AddFactory( SbxFactory* pFac )
132 GetSbxData_Impl().m_Factories.emplace_back(pFac);
135 void SbxBase::RemoveFactory( SbxFactory const * pFac )
137 if (!IsSbxData_Impl())
138 return;
139 SbxAppData& r = GetSbxData_Impl();
140 auto it = std::find(r.m_Factories.begin(), r.m_Factories.end(), pFac);
141 if (it != r.m_Factories.end())
142 r.m_Factories.erase( it );
146 SbxBaseRef SbxBase::Create( sal_uInt16 nSbxId, sal_uInt32 nCreator )
148 // #91626: Hack to skip old Basic dialogs
149 // Problem: There does not exist a factory any more,
150 // so we have to create a dummy SbxVariable instead
151 if( nSbxId == 0x65 ) // Dialog Id
152 return new SbxVariable;
154 if( nCreator == SBXCR_SBX )
155 switch( nSbxId )
157 case SBXID_VALUE: return new SbxValue;
158 case SBXID_VARIABLE: return new SbxVariable;
159 case SBXID_ARRAY: return new SbxArray;
160 case SBXID_DIMARRAY: return new SbxDimArray;
161 case SBXID_OBJECT: return new SbxObject( u""_ustr );
162 case SBXID_COLLECTION: return new SbxCollection;
163 case SBXID_FIXCOLLECTION:
164 return new SbxStdCollection;
165 case SBXID_METHOD: return new SbxMethod( u""_ustr, SbxEMPTY );
166 case SBXID_PROPERTY: return new SbxProperty( u""_ustr, SbxEMPTY );
168 // Unknown type: go over the factories!
169 SbxAppData& r = GetSbxData_Impl();
170 SbxBaseRef pNew;
171 for (auto const& rpFac : r.m_Factories)
173 pNew = rpFac->Create( nSbxId, nCreator );
174 if( pNew )
175 break;
177 SAL_WARN_IF(!pNew, "basic", "No factory for SBX ID " << nSbxId);
178 return pNew;
181 SbxObjectRef SbxBase::CreateObject( const OUString& rClass )
183 SbxAppData& r = GetSbxData_Impl();
184 SbxObjectRef pNew;
185 for (auto const& rpFac : r.m_Factories)
187 pNew = rpFac->CreateObject( rClass );
188 if( pNew )
189 break;
191 SAL_WARN_IF(!pNew, "basic", "No factory for object class " << rClass);
192 return pNew;
195 namespace {
197 // coverity[ -taint_source ]
198 [[nodiscard]] SbxFlagBits CorrectFlags(SbxFlagBits nFlags)
200 // Correcting a foolishness of mine:
201 if (nFlags & SbxFlagBits::Reserved)
202 nFlags |= SbxFlagBits::GlobalSearch;
203 return nFlags & ~SbxFlagBits::Reserved;
208 SbxBaseRef SbxBase::Load( SvStream& rStrm )
210 sal_uInt16 nSbxId(0), nFlagsTmp(0), nVer(0);
211 sal_uInt32 nCreator(0), nSize(0);
212 rStrm.ReadUInt32( nCreator ).ReadUInt16( nSbxId ).ReadUInt16( nFlagsTmp ).ReadUInt16( nVer );
213 SbxFlagBits nFlags = CorrectFlags(static_cast<SbxFlagBits>(nFlagsTmp));
215 sal_uInt64 nOldPos = rStrm.Tell();
216 rStrm.ReadUInt32( nSize );
217 SbxBaseRef p = Create( nSbxId, nCreator );
218 if( p )
220 p->nFlags = nFlags;
221 if( p->LoadData( rStrm, nVer ) )
223 sal_uInt64 const nNewPos = rStrm.Tell();
224 nOldPos += nSize;
225 DBG_ASSERT( nOldPos >= nNewPos, "SBX: Too much data loaded" );
226 if( nOldPos != nNewPos )
227 rStrm.Seek( nOldPos );
228 if( !p->LoadCompleted() )
230 // Deleting of the object
231 SbxBaseRef xDeleteRef( p );
232 p = nullptr;
235 else
237 rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR );
238 // Deleting of the object
239 SbxBaseRef xDeleteRef( p );
240 p = nullptr;
243 else
244 rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR );
245 return p;
248 std::pair<bool, sal_uInt32> SbxBase::Store( SvStream& rStrm )
250 if( ( nFlags & SbxFlagBits::DontStore ) == SbxFlagBits::NONE )
252 rStrm.WriteUInt32( SBXCR_SBX )
253 .WriteUInt16( GetSbxId() )
254 .WriteUInt16( static_cast<sal_uInt16>(GetFlags()) )
255 .WriteUInt16( GetVersion() );
256 sal_uInt64 const nOldPos = rStrm.Tell();
257 rStrm.WriteUInt32( 0 );
258 auto [bRes, nVersion] = StoreData(rStrm);
259 sal_uInt64 const nNewPos = rStrm.Tell();
260 rStrm.Seek( nOldPos );
261 rStrm.WriteUInt32( nNewPos - nOldPos );
262 rStrm.Seek( nNewPos );
263 if( rStrm.GetError() != ERRCODE_NONE )
264 bRes = false;
265 if( bRes )
266 bRes = true;
267 return { bRes, nVersion };
269 else
270 return { true, B_IMG_VERSION_12 };
273 bool SbxBase::LoadCompleted()
275 return true;
278 //////////////////////////////// SbxFactory
280 SbxFactory::~SbxFactory()
284 SbxBaseRef SbxFactory::Create( sal_uInt16, sal_uInt32 )
286 return nullptr;
289 SbxObjectRef SbxFactory::CreateObject( const OUString& )
291 return nullptr;
294 ///////////////////////////////// SbxInfo
296 SbxInfo::~SbxInfo()
299 void SbxInfo::AddParam(const OUString& rName, SbxDataType eType, SbxFlagBits nFlags)
301 m_Params.push_back(std::make_unique<SbxParamInfo>(rName, eType, nFlags));
304 const SbxParamInfo* SbxInfo::GetParam( sal_uInt16 n ) const
306 if (n < 1 || n > m_Params.size())
307 return nullptr;
308 else
309 return m_Params[n - 1].get();
312 void SbxInfo::LoadData( SvStream& rStrm, sal_uInt16 nVer )
314 m_Params.clear();
315 sal_uInt16 nParam;
316 aComment = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
317 RTL_TEXTENCODING_ASCII_US);
318 aHelpFile = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
319 RTL_TEXTENCODING_ASCII_US);
320 rStrm.ReadUInt32( nHelpId ).ReadUInt16( nParam );
321 while( nParam-- )
323 sal_uInt16 nType(0), nFlagsTmp(0);
324 sal_uInt32 nUserData = 0;
325 OUString aName = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
326 RTL_TEXTENCODING_ASCII_US);
327 rStrm.ReadUInt16( nType ).ReadUInt16( nFlagsTmp );
328 SbxFlagBits nFlags = static_cast<SbxFlagBits>(nFlagsTmp);
329 if( nVer > 1 )
330 rStrm.ReadUInt32( nUserData );
331 AddParam( aName, static_cast<SbxDataType>(nType), nFlags );
332 SbxParamInfo& p(*m_Params.back());
333 p.nUserData = nUserData;
337 void SbxInfo::StoreData( SvStream& rStrm ) const
339 write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, aComment,
340 RTL_TEXTENCODING_ASCII_US );
341 write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, aHelpFile,
342 RTL_TEXTENCODING_ASCII_US);
343 rStrm.WriteUInt32( nHelpId ).WriteUInt16( m_Params.size() );
344 for (auto const& i : m_Params)
346 write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, i->aName,
347 RTL_TEXTENCODING_ASCII_US);
348 rStrm.WriteUInt16( i->eType )
349 .WriteUInt16( static_cast<sal_uInt16>(i->nFlags) )
350 .WriteUInt32( i->nUserData );
354 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */