android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / filter / ww8 / ww8toolbar.cxx
blobf8a271825d390a621d1f2caa3cb61e2bef9a9e68
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 */
10 #include "ww8toolbar.hxx"
11 #include "ww8scan.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/lang/XSingleComponentFactory.hpp>
16 #include <com/sun/star/ui/ItemType.hpp>
17 #include <fstream>
18 #include <comphelper/documentinfo.hxx>
19 #include <comphelper/indexedpropertyvalues.hxx>
20 #include <comphelper/processfactory.hxx>
21 #include <comphelper/propertyvalue.hxx>
22 #include <comphelper/sequence.hxx>
23 #include <o3tl/safeint.hxx>
24 #include <sfx2/objsh.hxx>
25 #include <comphelper/diagnose_ex.hxx>
26 #include <unotools/configmgr.hxx>
27 #include <rtl/ref.hxx>
28 #include <map>
29 #include <sal/log.hxx>
31 using namespace com::sun::star;
33 // no. of visual data elements in a SwCTB ( fixed )
34 const short nVisualData = 5;
36 typedef std::map< sal_Int16, OUString > IdToString;
38 namespace {
40 class MSOWordCommandConvertor : public MSOCommandConvertor
42 IdToString m_MSOToOOcmd;
43 IdToString m_TCIDToOOcmd;
45 public:
46 MSOWordCommandConvertor();
47 virtual OUString MSOCommandToOOCommand( sal_Int16 msoCmd ) override;
48 virtual OUString MSOTCIDToOOCommand( sal_Int16 key ) override;
53 MSOWordCommandConvertor::MSOWordCommandConvertor()
55 // mso command id to ooo command string
56 // #FIXME and *HUNDREDS* of id's to added here
57 m_MSOToOOcmd[ 0x20b ] = ".uno:CloseDoc";
58 m_MSOToOOcmd[ 0x50 ] = ".uno:Open";
60 // mso tcid to ooo command string
61 // #FIXME and *HUNDREDS* of id's to added here
62 m_TCIDToOOcmd[ 0x9d9 ] = ".uno:Print";
65 OUString MSOWordCommandConvertor::MSOCommandToOOCommand( sal_Int16 key )
67 IdToString::iterator it = m_MSOToOOcmd.find( key );
68 if ( it != m_MSOToOOcmd.end() )
69 return it->second;
70 return OUString();
73 OUString MSOWordCommandConvertor::MSOTCIDToOOCommand( sal_Int16 key )
75 IdToString::iterator it = m_TCIDToOOcmd.find( key );
76 if ( it != m_TCIDToOOcmd.end() )
77 return it->second;
78 return OUString();
81 SwCTBWrapper::SwCTBWrapper() :
82 m_reserved2(0)
83 ,m_reserved3(0)
84 ,m_reserved4(0)
85 ,m_reserved5(0)
86 ,m_cbTBD(0)
87 ,m_cCust(0)
88 ,m_cbDTBC(0)
89 ,m_rtbdc(0)
93 SwCTBWrapper::~SwCTBWrapper()
97 Customization* SwCTBWrapper::GetCustomizaton( sal_Int16 index )
99 if ( index < 0 || o3tl::make_unsigned(index) >= m_rCustomizations.size() )
100 return nullptr;
101 return &m_rCustomizations[ index ];
104 SwCTB* SwCTBWrapper::GetCustomizationData( const OUString& sTBName )
106 auto it = std::find_if(m_rCustomizations.begin(), m_rCustomizations.end(),
107 [&sTBName](Customization& rCustomization) {
108 SwCTB* pCTB = rCustomization.GetCustomizationData();
109 return pCTB && pCTB->GetName() == sTBName;
111 if (it != m_rCustomizations.end())
112 return it->GetCustomizationData();
113 return nullptr;
116 bool SwCTBWrapper::Read( SvStream& rS )
118 SAL_INFO("sw.ww8","SwCTBWrapper::Read() stream pos 0x" << std::hex << rS.Tell() );
119 nOffSet = rS.Tell();
120 Tcg255SubStruct::Read( rS );
121 rS.ReadUInt16( m_reserved2 ).ReadUChar( m_reserved3 ).ReadUInt16( m_reserved4 ).ReadUInt16( m_reserved5 );
122 rS.ReadInt16( m_cbTBD ).ReadUInt16( m_cCust ).ReadInt32( m_cbDTBC );
123 sal_uInt64 nExpectedPos = rS.Tell() + m_cbDTBC;
124 if ( m_cbDTBC )
126 // cbDTBC is the size in bytes of the SwTBC array
127 // but the size of a SwTBC element is dynamic ( and this relates to TBDelta's
128 int nStart = rS.Tell();
130 int bytesToRead;
131 // cbDTBC specifies the size ( in bytes ) taken by an array ( of unspecified size )
132 // of SwTBC records ( SwTBC records have dynamic length, so we need to check our position
133 // after each read )
136 SwTBC aTBC;
137 if ( !aTBC.Read( rS ) )
138 return false;
139 m_rtbdc.push_back( aTBC );
140 bytesToRead = m_cbDTBC - ( rS.Tell() - nStart );
141 } while ( bytesToRead > 0 );
143 if ( rS.Tell() != nExpectedPos )
145 // Strange error condition, shouldn't happen ( but does in at least
146 // one test document ) In the case where it happens the SwTBC &
147 // TBCHeader records seem blank??? ( and incorrect )
148 SAL_WARN_IF( rS.Tell() != nExpectedPos, "sw.ww8","### Error: Expected pos not equal to actual pos after reading rtbdc");
149 SAL_INFO("sw.ww8","\tPos now is 0x" << std::hex << rS.Tell() << " should be 0x" << std::hex << nExpectedPos );
150 // seek to correct position after rtbdc
151 rS.Seek( nExpectedPos );
153 if (m_cCust)
155 //Each customization takes a min of 8 bytes
156 size_t nMaxPossibleRecords = rS.remainingSize() / 8;
157 if (m_cCust > nMaxPossibleRecords)
159 return false;
161 for (sal_uInt16 index = 0; index < m_cCust; ++index)
163 Customization aCust( this );
164 if ( !aCust.Read( rS ) )
165 return false;
166 m_rCustomizations.push_back( aCust );
169 for ( const auto& rIndex : m_dropDownMenuIndices )
171 if (rIndex < 0 || o3tl::make_unsigned(rIndex) >= m_rCustomizations.size())
172 continue;
173 m_rCustomizations[rIndex].m_bIsDroppedMenuTB = true;
175 return rS.good();
178 SwTBC* SwCTBWrapper::GetTBCAtOffset( sal_uInt32 nStreamOffset )
180 auto it = std::find_if(m_rtbdc.begin(), m_rtbdc.end(),
181 [&nStreamOffset](SwTBC& rItem) { return rItem.GetOffset() == nStreamOffset; });
182 if ( it != m_rtbdc.end() )
183 return &(*it);
184 return nullptr;
187 bool SwCTBWrapper::ImportCustomToolBar( SfxObjectShell& rDocSh )
189 for ( auto& rCustomization : m_rCustomizations )
193 css::uno::Reference<css::ui::XUIConfigurationManager> xCfgMgr;
194 if (!utl::ConfigManager::IsFuzzing())
196 uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
197 uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xAppCfgSupp( ui::theModuleUIConfigurationManagerSupplier::get(xContext) );
198 xCfgMgr = xAppCfgSupp->getUIConfigurationManager("com.sun.star.text.TextDocument");
200 CustomToolBarImportHelper helper(rDocSh, xCfgMgr);
201 helper.setMSOCommandMap( new MSOWordCommandConvertor() );
203 if ( !rCustomization.ImportCustomToolBar( *this, helper ) )
204 return false;
206 catch (...)
208 continue;
211 return true;
214 Customization::Customization( SwCTBWrapper* wrapper )
215 : m_tbidForTBD( 0 )
216 , m_reserved1( 0 )
217 , m_ctbds( 0 )
218 , m_pWrapper( wrapper )
219 , m_bIsDroppedMenuTB( false )
223 bool Customization::Read( SvStream &rS)
225 SAL_INFO("sw.ww8","Customization::Read() stream pos 0x" << std::hex << rS.Tell() );
226 nOffSet = rS.Tell();
227 rS.ReadInt32( m_tbidForTBD ).ReadUInt16( m_reserved1 ).ReadUInt16( m_ctbds );
228 if ( m_tbidForTBD )
230 //each TBDelta is at least 18 bytes in size
231 size_t nMaxAvailableRecords = rS.remainingSize() / 18;
232 if (m_ctbds > nMaxAvailableRecords)
233 return false;
234 for (sal_uInt16 index = 0; index < m_ctbds; ++index)
236 TBDelta aTBDelta;
237 if (!aTBDelta.Read( rS ) )
238 return false;
239 m_customizationDataTBDelta.push_back( aTBDelta );
240 // Only set the drop down for menus associated with standard toolbar
241 if ( aTBDelta.ControlDropsToolBar() && m_tbidForTBD == 0x25 )
242 m_pWrapper->InsertDropIndex( aTBDelta.CustomizationIndex() );
245 else
247 m_customizationDataCTB = std::make_shared<SwCTB>();
248 if ( !m_customizationDataCTB->Read( rS ) )
249 return false;
251 return rS.good();
254 bool Customization::ImportMenu( SwCTBWrapper& rWrapper, CustomToolBarImportHelper& helper )
256 if ( m_tbidForTBD == 0x25 ) // we can handle in a limited way additions the built-in menu bar
258 for ( auto& rTBDelta : m_customizationDataTBDelta )
260 // for each new menu ( control that drops a toolbar )
261 // import a toolbar
262 if ( rTBDelta.ControlIsInserted() && rTBDelta.ControlDropsToolBar() )
264 Customization* pCust = m_pWrapper->GetCustomizaton( rTBDelta.CustomizationIndex() );
265 if ( pCust )
267 // currently only support built-in menu
268 static const OUStringLiteral sMenuBar( u"private:resource/menubar/menubar" );
270 // Get menu name
271 SwTBC* pTBC = m_pWrapper->GetTBCAtOffset( rTBDelta.TBCStreamOffset() );
272 if ( !pTBC )
273 return false;
274 const OUString sMenuName = pTBC->GetCustomText().replace('&','~');
276 // see if the document has already setting for the menubar
278 uno::Reference< container::XIndexContainer > xIndexContainer;
279 bool bHasSettings = false;
280 if ( helper.getCfgManager()->hasSettings( sMenuBar ) )
282 xIndexContainer.set( helper.getCfgManager()->getSettings( sMenuBar, true ), uno::UNO_QUERY_THROW );
283 bHasSettings = true;
285 else
287 if ( helper.getAppCfgManager()->hasSettings( sMenuBar ) )
288 xIndexContainer.set( helper.getAppCfgManager()->getSettings( sMenuBar, true ), uno::UNO_QUERY_THROW );
289 else
290 xIndexContainer.set( helper.getAppCfgManager()->createSettings(), uno::UNO_SET_THROW );
293 uno::Reference< lang::XSingleComponentFactory > xSCF( xIndexContainer, uno::UNO_QUERY_THROW );
294 uno::Reference< uno::XComponentContext > xContext(
295 comphelper::getProcessComponentContext() );
296 uno::Reference< container::XIndexContainer > xMenuContainer( xSCF->createInstanceWithContext( xContext ), uno::UNO_QUERY_THROW );
297 // create the popup menu
298 uno::Sequence< beans::PropertyValue > aPopupMenu{
299 comphelper::makePropertyValue("CommandURL", "vnd.openoffice.org:" + sMenuName),
300 comphelper::makePropertyValue("Label", sMenuName),
301 comphelper::makePropertyValue("Type", sal_Int32( 0 )),
302 comphelper::makePropertyValue("ItemDescriptorContainer", xMenuContainer)
304 if ( pCust->m_customizationDataCTB && !pCust->m_customizationDataCTB->ImportMenuTB( rWrapper, xMenuContainer, helper ) )
305 return false;
306 SAL_INFO("sw.ww8","** there are " << xIndexContainer->getCount() << " menu items on the bar, inserting after that");
307 xIndexContainer->insertByIndex( xIndexContainer->getCount(), uno::Any( aPopupMenu ) );
309 if ( bHasSettings )
310 helper.getCfgManager()->replaceSettings( sMenuBar, uno::Reference< container::XIndexAccess >( xIndexContainer, uno::UNO_QUERY_THROW ) );
311 else
312 helper.getCfgManager()->insertSettings( sMenuBar, uno::Reference< container::XIndexAccess >( xIndexContainer, uno::UNO_QUERY_THROW ) );
314 uno::Reference< ui::XUIConfigurationPersistence > xPersistence( helper.getCfgManager(), uno::UNO_QUERY_THROW );
315 xPersistence->store();
319 return true;
321 return true;
324 bool Customization::ImportCustomToolBar( SwCTBWrapper& rWrapper, CustomToolBarImportHelper& helper )
326 if ( m_tbidForTBD == 0x25 )
327 return ImportMenu( rWrapper, helper );
328 if ( !m_customizationDataCTB )
329 return false;
330 if ( !m_customizationDataCTB->IsMenuToolbar() )
332 if ( !m_customizationDataCTB->ImportCustomToolBar( rWrapper, helper ) )
333 return false;
335 return true;
338 TBDelta::TBDelta()
339 : m_doprfatendFlags(0)
340 , m_ibts(0)
341 , m_cidNext(0)
342 , m_cid(0)
343 , m_fc(0)
344 , m_CiTBDE(0)
345 , m_cbTBC(0)
349 bool TBDelta::ControlIsInserted()
351 return ( ( m_doprfatendFlags & 0x3 ) == 0x1 );
354 bool TBDelta::ControlDropsToolBar()
356 return !( m_CiTBDE & 0x8000 );
360 sal_Int16 TBDelta::CustomizationIndex()
362 sal_Int16 nIndex = m_CiTBDE;
363 nIndex = nIndex >> 1;
364 nIndex &= 0x1ff; // only 13 bits are relevant
365 return nIndex;
368 bool TBDelta::Read(SvStream &rS)
370 SAL_INFO("sw.ww8","TBDelta::Read() stream pos 0x" << std::hex << rS.Tell() );
371 nOffSet = rS.Tell();
372 rS.ReadUChar( m_doprfatendFlags ).ReadUChar( m_ibts ).ReadInt32( m_cidNext ).ReadInt32( m_cid ).ReadInt32( m_fc ) ;
373 rS.ReadUInt16( m_CiTBDE ).ReadUInt16( m_cbTBC );
374 return rS.good();
377 SwCTB::SwCTB() : m_cbTBData( 0 )
378 ,m_iWCTBl( 0 )
379 ,m_reserved( 0 )
380 ,m_unused( 0 )
381 ,m_cCtls( 0 )
385 SwCTB::~SwCTB()
389 bool SwCTB::IsMenuToolbar() const
391 return m_tb.IsMenuToolbar();
394 bool SwCTB::Read( SvStream &rS)
396 SAL_INFO("sw.ww8","SwCTB::Read() stream pos 0x" << std::hex << rS.Tell() );
397 nOffSet = rS.Tell();
398 if ( !m_name.Read( rS ) )
399 return false;
400 rS.ReadInt32( m_cbTBData );
401 if ( !m_tb.Read( rS ) )
402 return false;
403 for ( short index = 0; index < nVisualData; ++index )
405 TBVisualData aVisData;
406 aVisData.Read( rS );
407 m_rVisualData.push_back( aVisData );
410 rS.ReadInt32( m_iWCTBl ).ReadUInt16( m_reserved ).ReadUInt16( m_unused ).ReadInt32( m_cCtls );
412 if ( m_cCtls )
414 for ( sal_Int32 index = 0; index < m_cCtls; ++index )
416 SwTBC aTBC;
417 if ( !aTBC.Read( rS ) )
418 return false;
419 m_rTBC.push_back( aTBC );
422 return rS.good();
425 bool SwCTB::ImportCustomToolBar( SwCTBWrapper& rWrapper, CustomToolBarImportHelper& helper )
427 bool bRes = false;
430 if ( !m_tb.IsEnabled() )
431 return true; // didn't fail, just ignoring
432 // Create default setting
433 uno::Reference< container::XIndexContainer > xIndexContainer( helper.getCfgManager()->createSettings(), uno::UNO_SET_THROW );
434 uno::Reference< container::XIndexAccess > xIndexAccess( xIndexContainer, uno::UNO_QUERY_THROW );
435 uno::Reference< beans::XPropertySet > xProps( xIndexContainer, uno::UNO_QUERY_THROW );
437 // set UI name for toolbar
438 xProps->setPropertyValue( "UIName", uno::Any( m_name.getString() ) );
440 const OUString sToolBarName = "private:resource/toolbar/custom_" + m_name.getString();
441 for ( auto& rItem : m_rTBC )
443 // createToolBar item for control
444 if ( !rItem.ImportToolBarControl( rWrapper, xIndexContainer, helper, IsMenuToolbar() ) )
445 return false;
448 SAL_INFO("sw.ww8","Name of toolbar :-/ " << sToolBarName );
450 helper.getCfgManager()->insertSettings( sToolBarName, xIndexAccess );
451 helper.applyIcons();
452 #if 1 // don't think this is necessary
453 uno::Reference< ui::XUIConfigurationPersistence > xPersistence( helper.getCfgManager()->getImageManager(), uno::UNO_QUERY_THROW );
454 xPersistence->store();
456 xPersistence.set( helper.getCfgManager(), uno::UNO_QUERY_THROW );
457 xPersistence->store();
458 #endif
459 bRes = true;
461 catch( const uno::Exception& )
463 TOOLS_INFO_EXCEPTION("sw.ww8","***** For some reason we have an" );
464 bRes = false;
466 return bRes;
469 bool SwCTB::ImportMenuTB( SwCTBWrapper& rWrapper, const css::uno::Reference< css::container::XIndexContainer >& xIndexContainer, CustomToolBarImportHelper& rHelper )
471 for ( auto& rItem : m_rTBC )
473 // createToolBar item for control
474 if ( !rItem.ImportToolBarControl( rWrapper, xIndexContainer, rHelper, true ) )
475 return false;
477 return true;
480 SwTBC::SwTBC()
484 bool SwTBC::Read( SvStream &rS )
486 SAL_INFO("sw.ww8","SwTBC::Read() stream pos 0x" << std::hex << rS.Tell() );
487 nOffSet = rS.Tell();
488 if ( !m_tbch.Read( rS ) )
489 return false;
490 if ( m_tbch.getTcID() != 0x1 && m_tbch.getTcID() != 0x1051 )
492 m_cid = std::make_shared<sal_uInt32>();
493 rS.ReadUInt32( *m_cid );
495 // MUST exist if tbch.tct is not equal to 0x16
496 if ( m_tbch.getTct() != 0x16 )
498 m_tbcd = std::make_shared<TBCData>( m_tbch );
499 if ( !m_tbcd->Read( rS ) )
500 return false;
502 return rS.good();
505 bool
506 SwTBC::ImportToolBarControl( SwCTBWrapper& rWrapper, const css::uno::Reference< css::container::XIndexContainer >& toolbarcontainer, CustomToolBarImportHelper& helper, bool bIsMenuBar )
508 // cmtFci 0x1 Command based on a built-in command. See CidFci.
509 // cmtMacro 0x2 Macro command. See CidMacro.
510 // cmtAllocated 0x3 Allocated command. See CidAllocated.
511 // cmtNil 0x7 No command. See Cid.
512 bool bBuiltin = false;
513 sal_Int16 cmdId = 0;
514 if ( m_cid )
516 const sal_uInt32 nCid = ( *m_cid & 0xFFFF );
518 const sal_uInt8 cmt = static_cast<sal_uInt8>( nCid & 0x7 );
519 const sal_Int16 arg2 = static_cast<sal_Int16>( nCid >> 3 );
521 switch ( cmt )
523 case 1:
524 SAL_INFO("sw.ww8","cmt is cmtFci builtin command 0x" << std::hex << arg2);
525 bBuiltin = true;
526 cmdId = arg2;
527 break;
528 case 2:
529 SAL_INFO("sw.ww8","cmt is cmtMacro macro 0x" << std::hex << arg2);
530 break;
531 case 3:
532 SAL_INFO("sw.ww8","cmt is cmtAllocated [???] 0x" << std::hex << arg2);
533 break;
534 case 7:
535 SAL_INFO("sw.ww8","cmt is cmNill no-thing 0x" << std::hex << arg2);
536 break;
537 default:
538 SAL_INFO("sw.ww8","illegal 0x" << std::hex << cmt);
539 break;
543 if ( m_tbcd )
545 std::vector< css::beans::PropertyValue > props;
546 if ( bBuiltin )
548 const OUString sCommand = helper.MSOCommandToOOCommand( cmdId );
549 if ( !sCommand.isEmpty() )
551 beans::PropertyValue aProp;
553 aProp.Name = "CommandURL";
554 aProp.Value <<= sCommand;
555 props.push_back( aProp );
558 bool bBeginGroup = false;
559 m_tbcd->ImportToolBarControl( helper, props, bBeginGroup, bIsMenuBar );
561 TBCMenuSpecific* pMenu = m_tbcd->getMenuSpecific();
562 if ( pMenu )
564 SAL_INFO("sw.ww8","** control has a menu, name of toolbar with menu items is " << pMenu->Name() );
565 // search for SwCTB with the appropriate name ( it contains the
566 // menu items, although we cannot import ( or create ) a menu on
567 // a custom toolbar we can import the menu items in a separate
568 // toolbar ( better than nothing )
569 SwCTB* pCustTB = rWrapper.GetCustomizationData( pMenu->Name() );
570 if ( pCustTB )
572 rtl::Reference< comphelper::IndexedPropertyValuesContainer > xMenuDesc = new comphelper::IndexedPropertyValuesContainer();
573 if ( !pCustTB->ImportMenuTB( rWrapper,xMenuDesc, helper ) )
574 return false;
575 if ( !bIsMenuBar )
577 if ( !helper.createMenu( pMenu->Name(), xMenuDesc ) )
578 return false;
580 else
582 beans::PropertyValue aProp;
583 aProp.Name = "ItemDescriptorContainer";
584 aProp.Value <<= uno::Reference< container::XIndexContainer >(xMenuDesc);
585 props.push_back( aProp );
590 if ( bBeginGroup )
592 // insert spacer
593 uno::Sequence< beans::PropertyValue > sProps{ comphelper::makePropertyValue(
594 "Type", ui::ItemType::SEPARATOR_LINE) };
595 toolbarcontainer->insertByIndex( toolbarcontainer->getCount(), uno::Any( sProps ) );
598 toolbarcontainer->insertByIndex( toolbarcontainer->getCount(), uno::Any( comphelper::containerToSequence(props) ) );
600 return true;
603 OUString
604 SwTBC::GetCustomText()
606 if ( m_tbcd )
607 return m_tbcd->getGeneralInfo().CustomText();
608 return OUString();
611 bool
612 Xst::Read( SvStream& rS )
614 SAL_INFO("sw.ww8","Xst::Read() stream pos 0x" << std::hex << rS.Tell() );
615 nOffSet = rS.Tell();
616 m_sString = read_uInt16_PascalString(rS);
617 return rS.good();
620 Tcg::Tcg() : m_nTcgVer( -1 )
624 bool Tcg::Read(SvStream &rS)
626 SAL_INFO("sw.ww8","Tcg::Read() stream pos 0x" << std::hex << rS.Tell() );
627 nOffSet = rS.Tell();
628 rS.ReadSChar( m_nTcgVer );
629 if ( m_nTcgVer != -1 )
630 return false;
631 m_tcg.reset( new Tcg255() );
632 return m_tcg->Read( rS );
635 bool Tcg::ImportCustomToolBar( SfxObjectShell& rDocSh )
637 if (m_tcg)
638 return m_tcg->ImportCustomToolBar( rDocSh );
639 return false;
642 Tcg255::Tcg255()
646 Tcg255::~Tcg255()
650 bool Tcg255::processSubStruct( sal_uInt8 nId, SvStream &rS )
652 std::unique_ptr<Tcg255SubStruct> xSubStruct;
653 switch ( nId )
655 case 0x1:
657 xSubStruct.reset(new PlfMcd);
658 break;
660 case 0x2:
662 xSubStruct.reset(new PlfAcd);
663 break;
665 case 0x3:
666 case 0x4:
668 xSubStruct.reset(new PlfKme);
669 break;
671 case 0x10:
673 xSubStruct.reset(new TcgSttbf);
674 break;
676 case 0x11:
678 xSubStruct.reset(new MacroNames);
679 break;
681 case 0x12:
683 xSubStruct.reset(new SwCTBWrapper);
684 break;
686 default:
687 SAL_INFO("sw.ww8","Unknown id 0x" << std::hex << nId);
688 return false;
690 xSubStruct->m_ch = nId;
691 if (!xSubStruct->Read(rS))
692 return false;
693 m_rgtcgData.push_back(std::move(xSubStruct));
694 return true;
697 bool Tcg255::ImportCustomToolBar( SfxObjectShell& rDocSh )
699 // Find the SwCTBWrapper
700 for ( const auto & rSubStruct : m_rgtcgData )
702 if ( rSubStruct->id() == 0x12 )
704 // not so great, shouldn't really have to do a horror casting
705 SwCTBWrapper* pCTBWrapper = dynamic_cast< SwCTBWrapper* > ( rSubStruct.get() );
706 if ( pCTBWrapper )
708 // tdf#127048 set this flag if we might import something
709 uno::Reference<frame::XModel> const xModel(rDocSh.GetBaseModel());
710 comphelper::DocumentInfo::notifyMacroEventRead(xModel);
712 if ( !pCTBWrapper->ImportCustomToolBar( rDocSh ) )
713 return false;
717 return true;
720 bool Tcg255::Read(SvStream &rS)
722 SAL_INFO("sw.ww8","Tcg255::Read() stream pos 0x" << std::hex << rS.Tell() );
723 nOffSet = rS.Tell();
724 sal_uInt8 nId = 0x40;
725 rS.ReadUChar( nId );
726 while ( nId != 0x40 )
728 if ( !processSubStruct( nId, rS ) )
729 return false;
730 nId = 0x40;
731 rS.ReadUChar( nId );
733 return rS.good();
734 // Peek at
737 Tcg255SubStruct::Tcg255SubStruct( ) : m_ch(0)
741 bool Tcg255SubStruct::Read(SvStream &rS)
743 SAL_INFO("sw.ww8","Tcg255SubStruct::Read() stream pos 0x" << std::hex << rS.Tell() );
744 nOffSet = rS.Tell();
745 return rS.good();
748 PlfMcd::PlfMcd()
749 : m_iMac(0)
753 bool PlfMcd::Read(SvStream &rS)
755 SAL_INFO("sw.ww8","PffMcd::Read() stream pos 0x" << std::hex << rS.Tell() );
756 nOffSet = rS.Tell();
757 Tcg255SubStruct::Read( rS );
758 rS.ReadInt32( m_iMac );
759 if (m_iMac < 0)
760 return false;
761 auto nMaxPossibleRecords = rS.remainingSize() / 24 /*sizeof MCD*/;
762 if (o3tl::make_unsigned(m_iMac) > nMaxPossibleRecords)
764 SAL_WARN("sw.ww8", m_iMac << " records claimed, but max possible is " << nMaxPossibleRecords);
765 m_iMac = nMaxPossibleRecords;
767 if (m_iMac)
769 m_rgmcd.resize(m_iMac);
770 for ( sal_Int32 index = 0; index < m_iMac; ++index )
772 if ( !m_rgmcd[ index ].Read( rS ) )
773 return false;
776 return rS.good();
779 PlfAcd::PlfAcd() :
780 m_iMac(0)
784 PlfAcd::~PlfAcd()
788 bool PlfAcd::Read( SvStream &rS)
790 SAL_INFO("sw.ww8","PffAcd::Read() stream pos 0x" << std::hex << rS.Tell() );
791 nOffSet = rS.Tell();
792 Tcg255SubStruct::Read( rS );
793 rS.ReadInt32( m_iMac );
794 if (m_iMac < 0)
795 return false;
796 auto nMaxPossibleRecords = rS.remainingSize() / (sizeof(sal_uInt16)*2);
797 if (o3tl::make_unsigned(m_iMac) > nMaxPossibleRecords)
799 SAL_WARN("sw.ww8", m_iMac << " records claimed, but max possible is " << nMaxPossibleRecords);
800 m_iMac = nMaxPossibleRecords;
802 if (m_iMac)
804 m_rgacd.reset( new Acd[ m_iMac ] );
805 for ( sal_Int32 index = 0; index < m_iMac; ++index )
807 if ( !m_rgacd[ index ].Read( rS ) )
808 return false;
811 return rS.good();
814 PlfKme::PlfKme() :
815 m_iMac( 0 )
819 PlfKme::~PlfKme()
823 bool PlfKme::Read(SvStream &rS)
825 SAL_INFO("sw.ww8","PlfKme::Read() stream pos 0x" << std::hex << rS.Tell() );
826 nOffSet = rS.Tell();
827 Tcg255SubStruct::Read( rS );
828 rS.ReadInt32( m_iMac );
829 if (m_iMac > 0)
831 //each Kme is 14 bytes in size
832 size_t nMaxAvailableRecords = rS.remainingSize() / 14;
833 if (o3tl::make_unsigned(m_iMac) > nMaxAvailableRecords)
834 return false;
836 m_rgkme.reset( new Kme[ m_iMac ] );
837 for( sal_Int32 index=0; index<m_iMac; ++index )
839 if ( !m_rgkme[ index ].Read( rS ) )
840 return false;
843 return rS.good();
846 TcgSttbf::TcgSttbf()
850 bool TcgSttbf::Read( SvStream &rS)
852 SAL_INFO("sw.ww8","TcgSttbf::Read() stream pos 0x" << std::hex << rS.Tell() );
853 nOffSet = rS.Tell();
854 Tcg255SubStruct::Read( rS );
855 return m_sttbf.Read( rS );
858 TcgSttbfCore::TcgSttbfCore() : m_fExtend( 0 )
859 ,m_cData( 0 )
860 ,m_cbExtra( 0 )
864 TcgSttbfCore::~TcgSttbfCore()
868 bool TcgSttbfCore::Read( SvStream& rS )
870 SAL_INFO("sw.ww8","TcgSttbfCore::Read() stream pos 0x" << std::hex << rS.Tell() );
871 nOffSet = rS.Tell();
872 rS.ReadUInt16( m_fExtend ).ReadUInt16( m_cData ).ReadUInt16( m_cbExtra );
873 if ( m_cData )
875 if (m_cData > rS.remainingSize() / 4) //definitely an invalid record
876 return false;
877 m_dataItems.reset( new SBBItem[ m_cData ] );
878 for ( sal_Int32 index = 0; index < m_cData; ++index )
880 rS.ReadUInt16( m_dataItems[ index ].cchData );
881 m_dataItems[ index ].data = read_uInt16s_ToOUString(rS, m_dataItems[index].cchData);
882 rS.ReadUInt16( m_dataItems[ index ].extraData );
885 return rS.good();
888 MacroNames::MacroNames() :
889 m_iMac( 0 )
893 MacroNames::~MacroNames()
897 bool MacroNames::Read( SvStream &rS)
899 SAL_INFO("sw.ww8","MacroNames::Read() stream pos 0x" << std::hex << rS.Tell() );
900 nOffSet = rS.Tell();
901 Tcg255SubStruct::Read( rS );
902 rS.ReadUInt16( m_iMac );
903 if ( m_iMac )
905 //even an empty MacroName will take 2 bytes
906 size_t nMaxAvailableRecords = rS.remainingSize()/sizeof(sal_uInt16);
907 if (m_iMac > nMaxAvailableRecords)
908 return false;
909 m_rgNames.reset( new MacroName[ m_iMac ] );
910 for ( sal_Int32 index = 0; index < m_iMac; ++index )
912 if ( !m_rgNames[ index ].Read( rS ) )
913 return false;
916 return rS.good();
919 MacroName::MacroName():m_ibst(0)
923 bool MacroName::Read(SvStream &rS)
925 SAL_INFO("sw.ww8","MacroName::Read() stream pos 0x" << std::hex << rS.Tell() );
926 nOffSet = rS.Tell();
927 rS.ReadUInt16( m_ibst );
928 return m_xstz.Read( rS );
931 Xstz::Xstz():m_chTerm(0)
935 bool
936 Xstz::Read(SvStream &rS)
938 SAL_INFO("sw.ww8","Xstz::Read() stream pos 0x" << std::hex << rS.Tell() );
939 nOffSet = rS.Tell();
940 if ( !m_xst.Read( rS ) )
941 return false;
942 rS.ReadUInt16( m_chTerm );
943 if ( m_chTerm != 0 ) // should be an assert
944 return false;
945 return rS.good();
948 Kme::Kme() : m_reserved1(0)
949 ,m_reserved2(0)
950 ,m_kcm1(0)
951 ,m_kcm2(0)
952 ,m_kt(0)
953 ,m_param(0)
957 Kme::~Kme()
961 bool
962 Kme::Read(SvStream &rS)
964 SAL_INFO("sw.ww8","Kme::Read() stream pos 0x" << std::hex << rS.Tell() );
965 nOffSet = rS.Tell();
966 rS.ReadInt16( m_reserved1 ).ReadInt16( m_reserved2 ).ReadUInt16( m_kcm1 ).ReadUInt16( m_kcm2 ).ReadUInt16( m_kt ).ReadUInt32( m_param );
967 return rS.good();
970 Acd::Acd() : m_ibst( 0 )
971 , m_fciBasedOnABC( 0 )
975 bool Acd::Read(SvStream &rS)
977 SAL_INFO("sw.ww8","Acd::Read() stream pos 0x" << std::hex << rS.Tell() );
978 nOffSet = rS.Tell();
979 rS.ReadInt16( m_ibst ).ReadUInt16( m_fciBasedOnABC );
980 return rS.good();
983 MCD::MCD() : m_reserved1(0x56)
984 ,m_reserved2( 0 )
985 ,m_ibst( 0 )
986 ,m_ibstName( 0 )
987 ,m_reserved3( 0xFFFF )
988 ,m_reserved4( 0 )
989 ,m_reserved5( 0 )
990 ,m_reserved6( 0 )
991 ,m_reserved7( 0 )
995 bool MCD::Read(SvStream &rS)
997 SAL_INFO("sw.ww8","MCD::Read() stream pos 0x" << rS.Tell() );
998 nOffSet = rS.Tell();
999 rS.ReadSChar( m_reserved1 ).ReadUChar( m_reserved2 ).ReadUInt16( m_ibst ).ReadUInt16( m_ibstName ).ReadUInt16( m_reserved3 );
1000 rS.ReadUInt32( m_reserved4 ).ReadUInt32( m_reserved5 ).ReadUInt32( m_reserved6 ).ReadUInt32( m_reserved7 );
1001 return rS.good();
1004 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */