/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sfx2.hxx" #include #include #ifndef GCC #endif #include #include #include #include #include #include #include "sfx2/sfxresid.hxx" #include #include DBG_NAME(SfxInterface) //==================================================================== EXTERN_C #if defined( PM2 ) && (!defined( CSET ) && !defined ( MTW ) && !defined( WTC )) int _stdcall #else #ifdef WNT int _cdecl #else int #endif #endif SfxCompareSlots_Impl( const void* pSmaller, const void* pBigger ) { DBG_MEMTEST(); return ( (int) ((SfxSlot*)pSmaller)->GetSlotId() ) - ( (int) ((SfxSlot*)pBigger)->GetSlotId() ); } //========================================================================= struct SfxObjectUI_Impl { sal_uInt16 nPos; ResId aResId; sal_Bool bVisible; sal_Bool bContext; String* pName; sal_uInt32 nFeature; SfxObjectUI_Impl(sal_uInt16 n, const ResId& rResId, sal_Bool bVis, sal_uInt32 nFeat) : nPos(n), aResId(rResId.GetId(), *rResId.GetResMgr()), bVisible(bVis), bContext(sal_False), pName(0), nFeature(nFeat) { aResId.SetRT(rResId.GetRT()); } ~SfxObjectUI_Impl() { delete pName; } }; DECL_PTRARRAY(SfxObjectUIArr_Impl, SfxObjectUI_Impl*, 2, 2) struct SfxInterface_Impl { SfxObjectUIArr_Impl* pObjectBars; // registered ObjectBars SfxObjectUIArr_Impl* pChildWindows; // registered ChildWindows ResId aPopupRes; // registered PopupMenu ResId aStatBarRes; // registered StatusBar SfxModule* pModule; sal_Bool bRegistered; SfxInterface_Impl() : aPopupRes(0,*SfxApplication::GetOrCreate()->GetSfxResManager()), aStatBarRes(0,*SfxApplication::GetOrCreate()->GetSfxResManager()) , bRegistered(sal_False) { pObjectBars = new SfxObjectUIArr_Impl; pChildWindows = new SfxObjectUIArr_Impl; } ~SfxInterface_Impl() { sal_uInt16 n; for (n=0; nCount(); n++) delete (*pObjectBars)[n]; delete pObjectBars; for (n=0; nCount(); n++) delete (*pChildWindows)[n]; delete pChildWindows; } }; static SfxObjectUI_Impl* CreateObjectBarUI_Impl( sal_uInt16 nPos, const ResId& rResId, sal_uInt32 nFeature, const String *pStr ); //==================================================================== //==================================================================== // ctor, registeres a new unit SfxInterface::SfxInterface( const char *pClassName, const ResId& rNameResId, SfxInterfaceId nId, const SfxInterface* pParent, SfxSlot &rSlotMap, sal_uInt16 nSlotCount ): pName(pClassName), pGenoType(pParent), nClassId(nId), aNameResId(rNameResId.GetId(),*rNameResId.GetResMgr()), pImpData(0) { pImpData = new SfxInterface_Impl; SetSlotMap( rSlotMap, nSlotCount ); } void SfxInterface::Register( SfxModule* pMod ) { pImpData->bRegistered = sal_True; pImpData->pModule = pMod; if ( pMod ) pMod->GetSlotPool()->RegisterInterface(*this); else SFX_APP()->GetAppSlotPool_Impl().RegisterInterface(*this); } void SfxInterface::SetSlotMap( SfxSlot& rSlotMap, sal_uInt16 nSlotCount ) { pSlots = &rSlotMap; nCount = nSlotCount; SfxSlot* pIter = pSlots; if ( 1 == nCount && !pIter->pNextSlot ) pIter->pNextSlot = pIter; if ( !pIter->pNextSlot ) { // sort the SfxSlots by id qsort( pSlots, nCount, sizeof(SfxSlot), SfxCompareSlots_Impl ); // link masters and slaves sal_uInt16 nIter = 1; for ( pIter = pSlots; nIter <= nCount; ++pIter, ++nIter ) { //! hier bitte sinnvoll pruefen //! DBG_ASSERT(!(pIter->IsMode(SFX_SLOT_CACHABLE) && //! pIter->IsMode(SFX_SLOT_VOLATILE)), //! "invalid Flags" ); DBG_ASSERT( nIter == nCount || pIter->GetSlotId() != (pIter+1)->GetSlotId(), "doppelte SID" ); // jeder Master verweist auf seinen ersten Slave (ENUM), alle // Slaves auf ihren Master. // Slaves verweisen im Ring auf die anderen mit gleichem Master if ( pIter->GetKind() == SFX_KIND_ENUM ) { pIter->pLinkedSlot = GetSlot( pIter->nMasterSlotId ); DBG_ASSERT( pIter->pLinkedSlot, "slave without master" ); if ( !pIter->pLinkedSlot->pLinkedSlot ) ( (SfxSlot*) pIter->pLinkedSlot)->pLinkedSlot = pIter; if ( 0 == pIter->GetNextSlot() ) { SfxSlot *pLastSlot = pIter; for ( sal_uInt16 n = nIter; n < Count(); ++n ) { SfxSlot *pCurSlot = (pSlots+n); if ( pCurSlot->nMasterSlotId == pIter->nMasterSlotId ) { pLastSlot->pNextSlot = pCurSlot; pLastSlot = pCurSlot; } } pLastSlot->pNextSlot = pIter; } } else if ( 0 == pIter->GetNextSlot() ) { // Slots verweisen im Ring auf den n"achten mit derselben Statusmethode SfxSlot *pLastSlot = pIter; for ( sal_uInt16 n = nIter; n < Count(); ++n ) { SfxSlot *pCurSlot = (pSlots+n); if ( pCurSlot->GetStateFnc() == pIter->GetStateFnc() ) { pLastSlot->pNextSlot = pCurSlot; pLastSlot = pCurSlot; } } pLastSlot->pNextSlot = pIter; } } } #ifdef DBG_UTIL else { sal_uInt16 nIter = 1; for ( SfxSlot *pNext = pIter+1; nIter < nCount; ++pNext, ++nIter ) { if ( pNext->GetSlotId() <= pIter->GetSlotId() ) DBG_ERROR ("Falsche Reihenfolge!"); if ( pIter->GetKind() == SFX_KIND_ENUM ) { const SfxSlot *pMasterSlot = GetSlot(pIter->nMasterSlotId); const SfxSlot *pFirstSlave = pMasterSlot->pLinkedSlot; const SfxSlot *pSlave = pFirstSlave; do { if ( pSlave->pLinkedSlot != pMasterSlot ) { ByteString aStr("Falsche Master/Slave-Verkettung : "); aStr += ByteString::CreateFromInt32(pMasterSlot->GetSlotId()); aStr += " , "; aStr += ByteString::CreateFromInt32(pSlave->GetSlotId()); DBG_ERROR(aStr.GetBuffer()); } if ( pSlave->nMasterSlotId != pMasterSlot->GetSlotId() ) { ByteString aStr("Falsche Master/Slave-Ids : "); aStr += ByteString::CreateFromInt32(pMasterSlot->GetSlotId()); aStr += " , "; aStr += ByteString::CreateFromInt32(pSlave->GetSlotId()); DBG_ERROR(aStr.GetBuffer()); } pSlave = pSlave->pNextSlot; } while ( pSlave != pFirstSlave ); } else { if ( pIter->pLinkedSlot ) { if ( pIter->pLinkedSlot->GetKind() != SFX_KIND_ENUM ) { ByteString aStr("Slave ist kein enum : "); aStr += ByteString::CreateFromInt32(pIter->GetSlotId()); aStr += " , "; aStr += ByteString::CreateFromInt32(pIter->pLinkedSlot->GetSlotId()); DBG_ERROR(aStr.GetBuffer()); } } const SfxSlot *pCurSlot = pIter; do { pCurSlot = pCurSlot->pNextSlot; if ( pCurSlot->GetStateFnc() != pIter->GetStateFnc() ) { ByteString aStr("Verkettete Slots mit verschiedenen StateMethods : "); aStr += ByteString::CreateFromInt32(pCurSlot->GetSlotId()); aStr += " , "; aStr += ByteString::CreateFromInt32(pIter->GetSlotId()); DBG_ERROR(aStr.GetBuffer()); } } while ( pCurSlot != pIter ); } pIter = pNext; } } #endif } //-------------------------------------------------------------------- SfxInterface::~SfxInterface() { SfxModule *pMod = pImpData->pModule; sal_Bool bRegistered = pImpData->bRegistered; delete pImpData; DBG_ASSERT( bRegistered, "Interface not registered!" ); if ( bRegistered ) { if ( pMod ) pMod->GetSlotPool()->ReleaseInterface(*this); else SFX_APP()->GetAppSlotPool_Impl().ReleaseInterface(*this); } } //-------------------------------------------------------------------- // searches for the specified func const SfxSlot* SfxInterface::GetSlot( sal_uInt16 nFuncId ) const { DBG_MEMTEST(); DBG_CHKTHIS(SfxInterface, 0); DBG_ASSERT( this && pSlots && nCount, "" ); // find the id using binary search void* p = bsearch( &nFuncId, pSlots, nCount, sizeof(SfxSlot), SfxCompareSlots_Impl ); if ( !p && pGenoType ) return pGenoType->GetSlot( nFuncId ); return p ? (const SfxSlot*)p : 0; } const SfxSlot* SfxInterface::GetSlot( const String& rCommand ) const { static const char UNO_COMMAND[] = ".uno:"; String aCommand( rCommand ); if ( aCommand.SearchAscii( UNO_COMMAND ) == 0 ) aCommand.Erase( 0, sizeof( UNO_COMMAND )-1 ); for ( sal_uInt16 n=0; npUnoName && aCommand.CompareIgnoreCaseToAscii( (pSlots+n)->GetUnoName() ) == COMPARE_EQUAL ) return pSlots+n; } return pGenoType ? pGenoType->GetSlot( aCommand ) : NULL; } //-------------------------------------------------------------------- const SfxSlot* SfxInterface::GetRealSlot( const SfxSlot *pSlot ) const { DBG_MEMTEST(); DBG_CHKTHIS(SfxInterface, 0); DBG_ASSERT( this && pSlots && nCount, "" ); if ( !ContainsSlot_Impl(pSlot) ) { if(pGenoType) return pGenoType->GetRealSlot(pSlot); DBG_ERROR("fremder Slot"); return 0; } return pSlot->pLinkedSlot; } //-------------------------------------------------------------------- const SfxSlot* SfxInterface::GetRealSlot( sal_uInt16 nSlotId ) const { DBG_MEMTEST(); DBG_CHKTHIS(SfxInterface, 0); DBG_ASSERT( this && pSlots && nCount, "" ); const SfxSlot *pSlot = GetSlot(nSlotId); if ( !pSlot ) { if(pGenoType) return pGenoType->GetRealSlot(nSlotId); DBG_ERROR("fremder Slot"); return 0; } return pSlot->pLinkedSlot; } //-------------------------------------------------------------------- void SfxInterface::RegisterPopupMenu( const ResId& rResId ) { DBG_CHKTHIS(SfxInterface, 0); pImpData->aPopupRes = rResId; } //-------------------------------------------------------------------- void SfxInterface::RegisterObjectBar( sal_uInt16 nPos, const ResId& rResId, const String *pStr ) { RegisterObjectBar( nPos, rResId, 0UL, pStr ); } void SfxInterface::RegisterObjectBar( sal_uInt16 nPos, const ResId& rResId, sal_uInt32 nFeature, const String *pStr ) { SfxObjectUI_Impl* pUI = CreateObjectBarUI_Impl( nPos, rResId, nFeature, pStr ); if ( pUI ) pImpData->pObjectBars->Append(pUI); } SfxObjectUI_Impl* CreateObjectBarUI_Impl( sal_uInt16 nPos, const ResId& rResId, sal_uInt32 nFeature, const String *pStr ) { if ((nPos & SFX_VISIBILITY_MASK) == 0) nPos |= SFX_VISIBILITY_STANDARD; SfxObjectUI_Impl* pUI = new SfxObjectUI_Impl(nPos, rResId, sal_True, nFeature); if (pStr == 0) { ResId aResId(rResId); aResId.SetRT(RSC_STRING); aResId.SetResMgr(rResId.GetResMgr()); if( ! aResId.GetResMgr() ) aResId.SetResMgr( SfxApplication::GetOrCreate()->GetOffResManager_Impl() ); if ( !aResId.GetResMgr()->IsAvailable(aResId) ) pUI->pName = new String (DEFINE_CONST_UNICODE("NoName")); else pUI->pName = new String(aResId); } else pUI->pName = new String(*pStr); return pUI; } const ResId& SfxInterface::GetObjectBarResId( sal_uInt16 nNo ) const { sal_Bool bGenoType = (pGenoType != 0 && !pGenoType->HasName()); if ( bGenoType ) { // Gibt es Toolbars in der Superklasse ? sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount(); if ( nNo < nBaseCount ) // Die der Superklasse kommen zuerst return pGenoType->GetObjectBarResId( nNo ); else nNo = nNo - nBaseCount; } #ifdef DBG_UTIL sal_uInt16 nObjBarCount = pImpData->pObjectBars->Count(); DBG_ASSERT( nNopObjectBars)[nNo]->aResId; } //-------------------------------------------------------------------- sal_uInt16 SfxInterface::GetObjectBarPos( sal_uInt16 nNo ) const { sal_Bool bGenoType = (pGenoType != 0 && !pGenoType->HasName()); if ( bGenoType ) { // Gibt es Toolbars in der Superklasse ? sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount(); if ( nNo < nBaseCount ) // Die der Superklasse kommen zuerst return pGenoType->GetObjectBarPos( nNo ); else nNo = nNo - nBaseCount; } #ifdef DBG_UTIL sal_uInt16 nObjBarCount = pImpData->pObjectBars->Count(); DBG_ASSERT( nNopObjectBars)[nNo]->nPos; } //-------------------------------------------------------------------- sal_uInt16 SfxInterface::GetObjectBarCount() const { if (pGenoType && ! pGenoType->HasName()) return pImpData->pObjectBars->Count() + pGenoType->GetObjectBarCount(); else return pImpData->pObjectBars->Count(); } //-------------------------------------------------------------------- void SfxInterface::RegisterChildWindow(sal_uInt16 nId, sal_Bool bContext, const String* pChildWinName) { RegisterChildWindow( nId, bContext, 0UL, pChildWinName ); } void SfxInterface::RegisterChildWindow(sal_uInt16 nId, sal_Bool bContext, sal_uInt32 nFeature, const String*) { SfxObjectUI_Impl* pUI = new SfxObjectUI_Impl(0, ResId(nId, *SfxApplication::GetOrCreate()->GetOffResManager_Impl()), sal_True, nFeature); pUI->bContext = bContext; pImpData->pChildWindows->Append(pUI); } void SfxInterface::RegisterStatusBar(const ResId& rResId) { pImpData->aStatBarRes = rResId; } sal_uInt32 SfxInterface::GetChildWindowId (sal_uInt16 nNo) const { if ( pGenoType ) { // Gibt es ChildWindows in der Superklasse ? sal_uInt16 nBaseCount = pGenoType->GetChildWindowCount(); if ( nNo < nBaseCount ) // Die der Superklasse kommen zuerst return pGenoType->GetChildWindowId( nNo ); else nNo = nNo - nBaseCount; } #ifdef DBG_UTIL sal_uInt16 nCWCount = pImpData->pChildWindows->Count(); DBG_ASSERT( nNopChildWindows)[nNo]->aResId.GetId(); if ( (*pImpData->pChildWindows)[nNo]->bContext ) nRet += sal_uInt32( nClassId ) << 16; return nRet; } sal_uInt32 SfxInterface::GetChildWindowFeature (sal_uInt16 nNo) const { if ( pGenoType ) { // Gibt es ChildWindows in der Superklasse ? sal_uInt16 nBaseCount = pGenoType->GetChildWindowCount(); if ( nNo < nBaseCount ) // Die der Superklasse kommen zuerst return pGenoType->GetChildWindowFeature( nNo ); else nNo = nNo - nBaseCount; } #ifdef DBG_UTIL sal_uInt16 nCWCount = pImpData->pChildWindows->Count(); DBG_ASSERT( nNopChildWindows)[nNo]->nFeature; } //-------------------------------------------------------------------- sal_uInt16 SfxInterface::GetChildWindowCount() const { if (pGenoType) return pImpData->pChildWindows->Count() + pGenoType->GetChildWindowCount(); else return pImpData->pChildWindows->Count(); } const ResId& SfxInterface::GetPopupMenuResId() const { return pImpData->aPopupRes; } const ResId& SfxInterface::GetStatusBarResId() const { if (pImpData->aStatBarRes.GetId() == 0 && pGenoType) return pGenoType->GetStatusBarResId(); else return pImpData->aStatBarRes; } const String* SfxInterface::GetObjectBarName ( sal_uInt16 nNo ) const { sal_Bool bGenoType = (pGenoType != 0 && !pGenoType->HasName()); if ( bGenoType ) { // Gibt es Toolbars in der Superklasse ? sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount(); if ( nNo < nBaseCount ) // Die der Superklasse kommen zuerst return pGenoType->GetObjectBarName( nNo ); else nNo = nNo - nBaseCount; } #ifdef DBG_UTIL sal_uInt16 nObjBarCount = pImpData->pObjectBars->Count(); DBG_ASSERT( nNopObjectBars)[nNo]->pName; } sal_uInt32 SfxInterface::GetObjectBarFeature ( sal_uInt16 nNo ) const { sal_Bool bGenoType = (pGenoType != 0 && !pGenoType->HasName()); if ( bGenoType ) { // Gibt es Toolbars in der Superklasse ? sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount(); if ( nNo < nBaseCount ) // Die der Superklasse kommen zuerst return pGenoType->GetObjectBarFeature( nNo ); else nNo = nNo - nBaseCount; } #ifdef DBG_UTIL sal_uInt16 nObjBarCount = pImpData->pObjectBars->Count(); DBG_ASSERT( nNopObjectBars)[nNo]->nFeature; } sal_Bool SfxInterface::IsObjectBarVisible(sal_uInt16 nNo) const { sal_Bool bGenoType = (pGenoType != 0 && !pGenoType->HasName()); if ( bGenoType ) { // Gibt es Toolbars in der Superklasse ? sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount(); if ( nNo < nBaseCount ) // Die der Superklasse kommen zuerst return pGenoType->IsObjectBarVisible( nNo ); else nNo = nNo - nBaseCount; } #ifdef DBG_UTIL sal_uInt16 nObjBarCount = pImpData->pObjectBars->Count(); DBG_ASSERT( nNopObjectBars)[nNo]->bVisible; } const SfxInterface* SfxInterface::GetRealInterfaceForSlot( const SfxSlot *pRealSlot ) const { DBG_ASSERT( pImpData->bRegistered, "Interface not registered!" ); const SfxInterface* pInterface = this; // Der Slot k"onnte auch aus dem Interface einer Shell-Basisklasse stammen do { const SfxSlot *pLastSlot = (*pInterface)[pInterface->Count()-1]; const SfxSlot *pFirstSlot = (*pInterface)[0]; // Ist pInterface der Owner von pRealSlot ? if ( pFirstSlot <= pRealSlot && pRealSlot <= pLastSlot ) break; // Sonst Interface der Superklasse probieren pInterface = pInterface->pGenoType; } while ( pInterface ); return pInterface; }