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 #include "xltoolbar.hxx"
10 #include <sal/log.hxx>
11 #include <o3tl/safeint.hxx>
12 #include <com/sun/star/beans/XPropertySet.hpp>
13 #include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
14 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
15 #include <com/sun/star/ui/ItemType.hpp>
16 #include <comphelper/indexedpropertyvalues.hxx>
17 #include <comphelper/processfactory.hxx>
18 #include <comphelper/propertyvalue.hxx>
19 #include <comphelper/sequence.hxx>
20 #include <rtl/ref.hxx>
23 using namespace com::sun::star
;
25 typedef std::map
< sal_Int16
, OUString
> IdToString
;
29 class MSOExcelCommandConvertor
: public MSOCommandConvertor
31 IdToString msoToOOcmd
;
32 IdToString tcidToOOcmd
;
34 MSOExcelCommandConvertor();
35 virtual OUString
MSOCommandToOOCommand( sal_Int16 msoCmd
) override
;
36 virtual OUString
MSOTCIDToOOCommand( sal_Int16 key
) override
;
41 MSOExcelCommandConvertor::MSOExcelCommandConvertor()
44 // mso command id to ooo command string
45 // #FIXME and *HUNDREDS* of id's to added here
46 msoToOOcmd[ 0x20b ] = ".uno:CloseDoc";
47 msoToOOcmd[ 0x50 ] = ".uno:Open";
49 // mso tcid to ooo command string
50 // #FIXME and *HUNDREDS* of id's to added here
51 tcidToOOcmd[ 0x9d9 ] = ".uno:Print";
55 OUString
MSOExcelCommandConvertor::MSOCommandToOOCommand( sal_Int16 key
)
58 IdToString::iterator it
= msoToOOcmd
.find( key
);
59 if ( it
!= msoToOOcmd
.end() )
64 OUString
MSOExcelCommandConvertor::MSOTCIDToOOCommand( sal_Int16 key
)
67 IdToString::iterator it
= tcidToOOcmd
.find( key
);
68 if ( it
!= tcidToOOcmd
.end() )
73 CTBS::CTBS() : bSignature(0), bVersion(0), reserved1(0), reserved2(0), reserved3(0), ctb(0), ctbViews(0), ictbView(0)
77 ScCTB::ScCTB(sal_uInt16 nNum
) : nViews( nNum
), ectbid(0)
81 bool ScCTB::Read( SvStream
&rS
)
83 SAL_INFO("sc.filter", "stream pos " << rS
.Tell());
88 const size_t nMinRecordSize
= 20; // TBVisualData reads 20 bytes
89 const size_t nMaxPossibleRecords
= rS
.remainingSize() / nMinRecordSize
;
90 if (nViews
> nMaxPossibleRecords
)
92 SAL_WARN("sc.filter", "ScCTB::Read more entries claimed than stream could contain");
97 for ( sal_uInt16 index
= 0; index
< nViews
; ++index
)
99 TBVisualData aVisData
;
101 rVisualData
.push_back( aVisData
);
103 rS
.ReadUInt32( ectbid
);
105 sal_Int16 nCL
= tb
.getcCL();
108 auto nIndexes
= o3tl::make_unsigned(nCL
);
110 const size_t nMinRecordSize
= 11; // ScTBC's TBCHeader reads min 11 bytes
111 const size_t nMaxPossibleRecords
= rS
.remainingSize() / nMinRecordSize
;
112 if (nIndexes
> nMaxPossibleRecords
)
114 SAL_WARN("sc.filter", "ScCTB::Read more entries claimed than stream could contain");
118 for (decltype(nIndexes
) index
= 0; index
< nIndexes
; ++index
)
122 rTBC
.push_back( aTBC
);
129 #ifdef DEBUG_SC_EXCEL
130 void ScCTB::Print( FILE* fp
)
133 indent_printf( fp
, "[ 0x%x ] ScCTB -- dump\n", nOffSet
);
134 indent_printf( fp
, " nViews 0x%x\n", nViews
);
137 sal_Int32 counter
= 0;
138 for ( auto& rItem
: rVisualData
)
140 indent_printf( fp
, " TBVisualData [%d]\n", counter
++ );
144 indent_printf( fp
, " ectbid 0x%x\n", ectbid
);
146 for ( auto& rItem
: rTBC
)
148 indent_printf( fp
, " ScTBC [%d]\n", counter
++);
155 bool ScCTB::IsMenuToolbar() const
157 return tb
.IsMenuToolbar();
160 bool ScCTB::ImportMenuTB( ScCTBWrapper
& rWrapper
, const css::uno::Reference
< css::container::XIndexContainer
>& xMenuDesc
, CustomToolBarImportHelper
& helper
)
162 for ( auto& rItem
: rTBC
)
164 if ( !rItem
.ImportToolBarControl( rWrapper
, xMenuDesc
, helper
, IsMenuToolbar() ) )
170 bool ScCTB::ImportCustomToolBar( ScCTBWrapper
& rWrapper
, CustomToolBarImportHelper
& helper
)
176 if ( !tb
.IsEnabled() )
177 return true; // didn't fail, just ignoring
179 // Create default setting
180 uno::Reference
< container::XIndexContainer
> xIndexContainer( helper
.getCfgManager()->createSettings(), uno::UNO_SET_THROW
);
181 uno::Reference
< container::XIndexAccess
> xIndexAccess( xIndexContainer
, uno::UNO_QUERY_THROW
);
182 uno::Reference
< beans::XPropertySet
> xProps( xIndexContainer
, uno::UNO_QUERY_THROW
);
183 WString
& name
= tb
.getName();
184 // set UI name for toolbar
185 xProps
->setPropertyValue(u
"UIName"_ustr
, uno::Any( name
.getString() ) );
187 OUString sToolBarName
= "private:resource/toolbar/custom_" + name
.getString();
188 for ( auto& rItem
: rTBC
)
190 if ( !rItem
.ImportToolBarControl( rWrapper
, xIndexContainer
, helper
, IsMenuToolbar() ) )
194 helper
.getCfgManager()->insertSettings( sToolBarName
, xIndexAccess
);
197 uno::Reference
< ui::XUIConfigurationPersistence
> xPersistence( helper
.getCfgManager()->getImageManager(), uno::UNO_QUERY_THROW
);
198 xPersistence
->store();
200 xPersistence
.set( helper
.getCfgManager(), uno::UNO_QUERY_THROW
);
201 xPersistence
->store();
205 catch( uno::Exception
& )
211 bool CTBS::Read( SvStream
&rS
)
213 SAL_INFO("sc.filter", "stream pos " << rS
.Tell());
215 rS
.ReadUChar( bSignature
).ReadUChar( bVersion
).ReadUInt16( reserved1
).ReadUInt16( reserved2
).ReadUInt16( reserved3
).ReadUInt16( ctb
).ReadUInt16( ctbViews
).ReadUInt16( ictbView
);
219 #ifdef DEBUG_SC_EXCEL
220 void CTBS::Print( FILE* fp
)
223 indent_printf( fp
, "[ 0x%x ] CTBS -- dump\n", nOffSet
);
225 indent_printf( fp
, " bSignature 0x%x\n", bSignature
);
226 indent_printf( fp
, " bVersion 0x%x\n", bVersion
);
228 indent_printf( fp
, " reserved1 0x%x\n", reserved1
);
229 indent_printf( fp
, " reserved2 0x%x\n", reserved2
);
230 indent_printf( fp
, " reserved3 0x%x\n", reserved3
);
232 indent_printf( fp
, " ctb 0x%x\n", ctb
);
233 indent_printf( fp
, " ctbViews 0x%x\n", ctbViews
);
234 indent_printf( fp
, " ictbView 0x%x\n", ictbView
);
243 ScTBC::Read(SvStream
&rS
)
245 SAL_INFO("sc.filter", "stream pos " << rS
.Tell());
247 if ( !tbch
.Read( rS
) )
249 sal_uInt16 tcid
= tbch
.getTcID();
250 sal_uInt8 tct
= tbch
.getTct();
251 if ( ( tcid
!= 0x0001 && tcid
!= 0x06CC && tcid
!= 0x03D8 && tcid
!= 0x03EC && tcid
!= 0x1051 ) && ( ( tct
> 0 && tct
< 0x0B ) || ( ( tct
> 0x0B && tct
< 0x10 ) || tct
== 0x15 ) ) )
253 tbcCmd
= std::make_shared
<TBCCmd
>();
254 if ( ! tbcCmd
->Read( rS
) )
259 tbcd
= std::make_shared
<TBCData
>( tbch
);
260 if ( !tbcd
->Read( rS
) )
266 #ifdef DEBUG_SC_EXCEL
268 ScTBC::Print(FILE* fp
)
271 indent_printf( fp
, "[ 0x%x ] ScTBC -- dump\n", nOffSet
);
280 bool ScTBC::ImportToolBarControl( ScCTBWrapper
& rWrapper
, const css::uno::Reference
< css::container::XIndexContainer
>& toolbarcontainer
, CustomToolBarImportHelper
& helper
, bool bIsMenuToolbar
)
282 // how to identify built-in-command ?
283 // bool bBuiltin = false;
286 std::vector
< css::beans::PropertyValue
> props
;
287 bool bBeginGroup
= false;
288 tbcd
->ImportToolBarControl( helper
, props
, bBeginGroup
, bIsMenuToolbar
);
289 TBCMenuSpecific
* pMenu
= tbcd
->getMenuSpecific();
292 // search for ScCTB with the appropriate name ( it contains the
293 // menu items, although we cannot import ( or create ) a menu on
294 // a custom toolbar we can import the menu items in a separate
295 // toolbar ( better than nothing )
296 ScCTB
* pCustTB
= rWrapper
.GetCustomizationData( pMenu
->Name() );
299 rtl::Reference
< comphelper::IndexedPropertyValuesContainer
> xMenuDesc
= new comphelper::IndexedPropertyValuesContainer();
300 if ( !pCustTB
->ImportMenuTB( rWrapper
, xMenuDesc
, helper
) )
302 if ( !bIsMenuToolbar
)
304 if ( !helper
.createMenu( pMenu
->Name(), xMenuDesc
) )
309 beans::PropertyValue aProp
;
310 aProp
.Name
= "ItemDescriptorContainer";
311 aProp
.Value
<<= uno::Reference
< container::XIndexContainer
>(xMenuDesc
);
312 props
.push_back( aProp
);
320 uno::Sequence sProps
{ comphelper::makePropertyValue(u
"Type"_ustr
,
321 ui::ItemType::SEPARATOR_LINE
) };
322 toolbarcontainer
->insertByIndex( toolbarcontainer
->getCount(), uno::Any( sProps
) );
324 toolbarcontainer
->insertByIndex( toolbarcontainer
->getCount(), uno::Any( comphelper::containerToSequence(props
) ) );
329 #ifdef DEBUG_SC_EXCEL
331 TBCCmd::Print(FILE* fp
)
334 indent_printf( fp
, " TBCCmd -- dump\n" );
335 indent_printf( fp
, " cmdID 0x%x\n", cmdID
);
336 indent_printf( fp
, " A ( fHideDrawing ) %s\n", A
? "true" : "false" );
337 indent_printf( fp
, " B ( reserved - ignored ) %s\n", A
? "true" : "false" );
338 indent_printf( fp
, " cmdType 0x%x\n", cmdType
);
339 indent_printf( fp
, " C ( reserved - ignored ) %s\n", A
? "true" : "false" );
340 indent_printf( fp
, " reserved3 0x%x\n", reserved3
);
344 bool TBCCmd::Read( SvStream
&rS
)
346 SAL_INFO("sc.filter", "stream pos " << rS
.Tell());
348 rS
.ReadUInt16( cmdID
);
350 rS
.ReadUInt16( temp
);
351 A
= (temp
& 0x8000 ) == 0x8000;
352 B
= (temp
& 0x4000) == 0x4000;
353 cmdType
= ( temp
& 0x3E00 ) >> 9;
354 C
= ( temp
& 0x100 ) == 0x100;
355 reserved3
= ( temp
& 0xFF );
359 ScCTBWrapper::ScCTBWrapper()
363 ScCTBWrapper::~ScCTBWrapper()
368 ScCTBWrapper::Read( SvStream
&rS
)
370 SAL_INFO("sc.filter", "stream pos " << rS
.Tell());
372 if (!ctbSet
.Read(rS
))
375 //ScCTB is 1 TB which is min 15bytes, nViews TBVisualData which is min 20bytes
376 //and one 32bit number (4 bytes)
377 const size_t nMinRecordSize
= 19 + o3tl::sanitizing_min(ctbSet
.ctbViews
* 20, 0);
378 const size_t nMaxPossibleRecords
= rS
.remainingSize()/nMinRecordSize
;
379 if (ctbSet
.ctb
> nMaxPossibleRecords
)
382 for ( sal_uInt16 index
= 0; index
< ctbSet
.ctb
; ++index
)
384 ScCTB
aCTB( ctbSet
.ctbViews
);
385 if ( !aCTB
.Read( rS
) )
387 rCTB
.push_back( aCTB
);
392 #ifdef DEBUG_SC_EXCEL
394 ScCTBWrapper::Print( FILE* fp
)
397 indent_printf( fp
, "[ 0x%x ] ScCTBWrapper -- dump\n", nOffSet
);
399 for ( auto& rItem
: rCTB
)
407 ScCTB
* ScCTBWrapper::GetCustomizationData( const OUString
& sTBName
)
409 ScCTB
* pCTB
= nullptr;
410 auto it
= std::find_if(rCTB
.begin(), rCTB
.end(), [&sTBName
](ScCTB
& rItem
) { return rItem
.GetName() == sTBName
; });
411 if (it
!= rCTB
.end())
416 void ScCTBWrapper::ImportCustomToolBar( SfxObjectShell
& rDocSh
)
421 const uno::Reference
< uno::XComponentContext
>& xContext( ::comphelper::getProcessComponentContext() );
422 uno::Reference
< ui::XModuleUIConfigurationManagerSupplier
> xAppCfgSupp( ui::theModuleUIConfigurationManagerSupplier::get(xContext
) );
424 for ( auto& rItem
: rCTB
)
426 // for each customtoolbar
427 CustomToolBarImportHelper
helper( rDocSh
, xAppCfgSupp
->getUIConfigurationManager( u
"com.sun.star.sheet.SpreadsheetDocument"_ustr
) );
428 helper
.setMSOCommandMap( new MSOExcelCommandConvertor() );
429 // Ignore menu toolbars, excel doesn't ( afaics ) store
430 // menu customizations ( but you can have menus in a customtoolbar
431 // such menus will be dealt with when they are encountered
432 // as part of importing the appropriate MenuSpecific toolbar control )
434 if ( !rItem
.IsMenuToolbar() && !rItem
.ImportCustomToolBar( *this, helper
) )
439 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */