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