1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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:
37 class theSbxAppData
: public rtl::Static
<SbxAppData
, theSbxAppData
> {};
40 SbxAppData
& GetSbxData_Impl()
42 return theSbxAppData::get();
45 SbxAppData::~SbxAppData()
47 delete pBasicFormater
;
51 //////////////////////////////// SbxBase /////////////////////////////////
57 DBG_CTOR( SbxBase
, 0 );
58 nFlags
= SBX_READWRITE
;
61 SbxBase::SbxBase( const SbxBase
& r
)
64 DBG_CTOR( SbxBase
, 0 );
73 SbxBase
& SbxBase::operator=( const SbxBase
& r
)
75 DBG_CHKTHIS( SbxBase
, 0 );
80 SbxDataType
SbxBase::GetType() const
82 DBG_CHKTHIS( SbxBase
, 0 );
86 SbxClassType
SbxBase::GetClass() const
88 DBG_CHKTHIS( SbxBase
, 0 );
89 return SbxCLASS_DONTCARE
;
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
) )
109 SetFlag( SBX_MODIFIED
);
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
)
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
146 r
.aFacs
[ nPos
-1 ].IsHandleLast() )
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
)
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
)
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
);
197 SAL_WARN_IF(!pNew
, "basic", "No factory for SBX ID " << nSbxId
);
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
);
211 SAL_WARN_IF(!pNew
, "basic", "No factory for object class " << rClass
);
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();
227 SbxBase
* p
= Create( nSbxId
, nCreator
);
231 if( p
->LoadData( rStrm
, nVer
) )
233 sal_uIntPtr nNewPos
= rStrm
.Tell();
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
);
247 rStrm
.SetError( SVSTREAM_FILEFORMAT_ERROR
);
248 // Deleting of the object
249 SbxBaseRef
aRef( p
);
254 rStrm
.SetError( SVSTREAM_FILEFORMAT_ERROR
);
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();
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
)
290 bRes
= StoreCompleted();
297 sal_Bool
SbxBase::LoadData( SvStream
&, sal_uInt16
)
299 DBG_CHKTHIS( SbxBase
, 0 );
303 sal_Bool
SbxBase::StoreData( SvStream
& ) const
305 DBG_CHKTHIS( SbxBase
, 0 );
309 sal_Bool
SbxBase::LoadPrivateData( SvStream
&, sal_uInt16
)
311 DBG_CHKTHIS( SbxBase
, 0 );
315 sal_Bool
SbxBase::StorePrivateData( SvStream
& ) const
317 DBG_CHKTHIS( SbxBase
, 0 );
321 sal_Bool
SbxBase::LoadCompleted()
323 DBG_CHKTHIS( SbxBase
, 0 );
327 sal_Bool
SbxBase::StoreCompleted()
329 DBG_CHKTHIS( SbxBase
, 0 );
333 //////////////////////////////// SbxFactory ////////////////////////////////
335 SbxFactory::~SbxFactory()
339 SbxBase
* SbxFactory::Create( sal_uInt16
, sal_uInt32
)
344 SbxObject
* SbxFactory::CreateObject( const rtl::OUString
& )
349 ///////////////////////////////// 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() )
364 return &(aParams
[n
- 1]);
367 sal_Bool
SbxInfo::LoadData( SvStream
& rStrm
, sal_uInt16 nVer
)
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
;
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
;
385 AddParam( aName
, (SbxDataType
) nType
, nFlags
);
386 SbxParamInfo
& p(aParams
.back());
387 p
.nUserData
= nUserData
;
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
;
410 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */