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/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>
18 #include <comphelper/sequence.hxx>
19 #include <map>
20 
21 using namespace com::sun::star;
22 
23 typedef std::map< sal_Int16, OUString > IdToString;
24 
25 namespace {
26 
27 class MSOExcelCommandConvertor : public MSOCommandConvertor
28 {
29  IdToString msoToOOcmd;
30  IdToString tcidToOOcmd;
31 public:
32  MSOExcelCommandConvertor();
33  virtual OUString MSOCommandToOOCommand( sal_Int16 msoCmd ) override;
34  virtual OUString MSOTCIDToOOCommand( sal_Int16 key ) override;
35 };
36 
37 }
38 
39 MSOExcelCommandConvertor::MSOExcelCommandConvertor()
40 {
41 /*
42  // mso command id to ooo command string
43  // #FIXME and *HUNDREDS* of id's to added here
44  msoToOOcmd[ 0x20b ] = ".uno:CloseDoc";
45  msoToOOcmd[ 0x50 ] = ".uno:Open";
46 
47  // mso tcid to ooo command string
48  // #FIXME and *HUNDREDS* of id's to added here
49  tcidToOOcmd[ 0x9d9 ] = ".uno:Print";
50 */
51 }
52 
53 OUString MSOExcelCommandConvertor::MSOCommandToOOCommand( sal_Int16 key )
54 {
55  OUString sResult;
56  IdToString::iterator it = msoToOOcmd.find( key );
57  if ( it != msoToOOcmd.end() )
58  sResult = it->second;
59  return sResult;
60 }
61 
62 OUString MSOExcelCommandConvertor::MSOTCIDToOOCommand( sal_Int16 key )
63 {
64  OUString sResult;
65  IdToString::iterator it = tcidToOOcmd.find( key );
66  if ( it != tcidToOOcmd.end() )
67  sResult = it->second;
68  return sResult;
69 }
70 
71 CTBS::CTBS() : bSignature(0), bVersion(0), reserved1(0), reserved2(0), reserved3(0), ctb(0), ctbViews(0), ictbView(0)
72 {
73 }
74 
75 ScCTB::ScCTB(sal_uInt16 nNum ) : nViews( nNum ), ectbid(0)
76 {
77 }
78 
79 bool ScCTB::Read( SvStream &rS )
80 {
81  SAL_INFO("sc.filter", "stream pos " << rS.Tell());
82  nOffSet = rS.Tell();
83  tb.Read( rS );
84 
85  {
86  const size_t nMinRecordSize = 20; // TBVisualData reads 20 bytes
87  const size_t nMaxPossibleRecords = rS.remainingSize() / nMinRecordSize;
88  if (nViews > nMaxPossibleRecords)
89  {
90  SAL_WARN("sc.filter", "ScCTB::Read more entries claimed than stream could contain");
91  return false;
92  }
93  }
94 
95  for ( sal_uInt16 index = 0; index < nViews; ++index )
96  {
97  TBVisualData aVisData;
98  aVisData.Read( rS );
99  rVisualData.push_back( aVisData );
100  }
101  rS.ReadUInt32( ectbid );
102 
103  sal_Int16 nCL = tb.getcCL();
104  if (nCL > 0)
105  {
106  auto nIndexes = o3tl::make_unsigned(nCL);
107 
108  const size_t nMinRecordSize = 11; // ScTBC's TBCHeader reads min 11 bytes
109  const size_t nMaxPossibleRecords = rS.remainingSize() / nMinRecordSize;
110  if (nIndexes > nMaxPossibleRecords)
111  {
112  SAL_WARN("sc.filter", "ScCTB::Read more entries claimed than stream could contain");
113  return false;
114  }
115 
116  for (decltype(nIndexes) index = 0; index < nIndexes; ++index)
117  {
118  ScTBC aTBC;
119  aTBC.Read( rS );
120  rTBC.push_back( aTBC );
121  }
122  }
123 
124  return true;
125 }
126 
127 #ifdef DEBUG_SC_EXCEL
128 void ScCTB::Print( FILE* fp )
129 {
130  Indent a;
131  indent_printf( fp, "[ 0x%x ] ScCTB -- dump\n", nOffSet );
132  indent_printf( fp, " nViews 0x%x\n", nViews);
133  tb.Print( fp );
134 
135  sal_Int32 counter = 0;
136  for ( auto& rItem : rVisualData )
137  {
138  indent_printf( fp, " TBVisualData [%d]\n", counter++ );
139  Indent b;
140  rItem.Print( fp );
141  }
142  indent_printf( fp, " ectbid 0x%x\n", ectbid);
143  counter = 0;
144  for ( auto& rItem : rTBC )
145  {
146  indent_printf( fp, " ScTBC [%d]\n", counter++);
147  Indent c;
148  rItem.Print( fp );
149  }
150 }
151 #endif
152 
154 {
155  return tb.IsMenuToolbar();
156 }
157 
158 bool ScCTB::ImportMenuTB( ScCTBWrapper& rWrapper, const css::uno::Reference< css::container::XIndexContainer >& xMenuDesc, CustomToolBarImportHelper& helper )
159 {
160  for ( auto& rItem : rTBC )
161  {
162  if ( !rItem.ImportToolBarControl( rWrapper, xMenuDesc, helper, IsMenuToolbar() ) )
163  return false;
164  }
165  return true;
166 }
167 
169 {
170 
171  bool bRes = false;
172  try
173  {
174  if ( !tb.IsEnabled() )
175  return true; // didn't fail, just ignoring
176 
177  // Create default setting
178  uno::Reference< container::XIndexContainer > xIndexContainer( helper.getCfgManager()->createSettings(), uno::UNO_SET_THROW );
179  uno::Reference< container::XIndexAccess > xIndexAccess( xIndexContainer, uno::UNO_QUERY_THROW );
180  uno::Reference< beans::XPropertySet > xProps( xIndexContainer, uno::UNO_QUERY_THROW );
181  WString& name = tb.getName();
182  // set UI name for toolbar
183  xProps->setPropertyValue("UIName", uno::makeAny( name.getString() ) );
184 
185  OUString sToolBarName = "private:resource/toolbar/custom_" + name.getString();
186  for ( auto& rItem : rTBC )
187  {
188  if ( !rItem.ImportToolBarControl( rWrapper, xIndexContainer, helper, IsMenuToolbar() ) )
189  return false;
190  }
191 
192  helper.getCfgManager()->insertSettings( sToolBarName, xIndexAccess );
193  helper.applyIcons();
194 
195  uno::Reference< ui::XUIConfigurationPersistence > xPersistence( helper.getCfgManager()->getImageManager(), uno::UNO_QUERY_THROW );
196  xPersistence->store();
197 
198  xPersistence.set( helper.getCfgManager(), uno::UNO_QUERY_THROW );
199  xPersistence->store();
200 
201  bRes = true;
202  }
203  catch( uno::Exception& )
204  {
205  bRes = false;
206  }
207  return bRes;
208 }
209 bool CTBS::Read( SvStream &rS )
210 {
211  SAL_INFO("sc.filter", "stream pos " << rS.Tell());
212  nOffSet = rS.Tell();
214  return true;
215 }
216 
217 #ifdef DEBUG_SC_EXCEL
218 void CTBS::Print( FILE* fp )
219 {
220  Indent a;
221  indent_printf( fp, "[ 0x%x ] CTBS -- dump\n", nOffSet );
222 
223  indent_printf( fp, " bSignature 0x%x\n", bSignature);
224  indent_printf( fp, " bVersion 0x%x\n", bVersion);
225 
226  indent_printf( fp, " reserved1 0x%x\n", reserved1 );
227  indent_printf( fp, " reserved2 0x%x\n", reserved2 );
228  indent_printf( fp, " reserved3 0x%x\n", reserved3 );
229 
230  indent_printf( fp, " ctb 0x%x\n", ctb );
231  indent_printf( fp, " ctbViews 0x%x\n", ctbViews );
232  indent_printf( fp, " ictbView 0x%x\n", ictbView );
233 }
234 #endif
235 
237 {
238 }
239 
240 bool
242 {
243  SAL_INFO("sc.filter", "stream pos " << rS.Tell());
244  nOffSet = rS.Tell();
245  if ( !tbch.Read( rS ) )
246  return false;
247  sal_uInt16 tcid = tbch.getTcID();
248  sal_uInt8 tct = tbch.getTct();
249  if ( ( tcid != 0x0001 && tcid != 0x06CC && tcid != 0x03D8 && tcid != 0x03EC && tcid != 0x1051 ) && ( ( tct > 0 && tct < 0x0B ) || ( ( tct > 0x0B && tct < 0x10 ) || tct == 0x15 ) ) )
250  {
251  tbcCmd = std::make_shared<TBCCmd>();
252  if ( ! tbcCmd->Read( rS ) )
253  return false;
254  }
255  if ( tct != 0x16 )
256  {
257  tbcd = std::make_shared<TBCData>( tbch );
258  if ( !tbcd->Read( rS ) )
259  return false;
260  }
261  return true;
262 }
263 
264 #ifdef DEBUG_SC_EXCEL
265 void
266 ScTBC::Print(FILE* fp)
267 {
268  Indent a;
269  indent_printf( fp, "[ 0x%x ] ScTBC -- dump\n", nOffSet );
270  tbch.Print( fp );
271  if ( tbcCmd.get() )
272  tbcCmd->Print( fp );
273  if ( tbcd.get() )
274  tbcd->Print( fp );
275 }
276 #endif
277 
278 bool ScTBC::ImportToolBarControl( ScCTBWrapper& rWrapper, const css::uno::Reference< css::container::XIndexContainer >& toolbarcontainer, CustomToolBarImportHelper& helper, bool bIsMenuToolbar )
279 {
280  // how to identify built-in-command ?
281 // bool bBuiltin = false;
282  if ( tbcd )
283  {
284  std::vector< css::beans::PropertyValue > props;
285  bool bBeginGroup = false;
286  tbcd->ImportToolBarControl( helper, props, bBeginGroup, bIsMenuToolbar );
287  TBCMenuSpecific* pMenu = tbcd->getMenuSpecific();
288  if ( pMenu )
289  {
290  // search for ScCTB with the appropriate name ( it contains the
291  // menu items, although we cannot import ( or create ) a menu on
292  // a custom toolbar we can import the menu items in a separate
293  // toolbar ( better than nothing )
294  ScCTB* pCustTB = rWrapper.GetCustomizationData( pMenu->Name() );
295  if ( pCustTB )
296  {
297  uno::Reference< container::XIndexContainer > xMenuDesc = document::IndexedPropertyValues::create( comphelper::getProcessComponentContext() );
298  if ( !pCustTB->ImportMenuTB( rWrapper, xMenuDesc, helper ) )
299  return false;
300  if ( !bIsMenuToolbar )
301  {
302  if ( !helper.createMenu( pMenu->Name(), xMenuDesc ) )
303  return false;
304  }
305  else
306  {
307  beans::PropertyValue aProp;
308  aProp.Name = "ItemDescriptorContainer";
309  aProp.Value <<= xMenuDesc;
310  props.push_back( aProp );
311  }
312  }
313  }
314 
315  if ( bBeginGroup )
316  {
317  // insert spacer
318  uno::Sequence< beans::PropertyValue > sProps( 1 );
319  sProps[ 0 ].Name = "Type";
320  sProps[ 0 ].Value <<= ui::ItemType::SEPARATOR_LINE;
321  toolbarcontainer->insertByIndex( toolbarcontainer->getCount(), uno::makeAny( sProps ) );
322  }
323  toolbarcontainer->insertByIndex( toolbarcontainer->getCount(), uno::makeAny( comphelper::containerToSequence(props) ) );
324  }
325  return true;
326 }
327 
328 #ifdef DEBUG_SC_EXCEL
329 void
330 TBCCmd::Print(FILE* fp)
331 {
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 );
340 }
341 #endif
342 
344 {
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;
356 }
357 
359 {
360 }
361 
363 {
364 }
365 
366 bool
368 {
369  SAL_INFO("sc.filter", "stream pos " << rS.Tell());
370  nOffSet = rS.Tell();
371  if (!ctbSet.Read(rS))
372  return false;
373 
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;
380 
381  for ( sal_uInt16 index = 0; index < ctbSet.ctb; ++index )
382  {
383  ScCTB aCTB( ctbSet.ctbViews );
384  if ( !aCTB.Read( rS ) )
385  return false;
386  rCTB.push_back( aCTB );
387  }
388  return true;
389 }
390 
391 #ifdef DEBUG_SC_EXCEL
392 void
393 ScCTBWrapper::Print( FILE* fp )
394 {
395  Indent a;
396  indent_printf( fp, "[ 0x%x ] ScCTBWrapper -- dump\n", nOffSet );
397  ctbSet.Print( fp );
398  for ( auto& rItem : rCTB )
399  {
400  Indent b;
401  rItem.Print( fp );
402  }
403 }
404 #endif
405 
406 ScCTB* ScCTBWrapper::GetCustomizationData( const OUString& sTBName )
407 {
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;
413 }
414 
416 {
417  if(rCTB.empty())
418  return;
419 
420  uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
421  uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xAppCfgSupp( ui::theModuleUIConfigurationManagerSupplier::get(xContext) );
422 
423  for ( auto& rItem : rCTB )
424  {
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 )
432 
433  if ( !rItem.IsMenuToolbar() && !rItem.ImportCustomToolBar( *this, helper ) )
434  return;
435  }
436 }
437 
438 /* 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:241
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
CTBS()
Definition: xltoolbar.cxx:71
bool IsMenuToolbar() const
Definition: xltoolbar.cxx:153
std::map< sal_Int16, OUString > IdToString
Definition: xltoolbar.cxx:23
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:278
sal_uInt16 ctb
Definition: xltoolbar.hxx:77
void ImportCustomToolBar(SfxObjectShell &rDocSh)
Definition: xltoolbar.cxx:415
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:209
ScCTB * GetCustomizationData(const OUString &name)
Definition: xltoolbar.cxx:406
bool createMenu(const OUString &rName, const css::uno::Reference< css::container::XIndexAccess > &xMenuDesc)
bool Read(SvStream &rS) override
Definition: xltoolbar.cxx:343
sal_uInt16 reserved1
Definition: xltoolbar.hxx:74
bool IsMenuToolbar() const
bool ImportCustomToolBar(ScCTBWrapper &, CustomToolBarImportHelper &)
Definition: xltoolbar.cxx:168
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:79
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:75
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:362
#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:367
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:158