xref: /trunk/main/framework/source/fwe/xml/menudocumenthandler.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 
31 #include <stdio.h>
32 
33 //_________________________________________________________________________________________________________________
34 //  my own includes
35 //_________________________________________________________________________________________________________________
36 #include <xml/menudocumenthandler.hxx>
37 #include <framework/menuconfiguration.hxx>
38 #include <framework/addonmenu.hxx>
39 
40 //_________________________________________________________________________________________________________________
41 //  interface includes
42 //_________________________________________________________________________________________________________________
43 
44 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
45 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
46 #include <com/sun/star/ui/ItemType.hpp>
47 #include <com/sun/star/ui/ItemStyle.hpp>
48 #include <com/sun/star/beans/PropertyValue.hpp>
49 #include <com/sun/star/beans/XPropertySet.hpp>
50 
51 //_________________________________________________________________________________________________________________
52 //  other includes
53 //_________________________________________________________________________________________________________________
54 #include <comphelper/processfactory.hxx>
55 #include <rtl/logfile.hxx>
56 #include <comphelper/attributelist.hxx>
57 
58 //_________________________________________________________________________________________________________________
59 //  defines
60 //_________________________________________________________________________________________________________________
61 
62 #define XMLNS_MENU                  "http://openoffice.org/2001/menu"
63 #define XMLNS_PREFIX                "menu:"
64 
65 #define ELEMENT_MENUBAR             "http://openoffice.org/2001/menu^menubar"
66 #define ELEMENT_MENU                "http://openoffice.org/2001/menu^menu"
67 #define ELEMENT_MENUPOPUP           "http://openoffice.org/2001/menu^menupopup"
68 #define ELEMENT_MENUITEM            "http://openoffice.org/2001/menu^menuitem"
69 #define ELEMENT_MENUSEPARATOR       "http://openoffice.org/2001/menu^menuseparator"
70 
71 #define ELEMENT_NS_MENUBAR          "menu:menubar"
72 #define ELEMENT_NS_MENU             "menu:menu"
73 #define ELEMENT_NS_MENUPOPUP        "menu:menupopup"
74 #define ELEMENT_NS_MENUITEM         "menu:menuitem"
75 #define ELEMENT_NS_MENUSEPARATOR    "menu:menuseparator"
76 
77 #define ATTRIBUTE_ID                "http://openoffice.org/2001/menu^id"
78 #define ATTRIBUTE_LABEL             "http://openoffice.org/2001/menu^label"
79 #define ATTRIBUTE_HELPID            "http://openoffice.org/2001/menu^helpid"
80 #define ATTRIBUTE_LINEBREAK         "http://openoffice.org/2001/menu^linebreak"
81 #define ATTRIBUTE_STYLE         "http://openoffice.org/2001/menu^style"
82 
83 #define ATTRIBUTE_NS_ID             "menu:id"
84 #define ATTRIBUTE_NS_LABEL          "menu:label"
85 #define ATTRIBUTE_NS_HELPID         "menu:helpid"
86 #define ATTRIBUTE_NS_LINEBREAK      "menu:linebreak"
87 #define ATTRIBUTE_NS_STYLE          "menu:style"
88 
89 #define ATTRIBUTE_XMLNS_MENU        "xmlns:menu"
90 
91 #define ATTRIBUTE_TYPE_CDATA        "CDATA"
92 
93 #define MENUBAR_DOCTYPE             "<!DOCTYPE menu:menubar PUBLIC \"-//OpenOffice.org//DTD OfficeDocument 1.0//EN\" \"menubar.dtd\">"
94 
95 #define ATTRIBUTE_ITEMSTYLE_TEXT    "text"
96 #define ATTRIBUTE_ITEMSTYLE_IMAGE    "image"
97 #define ATTRIBUTE_ITEMSTYLE_RADIO    "radio"
98 
99 // Property names of a menu/menu item ItemDescriptor
100 static const char ITEM_DESCRIPTOR_COMMANDURL[]  = "CommandURL";
101 static const char ITEM_DESCRIPTOR_HELPURL[]     = "HelpURL";
102 static const char ITEM_DESCRIPTOR_CONTAINER[]   = "ItemDescriptorContainer";
103 static const char ITEM_DESCRIPTOR_LABEL[]       = "Label";
104 static const char ITEM_DESCRIPTOR_TYPE[]        = "Type";
105 static const char ITEM_DESCRIPTOR_STYLE[]       = "Style";
106 
107 // special popup menus (filled during runtime) must be saved as an empty popup menu or menuitem!!!
108 static const sal_Int32 CMD_PROTOCOL_SIZE        = 5;
109 static const char CMD_PROTOCOL[]                = ".uno:";
110 static const char ADDDIRECT_CMD[]               = ".uno:AddDirect" ;
111 static const char AUTOPILOTMENU_CMD[]           = ".uno:AutoPilotMenu" ;
112 static const char FILEMENU_CMD[]                = ".uno:Picklist" ;
113 static const char WINDOWMENU_CMD[]              = ".uno:WindowList" ;
114 
115 //_________________________________________________________________________________________________________________
116 //  using namespaces
117 //_________________________________________________________________________________________________________________
118 
119 using namespace ::com::sun::star::uno;
120 using namespace ::com::sun::star::lang;
121 using namespace ::com::sun::star::beans;
122 using namespace ::com::sun::star::xml::sax;
123 using namespace ::com::sun::star::container;
124 using namespace ::com::sun::star::ui;
125 
126 namespace framework
127 {
128 
129 struct MenuStyleItem
130 {
131     sal_Int16 nBit;
132     const char* attrName;
133 };
134 
135 MenuStyleItem MenuItemStyles[ ] = {
136     { ::com::sun::star::ui::ItemStyle::ICON, ATTRIBUTE_ITEMSTYLE_IMAGE },
137     { ::com::sun::star::ui::ItemStyle::TEXT, ATTRIBUTE_ITEMSTYLE_TEXT },
138     { ::com::sun::star::ui::ItemStyle::RADIO_CHECK, ATTRIBUTE_ITEMSTYLE_RADIO }
139 };
140 
141 
142 sal_Int32 nMenuStyleItemEntries = sizeof( MenuItemStyles ) / sizeof( MenuItemStyles[ 0 ] );
143 
144 static void ExtractMenuParameters( const Sequence< PropertyValue > rProp,
145                                    ::rtl::OUString&                       rCommandURL,
146                                    ::rtl::OUString&                       rLabel,
147                                    ::rtl::OUString&                       rHelpURL,
148                                    Reference< XIndexAccess >&      rSubMenu,
149                                    sal_Int16&                      rType,
150                                    sal_Int16&                      rStyle )
151 {
152     for ( sal_Int32 i = 0; i < rProp.getLength(); i++ )
153     {
154         if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_COMMANDURL ))
155         {
156             rProp[i].Value >>= rCommandURL;
157             rCommandURL = rCommandURL.intern();
158         }
159         else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_HELPURL ))
160         {
161             rProp[i].Value >>= rHelpURL;
162         }
163         else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_CONTAINER ))
164         {
165             rProp[i].Value >>= rSubMenu;
166         }
167         else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_LABEL ))
168         {
169             rProp[i].Value >>= rLabel;
170         }
171         else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_TYPE ))
172         {
173             rProp[i].Value >>= rType;
174         }
175         else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_STYLE ))
176         {
177             rProp[i].Value >>= rStyle;
178         }
179     }
180 }
181 
182 
183 // -----------------------------------------------------------------------------
184 // Base class implementation
185 
186 ReadMenuDocumentHandlerBase::ReadMenuDocumentHandlerBase() :
187     m_xLocator( 0 ),
188     m_xReader( 0 ),
189     m_aType( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_TYPE )),
190     m_aLabel( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_LABEL )),
191     m_aContainer( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_CONTAINER )),
192     m_aHelpURL( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_HELPURL )),
193     m_aCommandURL( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_COMMANDURL )),
194     m_aStyle( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_STYLE ))
195 {
196 }
197 
198 ReadMenuDocumentHandlerBase::~ReadMenuDocumentHandlerBase()
199 {
200 }
201 
202 void SAL_CALL ReadMenuDocumentHandlerBase::ignorableWhitespace(
203     const ::rtl::OUString& )
204 throw( SAXException, RuntimeException )
205 {
206 }
207 
208 void SAL_CALL ReadMenuDocumentHandlerBase::processingInstruction(
209     const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/ )
210 throw( SAXException, RuntimeException )
211 {
212 }
213 
214 void SAL_CALL ReadMenuDocumentHandlerBase::setDocumentLocator(
215     const Reference< XLocator > &xLocator)
216 throw(  SAXException, RuntimeException )
217 {
218     m_xLocator = xLocator;
219 }
220 
221 ::rtl::OUString ReadMenuDocumentHandlerBase::getErrorLineString()
222 {
223     char buffer[32];
224 
225     if ( m_xLocator.is() )
226     {
227         snprintf( buffer, sizeof(buffer), "Line: %ld - ", static_cast<long>( m_xLocator->getLineNumber() ));
228         return ::rtl::OUString::createFromAscii( buffer );
229     }
230     else
231         return ::rtl::OUString();
232 }
233 
234 void ReadMenuDocumentHandlerBase::initPropertyCommon(
235     Sequence< PropertyValue > &rProps, const rtl::OUString &rCommandURL,
236     const rtl::OUString &rHelpId, const rtl::OUString &rLabel, sal_Int16 nItemStyleBits )
237 {
238     rProps[0].Name = m_aCommandURL;
239     rProps[1].Name = m_aHelpURL;
240     rProps[2].Name = m_aContainer;
241     rProps[3].Name = m_aLabel;
242     rProps[4].Name = m_aStyle;
243     rProps[5].Name = m_aType;
244 
245     // Common values
246     rProps[0].Value <<= rCommandURL.intern();
247     rProps[1].Value <<= rHelpId;
248     rProps[2].Value <<= Reference< XIndexContainer >();
249     rProps[3].Value <<= rLabel;
250     rProps[4].Value <<= nItemStyleBits;
251     rProps[5].Value <<= ::com::sun::star::ui::ItemType::DEFAULT;
252 }
253 
254 // -----------------------------------------------------------------------------
255 
256 OReadMenuDocumentHandler::OReadMenuDocumentHandler(
257     const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory,
258     const Reference< XIndexContainer >& rMenuBarContainer )
259 :   m_nElementDepth( 0 ),
260     m_bMenuBarMode( sal_False ),
261     m_xMenuBarContainer( rMenuBarContainer ),
262       m_xContainerFactory( rMenuBarContainer, UNO_QUERY ),
263     mxServiceFactory(xServiceFactory)
264 {
265 }
266 
267 // #110897#
268 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& OReadMenuDocumentHandler::getServiceFactory()
269 {
270     // #110897#
271     return mxServiceFactory;
272 }
273 
274 OReadMenuDocumentHandler::~OReadMenuDocumentHandler()
275 {
276 }
277 
278 
279 void SAL_CALL OReadMenuDocumentHandler::startDocument(void)
280     throw ( SAXException, RuntimeException )
281 {
282 }
283 
284 
285 void SAL_CALL OReadMenuDocumentHandler::endDocument(void)
286     throw( SAXException, RuntimeException )
287 {
288     if ( m_nElementDepth > 0 )
289     {
290         ::rtl::OUString aErrorMessage = getErrorLineString();
291         aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "A closing element is missing!" ));
292         throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
293     }
294 }
295 
296 
297 void SAL_CALL OReadMenuDocumentHandler::startElement(
298     const ::rtl::OUString& aName, const Reference< XAttributeList > &xAttrList )
299 throw( SAXException, RuntimeException )
300 {
301     if ( m_bMenuBarMode )
302     {
303         ++m_nElementDepth;
304         m_xReader->startElement( aName, xAttrList );
305     }
306     else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUBAR )))
307     {
308         ++m_nElementDepth;
309         m_bMenuBarMode = sal_True;
310 
311         // #110897# m_xReader = Reference< XDocumentHandler >( new OReadMenuBarHandler( m_xMenuBarContainer, m_xContainerFactory ));
312         m_xReader = Reference< XDocumentHandler >( new OReadMenuBarHandler( getServiceFactory(), m_xMenuBarContainer, m_xContainerFactory ));
313 
314         m_xReader->startDocument();
315     }
316 }
317 
318 
319 void SAL_CALL OReadMenuDocumentHandler::characters(const rtl::OUString&)
320 throw(  SAXException, RuntimeException )
321 {
322 }
323 
324 
325 void SAL_CALL OReadMenuDocumentHandler::endElement( const ::rtl::OUString& aName )
326     throw( SAXException, RuntimeException )
327 {
328     if ( m_bMenuBarMode )
329     {
330         --m_nElementDepth;
331         m_xReader->endElement( aName );
332         if ( 0 == m_nElementDepth )
333         {
334             m_xReader->endDocument();
335             m_xReader = Reference< XDocumentHandler >();
336             m_bMenuBarMode = sal_False;
337             if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUBAR )))
338             {
339                 ::rtl::OUString aErrorMessage = getErrorLineString();
340                 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menubar expected!" ));
341                 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
342             }
343         }
344     }
345 }
346 
347 
348 // -----------------------------------------------------------------------------
349 
350 
351 // #110897#
352 OReadMenuBarHandler::OReadMenuBarHandler(
353     const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory,
354     const Reference< XIndexContainer >& rMenuBarContainer,
355     const Reference< XSingleComponentFactory >& rFactory          )
356 :   m_nElementDepth( 0 ),
357     m_bMenuMode( sal_False ),
358     m_xMenuBarContainer( rMenuBarContainer ),
359       m_xContainerFactory( rFactory ),
360     mxServiceFactory( xServiceFactory )
361 {
362 }
363 
364 // #110897#
365 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& OReadMenuBarHandler::getServiceFactory()
366 {
367     // #110897#
368     return mxServiceFactory;
369 }
370 
371 OReadMenuBarHandler::~OReadMenuBarHandler()
372 {
373 }
374 
375 
376 void SAL_CALL OReadMenuBarHandler::startDocument(void)
377     throw ( SAXException, RuntimeException )
378 {
379 }
380 
381 
382 void SAL_CALL OReadMenuBarHandler::endDocument(void)
383     throw( SAXException, RuntimeException )
384 {
385 }
386 
387 
388 void SAL_CALL OReadMenuBarHandler::startElement(
389     const ::rtl::OUString& rName, const Reference< XAttributeList > &xAttrList )
390 throw( SAXException, RuntimeException )
391 {
392     if ( m_bMenuMode )
393     {
394         ++m_nElementDepth;
395         m_xReader->startElement( rName, xAttrList );
396     }
397     else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENU )))
398     {
399         ++m_nElementDepth;
400 
401         ::rtl::OUString aHelpId;
402         ::rtl::OUString aCommandId;
403         ::rtl::OUString aLabel;
404         sal_Int16 nItemBits(0);
405 
406         m_bMenuMode = sal_True;
407 
408         // Container must be factory to create sub container
409         Reference< XComponentContext > xComponentContext;
410         Reference< XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY );
411         xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>=
412             xComponentContext;
413 
414         Reference< XIndexContainer > xSubItemContainer;
415         if ( m_xContainerFactory.is() )
416             xSubItemContainer = Reference< XIndexContainer >( m_xContainerFactory->createInstanceWithContext( xComponentContext ), UNO_QUERY );
417 
418         if ( xSubItemContainer.is() )
419         {
420             // read attributes for menu
421             for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ )
422             {
423                 ::rtl::OUString aName = xAttrList->getNameByIndex( i );
424                 ::rtl::OUString aValue = xAttrList->getValueByIndex( i );
425                 if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ID )))
426                     aCommandId = aValue;
427                 else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_LABEL )))
428                     aLabel = aValue;
429                 else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_HELPID )))
430                     aHelpId = aValue;
431                 else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_STYLE )))
432                 {
433                     ::rtl::OUString aTemp( aValue );
434                     sal_Int32 nIndex = 0;
435                     do
436                     {
437                         ::rtl::OUString aToken = aTemp.getToken( 0, '+', nIndex );
438                         if ( aToken.getLength() > 0 )
439                         {
440                             if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_TEXT ) ) )
441                                 nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT;
442                             else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_IMAGE ) ) )
443                                 nItemBits |= ::com::sun::star::ui::ItemStyle::ICON;
444                             else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_RADIO ) ) )
445                                 nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK;
446                         }
447                     }
448                     while ( nIndex >= 0 );
449                 }
450             }
451 
452             if ( aCommandId.getLength() > 0 )
453             {
454                 Sequence< PropertyValue > aSubMenuProp( 6 );
455                 initPropertyCommon( aSubMenuProp, aCommandId, aHelpId, aLabel, nItemBits );
456                 aSubMenuProp[2].Value <<= xSubItemContainer;
457 
458                 m_xMenuBarContainer->insertByIndex( m_xMenuBarContainer->getCount(), makeAny( aSubMenuProp ) );
459             }
460             else
461             {
462                 ::rtl::OUString aErrorMessage = getErrorLineString();
463                 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "attribute id for element menu required!" ));
464                 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
465             }
466 
467             m_xReader = Reference< XDocumentHandler >( new OReadMenuHandler( xSubItemContainer, m_xContainerFactory ));
468             m_xReader->startDocument();
469         }
470     }
471     else
472     {
473         ::rtl::OUString aErrorMessage = getErrorLineString();
474         aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "element menu expected!" ));
475         throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
476     }
477 }
478 
479 
480 void SAL_CALL OReadMenuBarHandler::characters(const rtl::OUString&)
481 throw(  SAXException, RuntimeException )
482 {
483 }
484 
485 
486 void OReadMenuBarHandler::endElement( const ::rtl::OUString& aName )
487     throw( SAXException, RuntimeException )
488 {
489     if ( m_bMenuMode )
490     {
491         --m_nElementDepth;
492         if ( 0 == m_nElementDepth )
493         {
494             m_xReader->endDocument();
495             m_xReader = Reference< XDocumentHandler >();
496             m_bMenuMode = sal_False;
497             if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENU )))
498             {
499                 ::rtl::OUString aErrorMessage = getErrorLineString();
500                 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menu expected!" ));
501                 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
502             }
503         }
504         else
505             m_xReader->endElement( aName );
506     }
507 }
508 
509 
510 // -----------------------------------------------------------------------------
511 
512 
513 OReadMenuHandler::OReadMenuHandler(
514     const Reference< XIndexContainer >& rMenuContainer,
515     const Reference< XSingleComponentFactory >& rFactory          ) :
516     m_nElementDepth( 0 ),
517     m_bMenuPopupMode( sal_False ),
518     m_xMenuContainer( rMenuContainer ),
519     m_xContainerFactory( rFactory )
520 {
521 }
522 
523 
524 OReadMenuHandler::~OReadMenuHandler()
525 {
526 }
527 
528 
529 void SAL_CALL OReadMenuHandler::startDocument(void)
530     throw ( SAXException, RuntimeException )
531 {
532 }
533 
534 
535 void SAL_CALL OReadMenuHandler::endDocument(void)
536     throw( SAXException, RuntimeException)
537 {
538 }
539 
540 
541 void SAL_CALL OReadMenuHandler::startElement(
542     const ::rtl::OUString& aName, const Reference< XAttributeList > &xAttrList )
543 throw( SAXException, RuntimeException )
544 {
545     if ( m_bMenuPopupMode )
546     {
547         ++m_nElementDepth;
548         m_xReader->startElement( aName, xAttrList );
549     }
550     else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUPOPUP )))
551     {
552         ++m_nElementDepth;
553         m_bMenuPopupMode = sal_True;
554         m_xReader = Reference< XDocumentHandler >( new OReadMenuPopupHandler( m_xMenuContainer, m_xContainerFactory ));
555         m_xReader->startDocument();
556     }
557     else
558     {
559         ::rtl::OUString aErrorMessage = getErrorLineString();
560         aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "unknown element found!" ));
561         throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
562     }
563 }
564 
565 
566 void SAL_CALL OReadMenuHandler::characters(const rtl::OUString&)
567 throw(  SAXException, RuntimeException )
568 {
569 }
570 
571 
572 void SAL_CALL OReadMenuHandler::endElement( const ::rtl::OUString& aName )
573     throw( SAXException, RuntimeException )
574 {
575     if ( m_bMenuPopupMode )
576     {
577         --m_nElementDepth;
578         if ( 0 == m_nElementDepth )
579         {
580             m_xReader->endDocument();
581             m_xReader = Reference< XDocumentHandler >();
582             m_bMenuPopupMode = sal_False;
583             if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUPOPUP )))
584             {
585                 ::rtl::OUString aErrorMessage = getErrorLineString();
586                 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menupopup expected!" ));
587                 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
588             }
589         }
590         else
591             m_xReader->endElement( aName );
592     }
593 }
594 
595 
596 // -----------------------------------------------------------------------------
597 
598 
599 OReadMenuPopupHandler::OReadMenuPopupHandler(
600     const Reference< XIndexContainer >& rMenuContainer,
601     const Reference< XSingleComponentFactory >& rFactory          ) :
602     m_nElementDepth( 0 ),
603     m_bMenuMode( sal_False ),
604     m_xMenuContainer( rMenuContainer ),
605     m_xContainerFactory( rFactory ),
606     m_nNextElementExpected( ELEM_CLOSE_NONE )
607 {
608 }
609 
610 
611 OReadMenuPopupHandler::~OReadMenuPopupHandler()
612 {
613 }
614 
615 
616 void SAL_CALL OReadMenuPopupHandler::startDocument(void)
617     throw ( SAXException, RuntimeException )
618 {
619 }
620 
621 
622 void SAL_CALL OReadMenuPopupHandler::endDocument(void)
623     throw( SAXException, RuntimeException)
624 {
625 }
626 
627 void SAL_CALL OReadMenuPopupHandler::startElement(
628     const ::rtl::OUString& rName, const Reference< XAttributeList > &xAttrList )
629 throw( SAXException, RuntimeException )
630 {
631     ++m_nElementDepth;
632 
633     if ( m_bMenuMode )
634         m_xReader->startElement( rName, xAttrList );
635     else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENU )))
636     {
637         ::rtl::OUString aHelpId;
638         ::rtl::OUString aCommandId;
639         ::rtl::OUString aLabel;
640         sal_Int16 nItemBits(0);
641 
642         m_bMenuMode = sal_True;
643 
644         // Container must be factory to create sub container
645         if ( !m_xComponentContext.is() )
646         {
647             const Reference< XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW );
648             m_xComponentContext.set(xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), UNO_QUERY_THROW );
649         }
650 
651         Reference< XIndexContainer > xSubItemContainer;
652         if ( m_xContainerFactory.is() )
653             xSubItemContainer = Reference< XIndexContainer >( m_xContainerFactory->createInstanceWithContext( m_xComponentContext ), UNO_QUERY );
654 
655         // read attributes for menu
656         for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ )
657         {
658             ::rtl::OUString aName = xAttrList->getNameByIndex( i );
659             ::rtl::OUString aValue = xAttrList->getValueByIndex( i );
660             if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ID )))
661                 aCommandId = aValue;
662             else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_LABEL )))
663                 aLabel = aValue;
664             else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_HELPID )))
665                 aHelpId = aValue;
666             else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_STYLE )))
667             {
668                 ::rtl::OUString aTemp( aValue );
669                 sal_Int32 nIndex = 0;
670                 do
671                 {
672                     ::rtl::OUString aToken = aTemp.getToken( 0, '+', nIndex );
673                     if ( aToken.getLength() > 0 )
674                     {
675                         if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_TEXT ) ) )
676                             nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT;
677                         else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_IMAGE ) ) )
678                             nItemBits |= ::com::sun::star::ui::ItemStyle::ICON;
679                         else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_RADIO ) ) )
680                             nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK;
681                     }
682                 }
683                 while ( nIndex >= 0 );
684             }
685 
686         }
687 
688         if ( aCommandId.getLength() > 0 )
689         {
690             Sequence< PropertyValue > aSubMenuProp( 6 );
691             initPropertyCommon( aSubMenuProp, aCommandId, aHelpId, aLabel, nItemBits );
692             aSubMenuProp[2].Value <<= xSubItemContainer;
693 
694             m_xMenuContainer->insertByIndex( m_xMenuContainer->getCount(), makeAny( aSubMenuProp ) );
695         }
696         else
697         {
698             ::rtl::OUString aErrorMessage = getErrorLineString();
699             aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "attribute id for element menu required!" ));
700             throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
701         }
702 
703         m_xReader = Reference< XDocumentHandler >( new OReadMenuHandler( xSubItemContainer, m_xContainerFactory ));
704         m_xReader->startDocument();
705     }
706     else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUITEM )))
707     {
708         ::rtl::OUString aHelpId;
709         ::rtl::OUString aCommandId;
710         ::rtl::OUString aLabel;
711         sal_Int16 nItemBits(0);
712         // read attributes for menu item
713         for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ )
714         {
715             ::rtl::OUString aName = xAttrList->getNameByIndex( i );
716             ::rtl::OUString aValue = xAttrList->getValueByIndex( i );
717             if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ID )))
718                 aCommandId = aValue;
719             else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_LABEL )))
720                 aLabel = aValue;
721             else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_HELPID )))
722                 aHelpId = aValue;
723             else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_STYLE )))
724             {
725                 ::rtl::OUString aTemp( aValue );
726                 sal_Int32 nIndex = 0;
727                 do
728                 {
729                     ::rtl::OUString aToken = aTemp.getToken( 0, '+', nIndex );
730                     if ( aToken.getLength() > 0 )
731                     {
732                         if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_TEXT ) ) )
733                             nItemBits |= ::com::sun::star::ui::ItemStyle::TEXT;
734                         else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_IMAGE ) ) )
735                             nItemBits |= ::com::sun::star::ui::ItemStyle::ICON;
736                         else if ( aToken.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_ITEMSTYLE_RADIO ) ) )
737                             nItemBits |= ::com::sun::star::ui::ItemStyle::RADIO_CHECK;
738                     }
739                 }
740                 while ( nIndex >= 0 );
741             }
742 
743         }
744 
745         if ( aCommandId.getLength() > 0 )
746         {
747             Sequence< PropertyValue > aMenuItem( 6 );
748             initPropertyCommon( aMenuItem, aCommandId, aHelpId, aLabel, nItemBits );
749             aMenuItem[2].Value <<= Reference< XIndexContainer >();
750 
751             m_xMenuContainer->insertByIndex( m_xMenuContainer->getCount(), makeAny( aMenuItem ) );
752         }
753 
754         m_nNextElementExpected = ELEM_CLOSE_MENUITEM;
755     }
756     else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUSEPARATOR )))
757     {
758         Sequence< PropertyValue > aMenuSeparator( 1 );
759         aMenuSeparator[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_TYPE ));
760         aMenuSeparator[0].Value <<= ::com::sun::star::ui::ItemType::SEPARATOR_LINE;
761 
762         m_xMenuContainer->insertByIndex( m_xMenuContainer->getCount(), makeAny( aMenuSeparator ) );
763 
764         m_nNextElementExpected = ELEM_CLOSE_MENUSEPARATOR;
765     }
766     else
767     {
768         ::rtl::OUString aErrorMessage = getErrorLineString();
769         aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "unknown element found!" ));
770         throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
771     }
772 }
773 
774 
775 void SAL_CALL OReadMenuPopupHandler::characters(const rtl::OUString&)
776 throw(  SAXException, RuntimeException )
777 {
778 }
779 
780 
781 void SAL_CALL OReadMenuPopupHandler::endElement( const ::rtl::OUString& aName )
782     throw( SAXException, RuntimeException )
783 {
784     --m_nElementDepth;
785     if ( m_bMenuMode )
786     {
787         if ( 0 == m_nElementDepth )
788         {
789             m_xReader->endDocument();
790             m_xReader = Reference< XDocumentHandler >();
791             m_bMenuMode = sal_False;
792             if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENU )))
793             {
794                 ::rtl::OUString aErrorMessage = getErrorLineString();
795                 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menu expected!" ));
796                 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
797             }
798         }
799         else
800             m_xReader->endElement( aName );
801     }
802     else
803     {
804         if ( m_nNextElementExpected == ELEM_CLOSE_MENUITEM )
805         {
806             if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUITEM )))
807             {
808                 ::rtl::OUString aErrorMessage = getErrorLineString();
809                 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menuitem expected!" ));
810                 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
811             }
812         }
813         else if ( m_nNextElementExpected == ELEM_CLOSE_MENUSEPARATOR )
814         {
815             if ( !aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_MENUSEPARATOR )))
816             {
817                 ::rtl::OUString aErrorMessage = getErrorLineString();
818                 aErrorMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "closing element menuseparator expected!" ));
819                 throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
820             }
821         }
822 
823         m_nNextElementExpected = ELEM_CLOSE_NONE;
824     }
825 }
826 
827 
828 // --------------------------------- Write XML ---------------------------------
829 
830 
831 OWriteMenuDocumentHandler::OWriteMenuDocumentHandler(
832     const Reference< XIndexAccess >& rMenuBarContainer,
833     const Reference< XDocumentHandler >& rDocumentHandler ) :
834     m_xMenuBarContainer( rMenuBarContainer ),
835     m_xWriteDocumentHandler( rDocumentHandler )
836 {
837     ::comphelper::AttributeList* pList = new ::comphelper::AttributeList;
838     m_xEmptyList = Reference< XAttributeList >( (XAttributeList *) pList, UNO_QUERY );
839     m_aAttributeType =  ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE_CDATA ));
840 }
841 
842 
843 OWriteMenuDocumentHandler::~OWriteMenuDocumentHandler()
844 {
845 }
846 
847 
848 void OWriteMenuDocumentHandler::WriteMenuDocument()
849 throw ( SAXException, RuntimeException )
850 {
851     ::comphelper::AttributeList* pList = new ::comphelper::AttributeList;
852     Reference< XAttributeList > rList( (XAttributeList *) pList , UNO_QUERY );
853 
854     m_xWriteDocumentHandler->startDocument();
855 
856     // write DOCTYPE line!
857     Reference< XExtendedDocumentHandler > xExtendedDocHandler( m_xWriteDocumentHandler, UNO_QUERY );
858     if ( xExtendedDocHandler.is() )
859     {
860         xExtendedDocHandler->unknown( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( MENUBAR_DOCTYPE )) );
861         m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
862     }
863 
864     pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_XMLNS_MENU )),
865                          m_aAttributeType,
866                          ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_MENU )) );
867 
868     pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_ID )),
869                          m_aAttributeType,
870                          ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "menubar" )) );
871 
872     m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUBAR )), pList );
873     m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
874 
875     WriteMenu( m_xMenuBarContainer );
876 
877     m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
878     m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUBAR )) );
879     m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
880     m_xWriteDocumentHandler->endDocument();
881 }
882 
883 
884 void OWriteMenuDocumentHandler::WriteMenu( const Reference< XIndexAccess >& rMenuContainer )
885 throw ( SAXException, RuntimeException )
886 {
887     sal_Int32  nItemCount = rMenuContainer->getCount();
888     sal_Bool   bSeparator = sal_False;
889     Any        aAny;
890 
891     for ( sal_Int32 nItemPos = 0; nItemPos < nItemCount; nItemPos++ )
892     {
893         Sequence< PropertyValue > aProps;
894         aAny = rMenuContainer->getByIndex( nItemPos );
895         if ( aAny >>= aProps )
896         {
897             ::rtl::OUString    aCommandURL;
898             ::rtl::OUString    aLabel;
899             ::rtl::OUString    aHelpURL;
900             sal_Int16   nType( ::com::sun::star::ui::ItemType::DEFAULT );
901             sal_Int16   nItemBits( 0 );
902             Reference< XIndexAccess > xSubMenu;
903 
904             ExtractMenuParameters( aProps, aCommandURL, aLabel, aHelpURL, xSubMenu, nType, nItemBits );
905             if ( xSubMenu.is() )
906             {
907                 if ( aCommandURL.equalsAscii( ADDDIRECT_CMD ) ||
908                     aCommandURL.equalsAscii( AUTOPILOTMENU_CMD ))
909                 {
910                     WriteMenuItem( aCommandURL, aLabel, aHelpURL, nItemBits );
911                     bSeparator = sal_False;
912                 }
913                 else if (( aCommandURL.getLength() > 0 ) && !AddonPopupMenu::IsCommandURLPrefix ( aCommandURL ))
914                 {
915                     ::comphelper::AttributeList* pListMenu = new ::comphelper::AttributeList;
916                     Reference< XAttributeList > xListMenu( (XAttributeList *)pListMenu , UNO_QUERY );
917 
918                     pListMenu->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_ID )),
919                                             m_aAttributeType,
920                                             aCommandURL );
921 
922                     if ( !( aCommandURL.copy( CMD_PROTOCOL_SIZE ).equalsAscii( CMD_PROTOCOL )))
923                         pListMenu->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_LABEL )),
924                                                  m_aAttributeType,
925                                                  aLabel );
926 
927                     m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
928                     m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENU )), xListMenu );
929                     m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
930                     m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUPOPUP )), m_xEmptyList );
931                     m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
932 
933                     WriteMenu( xSubMenu );
934 
935                     m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
936                     m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUPOPUP )) );
937                     m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
938                     m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENU )) );
939                     m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
940                     bSeparator = sal_False;
941                 }
942             }
943             else
944             {
945                 if ( nType == ::com::sun::star::ui::ItemType::DEFAULT )
946                 {
947                     if ( aCommandURL.getLength() > 0 )
948                     {
949                         bSeparator = sal_False;
950                         WriteMenuItem( aCommandURL, aLabel, aHelpURL, nItemBits );
951                     }
952                 }
953                 else if ( !bSeparator )
954                 {
955                     // Don't write two separators together
956                     WriteMenuSeparator();
957                     bSeparator = sal_True;
958                 }
959             }
960         }
961     }
962 }
963 
964 
965 void OWriteMenuDocumentHandler::WriteMenuItem( const ::rtl::OUString& aCommandURL, const ::rtl::OUString& aLabel, const ::rtl::OUString& aHelpURL, sal_Int16 nStyle )
966 {
967     ::comphelper::AttributeList* pList = new ::comphelper::AttributeList;
968     Reference< XAttributeList > xList( (XAttributeList *) pList , UNO_QUERY );
969 
970     pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_ID )),
971                                 m_aAttributeType,
972                                 aCommandURL );
973 
974     if ( aHelpURL.getLength() > 0 )
975     {
976         pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_HELPID )),
977                              m_aAttributeType,
978                              aHelpURL );
979     }
980 
981     if (( aLabel.getLength() > 0 ) && !( aCommandURL.copy( CMD_PROTOCOL_SIZE ).equalsAscii( CMD_PROTOCOL )))
982     {
983         pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_LABEL )),
984                                 m_aAttributeType,
985                                 aLabel );
986     }
987     if (( nStyle > 0 ) && !( aCommandURL.copy( CMD_PROTOCOL_SIZE ).equalsAscii( CMD_PROTOCOL )))
988     {
989         rtl::OUString aValue;
990         MenuStyleItem* pStyle = MenuItemStyles;
991 
992         for ( sal_Int32 nIndex = 0; nIndex < nMenuStyleItemEntries; ++nIndex, ++pStyle )
993         {
994             if ( nStyle & pStyle->nBit )
995             {
996                 if ( aValue.getLength() )
997                     aValue = aValue.concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("+") ) );
998                 aValue += rtl::OUString::createFromAscii( pStyle->attrName );
999             }
1000         }
1001         pList->AddAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_NS_STYLE )),
1002                                 m_aAttributeType,
1003                                 aValue );
1004     }
1005 
1006     m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
1007     m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUITEM )), xList );
1008     m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
1009     m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUITEM )) );
1010 }
1011 
1012 
1013 void OWriteMenuDocumentHandler::WriteMenuSeparator()
1014 {
1015     m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
1016     m_xWriteDocumentHandler->startElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUSEPARATOR )), m_xEmptyList );
1017     m_xWriteDocumentHandler->ignorableWhitespace( ::rtl::OUString() );
1018     m_xWriteDocumentHandler->endElement( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_NS_MENUSEPARATOR )) );
1019 }
1020 
1021 } // namespace framework
1022 
1023