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 //_________________________________________________________________________________________________________________
32 //	includes
33 //_________________________________________________________________________________________________________________
34 #include <framework/addonsoptions.hxx>
35 #include <unotools/configmgr.hxx>
36 #include <unotools/configitem.hxx>
37 #include <unotools/ucbstreamhelper.hxx>
38 #include <tools/debug.hxx>
39 #include <tools/stream.hxx>
40 #include <tools/color.hxx>
41 #include <com/sun/star/uno/Any.hxx>
42 #include <com/sun/star/uno/Sequence.hxx>
43 #include "com/sun/star/util/XMacroExpander.hpp"
44 #include "com/sun/star/uno/XComponentContext.hpp"
45 #include "com/sun/star/beans/XPropertySet.hpp"
46 #include <rtl/ustrbuf.hxx>
47 #include <rtl/uri.hxx>
48 #include <comphelper/processfactory.hxx>
49 #include <vcl/graph.hxx>
50 #include <svtools/filter.hxx>
51 
52 #include <hash_map>
53 #include <algorithm>
54 #include <vector>
55 
56 //_________________________________________________________________________________________________________________
57 //	namespaces
58 //_________________________________________________________________________________________________________________
59 
60 using namespace ::std					;
61 using namespace ::utl					;
62 using namespace ::osl					;
63 using namespace ::com::sun::star::uno	;
64 using namespace ::com::sun::star::beans	;
65 using namespace ::com::sun::star::lang	;
66 
67 //_________________________________________________________________________________________________________________
68 //	const
69 //_________________________________________________________________________________________________________________
70 
71 #define ROOTNODE_ADDONMENU                              ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Addons"	))
72 #define PATHDELIMITER                                   ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"				))
73 #define TOOLBARITEMS									::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ToolBarItems"		))
74 #define SEPARATOR_URL_STR								"private:separator"
75 #define SEPARATOR_URL_LEN								17
76 #define SEPARATOR_URL									::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SEPARATOR_URL_STR ))
77 
78 #define PROPERTYNAME_URL                                ADDONSMENUITEM_PROPERTYNAME_URL
79 #define PROPERTYNAME_TITLE                              ADDONSMENUITEM_PROPERTYNAME_TITLE
80 #define PROPERTYNAME_TARGET                             ADDONSMENUITEM_PROPERTYNAME_TARGET
81 #define PROPERTYNAME_IMAGEIDENTIFIER                    ADDONSMENUITEM_PROPERTYNAME_IMAGEIDENTIFIER
82 #define PROPERTYNAME_CONTEXT							ADDONSMENUITEM_PROPERTYNAME_CONTEXT
83 #define PROPERTYNAME_SUBMENU							ADDONSMENUITEM_PROPERTYNAME_SUBMENU
84 #define PROPERTYNAME_CONTROLTYPE                        ADDONSMENUITEM_PROPERTYNAME_CONTROLTYPE
85 #define PROPERTYNAME_WIDTH                              ADDONSMENUITEM_PROPERTYNAME_WIDTH
86 
87 #define PROPERTYNAME_IMAGESMALL							::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageSmall" ))
88 #define PROPERTYNAME_IMAGEBIG							::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageBig" ))
89 #define PROPERTYNAME_IMAGESMALLHC						::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageSmallHC" ))
90 #define PROPERTYNAME_IMAGEBIGHC							::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageBigHC" ))
91 #define PROPERTYNAME_IMAGESMALL_URL						::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageSmallURL" ))
92 #define PROPERTYNAME_IMAGEBIG_URL						::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageBigURL" ))
93 #define PROPERTYNAME_IMAGESMALLHC_URL					::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageSmallHCURL" ))
94 #define PROPERTYNAME_IMAGEBIGHC_URL						::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageBigHCURL" ))
95 
96 #define IMAGES_NODENAME									::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("UserDefinedImages" ))
97 #define PRIVATE_IMAGE_URL                               ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:image/" ))
98 
99 #define PROPERTYNAME_MERGEMENU_MERGEPOINT               ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergePoint" ))
100 #define PROPERTYNAME_MERGEMENU_MERGECOMMAND             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeCommand" ))
101 #define PROPERTYNAME_MERGEMENU_MERGECOMMANDPARAMETER    ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeCommandParameter" ))
102 #define PROPERTYNAME_MERGEMENU_MERGEFALLBACK            ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeFallback" ))
103 #define PROPERTYNAME_MERGEMENU_MERGECONTEXT             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeContext" ))
104 #define PROPERTYNAME_MERGEMENU_MENUITEMS                ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MenuItems" ))
105 #define MERGEMENU_MERGEPOINT_SEPARATOR                  '\\'
106 
107 #define PROPERTYNAME_MERGETOOLBAR_TOOLBAR               ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeToolBar" ))
108 #define PROPERTYNAME_MERGETOOLBAR_MERGEPOINT            ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergePoint" ))
109 #define PROPERTYNAME_MERGETOOLBAR_MERGECOMMAND          ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeCommand" ))
110 #define PROPERTYNAME_MERGETOOLBAR_MERGECOMMANDPARAMETER ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeCommandParameter" ))
111 #define PROPERTYNAME_MERGETOOLBAR_MERGEFALLBACK         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeFallback" ))
112 #define PROPERTYNAME_MERGETOOLBAR_MERGECONTEXT          ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MergeContext" ))
113 #define PROPERTYNAME_MERGETOOLBAR_TOOLBARITEMS          ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ToolBarItems" ))
114 
115 // The following order is mandatory. Please add properties at the end!
116 #define INDEX_URL             0
117 #define INDEX_TITLE           1
118 #define INDEX_IMAGEIDENTIFIER 2
119 #define INDEX_TARGET		  3
120 #define INDEX_CONTEXT		  4
121 #define INDEX_SUBMENU		  5
122 #define INDEX_CONTROLTYPE     6
123 #define INDEX_WIDTH           7
124 #define PROPERTYCOUNT_INDEX   8
125 
126 // The following order is mandatory. Please add properties at the end!
127 #define PROPERTYCOUNT_MENUITEM							6
128 #define OFFSET_MENUITEM_URL                             0
129 #define OFFSET_MENUITEM_TITLE                           1
130 #define OFFSET_MENUITEM_IMAGEIDENTIFIER					2
131 #define OFFSET_MENUITEM_TARGET							3
132 #define OFFSET_MENUITEM_CONTEXT							4
133 #define OFFSET_MENUITEM_SUBMENU							5
134 
135 // The following order is mandatory. Please add properties at the end!
136 #define PROPERTYCOUNT_POPUPMENU							4
137 #define OFFSET_POPUPMENU_TITLE							0
138 #define OFFSET_POPUPMENU_CONTEXT						1
139 #define OFFSET_POPUPMENU_SUBMENU						2
140 #define OFFSET_POPUPMENU_URL							3	// Used for property set
141 
142 // The following order is mandatory. Please add properties at the end!
143 #define PROPERTYCOUNT_TOOLBARITEM						7
144 #define OFFSET_TOOLBARITEM_URL							0
145 #define OFFSET_TOOLBARITEM_TITLE						1
146 #define OFFSET_TOOLBARITEM_IMAGEIDENTIFIER				2
147 #define OFFSET_TOOLBARITEM_TARGET						3
148 #define OFFSET_TOOLBARITEM_CONTEXT						4
149 #define OFFSET_TOOLBARITEM_CONTROLTYPE                  5
150 #define OFFSET_TOOLBARITEM_WIDTH                        6
151 
152 // The following order is mandatory. Please add properties at the end!
153 #define PROPERTYCOUNT_IMAGES							8
154 #define PROPERTYCOUNT_EMBEDDED_IMAGES                   4
155 #define OFFSET_IMAGES_SMALL								0
156 #define OFFSET_IMAGES_BIG								1
157 #define OFFSET_IMAGES_SMALLHC							2
158 #define OFFSET_IMAGES_BIGHC								3
159 #define OFFSET_IMAGES_SMALL_URL							4
160 #define OFFSET_IMAGES_BIG_URL							5
161 #define OFFSET_IMAGES_SMALLHC_URL						6
162 #define OFFSET_IMAGES_BIGHC_URL							7
163 
164 #define PROPERTYCOUNT_MERGE_MENUBAR                     6
165 #define OFFSET_MERGEMENU_MERGEPOINT                     0
166 #define OFFSET_MERGEMENU_MERGECOMMAND                   1
167 #define OFFSET_MERGEMENU_MERGECOMMANDPARAMETER          2
168 #define OFFSET_MERGEMENU_MERGEFALLBACK                  3
169 #define OFFSET_MERGEMENU_MERGECONTEXT                   4
170 #define OFFSET_MERGEMENU_MENUITEMS                      5
171 
172 #define PROPERTYCOUNT_MERGE_TOOLBAR                     7
173 #define OFFSET_MERGETOOLBAR_TOOLBAR                     0
174 #define OFFSET_MERGETOOLBAR_MERGEPOINT                  1
175 #define OFFSET_MERGETOOLBAR_MERGECOMMAND                2
176 #define OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER       3
177 #define OFFSET_MERGETOOLBAR_MERGEFALLBACK               4
178 #define OFFSET_MERGETOOLBAR_MERGECONTEXT                5
179 #define OFFSET_MERGETOOLBAR_TOOLBARITEMS                6
180 
181 #define EXPAND_PROTOCOL                                 "vnd.sun.star.expand:"
182 
183 const Size  aImageSizeSmall( 16, 16 );
184 const Size  aImageSizeBig( 26, 26 );
185 
186 //_________________________________________________________________________________________________________________
187 //	private declarations!
188 //_________________________________________________________________________________________________________________
189 
190 /*-****************************************************************************************************************
191     @descr  struct to hold information about one menu entry.
192 ****************************************************************************************************************-*/
193 
194 namespace framework
195 {
196 
197 class AddonsOptions_Impl : public ConfigItem
198 {
199 	//-------------------------------------------------------------------------------------------------------------
200 	//	public methods
201 	//-------------------------------------------------------------------------------------------------------------
202 
203 	public:
204 		//---------------------------------------------------------------------------------------------------------
205 		//	constructor / destructor
206 		//---------------------------------------------------------------------------------------------------------
207 
208          AddonsOptions_Impl();
209         ~AddonsOptions_Impl();
210 
211 		//---------------------------------------------------------------------------------------------------------
212 		//	overloaded methods of baseclass
213 		//---------------------------------------------------------------------------------------------------------
214 
215 		/*-****************************************************************************************************//**
216 			@short		called for notify of configmanager
217 			@descr		These method is called from the ConfigManager before application ends or from the
218 			 			PropertyChangeListener if the sub tree broadcasts changes. You must update your
219 						internal values.
220 
221 			@seealso	baseclass ConfigItem
222 
223             @param      "lPropertyNames" is the list of properties which should be updated.
224 			@return		-
225 
226 			@onerror	-
227 		*//*-*****************************************************************************************************/
228 
229         virtual void Notify( const Sequence< ::rtl::OUString >& lPropertyNames );
230 
231 		/*-****************************************************************************************************//**
232 			@short		write changes to configuration
233 			@descr		These method writes the changed values into the sub tree
234 						and should always called in our destructor to guarantee consistency of config data.
235 
236 			@seealso	baseclass ConfigItem
237 
238 			@param		-
239 			@return		-
240 
241 			@onerror	-
242 		*//*-*****************************************************************************************************/
243 
244     	virtual void Commit();
245 
246 		//---------------------------------------------------------------------------------------------------------
247 		//	public interface
248 		//---------------------------------------------------------------------------------------------------------
249 
250 		/*-****************************************************************************************************//**
251             @short      base implementation of public interface for "SvtDynamicMenuOptions"!
252             @descr      These class is used as static member of "SvtDynamicMenuOptions" ...
253 						=> The code exist only for one time and isn't duplicated for every instance!
254 
255 			@seealso	-
256 
257 			@param		-
258 			@return		-
259 
260 			@onerror	-
261 		*//*-*****************************************************************************************************/
262 
263 		sal_Bool										HasAddonsMenu		 () const ;
264 		sal_Bool										HasAddonsHelpMenu	 () const ;
265         sal_Int32                                       GetAddonsToolBarCount() const ;
266         const Sequence< Sequence< PropertyValue > >&	GetAddonsMenu		 () const ;
267 		const Sequence< Sequence< PropertyValue > >&	GetAddonsMenuBarPart () const ;
268         const Sequence< Sequence< PropertyValue > >&	GetAddonsToolBarPart ( sal_uInt32 nIndex ) const ;
269         const ::rtl::OUString                           GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const;
270 		const Sequence< Sequence< PropertyValue > >&	GetAddonsHelpMenu	 () const ;
271 		Image											GetImageFromURL( const rtl::OUString& aURL, sal_Bool bBig, sal_Bool bHiContrast, sal_Bool bNoScale ) const;
272         const MergeMenuInstructionContainer&            GetMergeMenuInstructions() const;
273         bool                                            GetMergeToolbarInstructions( const ::rtl::OUString& rToolbarName, MergeToolbarInstructionContainer& rToolbarInstructions ) const;
274 
275         void                                            ReadConfigurationData();
276 
277 	//-------------------------------------------------------------------------------------------------------------
278 	//	private methods
279 	//-------------------------------------------------------------------------------------------------------------
280 
281 	private:
282 		struct OUStringHashCode
283 		{
284 			size_t operator()( const ::rtl::OUString& sString ) const
285 			{
286 				return sString.hashCode();
287 			}
288 		};
289 
290 		struct ImageEntry
291 		{
292 			Image	aImageSmall;
293 			Image	aImageBig;
294 			Image	aImageSmallHC;
295 			Image	aImageBigHC;
296 
297             Image   aImageSmallNoScale;
298             Image   aImageBigNoScale;
299             Image   aImageSmallHCNoScale;
300             Image   aImageBigHCNoScale;
301 		};
302 
303 		typedef std::hash_map< ::rtl::OUString, ImageEntry, OUStringHashCode, ::std::equal_to< ::rtl::OUString > > ImageManager;
304         typedef std::hash_map< ::rtl::OUString, sal_uInt32, OUStringHashCode, ::std::equal_to< ::rtl::OUString > > StringToIndexMap;
305         typedef std::vector< Sequence< Sequence< PropertyValue > > > AddonToolBars;
306         typedef ::std::hash_map< ::rtl::OUString, MergeToolbarInstructionContainer, OUStringHashCode, ::std::equal_to< ::rtl::OUString > > ToolbarMergingInstructions;
307 
308         enum ImageSize
309         {
310             IMGSIZE_SMALL,
311             IMGSIZE_BIG
312         };
313 
314 		/*-****************************************************************************************************//**
315             @short      return list of key names of our configuration management which represent oue module tree
316 			@descr		These methods return the current list of key names! We need it to get needed values from our
317                         configuration management!
318 
319 			@seealso	-
320 
321             @param      "nCount"     ,   returns count of menu entries for "new"
322 			@return		A list of configuration key names is returned.
323 
324 			@onerror	-
325 		*//*-*****************************************************************************************************/
326 
327 		sal_Bool			 ReadAddonMenuSet( Sequence< Sequence< PropertyValue > >& aAddonMenuSeq );
328 		sal_Bool			 ReadOfficeMenuBarSet( Sequence< Sequence< PropertyValue > >& aAddonOfficeMenuBarSeq );
329         sal_Bool			 ReadOfficeToolBarSet( AddonToolBars& rAddonOfficeToolBars, std::vector< rtl::OUString >& rAddonOfficeToolBarResNames );
330 		sal_Bool			 ReadToolBarItemSet( const rtl::OUString rToolBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& aAddonOfficeToolBarSeq );
331 		sal_Bool			 ReadOfficeHelpSet( Sequence< Sequence< PropertyValue > >& aAddonOfficeHelpMenuSeq );
332 		sal_Bool			 ReadImages( ImageManager& aImageManager );
333         sal_Bool             ReadMenuMergeInstructions( MergeMenuInstructionContainer& rContainer );
334         sal_Bool             ReadToolbarMergeInstructions( ToolbarMergingInstructions& rToolbarMergeMap );
335 
336         sal_Bool             ReadMergeMenuData( const ::rtl::OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeMenu );
337         sal_Bool             ReadMergeToolbarData( const ::rtl::OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeToolbarItems );
338 		sal_Bool			 ReadMenuItem( const ::rtl::OUString& aMenuItemNodeName, Sequence< PropertyValue >& aMenuItem, sal_Bool bIgnoreSubMenu = sal_False );
339 		sal_Bool			 ReadPopupMenu( const ::rtl::OUString& aPopupMenuNodeName, Sequence< PropertyValue >& aPopupMenu );
340         sal_Bool             AppendPopupMenu( Sequence< PropertyValue >& aTargetPopupMenu, const Sequence< PropertyValue >& rSourcePopupMenu );
341 		sal_Bool			 ReadToolBarItem( const ::rtl::OUString& aToolBarItemNodeName, Sequence< PropertyValue >& aToolBarItem );
342 		sal_Bool			 ReadImagesItem( const ::rtl::OUString& aImagesItemNodeName, Sequence< PropertyValue >& aImagesItem );
343 		ImageEntry*			 ReadImageData( const ::rtl::OUString& aImagesNodeName );
344 		void                 ReadAndAssociateImages( const ::rtl::OUString& aURL, const ::rtl::OUString& aImageId );
345 		void                 ReadImageFromURL( ImageSize nImageSize, const ::rtl::OUString& aURL, Image& aImage, Image& aNoScaleImage );
346 		sal_Bool             HasAssociatedImages( const ::rtl::OUString& aURL );
347 		void                 SubstituteVariables( ::rtl::OUString& aURL );
348 
349 		sal_Bool			 ReadSubMenuEntries( const Sequence< ::rtl::OUString >& aSubMenuNodeNames, Sequence< Sequence< PropertyValue > >& rSubMenu );
350 		void				 InsertToolBarSeparator( Sequence< Sequence< PropertyValue > >& rAddonOfficeToolBarSeq );
351 		::rtl::OUString			 GeneratePrefixURL();
352 
353 		Sequence< ::rtl::OUString > GetPropertyNamesMergeMenuInstruction( const ::rtl::OUString& aPropertyRootName ) const;
354         Sequence< ::rtl::OUString > GetPropertyNamesMenuItem( const ::rtl::OUString& aPropertyRootNode ) const;
355 		Sequence< ::rtl::OUString > GetPropertyNamesPopupMenu( const ::rtl::OUString& aPropertyRootNode ) const;
356 		Sequence< ::rtl::OUString > GetPropertyNamesToolBarItem( const ::rtl::OUString& aPropertyRootNode ) const;
357 		Sequence< ::rtl::OUString > GetPropertyNamesImages( const ::rtl::OUString& aPropertyRootNode ) const;
358 		sal_Bool			 CreateImageFromSequence( Image& rImage, sal_Bool bBig, Sequence< sal_Int8 >& rBitmapDataSeq ) const;
359 
360 	//-------------------------------------------------------------------------------------------------------------
361 	//	private member
362 	//-------------------------------------------------------------------------------------------------------------
363 
364 	private:
365 		ImageEntry*	ReadOptionalImageData( const ::rtl::OUString& aMenuNodeName );
366 
367 		sal_Int32                                         m_nRootAddonPopupMenuId;
368 		::rtl::OUString                                          m_aPropNames[PROPERTYCOUNT_INDEX];
369 		::rtl::OUString                                          m_aPropImagesNames[PROPERTYCOUNT_IMAGES];
370         ::rtl::OUString                                          m_aPropMergeMenuNames[PROPERTYCOUNT_MERGE_MENUBAR];
371         ::rtl::OUString                                          m_aPropMergeToolbarNames[PROPERTYCOUNT_MERGE_TOOLBAR];
372 		::rtl::OUString                                          m_aEmpty;
373 		::rtl::OUString                                          m_aPathDelimiter;
374 		::rtl::OUString                                          m_aSeparator;
375 		::rtl::OUString                                          m_aRootAddonPopupMenuURLPrexfix;
376 		::rtl::OUString                                          m_aPrivateImageURL;
377 		Sequence< Sequence< PropertyValue > >             m_aCachedMenuProperties;
378 		Sequence< Sequence< PropertyValue > >             m_aCachedMenuBarPartProperties;
379         AddonToolBars                                     m_aCachedToolBarPartProperties;
380         std::vector< rtl::OUString >                      m_aCachedToolBarPartResourceNames;
381 		Sequence< Sequence< PropertyValue > >             m_aCachedHelpMenuProperties;
382 		Reference< com::sun::star::util::XMacroExpander > m_xMacroExpander;
383 		ImageManager                                      m_aImageManager;
384         Sequence< Sequence< PropertyValue > >             m_aEmptyAddonToolBar;
385         MergeMenuInstructionContainer                     m_aCachedMergeMenuInsContainer;
386         ToolbarMergingInstructions                        m_aCachedToolbarMergingInstructions;
387 };
388 
389 //_________________________________________________________________________________________________________________
390 //	definitions
391 //_________________________________________________________________________________________________________________
392 
393 //*****************************************************************************************************************
394 //	constructor
395 //*****************************************************************************************************************
396 AddonsOptions_Impl::AddonsOptions_Impl()
397     // Init baseclasses first
398     : ConfigItem( ROOTNODE_ADDONMENU ),
399 	m_nRootAddonPopupMenuId( 0 ),
400 	m_aPathDelimiter( PATHDELIMITER ),
401 	m_aSeparator( SEPARATOR_URL ),
402 	m_aRootAddonPopupMenuURLPrexfix( ADDONSPOPUPMENU_URL_PREFIX ),
403 	m_aPrivateImageURL( PRIVATE_IMAGE_URL )
404 {
405 	// initialize array with fixed property names
406 	m_aPropNames[ INDEX_URL				] = PROPERTYNAME_URL;
407 	m_aPropNames[ INDEX_TITLE			] = PROPERTYNAME_TITLE;
408 	m_aPropNames[ INDEX_TARGET			] = PROPERTYNAME_TARGET;
409 	m_aPropNames[ INDEX_IMAGEIDENTIFIER	] = PROPERTYNAME_IMAGEIDENTIFIER;
410 	m_aPropNames[ INDEX_CONTEXT			] = PROPERTYNAME_CONTEXT;
411 	m_aPropNames[ INDEX_SUBMENU			] = PROPERTYNAME_SUBMENU; // Submenu set!
412     m_aPropNames[ INDEX_CONTROLTYPE     ] = PROPERTYNAME_CONTROLTYPE;
413     m_aPropNames[ INDEX_WIDTH           ] = PROPERTYNAME_WIDTH;
414 
415 	// initialize array with fixed images property names
416 	m_aPropImagesNames[ OFFSET_IMAGES_SMALL			] = PROPERTYNAME_IMAGESMALL;
417 	m_aPropImagesNames[ OFFSET_IMAGES_BIG			] = PROPERTYNAME_IMAGEBIG;
418 	m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC		] = PROPERTYNAME_IMAGESMALLHC;
419 	m_aPropImagesNames[ OFFSET_IMAGES_BIGHC			] = PROPERTYNAME_IMAGEBIGHC;
420 	m_aPropImagesNames[ OFFSET_IMAGES_SMALL_URL		] = PROPERTYNAME_IMAGESMALL_URL;
421 	m_aPropImagesNames[ OFFSET_IMAGES_BIG_URL	    ] = PROPERTYNAME_IMAGEBIG_URL;
422 	m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC_URL	] = PROPERTYNAME_IMAGESMALLHC_URL;
423 	m_aPropImagesNames[ OFFSET_IMAGES_BIGHC_URL		] = PROPERTYNAME_IMAGEBIGHC_URL;
424 
425     // initialize array with fixed merge menu property names
426     m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT    ] = PROPERTYNAME_MERGEMENU_MERGEPOINT;
427     m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND  ] = PROPERTYNAME_MERGEMENU_MERGECOMMAND;
428     m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] = PROPERTYNAME_MERGEMENU_MERGECOMMANDPARAMETER;
429     m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ] = PROPERTYNAME_MERGEMENU_MERGEFALLBACK;
430     m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT  ] = PROPERTYNAME_MERGEMENU_MERGECONTEXT;
431     m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS     ] = PROPERTYNAME_MERGEMENU_MENUITEMS;
432 
433     m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBAR               ] = PROPERTYNAME_MERGETOOLBAR_TOOLBAR;
434     m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEPOINT            ] = PROPERTYNAME_MERGETOOLBAR_MERGEPOINT;
435     m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMAND          ] = PROPERTYNAME_MERGETOOLBAR_MERGECOMMAND;
436     m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER ] = PROPERTYNAME_MERGETOOLBAR_MERGECOMMANDPARAMETER;
437     m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEFALLBACK         ] = PROPERTYNAME_MERGETOOLBAR_MERGEFALLBACK;
438     m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECONTEXT          ] = PROPERTYNAME_MERGETOOLBAR_MERGECONTEXT;
439     m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS          ] = PROPERTYNAME_MERGETOOLBAR_TOOLBARITEMS;
440 
441     Reference< XComponentContext > xContext;
442     Reference< com::sun::star::beans::XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), UNO_QUERY );
443     xProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext;
444     if ( xContext.is() )
445     {
446         m_xMacroExpander =  Reference< com::sun::star::util::XMacroExpander >( xContext->getValueByName(
447                                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.util.theMacroExpander"))),
448                                 UNO_QUERY );
449     }
450 
451     ReadConfigurationData();
452 
453     // Enable notification mechanism of ouer baseclass.
454 	// We need it to get information about changes outside these class on ouer used configuration keys!
455     Sequence< rtl::OUString > aNotifySeq( 1 );
456     aNotifySeq[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AddonUI" ));
457     EnableNotification( aNotifySeq );
458 }
459 
460 //*****************************************************************************************************************
461 //	destructor
462 //*****************************************************************************************************************
463 AddonsOptions_Impl::~AddonsOptions_Impl()
464 {
465 	// We must save our current values .. if user forget it!
466 	if( IsModified() == sal_True )
467 	{
468 		Commit();
469 	}
470 }
471 
472 void AddonsOptions_Impl::ReadConfigurationData()
473 {
474     // reset members to be read again from configuration
475     m_aCachedMenuProperties = Sequence< Sequence< PropertyValue > >();
476     m_aCachedMenuBarPartProperties = Sequence< Sequence< PropertyValue > >();
477     m_aCachedToolBarPartProperties = AddonToolBars();
478     m_aCachedHelpMenuProperties = Sequence< Sequence< PropertyValue > >();
479     m_aCachedToolBarPartResourceNames.clear();
480     m_aImageManager = ImageManager();
481 
482     ReadAddonMenuSet( m_aCachedMenuProperties );
483 	ReadOfficeMenuBarSet( m_aCachedMenuBarPartProperties );
484 	ReadOfficeToolBarSet( m_aCachedToolBarPartProperties, m_aCachedToolBarPartResourceNames );
485 	ReadOfficeHelpSet( m_aCachedHelpMenuProperties );
486 	ReadImages( m_aImageManager );
487 
488     m_aCachedMergeMenuInsContainer.clear();
489     m_aCachedToolbarMergingInstructions.clear();
490 
491     ReadMenuMergeInstructions( m_aCachedMergeMenuInsContainer );
492     ReadToolbarMergeInstructions( m_aCachedToolbarMergingInstructions );
493 }
494 
495 //*****************************************************************************************************************
496 //	public method
497 //*****************************************************************************************************************
498 void AddonsOptions_Impl::Notify( const Sequence< ::rtl::OUString >& /*lPropertyNames*/ )
499 {
500     Application::PostUserEvent( STATIC_LINK( 0, AddonsOptions, Notify ) );
501 }
502 
503 //*****************************************************************************************************************
504 //	public method
505 //*****************************************************************************************************************
506 void AddonsOptions_Impl::Commit()
507 {
508     DBG_ERROR( "AddonsOptions_Impl::Commit()\nNot implemented yet!\n" );
509 }
510 
511 //*****************************************************************************************************************
512 //	public method
513 //*****************************************************************************************************************
514 sal_Bool AddonsOptions_Impl::HasAddonsMenu() const
515 {
516 	return ( m_aCachedMenuProperties.getLength() > 0 );
517 }
518 
519 //*****************************************************************************************************************
520 //	public method
521 //*****************************************************************************************************************
522 sal_Bool AddonsOptions_Impl::HasAddonsHelpMenu	() const
523 {
524 	return ( m_aCachedHelpMenuProperties.getLength() > 0 );
525 }
526 
527 //*****************************************************************************************************************
528 //	public method
529 //*****************************************************************************************************************
530 sal_Int32 AddonsOptions_Impl::GetAddonsToolBarCount() const
531 {
532     return m_aCachedToolBarPartProperties.size();
533 }
534 
535 //*****************************************************************************************************************
536 //	public method
537 //*****************************************************************************************************************
538 const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsMenu() const
539 {
540 	return m_aCachedMenuProperties;
541 }
542 
543 //*****************************************************************************************************************
544 //	public method
545 //*****************************************************************************************************************
546 const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsMenuBarPart() const
547 {
548 	return m_aCachedMenuBarPartProperties;
549 }
550 
551 //*****************************************************************************************************************
552 //	public method
553 //*****************************************************************************************************************
554 const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsToolBarPart( sal_uInt32 nIndex ) const
555 {
556     if ( /*nIndex >= 0 &&*/ nIndex < m_aCachedToolBarPartProperties.size() )
557         return m_aCachedToolBarPartProperties[nIndex];
558     else
559         return m_aEmptyAddonToolBar;
560 }
561 
562 //*****************************************************************************************************************
563 //	public method
564 //*****************************************************************************************************************
565 const ::rtl::OUString AddonsOptions_Impl::GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const
566 {
567     if ( nIndex < m_aCachedToolBarPartResourceNames.size() )
568         return m_aCachedToolBarPartResourceNames[nIndex];
569     else
570         return rtl::OUString();
571 }
572 
573 //*****************************************************************************************************************
574 //	public method
575 //*****************************************************************************************************************
576 const Sequence< Sequence< PropertyValue > >& AddonsOptions_Impl::GetAddonsHelpMenu	() const
577 {
578 	return m_aCachedHelpMenuProperties;
579 }
580 
581 //*****************************************************************************************************************
582 //	public method
583 //*****************************************************************************************************************
584 const MergeMenuInstructionContainer& AddonsOptions_Impl::GetMergeMenuInstructions() const
585 {
586     return m_aCachedMergeMenuInsContainer;
587 }
588 
589 //*****************************************************************************************************************
590 //	public method
591 //*****************************************************************************************************************
592 bool AddonsOptions_Impl::GetMergeToolbarInstructions(
593     const ::rtl::OUString& rToolbarName,
594     MergeToolbarInstructionContainer& rToolbarInstructions ) const
595 {
596     ToolbarMergingInstructions::const_iterator pIter = m_aCachedToolbarMergingInstructions.find( rToolbarName );
597     if ( pIter != m_aCachedToolbarMergingInstructions.end() )
598     {
599         rToolbarInstructions = pIter->second;
600         return true;
601     }
602     else
603         return false;
604 }
605 
606 //*****************************************************************************************************************
607 //	public method
608 //*****************************************************************************************************************
609 Image AddonsOptions_Impl::GetImageFromURL( const rtl::OUString& aURL, sal_Bool bBig, sal_Bool bHiContrast, sal_Bool bNoScale ) const
610 {
611 	Image aImage;
612 
613 	ImageManager::const_iterator pIter = m_aImageManager.find( aURL );
614 	if ( pIter != m_aImageManager.end() )
615 	{
616 		if ( !bHiContrast  )
617         {
618 			if ( bNoScale )
619                 aImage = ( bBig ? pIter->second.aImageBigNoScale : pIter->second.aImageSmallNoScale );
620             if ( !aImage )
621                 aImage = ( bBig ? pIter->second.aImageBig : pIter->second.aImageSmall );
622         }
623 		else
624         {
625 			if ( bNoScale )
626                 aImage = ( bBig ? pIter->second.aImageBigHCNoScale : pIter->second.aImageSmallHCNoScale );
627             if ( !aImage )
628 			    aImage = ( bBig ? pIter->second.aImageBigHC : pIter->second.aImageSmallHC );
629         }
630 	}
631 
632 	return aImage;
633 }
634 
635 //*****************************************************************************************************************
636 //	private method
637 //*****************************************************************************************************************
638 sal_Bool AddonsOptions_Impl::ReadAddonMenuSet( Sequence< Sequence< PropertyValue > >& rAddonMenuSeq )
639 {
640 	// Read the AddonMenu set and fill property sequences
641 	::rtl::OUString				aAddonMenuNodeName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/AddonMenu" ));
642 	Sequence< ::rtl::OUString >	aAddonMenuNodeSeq = GetNodeNames( aAddonMenuNodeName );
643 	::rtl::OUString				aAddonMenuItemNode( aAddonMenuNodeName + m_aPathDelimiter );
644 
645 	sal_uInt32				nCount = aAddonMenuNodeSeq.getLength();
646 	sal_uInt32				nIndex = 0;
647 	Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
648 
649 	// Init the property value sequence
650 	aMenuItem[ OFFSET_MENUITEM_URL				].Name = m_aPropNames[ INDEX_URL			];
651 	aMenuItem[ OFFSET_MENUITEM_TITLE			].Name = m_aPropNames[ INDEX_TITLE			];
652 	aMenuItem[ OFFSET_MENUITEM_TARGET			].Name = m_aPropNames[ INDEX_TARGET			];
653 	aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER	].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
654 	aMenuItem[ OFFSET_MENUITEM_CONTEXT			].Name = m_aPropNames[ INDEX_CONTEXT		];
655 	aMenuItem[ OFFSET_MENUITEM_SUBMENU			].Name = m_aPropNames[ INDEX_SUBMENU		];	// Submenu set!
656 
657 	for ( sal_uInt32 n = 0; n < nCount; n++ )
658 	{
659 		::rtl::OUString aRootMenuItemNode( aAddonMenuItemNode + aAddonMenuNodeSeq[n] );
660 
661 		// Read the MenuItem
662 		if ( ReadMenuItem( aRootMenuItemNode, aMenuItem ) )
663 		{
664 			// Successfully read a menu item, append to our list
665 			sal_uInt32 nMenuItemCount = rAddonMenuSeq.getLength() + 1;
666 			rAddonMenuSeq.realloc( nMenuItemCount );
667 			rAddonMenuSeq[nIndex++] = aMenuItem;
668 		}
669 	}
670 
671 	return ( rAddonMenuSeq.getLength() > 0 );
672 }
673 
674 //*****************************************************************************************************************
675 //	private method
676 //*****************************************************************************************************************
677 sal_Bool AddonsOptions_Impl::ReadOfficeHelpSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeHelpMenuSeq )
678 {
679 	// Read the AddonMenu set and fill property sequences
680 	::rtl::OUString				aAddonHelpMenuNodeName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/OfficeHelp" ));
681 	Sequence< ::rtl::OUString >	aAddonHelpMenuNodeSeq = GetNodeNames( aAddonHelpMenuNodeName );
682 	::rtl::OUString				aAddonHelpMenuItemNode( aAddonHelpMenuNodeName + m_aPathDelimiter );
683 
684 	sal_uInt32				nCount = aAddonHelpMenuNodeSeq.getLength();
685 	sal_uInt32				nIndex = 0;
686 	Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
687 
688 	// Init the property value sequence
689 	aMenuItem[ OFFSET_MENUITEM_URL				].Name = m_aPropNames[ INDEX_URL			];
690 	aMenuItem[ OFFSET_MENUITEM_TITLE			].Name = m_aPropNames[ INDEX_TITLE			];
691 	aMenuItem[ OFFSET_MENUITEM_TARGET			].Name = m_aPropNames[ INDEX_TARGET			];
692 	aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER	].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
693 	aMenuItem[ OFFSET_MENUITEM_CONTEXT			].Name = m_aPropNames[ INDEX_CONTEXT		];
694 	aMenuItem[ OFFSET_MENUITEM_SUBMENU			].Name = m_aPropNames[ INDEX_SUBMENU		];	// Submenu set!
695 
696 	for ( sal_uInt32 n = 0; n < nCount; n++ )
697 	{
698 		::rtl::OUString aRootMenuItemNode( aAddonHelpMenuItemNode + aAddonHelpMenuNodeSeq[n] );
699 
700 		// Read the MenuItem
701 		if ( ReadMenuItem( aRootMenuItemNode, aMenuItem, sal_True ) )
702 		{
703 			// Successfully read a menu item, append to our list
704 			sal_uInt32 nMenuItemCount = rAddonOfficeHelpMenuSeq.getLength() + 1;
705 			rAddonOfficeHelpMenuSeq.realloc( nMenuItemCount );
706 			rAddonOfficeHelpMenuSeq[nIndex++] = aMenuItem;
707 		}
708 	}
709 
710 	return ( rAddonOfficeHelpMenuSeq.getLength() > 0 );
711 }
712 
713 //*****************************************************************************************************************
714 //	private method
715 //*****************************************************************************************************************
716 sal_Bool AddonsOptions_Impl::ReadOfficeMenuBarSet( Sequence< Sequence< PropertyValue > >& rAddonOfficeMenuBarSeq )
717 {
718 	// Read the OfficeMenuBar set and fill property sequences
719 	::rtl::OUString				aAddonMenuBarNodeName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/OfficeMenuBar" ));
720 	Sequence< ::rtl::OUString >	aAddonMenuBarNodeSeq = GetNodeNames( aAddonMenuBarNodeName );
721 	::rtl::OUString				aAddonMenuBarNode( aAddonMenuBarNodeName + m_aPathDelimiter );
722 
723 	sal_uInt32				nCount = aAddonMenuBarNodeSeq.getLength();
724 	sal_uInt32				nIndex = 0;
725 	Sequence< PropertyValue > aPopupMenu( PROPERTYCOUNT_POPUPMENU );
726 
727 	// Init the property value sequence
728 	aPopupMenu[ OFFSET_POPUPMENU_TITLE		].Name = m_aPropNames[ INDEX_TITLE	];
729 	aPopupMenu[ OFFSET_POPUPMENU_CONTEXT	].Name = m_aPropNames[ INDEX_CONTEXT];
730 	aPopupMenu[ OFFSET_POPUPMENU_SUBMENU	].Name = m_aPropNames[ INDEX_SUBMENU];
731 	aPopupMenu[ OFFSET_POPUPMENU_URL		].Name = m_aPropNames[ INDEX_URL	];
732 
733     StringToIndexMap aTitleToIndexMap;
734 
735     for ( sal_uInt32 n = 0; n < nCount; n++ )
736 	{
737 		::rtl::OUString aPopupMenuNode( aAddonMenuBarNode + aAddonMenuBarNodeSeq[n] );
738 
739 		// Read the MenuItem
740 		if ( ReadPopupMenu( aPopupMenuNode, aPopupMenu ) )
741 		{
742 			// Successfully read a popup menu, append to our list
743             ::rtl::OUString aPopupTitle;
744             if ( aPopupMenu[OFFSET_POPUPMENU_TITLE].Value >>= aPopupTitle )
745             {
746                 StringToIndexMap::const_iterator pIter = aTitleToIndexMap.find( aPopupTitle );
747                 if ( pIter != aTitleToIndexMap.end() )
748                 {
749                     // title already there => concat both popup menus
750                     Sequence< PropertyValue >& rOldPopupMenu = rAddonOfficeMenuBarSeq[pIter->second];
751                     AppendPopupMenu( rOldPopupMenu, aPopupMenu );
752                 }
753                 else
754                 {
755                     // not found
756 			        sal_uInt32 nMenuItemCount = rAddonOfficeMenuBarSeq.getLength() + 1;
757 			        rAddonOfficeMenuBarSeq.realloc( nMenuItemCount );
758 			        rAddonOfficeMenuBarSeq[nIndex] = aPopupMenu;
759                     aTitleToIndexMap.insert( StringToIndexMap::value_type( aPopupTitle, nIndex ));
760                     ++nIndex;
761                 }
762             }
763 		}
764 	}
765 
766 	return ( rAddonOfficeMenuBarSeq.getLength() > 0 );
767 }
768 
769 //*****************************************************************************************************************
770 //	private method
771 //*****************************************************************************************************************
772 sal_Bool AddonsOptions_Impl::ReadOfficeToolBarSet( AddonToolBars& rAddonOfficeToolBars, std::vector< rtl::OUString >& rAddonOfficeToolBarResNames )
773 {
774 	// Read the OfficeToolBar set and fill property sequences
775 	::rtl::OUString             aAddonToolBarNodeName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/OfficeToolBar" ));
776 	Sequence< ::rtl::OUString > aAddonToolBarNodeSeq = GetNodeNames( aAddonToolBarNodeName );
777 	::rtl::OUString             aAddonToolBarNode( aAddonToolBarNodeName + m_aPathDelimiter );
778 
779 	sal_uInt32           nCount = aAddonToolBarNodeSeq.getLength();
780 
781 	for ( sal_uInt32 n = 0; n < nCount; n++ )
782 	{
783         ::rtl::OUString aToolBarItemNode( aAddonToolBarNode + aAddonToolBarNodeSeq[n] );
784         rAddonOfficeToolBarResNames.push_back( aAddonToolBarNodeSeq[n] );
785         rAddonOfficeToolBars.push_back( m_aEmptyAddonToolBar );
786         ReadToolBarItemSet( aToolBarItemNode, rAddonOfficeToolBars[n] );
787 	}
788 
789 	return ( !rAddonOfficeToolBars.empty() );
790 }
791 
792 
793 //*****************************************************************************************************************
794 //	private method
795 //*****************************************************************************************************************
796 sal_Bool AddonsOptions_Impl::ReadToolBarItemSet( const rtl::OUString rToolBarItemSetNodeName, Sequence< Sequence< PropertyValue > >& rAddonOfficeToolBarSeq )
797 {
798 	sal_Bool					bInsertSeparator		= sal_False;
799 	sal_uInt32					nToolBarItemCount		= rAddonOfficeToolBarSeq.getLength();
800 	::rtl::OUString					aAddonToolBarItemSetNode( rToolBarItemSetNodeName + m_aPathDelimiter );
801 	Sequence< ::rtl::OUString >		aAddonToolBarItemSetNodeSeq = GetNodeNames( rToolBarItemSetNodeName );
802 	Sequence< PropertyValue >	aToolBarItem( PROPERTYCOUNT_TOOLBARITEM );
803 
804 	// Init the property value sequence
805 	aToolBarItem[ OFFSET_TOOLBARITEM_URL				].Name = m_aPropNames[ INDEX_URL			];
806 	aToolBarItem[ OFFSET_TOOLBARITEM_TITLE				].Name = m_aPropNames[ INDEX_TITLE			];
807 	aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER	].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
808 	aToolBarItem[ OFFSET_TOOLBARITEM_TARGET				].Name = m_aPropNames[ INDEX_TARGET			];
809 	aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT			].Name = m_aPropNames[ INDEX_CONTEXT		];
810 	aToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE		].Name = m_aPropNames[ INDEX_CONTROLTYPE	];
811 	aToolBarItem[ OFFSET_TOOLBARITEM_WIDTH			    ].Name = m_aPropNames[ INDEX_WIDTH		    ];
812 
813 	sal_uInt32 nCount = aAddonToolBarItemSetNodeSeq.getLength();
814 	for ( sal_uInt32 n = 0; n < nCount; n++ )
815 	{
816 		::rtl::OUString aToolBarItemNode( aAddonToolBarItemSetNode + aAddonToolBarItemSetNodeSeq[n] );
817 
818 		// Read the ToolBarItem
819 		if ( ReadToolBarItem( aToolBarItemNode, aToolBarItem ) )
820 		{
821 			if ( bInsertSeparator )
822 			{
823 				bInsertSeparator = sal_False;
824 				InsertToolBarSeparator( rAddonOfficeToolBarSeq );
825 			}
826 
827 			// Successfully read a toolbar item, append to our list
828 			sal_uInt32 nAddonCount = rAddonOfficeToolBarSeq.getLength();
829 			rAddonOfficeToolBarSeq.realloc( nAddonCount+1 );
830 			rAddonOfficeToolBarSeq[nAddonCount] = aToolBarItem;
831 		}
832 	}
833 
834 	return ( (sal_uInt32)rAddonOfficeToolBarSeq.getLength() > nToolBarItemCount );
835 }
836 
837 //*****************************************************************************************************************
838 //	private method
839 //*****************************************************************************************************************
840 void AddonsOptions_Impl::InsertToolBarSeparator( Sequence< Sequence< PropertyValue > >& rAddonOfficeToolBarSeq )
841 {
842 	Sequence< PropertyValue >	aToolBarItem( PROPERTYCOUNT_TOOLBARITEM );
843 
844 	aToolBarItem[ OFFSET_TOOLBARITEM_URL				].Name = m_aPropNames[ INDEX_URL			];
845 	aToolBarItem[ OFFSET_TOOLBARITEM_TITLE				].Name = m_aPropNames[ INDEX_TITLE			];
846 	aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER	].Name = m_aPropNames[ INDEX_IMAGEIDENTIFIER];
847 	aToolBarItem[ OFFSET_TOOLBARITEM_TARGET				].Name = m_aPropNames[ INDEX_TARGET			];
848 	aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT			].Name = m_aPropNames[ INDEX_CONTEXT		];
849 
850 	aToolBarItem[ OFFSET_TOOLBARITEM_URL				].Value <<= SEPARATOR_URL;
851 	aToolBarItem[ OFFSET_TOOLBARITEM_TITLE				].Value <<= m_aEmpty;
852 	aToolBarItem[ OFFSET_TOOLBARITEM_TARGET				].Value <<= m_aEmpty;
853 	aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER	].Value <<= m_aEmpty;
854 	aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT			].Value <<= m_aEmpty;
855 
856 	sal_uInt32 nToolBarItemCount = rAddonOfficeToolBarSeq.getLength();
857 	rAddonOfficeToolBarSeq.realloc( nToolBarItemCount+1 );
858 	rAddonOfficeToolBarSeq[nToolBarItemCount] = aToolBarItem;
859 }
860 
861 //*****************************************************************************************************************
862 //	private method
863 //*****************************************************************************************************************
864 sal_Bool AddonsOptions_Impl::ReadImages( ImageManager& aImageManager )
865 {
866 	// Read the user-defined Images set and fill image manager
867 	::rtl::OUString                aAddonImagesNodeName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/Images" ));
868 	Sequence< ::rtl::OUString >	aAddonImagesNodeSeq = GetNodeNames( aAddonImagesNodeName );
869 	::rtl::OUString                aAddonImagesNode( aAddonImagesNodeName + m_aPathDelimiter );
870 
871 	sal_uInt32              nCount = aAddonImagesNodeSeq.getLength();
872 
873 	// Init the property value sequence
874 	Sequence< ::rtl::OUString >	aAddonImageItemNodePropNames( 1 );
875 	::rtl::OUString                aURL;
876 
877 	for ( sal_uInt32 n = 0; n < nCount; n++ )
878 	{
879 		::rtl::OUString aImagesItemNode( aAddonImagesNode + aAddonImagesNodeSeq[n] );
880 
881 		// Create sequence for data access
882 		::rtl::OUStringBuffer aBuffer( aImagesItemNode );
883 		aBuffer.append( m_aPathDelimiter );
884 		aBuffer.append( m_aPropNames[ OFFSET_MENUITEM_URL ] );
885 		aAddonImageItemNodePropNames[0] = aBuffer.makeStringAndClear();
886 
887 		Sequence< Any > aAddonImageItemNodeValues = GetProperties( aAddonImageItemNodePropNames );
888 
889 		// An user-defined image entry must have an URL. As "ImageIdentifier" has a higher priority
890 		// we also check if we already have an images association.
891 		if (( aAddonImageItemNodeValues[0] >>= aURL ) &&
892 		    aURL.getLength() > 0 &&
893 		    !HasAssociatedImages( aURL ))
894 		{
895 			::rtl::OUStringBuffer aBuf( aImagesItemNode );
896 			aBuf.append( m_aPathDelimiter );
897 			aBuf.append( IMAGES_NODENAME );
898 			aBuf.append( m_aPathDelimiter );
899 			::rtl::OUString aImagesUserDefinedItemNode = aBuf.makeStringAndClear();
900 
901 			// Read a user-defined images data
902 			ImageEntry* pImageEntry = ReadImageData( aImagesUserDefinedItemNode );
903 			if ( pImageEntry )
904 			{
905 				// Successfully read a user-defined images item, put it into our image manager
906 				aImageManager.insert( ImageManager::value_type( aURL, *pImageEntry ));
907 				delete pImageEntry; // We have the ownership of the pointer
908 			}
909 		}
910 	}
911 
912 	return sal_True;
913 }
914 
915 //*****************************************************************************************************************
916 //	private method
917 //*****************************************************************************************************************
918 
919 ::rtl::OUString AddonsOptions_Impl::GeneratePrefixURL()
920 {
921 	// Create an unique prefixed Add-On popup menu URL so it can be identified later as a runtime popup menu.
922 	// They use a different image manager, so they must be identified by the sfx2/framework code.
923 	::rtl::OUString aPopupMenuURL;
924 	::rtl::OUStringBuffer aBuf( m_aRootAddonPopupMenuURLPrexfix.getLength() + 3 );
925 	aBuf.append( m_aRootAddonPopupMenuURLPrexfix );
926 	aBuf.append( ::rtl::OUString::valueOf( ++m_nRootAddonPopupMenuId ));
927 	aPopupMenuURL = aBuf.makeStringAndClear();
928 	return aPopupMenuURL;
929 }
930 
931 //*****************************************************************************************************************
932 //	private method
933 //*****************************************************************************************************************
934 
935 sal_Bool AddonsOptions_Impl::ReadMenuMergeInstructions( MergeMenuInstructionContainer& aContainer )
936 {
937     const ::rtl::OUString aMenuMergeRootName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/OfficeMenuBarMerging/" ));
938 
939 	Sequence< ::rtl::OUString >	aAddonMergeNodesSeq = GetNodeNames( aMenuMergeRootName );
940 	::rtl::OUString                aAddonMergeNode( aMenuMergeRootName );
941 
942 	sal_uInt32              nCount = aAddonMergeNodesSeq.getLength();
943 
944 	// Init the property value sequence
945 	Sequence< ::rtl::OUString >	aNodePropNames( 5 );
946 	::rtl::OUString                aURL;
947 
948 	for ( sal_uInt32 i = 0; i < nCount; i++ )
949     {
950 		::rtl::OUString aMergeAddonInstructions( aAddonMergeNode + aAddonMergeNodesSeq[i] );
951 
952         Sequence< ::rtl::OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
953         sal_uInt32           nCountAddons = aAddonInstMergeNodesSeq.getLength();
954 
955         for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
956 	    {
957 		    ::rtl::OUStringBuffer aMergeAddonInstructionBase( aMergeAddonInstructions );
958             aMergeAddonInstructionBase.append( m_aPathDelimiter );
959             aMergeAddonInstructionBase.append( aAddonInstMergeNodesSeq[j] );
960             aMergeAddonInstructionBase.append( m_aPathDelimiter );
961 
962             // Create sequence for data access
963             ::rtl::OUStringBuffer aBuffer( aMergeAddonInstructionBase );
964 		    aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT ] );
965 		    aNodePropNames[0] = aBuffer.makeStringAndClear();
966 
967             aBuffer = aMergeAddonInstructionBase;
968             aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND ] );
969             aNodePropNames[1] = aBuffer.makeStringAndClear();
970 
971             aBuffer = aMergeAddonInstructionBase;
972             aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] );
973             aNodePropNames[2] = aBuffer.makeStringAndClear();
974 
975             aBuffer = aMergeAddonInstructionBase;
976             aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ] );
977             aNodePropNames[3] = aBuffer.makeStringAndClear();
978 
979             aBuffer = aMergeAddonInstructionBase;
980             aBuffer.append( m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT ] );
981             aNodePropNames[4] = aBuffer.makeStringAndClear();
982 
983             Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );
984 
985             MergeMenuInstruction aMergeMenuInstruction;
986             aNodePropValues[0] >>= aMergeMenuInstruction.aMergePoint;
987             aNodePropValues[1] >>= aMergeMenuInstruction.aMergeCommand;
988             aNodePropValues[2] >>= aMergeMenuInstruction.aMergeCommandParameter;
989             aNodePropValues[3] >>= aMergeMenuInstruction.aMergeFallback;
990             aNodePropValues[4] >>= aMergeMenuInstruction.aMergeContext;
991 
992             ::rtl::OUString aMergeMenuBase = aMergeAddonInstructionBase.makeStringAndClear();
993             ReadMergeMenuData( aMergeMenuBase, aMergeMenuInstruction.aMergeMenu );
994 
995             aContainer.push_back( aMergeMenuInstruction );
996         }
997     }
998 
999     return sal_True;
1000 }
1001 
1002 //*****************************************************************************************************************
1003 //	private method
1004 //*****************************************************************************************************************
1005 sal_Bool AddonsOptions_Impl::ReadMergeMenuData( const ::rtl::OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeMenu )
1006 {
1007     ::rtl::OUString aMergeMenuBaseNode( aMergeAddonInstructionBase+m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS ] );
1008 
1009     Sequence< ::rtl::OUString > aSubMenuNodeNames = GetNodeNames( aMergeMenuBaseNode );
1010     aMergeMenuBaseNode += m_aPathDelimiter;
1011 
1012     // extend the node names to have full path strings
1013     for ( sal_uInt32 i = 0; i < (sal_uInt32)aSubMenuNodeNames.getLength(); i++ )
1014 		aSubMenuNodeNames[i] = ::rtl::OUString( aMergeMenuBaseNode + aSubMenuNodeNames[i] );
1015 
1016     return ReadSubMenuEntries( aSubMenuNodeNames, rMergeMenu );
1017 }
1018 
1019 //*****************************************************************************************************************
1020 //	private method
1021 //*****************************************************************************************************************
1022 sal_Bool AddonsOptions_Impl::ReadToolbarMergeInstructions( ToolbarMergingInstructions& rCachedToolbarMergingInstructions )
1023 {
1024     const ::rtl::OUString aToolbarMergeRootName( RTL_CONSTASCII_USTRINGPARAM( "AddonUI/OfficeToolbarMerging/" ));
1025 
1026 	Sequence< ::rtl::OUString >	aAddonMergeNodesSeq = GetNodeNames( aToolbarMergeRootName );
1027 	::rtl::OUString                aAddonMergeNode( aToolbarMergeRootName );
1028 
1029 	sal_uInt32              nCount = aAddonMergeNodesSeq.getLength();
1030 
1031 	// Init the property value sequence
1032 	Sequence< ::rtl::OUString >	aNodePropNames( 6 );
1033 	::rtl::OUString                aURL;
1034 
1035 	for ( sal_uInt32 i = 0; i < nCount; i++ )
1036     {
1037 		::rtl::OUString aMergeAddonInstructions( aAddonMergeNode + aAddonMergeNodesSeq[i] );
1038 
1039         Sequence< ::rtl::OUString > aAddonInstMergeNodesSeq = GetNodeNames( aMergeAddonInstructions );
1040         sal_uInt32           nCountAddons = aAddonInstMergeNodesSeq.getLength();
1041 
1042         for ( sal_uInt32 j = 0; j < nCountAddons; j++ )
1043 	    {
1044 		    ::rtl::OUStringBuffer aMergeAddonInstructionBase( aMergeAddonInstructions );
1045             aMergeAddonInstructionBase.append( m_aPathDelimiter );
1046             aMergeAddonInstructionBase.append( aAddonInstMergeNodesSeq[j] );
1047             aMergeAddonInstructionBase.append( m_aPathDelimiter );
1048 
1049             // Create sequence for data access
1050             ::rtl::OUStringBuffer aBuffer( aMergeAddonInstructionBase );
1051 		    aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBAR ] );
1052 		    aNodePropNames[0] = aBuffer.makeStringAndClear();
1053 
1054             aBuffer = aMergeAddonInstructionBase;
1055 		    aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEPOINT ] );
1056 		    aNodePropNames[1] = aBuffer.makeStringAndClear();
1057 
1058             aBuffer = aMergeAddonInstructionBase;
1059             aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMAND ] );
1060             aNodePropNames[2] = aBuffer.makeStringAndClear();
1061 
1062             aBuffer = aMergeAddonInstructionBase;
1063             aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECOMMANDPARAMETER ] );
1064             aNodePropNames[3] = aBuffer.makeStringAndClear();
1065 
1066             aBuffer = aMergeAddonInstructionBase;
1067             aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGEFALLBACK ] );
1068             aNodePropNames[4] = aBuffer.makeStringAndClear();
1069 
1070             aBuffer = aMergeAddonInstructionBase;
1071             aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_MERGECONTEXT ] );
1072             aNodePropNames[5] = aBuffer.makeStringAndClear();
1073 
1074             Sequence< Any > aNodePropValues = GetProperties( aNodePropNames );
1075 
1076             MergeToolbarInstruction aMergeToolbarInstruction;
1077             aNodePropValues[0] >>= aMergeToolbarInstruction.aMergeToolbar;
1078             aNodePropValues[1] >>= aMergeToolbarInstruction.aMergePoint;
1079             aNodePropValues[2] >>= aMergeToolbarInstruction.aMergeCommand;
1080             aNodePropValues[3] >>= aMergeToolbarInstruction.aMergeCommandParameter;
1081             aNodePropValues[4] >>= aMergeToolbarInstruction.aMergeFallback;
1082             aNodePropValues[5] >>= aMergeToolbarInstruction.aMergeContext;
1083 
1084             ReadMergeToolbarData( aMergeAddonInstructionBase.makeStringAndClear(),
1085                                   aMergeToolbarInstruction.aMergeToolbarItems );
1086 
1087             MergeToolbarInstructionContainer& rVector = rCachedToolbarMergingInstructions[ aMergeToolbarInstruction.aMergeToolbar ];
1088             rVector.push_back( aMergeToolbarInstruction );
1089         }
1090     }
1091 
1092     return sal_True;
1093 }
1094 
1095 //*****************************************************************************************************************
1096 //	private method
1097 //*****************************************************************************************************************
1098 sal_Bool AddonsOptions_Impl::ReadMergeToolbarData( const ::rtl::OUString& aMergeAddonInstructionBase, Sequence< Sequence< PropertyValue > >& rMergeToolbarItems )
1099 {
1100     ::rtl::OUStringBuffer aBuffer( aMergeAddonInstructionBase );
1101     aBuffer.append( m_aPropMergeToolbarNames[ OFFSET_MERGETOOLBAR_TOOLBARITEMS ] );
1102 
1103     ::rtl::OUString aMergeToolbarBaseNode = aBuffer.makeStringAndClear();
1104 
1105     return ReadToolBarItemSet( aMergeToolbarBaseNode, rMergeToolbarItems );
1106 }
1107 
1108 //*****************************************************************************************************************
1109 //	private method
1110 //*****************************************************************************************************************
1111 sal_Bool AddonsOptions_Impl::ReadMenuItem( const ::rtl::OUString& aMenuNodeName, Sequence< PropertyValue >& aMenuItem, sal_Bool bIgnoreSubMenu )
1112 {
1113 	sal_Bool			bResult = sal_False;
1114 	::rtl::OUString			aStrValue;
1115 	::rtl::OUString			aAddonMenuItemTreeNode( aMenuNodeName + m_aPathDelimiter );
1116 	Sequence< Any >		aMenuItemNodePropValues;
1117 
1118 	aMenuItemNodePropValues = GetProperties( GetPropertyNamesMenuItem( aAddonMenuItemTreeNode ) );
1119 	if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_TITLE ] >>= aStrValue ) && aStrValue.getLength() > 0 )
1120 	{
1121 		aMenuItem[ OFFSET_MENUITEM_TITLE ].Value <<= aStrValue;
1122 
1123 		::rtl::OUString aRootSubMenuName( aAddonMenuItemTreeNode + m_aPropNames[ INDEX_SUBMENU ] );
1124 		Sequence< ::rtl::OUString > aRootSubMenuNodeNames = GetNodeNames( aRootSubMenuName );
1125 		if ( aRootSubMenuNodeNames.getLength() > 0 && !bIgnoreSubMenu )
1126 		{
1127 			// Set a unique prefixed Add-On popup menu URL so it can be identified later
1128 			::rtl::OUString aPopupMenuURL     = GeneratePrefixURL();
1129             ::rtl::OUString aPopupMenuImageId;
1130 
1131             aMenuItemNodePropValues[ OFFSET_MENUITEM_IMAGEIDENTIFIER ] >>= aPopupMenuImageId;
1132             ReadAndAssociateImages( aPopupMenuURL, aPopupMenuImageId );
1133 
1134 			// A popup menu must have a title and can have a URL and ImageIdentifier
1135 			// Set the other property values to empty
1136 			aMenuItem[ OFFSET_MENUITEM_URL				].Value <<= aPopupMenuURL;
1137 			aMenuItem[ OFFSET_MENUITEM_TARGET			].Value <<= m_aEmpty;
1138 			aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER	].Value <<= aPopupMenuImageId;
1139 			aMenuItem[ OFFSET_MENUITEM_CONTEXT			].Value <<= aMenuItemNodePropValues[ OFFSET_MENUITEM_CONTEXT ];
1140 
1141 			// Continue to read the sub menu nodes
1142 			Sequence< Sequence< PropertyValue > > aSubMenuSeq;
1143 			::rtl::OUString aSubMenuRootNodeName( aRootSubMenuName + m_aPathDelimiter );
1144 			for ( sal_uInt32 n = 0; n < (sal_uInt32)aRootSubMenuNodeNames.getLength(); n++ )
1145 				aRootSubMenuNodeNames[n] = ::rtl::OUString( aSubMenuRootNodeName + aRootSubMenuNodeNames[n] );
1146 			ReadSubMenuEntries( aRootSubMenuNodeNames, aSubMenuSeq );
1147 			aMenuItem[ OFFSET_MENUITEM_SUBMENU ].Value <<= aSubMenuSeq;
1148 			bResult = sal_True;
1149 		}
1150 		else if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_URL ] >>= aStrValue ) && aStrValue.getLength() > 0 )
1151 		{
1152 			// A simple menu item => read the other properties;
1153 			::rtl::OUString aMenuImageId;
1154 
1155 			aMenuItemNodePropValues[ OFFSET_MENUITEM_IMAGEIDENTIFIER ] >>= aMenuImageId;
1156  			ReadAndAssociateImages( aStrValue, aMenuImageId );
1157 
1158 			aMenuItem[ OFFSET_MENUITEM_URL				].Value <<= aStrValue;
1159 			aMenuItem[ OFFSET_MENUITEM_TARGET			].Value <<= aMenuItemNodePropValues[ OFFSET_MENUITEM_TARGET			];
1160 			aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER	].Value <<= aMenuImageId;
1161 		    aMenuItem[ OFFSET_MENUITEM_CONTEXT			].Value <<= aMenuItemNodePropValues[ OFFSET_MENUITEM_CONTEXT        ];
1162 			aMenuItem[ OFFSET_MENUITEM_SUBMENU			].Value <<= Sequence< Sequence< PropertyValue > >(); // Submenu set!
1163 
1164 			bResult = sal_True;
1165 		}
1166 	}
1167 	else if (( aMenuItemNodePropValues[ OFFSET_MENUITEM_URL ] >>= aStrValue ) &&
1168 			  aStrValue.equalsAsciiL( SEPARATOR_URL_STR, SEPARATOR_URL_LEN ))
1169 	{
1170 		// Separator
1171 		aMenuItem[ OFFSET_MENUITEM_URL				].Value <<= aStrValue;
1172 		aMenuItem[ OFFSET_MENUITEM_TARGET			].Value <<= m_aEmpty;
1173 		aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER	].Value <<= m_aEmpty;
1174 		aMenuItem[ OFFSET_MENUITEM_CONTEXT			].Value <<= m_aEmpty;
1175 		aMenuItem[ OFFSET_MENUITEM_SUBMENU			].Value <<= Sequence< Sequence< PropertyValue > >(); // Submenu set!
1176 		bResult = sal_True;
1177 	}
1178 
1179 	return bResult;
1180 }
1181 
1182 //*****************************************************************************************************************
1183 //	private method
1184 //*****************************************************************************************************************
1185 sal_Bool AddonsOptions_Impl::ReadPopupMenu( const ::rtl::OUString& aPopupMenuNodeName, Sequence< PropertyValue >& aPopupMenu )
1186 {
1187 	sal_Bool			bResult = sal_False;
1188 	::rtl::OUString			aStrValue;
1189 	::rtl::OUString			aAddonPopupMenuTreeNode( aPopupMenuNodeName + m_aPathDelimiter );
1190 	Sequence< Any >		aPopupMenuNodePropValues;
1191 
1192 	aPopupMenuNodePropValues = GetProperties( GetPropertyNamesPopupMenu( aAddonPopupMenuTreeNode ) );
1193 	if (( aPopupMenuNodePropValues[ OFFSET_POPUPMENU_TITLE ] >>= aStrValue ) &&
1194 		 aStrValue.getLength() > 0 )
1195 	{
1196 		aPopupMenu[ OFFSET_POPUPMENU_TITLE ].Value <<= aStrValue;
1197 
1198 		::rtl::OUString aRootSubMenuName( aAddonPopupMenuTreeNode + m_aPropNames[ INDEX_SUBMENU ] );
1199 		Sequence< ::rtl::OUString > aRootSubMenuNodeNames = GetNodeNames( aRootSubMenuName );
1200 		if ( aRootSubMenuNodeNames.getLength() > 0 )
1201 		{
1202 			// A top-level popup menu needs a title
1203 			// Set a unique prefixed Add-On popup menu URL so it can be identified later
1204 			::rtl::OUString aPopupMenuURL = GeneratePrefixURL();
1205 
1206             aPopupMenu[ OFFSET_POPUPMENU_URL		].Value <<= aPopupMenuURL;
1207 			aPopupMenu[ OFFSET_POPUPMENU_CONTEXT	].Value <<= aPopupMenuNodePropValues[ OFFSET_POPUPMENU_CONTEXT ];
1208 
1209 			// Continue to read the sub menu nodes
1210 			Sequence< Sequence< PropertyValue > > aSubMenuSeq;
1211 			::rtl::OUString aSubMenuRootNodeName( aRootSubMenuName + m_aPathDelimiter );
1212 			for ( sal_uInt32 n = 0; n < (sal_uInt32)aRootSubMenuNodeNames.getLength(); n++ )
1213 				aRootSubMenuNodeNames[n] = ::rtl::OUString( aSubMenuRootNodeName + aRootSubMenuNodeNames[n] );
1214 			ReadSubMenuEntries( aRootSubMenuNodeNames, aSubMenuSeq );
1215 			aPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value <<= aSubMenuSeq;
1216 			bResult = sal_True;
1217 		}
1218 	}
1219 
1220 	return bResult;
1221 }
1222 
1223 //*****************************************************************************************************************
1224 //	private method
1225 //*****************************************************************************************************************
1226 sal_Bool AddonsOptions_Impl::AppendPopupMenu( Sequence< PropertyValue >& rTargetPopupMenu, const Sequence< PropertyValue >& rSourcePopupMenu )
1227 {
1228     Sequence< Sequence< PropertyValue > > aTargetSubMenuSeq;
1229     Sequence< Sequence< PropertyValue > > aSourceSubMenuSeq;
1230 
1231     if (( rTargetPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value >>= aTargetSubMenuSeq ) &&
1232         ( rSourcePopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value >>= aSourceSubMenuSeq ))
1233     {
1234         sal_uInt32 nIndex = aTargetSubMenuSeq.getLength();
1235         aTargetSubMenuSeq.realloc( nIndex + aSourceSubMenuSeq.getLength() );
1236         for ( sal_uInt32 i = 0; i < sal_uInt32( aSourceSubMenuSeq.getLength() ); i++ )
1237             aTargetSubMenuSeq[nIndex++] = aSourceSubMenuSeq[i];
1238         rTargetPopupMenu[ OFFSET_POPUPMENU_SUBMENU ].Value <<= aTargetSubMenuSeq;
1239     }
1240 
1241     return sal_True;
1242 }
1243 
1244 //*****************************************************************************************************************
1245 //	private method
1246 //*****************************************************************************************************************
1247 sal_Bool AddonsOptions_Impl::ReadToolBarItem( const ::rtl::OUString& aToolBarItemNodeName, Sequence< PropertyValue >& aToolBarItem )
1248 {
1249 	sal_Bool			bResult = sal_False;
1250 	::rtl::OUString			aTitle;
1251 	::rtl::OUString			aURL;
1252 	::rtl::OUString			aAddonToolBarItemTreeNode( aToolBarItemNodeName + m_aPathDelimiter );
1253 	Sequence< Any >		aToolBarItemNodePropValues;
1254 
1255 	aToolBarItemNodePropValues = GetProperties( GetPropertyNamesToolBarItem( aAddonToolBarItemTreeNode ) );
1256 
1257 	// A toolbar item must have a command URL
1258 	if (( aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_URL ] >>= aURL ) && aURL.getLength() > 0 )
1259 	{
1260 		if ( aURL.equals( SEPARATOR_URL ))
1261 		{
1262 			// A speparator toolbar item only needs a URL
1263 			aToolBarItem[ OFFSET_TOOLBARITEM_URL				].Value <<= aURL;
1264 			aToolBarItem[ OFFSET_TOOLBARITEM_TITLE				].Value <<= m_aEmpty;
1265 			aToolBarItem[ OFFSET_TOOLBARITEM_TARGET				].Value <<= m_aEmpty;
1266 			aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER	].Value <<= m_aEmpty;
1267 			aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT			].Value <<= m_aEmpty;
1268 			aToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE		].Value <<= m_aEmpty;
1269 			aToolBarItem[ OFFSET_TOOLBARITEM_WIDTH		        ].Value <<= sal_Int32( 0 );
1270 
1271 			bResult = sal_True;
1272 		}
1273 		else if (( aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_TITLE	] >>= aTitle ) && aTitle.getLength() > 0 )
1274 		{
1275 			// A normal toolbar item must also have title => read the other properties;
1276 			::rtl::OUString aImageId;
1277 
1278             // Try to map a user-defined image URL to our internal private image URL
1279 			aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER ] >>= aImageId;
1280  			ReadAndAssociateImages( aURL, aImageId );
1281 
1282 			aToolBarItem[ OFFSET_TOOLBARITEM_URL				].Value <<= aURL;
1283 			aToolBarItem[ OFFSET_TOOLBARITEM_TITLE				].Value <<= aTitle;
1284 			aToolBarItem[ OFFSET_TOOLBARITEM_TARGET				].Value <<= aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_TARGET	   ];
1285 			aToolBarItem[ OFFSET_TOOLBARITEM_IMAGEIDENTIFIER	].Value <<= aImageId;
1286 			aToolBarItem[ OFFSET_TOOLBARITEM_CONTEXT			].Value <<= aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_CONTEXT	   ];
1287 			aToolBarItem[ OFFSET_TOOLBARITEM_CONTROLTYPE		].Value <<= aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_CONTROLTYPE ];
1288 
1289             // Configuration uses hyper for long. Therefore transform into sal_Int32
1290             sal_Int64 nValue( 0 );
1291             aToolBarItemNodePropValues[ OFFSET_TOOLBARITEM_WIDTH ] >>= nValue;
1292             aToolBarItem[ OFFSET_TOOLBARITEM_WIDTH		        ].Value <<= sal_Int32( nValue );
1293 
1294 			bResult = sal_True;
1295 		}
1296 	}
1297 
1298 	return bResult;
1299 }
1300 
1301 //*****************************************************************************************************************
1302 //	private method
1303 //*****************************************************************************************************************
1304 sal_Bool AddonsOptions_Impl::ReadSubMenuEntries( const Sequence< ::rtl::OUString >& aSubMenuNodeNames, Sequence< Sequence< PropertyValue > >& rSubMenuSeq )
1305 {
1306 	Sequence< PropertyValue > aMenuItem( PROPERTYCOUNT_MENUITEM );
1307 
1308 	// Init the property value sequence
1309 	aMenuItem[ OFFSET_MENUITEM_URL				].Name = PROPERTYNAME_URL;
1310 	aMenuItem[ OFFSET_MENUITEM_TITLE			].Name = PROPERTYNAME_TITLE;
1311 	aMenuItem[ OFFSET_MENUITEM_TARGET			].Name = PROPERTYNAME_TARGET;
1312 	aMenuItem[ OFFSET_MENUITEM_IMAGEIDENTIFIER	].Name = PROPERTYNAME_IMAGEIDENTIFIER;
1313 	aMenuItem[ OFFSET_MENUITEM_CONTEXT			].Name = PROPERTYNAME_CONTEXT;
1314 	aMenuItem[ OFFSET_MENUITEM_SUBMENU			].Name = PROPERTYNAME_SUBMENU;	// Submenu set!
1315 
1316 	sal_uInt32 nIndex = 0;
1317 	sal_uInt32 nCount = aSubMenuNodeNames.getLength();
1318 	for ( sal_uInt32 n = 0; n < nCount; n++ )
1319 	{
1320 		if ( ReadMenuItem( aSubMenuNodeNames[n], aMenuItem ))
1321 		{
1322 			sal_uInt32 nSubMenuCount = rSubMenuSeq.getLength() + 1;
1323 			rSubMenuSeq.realloc( nSubMenuCount );
1324 			rSubMenuSeq[nIndex++] = aMenuItem;
1325 		}
1326 	}
1327 
1328 	return sal_True;
1329 }
1330 
1331 //*****************************************************************************************************************
1332 //	private method
1333 //*****************************************************************************************************************
1334 sal_Bool AddonsOptions_Impl::HasAssociatedImages( const ::rtl::OUString& aURL )
1335 {
1336 	ImageManager::const_iterator pIter = m_aImageManager.find( aURL );
1337 	return ( pIter != m_aImageManager.end() );
1338 }
1339 
1340 //*****************************************************************************************************************
1341 //	private method
1342 //*****************************************************************************************************************
1343 void AddonsOptions_Impl::SubstituteVariables( ::rtl::OUString& aURL )
1344 {
1345     if (( aURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( EXPAND_PROTOCOL )) == 0 ) &&
1346         m_xMacroExpander.is() )
1347     {
1348         // cut protocol
1349         ::rtl::OUString macro( aURL.copy( sizeof ( EXPAND_PROTOCOL ) -1 ) );
1350         // decode uric class chars
1351         macro = ::rtl::Uri::decode(
1352             macro, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
1353         // expand macro string
1354         aURL = m_xMacroExpander->expandMacros( macro );
1355     }
1356 }
1357 
1358 //*****************************************************************************************************************
1359 //	private method
1360 //*****************************************************************************************************************
1361 void AddonsOptions_Impl::ReadImageFromURL( ImageSize nImageSize, const ::rtl::OUString& aImageURL, Image& aImage, Image& aImageNoScale )
1362 {
1363     SvStream* pStream = UcbStreamHelper::CreateStream( aImageURL, STREAM_STD_READ );
1364     if ( pStream && ( pStream->GetErrorCode() == 0 ))
1365     {
1366         // Use graphic class to also support more graphic formats (bmp,png,...)
1367         Graphic aGraphic;
1368 
1369         GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
1370         pGF->ImportGraphic( aGraphic, String(), *pStream, GRFILTER_FORMAT_DONTKNOW );
1371 
1372         BitmapEx aBitmapEx = aGraphic.GetBitmapEx();
1373 
1374 	    const Size aSize = ( nImageSize == IMGSIZE_SMALL ) ? aImageSizeSmall : aImageSizeBig; // Sizes used for menu/toolbox images
1375 
1376         Size aBmpSize = aBitmapEx.GetSizePixel();
1377 	    if ( aBmpSize.Width() > 0 && aBmpSize.Height() > 0 )
1378         {
1379             // Support non-transparent bitmaps to be downward compatible with OOo 1.1.x addons
1380             if( !aBitmapEx.IsTransparent() )
1381                 aBitmapEx = BitmapEx( aBitmapEx.GetBitmap(), COL_LIGHTMAGENTA );
1382 
1383             // A non-scaled bitmap can have a flexible width, but must have a defined height!
1384             Size aNoScaleSize( aBmpSize.Width(), aSize.Height() );
1385             if ( aBmpSize != aNoScaleSize )
1386             {
1387                 BitmapEx aNoScaleBmp( aBitmapEx );
1388                 aNoScaleBmp.Scale( aNoScaleSize, BMP_SCALE_INTERPOLATE );
1389             }
1390             else
1391                 aImageNoScale = Image( aBitmapEx );
1392 
1393             if ( aBmpSize != aSize )
1394                 aBitmapEx.Scale( aSize, BMP_SCALE_INTERPOLATE );
1395 
1396             aImage = Image( aBitmapEx );
1397         }
1398     }
1399 
1400     delete pStream;
1401 }
1402 
1403 //*****************************************************************************************************************
1404 //	private method
1405 //*****************************************************************************************************************
1406 void AddonsOptions_Impl::ReadAndAssociateImages( const ::rtl::OUString& aURL, const ::rtl::OUString& aImageId )
1407 {
1408     const int   MAX_NUM_IMAGES = 4;
1409     const char* aExtArray[MAX_NUM_IMAGES] = { "_16", "_26", "_16h", "_26h" };
1410     const char* pBmpExt = ".bmp";
1411 
1412     if ( aImageId.getLength() == 0 )
1413         return;
1414 
1415     bool        bImageFound = true;
1416     ImageEntry  aImageEntry;
1417     ::rtl::OUString    aImageURL( aImageId );
1418 
1419     SubstituteVariables( aImageURL );
1420 
1421     // Loop to create the four possible image names and try to read the bitmap files
1422     for ( int i = 0; i < MAX_NUM_IMAGES; i++ )
1423     {
1424         ::rtl::OUStringBuffer aFileURL( aImageURL );
1425         aFileURL.appendAscii( aExtArray[i] );
1426         aFileURL.appendAscii( pBmpExt );
1427 
1428         Image aImage;
1429         Image aImageNoScale;
1430         ReadImageFromURL( ((i==0)||(i==2)) ? IMGSIZE_SMALL : IMGSIZE_BIG, aFileURL.makeStringAndClear(), aImage, aImageNoScale );
1431         if ( !!aImage )
1432         {
1433             bImageFound = true;
1434             switch ( i )
1435             {
1436                 case 0:
1437                     aImageEntry.aImageSmall          = aImage;
1438                     aImageEntry.aImageSmallNoScale   = aImageNoScale;
1439                     break;
1440                 case 1:
1441                     aImageEntry.aImageBig            = aImage;
1442                     aImageEntry.aImageBigNoScale     = aImageNoScale;
1443                     break;
1444                 case 2:
1445                     aImageEntry.aImageSmallHC        = aImage;
1446                     aImageEntry.aImageSmallHCNoScale = aImageNoScale;
1447                     break;
1448                 case 3:
1449                     aImageEntry.aImageBigHC          = aImage;
1450                     aImageEntry.aImageBigHCNoScale   = aImageNoScale;
1451                     break;
1452             }
1453         }
1454     }
1455 
1456     if ( bImageFound )
1457         m_aImageManager.insert( ImageManager::value_type( aURL, aImageEntry ));
1458 }
1459 
1460 //*****************************************************************************************************************
1461 //	private method
1462 //*****************************************************************************************************************
1463 AddonsOptions_Impl::ImageEntry* AddonsOptions_Impl::ReadImageData( const ::rtl::OUString& aImagesNodeName )
1464 {
1465 	Sequence< ::rtl::OUString > aImageDataNodeNames = GetPropertyNamesImages( aImagesNodeName );
1466 	Sequence< Any >		 aPropertyData;
1467 	Sequence< sal_Int8 > aImageDataSeq;
1468 	::rtl::OUString             aImageURL;
1469 
1470 	ImageEntry* pEntry = NULL;
1471 
1472     // It is possible to use both forms (embedded image data and URLs to external bitmap files) at the
1473     // same time. Embedded image data has a higher priority.
1474 	aPropertyData = GetProperties( aImageDataNodeNames );
1475 	for ( int i = 0; i < PROPERTYCOUNT_IMAGES; i++ )
1476 	{
1477         if ( i < PROPERTYCOUNT_EMBEDDED_IMAGES )
1478         {
1479             // Extract image data from the embedded hex binary sequence
1480             Image aImage;
1481 		    if (( aPropertyData[i] >>= aImageDataSeq ) &&
1482 		        aImageDataSeq.getLength() > 0 &&
1483 			    ( CreateImageFromSequence( aImage,
1484 									    (( i == OFFSET_IMAGES_BIG ) ||
1485 									    ( i == OFFSET_IMAGES_BIGHC )),
1486 									    aImageDataSeq )) )
1487 		    {
1488 			    if ( !pEntry )
1489 				    pEntry = new ImageEntry;
1490 
1491 			    if ( i == OFFSET_IMAGES_SMALL )
1492 				    pEntry->aImageSmall = aImage;
1493 			    else if ( i == OFFSET_IMAGES_BIG )
1494 				    pEntry->aImageBig = aImage;
1495 			    else if ( i == OFFSET_IMAGES_SMALLHC )
1496 				    pEntry->aImageSmallHC = aImage;
1497 			    else
1498 				    pEntry->aImageBigHC = aImage;
1499 		    }
1500         }
1501         else
1502         {
1503             // Retrieve image data from a external bitmap file. Make sure that embedded image data
1504             // has a higher priority.
1505             aPropertyData[i] >>= aImageURL;
1506 
1507             if ( aImageURL.getLength() > 0 )
1508             {
1509                 Image aImage;
1510                 Image aImageNoScale;
1511 
1512                 SubstituteVariables( aImageURL );
1513                 ReadImageFromURL( ((i==OFFSET_IMAGES_SMALL_URL)||(i==OFFSET_IMAGES_SMALLHC_URL)) ? IMGSIZE_SMALL : IMGSIZE_BIG,
1514                                   aImageURL, aImage, aImageNoScale );
1515                 if ( !!aImage )
1516                 {
1517                     if ( !pEntry )
1518                         pEntry = new ImageEntry;
1519 
1520                     if ( i == OFFSET_IMAGES_SMALL_URL && !pEntry->aImageSmall )
1521                     {
1522                         pEntry->aImageSmall = aImage;
1523                         pEntry->aImageSmallNoScale = aImageNoScale;
1524                     }
1525                     else if ( i == OFFSET_IMAGES_BIG_URL && !pEntry->aImageBig )
1526                     {
1527                         pEntry->aImageBig = aImage;
1528                         pEntry->aImageBigNoScale = aImageNoScale;
1529                     }
1530 			        else if ( i == OFFSET_IMAGES_SMALLHC_URL && !pEntry->aImageSmallHC )
1531                     {
1532 				        pEntry->aImageSmallHC = aImage;
1533 				        pEntry->aImageSmallHCNoScale = aImageNoScale;
1534                     }
1535 			        else if ( !pEntry->aImageBigHC )
1536                     {
1537 				        pEntry->aImageBigHC = aImage;
1538 				        pEntry->aImageBigHCNoScale = aImageNoScale;
1539                     }
1540                 }
1541             }
1542         }
1543 	}
1544 
1545 	return pEntry;
1546 }
1547 
1548 //*****************************************************************************************************************
1549 //	private method
1550 //*****************************************************************************************************************
1551 sal_Bool AddonsOptions_Impl::CreateImageFromSequence( Image& rImage, sal_Bool bBig, Sequence< sal_Int8 >& rBitmapDataSeq ) const
1552 {
1553 	sal_Bool	bResult = sal_False;
1554 	Size		aSize = bBig ? aImageSizeBig : aImageSizeSmall; // Sizes used for menu/toolbox images
1555 
1556 	if ( rBitmapDataSeq.getLength() > 0 )
1557 	{
1558 		SvMemoryStream	aMemStream( rBitmapDataSeq.getArray(), rBitmapDataSeq.getLength(), STREAM_STD_READ );
1559 		BitmapEx 		aBitmapEx;
1560 
1561         aMemStream >> aBitmapEx;
1562 
1563 		// Scale bitmap to fit the correct size for the menu/toolbar. Use best quality
1564 		if ( aBitmapEx.GetSizePixel() != aSize )
1565 			aBitmapEx.Scale( aSize, BMP_SCALE_INTERPOLATE );
1566 
1567         if( !aBitmapEx.IsTransparent() )
1568         {
1569             // Support non-transparent bitmaps to be downward compatible with OOo 1.1.x addons
1570             aBitmapEx = BitmapEx( aBitmapEx.GetBitmap(), COL_LIGHTMAGENTA );
1571         }
1572 
1573 		rImage = Image( aBitmapEx );
1574 		bResult = sal_True;
1575 	}
1576 
1577 	return bResult;
1578 }
1579 
1580 //*****************************************************************************************************************
1581 //	private methods
1582 //*****************************************************************************************************************
1583 Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesMergeMenuInstruction( const ::rtl::OUString& aPropertyRootNode ) const
1584 {
1585 	Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_MERGE_MENUBAR );
1586 
1587     // Create property names dependent from the root node name
1588     lResult[ OFFSET_MERGEMENU_MERGEPOINT            ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEPOINT    ] );
1589     lResult[ OFFSET_MERGEMENU_MERGECOMMAND          ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMAND  ] );
1590     lResult[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECOMMANDPARAMETER ] );
1591     lResult[ OFFSET_MERGEMENU_MERGEFALLBACK         ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGEFALLBACK ] );
1592     lResult[ OFFSET_MERGEMENU_MERGECONTEXT          ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MERGECONTEXT  ] );
1593     lResult[ OFFSET_MERGEMENU_MENUITEMS             ] = ::rtl::OUString( aPropertyRootNode + m_aPropMergeMenuNames[ OFFSET_MERGEMENU_MENUITEMS     ] );
1594 
1595 	return lResult;
1596 }
1597 
1598 Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesMenuItem( const ::rtl::OUString& aPropertyRootNode ) const
1599 {
1600 	Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_MENUITEM );
1601 
1602     // Create property names dependent from the root node name
1603 	lResult[OFFSET_MENUITEM_URL]             = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_URL			 ] );
1604 	lResult[OFFSET_MENUITEM_TITLE]           = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TITLE			 ] );
1605 	lResult[OFFSET_MENUITEM_IMAGEIDENTIFIER] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER ] );
1606 	lResult[OFFSET_MENUITEM_TARGET]          = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TARGET			 ] );
1607 	lResult[OFFSET_MENUITEM_CONTEXT]         = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT	     ] );
1608 	lResult[OFFSET_MENUITEM_SUBMENU]         = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_SUBMENU	     ] );
1609 
1610 	return lResult;
1611 }
1612 
1613 //*****************************************************************************************************************
1614 //	private method
1615 //*****************************************************************************************************************
1616 Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesPopupMenu( const ::rtl::OUString& aPropertyRootNode ) const
1617 {
1618 	// The URL is automatically set and not read from the configuration.
1619 	Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_POPUPMENU-1 );
1620 
1621 	// Create property names dependent from the root node name
1622 	lResult[OFFSET_POPUPMENU_TITLE]   = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TITLE	] );
1623 	lResult[OFFSET_POPUPMENU_CONTEXT] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT	] );
1624 	lResult[OFFSET_POPUPMENU_SUBMENU] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_SUBMENU	] );
1625 
1626 	return lResult;
1627 }
1628 
1629 //*****************************************************************************************************************
1630 //	private method
1631 //*****************************************************************************************************************
1632 Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesToolBarItem( const ::rtl::OUString& aPropertyRootNode ) const
1633 {
1634 	Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_TOOLBARITEM );
1635 
1636 	// Create property names dependent from the root node name
1637 	lResult[0] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_URL			  ] );
1638 	lResult[1] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TITLE		  ] );
1639 	lResult[2] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_IMAGEIDENTIFIER] );
1640 	lResult[3] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_TARGET		  ] );
1641 	lResult[4] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTEXT		  ] );
1642 	lResult[5] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_CONTROLTYPE	  ] );
1643 	lResult[6] = ::rtl::OUString( aPropertyRootNode + m_aPropNames[ INDEX_WIDTH		  ] );
1644 
1645 	return lResult;
1646 }
1647 
1648 //*****************************************************************************************************************
1649 //	private method
1650 //*****************************************************************************************************************
1651 Sequence< ::rtl::OUString > AddonsOptions_Impl::GetPropertyNamesImages( const ::rtl::OUString& aPropertyRootNode ) const
1652 {
1653 	Sequence< ::rtl::OUString > lResult( PROPERTYCOUNT_IMAGES );
1654 
1655 	// Create property names dependent from the root node name
1656 	lResult[0] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALL		] );
1657 	lResult[1] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIG		] );
1658 	lResult[2] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC	] );
1659 	lResult[3] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC		] );
1660 	lResult[4] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALL_URL  ] );
1661 	lResult[5] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIG_URL	] );
1662 	lResult[6] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_SMALLHC_URL] );
1663 	lResult[7] = ::rtl::OUString( aPropertyRootNode + m_aPropImagesNames[ OFFSET_IMAGES_BIGHC_URL	] );
1664 
1665 	return lResult;
1666 }
1667 
1668 //*****************************************************************************************************************
1669 //	initialize static member
1670 //	DON'T DO IT IN YOUR HEADER!
1671 //	see definition for further informations
1672 //*****************************************************************************************************************
1673 AddonsOptions_Impl*		AddonsOptions::m_pDataContainer = NULL  ;
1674 sal_Int32				AddonsOptions::m_nRefCount      = 0     ;
1675 
1676 //*****************************************************************************************************************
1677 //	constructor
1678 //*****************************************************************************************************************
1679 AddonsOptions::AddonsOptions()
1680 {
1681     // Global access, must be guarded (multithreading!).
1682     MutexGuard aGuard( GetOwnStaticMutex() );
1683 	// Increase ouer refcount ...
1684 	++m_nRefCount;
1685 	// ... and initialize ouer data container only if it not already exist!
1686     if( m_pDataContainer == NULL )
1687 	{
1688         m_pDataContainer = new AddonsOptions_Impl;
1689 	}
1690 }
1691 
1692 //*****************************************************************************************************************
1693 //	destructor
1694 //*****************************************************************************************************************
1695 AddonsOptions::~AddonsOptions()
1696 {
1697     // Global access, must be guarded (multithreading!)
1698     MutexGuard aGuard( GetOwnStaticMutex() );
1699 	// Decrease ouer refcount.
1700 	--m_nRefCount;
1701 	// If last instance was deleted ...
1702 	// we must destroy ouer static data container!
1703     if( m_nRefCount <= 0 )
1704 	{
1705 		delete m_pDataContainer;
1706 		m_pDataContainer = NULL;
1707 	}
1708 }
1709 
1710 //*****************************************************************************************************************
1711 //	public method
1712 //*****************************************************************************************************************
1713 sal_Bool AddonsOptions::HasAddonsMenu() const
1714 {
1715     MutexGuard aGuard( GetOwnStaticMutex() );
1716     return m_pDataContainer->HasAddonsMenu();
1717 }
1718 
1719 //*****************************************************************************************************************
1720 //	public method
1721 //*****************************************************************************************************************
1722 
1723 sal_Bool AddonsOptions::HasAddonsHelpMenu() const
1724 {
1725     MutexGuard aGuard( GetOwnStaticMutex() );
1726     return m_pDataContainer->HasAddonsHelpMenu();
1727 }
1728 
1729 //*****************************************************************************************************************
1730 //	public method
1731 //*****************************************************************************************************************
1732 
1733 sal_Int32 AddonsOptions::GetAddonsToolBarCount() const
1734 {
1735     MutexGuard aGuard( GetOwnStaticMutex() );
1736     return m_pDataContainer->GetAddonsToolBarCount();
1737 }
1738 
1739 //*****************************************************************************************************************
1740 //	public method
1741 //*****************************************************************************************************************
1742 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsMenu() const
1743 {
1744     MutexGuard aGuard( GetOwnStaticMutex() );
1745     return m_pDataContainer->GetAddonsMenu();
1746 }
1747 
1748 //*****************************************************************************************************************
1749 //	public method
1750 //*****************************************************************************************************************
1751 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsMenuBarPart() const
1752 {
1753     MutexGuard aGuard( GetOwnStaticMutex() );
1754     return m_pDataContainer->GetAddonsMenuBarPart();
1755 }
1756 
1757 //*****************************************************************************************************************
1758 //	public method
1759 //*****************************************************************************************************************
1760 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsToolBarPart( sal_uInt32 nIndex ) const
1761 {
1762     MutexGuard aGuard( GetOwnStaticMutex() );
1763     return m_pDataContainer->GetAddonsToolBarPart( nIndex );
1764 }
1765 
1766 //*****************************************************************************************************************
1767 //	public method
1768 //*****************************************************************************************************************
1769 const ::rtl::OUString AddonsOptions::GetAddonsToolbarResourceName( sal_uInt32 nIndex ) const
1770 {
1771     MutexGuard aGuard( GetOwnStaticMutex() );
1772     return m_pDataContainer->GetAddonsToolbarResourceName( nIndex );
1773 }
1774 
1775 //*****************************************************************************************************************
1776 //	public method
1777 //*****************************************************************************************************************
1778 const Sequence< Sequence< PropertyValue > >& AddonsOptions::GetAddonsHelpMenu() const
1779 {
1780     MutexGuard aGuard( GetOwnStaticMutex() );
1781     return m_pDataContainer->GetAddonsHelpMenu();
1782 }
1783 
1784 //*****************************************************************************************************************
1785 //	public method
1786 //*****************************************************************************************************************
1787 const MergeMenuInstructionContainer& AddonsOptions::GetMergeMenuInstructions() const
1788 {
1789     MutexGuard aGuard( GetOwnStaticMutex() );
1790     return m_pDataContainer->GetMergeMenuInstructions();
1791 }
1792 
1793 //*****************************************************************************************************************
1794 //	public method
1795 //*****************************************************************************************************************
1796 bool AddonsOptions::GetMergeToolbarInstructions(
1797     const ::rtl::OUString& rToolbarName,
1798     MergeToolbarInstructionContainer& rToolbarInstructions ) const
1799 {
1800     MutexGuard aGuard( GetOwnStaticMutex() );
1801     return m_pDataContainer->GetMergeToolbarInstructions(
1802         rToolbarName, rToolbarInstructions );
1803 }
1804 
1805 //*****************************************************************************************************************
1806 //	public method
1807 //*****************************************************************************************************************
1808 Image AddonsOptions::GetImageFromURL( const rtl::OUString& aURL, sal_Bool bBig, sal_Bool bHiContrast, sal_Bool bNoScale ) const
1809 {
1810     MutexGuard aGuard( GetOwnStaticMutex() );
1811     return m_pDataContainer->GetImageFromURL( aURL, bBig, bHiContrast, bNoScale );
1812 }
1813 
1814 //*****************************************************************************************************************
1815 //	public method
1816 //*****************************************************************************************************************
1817 Image AddonsOptions::GetImageFromURL( const rtl::OUString& aURL, sal_Bool bBig, sal_Bool bHiContrast ) const
1818 {
1819     return GetImageFromURL( aURL, bBig, bHiContrast, sal_False );
1820 }
1821 
1822 //*****************************************************************************************************************
1823 //	private method
1824 //*****************************************************************************************************************
1825 Mutex& AddonsOptions::GetOwnStaticMutex()
1826 {
1827 	// Initialize static mutex only for one time!
1828     static Mutex* pMutex = NULL;
1829 	// If these method first called (Mutex not already exist!) ...
1830     if( pMutex == NULL )
1831     {
1832 		// ... we must create a new one. Protect follow code with the global mutex -
1833 		// It must be - we create a static variable!
1834         MutexGuard aGuard( Mutex::getGlobalMutex() );
1835 		// We must check our pointer again - because it can be that another instance of ouer class will be fastr then these!
1836         if( pMutex == NULL )
1837         {
1838 			// Create the new mutex and set it for return on static variable.
1839             static Mutex aMutex;
1840             pMutex = &aMutex;
1841         }
1842     }
1843 	// Return new created or already existing mutex object.
1844     return *pMutex;
1845 }
1846 
1847 //*****************************************************************************************************************
1848 //	private method
1849 //*****************************************************************************************************************
1850 IMPL_STATIC_LINK_NOINSTANCE( AddonsOptions, Notify, void*, EMPTYARG )
1851 {
1852     MutexGuard aGuard( GetOwnStaticMutex() );
1853     m_pDataContainer->ReadConfigurationData();
1854 	return 0;
1855 }
1856 
1857 }
1858 
1859