Files
loongoffice/framework/source/fwe/xml/menudocumenthandler.cxx
Noel Grandin 248145f99e Find places where uno::Sequence is passed by value.
Implement a clang plugin to find them, and clean up existing code
to pass them by reference.

Change-Id: If642d87407c73346d9c0164b9fc77c5c3c4354b8
Reviewed-on: https://gerrit.libreoffice.org/9351
Reviewed-by: Noel Grandin <noelgrandin@gmail.com>
Tested-by: Noel Grandin <noelgrandin@gmail.com>
2014-05-14 08:10:22 +00:00

918 lines
32 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <stdio.h>
#include <sal/macros.h>
#include <xml/menudocumenthandler.hxx>
#include <framework/menuconfiguration.hxx>
#include <framework/addonmenu.hxx>
#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
#include <com/sun/star/lang/XSingleComponentFactory.hpp>
#include <com/sun/star/ui/ItemType.hpp>
#include <com/sun/star/ui/ItemStyle.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <comphelper/processfactory.hxx>
#include <comphelper/attributelist.hxx>
#define XMLNS_MENU "http://openoffice.org/2001/menu"
#define ELEMENT_MENUBAR "http://openoffice.org/2001/menu^menubar"
#define ELEMENT_MENU "http://openoffice.org/2001/menu^menu"
#define ELEMENT_MENUPOPUP "http://openoffice.org/2001/menu^menupopup"
#define ELEMENT_MENUITEM "http://openoffice.org/2001/menu^menuitem"
#define ELEMENT_MENUSEPARATOR "http://openoffice.org/2001/menu^menuseparator"
#define ELEMENT_NS_MENUBAR "menu:menubar"
#define ELEMENT_NS_MENU "menu:menu"
#define ELEMENT_NS_MENUPOPUP "menu:menupopup"
#define ELEMENT_NS_MENUITEM "menu:menuitem"
#define ELEMENT_NS_MENUSEPARATOR "menu:menuseparator"
#define ATTRIBUTE_ID "http://openoffice.org/2001/menu^id"
#define ATTRIBUTE_LABEL "http://openoffice.org/2001/menu^label"
#define ATTRIBUTE_HELPID "http://openoffice.org/2001/menu^helpid"
#define ATTRIBUTE_STYLE "http://openoffice.org/2001/menu^style"
#define ATTRIBUTE_NS_ID "menu:id"
#define ATTRIBUTE_NS_LABEL "menu:label"
#define ATTRIBUTE_NS_HELPID "menu:helpid"
#define ATTRIBUTE_NS_STYLE "menu:style"
#define ATTRIBUTE_XMLNS_MENU "xmlns:menu"
#define ATTRIBUTE_TYPE_CDATA "CDATA"
#define MENUBAR_DOCTYPE "<!DOCTYPE menu:menubar PUBLIC \"-//OpenOffice.org//DTD OfficeDocument 1.0//EN\" \"menubar.dtd\">"
#define ATTRIBUTE_ITEMSTYLE_TEXT "text"
#define ATTRIBUTE_ITEMSTYLE_IMAGE "image"
#define ATTRIBUTE_ITEMSTYLE_RADIO "radio"
// Property names of a menu/menu item ItemDescriptor
static const char ITEM_DESCRIPTOR_COMMANDURL[] = "CommandURL";
static const char ITEM_DESCRIPTOR_HELPURL[] = "HelpURL";
static const char ITEM_DESCRIPTOR_CONTAINER[] = "ItemDescriptorContainer";
static const char ITEM_DESCRIPTOR_LABEL[] = "Label";
static const char ITEM_DESCRIPTOR_TYPE[] = "Type";
static const char ITEM_DESCRIPTOR_STYLE[] = "Style";
// special popup menus (filled during runtime) must be saved as an empty popup menu or menuitem!!!
static const sal_Int32 CMD_PROTOCOL_SIZE = 5;
static const char CMD_PROTOCOL[] = ".uno:";
static const char ADDDIRECT_CMD[] = ".uno:AddDirect";
static const char AUTOPILOTMENU_CMD[] = ".uno:AutoPilotMenu";
// using namespaces
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::xml::sax;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::ui;
namespace framework
{
struct MenuStyleItem
{
sal_Int16 nBit;
const char* attrName;
};
MenuStyleItem MenuItemStyles[ ] = {
{ ::com::sun::star::ui::ItemStyle::ICON, ATTRIBUTE_ITEMSTYLE_IMAGE },
{ ::com::sun::star::ui::ItemStyle::TEXT, ATTRIBUTE_ITEMSTYLE_TEXT },
{ ::com::sun::star::ui::ItemStyle::RADIO_CHECK, ATTRIBUTE_ITEMSTYLE_RADIO }
};
sal_Int32 nMenuStyleItemEntries = (sizeof (MenuItemStyles) / sizeof (MenuItemStyles[0]));
static void ExtractMenuParameters( const Sequence< PropertyValue >& rProp,
OUString& rCommandURL,
OUString& rLabel,
OUString& rHelpURL,
Reference< XIndexAccess >& rSubMenu,
sal_Int16& rType,
sal_Int16& rStyle )
{
for ( sal_Int32 i = 0; i < rProp.getLength(); i++ )
{
if ( rProp[i].Name == ITEM_DESCRIPTOR_COMMANDURL )
{
rProp[i].Value >>= rCommandURL;
rCommandURL = rCommandURL.intern();
}
else if ( rProp[i].Name == ITEM_DESCRIPTOR_HELPURL )
{
rProp[i].Value >>= rHelpURL;
}
else if ( rProp[i].Name == ITEM_DESCRIPTOR_CONTAINER )
{
rProp[i].Value >>= rSubMenu;
}
else if ( rProp[i].Name == ITEM_DESCRIPTOR_LABEL )
{
rProp[i].Value >>= rLabel;
}
else if ( rProp[i].Name == ITEM_DESCRIPTOR_TYPE )
{
rProp[i].Value >>= rType;
}
else if ( rProp[i].Name == ITEM_DESCRIPTOR_STYLE )
{
rProp[i].Value >>= rStyle;
}
}
}
// Base class implementation
ReadMenuDocumentHandlerBase::ReadMenuDocumentHandlerBase() :
m_xLocator( 0 ),
m_xReader( 0 ),
m_aType( ITEM_DESCRIPTOR_TYPE ),
m_aLabel( ITEM_DESCRIPTOR_LABEL ),
m_aContainer( ITEM_DESCRIPTOR_CONTAINER ),
m_aHelpURL( ITEM_DESCRIPTOR_HELPURL ),
m_aCommandURL( ITEM_DESCRIPTOR_COMMANDURL ),
m_aStyle( ITEM_DESCRIPTOR_STYLE )
{
}
ReadMenuDocumentHandlerBase::~ReadMenuDocumentHandlerBase()
{
}
void SAL_CALL ReadMenuDocumentHandlerBase::ignorableWhitespace(
const OUString& )
throw( SAXException, RuntimeException, std::exception )
{
}
void SAL_CALL ReadMenuDocumentHandlerBase::processingInstruction(
const OUString& /*aTarget*/, const OUString& /*aData*/ )
throw( SAXException, RuntimeException, std::exception )
{
}
void SAL_CALL ReadMenuDocumentHandlerBase::setDocumentLocator(
const Reference< XLocator > &xLocator)
throw( SAXException, RuntimeException, std::exception )
{
m_xLocator = xLocator;
}
OUString ReadMenuDocumentHandlerBase::getErrorLineString()
{
char buffer[32];
if ( m_xLocator.is() )
{
snprintf( buffer, sizeof(buffer), "Line: %ld - ", static_cast<long>( m_xLocator->getLineNumber() ));
return OUString::createFromAscii( buffer );
}
else
return OUString();
}
void ReadMenuDocumentHandlerBase::initPropertyCommon(
Sequence< PropertyValue > &rProps, const OUString &rCommandURL,
const OUString &rHelpId, const OUString &rLabel, sal_Int16 nItemStyleBits )
{
rProps[0].Name = m_aCommandURL;
rProps[1].Name = m_aHelpURL;
rProps[2].Name = m_aContainer;
rProps[3].Name = m_aLabel;
rProps[4].Name = m_aStyle;
rProps[5].Name = m_aType;
// Common values
rProps[0].Value <<= rCommandURL.intern();
rProps[1].Value <<= rHelpId;
rProps[2].Value <<= Reference< XIndexContainer >();
rProps[3].Value <<= rLabel;
rProps[4].Value <<= nItemStyleBits;
rProps[5].Value <<= ::com::sun::star::ui::ItemType::DEFAULT;
}
OReadMenuDocumentHandler::OReadMenuDocumentHandler(
const Reference< XIndexContainer >& rMenuBarContainer )
: m_nElementDepth( 0 ),
m_bMenuBarMode( false ),
m_xMenuBarContainer( rMenuBarContainer ),
m_xContainerFactory( rMenuBarContainer, UNO_QUERY )
{
}
OReadMenuDocumentHandler::~OReadMenuDocumentHandler()
{
}
void SAL_CALL OReadMenuDocumentHandler::startDocument(void)
throw ( SAXException, RuntimeException, std::exception )
{
}
void SAL_CALL OReadMenuDocumentHandler::endDocument(void)
throw( SAXException, RuntimeException, std::exception )
{
if ( m_nElementDepth > 0 )
{
OUString aErrorMessage = getErrorLineString();
aErrorMessage += "A closing element is missing!";
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
}
void SAL_CALL OReadMenuDocumentHandler::startElement(
const OUString& aName, const Reference< XAttributeList > &xAttrList )
throw( SAXException, RuntimeException, std::exception )
{
if ( m_bMenuBarMode )
{
++m_nElementDepth;
m_xReader->startElement( aName, xAttrList );
}
else if ( aName == ELEMENT_MENUBAR )
{
++m_nElementDepth;
m_bMenuBarMode = true;
m_xReader = Reference< XDocumentHandler >( new OReadMenuBarHandler( m_xMenuBarContainer, m_xContainerFactory ));
m_xReader->startDocument();
}
}
void SAL_CALL OReadMenuDocumentHandler::characters(const OUString&)
throw( SAXException, RuntimeException, std::exception )
{
}
void SAL_CALL OReadMenuDocumentHandler::endElement( const OUString& aName )
throw( SAXException, RuntimeException, std::exception )
{
if ( m_bMenuBarMode )
{
--m_nElementDepth;
m_xReader->endElement( aName );
if ( 0 == m_nElementDepth )
{
m_xReader->endDocument();
m_xReader.clear();
m_bMenuBarMode = false;
if ( aName != ELEMENT_MENUBAR )
{
OUString aErrorMessage = getErrorLineString();
aErrorMessage += "closing element menubar expected!";
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
}
}
}
OReadMenuBarHandler::OReadMenuBarHandler(
const Reference< XIndexContainer >& rMenuBarContainer,
const Reference< XSingleComponentFactory >& rFactory )
: m_nElementDepth( 0 ),
m_bMenuMode( false ),
m_xMenuBarContainer( rMenuBarContainer ),
m_xContainerFactory( rFactory )
{
}
OReadMenuBarHandler::~OReadMenuBarHandler()
{
}
void SAL_CALL OReadMenuBarHandler::startDocument(void)
throw ( SAXException, RuntimeException, std::exception )
{
}
void SAL_CALL OReadMenuBarHandler::endDocument(void)
throw( SAXException, RuntimeException, std::exception )
{
}
void SAL_CALL OReadMenuBarHandler::startElement(
const OUString& rName, const Reference< XAttributeList > &xAttrList )
throw( SAXException, RuntimeException, std::exception )
{
if ( m_bMenuMode )
{
++m_nElementDepth;
m_xReader->startElement( rName, xAttrList );
}
else if ( rName == ELEMENT_MENU )
{
++m_nElementDepth;
OUString aHelpId;
OUString aCommandId;
OUString aLabel;
sal_Int16 nItemBits(0);
m_bMenuMode = true;
// Container must be factory to create sub container
Reference< XComponentContext > xComponentContext(
comphelper::getProcessComponentContext() );
Reference< XIndexContainer > xSubItemContainer;
if ( m_xContainerFactory.is() )
xSubItemContainer = Reference< XIndexContainer >( m_xContainerFactory->createInstanceWithContext( xComponentContext ), UNO_QUERY );
if ( xSubItemContainer.is() )
{
// read attributes for menu
for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ )
{
OUString aName = xAttrList->getNameByIndex( i );
OUString aValue = xAttrList->getValueByIndex( i );
if ( aName == ATTRIBUTE_ID )
aCommandId = aValue;
else if ( aName == ATTRIBUTE_LABEL )
aLabel = aValue;
else if ( aName == ATTRIBUTE_HELPID )
aHelpId = aValue;
else if ( aName == ATTRIBUTE_STYLE )
{
OUString aTemp( aValue );
sal_Int32 nIndex = 0;
do
{
OUString aToken = aTemp.getToken( 0, '+', nIndex );
if ( !aToken.isEmpty() )
{
if ( aToken == ATTRIBUTE_ITEMSTYLE_TEXT )
nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT;
else if ( aToken == ATTRIBUTE_ITEMSTYLE_IMAGE )
nItemBits |= ::com::sun::star::ui::ItemStyle::ICON;
else if ( aToken == ATTRIBUTE_ITEMSTYLE_RADIO )
nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK;
}
}
while ( nIndex >= 0 );
}
}
if ( !aCommandId.isEmpty() )
{
Sequence< PropertyValue > aSubMenuProp( 6 );
initPropertyCommon( aSubMenuProp, aCommandId, aHelpId, aLabel, nItemBits );
aSubMenuProp[2].Value <<= xSubItemContainer;
m_xMenuBarContainer->insertByIndex( m_xMenuBarContainer->getCount(), makeAny( aSubMenuProp ) );
}
else
{
OUString aErrorMessage = getErrorLineString();
aErrorMessage += "attribute id for element menu required!";
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
m_xReader = Reference< XDocumentHandler >( new OReadMenuHandler( xSubItemContainer, m_xContainerFactory ));
m_xReader->startDocument();
}
}
else
{
OUString aErrorMessage = getErrorLineString();
aErrorMessage += "element menu expected!";
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
}
void SAL_CALL OReadMenuBarHandler::characters(const OUString&)
throw( SAXException, RuntimeException, std::exception )
{
}
void OReadMenuBarHandler::endElement( const OUString& aName )
throw( SAXException, RuntimeException, std::exception )
{
if ( m_bMenuMode )
{
--m_nElementDepth;
if ( 0 == m_nElementDepth )
{
m_xReader->endDocument();
m_xReader.clear();
m_bMenuMode = false;
if ( aName != ELEMENT_MENU )
{
OUString aErrorMessage = getErrorLineString();
aErrorMessage += "closing element menu expected!";
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
}
else
m_xReader->endElement( aName );
}
}
OReadMenuHandler::OReadMenuHandler(
const Reference< XIndexContainer >& rMenuContainer,
const Reference< XSingleComponentFactory >& rFactory ) :
m_nElementDepth( 0 ),
m_bMenuPopupMode( false ),
m_xMenuContainer( rMenuContainer ),
m_xContainerFactory( rFactory )
{
}
OReadMenuHandler::~OReadMenuHandler()
{
}
void SAL_CALL OReadMenuHandler::startDocument(void)
throw ( SAXException, RuntimeException, std::exception )
{
}
void SAL_CALL OReadMenuHandler::endDocument(void)
throw( SAXException, RuntimeException, std::exception)
{
}
void SAL_CALL OReadMenuHandler::startElement(
const OUString& aName, const Reference< XAttributeList > &xAttrList )
throw( SAXException, RuntimeException, std::exception )
{
if ( m_bMenuPopupMode )
{
++m_nElementDepth;
m_xReader->startElement( aName, xAttrList );
}
else if ( aName == ELEMENT_MENUPOPUP )
{
++m_nElementDepth;
m_bMenuPopupMode = true;
m_xReader = Reference< XDocumentHandler >( new OReadMenuPopupHandler( m_xMenuContainer, m_xContainerFactory ));
m_xReader->startDocument();
}
else
{
OUString aErrorMessage = getErrorLineString();
aErrorMessage += "unknown element found!";
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
}
void SAL_CALL OReadMenuHandler::characters(const OUString&)
throw( SAXException, RuntimeException, std::exception )
{
}
void SAL_CALL OReadMenuHandler::endElement( const OUString& aName )
throw( SAXException, RuntimeException, std::exception )
{
if ( m_bMenuPopupMode )
{
--m_nElementDepth;
if ( 0 == m_nElementDepth )
{
m_xReader->endDocument();
m_xReader.clear();
m_bMenuPopupMode = false;
if ( aName != ELEMENT_MENUPOPUP )
{
OUString aErrorMessage = getErrorLineString();
aErrorMessage += "closing element menupopup expected!";
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
}
else
m_xReader->endElement( aName );
}
}
OReadMenuPopupHandler::OReadMenuPopupHandler(
const Reference< XIndexContainer >& rMenuContainer,
const Reference< XSingleComponentFactory >& rFactory ) :
m_nElementDepth( 0 ),
m_bMenuMode( false ),
m_xMenuContainer( rMenuContainer ),
m_xContainerFactory( rFactory ),
m_xComponentContext( comphelper::getProcessComponentContext() ),
m_nNextElementExpected( ELEM_CLOSE_NONE )
{
}
OReadMenuPopupHandler::~OReadMenuPopupHandler()
{
}
void SAL_CALL OReadMenuPopupHandler::startDocument(void)
throw ( SAXException, RuntimeException, std::exception )
{
}
void SAL_CALL OReadMenuPopupHandler::endDocument(void)
throw( SAXException, RuntimeException, std::exception)
{
}
void SAL_CALL OReadMenuPopupHandler::startElement(
const OUString& rName, const Reference< XAttributeList > &xAttrList )
throw( SAXException, RuntimeException, std::exception )
{
++m_nElementDepth;
if ( m_bMenuMode )
m_xReader->startElement( rName, xAttrList );
else if ( rName == ELEMENT_MENU )
{
OUString aHelpId;
OUString aCommandId;
OUString aLabel;
sal_Int16 nItemBits(0);
m_bMenuMode = true;
// Container must be factory to create sub container
Reference< XIndexContainer > xSubItemContainer;
if ( m_xContainerFactory.is() )
xSubItemContainer = Reference< XIndexContainer >( m_xContainerFactory->createInstanceWithContext( m_xComponentContext ), UNO_QUERY );
// read attributes for menu
for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ )
{
OUString aName = xAttrList->getNameByIndex( i );
OUString aValue = xAttrList->getValueByIndex( i );
if ( aName == ATTRIBUTE_ID )
aCommandId = aValue;
else if ( aName == ATTRIBUTE_LABEL )
aLabel = aValue;
else if ( aName == ATTRIBUTE_HELPID )
aHelpId = aValue;
else if ( aName == ATTRIBUTE_STYLE )
{
OUString aTemp( aValue );
sal_Int32 nIndex = 0;
do
{
OUString aToken = aTemp.getToken( 0, '+', nIndex );
if ( !aToken.isEmpty() )
{
if ( aToken == ATTRIBUTE_ITEMSTYLE_TEXT )
nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT;
else if ( aToken == ATTRIBUTE_ITEMSTYLE_IMAGE )
nItemBits |= ::com::sun::star::ui::ItemStyle::ICON;
else if ( aToken == ATTRIBUTE_ITEMSTYLE_RADIO )
nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK;
}
}
while ( nIndex >= 0 );
}
}
if ( !aCommandId.isEmpty() )
{
Sequence< PropertyValue > aSubMenuProp( 6 );
initPropertyCommon( aSubMenuProp, aCommandId, aHelpId, aLabel, nItemBits );
aSubMenuProp[2].Value <<= xSubItemContainer;
m_xMenuContainer->insertByIndex( m_xMenuContainer->getCount(), makeAny( aSubMenuProp ) );
}
else
{
OUString aErrorMessage = getErrorLineString();
aErrorMessage += "attribute id for element menu required!";
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
m_xReader = Reference< XDocumentHandler >( new OReadMenuHandler( xSubItemContainer, m_xContainerFactory ));
m_xReader->startDocument();
}
else if ( rName == ELEMENT_MENUITEM )
{
OUString aHelpId;
OUString aCommandId;
OUString aLabel;
sal_Int16 nItemBits(0);
// read attributes for menu item
for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ )
{
OUString aName = xAttrList->getNameByIndex( i );
OUString aValue = xAttrList->getValueByIndex( i );
if ( aName == ATTRIBUTE_ID )
aCommandId = aValue;
else if ( aName == ATTRIBUTE_LABEL )
aLabel = aValue;
else if ( aName == ATTRIBUTE_HELPID )
aHelpId = aValue;
else if ( aName == ATTRIBUTE_STYLE )
{
OUString aTemp( aValue );
sal_Int32 nIndex = 0;
do
{
OUString aToken = aTemp.getToken( 0, '+', nIndex );
if ( !aToken.isEmpty() )
{
if ( aToken == ATTRIBUTE_ITEMSTYLE_TEXT )
nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT;
else if ( aToken == ATTRIBUTE_ITEMSTYLE_IMAGE )
nItemBits |= ::com::sun::star::ui::ItemStyle::ICON;
else if ( aToken == ATTRIBUTE_ITEMSTYLE_RADIO )
nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK;
}
}
while ( nIndex >= 0 );
}
}
if ( !aCommandId.isEmpty() )
{
Sequence< PropertyValue > aMenuItem( 6 );
initPropertyCommon( aMenuItem, aCommandId, aHelpId, aLabel, nItemBits );
aMenuItem[2].Value <<= Reference< XIndexContainer >();
m_xMenuContainer->insertByIndex( m_xMenuContainer->getCount(), makeAny( aMenuItem ) );
}
m_nNextElementExpected = ELEM_CLOSE_MENUITEM;
}
else if ( rName == ELEMENT_MENUSEPARATOR )
{
Sequence< PropertyValue > aMenuSeparator( 1 );
aMenuSeparator[0].Name = OUString( ITEM_DESCRIPTOR_TYPE );
aMenuSeparator[0].Value <<= ::com::sun::star::ui::ItemType::SEPARATOR_LINE;
m_xMenuContainer->insertByIndex( m_xMenuContainer->getCount(), makeAny( aMenuSeparator ) );
m_nNextElementExpected = ELEM_CLOSE_MENUSEPARATOR;
}
else
{
OUString aErrorMessage = getErrorLineString();
aErrorMessage += "unknown element found!";
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
}
void SAL_CALL OReadMenuPopupHandler::characters(const OUString&)
throw( SAXException, RuntimeException, std::exception )
{
}
void SAL_CALL OReadMenuPopupHandler::endElement( const OUString& aName )
throw( SAXException, RuntimeException, std::exception )
{
--m_nElementDepth;
if ( m_bMenuMode )
{
if ( 0 == m_nElementDepth )
{
m_xReader->endDocument();
m_xReader.clear();
m_bMenuMode = false;
if ( aName != ELEMENT_MENU )
{
OUString aErrorMessage = getErrorLineString();
aErrorMessage += "closing element menu expected!";
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
}
else
m_xReader->endElement( aName );
}
else
{
if ( m_nNextElementExpected == ELEM_CLOSE_MENUITEM )
{
if ( aName != ELEMENT_MENUITEM )
{
OUString aErrorMessage = getErrorLineString();
aErrorMessage += "closing element menuitem expected!";
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
}
else if ( m_nNextElementExpected == ELEM_CLOSE_MENUSEPARATOR )
{
if ( aName != ELEMENT_MENUSEPARATOR )
{
OUString aErrorMessage = getErrorLineString();
aErrorMessage += "closing element menuseparator expected!";
throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
}
}
m_nNextElementExpected = ELEM_CLOSE_NONE;
}
}
// --------------------------------- Write XML ---------------------------------
OWriteMenuDocumentHandler::OWriteMenuDocumentHandler(
const Reference< XIndexAccess >& rMenuBarContainer,
const Reference< XDocumentHandler >& rDocumentHandler ) :
m_xMenuBarContainer( rMenuBarContainer ),
m_xWriteDocumentHandler( rDocumentHandler )
{
::comphelper::AttributeList* pList = new ::comphelper::AttributeList;
m_xEmptyList = Reference< XAttributeList >( (XAttributeList *) pList, UNO_QUERY );
m_aAttributeType = OUString( ATTRIBUTE_TYPE_CDATA );
}
OWriteMenuDocumentHandler::~OWriteMenuDocumentHandler()
{
}
void OWriteMenuDocumentHandler::WriteMenuDocument()
throw ( SAXException, RuntimeException )
{
::comphelper::AttributeList* pList = new ::comphelper::AttributeList;
Reference< XAttributeList > rList( (XAttributeList *) pList , UNO_QUERY );
m_xWriteDocumentHandler->startDocument();
// write DOCTYPE line!
Reference< XExtendedDocumentHandler > xExtendedDocHandler( m_xWriteDocumentHandler, UNO_QUERY );
if ( xExtendedDocHandler.is() )
{
xExtendedDocHandler->unknown( OUString( MENUBAR_DOCTYPE ) );
m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
}
pList->AddAttribute( OUString( ATTRIBUTE_XMLNS_MENU ),
m_aAttributeType,
OUString( XMLNS_MENU ) );
pList->AddAttribute( OUString( ATTRIBUTE_NS_ID ),
m_aAttributeType,
OUString( "menubar" ) );
m_xWriteDocumentHandler->startElement( OUString( ELEMENT_NS_MENUBAR ), pList );
m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
WriteMenu( m_xMenuBarContainer );
m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
m_xWriteDocumentHandler->endElement( OUString( ELEMENT_NS_MENUBAR ) );
m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
m_xWriteDocumentHandler->endDocument();
}
void OWriteMenuDocumentHandler::WriteMenu( const Reference< XIndexAccess >& rMenuContainer )
throw ( SAXException, RuntimeException )
{
sal_Int32 nItemCount = rMenuContainer->getCount();
bool bSeparator = false;
Any aAny;
for ( sal_Int32 nItemPos = 0; nItemPos < nItemCount; nItemPos++ )
{
Sequence< PropertyValue > aProps;
aAny = rMenuContainer->getByIndex( nItemPos );
if ( aAny >>= aProps )
{
OUString aCommandURL;
OUString aLabel;
OUString aHelpURL;
sal_Int16 nType( ::com::sun::star::ui::ItemType::DEFAULT );
sal_Int16 nItemBits( 0 );
Reference< XIndexAccess > xSubMenu;
ExtractMenuParameters( aProps, aCommandURL, aLabel, aHelpURL, xSubMenu, nType, nItemBits );
if ( xSubMenu.is() )
{
if ( aCommandURL == ADDDIRECT_CMD ||
aCommandURL == AUTOPILOTMENU_CMD )
{
WriteMenuItem( aCommandURL, aLabel, aHelpURL, nItemBits );
bSeparator = false;
}
else if ( !aCommandURL.isEmpty() && !AddonPopupMenu::IsCommandURLPrefix( aCommandURL ))
{
::comphelper::AttributeList* pListMenu = new ::comphelper::AttributeList;
Reference< XAttributeList > xListMenu( (XAttributeList *)pListMenu , UNO_QUERY );
pListMenu->AddAttribute( OUString( ATTRIBUTE_NS_ID ),
m_aAttributeType,
aCommandURL );
if ( aCommandURL.copy( CMD_PROTOCOL_SIZE ) != CMD_PROTOCOL )
pListMenu->AddAttribute( OUString( ATTRIBUTE_NS_LABEL ),
m_aAttributeType,
aLabel );
m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
m_xWriteDocumentHandler->startElement( OUString( ELEMENT_NS_MENU ), xListMenu );
m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
m_xWriteDocumentHandler->startElement( OUString( ELEMENT_NS_MENUPOPUP ), m_xEmptyList );
m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
WriteMenu( xSubMenu );
m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
m_xWriteDocumentHandler->endElement( OUString( ELEMENT_NS_MENUPOPUP ) );
m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
m_xWriteDocumentHandler->endElement( OUString( ELEMENT_NS_MENU ) );
m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
bSeparator = false;
}
}
else
{
if ( nType == ::com::sun::star::ui::ItemType::DEFAULT )
{
if ( !aCommandURL.isEmpty() )
{
bSeparator = false;
WriteMenuItem( aCommandURL, aLabel, aHelpURL, nItemBits );
}
}
else if ( !bSeparator )
{
// Don't write two separators together
WriteMenuSeparator();
bSeparator = true;
}
}
}
}
}
void OWriteMenuDocumentHandler::WriteMenuItem( const OUString& aCommandURL, const OUString& aLabel, const OUString& aHelpURL, sal_Int16 nStyle )
{
::comphelper::AttributeList* pList = new ::comphelper::AttributeList;
Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY );
pList->AddAttribute( OUString( ATTRIBUTE_NS_ID ),
m_aAttributeType,
aCommandURL );
if ( !aHelpURL.isEmpty() )
{
pList->AddAttribute( OUString( ATTRIBUTE_NS_HELPID ),
m_aAttributeType,
aHelpURL );
}
if ( !aLabel.isEmpty() && aCommandURL.copy( CMD_PROTOCOL_SIZE ) != CMD_PROTOCOL )
{
pList->AddAttribute( OUString( ATTRIBUTE_NS_LABEL ),
m_aAttributeType,
aLabel );
}
if (( nStyle > 0 ) && aCommandURL.copy( CMD_PROTOCOL_SIZE ) != CMD_PROTOCOL )
{
OUString aValue;
MenuStyleItem* pStyle = MenuItemStyles;
for ( sal_Int32 nIndex = 0; nIndex < nMenuStyleItemEntries; ++nIndex, ++pStyle )
{
if ( nStyle & pStyle->nBit )
{
if ( !aValue.isEmpty() )
aValue = aValue.concat( OUString( "+" ) );
aValue += OUString::createFromAscii( pStyle->attrName );
}
}
pList->AddAttribute( OUString( ATTRIBUTE_NS_STYLE ),
m_aAttributeType,
aValue );
}
m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
m_xWriteDocumentHandler->startElement( OUString( ELEMENT_NS_MENUITEM ), xList );
m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
m_xWriteDocumentHandler->endElement( OUString( ELEMENT_NS_MENUITEM ) );
}
void OWriteMenuDocumentHandler::WriteMenuSeparator()
{
m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
m_xWriteDocumentHandler->startElement( OUString( ELEMENT_NS_MENUSEPARATOR ), m_xEmptyList );
m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
m_xWriteDocumentHandler->endElement( OUString( ELEMENT_NS_MENUSEPARATOR ) );
}
} // namespace framework
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */