diff options
Diffstat (limited to 'sc/source/filter/excel/xltoolbar.cxx')
-rw-r--r-- | sc/source/filter/excel/xltoolbar.cxx | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/sc/source/filter/excel/xltoolbar.cxx b/sc/source/filter/excel/xltoolbar.cxx new file mode 100644 index 000000000..efb54925b --- /dev/null +++ b/sc/source/filter/excel/xltoolbar.cxx @@ -0,0 +1,439 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#include "xltoolbar.hxx" +#include <sal/log.hxx> +#include <o3tl/safeint.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/ui/XUIConfigurationPersistence.hpp> +#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/ItemType.hpp> +#include <comphelper/indexedpropertyvalues.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/sequence.hxx> +#include <rtl/ref.hxx> +#include <map> + +using namespace com::sun::star; + +typedef std::map< sal_Int16, OUString > IdToString; + +namespace { + +class MSOExcelCommandConvertor : public MSOCommandConvertor +{ + IdToString msoToOOcmd; + IdToString tcidToOOcmd; +public: + MSOExcelCommandConvertor(); + virtual OUString MSOCommandToOOCommand( sal_Int16 msoCmd ) override; + virtual OUString MSOTCIDToOOCommand( sal_Int16 key ) override; +}; + +} + +MSOExcelCommandConvertor::MSOExcelCommandConvertor() +{ +/* + // mso command id to ooo command string + // #FIXME and *HUNDREDS* of id's to added here + msoToOOcmd[ 0x20b ] = ".uno:CloseDoc"; + msoToOOcmd[ 0x50 ] = ".uno:Open"; + + // mso tcid to ooo command string + // #FIXME and *HUNDREDS* of id's to added here + tcidToOOcmd[ 0x9d9 ] = ".uno:Print"; +*/ +} + +OUString MSOExcelCommandConvertor::MSOCommandToOOCommand( sal_Int16 key ) +{ + OUString sResult; + IdToString::iterator it = msoToOOcmd.find( key ); + if ( it != msoToOOcmd.end() ) + sResult = it->second; + return sResult; +} + +OUString MSOExcelCommandConvertor::MSOTCIDToOOCommand( sal_Int16 key ) +{ + OUString sResult; + IdToString::iterator it = tcidToOOcmd.find( key ); + if ( it != tcidToOOcmd.end() ) + sResult = it->second; + return sResult; +} + +CTBS::CTBS() : bSignature(0), bVersion(0), reserved1(0), reserved2(0), reserved3(0), ctb(0), ctbViews(0), ictbView(0) +{ +} + +ScCTB::ScCTB(sal_uInt16 nNum ) : nViews( nNum ), ectbid(0) +{ +} + +bool ScCTB::Read( SvStream &rS ) +{ + SAL_INFO("sc.filter", "stream pos " << rS.Tell()); + nOffSet = rS.Tell(); + tb.Read( rS ); + + { + const size_t nMinRecordSize = 20; // TBVisualData reads 20 bytes + const size_t nMaxPossibleRecords = rS.remainingSize() / nMinRecordSize; + if (nViews > nMaxPossibleRecords) + { + SAL_WARN("sc.filter", "ScCTB::Read more entries claimed than stream could contain"); + return false; + } + } + + for ( sal_uInt16 index = 0; index < nViews; ++index ) + { + TBVisualData aVisData; + aVisData.Read( rS ); + rVisualData.push_back( aVisData ); + } + rS.ReadUInt32( ectbid ); + + sal_Int16 nCL = tb.getcCL(); + if (nCL > 0) + { + auto nIndexes = o3tl::make_unsigned(nCL); + + const size_t nMinRecordSize = 11; // ScTBC's TBCHeader reads min 11 bytes + const size_t nMaxPossibleRecords = rS.remainingSize() / nMinRecordSize; + if (nIndexes > nMaxPossibleRecords) + { + SAL_WARN("sc.filter", "ScCTB::Read more entries claimed than stream could contain"); + return false; + } + + for (decltype(nIndexes) index = 0; index < nIndexes; ++index) + { + ScTBC aTBC; + aTBC.Read( rS ); + rTBC.push_back( aTBC ); + } + } + + return true; +} + +#ifdef DEBUG_SC_EXCEL +void ScCTB::Print( FILE* fp ) +{ + Indent a; + indent_printf( fp, "[ 0x%x ] ScCTB -- dump\n", nOffSet ); + indent_printf( fp, " nViews 0x%x\n", nViews); + tb.Print( fp ); + + sal_Int32 counter = 0; + for ( auto& rItem : rVisualData ) + { + indent_printf( fp, " TBVisualData [%d]\n", counter++ ); + Indent b; + rItem.Print( fp ); + } + indent_printf( fp, " ectbid 0x%x\n", ectbid); + counter = 0; + for ( auto& rItem : rTBC ) + { + indent_printf( fp, " ScTBC [%d]\n", counter++); + Indent c; + rItem.Print( fp ); + } +} +#endif + +bool ScCTB::IsMenuToolbar() const +{ + return tb.IsMenuToolbar(); +} + +bool ScCTB::ImportMenuTB( ScCTBWrapper& rWrapper, const css::uno::Reference< css::container::XIndexContainer >& xMenuDesc, CustomToolBarImportHelper& helper ) +{ + for ( auto& rItem : rTBC ) + { + if ( !rItem.ImportToolBarControl( rWrapper, xMenuDesc, helper, IsMenuToolbar() ) ) + return false; + } + return true; +} + +bool ScCTB::ImportCustomToolBar( ScCTBWrapper& rWrapper, CustomToolBarImportHelper& helper ) +{ + + bool bRes = false; + try + { + if ( !tb.IsEnabled() ) + return true; // didn't fail, just ignoring + + // Create default setting + uno::Reference< container::XIndexContainer > xIndexContainer( helper.getCfgManager()->createSettings(), uno::UNO_SET_THROW ); + uno::Reference< container::XIndexAccess > xIndexAccess( xIndexContainer, uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySet > xProps( xIndexContainer, uno::UNO_QUERY_THROW ); + WString& name = tb.getName(); + // set UI name for toolbar + xProps->setPropertyValue("UIName", uno::Any( name.getString() ) ); + + OUString sToolBarName = "private:resource/toolbar/custom_" + name.getString(); + for ( auto& rItem : rTBC ) + { + if ( !rItem.ImportToolBarControl( rWrapper, xIndexContainer, helper, IsMenuToolbar() ) ) + return false; + } + + helper.getCfgManager()->insertSettings( sToolBarName, xIndexAccess ); + helper.applyIcons(); + + uno::Reference< ui::XUIConfigurationPersistence > xPersistence( helper.getCfgManager()->getImageManager(), uno::UNO_QUERY_THROW ); + xPersistence->store(); + + xPersistence.set( helper.getCfgManager(), uno::UNO_QUERY_THROW ); + xPersistence->store(); + + bRes = true; + } + catch( uno::Exception& ) + { + bRes = false; + } + return bRes; +} +bool CTBS::Read( SvStream &rS ) +{ + SAL_INFO("sc.filter", "stream pos " << rS.Tell()); + nOffSet = rS.Tell(); + rS.ReadUChar( bSignature ).ReadUChar( bVersion ).ReadUInt16( reserved1 ).ReadUInt16( reserved2 ).ReadUInt16( reserved3 ).ReadUInt16( ctb ).ReadUInt16( ctbViews ).ReadUInt16( ictbView ); + return true; +} + +#ifdef DEBUG_SC_EXCEL +void CTBS::Print( FILE* fp ) +{ + Indent a; + indent_printf( fp, "[ 0x%x ] CTBS -- dump\n", nOffSet ); + + indent_printf( fp, " bSignature 0x%x\n", bSignature); + indent_printf( fp, " bVersion 0x%x\n", bVersion); + + indent_printf( fp, " reserved1 0x%x\n", reserved1 ); + indent_printf( fp, " reserved2 0x%x\n", reserved2 ); + indent_printf( fp, " reserved3 0x%x\n", reserved3 ); + + indent_printf( fp, " ctb 0x%x\n", ctb ); + indent_printf( fp, " ctbViews 0x%x\n", ctbViews ); + indent_printf( fp, " ictbView 0x%x\n", ictbView ); +} +#endif + +ScTBC::ScTBC() +{ +} + +bool +ScTBC::Read(SvStream &rS) +{ + SAL_INFO("sc.filter", "stream pos " << rS.Tell()); + nOffSet = rS.Tell(); + if ( !tbch.Read( rS ) ) + return false; + sal_uInt16 tcid = tbch.getTcID(); + sal_uInt8 tct = tbch.getTct(); + if ( ( tcid != 0x0001 && tcid != 0x06CC && tcid != 0x03D8 && tcid != 0x03EC && tcid != 0x1051 ) && ( ( tct > 0 && tct < 0x0B ) || ( ( tct > 0x0B && tct < 0x10 ) || tct == 0x15 ) ) ) + { + tbcCmd = std::make_shared<TBCCmd>(); + if ( ! tbcCmd->Read( rS ) ) + return false; + } + if ( tct != 0x16 ) + { + tbcd = std::make_shared<TBCData>( tbch ); + if ( !tbcd->Read( rS ) ) + return false; + } + return true; +} + +#ifdef DEBUG_SC_EXCEL +void +ScTBC::Print(FILE* fp) +{ + Indent a; + indent_printf( fp, "[ 0x%x ] ScTBC -- dump\n", nOffSet ); + tbch.Print( fp ); + if ( tbcCmd.get() ) + tbcCmd->Print( fp ); + if ( tbcd.get() ) + tbcd->Print( fp ); +} +#endif + +bool ScTBC::ImportToolBarControl( ScCTBWrapper& rWrapper, const css::uno::Reference< css::container::XIndexContainer >& toolbarcontainer, CustomToolBarImportHelper& helper, bool bIsMenuToolbar ) +{ + // how to identify built-in-command ? +// bool bBuiltin = false; + if ( tbcd ) + { + std::vector< css::beans::PropertyValue > props; + bool bBeginGroup = false; + tbcd->ImportToolBarControl( helper, props, bBeginGroup, bIsMenuToolbar ); + TBCMenuSpecific* pMenu = tbcd->getMenuSpecific(); + if ( pMenu ) + { + // search for ScCTB with the appropriate name ( it contains the + // menu items, although we cannot import ( or create ) a menu on + // a custom toolbar we can import the menu items in a separate + // toolbar ( better than nothing ) + ScCTB* pCustTB = rWrapper.GetCustomizationData( pMenu->Name() ); + if ( pCustTB ) + { + rtl::Reference< comphelper::IndexedPropertyValuesContainer > xMenuDesc = new comphelper::IndexedPropertyValuesContainer(); + if ( !pCustTB->ImportMenuTB( rWrapper, xMenuDesc, helper ) ) + return false; + if ( !bIsMenuToolbar ) + { + if ( !helper.createMenu( pMenu->Name(), xMenuDesc ) ) + return false; + } + else + { + beans::PropertyValue aProp; + aProp.Name = "ItemDescriptorContainer"; + aProp.Value <<= uno::Reference< container::XIndexContainer >(xMenuDesc); + props.push_back( aProp ); + } + } + } + + if ( bBeginGroup ) + { + // insert spacer + uno::Sequence sProps{ comphelper::makePropertyValue("Type", + ui::ItemType::SEPARATOR_LINE) }; + toolbarcontainer->insertByIndex( toolbarcontainer->getCount(), uno::Any( sProps ) ); + } + toolbarcontainer->insertByIndex( toolbarcontainer->getCount(), uno::Any( comphelper::containerToSequence(props) ) ); + } + return true; +} + +#ifdef DEBUG_SC_EXCEL +void +TBCCmd::Print(FILE* fp) +{ + Indent a; + indent_printf( fp, " TBCCmd -- dump\n" ); + indent_printf( fp, " cmdID 0x%x\n", cmdID ); + indent_printf( fp, " A ( fHideDrawing ) %s\n", A ? "true" : "false" ); + indent_printf( fp, " B ( reserved - ignored ) %s\n", A ? "true" : "false" ); + indent_printf( fp, " cmdType 0x%x\n", cmdType ); + indent_printf( fp, " C ( reserved - ignored ) %s\n", A ? "true" : "false" ); + indent_printf( fp, " reserved3 0x%x\n", reserved3 ); +} +#endif + +bool TBCCmd::Read( SvStream &rS ) +{ + SAL_INFO("sc.filter", "stream pos " << rS.Tell()); + nOffSet = rS.Tell(); + rS.ReadUInt16( cmdID ); + sal_uInt16 temp; + rS.ReadUInt16( temp ); + A = (temp & 0x8000 ) == 0x8000; + B = (temp & 0x4000) == 0x4000; + cmdType = ( temp & 0x3E00 ) >> 9; + C = ( temp & 0x100 ) == 0x100; + reserved3 = ( temp & 0xFF ); + return true; +} + +ScCTBWrapper::ScCTBWrapper() +{ +} + +ScCTBWrapper::~ScCTBWrapper() +{ +} + +bool +ScCTBWrapper::Read( SvStream &rS) +{ + SAL_INFO("sc.filter", "stream pos " << rS.Tell()); + nOffSet = rS.Tell(); + if (!ctbSet.Read(rS)) + return false; + + //ScCTB is 1 TB which is min 15bytes, nViews TBVisualData which is min 20bytes + //and one 32bit number (4 bytes) + const size_t nMinRecordSize = 19 + o3tl::sanitizing_min(ctbSet.ctbViews * 20, 0); + const size_t nMaxPossibleRecords = rS.remainingSize()/nMinRecordSize; + if (ctbSet.ctb > nMaxPossibleRecords) + return false; + + for ( sal_uInt16 index = 0; index < ctbSet.ctb; ++index ) + { + ScCTB aCTB( ctbSet.ctbViews ); + if ( !aCTB.Read( rS ) ) + return false; + rCTB.push_back( aCTB ); + } + return true; +} + +#ifdef DEBUG_SC_EXCEL +void +ScCTBWrapper::Print( FILE* fp ) +{ + Indent a; + indent_printf( fp, "[ 0x%x ] ScCTBWrapper -- dump\n", nOffSet ); + ctbSet.Print( fp ); + for ( auto& rItem : rCTB ) + { + Indent b; + rItem.Print( fp ); + } +} +#endif + +ScCTB* ScCTBWrapper::GetCustomizationData( const OUString& sTBName ) +{ + ScCTB* pCTB = nullptr; + auto it = std::find_if(rCTB.begin(), rCTB.end(), [&sTBName](ScCTB& rItem) { return rItem.GetName() == sTBName; }); + if (it != rCTB.end()) + pCTB = &(*it); + return pCTB; +} + +void ScCTBWrapper::ImportCustomToolBar( SfxObjectShell& rDocSh ) +{ + if(rCTB.empty()) + return; + + uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xAppCfgSupp( ui::theModuleUIConfigurationManagerSupplier::get(xContext) ); + + for ( auto& rItem : rCTB ) + { + // for each customtoolbar + CustomToolBarImportHelper helper( rDocSh, xAppCfgSupp->getUIConfigurationManager( "com.sun.star.sheet.SpreadsheetDocument" ) ); + helper.setMSOCommandMap( new MSOExcelCommandConvertor() ); + // Ignore menu toolbars, excel doesn't ( afaics ) store + // menu customizations ( but you can have menus in a customtoolbar + // such menus will be dealt with when they are encountered + // as part of importing the appropriate MenuSpecific toolbar control ) + + if ( !rItem.IsMenuToolbar() && !rItem.ImportCustomToolBar( *this, helper ) ) + return; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |