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/document/IndexedPropertyValues.hpp>
14 #include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
15 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
16 #include <com/sun/star/ui/ItemType.hpp>
17 #include <comphelper/processfactory.hxx>
18 #include <comphelper/propertyvalue.hxx>
19 #include <comphelper/sequence.hxx>
22 using namespace com::sun::star
;
24 typedef std::map
< sal_Int16
, OUString
> IdToString
;
28 class MSOExcelCommandConvertor
: public MSOCommandConvertor
30 IdToString msoToOOcmd
;
31 IdToString tcidToOOcmd
;
33 MSOExcelCommandConvertor();
34 virtual OUString
MSOCommandToOOCommand( sal_Int16 msoCmd
) override
;
35 virtual OUString
MSOTCIDToOOCommand( sal_Int16 key
) override
;
40 MSOExcelCommandConvertor::MSOExcelCommandConvertor()
43 // mso command id to ooo command string
44 // #FIXME and *HUNDREDS* of id's to added here
45 msoToOOcmd[ 0x20b ] = ".uno:CloseDoc";
46 msoToOOcmd[ 0x50 ] = ".uno:Open";
48 // mso tcid to ooo command string
49 // #FIXME and *HUNDREDS* of id's to added here
50 tcidToOOcmd[ 0x9d9 ] = ".uno:Print";
54 OUString
MSOExcelCommandConvertor::MSOCommandToOOCommand( sal_Int16 key
)
57 IdToString::iterator it
= msoToOOcmd
.find( key
);
58 if ( it
!= msoToOOcmd
.end() )
63 OUString
MSOExcelCommandConvertor::MSOTCIDToOOCommand( sal_Int16 key
)
66 IdToString::iterator it
= tcidToOOcmd
.find( key
);
67 if ( it
!= tcidToOOcmd
.end() )
72 CTBS::CTBS() : bSignature(0), bVersion(0), reserved1(0), reserved2(0), reserved3(0), ctb(0), ctbViews(0), ictbView(0)
76 ScCTB::ScCTB(sal_uInt16 nNum
) : nViews( nNum
), ectbid(0)
80 bool ScCTB::Read( SvStream
&rS
)
82 SAL_INFO("sc.filter", "stream pos " << rS
.Tell());
87 const size_t nMinRecordSize
= 20; // TBVisualData reads 20 bytes
88 const size_t nMaxPossibleRecords
= rS
.remainingSize() / nMinRecordSize
;
89 if (nViews
> nMaxPossibleRecords
)
91 SAL_WARN("sc.filter", "ScCTB::Read more entries claimed than stream could contain");
96 for ( sal_uInt16 index
= 0; index
< nViews
; ++index
)
98 TBVisualData aVisData
;
100 rVisualData
.push_back( aVisData
);
102 rS
.ReadUInt32( ectbid
);
104 sal_Int16 nCL
= tb
.getcCL();
107 auto nIndexes
= o3tl::make_unsigned(nCL
);
109 const size_t nMinRecordSize
= 11; // ScTBC's TBCHeader reads min 11 bytes
110 const size_t nMaxPossibleRecords
= rS
.remainingSize() / nMinRecordSize
;
111 if (nIndexes
> nMaxPossibleRecords
)
113 SAL_WARN("sc.filter", "ScCTB::Read more entries claimed than stream could contain");
117 for (decltype(nIndexes
) index
= 0; index
< nIndexes
; ++index
)
121 rTBC
.push_back( aTBC
);
128 #ifdef DEBUG_SC_EXCEL
129 void ScCTB::Print( FILE* fp
)
132 indent_printf( fp
, "[ 0x%x ] ScCTB -- dump\n", nOffSet
);
133 indent_printf( fp
, " nViews 0x%x\n", nViews
);
136 sal_Int32 counter
= 0;
137 for ( auto& rItem
: rVisualData
)
139 indent_printf( fp
, " TBVisualData [%d]\n", counter
++ );
143 indent_printf( fp
, " ectbid 0x%x\n", ectbid
);
145 for ( auto& rItem
: rTBC
)
147 indent_printf( fp
, " ScTBC [%d]\n", counter
++);
154 bool ScCTB::IsMenuToolbar() const
156 return tb
.IsMenuToolbar();
159 bool ScCTB::ImportMenuTB( ScCTBWrapper
& rWrapper
, const css::uno::Reference
< css::container::XIndexContainer
>& xMenuDesc
, CustomToolBarImportHelper
& helper
)
161 for ( auto& rItem
: rTBC
)
163 if ( !rItem
.ImportToolBarControl( rWrapper
, xMenuDesc
, helper
, IsMenuToolbar() ) )
169 bool ScCTB::ImportCustomToolBar( ScCTBWrapper
& rWrapper
, CustomToolBarImportHelper
& helper
)
175 if ( !tb
.IsEnabled() )
176 return true; // didn't fail, just ignoring
178 // Create default setting
179 uno::Reference
< container::XIndexContainer
> xIndexContainer( helper
.getCfgManager()->createSettings(), uno::UNO_SET_THROW
);
180 uno::Reference
< container::XIndexAccess
> xIndexAccess( xIndexContainer
, uno::UNO_QUERY_THROW
);
181 uno::Reference
< beans::XPropertySet
> xProps( xIndexContainer
, uno::UNO_QUERY_THROW
);
182 WString
& name
= tb
.getName();
183 // set UI name for toolbar
184 xProps
->setPropertyValue("UIName", uno::makeAny( name
.getString() ) );
186 OUString sToolBarName
= "private:resource/toolbar/custom_" + name
.getString();
187 for ( auto& rItem
: rTBC
)
189 if ( !rItem
.ImportToolBarControl( rWrapper
, xIndexContainer
, helper
, IsMenuToolbar() ) )
193 helper
.getCfgManager()->insertSettings( sToolBarName
, xIndexAccess
);
196 uno::Reference
< ui::XUIConfigurationPersistence
> xPersistence( helper
.getCfgManager()->getImageManager(), uno::UNO_QUERY_THROW
);
197 xPersistence
->store();
199 xPersistence
.set( helper
.getCfgManager(), uno::UNO_QUERY_THROW
);
200 xPersistence
->store();
204 catch( uno::Exception
& )
210 bool CTBS::Read( SvStream
&rS
)
212 SAL_INFO("sc.filter", "stream pos " << rS
.Tell());
214 rS
.ReadUChar( bSignature
).ReadUChar( bVersion
).ReadUInt16( reserved1
).ReadUInt16( reserved2
).ReadUInt16( reserved3
).ReadUInt16( ctb
).ReadUInt16( ctbViews
).ReadUInt16( ictbView
);
218 #ifdef DEBUG_SC_EXCEL
219 void CTBS::Print( FILE* fp
)
222 indent_printf( fp
, "[ 0x%x ] CTBS -- dump\n", nOffSet
);
224 indent_printf( fp
, " bSignature 0x%x\n", bSignature
);
225 indent_printf( fp
, " bVersion 0x%x\n", bVersion
);
227 indent_printf( fp
, " reserved1 0x%x\n", reserved1
);
228 indent_printf( fp
, " reserved2 0x%x\n", reserved2
);
229 indent_printf( fp
, " reserved3 0x%x\n", reserved3
);
231 indent_printf( fp
, " ctb 0x%x\n", ctb
);
232 indent_printf( fp
, " ctbViews 0x%x\n", ctbViews
);
233 indent_printf( fp
, " ictbView 0x%x\n", ictbView
);
242 ScTBC::Read(SvStream
&rS
)
244 SAL_INFO("sc.filter", "stream pos " << rS
.Tell());
246 if ( !tbch
.Read( rS
) )
248 sal_uInt16 tcid
= tbch
.getTcID();
249 sal_uInt8 tct
= tbch
.getTct();
250 if ( ( tcid
!= 0x0001 && tcid
!= 0x06CC && tcid
!= 0x03D8 && tcid
!= 0x03EC && tcid
!= 0x1051 ) && ( ( tct
> 0 && tct
< 0x0B ) || ( ( tct
> 0x0B && tct
< 0x10 ) || tct
== 0x15 ) ) )
252 tbcCmd
= std::make_shared
<TBCCmd
>();
253 if ( ! tbcCmd
->Read( rS
) )
258 tbcd
= std::make_shared
<TBCData
>( tbch
);
259 if ( !tbcd
->Read( rS
) )
265 #ifdef DEBUG_SC_EXCEL
267 ScTBC::Print(FILE* fp
)
270 indent_printf( fp
, "[ 0x%x ] ScTBC -- dump\n", nOffSet
);
279 bool ScTBC::ImportToolBarControl( ScCTBWrapper
& rWrapper
, const css::uno::Reference
< css::container::XIndexContainer
>& toolbarcontainer
, CustomToolBarImportHelper
& helper
, bool bIsMenuToolbar
)
281 // how to identify built-in-command ?
282 // bool bBuiltin = false;
285 std::vector
< css::beans::PropertyValue
> props
;
286 bool bBeginGroup
= false;
287 tbcd
->ImportToolBarControl( helper
, props
, bBeginGroup
, bIsMenuToolbar
);
288 TBCMenuSpecific
* pMenu
= tbcd
->getMenuSpecific();
291 // search for ScCTB with the appropriate name ( it contains the
292 // menu items, although we cannot import ( or create ) a menu on
293 // a custom toolbar we can import the menu items in a separate
294 // toolbar ( better than nothing )
295 ScCTB
* pCustTB
= rWrapper
.GetCustomizationData( pMenu
->Name() );
298 uno::Reference
< container::XIndexContainer
> xMenuDesc
= document::IndexedPropertyValues::create( comphelper::getProcessComponentContext() );
299 if ( !pCustTB
->ImportMenuTB( rWrapper
, xMenuDesc
, helper
) )
301 if ( !bIsMenuToolbar
)
303 if ( !helper
.createMenu( pMenu
->Name(), xMenuDesc
) )
308 beans::PropertyValue aProp
;
309 aProp
.Name
= "ItemDescriptorContainer";
310 aProp
.Value
<<= xMenuDesc
;
311 props
.push_back( aProp
);
319 uno::Sequence sProps
{ comphelper::makePropertyValue("Type",
320 ui::ItemType::SEPARATOR_LINE
) };
321 toolbarcontainer
->insertByIndex( toolbarcontainer
->getCount(), uno::makeAny( sProps
) );
323 toolbarcontainer
->insertByIndex( toolbarcontainer
->getCount(), uno::makeAny( comphelper::containerToSequence(props
) ) );
328 #ifdef DEBUG_SC_EXCEL
330 TBCCmd::Print(FILE* fp
)
333 indent_printf( fp
, " TBCCmd -- dump\n" );
334 indent_printf( fp
, " cmdID 0x%x\n", cmdID
);
335 indent_printf( fp
, " A ( fHideDrawing ) %s\n", A
? "true" : "false" );
336 indent_printf( fp
, " B ( reserved - ignored ) %s\n", A
? "true" : "false" );
337 indent_printf( fp
, " cmdType 0x%x\n", cmdType
);
338 indent_printf( fp
, " C ( reserved - ignored ) %s\n", A
? "true" : "false" );
339 indent_printf( fp
, " reserved3 0x%x\n", reserved3
);
343 bool TBCCmd::Read( SvStream
&rS
)
345 SAL_INFO("sc.filter", "stream pos " << rS
.Tell());
347 rS
.ReadUInt16( cmdID
);
349 rS
.ReadUInt16( temp
);
350 A
= (temp
& 0x8000 ) == 0x8000;
351 B
= (temp
& 0x4000) == 0x4000;
352 cmdType
= ( temp
& 0x3E00 ) >> 9;
353 C
= ( temp
& 0x100 ) == 0x100;
354 reserved3
= ( temp
& 0xFF );
358 ScCTBWrapper::ScCTBWrapper()
362 ScCTBWrapper::~ScCTBWrapper()
367 ScCTBWrapper::Read( SvStream
&rS
)
369 SAL_INFO("sc.filter", "stream pos " << rS
.Tell());
371 if (!ctbSet
.Read(rS
))
374 //ScCTB is 1 TB which is min 15bytes, nViews TBVisualData which is min 20bytes
375 //and one 32bit number (4 bytes)
376 const size_t nMinRecordSize
= 19 + o3tl::sanitizing_min(ctbSet
.ctbViews
* 20, 0);
377 const size_t nMaxPossibleRecords
= rS
.remainingSize()/nMinRecordSize
;
378 if (ctbSet
.ctb
> nMaxPossibleRecords
)
381 for ( sal_uInt16 index
= 0; index
< ctbSet
.ctb
; ++index
)
383 ScCTB
aCTB( ctbSet
.ctbViews
);
384 if ( !aCTB
.Read( rS
) )
386 rCTB
.push_back( aCTB
);
391 #ifdef DEBUG_SC_EXCEL
393 ScCTBWrapper::Print( FILE* fp
)
396 indent_printf( fp
, "[ 0x%x ] ScCTBWrapper -- dump\n", nOffSet
);
398 for ( auto& rItem
: rCTB
)
406 ScCTB
* ScCTBWrapper::GetCustomizationData( const OUString
& sTBName
)
408 ScCTB
* pCTB
= nullptr;
409 auto it
= std::find_if(rCTB
.begin(), rCTB
.end(), [&sTBName
](ScCTB
& rItem
) { return rItem
.GetName() == sTBName
; });
410 if (it
!= rCTB
.end())
415 void ScCTBWrapper::ImportCustomToolBar( SfxObjectShell
& rDocSh
)
420 uno::Reference
< uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
421 uno::Reference
< ui::XModuleUIConfigurationManagerSupplier
> xAppCfgSupp( ui::theModuleUIConfigurationManagerSupplier::get(xContext
) );
423 for ( auto& rItem
: rCTB
)
425 // for each customtoolbar
426 CustomToolBarImportHelper
helper( rDocSh
, xAppCfgSupp
->getUIConfigurationManager( "com.sun.star.sheet.SpreadsheetDocument" ) );
427 helper
.setMSOCommandMap( new MSOExcelCommandConvertor() );
428 // Ignore menu toolbars, excel doesn't ( afaics ) store
429 // menu customizations ( but you can have menus in a customtoolbar
430 // such menus will be dealt with when they are encountered
431 // as part of importing the appropriate MenuSpecific toolbar control )
433 if ( !rItem
.IsMenuToolbar() && !rItem
.ImportCustomToolBar( *this, helper
) )
438 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */