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