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