Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <tools/debug.hxx>
21 : #include <tools/stream.hxx>
22 : #include <vcl/svapp.hxx>
23 :
24 : #include <basic/sbx.hxx>
25 : #include <basic/sbxfac.hxx>
26 : #include "sbxbase.hxx"
27 :
28 : #include <rtl/instance.hxx>
29 : #include <rtl/ustring.hxx>
30 : #include <boost/foreach.hpp>
31 :
32 : // AppData-Structure for SBX:
33 :
34 816656 : TYPEINIT0(SbxBase)
35 :
36 373 : SbxAppData::SbxAppData()
37 : : eSbxError(SbxERR_OK)
38 : , pBasicFormater(0)
39 373 : , eBasicFormaterLangType(LANGUAGE_DONTKNOW)
40 : {
41 373 : }
42 :
43 476 : SbxAppData::~SbxAppData()
44 : {
45 238 : SolarMutexGuard g;
46 :
47 238 : delete pBasicFormater;
48 238 : aFacs.clear();
49 238 : }
50 :
51 476236 : SbxBase::SbxBase()
52 : {
53 476236 : nFlags = SBX_READWRITE;
54 476236 : }
55 :
56 16510 : SbxBase::SbxBase( const SbxBase& r )
57 16510 : : SvRefBase( r )
58 : {
59 16510 : nFlags = r.nFlags;
60 16510 : }
61 :
62 466352 : SbxBase::~SbxBase()
63 : {
64 466352 : }
65 :
66 0 : SbxBase& SbxBase::operator=( const SbxBase& r )
67 : {
68 0 : nFlags = r.nFlags;
69 0 : return *this;
70 : }
71 :
72 0 : SbxDataType SbxBase::GetType() const
73 : {
74 0 : return SbxEMPTY;
75 : }
76 :
77 0 : SbxClassType SbxBase::GetClass() const
78 : {
79 0 : return SbxCLASS_DONTCARE;
80 : }
81 :
82 0 : void SbxBase::Clear()
83 : {
84 0 : }
85 :
86 0 : bool SbxBase::IsFixed() const
87 : {
88 0 : return IsSet( SBX_FIXED );
89 : }
90 :
91 458974 : void SbxBase::SetModified( bool b )
92 : {
93 458974 : if( IsSet( SBX_NO_MODIFY ) )
94 463218 : return;
95 454730 : if( b )
96 375080 : SetFlag( SBX_MODIFIED );
97 : else
98 79650 : ResetFlag( SBX_MODIFIED );
99 : }
100 :
101 435564 : SbxError SbxBase::GetError()
102 : {
103 435564 : return GetSbxData_Impl().eSbxError;
104 : }
105 :
106 38 : void SbxBase::SetError( SbxError e )
107 : {
108 38 : SbxAppData& r = GetSbxData_Impl();
109 38 : if( e && r.eSbxError == SbxERR_OK )
110 38 : r.eSbxError = e;
111 38 : }
112 :
113 328790 : bool SbxBase::IsError()
114 : {
115 328790 : return GetSbxData_Impl().eSbxError != SbxERR_OK;
116 : }
117 :
118 4408 : void SbxBase::ResetError()
119 : {
120 4408 : GetSbxData_Impl().eSbxError = SbxERR_OK;
121 4408 : }
122 :
123 6866 : void SbxBase::AddFactory( SbxFactory* pFac )
124 : {
125 6866 : SbxAppData& r = GetSbxData_Impl();
126 :
127 : // From 1996-03-06: take the HandleLast-Flag into account
128 6866 : sal_uInt16 nPos = r.aFacs.size(); // Insert position
129 6866 : if( !pFac->IsHandleLast() ) // Only if not self HandleLast
130 : {
131 : // Rank new factory in front of factories with HandleLast
132 20360 : while( nPos > 0 &&
133 6628 : r.aFacs[ nPos-1 ].IsHandleLast() )
134 0 : nPos--;
135 : }
136 6866 : r.aFacs.insert( r.aFacs.begin() + nPos, pFac );
137 6866 : }
138 :
139 5220 : void SbxBase::RemoveFactory( SbxFactory* pFac )
140 : {
141 5220 : SbxAppData& r = GetSbxData_Impl();
142 70088 : for(SbxFacs::iterator it = r.aFacs.begin(); it != r.aFacs.end(); ++it)
143 : {
144 70088 : if( &(*it) == pFac )
145 : {
146 5220 : r.aFacs.release( it ).release(); break;
147 : }
148 : }
149 5220 : }
150 :
151 :
152 0 : SbxBase* SbxBase::Create( sal_uInt16 nSbxId, sal_uInt32 nCreator )
153 : {
154 : // #91626: Hack to skip old Basic dialogs
155 : // Problem: There does not exist a factory any more,
156 : // so we have to create a dummy SbxVariable instead
157 0 : if( nSbxId == 0x65 ) // Dialog Id
158 0 : return new SbxVariable;
159 :
160 0 : OUString aEmptyStr;
161 0 : if( nCreator == SBXCR_SBX )
162 0 : switch( nSbxId )
163 : {
164 0 : case SBXID_VALUE: return new SbxValue;
165 0 : case SBXID_VARIABLE: return new SbxVariable;
166 0 : case SBXID_ARRAY: return new SbxArray;
167 0 : case SBXID_DIMARRAY: return new SbxDimArray;
168 0 : case SBXID_OBJECT: return new SbxObject( aEmptyStr );
169 0 : case SBXID_COLLECTION: return new SbxCollection( aEmptyStr );
170 : case SBXID_FIXCOLLECTION:
171 0 : return new SbxStdCollection( aEmptyStr, aEmptyStr );
172 0 : case SBXID_METHOD: return new SbxMethod( aEmptyStr, SbxEMPTY );
173 0 : case SBXID_PROPERTY: return new SbxProperty( aEmptyStr, SbxEMPTY );
174 : }
175 : // Unknown type: go over the factories!
176 0 : SbxAppData& r = GetSbxData_Impl();
177 0 : SbxBase* pNew = NULL;
178 0 : BOOST_FOREACH(SbxFactory& rFac, r.aFacs)
179 : {
180 0 : pNew = rFac.Create( nSbxId, nCreator );
181 0 : if( pNew )
182 0 : break;
183 : }
184 : SAL_WARN_IF(!pNew, "basic", "No factory for SBX ID " << nSbxId);
185 0 : return pNew;
186 : }
187 :
188 40 : SbxObject* SbxBase::CreateObject( const OUString& rClass )
189 : {
190 40 : SbxAppData& r = GetSbxData_Impl();
191 40 : SbxObject* pNew = NULL;
192 240 : BOOST_FOREACH(SbxFactory& rFac, r.aFacs)
193 : {
194 240 : pNew = rFac.CreateObject( rClass );
195 240 : if( pNew )
196 40 : break;
197 : }
198 : SAL_WARN_IF(!pNew, "basic", "No factory for object class " << rClass);
199 40 : return pNew;
200 : }
201 :
202 0 : SbxBase* SbxBase::Load( SvStream& rStrm )
203 : {
204 : sal_uInt16 nSbxId, nFlagsTmp, nVer;
205 : sal_uInt32 nCreator, nSize;
206 0 : rStrm.ReadUInt32( nCreator ).ReadUInt16( nSbxId ).ReadUInt16( nFlagsTmp ).ReadUInt16( nVer );
207 0 : SbxFlagBits nFlags = static_cast<SbxFlagBits>(nFlagsTmp);
208 :
209 : // Correcting a foolishness of mine:
210 0 : if( (nFlags & SBX_RESERVED) != SBX_NONE )
211 0 : nFlags = ( nFlags & ~SBX_RESERVED ) | SBX_GBLSEARCH;
212 :
213 0 : sal_Size nOldPos = rStrm.Tell();
214 0 : rStrm.ReadUInt32( nSize );
215 0 : SbxBase* p = Create( nSbxId, nCreator );
216 0 : if( p )
217 : {
218 0 : p->nFlags = nFlags;
219 0 : if( p->LoadData( rStrm, nVer ) )
220 : {
221 0 : sal_Size nNewPos = rStrm.Tell();
222 0 : nOldPos += nSize;
223 : DBG_ASSERT( nOldPos >= nNewPos, "SBX: Too much data loaded" );
224 0 : if( nOldPos != nNewPos )
225 0 : rStrm.Seek( nOldPos );
226 0 : if( !p->LoadCompleted() )
227 : {
228 : // Deleting of the object
229 0 : SbxBaseRef aRef( p );
230 0 : p = NULL;
231 : }
232 : }
233 : else
234 : {
235 0 : rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR );
236 : // Deleting of the object
237 0 : SbxBaseRef aRef( p );
238 0 : p = NULL;
239 : }
240 : }
241 : else
242 0 : rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR );
243 0 : return p;
244 : }
245 :
246 : // Skip the Sbx-Object inside the stream
247 0 : void SbxBase::Skip( SvStream& rStrm )
248 : {
249 : sal_uInt16 nSbxId, nFlags, nVer;
250 : sal_uInt32 nCreator, nSize;
251 0 : rStrm.ReadUInt32( nCreator ).ReadUInt16( nSbxId ).ReadUInt16( nFlags ).ReadUInt16( nVer );
252 :
253 0 : sal_Size nStartPos = rStrm.Tell();
254 0 : rStrm.ReadUInt32( nSize );
255 :
256 0 : rStrm.Seek( nStartPos + nSize );
257 0 : }
258 :
259 0 : bool SbxBase::Store( SvStream& rStrm )
260 : {
261 0 : if( ( nFlags & SBX_DONTSTORE ) == SBX_NONE )
262 : {
263 0 : rStrm.WriteUInt32( GetCreator() )
264 0 : .WriteUInt16( GetSbxId() )
265 0 : .WriteUInt16( GetFlags() )
266 0 : .WriteUInt16( GetVersion() );
267 0 : sal_Size nOldPos = rStrm.Tell();
268 0 : rStrm.WriteUInt32( 0L );
269 0 : bool bRes = StoreData( rStrm );
270 0 : sal_Size nNewPos = rStrm.Tell();
271 0 : rStrm.Seek( nOldPos );
272 0 : rStrm.WriteUInt32( ( nNewPos - nOldPos ) );
273 0 : rStrm.Seek( nNewPos );
274 0 : if( rStrm.GetError() != SVSTREAM_OK )
275 0 : bRes = false;
276 0 : if( bRes )
277 0 : bRes = StoreCompleted();
278 0 : return bRes;
279 : }
280 : else
281 0 : return true;
282 : }
283 :
284 0 : bool SbxBase::LoadData( SvStream&, sal_uInt16 )
285 : {
286 0 : return false;
287 : }
288 :
289 0 : bool SbxBase::StoreData( SvStream& ) const
290 : {
291 0 : return false;
292 : }
293 :
294 0 : bool SbxBase::LoadPrivateData( SvStream&, sal_uInt16 )
295 : {
296 0 : return true;
297 : }
298 :
299 0 : bool SbxBase::StorePrivateData( SvStream& ) const
300 : {
301 0 : return true;
302 : }
303 :
304 0 : bool SbxBase::LoadCompleted()
305 : {
306 0 : return true;
307 : }
308 :
309 0 : bool SbxBase::StoreCompleted()
310 : {
311 0 : return true;
312 : }
313 :
314 : //////////////////////////////// SbxFactory
315 :
316 5220 : SbxFactory::~SbxFactory()
317 : {
318 5220 : }
319 :
320 0 : SbxBase* SbxFactory::Create( sal_uInt16, sal_uInt32 )
321 : {
322 0 : return NULL;
323 : }
324 :
325 0 : SbxObject* SbxFactory::CreateObject( const OUString& )
326 : {
327 0 : return NULL;
328 : }
329 :
330 : ///////////////////////////////// SbxInfo
331 :
332 1840 : SbxInfo::~SbxInfo()
333 1840 : {}
334 :
335 954 : void SbxInfo::AddParam(const OUString& rName, SbxDataType eType, SbxFlagBits nFlags)
336 : {
337 954 : aParams.push_back(new SbxParamInfo(rName, eType, nFlags));
338 954 : }
339 :
340 8416 : const SbxParamInfo* SbxInfo::GetParam( sal_uInt16 n ) const
341 : {
342 8416 : if( n < 1 || n > aParams.size() )
343 2012 : return NULL;
344 : else
345 6404 : return &(aParams[n - 1]);
346 : }
347 :
348 0 : bool SbxInfo::LoadData( SvStream& rStrm, sal_uInt16 nVer )
349 : {
350 0 : aParams.clear();
351 : sal_uInt16 nParam;
352 0 : aComment = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
353 0 : RTL_TEXTENCODING_ASCII_US);
354 0 : aHelpFile = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
355 0 : RTL_TEXTENCODING_ASCII_US);
356 0 : rStrm.ReadUInt32( nHelpId ).ReadUInt16( nParam );
357 0 : while( nParam-- )
358 : {
359 : sal_uInt16 nType, nFlagsTmp;
360 0 : sal_uInt32 nUserData = 0;
361 : OUString aName = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
362 0 : RTL_TEXTENCODING_ASCII_US);
363 0 : rStrm.ReadUInt16( nType ).ReadUInt16( nFlagsTmp );
364 0 : SbxFlagBits nFlags = static_cast<SbxFlagBits>(nFlagsTmp);
365 0 : if( nVer > 1 )
366 0 : rStrm.ReadUInt32( nUserData );
367 0 : AddParam( aName, (SbxDataType) nType, nFlags );
368 0 : SbxParamInfo& p(aParams.back());
369 0 : p.nUserData = nUserData;
370 0 : }
371 0 : return true;
372 : }
373 :
374 0 : bool SbxInfo::StoreData( SvStream& rStrm ) const
375 : {
376 : write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, aComment,
377 0 : RTL_TEXTENCODING_ASCII_US );
378 : write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, aHelpFile,
379 0 : RTL_TEXTENCODING_ASCII_US);
380 0 : rStrm.WriteUInt32( nHelpId ).WriteUInt16( aParams.size() );
381 0 : for(SbxParams::const_iterator i = aParams.begin(); i != aParams.end(); ++i)
382 : {
383 0 : write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, i->aName,
384 0 : RTL_TEXTENCODING_ASCII_US);
385 0 : rStrm.WriteUInt16( i->eType )
386 0 : .WriteUInt16( i->nFlags )
387 0 : .WriteUInt32( i->nUserData );
388 : }
389 0 : return true;
390 1203 : }
391 :
392 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|