1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_basic.hxx" 30 31 32 #include <tools/shl.hxx> 33 #include <tools/stream.hxx> 34 35 #include <basic/sbx.hxx> 36 #include <basic/sbxfac.hxx> 37 #include <basic/sbxbase.hxx> 38 39 // AppData-Struktur fuer SBX: 40 41 SV_IMPL_PTRARR(SbxParams,SbxParamInfo*); 42 SV_IMPL_PTRARR(SbxFacs,SbxFactory*); 43 44 TYPEINIT0(SbxBase) 45 46 // SBX-Daten anfordern oder ggf. anlegen 47 // wir legen den Bereich einfach an und verzichten auf die Freigabe! 48 49 SbxAppData* GetSbxData_Impl() 50 { 51 SbxAppData** ppData = (SbxAppData**) ::GetAppData( SHL_SBX ); 52 SbxAppData* p = *ppData; 53 if( !p ) 54 p = *ppData = new SbxAppData; 55 return p; 56 } 57 58 SbxAppData::~SbxAppData() 59 { 60 if( pBasicFormater ) 61 delete pBasicFormater; 62 } 63 64 65 //////////////////////////////// SbxBase ///////////////////////////////// 66 67 DBG_NAME(SbxBase); 68 69 SbxBase::SbxBase() 70 { 71 DBG_CTOR( SbxBase, 0 ); 72 nFlags = SBX_READWRITE; 73 } 74 75 SbxBase::SbxBase( const SbxBase& r ) 76 : SvRefBase( r ) 77 { 78 DBG_CTOR( SbxBase, 0 ); 79 nFlags = r.nFlags; 80 } 81 82 SbxBase::~SbxBase() 83 { 84 DBG_DTOR(SbxBase,0); 85 } 86 87 SbxBase& SbxBase::operator=( const SbxBase& r ) 88 { 89 DBG_CHKTHIS( SbxBase, 0 ); 90 nFlags = r.nFlags; 91 return *this; 92 } 93 94 SbxDataType SbxBase::GetType() const 95 { 96 DBG_CHKTHIS( SbxBase, 0 ); 97 return SbxEMPTY; 98 } 99 100 SbxClassType SbxBase::GetClass() const 101 { 102 DBG_CHKTHIS( SbxBase, 0 ); 103 return SbxCLASS_DONTCARE; 104 } 105 106 void SbxBase::Clear() 107 { 108 DBG_CHKTHIS( SbxBase, 0 ); 109 } 110 111 sal_Bool SbxBase::IsFixed() const 112 { 113 DBG_CHKTHIS( SbxBase, 0 ); 114 return IsSet( SBX_FIXED ); 115 } 116 117 void SbxBase::SetModified( sal_Bool b ) 118 { 119 DBG_CHKTHIS( SbxBase, 0 ); 120 if( IsSet( SBX_NO_MODIFY ) ) 121 return; 122 if( b ) 123 SetFlag( SBX_MODIFIED ); 124 else 125 ResetFlag( SBX_MODIFIED ); 126 } 127 128 SbxError SbxBase::GetError() 129 { 130 return GetSbxData_Impl()->eSbxError; 131 } 132 133 void SbxBase::SetError( SbxError e ) 134 { 135 SbxAppData* p = GetSbxData_Impl(); 136 if( e && p->eSbxError == SbxERR_OK ) 137 p->eSbxError = e; 138 } 139 140 sal_Bool SbxBase::IsError() 141 { 142 return sal_Bool( GetSbxData_Impl()->eSbxError != SbxERR_OK ); 143 } 144 145 void SbxBase::ResetError() 146 { 147 GetSbxData_Impl()->eSbxError = SbxERR_OK; 148 } 149 150 void SbxBase::AddFactory( SbxFactory* pFac ) 151 { 152 SbxAppData* p = GetSbxData_Impl(); 153 const SbxFactory* pTemp = pFac; 154 155 // AB, 6.3.96: HandleLast-Flag beruecksichtigen 156 sal_uInt16 nPos = p->aFacs.Count(); // Einfuege-Position 157 if( !pFac->IsHandleLast() ) // Nur, wenn nicht selbst HandleLast 158 { 159 // Neue Factory vor Factories mit HandleLast einordnen 160 while( nPos > 0 && 161 (static_cast<SbxFactory*>(p->aFacs.GetObject( nPos-1 )))->IsHandleLast() ) 162 nPos--; 163 } 164 p->aFacs.Insert( pTemp, nPos ); 165 } 166 167 void SbxBase::RemoveFactory( SbxFactory* pFac ) 168 { 169 SbxAppData* p = GetSbxData_Impl(); 170 for( sal_uInt16 i = 0; i < p->aFacs.Count(); i++ ) 171 { 172 if( p->aFacs.GetObject( i ) == pFac ) 173 { 174 p->aFacs.Remove( i, 1 ); break; 175 } 176 } 177 } 178 179 180 SbxBase* SbxBase::Create( sal_uInt16 nSbxId, sal_uInt32 nCreator ) 181 { 182 // #91626: Hack to skip old Basic dialogs 183 // Problem: There does not exist a factory any more, 184 // so we have to create a dummy SbxVariable instead 185 if( nSbxId == 0x65 ) // Dialog Id 186 return new SbxVariable; 187 188 XubString aEmptyStr; 189 if( nCreator == SBXCR_SBX ) 190 switch( nSbxId ) 191 { 192 case SBXID_VALUE: return new SbxValue; 193 case SBXID_VARIABLE: return new SbxVariable; 194 case SBXID_ARRAY: return new SbxArray; 195 case SBXID_DIMARRAY: return new SbxDimArray; 196 case SBXID_OBJECT: return new SbxObject( aEmptyStr ); 197 case SBXID_COLLECTION: return new SbxCollection( aEmptyStr ); 198 case SBXID_FIXCOLLECTION: 199 return new SbxStdCollection( aEmptyStr, aEmptyStr ); 200 case SBXID_METHOD: return new SbxMethod( aEmptyStr, SbxEMPTY ); 201 case SBXID_PROPERTY: return new SbxProperty( aEmptyStr, SbxEMPTY ); 202 } 203 // Unbekanter Typ: �ber die Factories gehen! 204 SbxAppData* p = GetSbxData_Impl(); 205 SbxBase* pNew = NULL; 206 for( sal_uInt16 i = 0; i < p->aFacs.Count(); i++ ) 207 { 208 SbxFactory* pFac = p->aFacs.GetObject( i ); 209 pNew = pFac->Create( nSbxId, nCreator ); 210 if( pNew ) 211 break; 212 } 213 #ifdef DBG_UTIL 214 if( !pNew ) 215 { 216 ByteString aMsg( "SBX: Keine Factory fuer SBX-ID " ); 217 aMsg += ByteString::CreateFromInt32(nSbxId); 218 DbgError( aMsg.GetBuffer() ); 219 } 220 #endif 221 return pNew; 222 } 223 224 SbxObject* SbxBase::CreateObject( const XubString& rClass ) 225 { 226 SbxAppData* p = GetSbxData_Impl(); 227 SbxObject* pNew = NULL; 228 for( sal_uInt16 i = 0; i < p->aFacs.Count(); i++ ) 229 { 230 pNew = p->aFacs.GetObject( i )->CreateObject( rClass ); 231 if( pNew ) 232 break; 233 } 234 #ifdef DBG_UTIL 235 if( !pNew ) 236 { 237 ByteString aMsg( "SBX: Keine Factory fuer Objektklasse " ); 238 ByteString aClassStr( (const UniString&)rClass, RTL_TEXTENCODING_ASCII_US ); 239 aMsg += aClassStr; 240 DbgError( (const char*)aMsg.GetBuffer() ); 241 } 242 #endif 243 return pNew; 244 } 245 246 static sal_Bool bStaticEnableBroadcasting = sal_True; 247 248 // Sbx-Loesung als Ersatz fuer SfxBroadcaster::Enable() 249 void SbxBase::StaticEnableBroadcasting( sal_Bool bEnable ) 250 { 251 bStaticEnableBroadcasting = bEnable; 252 } 253 254 sal_Bool SbxBase::StaticIsEnabledBroadcasting( void ) 255 { 256 return bStaticEnableBroadcasting; 257 } 258 259 260 SbxBase* SbxBase::Load( SvStream& rStrm ) 261 { 262 sal_uInt16 nSbxId, nFlags, nVer; 263 sal_uInt32 nCreator, nSize; 264 rStrm >> nCreator >> nSbxId >> nFlags >> nVer; 265 266 // Eine Dummheit meinerseits korrigieren: 267 if( nFlags & SBX_RESERVED ) 268 nFlags = ( nFlags & ~SBX_RESERVED ) | SBX_GBLSEARCH; 269 270 sal_uIntPtr nOldPos = rStrm.Tell(); 271 rStrm >> nSize; 272 SbxBase* p = Create( nSbxId, nCreator ); 273 if( p ) 274 { 275 p->nFlags = nFlags; 276 if( p->LoadData( rStrm, nVer ) ) 277 { 278 sal_uIntPtr nNewPos = rStrm.Tell(); 279 nOldPos += nSize; 280 DBG_ASSERT( nOldPos >= nNewPos, "SBX: Zu viele Daten eingelesen" ); 281 if( nOldPos != nNewPos ) 282 rStrm.Seek( nOldPos ); 283 if( !p->LoadCompleted() ) 284 { 285 // Loeschen des Objekts 286 SbxBaseRef aRef( p ); 287 p = NULL; 288 } 289 } 290 else 291 { 292 rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR ); 293 // Loeschen des Objekts 294 SbxBaseRef aRef( p ); 295 p = NULL; 296 } 297 } 298 else 299 rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR ); 300 return p; 301 } 302 303 // Sbx-Objekt im Stream ueberspringen 304 void SbxBase::Skip( SvStream& rStrm ) 305 { 306 sal_uInt16 nSbxId, nFlags, nVer; 307 sal_uInt32 nCreator, nSize; 308 rStrm >> nCreator >> nSbxId >> nFlags >> nVer; 309 310 sal_uIntPtr nStartPos = rStrm.Tell(); 311 rStrm >> nSize; 312 313 rStrm.Seek( nStartPos + nSize ); 314 } 315 316 sal_Bool SbxBase::Store( SvStream& rStrm ) 317 { 318 DBG_CHKTHIS( SbxBase, 0 ); 319 if( !( nFlags & SBX_DONTSTORE ) ) 320 { 321 rStrm << (sal_uInt32) GetCreator() 322 << (sal_uInt16) GetSbxId() 323 << (sal_uInt16) GetFlags() 324 << (sal_uInt16) GetVersion(); 325 sal_uIntPtr nOldPos = rStrm.Tell(); 326 rStrm << (sal_uInt32) 0L; 327 sal_Bool bRes = StoreData( rStrm ); 328 sal_uIntPtr nNewPos = rStrm.Tell(); 329 rStrm.Seek( nOldPos ); 330 rStrm << (sal_uInt32) ( nNewPos - nOldPos ); 331 rStrm.Seek( nNewPos ); 332 if( rStrm.GetError() != SVSTREAM_OK ) 333 bRes = sal_False; 334 if( bRes ) 335 bRes = StoreCompleted(); 336 return bRes; 337 } 338 else 339 return sal_True; 340 } 341 342 sal_Bool SbxBase::LoadData( SvStream&, sal_uInt16 ) 343 { 344 DBG_CHKTHIS( SbxBase, 0 ); 345 return sal_False; 346 } 347 348 sal_Bool SbxBase::StoreData( SvStream& ) const 349 { 350 DBG_CHKTHIS( SbxBase, 0 ); 351 return sal_False; 352 } 353 354 sal_Bool SbxBase::LoadPrivateData( SvStream&, sal_uInt16 ) 355 { 356 DBG_CHKTHIS( SbxBase, 0 ); 357 return sal_True; 358 } 359 360 sal_Bool SbxBase::StorePrivateData( SvStream& ) const 361 { 362 DBG_CHKTHIS( SbxBase, 0 ); 363 return sal_True; 364 } 365 366 sal_Bool SbxBase::LoadCompleted() 367 { 368 DBG_CHKTHIS( SbxBase, 0 ); 369 return sal_True; 370 } 371 372 sal_Bool SbxBase::StoreCompleted() 373 { 374 DBG_CHKTHIS( SbxBase, 0 ); 375 return sal_True; 376 } 377 378 //////////////////////////////// SbxFactory //////////////////////////////// 379 380 SbxBase* SbxFactory::Create( sal_uInt16, sal_uInt32 ) 381 { 382 return NULL; 383 } 384 385 SbxObject* SbxFactory::CreateObject( const XubString& ) 386 { 387 return NULL; 388 } 389 390 ///////////////////////////////// SbxInfo ////////////////////////////////// 391 392 SbxInfo::~SbxInfo() 393 {} 394 395 void SbxInfo::AddParam 396 ( const XubString& rName, SbxDataType eType, sal_uInt16 nFlags ) 397 { 398 const SbxParamInfo* p = new SbxParamInfo( rName, eType, nFlags ); 399 aParams.Insert( p, aParams.Count() ); 400 } 401 402 void SbxInfo::AddParam( const SbxParamInfo& r ) 403 { 404 const SbxParamInfo* p = new SbxParamInfo 405 ( r.aName, r.eType, r.nFlags, r.aTypeRef ); 406 aParams.Insert( p, aParams.Count() ); 407 } 408 409 const SbxParamInfo* SbxInfo::GetParam( sal_uInt16 n ) const 410 { 411 if( n < 1 || n > aParams.Count() ) 412 return NULL; 413 else 414 return aParams.GetObject( n-1 ); 415 } 416 417 sal_Bool SbxInfo::LoadData( SvStream& rStrm, sal_uInt16 nVer ) 418 { 419 aParams.Remove( 0, aParams.Count() ); 420 sal_uInt16 nParam; 421 rStrm.ReadByteString( aComment, RTL_TEXTENCODING_ASCII_US ); 422 rStrm.ReadByteString( aHelpFile, RTL_TEXTENCODING_ASCII_US ); 423 rStrm >> nHelpId >> nParam; 424 while( nParam-- ) 425 { 426 XubString aName; 427 sal_uInt16 nType, nFlags; 428 sal_uInt32 nUserData = 0; 429 rStrm.ReadByteString( aName, RTL_TEXTENCODING_ASCII_US ); 430 rStrm >> nType >> nFlags; 431 if( nVer > 1 ) 432 rStrm >> nUserData; 433 AddParam( aName, (SbxDataType) nType, nFlags ); 434 SbxParamInfo* p = aParams.GetObject( aParams.Count() - 1 ); 435 p->nUserData = nUserData; 436 } 437 return sal_True; 438 } 439 440 sal_Bool SbxInfo::StoreData( SvStream& rStrm ) const 441 { 442 rStrm.WriteByteString( aComment, RTL_TEXTENCODING_ASCII_US ); 443 rStrm.WriteByteString( aHelpFile, RTL_TEXTENCODING_ASCII_US ); 444 rStrm << nHelpId << aParams.Count(); 445 for( sal_uInt16 i = 0; i < aParams.Count(); i++ ) 446 { 447 SbxParamInfo* p = aParams.GetObject( i ); 448 rStrm.WriteByteString( p->aName, RTL_TEXTENCODING_ASCII_US ); 449 rStrm << (sal_uInt16) p->eType 450 << (sal_uInt16) p->nFlags 451 << (sal_uInt32) p->nUserData; 452 } 453 return sal_True; 454 } 455 456