LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sc / source / filter / excel / xltoolbar.cxx
blob40759538405a1268f0dc126afcce2fbca01642a3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
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>
20 #include <map>
22 using namespace com::sun::star;
24 typedef std::map< sal_Int16, OUString > IdToString;
26 namespace {
28 class MSOExcelCommandConvertor : public MSOCommandConvertor
30 IdToString msoToOOcmd;
31 IdToString tcidToOOcmd;
32 public:
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 )
56 OUString sResult;
57 IdToString::iterator it = msoToOOcmd.find( key );
58 if ( it != msoToOOcmd.end() )
59 sResult = it->second;
60 return sResult;
63 OUString MSOExcelCommandConvertor::MSOTCIDToOOCommand( sal_Int16 key )
65 OUString sResult;
66 IdToString::iterator it = tcidToOOcmd.find( key );
67 if ( it != tcidToOOcmd.end() )
68 sResult = it->second;
69 return sResult;
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());
83 nOffSet = rS.Tell();
84 tb.Read( rS );
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");
92 return false;
96 for ( sal_uInt16 index = 0; index < nViews; ++index )
98 TBVisualData aVisData;
99 aVisData.Read( rS );
100 rVisualData.push_back( aVisData );
102 rS.ReadUInt32( ectbid );
104 sal_Int16 nCL = tb.getcCL();
105 if (nCL > 0)
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");
114 return false;
117 for (decltype(nIndexes) index = 0; index < nIndexes; ++index)
119 ScTBC aTBC;
120 aTBC.Read( rS );
121 rTBC.push_back( aTBC );
125 return true;
128 #ifdef DEBUG_SC_EXCEL
129 void ScCTB::Print( FILE* fp )
131 Indent a;
132 indent_printf( fp, "[ 0x%x ] ScCTB -- dump\n", nOffSet );
133 indent_printf( fp, " nViews 0x%x\n", nViews);
134 tb.Print( fp );
136 sal_Int32 counter = 0;
137 for ( auto& rItem : rVisualData )
139 indent_printf( fp, " TBVisualData [%d]\n", counter++ );
140 Indent b;
141 rItem.Print( fp );
143 indent_printf( fp, " ectbid 0x%x\n", ectbid);
144 counter = 0;
145 for ( auto& rItem : rTBC )
147 indent_printf( fp, " ScTBC [%d]\n", counter++);
148 Indent c;
149 rItem.Print( fp );
152 #endif
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() ) )
164 return false;
166 return true;
169 bool ScCTB::ImportCustomToolBar( ScCTBWrapper& rWrapper, CustomToolBarImportHelper& helper )
172 bool bRes = false;
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() ) )
190 return false;
193 helper.getCfgManager()->insertSettings( sToolBarName, xIndexAccess );
194 helper.applyIcons();
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();
202 bRes = true;
204 catch( uno::Exception& )
206 bRes = false;
208 return bRes;
210 bool CTBS::Read( SvStream &rS )
212 SAL_INFO("sc.filter", "stream pos " << rS.Tell());
213 nOffSet = rS.Tell();
214 rS.ReadUChar( bSignature ).ReadUChar( bVersion ).ReadUInt16( reserved1 ).ReadUInt16( reserved2 ).ReadUInt16( reserved3 ).ReadUInt16( ctb ).ReadUInt16( ctbViews ).ReadUInt16( ictbView );
215 return true;
218 #ifdef DEBUG_SC_EXCEL
219 void CTBS::Print( FILE* fp )
221 Indent a;
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 );
235 #endif
237 ScTBC::ScTBC()
241 bool
242 ScTBC::Read(SvStream &rS)
244 SAL_INFO("sc.filter", "stream pos " << rS.Tell());
245 nOffSet = rS.Tell();
246 if ( !tbch.Read( rS ) )
247 return false;
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 ) )
254 return false;
256 if ( tct != 0x16 )
258 tbcd = std::make_shared<TBCData>( tbch );
259 if ( !tbcd->Read( rS ) )
260 return false;
262 return true;
265 #ifdef DEBUG_SC_EXCEL
266 void
267 ScTBC::Print(FILE* fp)
269 Indent a;
270 indent_printf( fp, "[ 0x%x ] ScTBC -- dump\n", nOffSet );
271 tbch.Print( fp );
272 if ( tbcCmd.get() )
273 tbcCmd->Print( fp );
274 if ( tbcd.get() )
275 tbcd->Print( fp );
277 #endif
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;
283 if ( tbcd )
285 std::vector< css::beans::PropertyValue > props;
286 bool bBeginGroup = false;
287 tbcd->ImportToolBarControl( helper, props, bBeginGroup, bIsMenuToolbar );
288 TBCMenuSpecific* pMenu = tbcd->getMenuSpecific();
289 if ( pMenu )
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() );
296 if ( pCustTB )
298 uno::Reference< container::XIndexContainer > xMenuDesc = document::IndexedPropertyValues::create( comphelper::getProcessComponentContext() );
299 if ( !pCustTB->ImportMenuTB( rWrapper, xMenuDesc, helper ) )
300 return false;
301 if ( !bIsMenuToolbar )
303 if ( !helper.createMenu( pMenu->Name(), xMenuDesc ) )
304 return false;
306 else
308 beans::PropertyValue aProp;
309 aProp.Name = "ItemDescriptorContainer";
310 aProp.Value <<= xMenuDesc;
311 props.push_back( aProp );
316 if ( bBeginGroup )
318 // insert spacer
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) ) );
325 return true;
328 #ifdef DEBUG_SC_EXCEL
329 void
330 TBCCmd::Print(FILE* fp)
332 Indent a;
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 );
341 #endif
343 bool TBCCmd::Read( SvStream &rS )
345 SAL_INFO("sc.filter", "stream pos " << rS.Tell());
346 nOffSet = rS.Tell();
347 rS.ReadUInt16( cmdID );
348 sal_uInt16 temp;
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 );
355 return true;
358 ScCTBWrapper::ScCTBWrapper()
362 ScCTBWrapper::~ScCTBWrapper()
366 bool
367 ScCTBWrapper::Read( SvStream &rS)
369 SAL_INFO("sc.filter", "stream pos " << rS.Tell());
370 nOffSet = rS.Tell();
371 if (!ctbSet.Read(rS))
372 return false;
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)
379 return false;
381 for ( sal_uInt16 index = 0; index < ctbSet.ctb; ++index )
383 ScCTB aCTB( ctbSet.ctbViews );
384 if ( !aCTB.Read( rS ) )
385 return false;
386 rCTB.push_back( aCTB );
388 return true;
391 #ifdef DEBUG_SC_EXCEL
392 void
393 ScCTBWrapper::Print( FILE* fp )
395 Indent a;
396 indent_printf( fp, "[ 0x%x ] ScCTBWrapper -- dump\n", nOffSet );
397 ctbSet.Print( fp );
398 for ( auto& rItem : rCTB )
400 Indent b;
401 rItem.Print( fp );
404 #endif
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())
411 pCTB = &(*it);
412 return pCTB;
415 void ScCTBWrapper::ImportCustomToolBar( SfxObjectShell& rDocSh )
417 if(rCTB.empty())
418 return;
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 ) )
434 return;
438 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */