LibreOffice Module sc (master)  1
xltoolbar.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/ui/XUIConfigurationPersistence.hpp>
14 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
15 #include <com/sun/star/ui/ItemType.hpp>
19 #include <comphelper/sequence.hxx>
20 #include <rtl/ref.hxx>
21 #include <map>
22 
23 using namespace com::sun::star;
24 
25 typedef std::map< sal_Int16, OUString > IdToString;
26 
27 namespace {
28 
29 class MSOExcelCommandConvertor : public MSOCommandConvertor
30 {
31  IdToString msoToOOcmd;
32  IdToString tcidToOOcmd;
33 public:
34  MSOExcelCommandConvertor();
35  virtual OUString MSOCommandToOOCommand( sal_Int16 msoCmd ) override;
36  virtual OUString MSOTCIDToOOCommand( sal_Int16 key ) override;
37 };
38 
39 }
40 
41 MSOExcelCommandConvertor::MSOExcelCommandConvertor()
42 {
43 /*
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";
48 
49  // mso tcid to ooo command string
50  // #FIXME and *HUNDREDS* of id's to added here
51  tcidToOOcmd[ 0x9d9 ] = ".uno:Print";
52 */
53 }
54 
55 OUString MSOExcelCommandConvertor::MSOCommandToOOCommand( sal_Int16 key )
56 {
57  OUString sResult;
58  IdToString::iterator it = msoToOOcmd.find( key );
59  if ( it != msoToOOcmd.end() )
60  sResult = it->second;
61  return sResult;
62 }
63 
64 OUString MSOExcelCommandConvertor::MSOTCIDToOOCommand( sal_Int16 key )
65 {
66  OUString sResult;
67  IdToString::iterator it = tcidToOOcmd.find( key );
68  if ( it != tcidToOOcmd.end() )
69  sResult = it->second;
70  return sResult;
71 }
72 
73 CTBS::CTBS() : bSignature(0), bVersion(0), reserved1(0), reserved2(0), reserved3(0), ctb(0), ctbViews(0), ictbView(0)
74 {
75 }
76 
77 ScCTB::ScCTB(sal_uInt16 nNum ) : nViews( nNum ), ectbid(0)
78 {
79 }
80 
81 bool ScCTB::Read( SvStream &rS )
82 {
83  SAL_INFO("sc.filter", "stream pos " << rS.Tell());
84  nOffSet = rS.Tell();
85  tb.Read( rS );
86 
87  {
88  const size_t nMinRecordSize = 20; // TBVisualData reads 20 bytes
89  const size_t nMaxPossibleRecords = rS.remainingSize() / nMinRecordSize;
90  if (nViews > nMaxPossibleRecords)
91  {
92  SAL_WARN("sc.filter", "ScCTB::Read more entries claimed than stream could contain");
93  return false;
94  }
95  }
96 
97  for ( sal_uInt16 index = 0; index < nViews; ++index )
98  {
99  TBVisualData aVisData;
100  aVisData.Read( rS );
101  rVisualData.push_back( aVisData );
102  }
103  rS.ReadUInt32( ectbid );
104 
105  sal_Int16 nCL = tb.getcCL();
106  if (nCL > 0)
107  {
108  auto nIndexes = o3tl::make_unsigned(nCL);
109 
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)
113  {
114  SAL_WARN("sc.filter", "ScCTB::Read more entries claimed than stream could contain");
115  return false;
116  }
117 
118  for (decltype(nIndexes) index = 0; index < nIndexes; ++index)
119  {
120  ScTBC aTBC;
121  aTBC.Read( rS );
122  rTBC.push_back( aTBC );
123  }
124  }
125 
126  return true;
127 }
128 
129 #ifdef DEBUG_SC_EXCEL
130 void ScCTB::Print( FILE* fp )
131 {
132  Indent a;
133  indent_printf( fp, "[ 0x%x ] ScCTB -- dump\n", nOffSet );
134  indent_printf( fp, " nViews 0x%x\n", nViews);
135  tb.Print( fp );
136 
137  sal_Int32 counter = 0;
138  for ( auto& rItem : rVisualData )
139  {
140  indent_printf( fp, " TBVisualData [%d]\n", counter++ );
141  Indent b;
142  rItem.Print( fp );
143  }
144  indent_printf( fp, " ectbid 0x%x\n", ectbid);
145  counter = 0;
146  for ( auto& rItem : rTBC )
147  {
148  indent_printf( fp, " ScTBC [%d]\n", counter++);
149  Indent c;
150  rItem.Print( fp );
151  }
152 }
153 #endif
154 
156 {
157  return tb.IsMenuToolbar();
158 }
159 
160 bool ScCTB::ImportMenuTB( ScCTBWrapper& rWrapper, const css::uno::Reference< css::container::XIndexContainer >& xMenuDesc, CustomToolBarImportHelper& helper )
161 {
162  for ( auto& rItem : rTBC )
163  {
164  if ( !rItem.ImportToolBarControl( rWrapper, xMenuDesc, helper, IsMenuToolbar() ) )
165  return false;
166  }
167  return true;
168 }
169 
171 {
172 
173  bool bRes = false;
174  try
175  {
176  if ( !tb.IsEnabled() )
177  return true; // didn't fail, just ignoring
178 
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("UIName", uno::Any( name.getString() ) );
186 
187  OUString sToolBarName = "private:resource/toolbar/custom_" + name.getString();
188  for ( auto& rItem : rTBC )
189  {
190  if ( !rItem.ImportToolBarControl( rWrapper, xIndexContainer, helper, IsMenuToolbar() ) )
191  return false;
192  }
193 
194  helper.getCfgManager()->insertSettings( sToolBarName, xIndexAccess );
195  helper.applyIcons();
196 
197  uno::Reference< ui::XUIConfigurationPersistence > xPersistence( helper.getCfgManager()->getImageManager(), uno::UNO_QUERY_THROW );
198  xPersistence->store();
199 
200  xPersistence.set( helper.getCfgManager(), uno::UNO_QUERY_THROW );
201  xPersistence->store();
202 
203  bRes = true;
204  }
205  catch( uno::Exception& )
206  {
207  bRes = false;
208  }
209  return bRes;
210 }
211 bool CTBS::Read( SvStream &rS )
212 {
213  SAL_INFO("sc.filter", "stream pos " << rS.Tell());
214  nOffSet = rS.Tell();
216  return true;
217 }
218 
219 #ifdef DEBUG_SC_EXCEL
220 void CTBS::Print( FILE* fp )
221 {
222  Indent a;
223  indent_printf( fp, "[ 0x%x ] CTBS -- dump\n", nOffSet );
224 
225  indent_printf( fp, " bSignature 0x%x\n", bSignature);
226  indent_printf( fp, " bVersion 0x%x\n", bVersion);
227 
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 );
231 
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 );
235 }
236 #endif
237 
239 {
240 }
241 
242 bool
244 {
245  SAL_INFO("sc.filter", "stream pos " << rS.Tell());
246  nOffSet = rS.Tell();
247  if ( !tbch.Read( rS ) )
248  return false;
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 ) ) )
252  {
253  tbcCmd = std::make_shared<TBCCmd>();
254  if ( ! tbcCmd->Read( rS ) )
255  return false;
256  }
257  if ( tct != 0x16 )
258  {
259  tbcd = std::make_shared<TBCData>( tbch );
260  if ( !tbcd->Read( rS ) )
261  return false;
262  }
263  return true;
264 }
265 
266 #ifdef DEBUG_SC_EXCEL
267 void
268 ScTBC::Print(FILE* fp)
269 {
270  Indent a;
271  indent_printf( fp, "[ 0x%x ] ScTBC -- dump\n", nOffSet );
272  tbch.Print( fp );
273  if ( tbcCmd.get() )
274  tbcCmd->Print( fp );
275  if ( tbcd.get() )
276  tbcd->Print( fp );
277 }
278 #endif
279 
280 bool ScTBC::ImportToolBarControl( ScCTBWrapper& rWrapper, const css::uno::Reference< css::container::XIndexContainer >& toolbarcontainer, CustomToolBarImportHelper& helper, bool bIsMenuToolbar )
281 {
282  // how to identify built-in-command ?
283 // bool bBuiltin = false;
284  if ( tbcd )
285  {
286  std::vector< css::beans::PropertyValue > props;
287  bool bBeginGroup = false;
288  tbcd->ImportToolBarControl( helper, props, bBeginGroup, bIsMenuToolbar );
289  TBCMenuSpecific* pMenu = tbcd->getMenuSpecific();
290  if ( pMenu )
291  {
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() );
297  if ( pCustTB )
298  {
300  if ( !pCustTB->ImportMenuTB( rWrapper, xMenuDesc, helper ) )
301  return false;
302  if ( !bIsMenuToolbar )
303  {
304  if ( !helper.createMenu( pMenu->Name(), xMenuDesc ) )
305  return false;
306  }
307  else
308  {
309  beans::PropertyValue aProp;
310  aProp.Name = "ItemDescriptorContainer";
311  aProp.Value <<= uno::Reference< container::XIndexContainer >(xMenuDesc);
312  props.push_back( aProp );
313  }
314  }
315  }
316 
317  if ( bBeginGroup )
318  {
319  // insert spacer
320  uno::Sequence sProps{ comphelper::makePropertyValue("Type",
321  ui::ItemType::SEPARATOR_LINE) };
322  toolbarcontainer->insertByIndex( toolbarcontainer->getCount(), uno::Any( sProps ) );
323  }
324  toolbarcontainer->insertByIndex( toolbarcontainer->getCount(), uno::Any( comphelper::containerToSequence(props) ) );
325  }
326  return true;
327 }
328 
329 #ifdef DEBUG_SC_EXCEL
330 void
331 TBCCmd::Print(FILE* fp)
332 {
333  Indent a;
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 );
341 }
342 #endif
343 
345 {
346  SAL_INFO("sc.filter", "stream pos " << rS.Tell());
347  nOffSet = rS.Tell();
348  rS.ReadUInt16( cmdID );
349  sal_uInt16 temp;
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 );
356  return true;
357 }
358 
360 {
361 }
362 
364 {
365 }
366 
367 bool
369 {
370  SAL_INFO("sc.filter", "stream pos " << rS.Tell());
371  nOffSet = rS.Tell();
372  if (!ctbSet.Read(rS))
373  return false;
374 
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)
380  return false;
381 
382  for ( sal_uInt16 index = 0; index < ctbSet.ctb; ++index )
383  {
384  ScCTB aCTB( ctbSet.ctbViews );
385  if ( !aCTB.Read( rS ) )
386  return false;
387  rCTB.push_back( aCTB );
388  }
389  return true;
390 }
391 
392 #ifdef DEBUG_SC_EXCEL
393 void
394 ScCTBWrapper::Print( FILE* fp )
395 {
396  Indent a;
397  indent_printf( fp, "[ 0x%x ] ScCTBWrapper -- dump\n", nOffSet );
398  ctbSet.Print( fp );
399  for ( auto& rItem : rCTB )
400  {
401  Indent b;
402  rItem.Print( fp );
403  }
404 }
405 #endif
406 
407 ScCTB* ScCTBWrapper::GetCustomizationData( const OUString& sTBName )
408 {
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())
412  pCTB = &(*it);
413  return pCTB;
414 }
415 
417 {
418  if(rCTB.empty())
419  return;
420 
421  uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
422  uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xAppCfgSupp( ui::theModuleUIConfigurationManagerSupplier::get(xContext) );
423 
424  for ( auto& rItem : rCTB )
425  {
426  // for each customtoolbar
427  CustomToolBarImportHelper helper( rDocSh, xAppCfgSupp->getUIConfigurationManager( "com.sun.star.sheet.SpreadsheetDocument" ) );
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 )
433 
434  if ( !rItem.IsMenuToolbar() && !rItem.ImportCustomToolBar( *this, helper ) )
435  return;
436  }
437 }
438 
439 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool A
Definition: xltoolbar.hxx:24
OUString Name()
sal_uInt32 ectbid
Definition: xltoolbar.hxx:54
sal_Int16 getcCL() const
bool Read(SvStream &rS) override
bool IsEnabled() const
sal_uInt16 ctbViews
Definition: xltoolbar.hxx:78
bool Read(SvStream &rS) override
Definition: xltoolbar.cxx:243
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
CTBS()
Definition: xltoolbar.cxx:73
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
bool IsMenuToolbar() const
Definition: xltoolbar.cxx:155
std::map< sal_Int16, OUString > IdToString
Definition: xltoolbar.cxx:25
sal_uInt16 reserved3
Definition: xltoolbar.hxx:76
std::vector< TBVisualData > rVisualData
Definition: xltoolbar.hxx:53
sal_uInt16 reserved2
Definition: xltoolbar.hxx:75
bool ImportToolBarControl(ScCTBWrapper &, const css::uno::Reference< css::container::XIndexContainer > &toolbarcontainer, CustomToolBarImportHelper &helper, bool bIsMenuBar)
Definition: xltoolbar.cxx:280
sal_uInt16 ctb
Definition: xltoolbar.hxx:77
void ImportCustomToolBar(SfxObjectShell &rDocSh)
Definition: xltoolbar.cxx:416
sal_uInt64 remainingSize()
sal_uInt8 bVersion
Definition: xltoolbar.hxx:73
css::uno::Reference< css::ui::XUIConfigurationManager > getCfgManager()
std::shared_ptr< TBCData > tbcd
Definition: xltoolbar.hxx:39
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
sal_uInt8 bSignature
Definition: xltoolbar.hxx:72
std::map< sal_Int16, OUString > IdToString
T sanitizing_min(T a, T b)
sal_uInt16 ictbView
Definition: xltoolbar.hxx:79
std::vector< ScCTB > rCTB
Definition: xltoolbar.hxx:93
uno_Any a
bool Read(SvStream &rS) override
Definition: xltoolbar.cxx:211
ScCTB * GetCustomizationData(const OUString &name)
Definition: xltoolbar.cxx:407
bool createMenu(const OUString &rName, const css::uno::Reference< css::container::XIndexAccess > &xMenuDesc)
bool Read(SvStream &rS) override
Definition: xltoolbar.cxx:344
sal_uInt16 reserved1
Definition: xltoolbar.hxx:74
bool IsMenuToolbar() const
bool ImportCustomToolBar(ScCTBWrapper &, CustomToolBarImportHelper &)
Definition: xltoolbar.cxx:170
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
dictionary props
bool Read(SvStream &rS) override
bool Read(SvStream &rS) override
Definition: xltoolbar.cxx:81
SvStream & ReadUChar(unsigned char &rChar)
tuple index
sal_uInt16 nViews
Definition: xltoolbar.hxx:51
std::vector< ScTBC > rTBC
Definition: xltoolbar.hxx:55
sal_uInt32 nOffSet
sal_uInt16 getTcID() const
ScCTB(sal_uInt16)
Definition: xltoolbar.cxx:77
unsigned char sal_uInt8
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
TBCHeader tbch
Definition: xltoolbar.hxx:37
sal_uInt16 cmdType
Definition: xltoolbar.hxx:26
bool B
Definition: xltoolbar.hxx:25
virtual ~ScCTBWrapper() override
Definition: xltoolbar.cxx:363
#define SAL_INFO(area, stream)
sal_uInt8 getTct() const
WString & getName()
sal_uInt64 Tell() const
Reference< XComponentContext > getProcessComponentContext()
const char * name
const OUString & getString() const
std::shared_ptr< TBCCmd > tbcCmd
Definition: xltoolbar.hxx:38
bool Read(SvStream &rS) override
#define SAL_WARN(area, stream)
bool Read(SvStream &rS) override
Definition: xltoolbar.cxx:368
TB tb
Definition: xltoolbar.hxx:52
sal_uInt16 reserved3
Definition: xltoolbar.hxx:28
sal_uInt16 cmdID
Definition: xltoolbar.hxx:23
bool C
Definition: xltoolbar.hxx:27
bool ImportMenuTB(ScCTBWrapper &, const css::uno::Reference< css::container::XIndexContainer > &, CustomToolBarImportHelper &)
Definition: xltoolbar.cxx:160