/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include #include #include #include #include #include #include #include #include "sfx2/sfxresid.hxx" #include #include #include DBG_NAME(SfxInterface) //==================================================================== EXTERN_C #ifdef WNT int _cdecl #else int #endif SfxCompareSlots_Impl( const void* pSmaller, const void* pBigger ) { 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 ); //==================================================================== //==================================================================== // constuctor, 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 ) { DBG_ASSERT( nIter == nCount || pIter->GetSlotId() != (pIter+1)->GetSlotId(), "doppelte SID" ); // every master refers to his first slave (ENUM), // all slaves refer to their master. // Slaves refer in a circle to the other slaves with the same 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 refering in circle to the next with the same // Status method. 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() ) OSL_FAIL("Wrong order!"); 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 ) { rtl::OStringBuffer aStr(RTL_CONSTASCII_STRINGPARAM( "Wrong Master/Slave- link: ")); aStr.append(static_cast( pMasterSlot->GetSlotId())); aStr.append(RTL_CONSTASCII_STRINGPARAM(" , ")); aStr.append(static_cast( pSlave->GetSlotId())); OSL_FAIL(aStr.getStr()); } if ( pSlave->nMasterSlotId != pMasterSlot->GetSlotId() ) { rtl::OStringBuffer aStr(RTL_CONSTASCII_STRINGPARAM( "Wrong Master/Slave-Ids: ")); aStr.append(static_cast( pMasterSlot->GetSlotId())); aStr.append(RTL_CONSTASCII_STRINGPARAM(" , ")); aStr.append(static_cast( pSlave->GetSlotId())); OSL_FAIL(aStr.getStr()); } pSlave = pSlave->pNextSlot; } while ( pSlave != pFirstSlave ); } else { if ( pIter->pLinkedSlot ) { if ( pIter->pLinkedSlot->GetKind() != SFX_KIND_ENUM ) { rtl::OStringBuffer aStr(RTL_CONSTASCII_STRINGPARAM( "Slave is no enum: ")); aStr.append(static_cast(pIter->GetSlotId())); aStr.append(RTL_CONSTASCII_STRINGPARAM(" , ")); aStr.append(static_cast( pIter->pLinkedSlot->GetSlotId())); OSL_FAIL(aStr.getStr()); } } const SfxSlot *pCurSlot = pIter; do { pCurSlot = pCurSlot->pNextSlot; if ( pCurSlot->GetStateFnc() != pIter->GetStateFnc() ) { rtl::OStringBuffer aStr(RTL_CONSTASCII_STRINGPARAM( "Linked Slots with different State Methods : ")); aStr.append(static_cast( pCurSlot->GetSlotId())); aStr.append(RTL_CONSTASCII_STRINGPARAM(" , ")); aStr.append(static_cast(pIter->GetSlotId())); OSL_FAIL(aStr.getStr()); } } 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_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_CHKTHIS(SfxInterface, 0); DBG_ASSERT( this && pSlots && nCount, "" ); if ( !ContainsSlot_Impl(pSlot) ) { if(pGenoType) return pGenoType->GetRealSlot(pSlot); OSL_FAIL("unknown Slot"); return 0; } return pSlot->pLinkedSlot; } //-------------------------------------------------------------------- const SfxSlot* SfxInterface::GetRealSlot( sal_uInt16 nSlotId ) const { DBG_CHKTHIS(SfxInterface, 0); DBG_ASSERT( this && pSlots && nCount, "" ); const SfxSlot *pSlot = GetSlot(nSlotId); if ( !pSlot ) { if(pGenoType) return pGenoType->GetRealSlot(nSlotId); OSL_FAIL("unkonown 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() || !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 ) { // Are there toolbars in the super class? sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount(); if ( nNo < nBaseCount ) // The Super class comes first 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 ) { // Are there toolbars in the super class? sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount(); if ( nNo < nBaseCount ) // The Super class comes first 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 ) { // Are there ChildWindows in der Superklasse? sal_uInt16 nBaseCount = pGenoType->GetChildWindowCount(); if ( nNo < nBaseCount ) // The Super class comes first 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 ) { // Are there ChildWindows in der Superklasse? sal_uInt16 nBaseCount = pGenoType->GetChildWindowCount(); if ( nNo < nBaseCount ) // The Super class comes first 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 ) { // Are there toolbars in the super class? sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount(); if ( nNo < nBaseCount ) // The Super class comes first 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 ) { // Are there toolbars in the super class? sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount(); if ( nNo < nBaseCount ) // The Super class comes first 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 ) { // Are there toolbars in the super class? sal_uInt16 nBaseCount = pGenoType->GetObjectBarCount(); if ( nNo < nBaseCount ) // The Super class comes first 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; // The slot could also originate from the interface of a shell base class. do { const SfxSlot *pLastSlot = (*pInterface)[pInterface->Count()-1]; const SfxSlot *pFirstSlot = (*pInterface)[0]; // Is pInterface the Owner of pRealSlot ? if ( pFirstSlot <= pRealSlot && pRealSlot <= pLastSlot ) break; // Otherwise try the Interface of Super class pInterface = pInterface->pGenoType; } while ( pInterface ); return pInterface; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */