xref: /aoo41x/main/vcl/source/window/menu.cxx (revision 9f62ea84)
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_vcl.hxx"
26 
27 #include "tools/list.hxx"
28 #include "tools/debug.hxx"
29 #include "tools/diagnose_ex.h"
30 #include "tools/rc.h"
31 #include "tools/stream.hxx"
32 
33 #include "vcl/svapp.hxx"
34 #include "vcl/mnemonic.hxx"
35 #include "vcl/image.hxx"
36 #include "vcl/event.hxx"
37 #include "vcl/help.hxx"
38 #include "vcl/floatwin.hxx"
39 #include "vcl/wrkwin.hxx"
40 #include "vcl/timer.hxx"
41 #include "vcl/sound.hxx"
42 #include "vcl/decoview.hxx"
43 #include "vcl/bitmap.hxx"
44 #include "vcl/menu.hxx"
45 #include "vcl/button.hxx"
46 #include "vcl/gradient.hxx"
47 #include "vcl/i18nhelp.hxx"
48 #include "vcl/taskpanelist.hxx"
49 #include "vcl/controllayout.hxx"
50 #include "vcl/toolbox.hxx"
51 #include "vcl/dockingarea.hxx"
52 
53 #include "salinst.hxx"
54 #include "svdata.hxx"
55 #include "svids.hrc"
56 #include "window.h"
57 #include "salmenu.hxx"
58 #include "salframe.hxx"
59 
60 
61 #include <com/sun/star/uno/Reference.h>
62 #include <com/sun/star/i18n/XCharacterClassification.hpp>
63 #include <com/sun/star/lang/XComponent.hpp>
64 #include <com/sun/star/accessibility/XAccessible.hpp>
65 #include <com/sun/star/accessibility/AccessibleRole.hpp>
66 #include <vcl/unowrap.hxx>
67 
68 #include <vcl/unohelp.hxx>
69 #include <vcl/configsettings.hxx>
70 
71 #include "vcl/lazydelete.hxx"
72 
73 #include <map>
74 
75 namespace vcl
76 {
77 
78 struct MenuLayoutData : public ControlLayoutData
79 {
80     std::vector< sal_uInt16 >				m_aLineItemIds;
81     std::vector< sal_uInt16 >				m_aLineItemPositions;
82     std::map< sal_uInt16, Rectangle >		m_aVisibleItemBoundRects;
83 };
84 
85 }
86 
87 using namespace ::com::sun::star;
88 using namespace vcl;
89 
90 DBG_NAME( Menu )
91 
92 #define ITEMPOS_INVALID     0xFFFF
93 
94 #define EXTRASPACEY         2
95 #define EXTRAITEMHEIGHT     4
96 #define GUTTERBORDER        8
97 
98 // document closer
99 #define IID_DOCUMENTCLOSE 1
100 
101 #ifdef OS2
102 
103 #include <xwphook.h>
104 
105 // return sal_True if hilite should be executed: left mouse button down
106 // or xwp mouse hook enabled
107 static sal_Bool ImplHilite( const MouseEvent& rMEvt )
108 {
109 	static sal_Bool init = sal_False;
110 	static HOOKCONFIG hc;
111 
112 	// read XWP settings at program startup
113 	if (init == sal_False) {
114 		sal_Bool	rc;
115 		sal_uLong 	cb = sizeof(HOOKCONFIG);
116 		memset(&hc, 0, sizeof(HOOKCONFIG));
117 		rc = PrfQueryProfileData( HINI_USER, INIAPP_XWPHOOK, INIKEY_HOOK_CONFIG,
118 			&hc, &cb);
119 		init = sal_True;
120 	}
121 	// check mouse left button
122 	if (rMEvt.GetButtons() == MOUSE_LEFT)
123 		return sal_True;
124 	// return xwp flag
125 	return hc.fSlidingMenus;
126 }
127 
128 #endif
129 
130 static sal_Bool ImplAccelDisabled()
131 {
132     // display of accelerator strings may be suppressed via configuration
133     static int nAccelDisabled = -1;
134 
135     if( nAccelDisabled == -1 )
136     {
137         rtl::OUString aStr =
138             vcl::SettingsConfigItem::get()->
139             getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Menu" ) ),
140                         rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SuppressAccelerators" ) ) );
141         nAccelDisabled = aStr.equalsIgnoreAsciiCaseAscii( "true" ) ? 1 : 0;
142     }
143     return (nAccelDisabled == 1) ? sal_True : sal_False;
144 }
145 
146 struct MenuItemData
147 {
148     sal_uInt16          nId;					// SV Id
149     MenuItemType    eType;					// MenuItem-Type
150     MenuItemBits    nBits;					// MenuItem-Bits
151     Menu*           pSubMenu;				// Pointer auf das SubMenu
152     Menu*           pAutoSubMenu;			// Pointer auf SubMenu aus Resource
153     XubString       aText;					// Menu-Text
154     XubString       aHelpText;				// Help-String
155     XubString       aTipHelpText;			// TipHelp-String (eg, expanded filenames)
156     XubString       aCommandStr;			// CommandString
157     XubString       aHelpCommandStr;        // Help command string (to reference external help)
158     rtl::OString    aHelpId;				// Help-Id
159     sal_uLong           nUserValue;				// User value
160     Image           aImage;					// Image
161     KeyCode         aAccelKey;				// Accelerator-Key
162     sal_Bool            bChecked;				// Checked
163     sal_Bool            bEnabled;				// Enabled
164     sal_Bool            bVisible;				// Visible (note: this flag will not override MENU_FLAG_HIDEDISABLEDENTRIES when true)
165     sal_Bool            bIsTemporary;			// Temporary inserted ('No selection possible')
166     sal_Bool			bMirrorMode;
167     long			nItemImageAngle;
168     Size            aSz;					// nur temporaer gueltig
169 	XubString		aAccessibleName;		// accessible name
170 	XubString		aAccessibleDescription;	// accessible description
171 
172     SalMenuItem*    pSalMenuItem;           // access to native menu
173 
174                     MenuItemData() :
175                         pSalMenuItem ( NULL )
176                     {}
177                     MenuItemData( const XubString& rStr, const Image& rImage ) :
178                         aText( rStr ),
179                         aImage( rImage ),
180                         pSalMenuItem ( NULL )
181                     {}
182                     ~MenuItemData();
183 		bool HasCheck()
184 		{
185 			return bChecked || ( nBits & ( MIB_RADIOCHECK | MIB_CHECKABLE | MIB_AUTOCHECK ) );
186 		}
187 };
188 
189 MenuItemData::~MenuItemData()
190 {
191     if( pAutoSubMenu )
192     {
193         ((PopupMenu*)pAutoSubMenu)->pRefAutoSubMenu = NULL;
194         delete pAutoSubMenu;
195         pAutoSubMenu = NULL;
196     }
197     if( pSalMenuItem )
198         ImplGetSVData()->mpDefInst->DestroyMenuItem( pSalMenuItem );
199 }
200 
201 class MenuItemList : public List
202 {
203 private:
204     uno::Reference< i18n::XCharacterClassification > xCharClass;
205 
206 
207 public:
208                     MenuItemList() : List( 16, 4 ) {}
209                     ~MenuItemList();
210 
211     MenuItemData*   Insert( sal_uInt16 nId, MenuItemType eType, MenuItemBits nBits,
212                             const XubString& rStr, const Image& rImage,
213                             Menu* pMenu, sal_uInt16 nPos );
214     void            InsertSeparator( sal_uInt16 nPos );
215     void            Remove( sal_uInt16 nPos );
216 
217 
218     MenuItemData*   GetData( sal_uInt16 nSVId, sal_uInt16& rPos ) const;
219     MenuItemData*   GetData( sal_uInt16 nSVId ) const
220                         { sal_uInt16 nTemp; return GetData( nSVId, nTemp ); }
221     MenuItemData*   GetDataFromPos( sal_uLong nPos ) const
222                         { return (MenuItemData*)List::GetObject( nPos ); }
223 
224     MenuItemData*   SearchItem( xub_Unicode cSelectChar, KeyCode aKeyCode, sal_uInt16& rPos, sal_uInt16& nDuplicates, sal_uInt16 nCurrentPos ) const;
225 	sal_uInt16			GetItemCount( xub_Unicode cSelectChar ) const;
226     sal_uInt16          GetItemCount( KeyCode aKeyCode ) const;
227 
228     uno::Reference< i18n::XCharacterClassification > GetCharClass() const;
229 };
230 
231 
232 
233 MenuItemList::~MenuItemList()
234 {
235     for ( sal_uLong n = Count(); n; )
236     {
237         MenuItemData* pData = GetDataFromPos( --n );
238         delete pData;
239     }
240 }
241 
242 MenuItemData* MenuItemList::Insert( sal_uInt16 nId, MenuItemType eType,
243                                     MenuItemBits nBits,
244                                     const XubString& rStr, const Image& rImage,
245                                     Menu* pMenu, sal_uInt16 nPos )
246 {
247     MenuItemData* pData		= new MenuItemData( rStr, rImage );
248     pData->nId          	= nId;
249     pData->eType        	= eType;
250     pData->nBits        	= nBits;
251     pData->pSubMenu     	= NULL;
252     pData->pAutoSubMenu 	= NULL;
253     pData->nUserValue   	= 0;
254     pData->bChecked     	= sal_False;
255     pData->bEnabled     	= sal_True;
256     pData->bVisible     	= sal_True;
257     pData->bIsTemporary 	= sal_False;
258     pData->bMirrorMode		= sal_False;
259     pData->nItemImageAngle	= 0;
260 
261     SalItemParams aSalMIData;
262     aSalMIData.nId = nId;
263     aSalMIData.eType = eType;
264     aSalMIData.nBits = nBits;
265     aSalMIData.pMenu = pMenu;
266     aSalMIData.aText = rStr;
267     aSalMIData.aImage = rImage;
268 
269     // Native-support: returns NULL if not supported
270     pData->pSalMenuItem = ImplGetSVData()->mpDefInst->CreateMenuItem( &aSalMIData );
271 
272     List::Insert( (void*)pData, nPos );
273     return pData;
274 }
275 
276 void MenuItemList::InsertSeparator( sal_uInt16 nPos )
277 {
278     MenuItemData* pData		= new MenuItemData;
279     pData->nId          	= 0;
280     pData->eType        	= MENUITEM_SEPARATOR;
281     pData->nBits        	= 0;
282     pData->pSubMenu     	= NULL;
283     pData->pAutoSubMenu 	= NULL;
284     pData->nUserValue   	= 0;
285     pData->bChecked     	= sal_False;
286     pData->bEnabled     	= sal_True;
287     pData->bVisible     	= sal_True;
288     pData->bIsTemporary 	= sal_False;
289     pData->bMirrorMode		= sal_False;
290     pData->nItemImageAngle	= 0;
291 
292     SalItemParams aSalMIData;
293     aSalMIData.nId = 0;
294     aSalMIData.eType = MENUITEM_SEPARATOR;
295     aSalMIData.nBits = 0;
296     aSalMIData.pMenu = NULL;
297     aSalMIData.aText = XubString();
298     aSalMIData.aImage = Image();
299 
300     // Native-support: returns NULL if not supported
301     pData->pSalMenuItem = ImplGetSVData()->mpDefInst->CreateMenuItem( &aSalMIData );
302 
303     List::Insert( (void*)pData, nPos );
304 }
305 
306 void MenuItemList::Remove( sal_uInt16 nPos )
307 {
308     MenuItemData* pData = (MenuItemData*)List::Remove( (sal_uLong)nPos );
309     if ( pData )
310         delete pData;
311 }
312 
313 MenuItemData* MenuItemList::GetData( sal_uInt16 nSVId, sal_uInt16& rPos ) const
314 {
315     rPos = 0;
316     MenuItemData* pData = (MenuItemData*)GetObject( rPos );
317     while ( pData )
318     {
319         if ( pData->nId == nSVId )
320             return pData;
321 
322         rPos++;
323         pData = (MenuItemData*)GetObject( rPos );
324     }
325 
326     return NULL;
327 }
328 
329 MenuItemData* MenuItemList::SearchItem( xub_Unicode cSelectChar, KeyCode aKeyCode, sal_uInt16& rPos, sal_uInt16& nDuplicates, sal_uInt16 nCurrentPos ) const
330 {
331     const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
332 
333 	sal_uInt16 nListCount = (sal_uInt16)Count();
334 
335     // try character code first
336 	nDuplicates = GetItemCount( cSelectChar );	// return number of duplicates
337     if( nDuplicates )
338     {
339         for ( rPos = 0; rPos < nListCount; rPos++)
340         {
341             MenuItemData* pData = GetDataFromPos( rPos );
342             if ( pData->bEnabled && rI18nHelper.MatchMnemonic( pData->aText, cSelectChar ) )
343             {
344 			    if( nDuplicates > 1 && rPos == nCurrentPos )
345 				    continue;	// select next entry with the same mnemonic
346 			    else
347 				    return pData;
348             }
349         }
350     }
351 
352     // nothing found, try keycode instead
353 	nDuplicates = GetItemCount( aKeyCode );	// return number of duplicates
354 
355     if( nDuplicates )
356     {
357         char ascii = 0;
358         if( aKeyCode.GetCode() >= KEY_A && aKeyCode.GetCode() <= KEY_Z )
359             ascii = sal::static_int_cast<char>('A' + (aKeyCode.GetCode() - KEY_A));
360 
361         for ( rPos = 0; rPos < nListCount; rPos++)
362         {
363             MenuItemData* pData = GetDataFromPos( rPos );
364             if ( pData->bEnabled )
365             {
366                 sal_uInt16 n = pData->aText.Search( '~' );
367                 if ( n != STRING_NOTFOUND )
368                 {
369                     KeyCode mnKeyCode;
370                     xub_Unicode mnUnicode = pData->aText.GetChar(n+1);
371                     Window* pDefWindow = ImplGetDefaultWindow();
372                     if( (pDefWindow && pDefWindow->ImplGetFrame()->MapUnicodeToKeyCode( mnUnicode, Application::GetSettings().GetUILanguage(), mnKeyCode )
373                         && aKeyCode.GetCode() == mnKeyCode.GetCode())
374                         || (ascii && rI18nHelper.MatchMnemonic( pData->aText, ascii ) ) )
375 
376                     {
377 			            if( nDuplicates > 1 && rPos == nCurrentPos )
378 				            continue;	// select next entry with the same mnemonic
379 			            else
380 				            return pData;
381                     }
382                 }
383             }
384         }
385     }
386 
387     return NULL;
388 }
389 
390 sal_uInt16 MenuItemList::GetItemCount( xub_Unicode cSelectChar ) const
391 {
392 	// returns number of entries with same mnemonic
393     const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
394 
395 	sal_uInt16 nItems = 0, nPos;
396     for ( nPos = (sal_uInt16)Count(); nPos; )
397     {
398         MenuItemData* pData = GetDataFromPos( --nPos );
399         if ( pData->bEnabled && rI18nHelper.MatchMnemonic( pData->aText, cSelectChar ) )
400             nItems++;
401     }
402 
403     return nItems;
404 }
405 
406 sal_uInt16 MenuItemList::GetItemCount( KeyCode aKeyCode ) const
407 {
408 	// returns number of entries with same mnemonic
409     // uses key codes instead of character codes
410     const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
411     char ascii = 0;
412     if( aKeyCode.GetCode() >= KEY_A && aKeyCode.GetCode() <= KEY_Z )
413         ascii = sal::static_int_cast<char>('A' + (aKeyCode.GetCode() - KEY_A));
414 
415 	sal_uInt16 nItems = 0, nPos;
416     for ( nPos = (sal_uInt16)Count(); nPos; )
417     {
418         MenuItemData* pData = GetDataFromPos( --nPos );
419         if ( pData->bEnabled )
420         {
421             sal_uInt16 n = pData->aText.Search( '~' );
422             if ( n != STRING_NOTFOUND )
423             {
424                 KeyCode mnKeyCode;
425                 // if MapUnicodeToKeyCode fails or is unsupported we try the pure ascii mapping of the keycodes
426                 // so we have working shortcuts when ascii mnemonics are used
427                 Window* pDefWindow = ImplGetDefaultWindow();
428                 if( (pDefWindow && pDefWindow->ImplGetFrame()->MapUnicodeToKeyCode( pData->aText.GetChar(n+1), Application::GetSettings().GetUILanguage(), mnKeyCode )
429                     && aKeyCode.GetCode() == mnKeyCode.GetCode())
430                     || ( ascii && rI18nHelper.MatchMnemonic( pData->aText, ascii ) ) )
431                     nItems++;
432             }
433         }
434     }
435 
436     return nItems;
437 }
438 
439 uno::Reference< i18n::XCharacterClassification > MenuItemList::GetCharClass() const
440 {
441     if ( !xCharClass.is() )
442         ((MenuItemList*)this)->xCharClass = vcl::unohelper::CreateCharacterClassification();
443     return xCharClass;
444 }
445 
446 
447 
448 // ----------------------
449 // - MenuFloatingWindow -
450 // ----------------------
451 
452 class MenuFloatingWindow : public FloatingWindow
453 {
454     friend void Menu::ImplFillLayoutData() const;
455     friend Menu::~Menu();
456 
457 private:
458     Menu*           pMenu;
459     PopupMenu*      pActivePopup;
460     Timer           aHighlightChangedTimer;
461     Timer           aSubmenuCloseTimer;
462     Timer           aScrollTimer;
463     sal_uLong           nSaveFocusId;
464 //    long            nStartY;
465     sal_uInt16          nHighlightedItem;       // gehighlightetes/selektiertes Item
466     sal_uInt16          nMBDownPos;
467     sal_uInt16          nScrollerHeight;
468     sal_uInt16          nFirstEntry;
469     sal_uInt16          nBorder;
470     sal_uInt16          nPosInParent;
471     sal_Bool            bInExecute;
472 
473     sal_Bool            bScrollMenu;
474     sal_Bool            bScrollUp;
475     sal_Bool            bScrollDown;
476     sal_Bool            bIgnoreFirstMove;
477     sal_Bool            bKeyInput;
478 
479                     DECL_LINK( PopupEnd, FloatingWindow* );
480                     DECL_LINK( HighlightChanged, Timer* );
481                     DECL_LINK( SubmenuClose, Timer* );
482                     DECL_LINK( AutoScroll, Timer* );
483                     DECL_LINK( ShowHideListener, VclWindowEvent* );
484 
485     void            StateChanged( StateChangedType nType );
486     void            DataChanged( const DataChangedEvent& rDCEvt );
487 protected:
488     Region          ImplCalcClipRegion( sal_Bool bIncludeLogo = sal_True ) const;
489     void            ImplInitClipRegion();
490     void            ImplDrawScroller( sal_Bool bUp );
491     using Window::ImplScroll;
492     void            ImplScroll( const Point& rMousePos );
493     void            ImplScroll( sal_Bool bUp );
494     void            ImplCursorUpDown( sal_Bool bUp, sal_Bool bHomeEnd = sal_False );
495     void            ImplHighlightItem( const MouseEvent& rMEvt, sal_Bool bMBDown );
496     long            ImplGetStartY() const;
497 	Rectangle		ImplGetItemRect( sal_uInt16 nPos );
498 
499 public:
500                     MenuFloatingWindow( Menu* pMenu, Window* pParent, WinBits nStyle );
501                     ~MenuFloatingWindow();
502 
503             void    doShutdown();
504 
505     virtual void    MouseMove( const MouseEvent& rMEvt );
506     virtual void    MouseButtonDown( const MouseEvent& rMEvt );
507     virtual void    MouseButtonUp( const MouseEvent& rMEvt );
508     virtual void    KeyInput( const KeyEvent& rKEvent );
509     virtual void    Command( const CommandEvent& rCEvt );
510     virtual void    Paint( const Rectangle& rRect );
511     virtual void    RequestHelp( const HelpEvent& rHEvt );
512     virtual void    Resize();
513 
514     void            SetFocusId( sal_uLong nId ) { nSaveFocusId = nId; }
515     sal_uLong           GetFocusId() const      { return nSaveFocusId; }
516 
517     void            EnableScrollMenu( sal_Bool b );
518     sal_Bool            IsScrollMenu() const        { return bScrollMenu; }
519     sal_uInt16          GetScrollerHeight() const   { return nScrollerHeight; }
520 
521     void            Execute();
522     void            StopExecute( sal_uLong nFocusId = 0 );
523     void            EndExecute();
524     void            EndExecute( sal_uInt16 nSelectId );
525 
526     PopupMenu*      GetActivePopup() const  { return pActivePopup; }
527     void            KillActivePopup( PopupMenu* pThisOnly = NULL );
528 
529     void            HighlightItem( sal_uInt16 nPos, sal_Bool bHighlight );
530     void            ChangeHighlightItem( sal_uInt16 n, sal_Bool bStartPopupTimer );
531     sal_uInt16          GetHighlightedItem() const { return nHighlightedItem; }
532 
533     void            SetPosInParent( sal_uInt16 nPos ) { nPosInParent = nPos; }
534     sal_uInt16          GetPosInParent() const { return nPosInParent; }
535 
536     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible();
537 };
538 
539 // To get the transparent mouse-over look, the closer is actually a toolbox
540 // overload DataChange to handle style changes correctly
541 class DecoToolBox : public ToolBox
542 {
543     long lastSize;
544     Size maMinSize;
545 
546     using Window::ImplInit;
547 public:
548             DecoToolBox( Window* pParent, WinBits nStyle = 0 );
549             DecoToolBox( Window* pParent, const ResId& rResId );
550     void    ImplInit();
551 
552     void    DataChanged( const DataChangedEvent& rDCEvt );
553 
554     void    SetImages( long nMaxHeight = 0, bool bForce = false );
555 
556     void    calcMinSize();
557     Size    getMinSize();
558 
559     Image   maImage;
560     Image   maImageHC;
561 };
562 
563 DecoToolBox::DecoToolBox( Window* pParent, WinBits nStyle ) :
564     ToolBox( pParent, nStyle )
565 {
566     ImplInit();
567 }
568 DecoToolBox::DecoToolBox( Window* pParent, const ResId& rResId ) :
569     ToolBox( pParent, rResId )
570 {
571     ImplInit();
572 }
573 
574 void DecoToolBox::ImplInit()
575 {
576     lastSize = -1;
577     calcMinSize();
578 }
579 
580 void DecoToolBox::DataChanged( const DataChangedEvent& rDCEvt )
581 {
582     Window::DataChanged( rDCEvt );
583 
584     if ( rDCEvt.GetFlags() & SETTINGS_STYLE )
585     {
586         calcMinSize();
587         SetBackground();
588         SetImages( 0, true);
589     }
590 }
591 
592 void DecoToolBox::calcMinSize()
593 {
594     ToolBox aTbx( GetParent() );
595     if( GetItemCount() == 0 )
596     {
597         ResMgr* pResMgr = ImplGetResMgr();
598 
599         Bitmap aBitmap;
600         if( pResMgr )
601             aBitmap = Bitmap( ResId( SV_RESID_BITMAP_CLOSEDOC, *pResMgr ) );
602         aTbx.InsertItem( IID_DOCUMENTCLOSE, Image( aBitmap ) );
603     }
604     else
605     {
606         sal_uInt16 nItems = GetItemCount();
607         for( sal_uInt16 i = 0; i < nItems; i++ )
608         {
609             sal_uInt16 nId = GetItemId( i );
610             aTbx.InsertItem( nId, GetItemImage( nId ) );
611         }
612     }
613     aTbx.SetOutStyle( TOOLBOX_STYLE_FLAT );
614     maMinSize = aTbx.CalcWindowSizePixel();
615 }
616 
617 Size DecoToolBox::getMinSize()
618 {
619     return maMinSize;
620 }
621 
622 void DecoToolBox::SetImages( long nMaxHeight, bool bForce )
623 {
624     long border = getMinSize().Height() - maImage.GetSizePixel().Height();
625 
626     if( !nMaxHeight && lastSize != -1 )
627         nMaxHeight = lastSize + border; // don't change anything if called with 0
628 
629     if( nMaxHeight < getMinSize().Height() )
630         nMaxHeight = getMinSize().Height();
631 
632     if( (lastSize != nMaxHeight - border) || bForce )
633     {
634         lastSize = nMaxHeight - border;
635 
636 		Color		aEraseColor( 255, 255, 255, 255 );
637         BitmapEx 	aBmpExDst( maImage.GetBitmapEx() );
638         BitmapEx 	aBmpExSrc( GetSettings().GetStyleSettings().GetHighContrastMode() ?
639             			  	maImageHC.GetBitmapEx() : aBmpExDst );
640 
641 		aEraseColor.SetTransparency( 255 );
642 		aBmpExDst.Erase( aEraseColor );
643         aBmpExDst.SetSizePixel( Size( lastSize, lastSize ) );
644 
645         Rectangle aSrcRect( Point(0,0), maImage.GetSizePixel() );
646         Rectangle aDestRect( Point((lastSize - maImage.GetSizePixel().Width())/2,
647 								(lastSize - maImage.GetSizePixel().Height())/2 ),
648 							maImage.GetSizePixel() );
649 
650 
651 		aBmpExDst.CopyPixel( aDestRect, aSrcRect, &aBmpExSrc );
652         SetItemImage( IID_DOCUMENTCLOSE, Image( aBmpExDst ) );
653     }
654 }
655 
656 
657 // Eine Basicklasse fuer beide (wegen pActivePopup, Timer, ...) waere nett,
658 // aber dann musste eine 'Container'-Klasse gemacht werden, da von
659 // unterschiedlichen Windows abgeleitet...
660 // In den meisten Funktionen muessen dann sowieso Sonderbehandlungen fuer
661 // MenuBar, PopupMenu gemacht werden, also doch zwei verschiedene Klassen.
662 
663 class MenuBarWindow : public Window
664 {
665     friend class MenuBar;
666     friend class Menu;
667 
668 private:
669     struct AddButtonEntry
670     {
671         sal_uInt16      m_nId;
672         Link        m_aSelectLink;
673         Link        m_aHighlightLink;
674 
675         AddButtonEntry() : m_nId( 0 ) {}
676     };
677 
678     Menu*           pMenu;
679     PopupMenu*      pActivePopup;
680     sal_uInt16          nHighlightedItem;
681     sal_uLong           nSaveFocusId;
682     sal_Bool            mbAutoPopup;
683     sal_Bool            bIgnoreFirstMove;
684 	sal_Bool			bStayActive;
685 
686     DecoToolBox     aCloser;
687     PushButton      aFloatBtn;
688     PushButton      aHideBtn;
689 
690     std::map< sal_uInt16, AddButtonEntry > m_aAddButtons;
691 
692     void            HighlightItem( sal_uInt16 nPos, sal_Bool bHighlight );
693     void            ChangeHighlightItem( sal_uInt16 n, sal_Bool bSelectPopupEntry, sal_Bool bAllowRestoreFocus = sal_True, sal_Bool bDefaultToDocument = sal_True );
694 
695     sal_uInt16          ImplFindEntry( const Point& rMousePos ) const;
696     void            ImplCreatePopup( sal_Bool bPreSelectFirst );
697     sal_Bool            ImplHandleKeyEvent( const KeyEvent& rKEvent, sal_Bool bFromMenu = sal_True );
698 	Rectangle		ImplGetItemRect( sal_uInt16 nPos );
699 
700     void            ImplInitStyleSettings();
701 
702                     DECL_LINK( CloserHdl, PushButton* );
703                     DECL_LINK( FloatHdl, PushButton* );
704                     DECL_LINK( HideHdl, PushButton* );
705                     DECL_LINK( ToolboxEventHdl, VclWindowEvent* );
706                     DECL_LINK( ShowHideListener, VclWindowEvent* );
707 
708     void            StateChanged( StateChangedType nType );
709     void            DataChanged( const DataChangedEvent& rDCEvt );
710     void            LoseFocus();
711     void            GetFocus();
712 
713 public:
714                     MenuBarWindow( Window* pParent );
715                     ~MenuBarWindow();
716 
717     void            ShowButtons( sal_Bool bClose, sal_Bool bFloat, sal_Bool bHide );
718 
719     virtual void    MouseMove( const MouseEvent& rMEvt );
720     virtual void    MouseButtonDown( const MouseEvent& rMEvt );
721     virtual void    MouseButtonUp( const MouseEvent& rMEvt );
722     virtual void    KeyInput( const KeyEvent& rKEvent );
723     virtual void    Paint( const Rectangle& rRect );
724     virtual void    Resize();
725     virtual void    RequestHelp( const HelpEvent& rHEvt );
726 
727     void            SetFocusId( sal_uLong nId ) { nSaveFocusId = nId; }
728     sal_uLong           GetFocusId() const { return nSaveFocusId; }
729 
730     void            SetMenu( MenuBar* pMenu );
731     void            KillActivePopup();
732     PopupMenu*      GetActivePopup() const  { return pActivePopup; }
733     void            PopupClosed( Menu* pMenu );
734     sal_uInt16          GetHighlightedItem() const { return nHighlightedItem; }
735     virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible();
736 
737     void SetAutoPopup( sal_Bool bAuto ) { mbAutoPopup = bAuto; }
738     void            ImplLayoutChanged();
739     Size            MinCloseButtonSize();
740 
741     // add an arbitrary button to the menubar (will appear next to closer)
742     sal_uInt16              AddMenuBarButton( const Image&, const Link&, const String&, sal_uInt16 nPos );
743     void                SetMenuBarButtonHighlightHdl( sal_uInt16 nId, const Link& );
744     Rectangle           GetMenuBarButtonRectPixel( sal_uInt16 nId );
745     void                RemoveMenuBarButton( sal_uInt16 nId );
746     bool                HandleMenuButtonEvent( sal_uInt16 i_nButtonId );
747 };
748 
749 static void ImplAddNWFSeparator( Window *pThis, const MenubarValue& rMenubarValue )
750 {
751     // add a separator if
752     // - we have an adjacent docking area
753     // - and if toolbars would draw them as well (mbDockingAreaSeparateTB must not be set, see dockingarea.cxx)
754     if( rMenubarValue.maTopDockingAreaHeight && !ImplGetSVData()->maNWFData.mbDockingAreaSeparateTB )
755     {
756         // note: the menubar only provides the upper (dark) half of it, the rest (bright part) is drawn by the docking area
757 
758         pThis->SetLineColor( pThis->GetSettings().GetStyleSettings().GetSeparatorColor() );
759         Point aPt;
760         Rectangle aRect( aPt, pThis->GetOutputSizePixel() );
761         pThis->DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
762     }
763 }
764 
765 static void ImplSetMenuItemData( MenuItemData* pData )
766 {
767     // Daten umsetzen
768     if ( !pData->aImage )
769         pData->eType = MENUITEM_STRING;
770     else if ( !pData->aText.Len() )
771         pData->eType = MENUITEM_IMAGE;
772     else
773         pData->eType = MENUITEM_STRINGIMAGE;
774 }
775 
776 static sal_uLong ImplChangeTipTimeout( sal_uLong nTimeout, Window *pWindow )
777 {
778        AllSettings aAllSettings( pWindow->GetSettings() );
779        HelpSettings aHelpSettings( aAllSettings.GetHelpSettings() );
780        sal_uLong nRet = aHelpSettings.GetTipTimeout();
781        aHelpSettings.SetTipTimeout( nTimeout );
782        aAllSettings.SetHelpSettings( aHelpSettings );
783        pWindow->SetSettings( aAllSettings );
784        return nRet;
785 }
786 
787 static sal_Bool ImplHandleHelpEvent( Window* pMenuWindow, Menu* pMenu, sal_uInt16 nHighlightedItem, const HelpEvent& rHEvt, const Rectangle &rHighlightRect )
788 {
789     if( ! pMenu )
790         return sal_False;
791 
792     sal_Bool bDone = sal_False;
793     sal_uInt16 nId = 0;
794 
795     if ( nHighlightedItem != ITEMPOS_INVALID )
796     {
797         MenuItemData* pItemData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
798         if ( pItemData )
799             nId = pItemData->nId;
800     }
801 
802     if ( ( rHEvt.GetMode() & HELPMODE_BALLOON ) && pMenuWindow )
803     {
804         Point aPos;
805 		if( rHEvt.KeyboardActivated() )
806 			aPos = rHighlightRect.Center();
807 		else
808 			aPos = rHEvt.GetMousePosPixel();
809 
810         Rectangle aRect( aPos, Size() );
811         if( pMenu->GetHelpText( nId ).Len() )
812             Help::ShowBalloon( pMenuWindow, aPos, pMenu->GetHelpText( nId ) );
813         else
814 		{
815 			// give user a chance to read the full filename
816 			sal_uLong oldTimeout=ImplChangeTipTimeout( 60000, pMenuWindow );
817 			// call always, even when strlen==0 to correctly remove tip
818 			Help::ShowQuickHelp( pMenuWindow, aRect, pMenu->GetTipHelpText( nId ) );
819 			ImplChangeTipTimeout( oldTimeout, pMenuWindow );
820 		}
821         bDone = sal_True;
822     }
823     else if ( ( rHEvt.GetMode() & HELPMODE_QUICK ) && pMenuWindow )
824     {
825         Point aPos = rHEvt.GetMousePosPixel();
826         Rectangle aRect( aPos, Size() );
827 		// give user a chance to read the full filename
828 		sal_uLong oldTimeout=ImplChangeTipTimeout( 60000, pMenuWindow );
829 		// call always, even when strlen==0 to correctly remove tip
830 		Help::ShowQuickHelp( pMenuWindow, aRect, pMenu->GetTipHelpText( nId ) );
831 		ImplChangeTipTimeout( oldTimeout, pMenuWindow );
832         bDone = sal_True;
833     }
834     else if ( rHEvt.GetMode() & (HELPMODE_CONTEXT | HELPMODE_EXTENDED) )
835     {
836         // Ist eine Hilfe in die Applikation selektiert
837         Help* pHelp = Application::GetHelp();
838         if ( pHelp )
839         {
840             // Ist eine ID vorhanden, dann Hilfe mit der ID aufrufen, sonst
841             // den Hilfe-Index
842             String aCommand = pMenu->GetItemCommand( nId );
843             rtl::OString aHelpId(  pMenu->GetHelpId( nId ) );
844             if( ! aHelpId.getLength() )
845                 aHelpId = OOO_HELP_INDEX;
846 
847             if ( aCommand.Len() )
848                 pHelp->Start( aCommand, NULL );
849             else
850                 pHelp->Start( rtl::OStringToOUString( aHelpId, RTL_TEXTENCODING_UTF8 ), NULL );
851         }
852         bDone = sal_True;
853     }
854     return bDone;
855 }
856 
857 static int ImplGetTopDockingAreaHeight( Window *pWindow )
858 {
859     // find docking area that is top aligned and return its height
860     // note: dockingareas are direct children of the SystemWindow
861     int height=0;
862     sal_Bool bDone = sal_False;
863     if( pWindow->ImplGetFrameWindow() )
864     {
865         Window *pWin = pWindow->ImplGetFrameWindow()->GetWindow( WINDOW_FIRSTCHILD); //mpWindowImpl->mpFirstChild;
866         while( pWin && !bDone )
867         {
868             if( pWin->IsSystemWindow() )
869             {
870                 pWin = pWin->GetWindow( WINDOW_FIRSTCHILD); //mpWindowImpl->mpFirstChild;
871                 while( pWin && !bDone )
872                 {
873                     DockingAreaWindow *pDockingArea = dynamic_cast< DockingAreaWindow* >( pWin );
874                     if( pDockingArea && pDockingArea->GetAlign() == WINDOWALIGN_TOP )
875                     {
876                         bDone = sal_True;
877                         if( pDockingArea->IsVisible() )
878                             height = pDockingArea->GetOutputSizePixel().Height();
879                     }
880                     else
881                         pWin = pWin->GetWindow( WINDOW_NEXT ); //mpWindowImpl->mpNext;
882                 }
883 
884             }
885             else
886                 pWin = pWin->GetWindow( WINDOW_NEXT ); //mpWindowImpl->mpNext;
887         }
888     }
889     return height;
890 }
891 
892 Menu::Menu()
893 {
894     DBG_CTOR( Menu, NULL );
895     bIsMenuBar = sal_False;
896     ImplInit();
897 }
898 
899 // this constructor makes sure we're creating the native menu
900 // with the correct type (ie, MenuBar vs. PopupMenu)
901 Menu::Menu( sal_Bool bMenubar )
902 {
903     DBG_CTOR( Menu, NULL );
904     bIsMenuBar = bMenubar;
905     ImplInit();
906 }
907 
908 Menu::~Menu()
909 {
910     DBG_DTOR( Menu, NULL );
911 
912     vcl::LazyDeletor<Menu>::Undelete( this );
913 
914     ImplCallEventListeners( VCLEVENT_OBJECT_DYING, ITEMPOS_INVALID );
915 
916 	// at the window free the reference to the accessible component
917     // and make sure the MenuFloatingWindow knows about our destruction
918 	if ( pWindow )
919     {
920         MenuFloatingWindow* pFloat = (MenuFloatingWindow*)pWindow;
921         if( pFloat->pMenu == this )
922             pFloat->pMenu = NULL;
923 		pWindow->SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >() );
924     }
925 
926 	// dispose accessible components
927     if ( mxAccessible.is() )
928     {
929         ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent> xComponent( mxAccessible, ::com::sun::star::uno::UNO_QUERY );
930         if ( xComponent.is() )
931             xComponent->dispose();
932     }
933 
934     if ( nEventId )
935         Application::RemoveUserEvent( nEventId );
936 
937     // Notify deletion of this menu
938     ImplMenuDelData* pDelData = mpFirstDel;
939     while ( pDelData )
940     {
941         pDelData->mpMenu = NULL;
942         pDelData = pDelData->mpNext;
943     }
944 
945     bKilled = sal_True;
946 
947     delete pItemList;
948     delete pLogo;
949     delete mpLayoutData;
950 
951     // Native-support: destroy SalMenu
952     ImplSetSalMenu( NULL );
953 }
954 
955 void Menu::doLazyDelete()
956 {
957     vcl::LazyDeletor<Menu>::Delete( this );
958 }
959 
960 void Menu::ImplInit()
961 {
962     mnHighlightedItemPos = ITEMPOS_INVALID;
963     mpSalMenu       = NULL;
964     nMenuFlags      = MENU_FLAG_SHOWCHECKIMAGES;
965     nDefaultItem    = 0;
966     //bIsMenuBar      = sal_False;  // this is now set in the ctor, must not be changed here!!!
967     nSelectedId     = 0;
968     pItemList       = new MenuItemList;
969     pLogo           = NULL;
970     pStartedFrom    = NULL;
971     pWindow         = NULL;
972     nEventId        = 0;
973     bCanceled       = sal_False;
974     bInCallback     = sal_False;
975     bKilled         = sal_False;
976     mpLayoutData	= NULL;
977 	mpFirstDel      = NULL;         // Dtor notification list
978     // Native-support: returns NULL if not supported
979     mpSalMenu = ImplGetSVData()->mpDefInst->CreateMenu( bIsMenuBar, this );
980 }
981 
982 Menu* Menu::ImplGetStartedFrom() const
983 {
984     return pStartedFrom;
985 }
986 
987 void Menu::ImplLoadRes( const ResId& rResId )
988 {
989     ResMgr* pMgr = rResId.GetResMgr();
990     if( ! pMgr )
991         return;
992 
993     rResId.SetRT( RSC_MENU );
994     GetRes( rResId );
995 
996     sal_uLong nObjMask = ReadLongRes();
997 
998     if( nObjMask & RSC_MENU_ITEMS )
999     {
1000         sal_uLong nObjFollows = ReadLongRes();
1001         // MenuItems einfuegen
1002         for( sal_uLong i = 0; i < nObjFollows; i++ )
1003         {
1004             InsertItem( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
1005             IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
1006         }
1007     }
1008 
1009     if( nObjMask & RSC_MENU_TEXT )
1010     {
1011         if( bIsMenuBar ) // Kein Titel im Menubar
1012             ReadStringRes();
1013         else
1014             aTitleText = ReadStringRes();
1015     }
1016     if( nObjMask & RSC_MENU_DEFAULTITEMID )
1017         SetDefaultItem( sal::static_int_cast<sal_uInt16>(ReadLongRes()) );
1018 }
1019 
1020 void Menu::CreateAutoMnemonics()
1021 {
1022     MnemonicGenerator aMnemonicGenerator;
1023     sal_uLong n;
1024     for ( n = 0; n < pItemList->Count(); n++ )
1025     {
1026         MenuItemData* pData = pItemList->GetDataFromPos(n);
1027         if ( ! (pData->nBits & MIB_NOSELECT ) )
1028             aMnemonicGenerator.RegisterMnemonic( pData->aText );
1029     }
1030     for ( n = 0; n < pItemList->Count(); n++ )
1031     {
1032         MenuItemData* pData = pItemList->GetDataFromPos(n);
1033         if ( ! (pData->nBits & MIB_NOSELECT ) )
1034             aMnemonicGenerator.CreateMnemonic( pData->aText );
1035     }
1036 }
1037 
1038 void Menu::Activate()
1039 {
1040     bInCallback = sal_True;
1041 
1042 	ImplMenuDelData aDelData( this );
1043 
1044     ImplCallEventListeners( VCLEVENT_MENU_ACTIVATE, ITEMPOS_INVALID );
1045 
1046 	if( !aDelData.isDeleted() )
1047 	{
1048 		if ( !aActivateHdl.Call( this ) )
1049 		{
1050 			if( !aDelData.isDeleted() )
1051 			{
1052 				Menu* pStartMenu = ImplGetStartMenu();
1053 				if ( pStartMenu && ( pStartMenu != this ) )
1054 				{
1055 					pStartMenu->bInCallback = sal_True;
1056 					// MT 11/01: Call EventListener here? I don't know...
1057 					pStartMenu->aActivateHdl.Call( this );
1058 					pStartMenu->bInCallback = sal_False;
1059 				}
1060 			}
1061 		}
1062 		bInCallback = sal_False;
1063 	}
1064 }
1065 
1066 void Menu::Deactivate()
1067 {
1068     for ( sal_uInt16 n = (sal_uInt16)pItemList->Count(); n; )
1069     {
1070         MenuItemData* pData = pItemList->GetDataFromPos( --n );
1071         if ( pData->bIsTemporary )
1072             pItemList->Remove( n );
1073     }
1074 
1075     bInCallback = sal_True;
1076 
1077 	ImplMenuDelData aDelData( this );
1078 
1079     Menu* pStartMenu = ImplGetStartMenu();
1080     ImplCallEventListeners( VCLEVENT_MENU_DEACTIVATE, ITEMPOS_INVALID );
1081 
1082 	if( !aDelData.isDeleted() )
1083 	{
1084 		if ( !aDeactivateHdl.Call( this ) )
1085 		{
1086 			if( !aDelData.isDeleted() )
1087 			{
1088 				if ( pStartMenu && ( pStartMenu != this ) )
1089 				{
1090 					pStartMenu->bInCallback = sal_True;
1091 					pStartMenu->aDeactivateHdl.Call( this );
1092 					pStartMenu->bInCallback = sal_False;
1093 				}
1094 			}
1095 		}
1096 	}
1097 
1098 	if( !aDelData.isDeleted() )
1099 	{
1100 		bInCallback = sal_False;
1101 
1102 		if ( this == pStartMenu )
1103 			GetpApp()->HideHelpStatusText();
1104 	}
1105 }
1106 
1107 void Menu::Highlight()
1108 {
1109 	ImplMenuDelData aDelData( this );
1110 
1111     Menu* pStartMenu = ImplGetStartMenu();
1112     if ( !aHighlightHdl.Call( this ) && !aDelData.isDeleted() )
1113     {
1114         if ( pStartMenu && ( pStartMenu != this ) )
1115             pStartMenu->aHighlightHdl.Call( this );
1116     }
1117 
1118     if ( !aDelData.isDeleted() && GetCurItemId() )
1119         GetpApp()->ShowHelpStatusText( GetHelpText( GetCurItemId() ) );
1120 }
1121 
1122 void Menu::ImplSelect()
1123 {
1124     MenuItemData* pData = GetItemList()->GetData( nSelectedId );
1125     if ( pData && (pData->nBits & MIB_AUTOCHECK) )
1126     {
1127         sal_Bool bChecked = IsItemChecked( nSelectedId );
1128         if ( pData->nBits & MIB_RADIOCHECK )
1129         {
1130             if ( !bChecked )
1131                 CheckItem( nSelectedId, sal_True );
1132         }
1133         else
1134             CheckItem( nSelectedId, !bChecked );
1135     }
1136 
1137     // Select rufen
1138     ImplSVData* pSVData = ImplGetSVData();
1139     pSVData->maAppData.mpActivePopupMenu = NULL;        // Falls neues Execute im Select()
1140     Application::PostUserEvent( nEventId, LINK( this, Menu, ImplCallSelect ) );
1141 }
1142 
1143 void Menu::Select()
1144 {
1145 	ImplMenuDelData aDelData( this );
1146 
1147     ImplCallEventListeners( VCLEVENT_MENU_SELECT, GetItemPos( GetCurItemId() ) );
1148     if ( !aDelData.isDeleted() && !aSelectHdl.Call( this ) )
1149     {
1150 		if( !aDelData.isDeleted() )
1151 		{
1152 			Menu* pStartMenu = ImplGetStartMenu();
1153 			if ( pStartMenu && ( pStartMenu != this ) )
1154 			{
1155 				pStartMenu->nSelectedId = nSelectedId;
1156 				pStartMenu->aSelectHdl.Call( this );
1157 			}
1158 		}
1159     }
1160 }
1161 
1162 void Menu::ImplSelectWithStart( Menu* pSMenu )
1163 {
1164     Menu* pOldStartedFrom = pStartedFrom;
1165     pStartedFrom = pSMenu;
1166     Menu* pOldStartedStarted = pOldStartedFrom ? pOldStartedFrom->pStartedFrom : NULL;
1167     Select();
1168     if( pOldStartedFrom )
1169         pOldStartedFrom->pStartedFrom = pOldStartedStarted;
1170     pStartedFrom = pOldStartedFrom;
1171 }
1172 
1173 void Menu::RequestHelp( const HelpEvent& )
1174 {
1175 }
1176 
1177 void Menu::ImplCallEventListeners( sal_uLong nEvent, sal_uInt16 nPos )
1178 {
1179 	ImplMenuDelData aDelData( this );
1180 
1181     VclMenuEvent aEvent( this, nEvent, nPos );
1182 
1183     // This is needed by atk accessibility bridge
1184     if ( nEvent == VCLEVENT_MENU_HIGHLIGHT )
1185     {
1186         ImplGetSVData()->mpApp->ImplCallEventListeners( &aEvent );
1187     }
1188 
1189     if ( !aDelData.isDeleted() && !maEventListeners.empty() )
1190         maEventListeners.Call( &aEvent );
1191 
1192 	if( !aDelData.isDeleted() )
1193 	{
1194 		Menu* pMenu = this;
1195 		while ( pMenu )
1196 		{
1197 			if ( !maChildEventListeners.empty() )
1198 				maChildEventListeners.Call( &aEvent );
1199 
1200 			if( aDelData.isDeleted() )
1201 				break;
1202 
1203 			pMenu = ( pMenu->pStartedFrom != pMenu ) ? pMenu->pStartedFrom : NULL;
1204 		}
1205 	}
1206 }
1207 
1208 void Menu::AddEventListener( const Link& rEventListener )
1209 {
1210     maEventListeners.push_back( rEventListener );
1211 }
1212 
1213 void Menu::RemoveEventListener( const Link& rEventListener )
1214 {
1215     maEventListeners.remove( rEventListener );
1216 }
1217 
1218 // -----------------------------------------------------------------------
1219 
1220 //void Menu::AddChildEventListener( const Link& rEventListener )
1221 //{
1222 //    mpDummy4_WindowChildEventListeners->push_back( rEventListener );
1223 //}
1224 
1225 // -----------------------------------------------------------------------
1226 
1227 //void Menu::RemoveChildEventListener( const Link& rEventListener )
1228 //{
1229 //    mpDummy4_WindowChildEventListeners->remove( rEventListener );
1230 //}
1231 
1232 void Menu::InsertItem( sal_uInt16 nItemId, const XubString& rStr, MenuItemBits nItemBits, sal_uInt16 nPos )
1233 {
1234     DBG_ASSERT( nItemId, "Menu::InsertItem(): ItemId == 0" );
1235     DBG_ASSERT( GetItemPos( nItemId ) == MENU_ITEM_NOTFOUND,
1236                 "Menu::InsertItem(): ItemId already exists" );
1237 
1238     // if Position > ItemCount, append
1239     if ( nPos >= (sal_uInt16)pItemList->Count() )
1240         nPos = MENU_APPEND;
1241 
1242     // put Item in MenuItemList
1243     MenuItemData* pData = pItemList->Insert( nItemId, MENUITEM_STRING,
1244                              nItemBits, rStr, Image(), this, nPos );
1245 
1246     // update native menu
1247     if( ImplGetSalMenu() && pData->pSalMenuItem )
1248         ImplGetSalMenu()->InsertItem( pData->pSalMenuItem, nPos );
1249 
1250     Window* pWin = ImplGetWindow();
1251     delete mpLayoutData, mpLayoutData = NULL;
1252     if ( pWin )
1253     {
1254         ImplCalcSize( pWin );
1255         if ( pWin->IsVisible() )
1256             pWin->Invalidate();
1257     }
1258     ImplCallEventListeners( VCLEVENT_MENU_INSERTITEM, nPos );
1259 }
1260 
1261 void Menu::InsertItem( sal_uInt16 nItemId, const Image& rImage,
1262                        MenuItemBits nItemBits, sal_uInt16 nPos )
1263 {
1264     InsertItem( nItemId, ImplGetSVEmptyStr(), nItemBits, nPos );
1265     SetItemImage( nItemId, rImage );
1266 }
1267 
1268 void Menu::InsertItem( sal_uInt16 nItemId,
1269                        const XubString& rStr, const Image& rImage,
1270                        MenuItemBits nItemBits, sal_uInt16 nPos )
1271 {
1272     InsertItem( nItemId, rStr, nItemBits, nPos );
1273     SetItemImage( nItemId, rImage );
1274 }
1275 
1276 void Menu::InsertItem( const ResId& rResId, sal_uInt16 nPos )
1277 {
1278     ResMgr* pMgr = rResId.GetResMgr();
1279     if( ! pMgr )
1280         return;
1281 
1282     sal_uLong              nObjMask;
1283 
1284     GetRes( rResId.SetRT( RSC_MENUITEM ) );
1285     nObjMask    = ReadLongRes();
1286 
1287     sal_Bool bSep = sal_False;
1288     if ( nObjMask & RSC_MENUITEM_SEPARATOR )
1289         bSep = (sal_Bool)ReadShortRes();
1290 
1291     sal_uInt16 nItemId = 1;
1292     if ( nObjMask & RSC_MENUITEM_ID )
1293         nItemId = sal::static_int_cast<sal_uInt16>(ReadLongRes());
1294 
1295     MenuItemBits nStatus = 0;
1296     if ( nObjMask & RSC_MENUITEM_STATUS )
1297         nStatus = sal::static_int_cast<MenuItemBits>(ReadLongRes());
1298 
1299     String aText;
1300     if ( nObjMask & RSC_MENUITEM_TEXT )
1301         aText = ReadStringRes();
1302 
1303     // Item erzeugen
1304     if ( nObjMask & RSC_MENUITEM_BITMAP )
1305     {
1306         if ( !bSep )
1307         {
1308             Bitmap aBmp( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
1309             if ( aText.Len() )
1310                 InsertItem( nItemId, aText, aBmp, nStatus, nPos );
1311             else
1312                 InsertItem( nItemId, aBmp, nStatus, nPos );
1313         }
1314         IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
1315     }
1316     else if ( !bSep )
1317         InsertItem( nItemId, aText, nStatus, nPos );
1318     if ( bSep )
1319         InsertSeparator( nPos );
1320 
1321     String aHelpText;
1322     if ( nObjMask & RSC_MENUITEM_HELPTEXT )
1323     {
1324         aHelpText = ReadStringRes();
1325         if( !bSep )
1326             SetHelpText( nItemId, aHelpText );
1327     }
1328 
1329     if ( nObjMask & RSC_MENUITEM_HELPID )
1330     {
1331         rtl::OString aHelpId( ReadByteStringRes() );
1332         if ( !bSep )
1333             SetHelpId( nItemId, aHelpId );
1334     }
1335 
1336     if( !bSep )
1337         SetHelpText( nItemId, aHelpText );
1338 
1339     if ( nObjMask & RSC_MENUITEM_KEYCODE )
1340     {
1341         if ( !bSep )
1342             SetAccelKey( nItemId, KeyCode( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) ) );
1343         IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
1344     }
1345     if( nObjMask & RSC_MENUITEM_CHECKED )
1346     {
1347         if ( !bSep )
1348             CheckItem( nItemId, (sal_Bool)ReadShortRes() );
1349     }
1350     if ( nObjMask & RSC_MENUITEM_DISABLE )
1351     {
1352         if ( !bSep )
1353             EnableItem( nItemId, !(sal_Bool)ReadShortRes() );
1354     }
1355     if ( nObjMask & RSC_MENUITEM_COMMAND )
1356     {
1357         String aCommandStr = ReadStringRes();
1358         if ( !bSep )
1359             SetItemCommand( nItemId, aCommandStr );
1360     }
1361     if ( nObjMask & RSC_MENUITEM_MENU )
1362     {
1363         if ( !bSep )
1364         {
1365             MenuItemData* pData = GetItemList()->GetData( nItemId );
1366             if ( pData )
1367             {
1368                 PopupMenu* pSubMenu = new PopupMenu( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
1369                 pData->pAutoSubMenu = pSubMenu;
1370                 // #111060# keep track of this pointer, may be it will be deleted from outside
1371                 pSubMenu->pRefAutoSubMenu = &pData->pAutoSubMenu;
1372                 SetPopupMenu( nItemId, pSubMenu );
1373             }
1374         }
1375         IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
1376     }
1377     delete mpLayoutData, mpLayoutData = NULL;
1378 }
1379 
1380 void Menu::InsertSeparator( sal_uInt16 nPos )
1381 {
1382     // do nothing if its a menu bar
1383     if ( bIsMenuBar )
1384         return;
1385 
1386     // if position > ItemCount, append
1387     if ( nPos >= (sal_uInt16)pItemList->Count() )
1388         nPos = MENU_APPEND;
1389 
1390     // put separator in item list
1391     pItemList->InsertSeparator( nPos );
1392 
1393     // update native menu
1394     sal_uInt16 itemPos = nPos != MENU_APPEND ? nPos : (sal_uInt16)pItemList->Count() - 1;
1395     MenuItemData *pData = pItemList->GetDataFromPos( itemPos );
1396     if( ImplGetSalMenu() && pData && pData->pSalMenuItem )
1397         ImplGetSalMenu()->InsertItem( pData->pSalMenuItem, nPos );
1398 
1399     delete mpLayoutData, mpLayoutData = NULL;
1400 
1401     ImplCallEventListeners( VCLEVENT_MENU_INSERTITEM, nPos );
1402 }
1403 
1404 void Menu::RemoveItem( sal_uInt16 nPos )
1405 {
1406 	sal_Bool bRemove = sal_False;
1407 
1408     if ( nPos < GetItemCount() )
1409 	{
1410         // update native menu
1411         if( ImplGetSalMenu() )
1412             ImplGetSalMenu()->RemoveItem( nPos );
1413 
1414         pItemList->Remove( nPos );
1415 		bRemove = sal_True;
1416 	}
1417 
1418     Window* pWin = ImplGetWindow();
1419     if ( pWin )
1420     {
1421         ImplCalcSize( pWin );
1422         if ( pWin->IsVisible() )
1423             pWin->Invalidate();
1424     }
1425     delete mpLayoutData, mpLayoutData = NULL;
1426 
1427 	if ( bRemove )
1428 		ImplCallEventListeners( VCLEVENT_MENU_REMOVEITEM, nPos );
1429 }
1430 
1431 void ImplCopyItem( Menu* pThis, const Menu& rMenu, sal_uInt16 nPos, sal_uInt16 nNewPos,
1432                   sal_uInt16 nMode = 0 )
1433 {
1434     MenuItemType eType = rMenu.GetItemType( nPos );
1435 
1436     if ( eType == MENUITEM_DONTKNOW )
1437         return;
1438 
1439     if ( eType == MENUITEM_SEPARATOR )
1440         pThis->InsertSeparator( nNewPos );
1441     else
1442     {
1443         sal_uInt16 nId = rMenu.GetItemId( nPos );
1444 
1445         DBG_ASSERT( pThis->GetItemPos( nId ) == MENU_ITEM_NOTFOUND,
1446                     "Menu::CopyItem(): ItemId already exists" );
1447 
1448         MenuItemData* pData = rMenu.GetItemList()->GetData( nId );
1449 
1450         if ( eType == MENUITEM_STRINGIMAGE )
1451             pThis->InsertItem( nId, pData->aText, pData->aImage, pData->nBits, nNewPos );
1452         else if ( eType == MENUITEM_STRING )
1453             pThis->InsertItem( nId, pData->aText, pData->nBits, nNewPos );
1454         else
1455             pThis->InsertItem( nId, pData->aImage, pData->nBits, nNewPos );
1456 
1457         if ( rMenu.IsItemChecked( nId ) )
1458             pThis->CheckItem( nId, sal_True );
1459         if ( !rMenu.IsItemEnabled( nId ) )
1460             pThis->EnableItem( nId, sal_False );
1461         pThis->SetHelpId( nId, pData->aHelpId );
1462         pThis->SetHelpText( nId, pData->aHelpText );
1463         pThis->SetAccelKey( nId, pData->aAccelKey );
1464         pThis->SetItemCommand( nId, pData->aCommandStr );
1465         pThis->SetHelpCommand( nId, pData->aHelpCommandStr );
1466 
1467         PopupMenu* pSubMenu = rMenu.GetPopupMenu( nId );
1468         if ( pSubMenu )
1469         {
1470             // AutoKopie anlegen
1471             if ( nMode == 1 )
1472             {
1473                 PopupMenu* pNewMenu = new PopupMenu( *pSubMenu );
1474                 pThis->SetPopupMenu( nId, pNewMenu );
1475 //                SetAutoMenu( pThis, nId, pNewMenu );
1476             }
1477             else
1478                 pThis->SetPopupMenu( nId, pSubMenu );
1479         }
1480     }
1481 }
1482 
1483 void Menu::CopyItem( const Menu& rMenu, sal_uInt16 nPos, sal_uInt16 nNewPos )
1484 {
1485     ImplCopyItem( this, rMenu, nPos, nNewPos );
1486 }
1487 
1488 void Menu::Clear()
1489 {
1490     for ( sal_uInt16 i = GetItemCount(); i; i-- )
1491         RemoveItem( 0 );
1492 }
1493 
1494 sal_uInt16 Menu::GetItemCount() const
1495 {
1496     return (sal_uInt16)pItemList->Count();
1497 }
1498 
1499 sal_uInt16 Menu::ImplGetVisibleItemCount() const
1500 {
1501     sal_uInt16 nItems = 0;
1502     for ( sal_uInt16 n = (sal_uInt16)pItemList->Count(); n; )
1503     {
1504         if ( ImplIsVisible( --n ) )
1505             nItems++;
1506     }
1507     return nItems;
1508 }
1509 
1510 sal_uInt16 Menu::ImplGetFirstVisible() const
1511 {
1512     for ( sal_uInt16 n = 0; n < pItemList->Count(); n++ )
1513     {
1514         if ( ImplIsVisible( n ) )
1515             return n;
1516     }
1517     return ITEMPOS_INVALID;
1518 }
1519 
1520 sal_uInt16 Menu::ImplGetPrevVisible( sal_uInt16 nPos ) const
1521 {
1522     for ( sal_uInt16 n = nPos; n; )
1523     {
1524         if ( n && ImplIsVisible( --n ) )
1525             return n;
1526     }
1527     return ITEMPOS_INVALID;
1528 }
1529 
1530 sal_uInt16 Menu::ImplGetNextVisible( sal_uInt16 nPos ) const
1531 {
1532     for ( sal_uInt16 n = nPos+1; n < pItemList->Count(); n++ )
1533     {
1534         if ( ImplIsVisible( n ) )
1535             return n;
1536     }
1537     return ITEMPOS_INVALID;
1538 }
1539 
1540 sal_uInt16 Menu::GetItemId( sal_uInt16 nPos ) const
1541 {
1542     MenuItemData* pData = pItemList->GetDataFromPos( nPos );
1543 
1544     if ( pData )
1545         return pData->nId;
1546     else
1547         return 0;
1548 }
1549 
1550 sal_uInt16 Menu::GetItemPos( sal_uInt16 nItemId ) const
1551 {
1552     sal_uInt16          nPos;
1553     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
1554 
1555     if ( pData )
1556         return nPos;
1557     else
1558         return MENU_ITEM_NOTFOUND;
1559 }
1560 
1561 MenuItemType Menu::GetItemType( sal_uInt16 nPos ) const
1562 {
1563     MenuItemData* pData = pItemList->GetDataFromPos( nPos );
1564 
1565     if ( pData )
1566         return pData->eType;
1567     else
1568         return MENUITEM_DONTKNOW;
1569 }
1570 
1571 sal_uInt16 Menu::GetCurItemId() const
1572 {
1573     return nSelectedId;
1574 }
1575 
1576 void Menu::SetItemBits( sal_uInt16 nItemId, MenuItemBits nBits )
1577 {
1578     MenuItemData* pData = pItemList->GetData( nItemId );
1579     if ( pData )
1580         pData->nBits = nBits;
1581 }
1582 
1583 MenuItemBits Menu::GetItemBits( sal_uInt16 nItemId ) const
1584 {
1585     MenuItemBits nBits = 0;
1586     MenuItemData* pData = pItemList->GetData( nItemId );
1587     if ( pData )
1588         nBits = pData->nBits;
1589     return nBits;
1590 }
1591 
1592 void Menu::SetUserValue( sal_uInt16 nItemId, sal_uLong nValue )
1593 {
1594     MenuItemData* pData = pItemList->GetData( nItemId );
1595     if ( pData )
1596         pData->nUserValue = nValue;
1597 }
1598 
1599 sal_uLong Menu::GetUserValue( sal_uInt16 nItemId ) const
1600 {
1601     MenuItemData* pData = pItemList->GetData( nItemId );
1602     return pData ? pData->nUserValue : 0;
1603 }
1604 
1605 void Menu::SetPopupMenu( sal_uInt16 nItemId, PopupMenu* pMenu )
1606 {
1607     sal_uInt16          nPos;
1608     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
1609 
1610     // Item does not exist -> return NULL
1611     if ( !pData )
1612         return;
1613 
1614     // same menu, nothing to do
1615     if ( (PopupMenu*)pData->pSubMenu == pMenu )
1616         return;
1617 
1618     // data exchange
1619     pData->pSubMenu = pMenu;
1620 
1621     // #112023# Make sure pStartedFrom does not point to invalid (old) data
1622     if ( pData->pSubMenu )
1623         pData->pSubMenu->pStartedFrom = 0;
1624 
1625     // set native submenu
1626     if( ImplGetSalMenu() && pData->pSalMenuItem )
1627     {
1628         if( pMenu )
1629             ImplGetSalMenu()->SetSubMenu( pData->pSalMenuItem, pMenu->ImplGetSalMenu(), nPos );
1630         else
1631             ImplGetSalMenu()->SetSubMenu( pData->pSalMenuItem, NULL, nPos );
1632     }
1633 
1634     ImplCallEventListeners( VCLEVENT_MENU_SUBMENUCHANGED, nPos );
1635 }
1636 
1637 PopupMenu* Menu::GetPopupMenu( sal_uInt16 nItemId ) const
1638 {
1639     MenuItemData* pData = pItemList->GetData( nItemId );
1640 
1641     if ( pData )
1642         return (PopupMenu*)(pData->pSubMenu);
1643     else
1644         return NULL;
1645 }
1646 
1647 void Menu::SetAccelKey( sal_uInt16 nItemId, const KeyCode& rKeyCode )
1648 {
1649     sal_uInt16          nPos;
1650     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
1651 
1652     if ( !pData )
1653         return;
1654 
1655     if ( pData->aAccelKey == rKeyCode )
1656         return;
1657 
1658     pData->aAccelKey = rKeyCode;
1659 
1660     // update native menu
1661     if( ImplGetSalMenu() && pData->pSalMenuItem )
1662         ImplGetSalMenu()->SetAccelerator( nPos, pData->pSalMenuItem, rKeyCode, rKeyCode.GetName() );
1663 }
1664 
1665 KeyCode Menu::GetAccelKey( sal_uInt16 nItemId ) const
1666 {
1667     MenuItemData* pData = pItemList->GetData( nItemId );
1668 
1669     if ( pData )
1670         return pData->aAccelKey;
1671     else
1672         return KeyCode();
1673 }
1674 
1675 KeyEvent Menu::GetActivationKey( sal_uInt16 nItemId ) const
1676 {
1677     KeyEvent aRet;
1678     MenuItemData* pData = pItemList->GetData( nItemId );
1679     if( pData )
1680     {
1681         sal_uInt16 nPos = pData->aText.Search( '~' );
1682         if( nPos != STRING_NOTFOUND && nPos < pData->aText.Len()-1 )
1683         {
1684             sal_uInt16 nCode = 0;
1685             sal_Unicode cAccel = pData->aText.GetChar( nPos+1 );
1686             if( cAccel >= 'a' && cAccel <= 'z' )
1687                 nCode = KEY_A + (cAccel-'a');
1688             else if( cAccel >= 'A' && cAccel <= 'Z' )
1689                 nCode = KEY_A + (cAccel-'A');
1690             else if( cAccel >= '0' && cAccel <= '9' )
1691                 nCode = KEY_0 + (cAccel-'0');
1692             if(nCode )
1693                 aRet = KeyEvent( cAccel, KeyCode( nCode, KEY_MOD2 ) );
1694         }
1695 
1696     }
1697     return aRet;
1698 }
1699 
1700 void Menu::CheckItem( sal_uInt16 nItemId, sal_Bool bCheck )
1701 {
1702     sal_uInt16 nPos;
1703     MenuItemData* pData = pItemList->GetData( nItemId, nPos );
1704 
1705     if ( !pData || pData->bChecked == bCheck )
1706         return;
1707 
1708     // Wenn RadioCheck, dann vorherigen unchecken
1709     if ( bCheck && (pData->nBits & MIB_AUTOCHECK) &&
1710          (pData->nBits & MIB_RADIOCHECK) )
1711     {
1712         MenuItemData*   pGroupData;
1713         sal_uInt16          nGroupPos;
1714         sal_uInt16          nItemCount = GetItemCount();
1715         sal_Bool            bFound = sal_False;
1716 
1717         nGroupPos = nPos;
1718         while ( nGroupPos )
1719         {
1720             pGroupData = pItemList->GetDataFromPos( nGroupPos-1 );
1721             if ( pGroupData->nBits & MIB_RADIOCHECK )
1722             {
1723                 if ( IsItemChecked( pGroupData->nId ) )
1724                 {
1725                     CheckItem( pGroupData->nId, sal_False );
1726                     bFound = sal_True;
1727                     break;
1728                 }
1729             }
1730             else
1731                 break;
1732             nGroupPos--;
1733         }
1734 
1735         if ( !bFound )
1736         {
1737             nGroupPos = nPos+1;
1738             while ( nGroupPos < nItemCount )
1739             {
1740                 pGroupData = pItemList->GetDataFromPos( nGroupPos );
1741                 if ( pGroupData->nBits & MIB_RADIOCHECK )
1742                 {
1743                     if ( IsItemChecked( pGroupData->nId ) )
1744                     {
1745                         CheckItem( pGroupData->nId, sal_False );
1746                         break;
1747                     }
1748                 }
1749                 else
1750                     break;
1751                 nGroupPos++;
1752             }
1753         }
1754     }
1755 
1756     pData->bChecked = bCheck;
1757 
1758     // update native menu
1759     if( ImplGetSalMenu() )
1760         ImplGetSalMenu()->CheckItem( nPos, bCheck );
1761 
1762 	ImplCallEventListeners( bCheck ? VCLEVENT_MENU_ITEMCHECKED : VCLEVENT_MENU_ITEMUNCHECKED, nPos );
1763 }
1764 
1765 sal_Bool Menu::IsItemChecked( sal_uInt16 nItemId ) const
1766 {
1767     sal_uInt16          nPos;
1768     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
1769 
1770     if ( !pData )
1771         return sal_False;
1772 
1773     return pData->bChecked;
1774 }
1775 
1776 void Menu::EnableItem( sal_uInt16 nItemId, sal_Bool bEnable )
1777 {
1778     sal_uInt16          nPos;
1779     MenuItemData*   pItemData = pItemList->GetData( nItemId, nPos );
1780 
1781     if ( pItemData && ( pItemData->bEnabled != bEnable ) )
1782     {
1783         pItemData->bEnabled = bEnable;
1784 
1785         Window* pWin = ImplGetWindow();
1786         if ( pWin && pWin->IsVisible() )
1787         {
1788             DBG_ASSERT( bIsMenuBar, "Menu::EnableItem - Popup visible!" );
1789             long nX = 0;
1790             sal_uLong nCount = pItemList->Count();
1791             for ( sal_uLong n = 0; n < nCount; n++ )
1792             {
1793                 MenuItemData* pData = pItemList->GetDataFromPos( n );
1794                 if ( n == nPos )
1795                 {
1796                     pWin->Invalidate( Rectangle( Point( nX, 0 ), Size( pData->aSz.Width(), pData->aSz.Height() ) ) );
1797                     break;
1798                 }
1799                 nX += pData->aSz.Width();
1800             }
1801         }
1802         // update native menu
1803         if( ImplGetSalMenu() )
1804             ImplGetSalMenu()->EnableItem( nPos, bEnable );
1805 
1806         ImplCallEventListeners( bEnable ? VCLEVENT_MENU_ENABLE : VCLEVENT_MENU_DISABLE, nPos );
1807     }
1808 }
1809 
1810 sal_Bool Menu::IsItemEnabled( sal_uInt16 nItemId ) const
1811 {
1812     sal_uInt16          nPos;
1813     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
1814 
1815     if ( !pData )
1816         return sal_False;
1817 
1818     return pData->bEnabled;
1819 }
1820 
1821 void Menu::ShowItem( sal_uInt16 nItemId, sal_Bool bVisible )
1822 {
1823     sal_uInt16          nPos;
1824     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
1825 
1826     DBG_ASSERT( !bIsMenuBar, "Menu::ShowItem - ignored for menu bar entries!" );
1827     if ( !bIsMenuBar && pData && ( pData->bVisible != bVisible ) )
1828     {
1829         Window* pWin = ImplGetWindow();
1830         if ( pWin && pWin->IsVisible() )
1831         {
1832             DBG_ASSERT( 0, "Menu::ShowItem - ignored for visible popups!" );
1833             return;
1834         }
1835         pData->bVisible = bVisible;
1836 
1837         // update native menu
1838         // as long as there is no support to hide native menu entries, we just disable them
1839         // TODO: add support to show/hide native menu entries
1840         if( ImplGetSalMenu() )
1841             ImplGetSalMenu()->EnableItem( nPos, bVisible );
1842     }
1843 }
1844 
1845 void Menu::SetItemText( sal_uInt16 nItemId, const XubString& rStr )
1846 {
1847     sal_uInt16          nPos;
1848     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
1849 
1850     if ( !pData )
1851         return;
1852 
1853 	if ( !rStr.Equals( pData->aText ) )
1854 	{
1855 		pData->aText = rStr;
1856 		ImplSetMenuItemData( pData );
1857         // update native menu
1858         if( ImplGetSalMenu() && pData->pSalMenuItem )
1859             ImplGetSalMenu()->SetItemText( nPos, pData->pSalMenuItem, rStr );
1860 
1861         Window* pWin = ImplGetWindow();
1862         delete mpLayoutData, mpLayoutData = NULL;
1863         if ( pWin && IsMenuBar() )
1864         {
1865             ImplCalcSize( pWin );
1866             if ( pWin->IsVisible() )
1867                 pWin->Invalidate();
1868         }
1869 
1870         ImplCallEventListeners( VCLEVENT_MENU_ITEMTEXTCHANGED, nPos );
1871 	}
1872 }
1873 
1874 XubString Menu::GetItemText( sal_uInt16 nItemId ) const
1875 {
1876     sal_uInt16          nPos;
1877     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
1878 
1879     if ( pData )
1880         return pData->aText;
1881     else
1882         return ImplGetSVEmptyStr();
1883 }
1884 
1885 void Menu::SetItemImage( sal_uInt16 nItemId, const Image& rImage )
1886 {
1887     sal_uInt16          nPos;
1888     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
1889 
1890     if ( !pData )
1891         return;
1892 
1893     pData->aImage = rImage;
1894     ImplSetMenuItemData( pData );
1895 
1896     // update native menu
1897     if( ImplGetSalMenu() && pData->pSalMenuItem )
1898         ImplGetSalMenu()->SetItemImage( nPos, pData->pSalMenuItem, rImage );
1899 }
1900 
1901 static inline Image ImplRotImage( const Image& rImage, long nAngle10 )
1902 {
1903     Image 		aRet;
1904 	BitmapEx	aBmpEx( rImage.GetBitmapEx() );
1905 
1906 	aBmpEx.Rotate( nAngle10, COL_WHITE );
1907 
1908     return Image( aBmpEx );
1909 }
1910 
1911 void Menu::SetItemImageAngle( sal_uInt16 nItemId, long nAngle10 )
1912 {
1913     sal_uInt16          nPos;
1914     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
1915 
1916 	if ( pData )
1917 	{
1918         long nDeltaAngle = (nAngle10 - pData->nItemImageAngle) % 3600;
1919         while( nDeltaAngle < 0 )
1920             nDeltaAngle += 3600;
1921 
1922         pData->nItemImageAngle = nAngle10;
1923         if( nDeltaAngle && !!pData->aImage )
1924             pData->aImage = ImplRotImage( pData->aImage, nDeltaAngle );
1925 	}
1926 }
1927 
1928 static inline Image ImplMirrorImage( const Image& rImage )
1929 {
1930     Image 		aRet;
1931 	BitmapEx	aBmpEx( rImage.GetBitmapEx() );
1932 
1933 	aBmpEx.Mirror( BMP_MIRROR_HORZ );
1934 
1935     return Image( aBmpEx );
1936 }
1937 
1938 void Menu::SetItemImageMirrorMode( sal_uInt16 nItemId, sal_Bool bMirror )
1939 {
1940     sal_uInt16          nPos;
1941     MenuItemData*   pData = pItemList->GetData( nItemId, nPos );
1942 
1943 	if ( pData )
1944 	{
1945         if( ( pData->bMirrorMode && ! bMirror ) ||
1946             ( ! pData->bMirrorMode && bMirror )
1947             )
1948         {
1949             pData->bMirrorMode = bMirror ? true : false;
1950             if( !!pData->aImage )
1951                 pData->aImage = ImplMirrorImage( pData->aImage );
1952         }
1953     }
1954 }
1955 
1956 Image Menu::GetItemImage( sal_uInt16 nItemId ) const
1957 {
1958     MenuItemData* pData = pItemList->GetData( nItemId );
1959 
1960     if ( pData )
1961         return pData->aImage;
1962     else
1963         return Image();
1964 }
1965 
1966 long Menu::GetItemImageAngle( sal_uInt16 nItemId ) const
1967 {
1968     MenuItemData* pData = pItemList->GetData( nItemId );
1969 
1970 	if ( pData )
1971 		return pData->nItemImageAngle;
1972 	else
1973 		return 0;
1974 }
1975 
1976 sal_Bool Menu::GetItemImageMirrorMode( sal_uInt16 nItemId ) const
1977 {
1978     MenuItemData* pData = pItemList->GetData( nItemId );
1979 
1980 	if ( pData )
1981 		return pData->bMirrorMode;
1982 	else
1983 		return sal_False;
1984 }
1985 
1986 void Menu::SetItemCommand( sal_uInt16 nItemId, const String& rCommand )
1987 {
1988     MenuItemData* pData = pItemList->GetData( nItemId );
1989 
1990     if ( pData )
1991         pData->aCommandStr = rCommand;
1992 }
1993 
1994 const XubString& Menu::GetItemCommand( sal_uInt16 nItemId ) const
1995 {
1996     MenuItemData* pData = pItemList->GetData( nItemId );
1997 
1998     if ( pData )
1999         return pData->aCommandStr;
2000     else
2001         return ImplGetSVEmptyStr();
2002 }
2003 
2004 void Menu::SetHelpCommand( sal_uInt16 nItemId, const XubString& rStr )
2005 {
2006     MenuItemData* pData = pItemList->GetData( nItemId );
2007 
2008     if ( pData )
2009         pData->aHelpCommandStr = rStr;
2010 }
2011 
2012 const XubString& Menu::GetHelpCommand( sal_uInt16 nItemId ) const
2013 {
2014     MenuItemData* pData = pItemList->GetData( nItemId );
2015 
2016     if ( pData )
2017         return pData->aHelpCommandStr;
2018     else
2019         return ImplGetSVEmptyStr();
2020 }
2021 
2022 void Menu::SetHelpText( sal_uInt16 nItemId, const XubString& rStr )
2023 {
2024     MenuItemData* pData = pItemList->GetData( nItemId );
2025 
2026     if ( pData )
2027         pData->aHelpText = rStr;
2028 }
2029 
2030 const XubString& Menu::ImplGetHelpText( sal_uInt16 nItemId ) const
2031 {
2032     MenuItemData* pData = pItemList->GetData( nItemId );
2033 
2034     if ( pData )
2035     {
2036         if ( !pData->aHelpText.Len() &&
2037              (( pData->aHelpId.getLength()  ) || ( pData->aCommandStr.Len() )))
2038         {
2039             Help* pHelp = Application::GetHelp();
2040             if ( pHelp )
2041             {
2042                 if ( pData->aCommandStr.Len() )
2043                     pData->aHelpText = pHelp->GetHelpText( pData->aCommandStr, NULL );
2044 
2045                 if( !pData->aHelpText.Len() && pData->aHelpId.getLength() )
2046                     pData->aHelpText = pHelp->GetHelpText( rtl::OStringToOUString( pData->aHelpId, RTL_TEXTENCODING_UTF8 ), NULL );
2047             }
2048         }
2049 
2050         return pData->aHelpText;
2051     }
2052     else
2053         return ImplGetSVEmptyStr();
2054 }
2055 
2056 const XubString& Menu::GetHelpText( sal_uInt16 nItemId ) const
2057 {
2058     return ImplGetHelpText( nItemId );
2059 }
2060 
2061 void Menu::SetTipHelpText( sal_uInt16 nItemId, const XubString& rStr )
2062 {
2063     MenuItemData* pData = pItemList->GetData( nItemId );
2064 
2065     if ( pData )
2066         pData->aTipHelpText = rStr;
2067 }
2068 
2069 const XubString& Menu::GetTipHelpText( sal_uInt16 nItemId ) const
2070 {
2071     MenuItemData* pData = pItemList->GetData( nItemId );
2072 
2073     if ( pData )
2074         return pData->aTipHelpText;
2075     else
2076         return ImplGetSVEmptyStr();
2077 }
2078 
2079 void Menu::SetHelpId( sal_uInt16 nItemId, const rtl::OString& rHelpId )
2080 {
2081     MenuItemData* pData = pItemList->GetData( nItemId );
2082 
2083     if ( pData )
2084         pData->aHelpId = rHelpId;
2085 }
2086 
2087 rtl::OString Menu::GetHelpId( sal_uInt16 nItemId ) const
2088 {
2089     rtl::OString aRet;
2090 
2091     MenuItemData* pData = pItemList->GetData( nItemId );
2092 
2093     if ( pData )
2094     {
2095         if ( pData->aHelpId.getLength() )
2096             aRet = pData->aHelpId;
2097         else
2098             aRet = ::rtl::OUStringToOString( pData->aCommandStr, RTL_TEXTENCODING_UTF8 );
2099     }
2100 
2101     return aRet;
2102 }
2103 
2104 Menu& Menu::operator=( const Menu& rMenu )
2105 {
2106     // Aufraeumen
2107     Clear();
2108 
2109     // Items kopieren
2110     sal_uInt16 nCount = rMenu.GetItemCount();
2111     for ( sal_uInt16 i = 0; i < nCount; i++ )
2112         ImplCopyItem( this, rMenu, i, MENU_APPEND, 1 );
2113 
2114     nDefaultItem = rMenu.nDefaultItem;
2115     aActivateHdl = rMenu.aActivateHdl;
2116     aDeactivateHdl = rMenu.aDeactivateHdl;
2117     aHighlightHdl = rMenu.aHighlightHdl;
2118     aSelectHdl = rMenu.aSelectHdl;
2119     aTitleText = rMenu.aTitleText;
2120     bIsMenuBar = rMenu.bIsMenuBar;
2121 
2122     return *this;
2123 }
2124 
2125 sal_Bool Menu::ImplIsVisible( sal_uInt16 nPos ) const
2126 {
2127     sal_Bool bVisible = sal_True;
2128 
2129     MenuItemData* pData = pItemList->GetDataFromPos( nPos );
2130     // check general visibility first
2131     if( pData && !pData->bVisible )
2132         bVisible = sal_False;
2133 
2134     if ( bVisible && pData && pData->eType == MENUITEM_SEPARATOR )
2135     {
2136         if( nPos == 0 ) // no separator should be shown at the very beginning
2137             bVisible = sal_False;
2138         else
2139         {
2140             // always avoid adjacent separators
2141             sal_uInt16 nCount = (sal_uInt16) pItemList->Count();
2142             sal_uInt16 n;
2143             MenuItemData* pNextData = NULL;
2144             // search next visible item
2145             for( n = nPos + 1; n < nCount; n++ )
2146             {
2147                 pNextData = pItemList->GetDataFromPos( n );
2148                 if( pNextData && pNextData->bVisible )
2149                 {
2150                     if( pNextData->eType == MENUITEM_SEPARATOR || ImplIsVisible(n) )
2151                         break;
2152                 }
2153             }
2154             if( n == nCount ) // no next visible item
2155                 bVisible = sal_False;
2156             // check for separator
2157             if( pNextData && pNextData->bVisible && pNextData->eType == MENUITEM_SEPARATOR )
2158                 bVisible = sal_False;
2159 
2160             if( bVisible )
2161             {
2162                 for( n = nPos; n > 0; n-- )
2163                 {
2164                     pNextData = pItemList->GetDataFromPos( n-1 );
2165                     if( pNextData && pNextData->bVisible )
2166                     {
2167                         if( pNextData->eType != MENUITEM_SEPARATOR && ImplIsVisible(n-1) )
2168                             break;
2169                     }
2170                 }
2171                 if( n == 0 ) // no previous visible item
2172                     bVisible = sal_False;
2173             }
2174         }
2175     }
2176 
2177     // Fuer den Menubar nicht erlaubt, weil ich nicht mitbekomme
2178     // ob dadurch ein Eintrag verschwindet oder wieder da ist.
2179     if ( bVisible && !bIsMenuBar && ( nMenuFlags & MENU_FLAG_HIDEDISABLEDENTRIES ) &&
2180         !( nMenuFlags & MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES ) )
2181     {
2182 		if( !pData ) // e.g. nPos == ITEMPOS_INVALID
2183 			bVisible = sal_False;
2184         else if ( pData->eType != MENUITEM_SEPARATOR ) // separators handled above
2185         {
2186             // bVisible = pData->bEnabled && ( !pData->pSubMenu || pData->pSubMenu->HasValidEntries( sal_True ) );
2187             bVisible = pData->bEnabled; // SubMenus nicht pruefen, weil sie ggf. erst im Activate() gefuellt werden.
2188         }
2189     }
2190 
2191     return bVisible;
2192 }
2193 
2194 sal_Bool Menu::IsItemVisible( sal_uInt16 nItemId ) const
2195 {
2196     return IsMenuVisible() && ImplIsVisible( GetItemPos( nItemId ) );
2197 }
2198 
2199 sal_Bool Menu::IsItemPosVisible( sal_uInt16 nItemPos ) const
2200 {
2201     return IsMenuVisible() && ImplIsVisible( nItemPos );
2202 }
2203 
2204 sal_Bool Menu::IsMenuVisible() const
2205 {
2206     return pWindow && pWindow->IsReallyVisible();
2207 }
2208 
2209 sal_Bool Menu::ImplIsSelectable( sal_uInt16 nPos ) const
2210 {
2211     sal_Bool bSelectable = sal_True;
2212 
2213     MenuItemData* pData = pItemList->GetDataFromPos( nPos );
2214     // check general visibility first
2215     if ( pData && ( pData->nBits & MIB_NOSELECT ) )
2216         bSelectable = sal_False;
2217 
2218     return bSelectable;
2219 }
2220 
2221 void Menu::SelectItem( sal_uInt16 nItemId )
2222 {
2223     if( bIsMenuBar )
2224         static_cast<MenuBar*>(this)->SelectEntry( nItemId );
2225     else
2226         static_cast<PopupMenu*>(this)->SelectEntry( nItemId );
2227 }
2228 
2229 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > Menu::GetAccessible()
2230 {
2231 	// Since PopupMenu are sometimes shared by different instances of MenuBar, the mxAccessible member gets
2232 	// overwritten and may contain a disposed object when the initial menubar gets set again. So use the
2233 	// mxAccessible member only for sub menus.
2234 	if ( pStartedFrom )
2235 	{
2236 		for ( sal_uInt16 i = 0, nCount = pStartedFrom->GetItemCount(); i < nCount; ++i )
2237 		{
2238 			sal_uInt16 nItemId = pStartedFrom->GetItemId( i );
2239 			if ( static_cast< Menu* >( pStartedFrom->GetPopupMenu( nItemId ) ) == this )
2240 			{
2241 				::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xParent = pStartedFrom->GetAccessible();
2242 				if ( xParent.is() )
2243 				{
2244 					::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
2245 					if ( xParentContext.is() )
2246 						return xParentContext->getAccessibleChild( i );
2247 				}
2248 			}
2249 		}
2250 	}
2251 	else if ( !mxAccessible.is() )
2252 	{
2253 		UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
2254 		if ( pWrapper )
2255 			mxAccessible = pWrapper->CreateAccessible( this, bIsMenuBar );
2256 	}
2257 
2258 	return mxAccessible;
2259 }
2260 
2261 void Menu::SetAccessible( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible )
2262 {
2263 	mxAccessible = rxAccessible;
2264 }
2265 
2266 long Menu::ImplGetNativeCheckAndRadioSize( Window* pWin, long& rCheckHeight, long& rRadioHeight, long &rMaxWidth ) const
2267 {
2268     rMaxWidth = rCheckHeight = rRadioHeight = 0;
2269 
2270     if( ! bIsMenuBar )
2271     {
2272         ImplControlValue aVal;
2273         Rectangle aNativeBounds;
2274         Rectangle aNativeContent;
2275         Point tmp( 0, 0 );
2276         Rectangle aCtrlRegion( Rectangle( tmp, Size( 100, 15 ) ) );
2277         if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_CHECK_MARK ) )
2278         {
2279             if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP),
2280                                               ControlPart(PART_MENU_ITEM_CHECK_MARK),
2281                                               aCtrlRegion,
2282                                               ControlState(CTRL_STATE_ENABLED),
2283                                               aVal,
2284                                               OUString(),
2285                                               aNativeBounds,
2286                                               aNativeContent )
2287             )
2288             {
2289                 rCheckHeight = aNativeBounds.GetHeight();
2290 				rMaxWidth = aNativeContent.GetWidth();
2291             }
2292         }
2293         if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_RADIO_MARK ) )
2294         {
2295             if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP),
2296                                               ControlPart(PART_MENU_ITEM_RADIO_MARK),
2297                                               aCtrlRegion,
2298                                               ControlState(CTRL_STATE_ENABLED),
2299                                               aVal,
2300                                               OUString(),
2301                                               aNativeBounds,
2302                                               aNativeContent )
2303             )
2304             {
2305                 rRadioHeight = aNativeBounds.GetHeight();
2306 				rMaxWidth = Max (rMaxWidth, aNativeContent.GetWidth());
2307             }
2308         }
2309     }
2310     return (rCheckHeight > rRadioHeight) ? rCheckHeight : rRadioHeight;
2311 }
2312 
2313 // -----------------------------------------------------------------------
2314 
2315 void Menu::ImplAddDel( ImplMenuDelData& rDel )
2316 {
2317     DBG_ASSERT( !rDel.mpMenu, "Menu::ImplAddDel(): cannot add ImplMenuDelData twice !" );
2318     if( !rDel.mpMenu )
2319     {
2320         rDel.mpMenu = this;
2321         rDel.mpNext = mpFirstDel;
2322         mpFirstDel = &rDel;
2323     }
2324 }
2325 
2326 // -----------------------------------------------------------------------
2327 
2328 void Menu::ImplRemoveDel( ImplMenuDelData& rDel )
2329 {
2330     rDel.mpMenu = NULL;
2331     if ( mpFirstDel == &rDel )
2332 	{
2333         mpFirstDel = rDel.mpNext;
2334 	}
2335     else
2336     {
2337         ImplMenuDelData* pData = mpFirstDel;
2338         while ( pData && (pData->mpNext != &rDel) )
2339             pData = pData->mpNext;
2340 
2341 		DBG_ASSERT( pData, "Menu::ImplRemoveDel(): ImplMenuDelData not registered !" );
2342 		if( pData )
2343 			pData->mpNext = rDel.mpNext;
2344     }
2345 }
2346 
2347 // -----------------------------------------------------------------------
2348 
2349 Size Menu::ImplCalcSize( Window* pWin )
2350 {
2351     // | Checked| Image| Text| Accel/Popup|
2352 
2353     // Fuer Symbole: nFontHeight x nFontHeight
2354     long nFontHeight = pWin->GetTextHeight();
2355     long nExtra = nFontHeight/4;
2356 
2357 
2358     Size aSz;
2359     Size aMaxImgSz;
2360     long nMaxWidth = 0;
2361     long nMinMenuItemHeight = nFontHeight;
2362     long nCheckHeight = 0, nRadioHeight = 0;
2363 	long nCheckWidth = 0, nMaxCheckWidth = 0;
2364     long nMax = ImplGetNativeCheckAndRadioSize( pWin, nCheckHeight, nRadioHeight, nMaxCheckWidth );
2365     if( nMax > nMinMenuItemHeight )
2366         nMinMenuItemHeight = nMax;
2367 
2368 	const StyleSettings& rSettings = pWin->GetSettings().GetStyleSettings();
2369 	if ( rSettings.GetUseImagesInMenus() )
2370 	{
2371 		nMinMenuItemHeight = 16;
2372 		for ( sal_uInt16 i = (sal_uInt16)pItemList->Count(); i; )
2373 		{
2374 			MenuItemData* pData = pItemList->GetDataFromPos( --i );
2375 			if ( ImplIsVisible( i ) && (( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE )))
2376 			{
2377 				Size aImgSz = pData->aImage.GetSizePixel();
2378 				if ( aImgSz.Height() > aMaxImgSz.Height() )
2379 					aMaxImgSz.Height() = aImgSz.Height();
2380 				if ( aImgSz.Height() > nMinMenuItemHeight )
2381 					nMinMenuItemHeight = aImgSz.Height();
2382 				break;
2383 			}
2384 		}
2385 	}
2386 
2387     for ( sal_uInt16 n = (sal_uInt16)pItemList->Count(); n; )
2388     {
2389         MenuItemData* pData = pItemList->GetDataFromPos( --n );
2390 
2391         pData->aSz.Height() = 0;
2392         pData->aSz.Width() = 0;
2393 
2394         if ( ImplIsVisible( n ) )
2395         {
2396             long nWidth = 0;
2397 
2398             // Separator
2399             if ( !bIsMenuBar && ( pData->eType == MENUITEM_SEPARATOR ) )
2400             {
2401                 DBG_ASSERT( !bIsMenuBar, "Separator in MenuBar ?! " );
2402                 pData->aSz.Height() = 4;
2403             }
2404 
2405             // Image:
2406             if ( !bIsMenuBar && ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
2407             {
2408                 Size aImgSz = pData->aImage.GetSizePixel();
2409                 aImgSz.Height() += 4; // add a border for native marks
2410                 aImgSz.Width() += 4; // add a border for native marks
2411                 if ( aImgSz.Width() > aMaxImgSz.Width() )
2412                     aMaxImgSz.Width() = aImgSz.Width();
2413                 if ( aImgSz.Height() > aMaxImgSz.Height() )
2414                     aMaxImgSz.Height() = aImgSz.Height();
2415                 if ( aImgSz.Height() > pData->aSz.Height() )
2416                     pData->aSz.Height() = aImgSz.Height();
2417             }
2418 
2419 			// Check Buttons:
2420 			if ( !bIsMenuBar && pData->HasCheck() )
2421 			{
2422 				nCheckWidth = nMaxCheckWidth;
2423 				if (nMenuFlags & MENU_FLAG_SHOWCHECKIMAGES)
2424                 {
2425                     // checks / images take the same place
2426                     if( ! ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
2427                         nWidth += nCheckWidth + nExtra * 2;
2428                 }
2429 			}
2430 
2431             // Text:
2432             if ( (pData->eType == MENUITEM_STRING) || (pData->eType == MENUITEM_STRINGIMAGE) )
2433             {
2434                 long nTextWidth = pWin->GetCtrlTextWidth( pData->aText );
2435                 long nTextHeight = pWin->GetTextHeight();
2436 
2437 //                if ( nTextHeight > pData->aSz.Height() )
2438 //                    pData->aSz.Height() = nTextHeight;
2439 
2440                 if ( bIsMenuBar )
2441                 {
2442 					if ( nTextHeight > pData->aSz.Height() )
2443 						pData->aSz.Height() = nTextHeight;
2444 
2445                     pData->aSz.Width() = nTextWidth + 4*nExtra;
2446                     aSz.Width() += pData->aSz.Width();
2447                 }
2448 				else
2449 					pData->aSz.Height() = Max( Max( nTextHeight, pData->aSz.Height() ), nMinMenuItemHeight );
2450 
2451                 nWidth += nTextWidth;
2452             }
2453 
2454             // Accel
2455             if ( !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() )
2456             {
2457                 String aName = pData->aAccelKey.GetName();
2458                 long nAccWidth = pWin->GetTextWidth( aName );
2459                 nAccWidth += nExtra;
2460                 nWidth += nAccWidth;
2461             }
2462 
2463             // SubMenu?
2464             if ( !bIsMenuBar && pData->pSubMenu )
2465             {
2466                     if ( nFontHeight > nWidth )
2467                         nWidth += nFontHeight;
2468 
2469 				pData->aSz.Height() = Max( Max( nFontHeight, pData->aSz.Height() ), nMinMenuItemHeight );
2470             }
2471 
2472             pData->aSz.Height() += EXTRAITEMHEIGHT; // Etwas mehr Abstand:
2473 
2474             if ( !bIsMenuBar )
2475                 aSz.Height() += (long)pData->aSz.Height();
2476 
2477             if ( nWidth > nMaxWidth )
2478                 nMaxWidth = nWidth;
2479 
2480         }
2481     }
2482 
2483     if ( !bIsMenuBar )
2484     {
2485         // popup menus should not be wider than half the screen
2486         // except on rather small screens
2487         // TODO: move GetScreenNumber from SystemWindow to Window ?
2488         // currently we rely on internal privileges
2489         unsigned int nScreenNumber = pWin->ImplGetWindowImpl()->mpFrame->maGeometry.nScreenNumber;
2490         Rectangle aDispRect( Application::GetScreenPosSizePixel( nScreenNumber ) );
2491         long nScreenWidth = aDispRect.GetWidth() >= 800 ? aDispRect.GetWidth() : 800;
2492         if( nMaxWidth > nScreenWidth/2 )
2493             nMaxWidth = nScreenWidth/2;
2494 
2495         sal_uInt16 gfxExtra = (sal_uInt16) Max( nExtra, 7L ); // #107710# increase space between checkmarks/images/text
2496         nCheckPos = (sal_uInt16)nExtra;
2497 		if (nMenuFlags & MENU_FLAG_SHOWCHECKIMAGES)
2498 		{
2499             long nImgOrChkWidth = 0;
2500             nImagePos = nCheckPos;
2501             if( nMax > 0 ) // NWF case
2502                 nImgOrChkWidth = nMax + nExtra;
2503             else // non NWF case
2504                 nImgOrChkWidth = nFontHeight/2 + gfxExtra;
2505             nImgOrChkWidth = Max( nImgOrChkWidth, aMaxImgSz.Width() + gfxExtra );
2506             nTextPos = (sal_uInt16)(nImagePos + nImgOrChkWidth);
2507 		}
2508 		else
2509 		{
2510 			nImagePos = nCheckPos;
2511 			nTextPos = (sal_uInt16)(nImagePos + Max( aMaxImgSz.Width(), nCheckWidth ));
2512 		}
2513 		nTextPos = nTextPos + gfxExtra;
2514 
2515         aSz.Width() = nTextPos + nMaxWidth + nExtra;
2516         aSz.Width() += 4*nExtra;   // a _little_ more ...
2517 
2518         int nOuterSpace = ImplGetSVData()->maNWFData.mnMenuFormatExtraBorder;
2519         aSz.Width() += 2*nOuterSpace;
2520         aSz.Height() += 2*nOuterSpace;
2521     }
2522     else
2523     {
2524         nTextPos = (sal_uInt16)(2*nExtra);
2525         aSz.Height() = nFontHeight+6;
2526 
2527         // get menubar height from native methods if supported
2528         if( pWindow->IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
2529         {
2530             ImplControlValue aVal;
2531             Rectangle aNativeBounds;
2532             Rectangle aNativeContent;
2533             Point tmp( 0, 0 );
2534             Rectangle aCtrlRegion( tmp, Size( 100, 15 ) );
2535             if( pWindow->GetNativeControlRegion( ControlType(CTRL_MENUBAR),
2536                                                  ControlPart(PART_ENTIRE_CONTROL),
2537                                                  aCtrlRegion,
2538                                                  ControlState(CTRL_STATE_ENABLED),
2539                                                  aVal,
2540                                                  OUString(),
2541                                                  aNativeBounds,
2542                                                  aNativeContent )
2543             )
2544             {
2545                 int nNativeHeight = aNativeBounds.GetHeight();
2546                 if( nNativeHeight > aSz.Height() )
2547                     aSz.Height() = nNativeHeight;
2548             }
2549         }
2550 
2551         // account for the size of the close button, which actually is a toolbox
2552         // due to NWF this is variable
2553         long nCloserHeight = ((MenuBarWindow*) pWindow)->MinCloseButtonSize().Height();
2554         if( aSz.Height() < nCloserHeight )
2555             aSz.Height() = nCloserHeight;
2556     }
2557 
2558     if ( pLogo )
2559         aSz.Width() += pLogo->aBitmap.GetSizePixel().Width();
2560 
2561     return aSz;
2562 }
2563 
2564 static void ImplPaintCheckBackground( Window* i_pWindow, const Rectangle& i_rRect, bool i_bHighlight )
2565 {
2566     sal_Bool bNativeOk = sal_False;
2567     if( i_pWindow->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
2568     {
2569         ImplControlValue    aControlValue;
2570         Rectangle           aCtrlRegion( i_rRect );
2571         ControlState        nState = CTRL_STATE_PRESSED | CTRL_STATE_ENABLED;
2572 
2573         aControlValue.setTristateVal( BUTTONVALUE_ON );
2574 
2575         bNativeOk = i_pWindow->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON,
2576                                                   aCtrlRegion, nState, aControlValue,
2577                                                   rtl::OUString() );
2578     }
2579 
2580     if( ! bNativeOk )
2581     {
2582         const StyleSettings& rSettings = i_pWindow->GetSettings().GetStyleSettings();
2583         Color aColor( i_bHighlight ? rSettings.GetMenuHighlightTextColor() : rSettings.GetHighlightColor() );
2584         i_pWindow->DrawSelectionBackground( i_rRect, 0, i_bHighlight, sal_True, sal_False, 2, NULL, &aColor );
2585     }
2586 }
2587 
2588 static String getShortenedString( const String& i_rLong, Window* i_pWin, long i_nMaxWidth )
2589 {
2590     xub_StrLen nPos = STRING_NOTFOUND;
2591     String aNonMnem( OutputDevice::GetNonMnemonicString( i_rLong, nPos ) );
2592     aNonMnem = i_pWin->GetEllipsisString( aNonMnem, i_nMaxWidth, TEXT_DRAW_CENTERELLIPSIS );
2593     // re-insert mnemonic
2594     if( nPos != STRING_NOTFOUND )
2595     {
2596         if( nPos < aNonMnem.Len() && i_rLong.GetChar(nPos+1) == aNonMnem.GetChar(nPos) )
2597         {
2598             rtl::OUStringBuffer aBuf( i_rLong.Len() );
2599             aBuf.append( aNonMnem.GetBuffer(), nPos );
2600             aBuf.append( sal_Unicode('~') );
2601             aBuf.append( aNonMnem.GetBuffer()+nPos );
2602             aNonMnem = aBuf.makeStringAndClear();
2603         }
2604     }
2605     return aNonMnem;
2606 }
2607 
2608 void Menu::ImplPaint( Window* pWin, sal_uInt16 nBorder, long nStartY, MenuItemData* pThisItemOnly, sal_Bool bHighlighted, bool bLayout ) const
2609 {
2610     // Fuer Symbole: nFontHeight x nFontHeight
2611     long nFontHeight = pWin->GetTextHeight();
2612     long nExtra = nFontHeight/4;
2613 
2614     long nCheckHeight = 0, nRadioHeight = 0, nMaxCheckWidth = 0;
2615     ImplGetNativeCheckAndRadioSize( pWin, nCheckHeight, nRadioHeight, nMaxCheckWidth );
2616 
2617     DecorationView aDecoView( pWin );
2618     const StyleSettings& rSettings = pWin->GetSettings().GetStyleSettings();
2619 
2620     Point aTopLeft, aTmpPos;
2621 
2622     if ( pLogo )
2623         aTopLeft.X() = pLogo->aBitmap.GetSizePixel().Width();
2624 
2625     int nOuterSpace = 0;
2626     if( !bIsMenuBar )
2627     {
2628         nOuterSpace = ImplGetSVData()->maNWFData.mnMenuFormatExtraBorder;
2629         aTopLeft.X() += nOuterSpace;
2630         aTopLeft.Y() += nOuterSpace;
2631     }
2632 
2633     Size aOutSz = pWin->GetOutputSizePixel();
2634     sal_uInt16 nCount = (sal_uInt16)pItemList->Count();
2635     if( bLayout )
2636         mpLayoutData->m_aVisibleItemBoundRects.clear();
2637     for ( sal_uInt16 n = 0; n < nCount; n++ )
2638     {
2639         MenuItemData* pData = pItemList->GetDataFromPos( n );
2640         if ( ImplIsVisible( n ) && ( !pThisItemOnly || ( pData == pThisItemOnly ) ) )
2641         {
2642             if ( pThisItemOnly && bHighlighted )
2643                 pWin->SetTextColor( rSettings.GetMenuHighlightTextColor() );
2644 
2645             Point aPos( aTopLeft );
2646             aPos.Y() += nBorder;
2647             aPos.Y() += nStartY;
2648 
2649             if ( aPos.Y() >= 0 )
2650             {
2651                 long    nTextOffsetY = ((pData->aSz.Height()-nFontHeight)/2);
2652                 if( bIsMenuBar )
2653                     nTextOffsetY += (aOutSz.Height()-pData->aSz.Height()) / 2;
2654                 sal_uInt16  nTextStyle   = 0;
2655                 sal_uInt16  nSymbolStyle = 0;
2656                 sal_uInt16  nImageStyle  = 0;
2657                 // SubMenus ohne Items werden nicht mehr disablte dargestellt,
2658                 // wenn keine Items enthalten sind, da die Anwendung selber
2659                 // darauf achten muss. Ansonsten gibt es Faelle, wo beim
2660                 // asyncronen laden die Eintraege disablte dargestellt werden.
2661                 if ( !pData->bEnabled )
2662                 {
2663                     nTextStyle   |= TEXT_DRAW_DISABLE;
2664                     nSymbolStyle |= SYMBOL_DRAW_DISABLE;
2665                     nImageStyle  |= IMAGE_DRAW_DISABLE;
2666                 }
2667 
2668                 // Separator
2669                 if ( !bLayout && !bIsMenuBar && ( pData->eType == MENUITEM_SEPARATOR ) )
2670                 {
2671                     bool bNativeOk = false;
2672                     if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP,
2673                                                         PART_MENU_SEPARATOR ) )
2674                     {
2675                         ControlState nState = 0;
2676                         if ( pData->bEnabled )
2677                             nState |= CTRL_STATE_ENABLED;
2678                         if ( bHighlighted )
2679                             nState |= CTRL_STATE_SELECTED;
2680 						Size aSz( pData->aSz );
2681 						aSz.Width() = aOutSz.Width() - 2*nOuterSpace;
2682                         Rectangle aItemRect( aPos, aSz );
2683                         MenupopupValue aVal( nTextPos-GUTTERBORDER, aItemRect );
2684                         bNativeOk = pWin->DrawNativeControl( CTRL_MENU_POPUP, PART_MENU_SEPARATOR,
2685                                                              aItemRect,
2686                                                              nState,
2687                                                              aVal,
2688                                                              OUString() );
2689                     }
2690                     if( ! bNativeOk )
2691                     {
2692                         aTmpPos.Y() = aPos.Y() + ((pData->aSz.Height()-2)/2);
2693                         aTmpPos.X() = aPos.X() + 2 + nOuterSpace;
2694                         pWin->SetLineColor( rSettings.GetShadowColor() );
2695                         pWin->DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpace, aTmpPos.Y() ) );
2696                         aTmpPos.Y()++;
2697                         pWin->SetLineColor( rSettings.GetLightColor() );
2698                         pWin->DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpace, aTmpPos.Y() ) );
2699                         pWin->SetLineColor();
2700                     }
2701                 }
2702 
2703                 Rectangle aOuterCheckRect( Point( aPos.X()+nCheckPos, aPos.Y() ), Size( pData->aSz.Height(), pData->aSz.Height() ) );
2704                 aOuterCheckRect.Left()      += 1;
2705                 aOuterCheckRect.Right()     -= 1;
2706                 aOuterCheckRect.Top()       += 1;
2707                 aOuterCheckRect.Bottom()    -= 1;
2708 
2709                 // CheckMark
2710                 if ( !bLayout && !bIsMenuBar && pData->HasCheck() )
2711                 {
2712                     // draw selection transparent marker if checked
2713                     // onto that either a checkmark or the item image
2714                     // will be painted
2715                     // however do not do this if native checks will be painted since
2716                     // the selection color too often does not fit the theme's check and/or radio
2717 
2718                     if( ! ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
2719                     {
2720                         if ( pWin->IsNativeControlSupported( CTRL_MENU_POPUP,
2721                                                              (pData->nBits & MIB_RADIOCHECK)
2722                                                              ? PART_MENU_ITEM_CHECK_MARK
2723                                                              : PART_MENU_ITEM_RADIO_MARK ) )
2724                         {
2725                             ControlPart nPart = ((pData->nBits & MIB_RADIOCHECK)
2726                                                  ? PART_MENU_ITEM_RADIO_MARK
2727                                                  : PART_MENU_ITEM_CHECK_MARK);
2728 
2729                             ControlState nState = 0;
2730 
2731                             if ( pData->bChecked )
2732                                 nState |= CTRL_STATE_PRESSED;
2733 
2734                             if ( pData->bEnabled )
2735                                 nState |= CTRL_STATE_ENABLED;
2736 
2737                             if ( bHighlighted )
2738                                 nState |= CTRL_STATE_SELECTED;
2739 
2740                             long nCtrlHeight = (pData->nBits & MIB_RADIOCHECK) ? nCheckHeight : nRadioHeight;
2741                             aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - nCtrlHeight)/2;
2742                             aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - nCtrlHeight)/2;
2743 
2744                             Rectangle aCheckRect( aTmpPos, Size( nCtrlHeight, nCtrlHeight ) );
2745                             MenupopupValue aVal( nTextPos-GUTTERBORDER, Rectangle( aPos, pData->aSz ) );
2746                             pWin->DrawNativeControl( CTRL_MENU_POPUP, nPart,
2747                                                      aCheckRect,
2748                                                      nState,
2749                                                      aVal,
2750                                                      OUString() );
2751                         }
2752                         else if ( pData->bChecked ) // by default do nothing for unchecked items
2753                         {
2754                             ImplPaintCheckBackground( pWin, aOuterCheckRect, pThisItemOnly && bHighlighted );
2755 
2756                             SymbolType eSymbol;
2757                             Size aSymbolSize;
2758                             if ( pData->nBits & MIB_RADIOCHECK )
2759                             {
2760                                 eSymbol = SYMBOL_RADIOCHECKMARK;
2761                                 aSymbolSize = Size( nFontHeight/2, nFontHeight/2 );
2762                             }
2763                             else
2764                             {
2765                                 eSymbol = SYMBOL_CHECKMARK;
2766                                 aSymbolSize = Size( (nFontHeight*25)/40, nFontHeight/2 );
2767                             }
2768                             aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - aSymbolSize.Width())/2;
2769                             aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - aSymbolSize.Height())/2;
2770                             Rectangle aRect( aTmpPos, aSymbolSize );
2771                             aDecoView.DrawSymbol( aRect, eSymbol, pWin->GetTextColor(), nSymbolStyle );
2772                         }
2773                     }
2774                 }
2775 
2776                 // Image:
2777                 if ( !bLayout && !bIsMenuBar && ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
2778                 {
2779 					// Don't render an image for a check thing
2780 					if ((nMenuFlags & MENU_FLAG_SHOWCHECKIMAGES) || !pData->HasCheck() )
2781 					{
2782                         if( pData->bChecked )
2783                             ImplPaintCheckBackground( pWin, aOuterCheckRect, pThisItemOnly && bHighlighted );
2784                         aTmpPos = aOuterCheckRect.TopLeft();
2785 	                    aTmpPos.X() += (aOuterCheckRect.GetWidth()-pData->aImage.GetSizePixel().Width())/2;
2786 	                    aTmpPos.Y() += (aOuterCheckRect.GetHeight()-pData->aImage.GetSizePixel().Height())/2;
2787 	                    pWin->DrawImage( aTmpPos, pData->aImage, nImageStyle );
2788 					}
2789                 }
2790 
2791                 // Text:
2792                 if ( ( pData->eType == MENUITEM_STRING ) || ( pData->eType == MENUITEM_STRINGIMAGE ) )
2793                 {
2794                     aTmpPos.X() = aPos.X() + nTextPos;
2795                     aTmpPos.Y() = aPos.Y();
2796                     aTmpPos.Y() += nTextOffsetY;
2797                     sal_uInt16 nStyle = nTextStyle|TEXT_DRAW_MNEMONIC;
2798                     if ( pData->bIsTemporary )
2799                         nStyle |= TEXT_DRAW_DISABLE;
2800                     MetricVector* pVector = bLayout ? &mpLayoutData->m_aUnicodeBoundRects : NULL;
2801                     String* pDisplayText = bLayout ? &mpLayoutData->m_aDisplayText : NULL;
2802                     if( bLayout )
2803                     {
2804                         mpLayoutData->m_aLineIndices.push_back( mpLayoutData->m_aDisplayText.Len() );
2805                         mpLayoutData->m_aLineItemIds.push_back( pData->nId );
2806                         mpLayoutData->m_aLineItemPositions.push_back( n );
2807                     }
2808                     // #i47946# with NWF painted menus the background is transparent
2809                     // since DrawCtrlText can depend on the background (e.g. for
2810                     // TEXT_DRAW_DISABLE), temporarily set a background which
2811                     // hopefully matches the NWF background since it is read
2812                     // from the system style settings
2813                     bool bSetTmpBackground = !pWin->IsBackground() && pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL );
2814                     if( bSetTmpBackground )
2815                     {
2816                         Color aBg = bIsMenuBar ?
2817                             pWin->GetSettings().GetStyleSettings().GetMenuBarColor() :
2818                             pWin->GetSettings().GetStyleSettings().GetMenuColor();
2819                         pWin->SetBackground( Wallpaper( aBg ) );
2820                     }
2821                     // how much space is there for the text ?
2822                     long nMaxItemTextWidth = aOutSz.Width() - aTmpPos.X() - nExtra - nOuterSpace;
2823                     if( !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() )
2824                     {
2825                         XubString aAccText = pData->aAccelKey.GetName();
2826                         nMaxItemTextWidth -= pWin->GetTextWidth( aAccText ) + 3*nExtra;
2827                     }
2828                     if( !bIsMenuBar && pData->pSubMenu )
2829                     {
2830                         nMaxItemTextWidth -= nFontHeight - nExtra;
2831                     }
2832                     String aItemText( getShortenedString( pData->aText, pWin, nMaxItemTextWidth ) );
2833                     pWin->DrawCtrlText( aTmpPos, aItemText, 0, aItemText.Len(), nStyle, pVector, pDisplayText );
2834                     if( bSetTmpBackground )
2835                         pWin->SetBackground();
2836                 }
2837 
2838                 // Accel
2839                 if ( !bLayout && !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() )
2840                 {
2841                     XubString aAccText = pData->aAccelKey.GetName();
2842                     aTmpPos.X() = aOutSz.Width() - pWin->GetTextWidth( aAccText );
2843                     aTmpPos.X() -= 4*nExtra;
2844 
2845                     aTmpPos.X() -= nOuterSpace;
2846                     aTmpPos.Y() = aPos.Y();
2847                     aTmpPos.Y() += nTextOffsetY;
2848                     pWin->DrawCtrlText( aTmpPos, aAccText, 0, aAccText.Len(), nTextStyle );
2849                 }
2850 
2851                 // SubMenu?
2852                 if ( !bLayout && !bIsMenuBar && pData->pSubMenu )
2853                 {
2854                     aTmpPos.X() = aOutSz.Width() - nFontHeight + nExtra - nOuterSpace;
2855                     aTmpPos.Y() = aPos.Y();
2856                     aTmpPos.Y() += nExtra/2;
2857                     aTmpPos.Y() += ( pData->aSz.Height() / 2 ) - ( nFontHeight/4 );
2858                     if ( pData->nBits & MIB_POPUPSELECT )
2859                     {
2860                         pWin->SetTextColor( rSettings.GetMenuTextColor() );
2861                         Point aTmpPos2( aPos );
2862                         aTmpPos2.X() = aOutSz.Width() - nFontHeight - nFontHeight/4;
2863                         aDecoView.DrawFrame(
2864                             Rectangle( aTmpPos2, Size( nFontHeight+nFontHeight/4, pData->aSz.Height() ) ), FRAME_DRAW_GROUP );
2865                     }
2866                     aDecoView.DrawSymbol(
2867                         Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ),
2868                         SYMBOL_SPIN_RIGHT, pWin->GetTextColor(), nSymbolStyle );
2869                 }
2870 
2871                 if ( pThisItemOnly && bHighlighted )
2872                 {
2873                     // This restores the normal menu or menu bar text
2874                     // color for when it is no longer highlighted.
2875 		    if ( bIsMenuBar )
2876 		        pWin->SetTextColor( rSettings.GetMenuBarTextColor() );
2877 		    else
2878 		        pWin->SetTextColor( rSettings.GetMenuTextColor() );
2879 		 }
2880             }
2881             if( bLayout )
2882             {
2883                 if ( !bIsMenuBar )
2884                     mpLayoutData->m_aVisibleItemBoundRects[ n ] = Rectangle( aTopLeft, Size( aOutSz.Width(), pData->aSz.Height() ) );
2885                 else
2886                     mpLayoutData->m_aVisibleItemBoundRects[ n ] = Rectangle( aTopLeft, pData->aSz );
2887             }
2888         }
2889 
2890         if ( !bIsMenuBar )
2891         {
2892             aTopLeft.Y() += pData->aSz.Height();
2893         }
2894         else
2895         {
2896             aTopLeft.X() += pData->aSz.Width();
2897         }
2898     }
2899 
2900     if ( !bLayout && !pThisItemOnly && pLogo )
2901     {
2902         Size aLogoSz = pLogo->aBitmap.GetSizePixel();
2903 
2904         Rectangle aRect( Point( 0, 0 ), Point( aLogoSz.Width()-1, aOutSz.Height() ) );
2905         if ( pWin->GetColorCount() >= 256 )
2906         {
2907             Gradient aGrad( GRADIENT_LINEAR, pLogo->aStartColor, pLogo->aEndColor );
2908             aGrad.SetAngle( 1800 );
2909             aGrad.SetBorder( 15 );
2910             pWin->DrawGradient( aRect, aGrad );
2911         }
2912         else
2913         {
2914             pWin->SetFillColor( pLogo->aStartColor );
2915             pWin->DrawRect( aRect );
2916         }
2917 
2918         Point aLogoPos( 0, aOutSz.Height() - aLogoSz.Height() );
2919         pLogo->aBitmap.Draw( pWin, aLogoPos );
2920     }
2921 }
2922 
2923 Menu* Menu::ImplGetStartMenu()
2924 {
2925     Menu* pStart = this;
2926     while ( pStart && pStart->pStartedFrom && ( pStart->pStartedFrom != pStart ) )
2927         pStart = pStart->pStartedFrom;
2928     return pStart;
2929 }
2930 
2931 void Menu::ImplCallHighlight( sal_uInt16 nHighlightedItem )
2932 {
2933 	ImplMenuDelData aDelData( this );
2934 
2935     nSelectedId = 0;
2936     MenuItemData* pData = pItemList->GetDataFromPos( nHighlightedItem );
2937     if ( pData )
2938         nSelectedId = pData->nId;
2939     ImplCallEventListeners( VCLEVENT_MENU_HIGHLIGHT, GetItemPos( GetCurItemId() ) );
2940 
2941 	if( !aDelData.isDeleted() )
2942 	{
2943 	    Highlight();
2944 		nSelectedId = 0;
2945 	}
2946 }
2947 
2948 IMPL_LINK( Menu, ImplCallSelect, Menu*, EMPTYARG )
2949 {
2950     nEventId = 0;
2951     Select();
2952     return 0;
2953 }
2954 
2955 Menu* Menu::ImplFindSelectMenu()
2956 {
2957     Menu* pSelMenu = nEventId ? this : NULL;
2958 
2959     for ( sal_uLong n = GetItemList()->Count(); n && !pSelMenu; )
2960     {
2961         MenuItemData* pData = GetItemList()->GetDataFromPos( --n );
2962 
2963         if ( pData->pSubMenu )
2964             pSelMenu = pData->pSubMenu->ImplFindSelectMenu();
2965     }
2966 
2967     return pSelMenu;
2968 }
2969 
2970 Menu* Menu::ImplFindMenu( sal_uInt16 nItemId )
2971 {
2972     Menu* pSelMenu = NULL;
2973 
2974     for ( sal_uLong n = GetItemList()->Count(); n && !pSelMenu; )
2975     {
2976         MenuItemData* pData = GetItemList()->GetDataFromPos( --n );
2977 
2978         if( pData->nId == nItemId )
2979             pSelMenu = this;
2980         else if ( pData->pSubMenu )
2981             pSelMenu = pData->pSubMenu->ImplFindMenu( nItemId );
2982     }
2983 
2984     return pSelMenu;
2985 }
2986 
2987 void Menu::RemoveDisabledEntries( sal_Bool bCheckPopups, sal_Bool bRemoveEmptyPopups )
2988 {
2989     for ( sal_uInt16 n = 0; n < GetItemCount(); n++ )
2990     {
2991         sal_Bool bRemove = sal_False;
2992         MenuItemData* pItem = pItemList->GetDataFromPos( n );
2993         if ( pItem->eType == MENUITEM_SEPARATOR )
2994         {
2995             if ( !n || ( GetItemType( n-1 ) == MENUITEM_SEPARATOR ) )
2996                 bRemove = sal_True;
2997         }
2998         else
2999             bRemove = !pItem->bEnabled;
3000 
3001         if ( bCheckPopups && pItem->pSubMenu )
3002         {
3003             pItem->pSubMenu->RemoveDisabledEntries( sal_True );
3004             if ( bRemoveEmptyPopups && !pItem->pSubMenu->GetItemCount() )
3005                 bRemove = sal_True;
3006         }
3007 
3008         if ( bRemove )
3009             RemoveItem( n-- );
3010     }
3011 
3012     if ( GetItemCount() )
3013     {
3014         sal_uInt16 nLast = GetItemCount() - 1;
3015         MenuItemData* pItem = pItemList->GetDataFromPos( nLast );
3016         if ( pItem->eType == MENUITEM_SEPARATOR )
3017             RemoveItem( nLast );
3018     }
3019     delete mpLayoutData, mpLayoutData = NULL;
3020 }
3021 
3022 sal_Bool Menu::HasValidEntries( sal_Bool bCheckPopups )
3023 {
3024     sal_Bool bValidEntries = sal_False;
3025     sal_uInt16 nCount = GetItemCount();
3026     for ( sal_uInt16 n = 0; !bValidEntries && ( n < nCount ); n++ )
3027     {
3028         MenuItemData* pItem = pItemList->GetDataFromPos( n );
3029         if ( pItem->bEnabled && ( pItem->eType != MENUITEM_SEPARATOR ) )
3030         {
3031             if ( bCheckPopups && pItem->pSubMenu )
3032                 bValidEntries = pItem->pSubMenu->HasValidEntries( sal_True );
3033             else
3034                 bValidEntries = sal_True;
3035         }
3036     }
3037     return bValidEntries;
3038 }
3039 
3040 void Menu::SetLogo( const MenuLogo& rLogo )
3041 {
3042     delete pLogo;
3043     pLogo = new MenuLogo( rLogo );
3044 }
3045 
3046 void Menu::SetLogo()
3047 {
3048     delete pLogo;
3049     pLogo = NULL;
3050 }
3051 
3052 MenuLogo Menu::GetLogo() const
3053 {
3054     MenuLogo aLogo;
3055     if ( pLogo )
3056         aLogo = *pLogo;
3057     return aLogo;
3058 }
3059 
3060 void Menu::ImplKillLayoutData() const
3061 {
3062     delete mpLayoutData, mpLayoutData = NULL;
3063 }
3064 
3065 void Menu::ImplFillLayoutData() const
3066 {
3067     if( pWindow && pWindow->IsReallyVisible() )
3068     {
3069         mpLayoutData = new MenuLayoutData();
3070         if( bIsMenuBar )
3071         {
3072             ImplPaint( pWindow, 0, 0, 0, sal_False, true );
3073         }
3074         else
3075         {
3076             MenuFloatingWindow* pFloat = (MenuFloatingWindow*)pWindow;
3077             ImplPaint( pWindow, pFloat->nScrollerHeight, pFloat->ImplGetStartY(), 0, sal_False, true );
3078         }
3079     }
3080 }
3081 
3082 String Menu::GetDisplayText() const
3083 {
3084     if( ! mpLayoutData )
3085         ImplFillLayoutData();
3086     return mpLayoutData ? mpLayoutData->m_aDisplayText : String();
3087 }
3088 
3089 Rectangle Menu::GetCharacterBounds( sal_uInt16 nItemID, long nIndex ) const
3090 {
3091     long nItemIndex = -1;
3092     if( ! mpLayoutData )
3093         ImplFillLayoutData();
3094     if( mpLayoutData )
3095     {
3096         for( size_t i = 0; i < mpLayoutData->m_aLineItemIds.size(); i++ )
3097         {
3098             if( mpLayoutData->m_aLineItemIds[i] == nItemID )
3099             {
3100                 nItemIndex = mpLayoutData->m_aLineIndices[i];
3101                 break;
3102             }
3103         }
3104     }
3105     return (mpLayoutData && nItemIndex != -1) ? mpLayoutData->GetCharacterBounds( nItemIndex+nIndex ) : Rectangle();
3106 }
3107 
3108 
3109 long Menu::GetIndexForPoint( const Point& rPoint, sal_uInt16& rItemID ) const
3110 {
3111     long nIndex = -1;
3112     rItemID = 0;
3113     if( ! mpLayoutData )
3114         ImplFillLayoutData();
3115     if( mpLayoutData )
3116     {
3117         nIndex = mpLayoutData->GetIndexForPoint( rPoint );
3118         for( size_t i = 0; i < mpLayoutData->m_aLineIndices.size(); i++ )
3119         {
3120             if( mpLayoutData->m_aLineIndices[i] <= nIndex &&
3121                 (i == mpLayoutData->m_aLineIndices.size()-1 || mpLayoutData->m_aLineIndices[i+1] > nIndex) )
3122             {
3123                 // make index relative to item
3124                 nIndex -= mpLayoutData->m_aLineIndices[i];
3125                 rItemID = mpLayoutData->m_aLineItemIds[i];
3126                 break;
3127             }
3128         }
3129     }
3130     return nIndex;
3131 }
3132 
3133 long Menu::GetLineCount() const
3134 {
3135     if( ! mpLayoutData )
3136         ImplFillLayoutData();
3137     return mpLayoutData ? mpLayoutData->GetLineCount() : 0;
3138 }
3139 
3140 Pair Menu::GetLineStartEnd( long nLine ) const
3141 {
3142     if( ! mpLayoutData )
3143         ImplFillLayoutData();
3144     return mpLayoutData ? mpLayoutData->GetLineStartEnd( nLine ) : Pair( -1, -1 );
3145 }
3146 
3147 Pair Menu::GetItemStartEnd( sal_uInt16 nItem ) const
3148 {
3149     if( ! mpLayoutData )
3150         ImplFillLayoutData();
3151 
3152     for( size_t i = 0; i < mpLayoutData->m_aLineItemIds.size(); i++ )
3153         if( mpLayoutData->m_aLineItemIds[i] == nItem )
3154             return GetLineStartEnd( i );
3155 
3156     return Pair( -1, -1 );
3157 }
3158 
3159 sal_uInt16 Menu::GetDisplayItemId( long nLine ) const
3160 {
3161     sal_uInt16 nItemId = 0;
3162     if( ! mpLayoutData )
3163         ImplFillLayoutData();
3164     if( mpLayoutData && ( nLine >= 0 ) && ( nLine < (long)mpLayoutData->m_aLineItemIds.size() ) )
3165         nItemId = mpLayoutData->m_aLineItemIds[nLine];
3166     return nItemId;
3167 }
3168 
3169 sal_Bool Menu::ConvertPoint( Point& rPoint, Window* pReferenceWindow ) const
3170 {
3171     sal_Bool bRet = sal_False;
3172     if( pWindow && pReferenceWindow )
3173     {
3174         rPoint = pReferenceWindow->OutputToAbsoluteScreenPixel( rPoint );
3175         rPoint = pWindow->AbsoluteScreenToOutputPixel( rPoint );
3176         bRet = sal_True;
3177     }
3178     return bRet;
3179 }
3180 
3181 Rectangle Menu::GetBoundingRectangle( sal_uInt16 nPos ) const
3182 {
3183     Rectangle aRet;
3184 
3185     if( ! mpLayoutData )
3186         ImplFillLayoutData();
3187     if( mpLayoutData )
3188     {
3189         std::map< sal_uInt16, Rectangle >::const_iterator it = mpLayoutData->m_aVisibleItemBoundRects.find( nPos );
3190         if( it != mpLayoutData->m_aVisibleItemBoundRects.end() )
3191             aRet = it->second;
3192     }
3193     return aRet;
3194 }
3195 
3196 void Menu::SetAccessibleName( sal_uInt16 nItemId, const XubString& rStr )
3197 {
3198     sal_uInt16        nPos;
3199     MenuItemData* pData = pItemList->GetData( nItemId, nPos );
3200 
3201 	if ( pData && !rStr.Equals( pData->aAccessibleName ) )
3202 	{
3203 		pData->aAccessibleName = rStr;
3204 		ImplCallEventListeners( VCLEVENT_MENU_ACCESSIBLENAMECHANGED, nPos );
3205 	}
3206 }
3207 
3208 XubString Menu::GetAccessibleName( sal_uInt16 nItemId ) const
3209 {
3210     MenuItemData* pData = pItemList->GetData( nItemId );
3211 
3212     if ( pData )
3213         return pData->aAccessibleName;
3214     else
3215         return ImplGetSVEmptyStr();
3216 }
3217 
3218 void Menu::SetAccessibleDescription( sal_uInt16 nItemId, const XubString& rStr )
3219 {
3220     MenuItemData* pData = pItemList->GetData( nItemId );
3221 
3222 	if ( pData )
3223 		pData->aAccessibleDescription = rStr;
3224 }
3225 
3226 XubString Menu::GetAccessibleDescription( sal_uInt16 nItemId ) const
3227 {
3228     MenuItemData* pData = pItemList->GetData( nItemId );
3229 
3230     if ( pData )
3231         return pData->aAccessibleDescription;
3232     else
3233         return ImplGetSVEmptyStr();
3234 }
3235 
3236 void Menu::ImplSetSalMenu( SalMenu *pSalMenu )
3237 {
3238     if( mpSalMenu )
3239         ImplGetSVData()->mpDefInst->DestroyMenu( mpSalMenu );
3240     mpSalMenu = pSalMenu;
3241 }
3242 
3243 sal_Bool Menu::GetSystemMenuData( SystemMenuData* pData ) const
3244 {
3245     Menu* pMenu = (Menu*)this;
3246     if( pData && pMenu->ImplGetSalMenu() )
3247     {
3248         pMenu->ImplGetSalMenu()->GetSystemMenuData( pData );
3249         return sal_True;
3250     }
3251     else
3252         return sal_False;
3253 }
3254 
3255 bool Menu::IsHighlighted( sal_uInt16 nItemPos ) const
3256 {
3257     bool bRet = false;
3258 
3259     if( pWindow )
3260     {
3261         if( bIsMenuBar )
3262             bRet = ( nItemPos == static_cast< MenuBarWindow * > (pWindow)->GetHighlightedItem() );
3263         else
3264             bRet = ( nItemPos == static_cast< MenuFloatingWindow * > (pWindow)->GetHighlightedItem() );
3265     }
3266 
3267     return bRet;
3268 }
3269 
3270 void Menu::HighlightItem( sal_uInt16 nItemPos )
3271 {
3272     if ( pWindow )
3273     {
3274         if ( bIsMenuBar )
3275         {
3276             MenuBarWindow* pMenuWin = static_cast< MenuBarWindow* >( pWindow );
3277             pMenuWin->SetAutoPopup( sal_False );
3278             pMenuWin->ChangeHighlightItem( nItemPos, sal_False );
3279         }
3280         else
3281         {
3282             static_cast< MenuFloatingWindow* >( pWindow )->ChangeHighlightItem( nItemPos, sal_False );
3283         }
3284     }
3285 }
3286 
3287 // -----------
3288 // - MenuBar -
3289 // -----------
3290 
3291 MenuBar::MenuBar() : Menu( sal_True )
3292 {
3293     mbDisplayable       = sal_True;
3294     mbCloserVisible     = sal_False;
3295     mbFloatBtnVisible   = sal_False;
3296     mbHideBtnVisible    = sal_False;
3297 }
3298 
3299 MenuBar::MenuBar( const MenuBar& rMenu ) : Menu( sal_True )
3300 {
3301     mbDisplayable       = sal_True;
3302     mbCloserVisible     = sal_False;
3303     mbFloatBtnVisible   = sal_False;
3304     mbHideBtnVisible    = sal_False;
3305     *this               = rMenu;
3306     bIsMenuBar          = sal_True;
3307 }
3308 
3309 MenuBar::MenuBar( const ResId& rResId ) : Menu ( sal_True )
3310 {
3311     mbDisplayable       = sal_True;
3312     mbCloserVisible     = sal_False;
3313     mbFloatBtnVisible   = sal_False;
3314     mbHideBtnVisible    = sal_False;
3315     ImplLoadRes( rResId );
3316 }
3317 
3318 MenuBar::~MenuBar()
3319 {
3320     ImplDestroy( this, sal_True );
3321 }
3322 
3323 void MenuBar::ShowCloser( sal_Bool bShow )
3324 {
3325     ShowButtons( bShow, mbFloatBtnVisible, mbHideBtnVisible );
3326 }
3327 
3328 void MenuBar::ShowFloatButton( sal_Bool bShow )
3329 {
3330     ShowButtons( mbCloserVisible, bShow, mbHideBtnVisible );
3331 }
3332 
3333 void MenuBar::ShowHideButton( sal_Bool bShow )
3334 {
3335     ShowButtons( mbCloserVisible, mbFloatBtnVisible, bShow );
3336 }
3337 
3338 void MenuBar::ShowButtons( sal_Bool bClose, sal_Bool bFloat, sal_Bool bHide )
3339 {
3340     if ( (bClose != mbCloserVisible)    ||
3341          (bFloat != mbFloatBtnVisible)  ||
3342          (bHide  != mbHideBtnVisible) )
3343     {
3344         mbCloserVisible     = bClose;
3345         mbFloatBtnVisible   = bFloat;
3346         mbHideBtnVisible    = bHide;
3347         if ( ImplGetWindow() )
3348             ((MenuBarWindow*)ImplGetWindow())->ShowButtons( bClose, bFloat, bHide );
3349     }
3350 }
3351 
3352 void MenuBar::SetDisplayable( sal_Bool bDisplayable )
3353 {
3354     if( bDisplayable != mbDisplayable )
3355     {
3356         mbDisplayable = bDisplayable;
3357         MenuBarWindow* pMenuWin = (MenuBarWindow*) ImplGetWindow();
3358         if( pMenuWin )
3359             pMenuWin->ImplLayoutChanged();
3360     }
3361 }
3362 
3363 Window* MenuBar::ImplCreate( Window* pParent, Window* pWindow, MenuBar* pMenu )
3364 {
3365     if ( !pWindow )
3366         pWindow = new MenuBarWindow( pParent );
3367 
3368     pMenu->pStartedFrom = 0;
3369     pMenu->pWindow = pWindow;
3370     ((MenuBarWindow*)pWindow)->SetMenu( pMenu );
3371     long nHeight = pMenu->ImplCalcSize( pWindow ).Height();
3372 
3373     // depending on the native implementation or the displayable flag
3374     // the menubar windows is supressed (ie, height=0)
3375     if( !((MenuBar*) pMenu)->IsDisplayable() ||
3376         ( pMenu->ImplGetSalMenu() && pMenu->ImplGetSalMenu()->VisibleMenuBar() ) )
3377         nHeight = 0;
3378 
3379     pWindow->SetPosSizePixel( 0, 0, 0, nHeight, WINDOW_POSSIZE_HEIGHT );
3380     return pWindow;
3381 }
3382 
3383 void MenuBar::ImplDestroy( MenuBar* pMenu, sal_Bool bDelete )
3384 {
3385     MenuBarWindow* pWindow = (MenuBarWindow*) pMenu->ImplGetWindow();
3386     if ( pWindow && bDelete )
3387     {
3388         pWindow->KillActivePopup();
3389         delete pWindow;
3390     }
3391     pMenu->pWindow = NULL;
3392 }
3393 
3394 sal_Bool MenuBar::ImplHandleKeyEvent( const KeyEvent& rKEvent, sal_Bool bFromMenu )
3395 {
3396     sal_Bool bDone = sal_False;
3397 
3398     // No keyboard processing when system handles the menu or our menubar is invisible
3399     if( !IsDisplayable() ||
3400         ( ImplGetSalMenu() && ImplGetSalMenu()->VisibleMenuBar() ) )
3401         return bDone;
3402 
3403     // Enabled-Abfragen, falls diese Methode von einem anderen Fenster gerufen wurde...
3404     Window* pWin = ImplGetWindow();
3405     if ( pWin && pWin->IsEnabled() && pWin->IsInputEnabled()  && ! pWin->IsInModalMode() )
3406         bDone = ((MenuBarWindow*)pWin)->ImplHandleKeyEvent( rKEvent, bFromMenu );
3407     return bDone;
3408 }
3409 
3410 // -----------------------------------------------------------------------
3411 
3412 void MenuBar::SelectEntry( sal_uInt16 nId )
3413 {
3414     MenuBarWindow* pMenuWin = (MenuBarWindow*) ImplGetWindow();
3415 
3416     if( pMenuWin )
3417     {
3418         pMenuWin->GrabFocus();
3419         nId = GetItemPos( nId );
3420 
3421         // #99705# popup the selected menu
3422         pMenuWin->SetAutoPopup( sal_True );
3423         if( ITEMPOS_INVALID != pMenuWin->nHighlightedItem )
3424         {
3425             pMenuWin->KillActivePopup();
3426             pMenuWin->ChangeHighlightItem( ITEMPOS_INVALID, sal_False );
3427         }
3428         if( nId != ITEMPOS_INVALID )
3429             pMenuWin->ChangeHighlightItem( nId, sal_False );
3430     }
3431 }
3432 
3433 // -----------------------------------------------------------------------
3434 
3435 // handler for native menu selection and command events
3436 
3437 sal_Bool MenuBar::HandleMenuActivateEvent( Menu *pMenu ) const
3438 {
3439     if( pMenu )
3440     {
3441 		ImplMenuDelData aDelData( this );
3442 
3443         pMenu->pStartedFrom = (Menu*)this;
3444         pMenu->bInCallback = sal_True;
3445         pMenu->Activate();
3446 
3447 		if( !aDelData.isDeleted() )
3448 	        pMenu->bInCallback = sal_False;
3449     }
3450     return sal_True;
3451 }
3452 
3453 sal_Bool MenuBar::HandleMenuDeActivateEvent( Menu *pMenu ) const
3454 {
3455     if( pMenu )
3456     {
3457 		ImplMenuDelData aDelData( this );
3458 
3459         pMenu->pStartedFrom = (Menu*)this;
3460         pMenu->bInCallback = sal_True;
3461         pMenu->Deactivate();
3462 		if( !aDelData.isDeleted() )
3463 			pMenu->bInCallback = sal_False;
3464     }
3465     return sal_True;
3466 }
3467 
3468 sal_Bool MenuBar::HandleMenuHighlightEvent( Menu *pMenu, sal_uInt16 nHighlightEventId ) const
3469 {
3470     if( !pMenu )
3471         pMenu = ((Menu*) this)->ImplFindMenu( nHighlightEventId );
3472     if( pMenu )
3473     {
3474 		ImplMenuDelData aDelData( pMenu );
3475 
3476         if( mnHighlightedItemPos != ITEMPOS_INVALID )
3477             pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, mnHighlightedItemPos );
3478 
3479 		if( !aDelData.isDeleted() )
3480 		{
3481 	        pMenu->mnHighlightedItemPos = pMenu->GetItemPos( nHighlightEventId );
3482 		    pMenu->nSelectedId = nHighlightEventId;
3483 			pMenu->pStartedFrom = (Menu*)this;
3484 			pMenu->ImplCallHighlight( pMenu->mnHighlightedItemPos );
3485 		}
3486         return sal_True;
3487     }
3488     else
3489         return sal_False;
3490 }
3491 
3492 sal_Bool MenuBar::HandleMenuCommandEvent( Menu *pMenu, sal_uInt16 nCommandEventId ) const
3493 {
3494     if( !pMenu )
3495         pMenu = ((Menu*) this)->ImplFindMenu( nCommandEventId );
3496     if( pMenu )
3497     {
3498         pMenu->nSelectedId = nCommandEventId;
3499         pMenu->pStartedFrom = (Menu*)this;
3500         pMenu->ImplSelect();
3501         return sal_True;
3502     }
3503     else
3504         return sal_False;
3505 }
3506 
3507 sal_uInt16 MenuBar::AddMenuBarButton( const Image& i_rImage, const Link& i_rLink, sal_uInt16 i_nPos )
3508 {
3509     return AddMenuBarButton( i_rImage, i_rLink, String(), i_nPos );
3510 }
3511 
3512 sal_uInt16 MenuBar::AddMenuBarButton( const Image& i_rImage, const Link& i_rLink, const String& i_rToolTip, sal_uInt16 i_nPos )
3513 {
3514     return pWindow ? static_cast<MenuBarWindow*>(pWindow)->AddMenuBarButton( i_rImage, i_rLink, i_rToolTip, i_nPos ) : 0;
3515 }
3516 
3517 void MenuBar::SetMenuBarButtonHighlightHdl( sal_uInt16 nId, const Link& rLink )
3518 {
3519     if( pWindow )
3520         static_cast<MenuBarWindow*>(pWindow)->SetMenuBarButtonHighlightHdl( nId, rLink );
3521 }
3522 
3523 Rectangle MenuBar::GetMenuBarButtonRectPixel( sal_uInt16 nId )
3524 {
3525     return pWindow ? static_cast<MenuBarWindow*>(pWindow)->GetMenuBarButtonRectPixel( nId ) : Rectangle();
3526 }
3527 
3528 void MenuBar::RemoveMenuBarButton( sal_uInt16 nId )
3529 {
3530     if( pWindow )
3531         static_cast<MenuBarWindow*>(pWindow)->RemoveMenuBarButton( nId );
3532 }
3533 
3534 sal_Bool MenuBar::HandleMenuButtonEvent( Menu *, sal_uInt16 i_nButtonId ) const
3535 {
3536     return static_cast<MenuBarWindow*>(pWindow)->HandleMenuButtonEvent( i_nButtonId );
3537 }
3538 
3539 // -----------------------------------------------------------------------
3540 
3541 // sal_Bool PopupMenu::bAnyPopupInExecute = sal_False;
3542 
3543 PopupMenu::PopupMenu()
3544 {
3545     pRefAutoSubMenu = NULL;
3546 }
3547 
3548 PopupMenu::PopupMenu( const ResId& rResId )
3549 {
3550     pRefAutoSubMenu = NULL;
3551     ImplLoadRes( rResId );
3552 }
3553 
3554 PopupMenu::PopupMenu( const PopupMenu& rMenu ) : Menu()
3555 {
3556     pRefAutoSubMenu = NULL;
3557     *this = rMenu;
3558 }
3559 
3560 PopupMenu::~PopupMenu()
3561 {
3562     if( pRefAutoSubMenu && *pRefAutoSubMenu == this )
3563         *pRefAutoSubMenu = NULL;    // #111060# avoid second delete in ~MenuItemData
3564 }
3565 
3566 sal_Bool PopupMenu::IsInExecute()
3567 {
3568     return GetActivePopupMenu() ? sal_True : sal_False;
3569 }
3570 
3571 PopupMenu* PopupMenu::GetActivePopupMenu()
3572 {
3573     ImplSVData* pSVData = ImplGetSVData();
3574     return pSVData->maAppData.mpActivePopupMenu;
3575 }
3576 
3577 void PopupMenu::EndExecute( sal_uInt16 nSelectId )
3578 {
3579     if ( ImplGetWindow() )
3580         ImplGetFloatingWindow()->EndExecute( nSelectId );
3581 }
3582 
3583 void PopupMenu::SelectEntry( sal_uInt16 nId )
3584 {
3585     if ( ImplGetWindow() )
3586     {
3587         if( nId != ITEMPOS_INVALID )
3588         {
3589 	        sal_uInt16 nPos;
3590 		    MenuItemData* pData = GetItemList()->GetData( nId, nPos );
3591             if ( pData->pSubMenu )
3592                 ImplGetFloatingWindow()->ChangeHighlightItem( nPos, sal_True );
3593             else
3594                 ImplGetFloatingWindow()->EndExecute( nId );
3595         }
3596         else
3597         {
3598 			MenuFloatingWindow* pFloat = ImplGetFloatingWindow();
3599 	        pFloat->GrabFocus();
3600 			sal_uInt16 nPos;
3601 			for( nPos = 0; nPos < GetItemList()->Count(); nPos++ )
3602 			{
3603 				MenuItemData* pData = (MenuItemData*)GetItemList()->GetObject( nPos );
3604 				if( pData->pSubMenu )
3605 				{
3606 					pFloat->KillActivePopup();
3607 				}
3608 			}
3609             pFloat->ChangeHighlightItem( ITEMPOS_INVALID, sal_False );
3610         }
3611     }
3612 }
3613 
3614 void PopupMenu::SetSelectedEntry( sal_uInt16 nId )
3615 {
3616     nSelectedId = nId;
3617 }
3618 
3619 sal_uInt16 PopupMenu::Execute( Window* pExecWindow, const Point& rPopupPos )
3620 {
3621     return Execute( pExecWindow, Rectangle( rPopupPos, rPopupPos ), POPUPMENU_EXECUTE_DOWN );
3622 }
3623 
3624 sal_uInt16 PopupMenu::Execute( Window* pExecWindow, const Rectangle& rRect, sal_uInt16 nFlags )
3625 {
3626     ENSURE_OR_RETURN( pExecWindow, "PopupMenu::Execute: need a non-NULL window!", 0 );
3627 
3628 
3629     sal_uLong nPopupModeFlags = 0;
3630     if ( nFlags & POPUPMENU_EXECUTE_DOWN )
3631         nPopupModeFlags = FLOATWIN_POPUPMODE_DOWN;
3632     else if ( nFlags & POPUPMENU_EXECUTE_UP )
3633         nPopupModeFlags = FLOATWIN_POPUPMODE_UP;
3634     else if ( nFlags & POPUPMENU_EXECUTE_LEFT )
3635         nPopupModeFlags = FLOATWIN_POPUPMODE_LEFT;
3636     else if ( nFlags & POPUPMENU_EXECUTE_RIGHT )
3637         nPopupModeFlags = FLOATWIN_POPUPMODE_RIGHT;
3638     else
3639         nPopupModeFlags = FLOATWIN_POPUPMODE_DOWN;
3640 
3641     if (nFlags & POPUPMENU_NOMOUSEUPCLOSE )                      // allow popup menus to stay open on mouse button up
3642         nPopupModeFlags |= FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE;    // useful if the menu was opened on mousebutton down (eg toolbox configuration)
3643 
3644     return ImplExecute( pExecWindow, rRect, nPopupModeFlags, 0, sal_False );
3645 }
3646 
3647 sal_uInt16 PopupMenu::ImplExecute( Window* pW, const Rectangle& rRect, sal_uLong nPopupModeFlags, Menu* pSFrom, sal_Bool bPreSelectFirst )
3648 {
3649     if ( !pSFrom && ( PopupMenu::IsInExecute() || !GetItemCount() ) )
3650         return 0;
3651 
3652     delete mpLayoutData, mpLayoutData = NULL;
3653 
3654     ImplSVData* pSVData = ImplGetSVData();
3655 
3656     pStartedFrom = pSFrom;
3657     nSelectedId = 0;
3658     bCanceled = sal_False;
3659 
3660     sal_uLong nFocusId = 0;
3661     sal_Bool bRealExecute = sal_False;
3662     if ( !pStartedFrom )
3663     {
3664         pSVData->maWinData.mbNoDeactivate = sal_True;
3665         nFocusId = Window::SaveFocus();
3666         bRealExecute = sal_True;
3667     }
3668     else
3669     {
3670         // assure that only one menu is open at a time
3671         if( pStartedFrom->bIsMenuBar && pSVData->maWinData.mpFirstFloat )
3672             pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
3673     }
3674 
3675     DBG_ASSERT( !ImplGetWindow(), "Win?!" );
3676     Rectangle aRect( rRect );
3677     aRect.SetPos( pW->OutputToScreenPixel( aRect.TopLeft() ) );
3678 
3679     WinBits nStyle = WB_BORDER;
3680     if ( bRealExecute )
3681         nPopupModeFlags |= FLOATWIN_POPUPMODE_NEWLEVEL;
3682     if ( !pStartedFrom || !pStartedFrom->bIsMenuBar )
3683         nPopupModeFlags |= FLOATWIN_POPUPMODE_PATHMOUSECANCELCLICK | FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE;
3684 
3685     nPopupModeFlags |= FLOATWIN_POPUPMODE_NOKEYCLOSE;
3686 
3687     // Kann beim Debuggen hilfreich sein.
3688     // nPopupModeFlags |= FLOATWIN_POPUPMODE_NOFOCUSCLOSE;
3689 
3690     ImplDelData aDelData;
3691     pW->ImplAddDel( &aDelData );
3692 
3693     bInCallback = sal_True; // hier schon setzen, falls Activate ueberladen
3694     Activate();
3695     bInCallback = sal_False;
3696 
3697     if ( aDelData.IsDelete() )
3698         return 0;   // Error
3699 
3700     pW->ImplRemoveDel( &aDelData );
3701 
3702     if ( bCanceled || bKilled )
3703         return 0;
3704 
3705     if ( !GetItemCount() )
3706         return 0;
3707 
3708     // Das Flag MENU_FLAG_HIDEDISABLEDENTRIES wird vererbt.
3709     if ( pSFrom )
3710     {
3711         if ( pSFrom->nMenuFlags & MENU_FLAG_HIDEDISABLEDENTRIES )
3712             nMenuFlags |= MENU_FLAG_HIDEDISABLEDENTRIES;
3713         else
3714             nMenuFlags &= ~MENU_FLAG_HIDEDISABLEDENTRIES;
3715     }
3716     else
3717         // #102790# context menues shall never show disabled entries
3718         nMenuFlags |= MENU_FLAG_HIDEDISABLEDENTRIES;
3719 
3720 
3721     sal_uInt16 nVisibleEntries = ImplGetVisibleItemCount();
3722     if ( !nVisibleEntries )
3723     {
3724         ResMgr* pResMgr = ImplGetResMgr();
3725         if( pResMgr )
3726         {
3727             String aTmpEntryText( ResId( SV_RESID_STRING_NOSELECTIONPOSSIBLE, *pResMgr ) );
3728             MenuItemData* pData = pItemList->Insert(
3729                 0xFFFF, MENUITEM_STRING, 0, aTmpEntryText, Image(), NULL, 0xFFFF );
3730                 pData->bIsTemporary = sal_True;
3731         }
3732     }
3733     else if ( Application::GetSettings().GetStyleSettings().GetAutoMnemonic() && !( nMenuFlags & MENU_FLAG_NOAUTOMNEMONICS ) )
3734     {
3735         CreateAutoMnemonics();
3736     }
3737 
3738     MenuFloatingWindow* pWin = new MenuFloatingWindow( this, pW, nStyle | WB_SYSTEMWINDOW );
3739     if( pSVData->maNWFData.mbFlatMenu )
3740         pWin->SetBorderStyle( WINDOW_BORDER_NOBORDER );
3741     else
3742         pWin->SetBorderStyle( pWin->GetBorderStyle() | WINDOW_BORDER_MENU );
3743     pWindow = pWin;
3744 
3745     Size aSz = ImplCalcSize( pWin );
3746 
3747     long nMaxHeight = pWin->GetDesktopRectPixel().GetHeight();
3748     if( Application::GetScreenCount() > 1 && ! Application::IsMultiDisplay() )
3749     {
3750         Window* pDeskW = pWindow->GetWindow( WINDOW_REALPARENT );
3751         if( ! pDeskW )
3752             pDeskW = pWindow;
3753         Point aDesktopTL( pDeskW->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) );
3754         nMaxHeight = Application::GetWorkAreaPosSizePixel(
3755             Application::GetBestScreen( Rectangle( aDesktopTL, aRect.GetSize() ) )
3756             ).GetHeight();
3757     }
3758     if ( pStartedFrom && pStartedFrom->bIsMenuBar )
3759         nMaxHeight -= pW->GetSizePixel().Height();
3760     sal_Int32 nLeft, nTop, nRight, nBottom;
3761     pWindow->GetBorder( nLeft, nTop, nRight, nBottom );
3762     nMaxHeight -= nTop+nBottom;
3763     if ( aSz.Height() > nMaxHeight )
3764     {
3765         pWin->EnableScrollMenu( sal_True );
3766         sal_uInt16 nStart = ImplGetFirstVisible();
3767         sal_uInt16 nEntries = ImplCalcVisEntries( nMaxHeight, nStart );
3768         aSz.Height() = ImplCalcHeight( nEntries );
3769     }
3770 
3771     pWin->SetFocusId( nFocusId );
3772     pWin->SetOutputSizePixel( aSz );
3773     // #102158# menus must never grab the focus, otherwise
3774     // they will be closed immediately
3775     // from now on focus grabbing is only prohibited automatically if
3776     // FLOATWIN_POPUPMODE_GRABFOCUS was set (which is done below), because some
3777     // floaters (like floating toolboxes) may grab the focus
3778     // pWin->GrabFocus();
3779     if ( GetItemCount() )
3780     {
3781         SalMenu* pMenu = ImplGetSalMenu();
3782         if( pMenu && bRealExecute && pMenu->ShowNativePopupMenu( pWin, aRect, nPopupModeFlags | FLOATWIN_POPUPMODE_GRABFOCUS ) )
3783         {
3784             pWin->StopExecute(0);
3785             pWin->doShutdown();
3786             pWindow->doLazyDelete();
3787             pWindow = NULL;
3788             return nSelectedId;
3789         }
3790         else
3791         {
3792             pWin->StartPopupMode( aRect, nPopupModeFlags | FLOATWIN_POPUPMODE_GRABFOCUS );
3793         }
3794         if( pSFrom )
3795         {
3796             sal_uInt16 aPos;
3797             if( pSFrom->bIsMenuBar )
3798                 aPos = ((MenuBarWindow *) pSFrom->pWindow)->GetHighlightedItem();
3799             else
3800                 aPos = ((MenuFloatingWindow *) pSFrom->pWindow)->GetHighlightedItem();
3801 
3802             pWin->SetPosInParent( aPos );  // store position to be sent in SUBMENUDEACTIVATE
3803             pSFrom->ImplCallEventListeners( VCLEVENT_MENU_SUBMENUACTIVATE, aPos );
3804         }
3805     }
3806     if ( bPreSelectFirst )
3807     {
3808         sal_uInt16 nCount = (sal_uInt16)pItemList->Count();
3809         for ( sal_uInt16 n = 0; n < nCount; n++ )
3810         {
3811             MenuItemData* pData = pItemList->GetDataFromPos( n );
3812             if (   ( pData->bEnabled || !Application::GetSettings().GetStyleSettings().GetSkipDisabledInMenus() )
3813                 && ( pData->eType != MENUITEM_SEPARATOR ) && ImplIsVisible( n ) && ImplIsSelectable( n ) )
3814             {
3815                 pWin->ChangeHighlightItem( n, sal_False );
3816                 break;
3817             }
3818         }
3819     }
3820     if ( bRealExecute )
3821     {
3822         pWin->ImplAddDel( &aDelData );
3823 
3824         ImplDelData aModalWinDel;
3825         pW->ImplAddDel( &aModalWinDel );
3826         pW->ImplIncModalCount();
3827 
3828         pWin->Execute();
3829 
3830         DBG_ASSERT( ! aModalWinDel.IsDead(), "window for popup died, modal count incorrect !" );
3831         if( ! aModalWinDel.IsDead() )
3832             pW->ImplDecModalCount();
3833 
3834         if ( !aDelData.IsDelete() )
3835             pWin->ImplRemoveDel( &aDelData );
3836         else
3837             return 0;
3838 
3839         // Focus wieder herstellen (kann schon im Select wieder
3840         // hergestellt wurden sein
3841         nFocusId = pWin->GetFocusId();
3842         if ( nFocusId )
3843         {
3844             pWin->SetFocusId( 0 );
3845             pSVData->maWinData.mbNoDeactivate = sal_False;
3846         }
3847         pWin->ImplEndPopupMode( 0, nFocusId );
3848 
3849         if ( nSelectedId )  // Dann abraeumen... ( sonst macht TH das )
3850         {
3851             PopupMenu* pSub = pWin->GetActivePopup();
3852             while ( pSub )
3853             {
3854                 pSub->ImplGetFloatingWindow()->EndPopupMode();
3855                 pSub = pSub->ImplGetFloatingWindow()->GetActivePopup();
3856             }
3857         }
3858         pWin->doShutdown();
3859         pWindow->doLazyDelete();
3860         pWindow = NULL;
3861 
3862         // Steht noch ein Select aus?
3863         Menu* pSelect = ImplFindSelectMenu();
3864         if ( pSelect )
3865         {
3866             // Beim Popup-Menu muss das Select vor dem Verlassen von Execute gerufen werden!
3867             Application::RemoveUserEvent( pSelect->nEventId );
3868             pSelect->nEventId = 0;
3869             pSelect->Select();
3870         }
3871     }
3872 
3873     return bRealExecute ? nSelectedId : 0;
3874 }
3875 
3876 sal_uInt16 PopupMenu::ImplCalcVisEntries( long nMaxHeight, sal_uInt16 nStartEntry, sal_uInt16* pLastVisible ) const
3877 {
3878     nMaxHeight -= 2 * ImplGetFloatingWindow()->GetScrollerHeight();
3879 
3880     long nHeight = 0;
3881     sal_uInt16 nEntries = (sal_uInt16) pItemList->Count();
3882     sal_uInt16 nVisEntries = 0;
3883 
3884     if ( pLastVisible )
3885         *pLastVisible = 0;
3886 
3887     for ( sal_uInt16 n = nStartEntry; n < nEntries; n++ )
3888     {
3889         if ( ImplIsVisible( n ) )
3890         {
3891             MenuItemData* pData = pItemList->GetDataFromPos( n );
3892             nHeight += pData->aSz.Height();
3893             if ( nHeight > nMaxHeight )
3894                 break;
3895 
3896             if ( pLastVisible )
3897                 *pLastVisible = n;
3898             nVisEntries++;
3899         }
3900     }
3901     return nVisEntries;
3902 }
3903 
3904 long PopupMenu::ImplCalcHeight( sal_uInt16 nEntries ) const
3905 {
3906     long nHeight = 0;
3907 
3908     sal_uInt16 nFound = 0;
3909     for ( sal_uInt16 n = 0; ( nFound < nEntries ) && ( n < pItemList->Count() ); n++ )
3910     {
3911         if ( ImplIsVisible( (sal_uInt16) n ) )
3912         {
3913             MenuItemData* pData = pItemList->GetDataFromPos( n );
3914             nHeight += pData->aSz.Height();
3915             nFound++;
3916         }
3917     }
3918 
3919     nHeight += 2*ImplGetFloatingWindow()->GetScrollerHeight();
3920 
3921     return nHeight;
3922 }
3923 
3924 
3925 static void ImplInitMenuWindow( Window* pWin, sal_Bool bFont, sal_Bool bMenuBar )
3926 {
3927     const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
3928 
3929     if ( bFont )
3930         pWin->SetPointFont( rStyleSettings.GetMenuFont() );
3931     if( bMenuBar )
3932     {
3933         if( pWin->IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
3934         {
3935             pWin->SetBackground();  // background will be drawn by NWF
3936         }
3937         else
3938         {
3939             Wallpaper aWallpaper;
3940             aWallpaper.SetStyle( WALLPAPER_APPLICATIONGRADIENT );
3941             pWin->SetBackground( aWallpaper );
3942             pWin->SetPaintTransparent( sal_False );
3943             pWin->SetParentClipMode( 0 );
3944         }
3945     }
3946     else
3947     {
3948         if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) )
3949         {
3950             pWin->SetBackground();  // background will be drawn by NWF
3951         }
3952         else
3953             pWin->SetBackground( Wallpaper( rStyleSettings.GetMenuColor() ) );
3954     }
3955 
3956     if ( bMenuBar )
3957         pWin->SetTextColor( rStyleSettings.GetMenuBarTextColor() );
3958     else
3959         pWin->SetTextColor( rStyleSettings.GetMenuTextColor() );
3960     pWin->SetTextFillColor();
3961     pWin->SetLineColor();
3962 }
3963 
3964 MenuFloatingWindow::MenuFloatingWindow( Menu* pMen, Window* pParent, WinBits nStyle ) :
3965     FloatingWindow( pParent, nStyle )
3966 {
3967     mpWindowImpl->mbMenuFloatingWindow= sal_True;
3968     pMenu               = pMen;
3969     pActivePopup        = 0;
3970     nSaveFocusId        = 0;
3971     bInExecute          = sal_False;
3972     bScrollMenu         = sal_False;
3973     nHighlightedItem    = ITEMPOS_INVALID;
3974     nMBDownPos          = ITEMPOS_INVALID;
3975     nPosInParent        = ITEMPOS_INVALID;
3976     nScrollerHeight     = 0;
3977 //    nStartY             = 0;
3978     nBorder             = EXTRASPACEY;
3979     nFirstEntry         = 0;
3980     bScrollUp           = sal_False;
3981     bScrollDown         = sal_False;
3982     bIgnoreFirstMove    = sal_True;
3983     bKeyInput           = sal_False;
3984 
3985     EnableSaveBackground();
3986     ImplInitMenuWindow( this, sal_True, sal_False );
3987 
3988     SetPopupModeEndHdl( LINK( this, MenuFloatingWindow, PopupEnd ) );
3989 
3990     aHighlightChangedTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, HighlightChanged ) );
3991 	aHighlightChangedTimer.SetTimeout( GetSettings().GetMouseSettings().GetMenuDelay() );
3992 	aSubmenuCloseTimer.SetTimeout( GetSettings().GetMouseSettings().GetMenuDelay() );
3993     aSubmenuCloseTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, SubmenuClose ) );
3994     aScrollTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, AutoScroll ) );
3995 
3996     AddEventListener( LINK( this, MenuFloatingWindow, ShowHideListener ) );
3997 }
3998 
3999 void MenuFloatingWindow::doShutdown()
4000 {
4001     if( pMenu )
4002     {
4003         // #105373# notify toolkit that highlight was removed
4004         // otherwise the entry will not be read when the menu is opened again
4005         if( nHighlightedItem != ITEMPOS_INVALID )
4006             pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
4007 
4008         if( !bKeyInput && pMenu && pMenu->pStartedFrom && !pMenu->pStartedFrom->bIsMenuBar )
4009         {
4010             // #102461# remove highlight in parent
4011             MenuItemData* pData;
4012             sal_uInt16 i, nCount = (sal_uInt16)pMenu->pStartedFrom->pItemList->Count();
4013             for(i = 0; i < nCount; i++)
4014             {
4015                 pData = pMenu->pStartedFrom->pItemList->GetDataFromPos( i );
4016                 if( pData && ( pData->pSubMenu == pMenu ) )
4017                     break;
4018             }
4019             if( i < nCount )
4020             {
4021                 MenuFloatingWindow* pPWin = (MenuFloatingWindow*)pMenu->pStartedFrom->ImplGetWindow();
4022                 if( pPWin )
4023                     pPWin->HighlightItem( i, sal_False );
4024             }
4025         }
4026 
4027         // free the reference to the accessible component
4028         SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >() );
4029 
4030         aHighlightChangedTimer.Stop();
4031 
4032         // #95056# invalidate screen area covered by system window
4033         // so this can be taken into account if the commandhandler performs a scroll operation
4034         if( GetParent() )
4035         {
4036             Rectangle aInvRect( GetWindowExtentsRelative( GetParent() ) );
4037             GetParent()->Invalidate( aInvRect );
4038         }
4039         pMenu = NULL;
4040         RemoveEventListener( LINK( this, MenuFloatingWindow, ShowHideListener ) );
4041     }
4042 }
4043 
4044 MenuFloatingWindow::~MenuFloatingWindow()
4045 {
4046     doShutdown();
4047 }
4048 
4049 void MenuFloatingWindow::Resize()
4050 {
4051     ImplInitClipRegion();
4052 }
4053 
4054 long MenuFloatingWindow::ImplGetStartY() const
4055 {
4056     long nY = 0;
4057     if( pMenu )
4058     {
4059         for ( sal_uInt16 n = 0; n < nFirstEntry; n++ )
4060             nY += pMenu->GetItemList()->GetDataFromPos( n )->aSz.Height();
4061     }
4062     return -nY;
4063 }
4064 
4065 Region MenuFloatingWindow::ImplCalcClipRegion( sal_Bool bIncludeLogo ) const
4066 {
4067     Size aOutSz = GetOutputSizePixel();
4068     Point aPos;
4069     Rectangle aRect( aPos, aOutSz );
4070     aRect.Top() += nScrollerHeight;
4071     aRect.Bottom() -= nScrollerHeight;
4072 
4073     if ( pMenu && pMenu->pLogo && !bIncludeLogo )
4074         aRect.Left() += pMenu->pLogo->aBitmap.GetSizePixel().Width();
4075 
4076     Region aRegion = aRect;
4077     if ( pMenu && pMenu->pLogo && bIncludeLogo && nScrollerHeight )
4078         aRegion.Union( Rectangle( Point(), Size( pMenu->pLogo->aBitmap.GetSizePixel().Width(), aOutSz.Height() ) ) );
4079 
4080     return aRegion;
4081 }
4082 
4083 void MenuFloatingWindow::ImplInitClipRegion()
4084 {
4085     if ( IsScrollMenu() )
4086     {
4087         SetClipRegion( ImplCalcClipRegion() );
4088     }
4089     else
4090     {
4091         SetClipRegion();
4092     }
4093 }
4094 
4095 void MenuFloatingWindow::ImplHighlightItem( const MouseEvent& rMEvt, sal_Bool bMBDown )
4096 {
4097     if( ! pMenu )
4098         return;
4099 
4100     long nY = nScrollerHeight;
4101     long nMouseY = rMEvt.GetPosPixel().Y();
4102     Size aOutSz = GetOutputSizePixel();
4103     if ( ( nMouseY >= nY ) && ( nMouseY < ( aOutSz.Height() - nY ) ) )
4104     {
4105         sal_Bool bHighlighted = sal_False;
4106         sal_uInt16 nCount = (sal_uInt16)pMenu->pItemList->Count();
4107         nY += ImplGetStartY();  // ggf. gescrollt.
4108         for ( sal_uInt16 n = 0; !bHighlighted && ( n < nCount ); n++ )
4109         {
4110             if ( pMenu->ImplIsVisible( n ) )
4111             {
4112                 MenuItemData* pItemData = pMenu->pItemList->GetDataFromPos( n );
4113                 long nOldY = nY;
4114                 nY += pItemData->aSz.Height();
4115                 if ( ( nOldY <= nMouseY ) && ( nY > nMouseY ) && pMenu->ImplIsSelectable( n ) )
4116                 {
4117                     sal_Bool bPopupArea = sal_True;
4118                     if ( pItemData->nBits & MIB_POPUPSELECT )
4119                     {
4120                         // Nur wenn ueber dem Pfeil geklickt wurde...
4121                         Size aSz = GetOutputSizePixel();
4122                         long nFontHeight = GetTextHeight();
4123                         bPopupArea = ( rMEvt.GetPosPixel().X() >= ( aSz.Width() - nFontHeight - nFontHeight/4 ) );
4124                     }
4125 
4126                     if ( bMBDown )
4127                     {
4128                         if ( n != nHighlightedItem )
4129                         {
4130                             ChangeHighlightItem( (sal_uInt16)n, sal_False );
4131                         }
4132 
4133                         sal_Bool bAllowNewPopup = sal_True;
4134                         if ( pActivePopup )
4135                         {
4136                             MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
4137                             bAllowNewPopup = pData && ( pData->pSubMenu != pActivePopup );
4138                             if ( bAllowNewPopup )
4139                                 KillActivePopup();
4140                         }
4141 
4142                         if ( bPopupArea && bAllowNewPopup )
4143                         {
4144                             HighlightChanged( NULL );
4145                         }
4146                     }
4147                     else
4148                     {
4149                         if ( n != nHighlightedItem )
4150                         {
4151                             ChangeHighlightItem( (sal_uInt16)n, sal_True );
4152                         }
4153                         else if ( pItemData->nBits & MIB_POPUPSELECT )
4154                         {
4155                             if ( bPopupArea && ( pActivePopup != pItemData->pSubMenu ) )
4156                                 HighlightChanged( NULL );
4157                         }
4158                     }
4159                     bHighlighted = sal_True;
4160                 }
4161             }
4162         }
4163         if ( !bHighlighted )
4164             ChangeHighlightItem( ITEMPOS_INVALID, sal_True );
4165     }
4166     else
4167     {
4168         ImplScroll( rMEvt.GetPosPixel() );
4169         ChangeHighlightItem( ITEMPOS_INVALID, sal_True );
4170     }
4171 }
4172 
4173 IMPL_LINK( MenuFloatingWindow, PopupEnd, FloatingWindow*, EMPTYARG )
4174 {
4175     // "this" will be deleted before the end of this method!
4176     Menu* pM = pMenu;
4177     if ( bInExecute )
4178     {
4179         if ( pActivePopup )
4180         {
4181             //DBG_ASSERT( !pActivePopup->ImplGetWindow(), "PopupEnd, obwohl pActivePopup MIT Window!" );
4182             KillActivePopup(); // should be ok to just remove it
4183             //pActivePopup->bCanceled = sal_True;
4184         }
4185         bInExecute = sal_False;
4186         pMenu->bInCallback = sal_True;
4187         pMenu->Deactivate();
4188         pMenu->bInCallback = sal_False;
4189     }
4190     else
4191     {
4192         if( pMenu )
4193         {
4194             // Wenn dies Fenster von TH geschlossen wurde, hat noch ein anderes
4195             // Menu dieses Fenster als pActivePopup.
4196             if ( pMenu->pStartedFrom )
4197             {
4198                 // Das pWin am 'Parent' kann aber schon 0 sein, falls die Kette von
4199                 // vorne abgeraeumt wurde und jetzt die EndPopup-Events eintrudeln
4200                 if ( pMenu->pStartedFrom->bIsMenuBar )
4201                 {
4202                     MenuBarWindow* p = (MenuBarWindow*) pMenu->pStartedFrom->ImplGetWindow();
4203                     if ( p )
4204                         p->PopupClosed( pMenu );
4205                 }
4206                 else
4207                 {
4208                     MenuFloatingWindow* p = (MenuFloatingWindow*) pMenu->pStartedFrom->ImplGetWindow();
4209                     if ( p )
4210                         p->KillActivePopup( (PopupMenu*)pMenu );
4211                 }
4212             }
4213         }
4214     }
4215 
4216     if ( pM )
4217         pM->pStartedFrom = 0;
4218 
4219     return 0;
4220 }
4221 
4222 IMPL_LINK( MenuFloatingWindow, AutoScroll, Timer*, EMPTYARG )
4223 {
4224     ImplScroll( GetPointerPosPixel() );
4225     return 1;
4226 }
4227 
4228 IMPL_LINK( MenuFloatingWindow, HighlightChanged, Timer*, pTimer )
4229 {
4230     if( ! pMenu )
4231         return 0;
4232 
4233     MenuItemData* pItemData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
4234     if ( pItemData )
4235     {
4236         if ( pActivePopup && ( pActivePopup != pItemData->pSubMenu ) )
4237         {
4238             sal_uLong nOldFlags = GetPopupModeFlags();
4239             SetPopupModeFlags( GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE );
4240             KillActivePopup();
4241             SetPopupModeFlags( nOldFlags );
4242         }
4243         if ( pItemData->bEnabled && pItemData->pSubMenu && pItemData->pSubMenu->GetItemCount() && ( pItemData->pSubMenu != pActivePopup ) )
4244         {
4245             pActivePopup = (PopupMenu*)pItemData->pSubMenu;
4246             long nY = nScrollerHeight+ImplGetStartY();
4247             MenuItemData* pData = 0;
4248             for ( sal_uLong n = 0; n < nHighlightedItem; n++ )
4249             {
4250                 pData = pMenu->pItemList->GetDataFromPos( n );
4251                 nY += pData->aSz.Height();
4252             }
4253             pData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
4254             Size MySize = GetOutputSizePixel();
4255 //          Point MyPos = GetPosPixel();
4256 //          Point aItemTopLeft( MyPos.X(), MyPos.Y()+nY );
4257             Point aItemTopLeft( 0, nY );
4258             Point aItemBottomRight( aItemTopLeft );
4259             aItemBottomRight.X() += MySize.Width();
4260             aItemBottomRight.Y() += pData->aSz.Height();
4261 
4262             // Popups leicht versetzen:
4263             aItemTopLeft.X() += 2;
4264             aItemBottomRight.X() -= 2;
4265             if ( nHighlightedItem )
4266                 aItemTopLeft.Y() -= 2;
4267             else
4268             {
4269                 sal_Int32 nL, nT, nR, nB;
4270                 GetBorder( nL, nT, nR, nB );
4271                 aItemTopLeft.Y() -= nT;
4272             }
4273 
4274             // pTest: Wegen Abstuerzen durch Reschedule() im Aufruf von Activate()
4275             // Ausserdem wird damit auch verhindert, dass SubMenus angezeigt werden,
4276             // die lange im Activate Rescheduled haben und jetzt schon nicht mehr
4277             // angezeigt werden sollen.
4278             Menu* pTest = pActivePopup;
4279             sal_uLong nOldFlags = GetPopupModeFlags();
4280             SetPopupModeFlags( GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE );
4281             sal_uInt16 nRet = pActivePopup->ImplExecute( this, Rectangle( aItemTopLeft, aItemBottomRight ), FLOATWIN_POPUPMODE_RIGHT, pMenu, pTimer ? sal_False : sal_True  );
4282             SetPopupModeFlags( nOldFlags );
4283 
4284             // nRet != 0, wenn es waerend Activate() abgeschossen wurde...
4285             if ( !nRet && ( pActivePopup == pTest ) && pActivePopup->ImplGetWindow() )
4286                 pActivePopup->ImplGetFloatingWindow()->AddPopupModeWindow( this );
4287         }
4288     }
4289 
4290     return 0;
4291 }
4292 
4293 IMPL_LINK( MenuFloatingWindow, SubmenuClose, Timer*, EMPTYARG )
4294 {
4295     if( pMenu && pMenu->pStartedFrom )
4296     {
4297         MenuFloatingWindow* pWin = (MenuFloatingWindow*) pMenu->pStartedFrom->GetWindow();
4298         if( pWin )
4299             pWin->KillActivePopup();
4300     }
4301     return 0;
4302 }
4303 
4304 IMPL_LINK( MenuFloatingWindow, ShowHideListener, VclWindowEvent*, pEvent )
4305 {
4306     if( ! pMenu )
4307         return 0;
4308 
4309     if( pEvent->GetId() == VCLEVENT_WINDOW_SHOW )
4310         pMenu->ImplCallEventListeners( VCLEVENT_MENU_SHOW, ITEMPOS_INVALID );
4311     else if( pEvent->GetId() == VCLEVENT_WINDOW_HIDE )
4312         pMenu->ImplCallEventListeners( VCLEVENT_MENU_HIDE, ITEMPOS_INVALID );
4313     return 0;
4314 }
4315 
4316 void MenuFloatingWindow::EnableScrollMenu( sal_Bool b )
4317 {
4318     bScrollMenu = b;
4319     nScrollerHeight = b ? (sal_uInt16) GetSettings().GetStyleSettings().GetScrollBarSize() /2 : 0;
4320     bScrollDown = sal_True;
4321     ImplInitClipRegion();
4322 }
4323 
4324 void MenuFloatingWindow::Execute()
4325 {
4326     ImplSVData* pSVData = ImplGetSVData();
4327 
4328     pSVData->maAppData.mpActivePopupMenu = (PopupMenu*)pMenu;
4329 
4330     bInExecute = sal_True;
4331 //  bCallingSelect = sal_False;
4332 
4333     while ( bInExecute )
4334         Application::Yield();
4335 
4336     pSVData->maAppData.mpActivePopupMenu = NULL;
4337 
4338 //  while ( bCallingSelect )
4339 //      Application::Yield();
4340 }
4341 
4342 void MenuFloatingWindow::StopExecute( sal_uLong nFocusId )
4343 {
4344     // Focus wieder herstellen
4345     // (kann schon im Select wieder hergestellt wurden sein)
4346     if ( nSaveFocusId )
4347     {
4348         Window::EndSaveFocus( nFocusId, sal_False );
4349         nFocusId = nSaveFocusId;
4350         if ( nFocusId )
4351         {
4352             nSaveFocusId = 0;
4353             ImplGetSVData()->maWinData.mbNoDeactivate = sal_False;
4354         }
4355     }
4356     ImplEndPopupMode( 0, nFocusId );
4357 
4358     aHighlightChangedTimer.Stop();
4359     bInExecute = sal_False;
4360     if ( pActivePopup )
4361     {
4362         KillActivePopup();
4363     }
4364     // notify parent, needed for accessibility
4365     if( pMenu && pMenu->pStartedFrom )
4366         pMenu->pStartedFrom->ImplCallEventListeners( VCLEVENT_MENU_SUBMENUDEACTIVATE, nPosInParent );
4367 }
4368 
4369 void MenuFloatingWindow::KillActivePopup( PopupMenu* pThisOnly )
4370 {
4371     if ( pActivePopup && ( !pThisOnly || ( pThisOnly == pActivePopup ) ) )
4372     {
4373         if( pActivePopup->pWindow != NULL )
4374             if( ((FloatingWindow *) pActivePopup->pWindow)->IsInCleanUp() )
4375                 return; // kill it later
4376         if ( pActivePopup->bInCallback )
4377             pActivePopup->bCanceled = sal_True;
4378 
4379         // Vor allen Aktionen schon pActivePopup = 0, falls z.B.
4380         // PopupModeEndHdl des zu zerstoerenden Popups mal synchron gerufen wird.
4381         PopupMenu* pPopup = pActivePopup;
4382         pActivePopup = NULL;
4383         pPopup->bInCallback = sal_True;
4384         pPopup->Deactivate();
4385         pPopup->bInCallback = sal_False;
4386         if ( pPopup->ImplGetWindow() )
4387         {
4388             pPopup->ImplGetFloatingWindow()->StopExecute();
4389             pPopup->ImplGetFloatingWindow()->doShutdown();
4390             pPopup->pWindow->doLazyDelete();
4391             pPopup->pWindow = NULL;
4392 
4393             Update();
4394         }
4395     }
4396 }
4397 
4398 void MenuFloatingWindow::EndExecute()
4399 {
4400     Menu* pStart = pMenu ? pMenu->ImplGetStartMenu() : NULL;
4401     sal_uLong nFocusId = 0;
4402     if ( pStart && pStart->bIsMenuBar )
4403     {
4404         nFocusId = ((MenuBarWindow*)((MenuBar*)pStart)->ImplGetWindow())->GetFocusId();
4405         if ( nFocusId )
4406         {
4407             ((MenuBarWindow*)((MenuBar*)pStart)->ImplGetWindow())->SetFocusId( 0 );
4408             ImplGetSVData()->maWinData.mbNoDeactivate = sal_False;
4409         }
4410     }
4411 
4412     // Wenn von woanders gestartet, dann ab dort aufraumen:
4413     MenuFloatingWindow* pCleanUpFrom = this;
4414     MenuFloatingWindow* pWin = this;
4415     while ( pWin && !pWin->bInExecute &&
4416         pWin->pMenu->pStartedFrom && !pWin->pMenu->pStartedFrom->bIsMenuBar )
4417     {
4418         pWin = ((PopupMenu*)pWin->pMenu->pStartedFrom)->ImplGetFloatingWindow();
4419     }
4420     if ( pWin )
4421         pCleanUpFrom = pWin;
4422 
4423     // Dies Fenster wird gleich zerstoert => Daten lokal merken...
4424     Menu* pM = pMenu;
4425     sal_uInt16 nItem = nHighlightedItem;
4426 
4427     pCleanUpFrom->StopExecute( nFocusId );
4428 
4429     if ( nItem != ITEMPOS_INVALID && pM )
4430     {
4431         MenuItemData* pItemData = pM->GetItemList()->GetDataFromPos( nItem );
4432         if ( pItemData && !pItemData->bIsTemporary )
4433         {
4434             pM->nSelectedId = pItemData->nId;
4435             if ( pStart )
4436                 pStart->nSelectedId = pItemData->nId;
4437 
4438             pM->ImplSelect();
4439         }
4440     }
4441 }
4442 
4443 void MenuFloatingWindow::EndExecute( sal_uInt16 nId )
4444 {
4445     sal_uInt16 nPos;
4446     if ( pMenu && pMenu->GetItemList()->GetData( nId, nPos ) )
4447         nHighlightedItem = nPos;
4448     else
4449         nHighlightedItem = ITEMPOS_INVALID;
4450 
4451     EndExecute();
4452 }
4453 
4454 void MenuFloatingWindow::MouseButtonDown( const MouseEvent& rMEvt )
4455 {
4456     // TH macht ein ToTop auf dieses Fenster, aber das aktive Popup
4457     // soll oben bleiben...
4458     // due to focus chage this would close all menues -> don't do it (#94123)
4459     //if ( pActivePopup && pActivePopup->ImplGetWindow() && !pActivePopup->ImplGetFloatingWindow()->pActivePopup )
4460     //    pActivePopup->ImplGetFloatingWindow()->ToTop( TOTOP_NOGRABFOCUS );
4461 
4462     ImplHighlightItem( rMEvt, sal_True );
4463 
4464     nMBDownPos = nHighlightedItem;
4465 }
4466 
4467 void MenuFloatingWindow::MouseButtonUp( const MouseEvent& rMEvt )
4468 {
4469     MenuItemData* pData = pMenu ? pMenu->GetItemList()->GetDataFromPos( nHighlightedItem ) : NULL;
4470     // nMBDownPos in lokaler Variable merken und gleich zuruecksetzen,
4471     // weil nach EndExecute zu spaet
4472     sal_uInt16 _nMBDownPos = nMBDownPos;
4473     nMBDownPos = ITEMPOS_INVALID;
4474     if ( pData && pData->bEnabled && ( pData->eType != MENUITEM_SEPARATOR ) )
4475     {
4476         if ( !pData->pSubMenu )
4477         {
4478             EndExecute();
4479         }
4480         else if ( ( pData->nBits & MIB_POPUPSELECT ) && ( nHighlightedItem == _nMBDownPos ) && ( rMEvt.GetClicks() == 2 ) )
4481         {
4482             // Nicht wenn ueber dem Pfeil geklickt wurde...
4483             Size aSz = GetOutputSizePixel();
4484             long nFontHeight = GetTextHeight();
4485             if ( rMEvt.GetPosPixel().X() < ( aSz.Width() - nFontHeight - nFontHeight/4 ) )
4486                 EndExecute();
4487         }
4488     }
4489 
4490 }
4491 
4492 void MenuFloatingWindow::MouseMove( const MouseEvent& rMEvt )
4493 {
4494     if ( !IsVisible() || rMEvt.IsSynthetic() || rMEvt.IsEnterWindow() )
4495         return;
4496 
4497     if ( rMEvt.IsLeaveWindow() )
4498     {
4499 #ifdef OS2
4500         if ( ImplHilite(rMEvt) )
4501         {
4502 #endif
4503         // #102461# do not remove highlight if a popup menu is open at this position
4504         MenuItemData* pData = pMenu ? pMenu->pItemList->GetDataFromPos( nHighlightedItem ) : NULL;
4505         // close popup with some delayed if we leave somewhere else
4506         if( pActivePopup && pData && pData->pSubMenu != pActivePopup )
4507             pActivePopup->ImplGetFloatingWindow()->aSubmenuCloseTimer.Start();
4508 
4509         if( !pActivePopup || (pData && pData->pSubMenu != pActivePopup ) )
4510             ChangeHighlightItem( ITEMPOS_INVALID, sal_False );
4511 #ifdef OS2
4512         }
4513 #endif
4514 
4515         if ( IsScrollMenu() )
4516             ImplScroll( rMEvt.GetPosPixel() );
4517     }
4518     else
4519 #ifdef OS2
4520         if ( ImplHilite(rMEvt) )
4521 #endif
4522     {
4523         aSubmenuCloseTimer.Stop();
4524 		if( bIgnoreFirstMove )
4525 			bIgnoreFirstMove = sal_False;
4526 		else
4527 			ImplHighlightItem( rMEvt, sal_False );
4528     }
4529 }
4530 
4531 void MenuFloatingWindow::ImplScroll( sal_Bool bUp )
4532 {
4533     KillActivePopup();
4534     Update();
4535 
4536     if( ! pMenu )
4537         return;
4538 
4539     HighlightItem( nHighlightedItem, sal_False );
4540 
4541     pMenu->ImplKillLayoutData();
4542 
4543     if ( bScrollUp && bUp )
4544     {
4545         nFirstEntry = pMenu->ImplGetPrevVisible( nFirstEntry );
4546         DBG_ASSERT( nFirstEntry != ITEMPOS_INVALID, "Scroll?!" );
4547 
4548         long nScrollEntryHeight = pMenu->GetItemList()->GetDataFromPos( nFirstEntry )->aSz.Height();
4549 
4550 //        nStartY += nEntryHeight;
4551 
4552         if ( !bScrollDown )
4553         {
4554             bScrollDown = sal_True;
4555             ImplDrawScroller( sal_False );
4556         }
4557 
4558         if ( pMenu->ImplGetPrevVisible( nFirstEntry ) == ITEMPOS_INVALID )
4559         {
4560             bScrollUp = sal_False;
4561             ImplDrawScroller( sal_True );
4562         }
4563 
4564         Scroll( 0, nScrollEntryHeight, ImplCalcClipRegion( sal_False ).GetBoundRect(), SCROLL_CLIP );
4565     }
4566     else if ( bScrollDown && !bUp )
4567     {
4568         long nScrollEntryHeight = pMenu->GetItemList()->GetDataFromPos( nFirstEntry )->aSz.Height();
4569 
4570         nFirstEntry = pMenu->ImplGetNextVisible( nFirstEntry );
4571         DBG_ASSERT( nFirstEntry != ITEMPOS_INVALID, "Scroll?!" );
4572 
4573 
4574         if ( !bScrollUp )
4575         {
4576             bScrollUp = sal_True;
4577             ImplDrawScroller( sal_True );
4578         }
4579 
4580         long nHeight = GetOutputSizePixel().Height();
4581         sal_uInt16 nLastVisible;
4582         ((PopupMenu*)pMenu)->ImplCalcVisEntries( nHeight, nFirstEntry, &nLastVisible );
4583         if ( pMenu->ImplGetNextVisible( nLastVisible ) == ITEMPOS_INVALID )
4584         {
4585             bScrollDown = sal_False;
4586             ImplDrawScroller( sal_False );
4587         }
4588 
4589 //        nStartY -= nEntryHeight;
4590         Scroll( 0, -nScrollEntryHeight, ImplCalcClipRegion( sal_False ).GetBoundRect(), SCROLL_CLIP );
4591     }
4592 
4593     HighlightItem( nHighlightedItem, sal_True );
4594 }
4595 
4596 void MenuFloatingWindow::ImplScroll( const Point& rMousePos )
4597 {
4598     Size aOutSz = GetOutputSizePixel();
4599 
4600     long nY = nScrollerHeight;
4601     long nMouseY = rMousePos.Y();
4602     long nDelta = 0;
4603 
4604     if ( bScrollUp && ( nMouseY < nY ) )
4605     {
4606         ImplScroll( sal_True );
4607         nDelta = nY - nMouseY;
4608     }
4609     else if ( bScrollDown && ( nMouseY > ( aOutSz.Height() - nY ) ) )
4610     {
4611         ImplScroll( sal_False );
4612         nDelta = nMouseY - ( aOutSz.Height() - nY );
4613     }
4614 
4615     if ( nDelta )
4616     {
4617         aScrollTimer.Stop();    // Falls durch MouseMove gescrollt.
4618         long nTimeout;
4619         if ( nDelta < 3 )
4620             nTimeout = 200;
4621         else if ( nDelta < 5 )
4622             nTimeout = 100;
4623         else if ( nDelta < 8 )
4624             nTimeout = 70;
4625         else if ( nDelta < 12 )
4626             nTimeout = 40;
4627         else
4628             nTimeout = 20;
4629         aScrollTimer.SetTimeout( nTimeout );
4630         aScrollTimer.Start();
4631     }
4632 }
4633 void MenuFloatingWindow::ChangeHighlightItem( sal_uInt16 n, sal_Bool bStartPopupTimer )
4634 {
4635     // #57934# ggf. das aktive Popup sofort schliessen, damit TH's Hintergrundsicherung funktioniert.
4636     // #65750# Dann verzichten wir lieber auf den schmalen Streifen Hintergrundsicherung.
4637     //         Sonst lassen sich die Menus schlecht bedienen.
4638 //  MenuItemData* pNextData = pMenu->pItemList->GetDataFromPos( n );
4639 //  if ( pActivePopup && pNextData && ( pActivePopup != pNextData->pSubMenu ) )
4640 //      KillActivePopup();
4641 
4642     aSubmenuCloseTimer.Stop();
4643     if( ! pMenu )
4644         return;
4645 
4646     if ( nHighlightedItem != ITEMPOS_INVALID )
4647     {
4648         HighlightItem( nHighlightedItem, sal_False );
4649         pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
4650     }
4651 
4652     nHighlightedItem = (sal_uInt16)n;
4653     DBG_ASSERT( pMenu->ImplIsVisible( nHighlightedItem ) || nHighlightedItem == ITEMPOS_INVALID, "ChangeHighlightItem: Not visible!" );
4654     if( nHighlightedItem != ITEMPOS_INVALID )
4655     {
4656         if( pMenu->pStartedFrom && !pMenu->pStartedFrom->bIsMenuBar )
4657         {
4658             // #102461# make sure parent entry is highlighted as well
4659             MenuItemData* pData;
4660             sal_uInt16 i, nCount = (sal_uInt16)pMenu->pStartedFrom->pItemList->Count();
4661             for(i = 0; i < nCount; i++)
4662             {
4663                 pData = pMenu->pStartedFrom->pItemList->GetDataFromPos( i );
4664                 if( pData && ( pData->pSubMenu == pMenu ) )
4665                     break;
4666             }
4667             if( i < nCount )
4668             {
4669                 MenuFloatingWindow* pPWin = (MenuFloatingWindow*)pMenu->pStartedFrom->ImplGetWindow();
4670                 if( pPWin && pPWin->nHighlightedItem != i )
4671                 {
4672                     pPWin->HighlightItem( i, sal_True );
4673                     pPWin->nHighlightedItem = i;
4674                 }
4675             }
4676         }
4677         HighlightItem( nHighlightedItem, sal_True );
4678         pMenu->ImplCallHighlight( nHighlightedItem );
4679     }
4680     else
4681         pMenu->nSelectedId = 0;
4682 
4683     if ( bStartPopupTimer )
4684 	{
4685 		// #102438# Menu items are not selectable
4686 		// If a menu item is selected by an AT-tool via the XAccessibleAction, XAccessibleValue
4687 		// or XAccessibleSelection interface, and the parent popup menus are not executed yet,
4688 		// the parent popup menus must be executed SYNCHRONOUSLY, before the menu item is selected.
4689 		if ( GetSettings().GetMouseSettings().GetMenuDelay() )
4690 			aHighlightChangedTimer.Start();
4691 		else
4692             HighlightChanged( &aHighlightChangedTimer );
4693 	}
4694 }
4695 
4696 void MenuFloatingWindow::HighlightItem( sal_uInt16 nPos, sal_Bool bHighlight )
4697 {
4698     if( ! pMenu )
4699         return;
4700 
4701     Size    aSz = GetOutputSizePixel();
4702     long    nStartY = ImplGetStartY();
4703     long    nY = nScrollerHeight+nStartY;
4704     long    nX = 0;
4705 
4706     if ( pMenu->pLogo )
4707         nX = pMenu->pLogo->aBitmap.GetSizePixel().Width();
4708 
4709     int nOuterSpace = ImplGetSVData()->maNWFData.mnMenuFormatExtraBorder;
4710     nY += nOuterSpace;
4711 
4712     sal_uInt16 nCount = (sal_uInt16)pMenu->pItemList->Count();
4713     for ( sal_uInt16 n = 0; n < nCount; n++ )
4714     {
4715         MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
4716         if ( n == nPos )
4717         {
4718             DBG_ASSERT( pMenu->ImplIsVisible( n ), "Highlight: Item not visible!" );
4719             if ( pData->eType != MENUITEM_SEPARATOR )
4720             {
4721                 sal_Bool bRestoreLineColor = sal_False;
4722                 Color oldLineColor;
4723                 bool bDrawItemRect = true;
4724 
4725                 Rectangle aItemRect( Point( nX+nOuterSpace, nY ), Size( aSz.Width()-2*nOuterSpace, pData->aSz.Height() ) );
4726                 if ( pData->nBits & MIB_POPUPSELECT )
4727                 {
4728                     long nFontHeight = GetTextHeight();
4729                     aItemRect.Right() -= nFontHeight + nFontHeight/4;
4730                 }
4731 
4732                 if( IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) )
4733                 {
4734                     Size aPxSize( GetOutputSizePixel() );
4735                     Push( PUSH_CLIPREGION );
4736                     IntersectClipRegion( Rectangle( Point( nX, nY ), Size( aSz.Width(), pData->aSz.Height() ) ) );
4737                     Rectangle aCtrlRect( Point( nX, 0 ), Size( aPxSize.Width()-nX, aPxSize.Height() ) );
4738                     MenupopupValue aVal( pMenu->nTextPos-GUTTERBORDER, aItemRect );
4739                     DrawNativeControl( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL,
4740                                        aCtrlRect,
4741                                        CTRL_STATE_ENABLED,
4742                                        aVal,
4743                                        OUString() );
4744                     if( bHighlight &&
4745                         IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM ) )
4746                     {
4747                         bDrawItemRect = false;
4748                         if( sal_False == DrawNativeControl( CTRL_MENU_POPUP, PART_MENU_ITEM,
4749                                                         aItemRect,
4750                                                         CTRL_STATE_SELECTED | ( pData->bEnabled? CTRL_STATE_ENABLED: 0 ),
4751                                                         aVal,
4752                                                         OUString() ) )
4753                         {
4754                             bDrawItemRect = bHighlight;
4755                         }
4756                     }
4757                     else
4758                         bDrawItemRect = bHighlight;
4759                     Pop();
4760                 }
4761                 if( bDrawItemRect )
4762                 {
4763                     if ( bHighlight )
4764                     {
4765                         if( pData->bEnabled )
4766                             SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
4767                         else
4768                         {
4769                             SetFillColor();
4770                             oldLineColor = GetLineColor();
4771                             SetLineColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
4772                             bRestoreLineColor = sal_True;
4773                         }
4774                     }
4775                     else
4776                         SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
4777 
4778                     DrawRect( aItemRect );
4779                 }
4780                 pMenu->ImplPaint( this, nScrollerHeight, nStartY, pData, bHighlight );
4781                 if( bRestoreLineColor )
4782                     SetLineColor( oldLineColor );
4783             }
4784             return;
4785         }
4786 
4787         nY += pData->aSz.Height();
4788     }
4789 }
4790 
4791 Rectangle MenuFloatingWindow::ImplGetItemRect( sal_uInt16 nPos )
4792 {
4793     if( ! pMenu )
4794         return Rectangle();
4795 
4796 	Rectangle aRect;
4797     Size    aSz = GetOutputSizePixel();
4798     long    nStartY = ImplGetStartY();
4799     long    nY = nScrollerHeight+nStartY;
4800     long    nX = 0;
4801 
4802     if ( pMenu->pLogo )
4803         nX = pMenu->pLogo->aBitmap.GetSizePixel().Width();
4804 
4805     sal_uInt16 nCount = (sal_uInt16)pMenu->pItemList->Count();
4806     for ( sal_uInt16 n = 0; n < nCount; n++ )
4807     {
4808         MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
4809         if ( n == nPos )
4810         {
4811             DBG_ASSERT( pMenu->ImplIsVisible( n ), "ImplGetItemRect: Item not visible!" );
4812             if ( pData->eType != MENUITEM_SEPARATOR )
4813             {
4814                 aRect = Rectangle( Point( nX, nY ), Size( aSz.Width(), pData->aSz.Height() ) );
4815                 if ( pData->nBits & MIB_POPUPSELECT )
4816                 {
4817                     long nFontHeight = GetTextHeight();
4818                     aRect.Right() -= nFontHeight + nFontHeight/4;
4819                 }
4820             }
4821             break;
4822         }
4823         nY += pData->aSz.Height();
4824     }
4825 	return aRect;
4826 }
4827 
4828 
4829 void MenuFloatingWindow::ImplCursorUpDown( sal_Bool bUp, sal_Bool bHomeEnd )
4830 {
4831     if( ! pMenu )
4832         return;
4833 
4834 	const StyleSettings& rSettings = GetSettings().GetStyleSettings();
4835 
4836     sal_uInt16 n = nHighlightedItem;
4837     if ( n == ITEMPOS_INVALID )
4838     {
4839         if ( bUp )
4840             n = 0;
4841         else
4842             n = pMenu->GetItemCount()-1;
4843     }
4844 
4845     sal_uInt16 nLoop = n;
4846 
4847 	if( bHomeEnd )
4848 	{
4849 		// absolute positioning
4850 		if( bUp )
4851 		{
4852             n = pMenu->GetItemCount();
4853 			nLoop = n-1;
4854 		}
4855 		else
4856 		{
4857 			n = (sal_uInt16)-1;
4858 			nLoop = n+1;
4859 		}
4860 	}
4861 
4862     do
4863     {
4864         if ( bUp )
4865         {
4866             if ( n )
4867                 n--;
4868             else
4869                 if ( !IsScrollMenu() || ( nHighlightedItem == ITEMPOS_INVALID ) )
4870                     n = pMenu->GetItemCount()-1;
4871                 else
4872                     break;
4873         }
4874         else
4875         {
4876             n++;
4877             if ( n >= pMenu->GetItemCount() )
4878             {
4879                 if ( !IsScrollMenu() || ( nHighlightedItem == ITEMPOS_INVALID ) )
4880                     n = 0;
4881                 else
4882                     break;
4883             }
4884         }
4885 
4886         MenuItemData* pData = (MenuItemData*)pMenu->GetItemList()->GetDataFromPos( n );
4887         if ( ( pData->bEnabled || !rSettings.GetSkipDisabledInMenus() )
4888 			  && ( pData->eType != MENUITEM_SEPARATOR ) && pMenu->ImplIsVisible( n ) && pMenu->ImplIsSelectable( n ) )
4889         {
4890             // Selektion noch im sichtbaren Bereich?
4891             if ( IsScrollMenu() )
4892             {
4893                 ChangeHighlightItem( ITEMPOS_INVALID, sal_False );
4894 
4895                 while ( n < nFirstEntry )
4896                     ImplScroll( sal_True );
4897 
4898                 Size aOutSz = GetOutputSizePixel();
4899 				sal_uInt16 nLastVisible;
4900 				((PopupMenu*)pMenu)->ImplCalcVisEntries( aOutSz.Height(), nFirstEntry, &nLastVisible );
4901                 while ( n > nLastVisible )
4902 				{
4903                     ImplScroll( sal_False );
4904 					((PopupMenu*)pMenu)->ImplCalcVisEntries( aOutSz.Height(), nFirstEntry, &nLastVisible );
4905 				}
4906             }
4907             ChangeHighlightItem( n, sal_False );
4908             break;
4909         }
4910     } while ( n != nLoop );
4911 }
4912 
4913 void MenuFloatingWindow::KeyInput( const KeyEvent& rKEvent )
4914 {
4915     ImplDelData aDelData;
4916     ImplAddDel( &aDelData );
4917 
4918     sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
4919     bKeyInput = sal_True;
4920     switch ( nCode )
4921     {
4922         case KEY_UP:
4923         case KEY_DOWN:
4924         {
4925             ImplCursorUpDown( nCode == KEY_UP );
4926         }
4927         break;
4928         case KEY_END:
4929         case KEY_HOME:
4930 		{
4931             ImplCursorUpDown( nCode == KEY_END, sal_True );
4932 		}
4933 		break;
4934         case KEY_F6:
4935         case KEY_ESCAPE:
4936 		{
4937             // Ctrl-F6 acts like ESC here, the menu bar however will then put the focus in the document
4938             if( nCode == KEY_F6 && !rKEvent.GetKeyCode().IsMod1() )
4939                 break;
4940             if( pMenu )
4941             {
4942                 if ( !pMenu->pStartedFrom )
4943                 {
4944                     StopExecute();
4945                     KillActivePopup();
4946                 }
4947                 else if ( pMenu->pStartedFrom->bIsMenuBar )
4948                 {
4949                     // Forward...
4950                     ((MenuBarWindow*)((MenuBar*)pMenu->pStartedFrom)->ImplGetWindow())->KeyInput( rKEvent );
4951                 }
4952                 else
4953                 {
4954                     StopExecute();
4955                     PopupMenu* pPopupMenu = (PopupMenu*)pMenu->pStartedFrom;
4956                     MenuFloatingWindow* pFloat = pPopupMenu->ImplGetFloatingWindow();
4957                     pFloat->GrabFocus();
4958                     pFloat->KillActivePopup();
4959                     pPopupMenu->ImplCallHighlight(pFloat->nHighlightedItem);
4960                 }
4961             }
4962 		}
4963 		break;
4964         case KEY_LEFT:
4965         {
4966             if ( pMenu && pMenu->pStartedFrom )
4967             {
4968                 StopExecute();
4969                 if ( pMenu->pStartedFrom->bIsMenuBar )
4970                 {
4971                     // Forward...
4972                     ((MenuBarWindow*)((MenuBar*)pMenu->pStartedFrom)->ImplGetWindow())->KeyInput( rKEvent );
4973                 }
4974                 else
4975                 {
4976                     MenuFloatingWindow* pFloat = ((PopupMenu*)pMenu->pStartedFrom)->ImplGetFloatingWindow();
4977                     pFloat->GrabFocus();
4978                     pFloat->KillActivePopup();
4979                 }
4980             }
4981         }
4982         break;
4983         case KEY_RIGHT:
4984         {
4985             if( pMenu )
4986             {
4987                 sal_Bool bDone = sal_False;
4988                 if ( nHighlightedItem != ITEMPOS_INVALID )
4989                 {
4990                     MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
4991                     if ( pData && pData->pSubMenu )
4992                     {
4993                         HighlightChanged( 0 );
4994                         bDone = sal_True;
4995                     }
4996                 }
4997                 if ( !bDone )
4998                 {
4999                     Menu* pStart = pMenu->ImplGetStartMenu();
5000                     if ( pStart && pStart->bIsMenuBar )
5001                     {
5002                         // Forward...
5003                         pStart->ImplGetWindow()->KeyInput( rKEvent );
5004                     }
5005                 }
5006             }
5007         }
5008         break;
5009         case KEY_RETURN:
5010         {
5011             if( pMenu )
5012             {
5013                 MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
5014                 if ( pData && pData->bEnabled )
5015                 {
5016                     if ( pData->pSubMenu )
5017                         HighlightChanged( 0 );
5018                     else
5019                         EndExecute();
5020                 }
5021                 else
5022                     StopExecute();
5023             }
5024         }
5025         break;
5026         case KEY_MENU:
5027         {
5028             if( pMenu )
5029             {
5030                 Menu* pStart = pMenu->ImplGetStartMenu();
5031                 if ( pStart && pStart->bIsMenuBar )
5032                 {
5033                     // Forward...
5034                     pStart->ImplGetWindow()->KeyInput( rKEvent );
5035                 }
5036             }
5037         }
5038         break;
5039         default:
5040         {
5041             xub_Unicode nCharCode = rKEvent.GetCharCode();
5042             sal_uInt16 nPos = 0;
5043 			sal_uInt16 nDuplicates = 0;
5044             MenuItemData* pData = (nCharCode && pMenu) ? pMenu->GetItemList()->SearchItem( nCharCode, rKEvent.GetKeyCode(), nPos, nDuplicates, nHighlightedItem ) : NULL;
5045             if ( pData )
5046             {
5047                 if ( pData->pSubMenu || nDuplicates > 1 )
5048                 {
5049                     ChangeHighlightItem( nPos, sal_False );
5050                     HighlightChanged( 0 );
5051                 }
5052                 else
5053                 {
5054                     nHighlightedItem = nPos;
5055                     EndExecute();
5056                 }
5057             }
5058             else
5059             {
5060                 // Bei ungueltigen Tasten Beepen, aber nicht bei HELP und F-Tasten
5061                 if ( !rKEvent.GetKeyCode().IsMod2() && ( nCode != KEY_HELP ) && ( rKEvent.GetKeyCode().GetGroup() != KEYGROUP_FKEYS ) )
5062                     Sound::Beep();
5063                 FloatingWindow::KeyInput( rKEvent );
5064             }
5065         }
5066     }
5067     // #105474# check if menu window was not destroyed
5068     if ( !aDelData.IsDelete() )
5069     {
5070         ImplRemoveDel( &aDelData );
5071         bKeyInput = sal_False;
5072     }
5073 }
5074 
5075 void MenuFloatingWindow::Paint( const Rectangle& )
5076 {
5077     if( ! pMenu )
5078         return;
5079 
5080     if( IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) )
5081     {
5082         SetClipRegion();
5083         long nX = pMenu->pLogo ? pMenu->pLogo->aBitmap.GetSizePixel().Width() : 0;
5084         Size aPxSize( GetOutputSizePixel() );
5085         aPxSize.Width() -= nX;
5086         ImplControlValue aVal( pMenu->nTextPos-GUTTERBORDER );
5087         DrawNativeControl( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL,
5088                            Rectangle( Point( nX, 0 ), aPxSize ),
5089                            CTRL_STATE_ENABLED,
5090                            aVal,
5091                            OUString() );
5092         ImplInitClipRegion();
5093     }
5094     if ( IsScrollMenu() )
5095     {
5096         ImplDrawScroller( sal_True );
5097         ImplDrawScroller( sal_False );
5098     }
5099     SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
5100     pMenu->ImplPaint( this, nScrollerHeight, ImplGetStartY() );
5101     if ( nHighlightedItem != ITEMPOS_INVALID )
5102         HighlightItem( nHighlightedItem, sal_True );
5103 }
5104 
5105 void MenuFloatingWindow::ImplDrawScroller( sal_Bool bUp )
5106 {
5107     if( ! pMenu )
5108         return;
5109 
5110     SetClipRegion();
5111 
5112     Size aOutSz = GetOutputSizePixel();
5113     long nY = bUp ? 0 : ( aOutSz.Height() - nScrollerHeight );
5114     long nX = pMenu->pLogo ? pMenu->pLogo->aBitmap.GetSizePixel().Width() : 0;
5115     Rectangle aRect( Point( nX, nY ), Size( aOutSz.Width()-nX, nScrollerHeight ) );
5116 
5117     DecorationView aDecoView( this );
5118     SymbolType eSymbol = bUp ? SYMBOL_SPIN_UP : SYMBOL_SPIN_DOWN;
5119 
5120     sal_uInt16 nStyle = 0;
5121     if ( ( bUp && !bScrollUp ) || ( !bUp && !bScrollDown ) )
5122         nStyle |= SYMBOL_DRAW_DISABLE;
5123 
5124     aDecoView.DrawSymbol( aRect, eSymbol, GetSettings().GetStyleSettings().GetButtonTextColor(), nStyle );
5125 
5126     ImplInitClipRegion();
5127 }
5128 
5129 void MenuFloatingWindow::RequestHelp( const HelpEvent& rHEvt )
5130 {
5131     sal_uInt16 nId = nHighlightedItem;
5132     Menu* pM = pMenu;
5133     Window* pW = this;
5134 
5135     // #102618# Get item rect before destroying the window in EndExecute() call
5136 	Rectangle aHighlightRect( ImplGetItemRect( nHighlightedItem ) );
5137 
5138     if ( rHEvt.GetMode() & (HELPMODE_CONTEXT | HELPMODE_EXTENDED) )
5139     {
5140         nHighlightedItem = ITEMPOS_INVALID;
5141         EndExecute();
5142         pW = NULL;
5143     }
5144 
5145     if( !ImplHandleHelpEvent( pW, pM, nId, rHEvt, aHighlightRect ) )
5146         Window::RequestHelp( rHEvt );
5147 }
5148 
5149 void MenuFloatingWindow::StateChanged( StateChangedType nType )
5150 {
5151     FloatingWindow::StateChanged( nType );
5152 
5153     if ( ( nType == STATE_CHANGE_CONTROLFOREGROUND ) || ( nType == STATE_CHANGE_CONTROLBACKGROUND ) )
5154     {
5155         ImplInitMenuWindow( this, sal_False, sal_False );
5156         Invalidate();
5157     }
5158 }
5159 
5160 void MenuFloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
5161 {
5162     FloatingWindow::DataChanged( rDCEvt );
5163 
5164     if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
5165          (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
5166          ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
5167           (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
5168     {
5169         ImplInitMenuWindow( this, sal_False, sal_False );
5170         Invalidate();
5171     }
5172 }
5173 
5174 void MenuFloatingWindow::Command( const CommandEvent& rCEvt )
5175 {
5176     if ( rCEvt.GetCommand() == COMMAND_WHEEL )
5177     {
5178         const CommandWheelData* pData = rCEvt.GetWheelData();
5179         if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) )
5180         {
5181 //          ImplCursorUpDown( pData->GetDelta() > 0L );
5182             ImplScroll( pData->GetDelta() > 0L );
5183             MouseMove( MouseEvent( GetPointerPosPixel(), 0 ) );
5184         }
5185     }
5186 }
5187 
5188 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > MenuFloatingWindow::CreateAccessible()
5189 {
5190 	::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xAcc;
5191 
5192 	if ( pMenu && !pMenu->pStartedFrom )
5193 		xAcc = pMenu->GetAccessible();
5194 
5195 	return xAcc;
5196 }
5197 
5198 MenuBarWindow::MenuBarWindow( Window* pParent ) :
5199     Window( pParent, 0 ),
5200     aCloser( this ),
5201     aFloatBtn( this, WB_NOPOINTERFOCUS | WB_SMALLSTYLE | WB_RECTSTYLE ),
5202     aHideBtn( this, WB_NOPOINTERFOCUS | WB_SMALLSTYLE | WB_RECTSTYLE )
5203 {
5204     SetType( WINDOW_MENUBARWINDOW );
5205     pMenu = NULL;
5206     pActivePopup = NULL;
5207     nSaveFocusId = 0;
5208     nHighlightedItem = ITEMPOS_INVALID;
5209     mbAutoPopup = sal_True;
5210     nSaveFocusId = 0;
5211 	bIgnoreFirstMove = sal_True;
5212 	bStayActive = sal_False;
5213 
5214     ResMgr* pResMgr = ImplGetResMgr();
5215 
5216     if( pResMgr )
5217     {
5218         BitmapEx aBitmap( ResId( SV_RESID_BITMAP_CLOSEDOC, *pResMgr ) );
5219         BitmapEx aBitmapHC( ResId( SV_RESID_BITMAP_CLOSEDOCHC, *pResMgr ) );
5220 
5221         aCloser.maImage = Image( aBitmap );
5222         aCloser.maImageHC = Image( aBitmapHC );
5223 
5224         aCloser.SetOutStyle( TOOLBOX_STYLE_FLAT );
5225         aCloser.SetBackground();
5226         aCloser.SetPaintTransparent( sal_True );
5227         aCloser.SetParentClipMode( PARENTCLIPMODE_NOCLIP );
5228 
5229         aCloser.InsertItem( IID_DOCUMENTCLOSE,
5230         GetSettings().GetStyleSettings().GetHighContrastMode() ? aCloser.maImageHC : aCloser.maImage, 0 );
5231         aCloser.SetSelectHdl( LINK( this, MenuBarWindow, CloserHdl ) );
5232         aCloser.AddEventListener( LINK( this, MenuBarWindow, ToolboxEventHdl ) );
5233         aCloser.SetQuickHelpText( IID_DOCUMENTCLOSE, XubString( ResId( SV_HELPTEXT_CLOSEDOCUMENT, *pResMgr ) ) );
5234 
5235         aFloatBtn.SetClickHdl( LINK( this, MenuBarWindow, FloatHdl ) );
5236         aFloatBtn.SetSymbol( SYMBOL_FLOAT );
5237         aFloatBtn.SetQuickHelpText( XubString( ResId( SV_HELPTEXT_RESTORE, *pResMgr ) ) );
5238 
5239         aHideBtn.SetClickHdl( LINK( this, MenuBarWindow, HideHdl ) );
5240         aHideBtn.SetSymbol( SYMBOL_HIDE );
5241         aHideBtn.SetQuickHelpText( XubString( ResId( SV_HELPTEXT_MINIMIZE, *pResMgr ) ) );
5242     }
5243 
5244     ImplInitStyleSettings();
5245 
5246     AddEventListener( LINK( this, MenuBarWindow, ShowHideListener ) );
5247 }
5248 
5249 MenuBarWindow::~MenuBarWindow()
5250 {
5251     aCloser.RemoveEventListener( LINK( this, MenuBarWindow, ToolboxEventHdl ) );
5252     RemoveEventListener( LINK( this, MenuBarWindow, ShowHideListener ) );
5253 }
5254 
5255 void MenuBarWindow::SetMenu( MenuBar* pMen )
5256 {
5257     pMenu = pMen;
5258     KillActivePopup();
5259     nHighlightedItem = ITEMPOS_INVALID;
5260     ImplInitMenuWindow( this, sal_True, sal_True );
5261     if ( pMen )
5262     {
5263         aCloser.ShowItem( IID_DOCUMENTCLOSE, pMen->HasCloser() );
5264         aCloser.Show( pMen->HasCloser() || !m_aAddButtons.empty() );
5265         aFloatBtn.Show( pMen->HasFloatButton() );
5266         aHideBtn.Show( pMen->HasHideButton() );
5267     }
5268     Invalidate();
5269 
5270     // show and connect native menubar
5271     if( pMenu && pMenu->ImplGetSalMenu() )
5272     {
5273         if( pMenu->ImplGetSalMenu()->VisibleMenuBar() )
5274             ImplGetFrame()->SetMenu( pMenu->ImplGetSalMenu() );
5275 
5276         pMenu->ImplGetSalMenu()->SetFrame( ImplGetFrame() );
5277     }
5278 }
5279 
5280 void MenuBarWindow::ShowButtons( sal_Bool bClose, sal_Bool bFloat, sal_Bool bHide )
5281 {
5282     aCloser.ShowItem( IID_DOCUMENTCLOSE, bClose );
5283     aCloser.Show( bClose || ! m_aAddButtons.empty() );
5284     aFloatBtn.Show( bFloat );
5285     aHideBtn.Show( bHide );
5286     Resize();
5287 }
5288 
5289 Size MenuBarWindow::MinCloseButtonSize()
5290 {
5291     return aCloser.getMinSize();
5292 }
5293 
5294 IMPL_LINK( MenuBarWindow, CloserHdl, PushButton*, EMPTYARG )
5295 {
5296     if( ! pMenu )
5297         return 0;
5298 
5299     if( aCloser.GetCurItemId() == IID_DOCUMENTCLOSE )
5300     {
5301         // #i106052# call close hdl asynchronously to ease handler implementation
5302         // this avoids still being in the handler while the DecoToolBox already
5303         // gets destroyed
5304         Application::PostUserEvent( ((MenuBar*)pMenu)->GetCloserHdl(), pMenu );
5305     }
5306     else
5307     {
5308         std::map<sal_uInt16,AddButtonEntry>::iterator it = m_aAddButtons.find( aCloser.GetCurItemId() );
5309         if( it != m_aAddButtons.end() )
5310         {
5311             MenuBar::MenuBarButtonCallbackArg aArg;
5312             aArg.nId = it->first;
5313             aArg.bHighlight = (aCloser.GetHighlightItemId() == it->first);
5314             aArg.pMenuBar = dynamic_cast<MenuBar*>(pMenu);
5315             return it->second.m_aSelectLink.Call( &aArg );
5316         }
5317     }
5318     return 0;
5319 }
5320 
5321 IMPL_LINK( MenuBarWindow, ToolboxEventHdl, VclWindowEvent*, pEvent )
5322 {
5323     if( ! pMenu )
5324         return 0;
5325 
5326     MenuBar::MenuBarButtonCallbackArg aArg;
5327     aArg.nId = 0xffff;
5328     aArg.bHighlight = (pEvent->GetId() == VCLEVENT_TOOLBOX_HIGHLIGHT);
5329     aArg.pMenuBar = dynamic_cast<MenuBar*>(pMenu);
5330     if( pEvent->GetId() == VCLEVENT_TOOLBOX_HIGHLIGHT )
5331         aArg.nId = aCloser.GetHighlightItemId();
5332     else if( pEvent->GetId() == VCLEVENT_TOOLBOX_HIGHLIGHTOFF )
5333     {
5334         sal_uInt16 nPos = static_cast< sal_uInt16 >(reinterpret_cast<sal_IntPtr>(pEvent->GetData()));
5335         aArg.nId = aCloser.GetItemId( nPos );
5336     }
5337     std::map< sal_uInt16, AddButtonEntry >::iterator it = m_aAddButtons.find( aArg.nId );
5338     if( it != m_aAddButtons.end() )
5339     {
5340         it->second.m_aHighlightLink.Call( &aArg );
5341     }
5342     return 0;
5343 }
5344 
5345 IMPL_LINK( MenuBarWindow, ShowHideListener, VclWindowEvent*, pEvent )
5346 {
5347     if( ! pMenu )
5348         return 0;
5349 
5350     if( pEvent->GetId() == VCLEVENT_WINDOW_SHOW )
5351         pMenu->ImplCallEventListeners( VCLEVENT_MENU_SHOW, ITEMPOS_INVALID );
5352     else if( pEvent->GetId() == VCLEVENT_WINDOW_HIDE )
5353         pMenu->ImplCallEventListeners( VCLEVENT_MENU_HIDE, ITEMPOS_INVALID );
5354     return 0;
5355 }
5356 
5357 IMPL_LINK( MenuBarWindow, FloatHdl, PushButton*, EMPTYARG )
5358 {
5359     return pMenu ? ((MenuBar*)pMenu)->GetFloatButtonClickHdl().Call( pMenu ) : 0;
5360 }
5361 
5362 IMPL_LINK( MenuBarWindow, HideHdl, PushButton*, EMPTYARG )
5363 {
5364     return pMenu ? ((MenuBar*)pMenu)->GetHideButtonClickHdl().Call( pMenu ) : 0;
5365 }
5366 
5367 void MenuBarWindow::ImplCreatePopup( sal_Bool bPreSelectFirst )
5368 {
5369     MenuItemData* pItemData = pMenu ? pMenu->GetItemList()->GetDataFromPos( nHighlightedItem ) : NULL;
5370     if ( pItemData )
5371     {
5372 		bIgnoreFirstMove = sal_True;
5373         if ( pActivePopup && ( pActivePopup != pItemData->pSubMenu ) )
5374         {
5375             KillActivePopup();
5376         }
5377         if ( pItemData->bEnabled && pItemData->pSubMenu && ( nHighlightedItem != ITEMPOS_INVALID ) && ( pItemData->pSubMenu != pActivePopup ) )
5378         {
5379             pActivePopup = (PopupMenu*)pItemData->pSubMenu;
5380             long nX = 0;
5381             MenuItemData* pData = 0;
5382             for ( sal_uLong n = 0; n < nHighlightedItem; n++ )
5383             {
5384                 pData = pMenu->GetItemList()->GetDataFromPos( n );
5385                 nX += pData->aSz.Width();
5386             }
5387             pData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
5388 //          Point MyPos = GetPosPixel();
5389 //          Point aItemTopLeft( MyPos.X()+nX, MyPos.Y() );
5390             Point aItemTopLeft( nX, 0 );
5391             Point aItemBottomRight( aItemTopLeft );
5392             aItemBottomRight.X() += pData->aSz.Width();
5393 
5394             // Im Vollbild-Modus hat die MenuBar ggf. die Hoehe 0:
5395             // Nicht immer einfach die Window-Hoehe nehmen, weil ItemHeight < WindowHeight.
5396             if ( GetSizePixel().Height() )
5397             {
5398                 // #107747# give menuitems the height of the menubar
5399                 aItemBottomRight.Y() += GetOutputSizePixel().Height()-1;
5400             }
5401 
5402             // ImplExecute ist doch nicht modal...
5403             // #99071# do not grab the focus, otherwise it will be restored to the menubar
5404             // when the frame is reactivated later
5405             //GrabFocus();
5406             pActivePopup->ImplExecute( this, Rectangle( aItemTopLeft, aItemBottomRight ), FLOATWIN_POPUPMODE_DOWN, pMenu, bPreSelectFirst );
5407             if ( pActivePopup )
5408             {
5409                 // Hat kein Window, wenn vorher abgebrochen oder keine Eintraege
5410                 if ( pActivePopup->ImplGetFloatingWindow() )
5411                     pActivePopup->ImplGetFloatingWindow()->AddPopupModeWindow( this );
5412                 else
5413                     pActivePopup = NULL;
5414             }
5415         }
5416     }
5417 }
5418 
5419 
5420 void MenuBarWindow::KillActivePopup()
5421 {
5422     if ( pActivePopup )
5423     {
5424         if( pActivePopup->pWindow != NULL )
5425             if( ((FloatingWindow *) pActivePopup->pWindow)->IsInCleanUp() )
5426                 return; // kill it later
5427 
5428         if ( pActivePopup->bInCallback )
5429             pActivePopup->bCanceled = sal_True;
5430 
5431         pActivePopup->bInCallback = sal_True;
5432         pActivePopup->Deactivate();
5433         pActivePopup->bInCallback = sal_False;
5434         // Abfrage auf pActivePopup, falls im Deactivate abgeschossen...
5435         if ( pActivePopup && pActivePopup->ImplGetWindow() )
5436         {
5437             pActivePopup->ImplGetFloatingWindow()->StopExecute();
5438             pActivePopup->ImplGetFloatingWindow()->doShutdown();
5439             pActivePopup->pWindow->doLazyDelete();
5440             pActivePopup->pWindow = NULL;
5441         }
5442         pActivePopup = 0;
5443     }
5444 }
5445 
5446 void MenuBarWindow::PopupClosed( Menu* pPopup )
5447 {
5448     if ( pPopup == pActivePopup )
5449     {
5450         KillActivePopup();
5451         ChangeHighlightItem( ITEMPOS_INVALID, sal_False, ImplGetFrameWindow()->ImplGetFrameData()->mbHasFocus, sal_False );
5452     }
5453 }
5454 
5455 void MenuBarWindow::MouseButtonDown( const MouseEvent& rMEvt )
5456 {
5457     mbAutoPopup = sal_True;
5458     sal_uInt16 nEntry = ImplFindEntry( rMEvt.GetPosPixel() );
5459     if ( ( nEntry != ITEMPOS_INVALID ) && ( nEntry != nHighlightedItem ) )
5460     {
5461         ChangeHighlightItem( nEntry, sal_False );
5462     }
5463     else
5464     {
5465         KillActivePopup();
5466         ChangeHighlightItem( ITEMPOS_INVALID, sal_False );
5467     }
5468 }
5469 
5470 void MenuBarWindow::MouseButtonUp( const MouseEvent& )
5471 {
5472 }
5473 
5474 void MenuBarWindow::MouseMove( const MouseEvent& rMEvt )
5475 {
5476     // Im Move nur Highlighten, wenn schon eins gehighlightet.
5477     if ( rMEvt.IsSynthetic() || rMEvt.IsLeaveWindow() || rMEvt.IsEnterWindow() || ( nHighlightedItem == ITEMPOS_INVALID ) )
5478         return;
5479 
5480 	if( bIgnoreFirstMove )
5481 	{
5482 		bIgnoreFirstMove = sal_False;
5483 		return;
5484 	}
5485 
5486     sal_uInt16 nEntry = ImplFindEntry( rMEvt.GetPosPixel() );
5487     if ( ( nEntry != ITEMPOS_INVALID )
5488 #ifdef OS2
5489        && ( ImplHilite(rMEvt) )
5490 #endif
5491 	   && ( nEntry != nHighlightedItem ) )
5492         ChangeHighlightItem( nEntry, sal_False );
5493 }
5494 
5495 void MenuBarWindow::ChangeHighlightItem( sal_uInt16 n, sal_Bool bSelectEntry, sal_Bool bAllowRestoreFocus, sal_Bool bDefaultToDocument)
5496 {
5497     if( ! pMenu )
5498         return;
5499 
5500     // #57934# ggf. das aktive Popup sofort schliessen, damit TH's Hintergrundsicherung funktioniert.
5501     MenuItemData* pNextData = pMenu->pItemList->GetDataFromPos( n );
5502     if ( pActivePopup && pActivePopup->ImplGetWindow() && ( !pNextData || ( pActivePopup != pNextData->pSubMenu ) ) )
5503         KillActivePopup(); // pActivePopup ggf. ohne pWin, wenn in Activate() Rescheduled wurde
5504 
5505     // Activate am MenuBar immer nur einmal pro Vorgang...
5506     sal_Bool bJustActivated = sal_False;
5507     if ( ( nHighlightedItem == ITEMPOS_INVALID ) && ( n != ITEMPOS_INVALID ) )
5508     {
5509         ImplGetSVData()->maWinData.mbNoDeactivate = sal_True;
5510         if( !bStayActive )
5511 		{
5512             // #105406# avoid saving the focus when we already have the focus
5513             sal_Bool bNoSaveFocus = (this == ImplGetSVData()->maWinData.mpFocusWin );
5514 
5515 			if( nSaveFocusId )
5516 			{
5517 				if( !ImplGetSVData()->maWinData.mbNoSaveFocus )
5518 				{
5519 					// we didn't clean up last time
5520 					Window::EndSaveFocus( nSaveFocusId, sal_False );	// clean up
5521                     nSaveFocusId = 0;
5522                     if( !bNoSaveFocus )
5523 					    nSaveFocusId = Window::SaveFocus();	// only save focus when initially activated
5524 				}
5525 				else {
5526 					; // do nothing: we 're activated again from taskpanelist, focus was already saved
5527                 }
5528 			}
5529 			else
5530 			{
5531                 if( !bNoSaveFocus )
5532 				    nSaveFocusId = Window::SaveFocus();	// only save focus when initially activated
5533 			}
5534 		}
5535 		else
5536 			bStayActive = sal_False;
5537         pMenu->bInCallback = sal_True;  // hier schon setzen, falls Activate ueberladen
5538         pMenu->Activate();
5539         pMenu->bInCallback = sal_False;
5540         bJustActivated = sal_True;
5541     }
5542     else if ( ( nHighlightedItem != ITEMPOS_INVALID ) && ( n == ITEMPOS_INVALID ) )
5543     {
5544         pMenu->bInCallback = sal_True;
5545         pMenu->Deactivate();
5546         pMenu->bInCallback = sal_False;
5547         ImplGetSVData()->maWinData.mbNoDeactivate = sal_False;
5548 		if( !ImplGetSVData()->maWinData.mbNoSaveFocus )
5549 		{
5550 			sal_uLong nTempFocusId = nSaveFocusId;
5551 			nSaveFocusId = 0;
5552 			Window::EndSaveFocus( nTempFocusId, bAllowRestoreFocus );
5553             // #105406# restore focus to document if we could not save focus before
5554             if( bDefaultToDocument && !nTempFocusId && bAllowRestoreFocus )
5555                 GrabFocusToDocument();
5556 		}
5557     }
5558 
5559     if ( nHighlightedItem != ITEMPOS_INVALID )
5560     {
5561         HighlightItem( nHighlightedItem, sal_False );
5562         pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
5563     }
5564 
5565     nHighlightedItem = (sal_uInt16)n;
5566     DBG_ASSERT( ( nHighlightedItem == ITEMPOS_INVALID ) || pMenu->ImplIsVisible( nHighlightedItem ), "ChangeHighlightItem: Not visible!" );
5567     HighlightItem( nHighlightedItem, sal_True );
5568     pMenu->ImplCallHighlight( nHighlightedItem );
5569 
5570     if( mbAutoPopup )
5571         ImplCreatePopup( bSelectEntry );
5572 
5573     // #58935# #73659# Focus, wenn kein Popup drunter haengt...
5574     if ( bJustActivated && !pActivePopup )
5575         GrabFocus();
5576 }
5577 
5578 void MenuBarWindow::HighlightItem( sal_uInt16 nPos, sal_Bool bHighlight )
5579 {
5580     if( ! pMenu )
5581         return;
5582 
5583     long nX = 0;
5584     sal_uLong nCount = pMenu->pItemList->Count();
5585     for ( sal_uLong n = 0; n < nCount; n++ )
5586     {
5587         MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
5588         if ( n == nPos )
5589         {
5590             if ( pData->eType != MENUITEM_SEPARATOR )
5591             {
5592                 // #107747# give menuitems the height of the menubar
5593                 Rectangle aRect = Rectangle( Point( nX, 1 ), Size( pData->aSz.Width(), GetOutputSizePixel().Height()-2 ) );
5594                 Push( PUSH_CLIPREGION );
5595                 IntersectClipRegion( aRect );
5596                 if ( bHighlight )
5597                 {
5598                     if( IsNativeControlSupported( CTRL_MENUBAR, PART_MENU_ITEM ) &&
5599                         IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
5600                     {
5601                         // draw background (transparency)
5602                         MenubarValue aControlValue;
5603                         aControlValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight( this );
5604 
5605                         Point tmp(0,0);
5606                         Rectangle aBgRegion( tmp, GetOutputSizePixel() );
5607                         DrawNativeControl( CTRL_MENUBAR, PART_ENTIRE_CONTROL,
5608                                            aBgRegion,
5609                                            CTRL_STATE_ENABLED,
5610                                            aControlValue,
5611                                            OUString() );
5612                         ImplAddNWFSeparator( this, aControlValue );
5613 
5614                         // draw selected item
5615                         DrawNativeControl( CTRL_MENUBAR, PART_MENU_ITEM,
5616                                            aRect,
5617                                            CTRL_STATE_ENABLED | CTRL_STATE_SELECTED,
5618                                            aControlValue,
5619                                            OUString() );
5620                     }
5621                     else
5622                     {
5623                         SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
5624                         SetLineColor();
5625                         DrawRect( aRect );
5626                     }
5627                 }
5628                 else
5629                 {
5630                     if( IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL) )
5631                     {
5632                         MenubarValue aMenubarValue;
5633                         aMenubarValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight( this );
5634 
5635                         // use full window size to get proper gradient
5636                         // but clip accordingly
5637                         Point aPt;
5638                         Rectangle aCtrlRect( aPt, GetOutputSizePixel() );
5639 
5640                         DrawNativeControl( CTRL_MENUBAR, PART_ENTIRE_CONTROL, aCtrlRect, CTRL_STATE_ENABLED, aMenubarValue, rtl::OUString() );
5641                         ImplAddNWFSeparator( this, aMenubarValue );
5642                     }
5643                     else
5644                         Erase( aRect );
5645                 }
5646                 Pop();
5647                 pMenu->ImplPaint( this, 0, 0, pData, bHighlight );
5648             }
5649             return;
5650         }
5651 
5652         nX += pData->aSz.Width();
5653     }
5654 }
5655 
5656 Rectangle MenuBarWindow::ImplGetItemRect( sal_uInt16 nPos )
5657 {
5658 	Rectangle aRect;
5659     if( pMenu )
5660     {
5661         long nX = 0;
5662         sal_uLong nCount = pMenu->pItemList->Count();
5663         for ( sal_uLong n = 0; n < nCount; n++ )
5664         {
5665             MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
5666             if ( n == nPos )
5667             {
5668                 if ( pData->eType != MENUITEM_SEPARATOR )
5669                     // #107747# give menuitems the height of the menubar
5670                     aRect = Rectangle( Point( nX, 1 ), Size( pData->aSz.Width(), GetOutputSizePixel().Height()-2 ) );
5671                 break;
5672             }
5673 
5674             nX += pData->aSz.Width();
5675         }
5676     }
5677 	return aRect;
5678 }
5679 
5680 void MenuBarWindow::KeyInput( const KeyEvent& rKEvent )
5681 {
5682     if ( !ImplHandleKeyEvent( rKEvent ) )
5683         Window::KeyInput( rKEvent );
5684 }
5685 
5686 sal_Bool MenuBarWindow::ImplHandleKeyEvent( const KeyEvent& rKEvent, sal_Bool bFromMenu )
5687 {
5688     if( ! pMenu )
5689         return sal_False;
5690 
5691     if ( pMenu->bInCallback )
5692         return sal_True;    // schlucken
5693 
5694     sal_Bool bDone = sal_False;
5695     sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
5696 
5697 	if( GetParent() )
5698 	{
5699 		if( GetParent()->GetWindow( WINDOW_CLIENT )->IsSystemWindow() )
5700         {
5701 		    SystemWindow *pSysWin = (SystemWindow*)GetParent()->GetWindow( WINDOW_CLIENT );
5702 		    if( pSysWin->GetTaskPaneList() )
5703 			    if( pSysWin->GetTaskPaneList()->HandleKeyEvent( rKEvent ) )
5704 				    return sal_True;
5705         }
5706 	}
5707 
5708     if ( nCode == KEY_MENU && !rKEvent.GetKeyCode().IsShift() ) // only F10, not Shift-F10
5709     {
5710         mbAutoPopup = ImplGetSVData()->maNWFData.mbOpenMenuOnF10;
5711         if ( nHighlightedItem == ITEMPOS_INVALID )
5712         {
5713             ChangeHighlightItem( 0, sal_False );
5714             GrabFocus();
5715         }
5716         else
5717         {
5718             ChangeHighlightItem( ITEMPOS_INVALID, sal_False );
5719             nSaveFocusId = 0;
5720         }
5721         bDone = sal_True;
5722     }
5723     else if ( bFromMenu )
5724     {
5725         if ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) ||
5726 			( nCode == KEY_HOME ) || ( nCode == KEY_END ) )
5727         {
5728             sal_uInt16 n = nHighlightedItem;
5729             if ( n == ITEMPOS_INVALID )
5730             {
5731                 if ( nCode == KEY_LEFT)
5732                     n = 0;
5733                 else
5734                     n = pMenu->GetItemCount()-1;
5735             }
5736 
5737             // handling gtk like (aka mbOpenMenuOnF10)
5738             // do not highlight an item when opening a sub menu
5739             // unless there already was a higlighted sub menu item
5740             bool bWasHighlight = false;
5741             if( pActivePopup )
5742             {
5743                 MenuFloatingWindow* pSubWindow = dynamic_cast<MenuFloatingWindow*>(pActivePopup->ImplGetWindow());
5744                 if( pSubWindow )
5745                     bWasHighlight = (pSubWindow->GetHighlightedItem() != ITEMPOS_INVALID);
5746             }
5747 
5748             sal_uInt16 nLoop = n;
5749 
5750 			if( nCode == KEY_HOME )
5751 				{ n = (sal_uInt16)-1; nLoop = n+1; }
5752 			if( nCode == KEY_END )
5753 				{ n = pMenu->GetItemCount(); nLoop = n-1; }
5754 
5755             do
5756             {
5757                 if ( nCode == KEY_LEFT || nCode == KEY_END )
5758                 {
5759                     if ( n )
5760                         n--;
5761                     else
5762                         n = pMenu->GetItemCount()-1;
5763                 }
5764                 if ( nCode == KEY_RIGHT || nCode == KEY_HOME )
5765                 {
5766                     n++;
5767                     if ( n >= pMenu->GetItemCount() )
5768                         n = 0;
5769                 }
5770 
5771                 MenuItemData* pData = (MenuItemData*)pMenu->GetItemList()->GetDataFromPos( n );
5772                 if ( ( pData->eType != MENUITEM_SEPARATOR ) && pMenu->ImplIsVisible( n ) )
5773                 {
5774                     sal_Bool bDoSelect = sal_True;
5775                     if( ImplGetSVData()->maNWFData.mbOpenMenuOnF10 )
5776                         bDoSelect = bWasHighlight;
5777                     ChangeHighlightItem( n, bDoSelect );
5778                     break;
5779                 }
5780             } while ( n != nLoop );
5781             bDone = sal_True;
5782         }
5783         else if ( nCode == KEY_RETURN )
5784         {
5785             if( pActivePopup ) KillActivePopup();
5786 			else
5787 				if ( !mbAutoPopup )
5788 				{
5789 					ImplCreatePopup( sal_True );
5790 					mbAutoPopup = sal_True;
5791 				}
5792             bDone = sal_True;
5793         }
5794         else if ( ( nCode == KEY_UP ) || ( nCode == KEY_DOWN ) )
5795         {
5796             if ( !mbAutoPopup )
5797             {
5798                 ImplCreatePopup( sal_True );
5799                 mbAutoPopup = sal_True;
5800             }
5801             bDone = sal_True;
5802         }
5803         else if ( nCode == KEY_ESCAPE || ( nCode == KEY_F6 && rKEvent.GetKeyCode().IsMod1() ) )
5804         {
5805 			if( pActivePopup )
5806 			{
5807 				// bring focus to menu bar without any open popup
5808 				mbAutoPopup = sal_False;
5809 				sal_uInt16 n = nHighlightedItem;
5810 				nHighlightedItem = ITEMPOS_INVALID;
5811 				bStayActive = sal_True;
5812 				ChangeHighlightItem( n, sal_False );
5813 				bStayActive = sal_False;
5814 				KillActivePopup();
5815 				GrabFocus();
5816 			}
5817 			else
5818 				ChangeHighlightItem( ITEMPOS_INVALID, sal_False );
5819 
5820             if( nCode == KEY_F6 && rKEvent.GetKeyCode().IsMod1() )
5821             {
5822                 // put focus into document
5823                 GrabFocusToDocument();
5824             }
5825 
5826             bDone = sal_True;
5827         }
5828     }
5829 
5830     if ( !bDone && ( bFromMenu || rKEvent.GetKeyCode().IsMod2() ) )
5831     {
5832         xub_Unicode nCharCode = rKEvent.GetCharCode();
5833         if ( nCharCode )
5834         {
5835             sal_uInt16 nEntry, nDuplicates;
5836             MenuItemData* pData = pMenu->GetItemList()->SearchItem( nCharCode, rKEvent.GetKeyCode(), nEntry, nDuplicates, nHighlightedItem );
5837             if ( pData && (nEntry != ITEMPOS_INVALID) )
5838             {
5839                 mbAutoPopup = sal_True;
5840                 ChangeHighlightItem( nEntry, sal_True );
5841                 bDone = sal_True;
5842             }
5843             else
5844             {
5845                 // Wegen Systemmenu und anderen System-HotKeys, nur
5846                 // eigenstaendige Character-Kombinationen auswerten
5847                 sal_uInt16 nKeyCode = rKEvent.GetKeyCode().GetCode();
5848                 if ( ((nKeyCode >= KEY_A) && (nKeyCode <= KEY_Z)) )
5849                     Sound::Beep();
5850             }
5851         }
5852     }
5853     return bDone;
5854 }
5855 
5856 void MenuBarWindow::Paint( const Rectangle& )
5857 {
5858     if( ! pMenu )
5859         return;
5860 
5861     // no VCL paint if native menus
5862     if( pMenu->ImplGetSalMenu() && pMenu->ImplGetSalMenu()->VisibleMenuBar() )
5863     {
5864         ImplGetFrame()->DrawMenuBar();
5865         return;
5866     }
5867 
5868     if( IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL) )
5869     {
5870         Point aPt;
5871         Rectangle aCtrlRegion( aPt, GetOutputSizePixel() );
5872 
5873         MenubarValue aMenubarValue;
5874         aMenubarValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight( this );
5875 
5876         DrawNativeControl( CTRL_MENUBAR, PART_ENTIRE_CONTROL, aCtrlRegion, CTRL_STATE_ENABLED, aMenubarValue, rtl::OUString() );
5877         ImplAddNWFSeparator( this, aMenubarValue );
5878     }
5879     SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
5880     pMenu->ImplPaint( this, 0 );
5881     if ( nHighlightedItem != ITEMPOS_INVALID )
5882         HighlightItem( nHighlightedItem, sal_True );
5883 
5884 	// in high contrast mode draw a separating line on the lower edge
5885 	if( ! IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL) &&
5886 		GetSettings().GetStyleSettings().GetHighContrastMode() )
5887     {
5888 		Push( PUSH_LINECOLOR | PUSH_MAPMODE );
5889 		SetLineColor( Color( COL_WHITE ) );
5890 		SetMapMode( MapMode( MAP_PIXEL ) );
5891 		Size aSize = GetSizePixel();
5892 		DrawLine( Point( 0, aSize.Height()-1 ), Point( aSize.Width()-1, aSize.Height()-1 ) );
5893 		Pop();
5894     }
5895 
5896 }
5897 
5898 void MenuBarWindow::Resize()
5899 {
5900     Size aOutSz = GetOutputSizePixel();
5901     long n      = aOutSz.Height()-4;
5902     long nX     = aOutSz.Width()-3;
5903     long nY     = 2;
5904 
5905     if ( aCloser.IsVisible() )
5906     {
5907         aCloser.Hide();
5908         aCloser.SetImages( n );
5909         Size aTbxSize( aCloser.CalcWindowSizePixel() );
5910         nX -= aTbxSize.Width();
5911         long nTbxY = (aOutSz.Height() - aTbxSize.Height())/2;
5912         aCloser.SetPosSizePixel( nX, nTbxY, aTbxSize.Width(), aTbxSize.Height() );
5913         nX -= 3;
5914         aCloser.Show();
5915     }
5916     if ( aFloatBtn.IsVisible() )
5917     {
5918         nX -= n;
5919         aFloatBtn.SetPosSizePixel( nX, nY, n, n );
5920     }
5921     if ( aHideBtn.IsVisible() )
5922     {
5923         nX -= n;
5924         aHideBtn.SetPosSizePixel( nX, nY, n, n );
5925     }
5926 
5927     aFloatBtn.SetSymbol( SYMBOL_FLOAT );
5928     aHideBtn.SetSymbol( SYMBOL_HIDE );
5929     //aCloser.SetSymbol( SYMBOL_CLOSE ); //is a toolbox now
5930 
5931     Invalidate();
5932 }
5933 
5934 sal_uInt16 MenuBarWindow::ImplFindEntry( const Point& rMousePos ) const
5935 {
5936     if( pMenu )
5937     {
5938         long nX = 0;
5939         sal_uInt16 nCount = (sal_uInt16)pMenu->pItemList->Count();
5940         for ( sal_uInt16 n = 0; n < nCount; n++ )
5941         {
5942             MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
5943             if ( pMenu->ImplIsVisible( n ) )
5944             {
5945                 nX += pData->aSz.Width();
5946                 if ( nX > rMousePos.X() )
5947                     return (sal_uInt16)n;
5948             }
5949         }
5950     }
5951     return ITEMPOS_INVALID;
5952 }
5953 
5954 void MenuBarWindow::RequestHelp( const HelpEvent& rHEvt )
5955 {
5956     sal_uInt16 nId = nHighlightedItem;
5957     if ( rHEvt.GetMode() & (HELPMODE_CONTEXT | HELPMODE_EXTENDED) )
5958         ChangeHighlightItem( ITEMPOS_INVALID, sal_True );
5959 
5960 	Rectangle aHighlightRect( ImplGetItemRect( nHighlightedItem ) );
5961     if( !ImplHandleHelpEvent( this, pMenu, nId, rHEvt, aHighlightRect ) )
5962         Window::RequestHelp( rHEvt );
5963 }
5964 
5965 void MenuBarWindow::StateChanged( StateChangedType nType )
5966 {
5967     Window::StateChanged( nType );
5968 
5969     if ( ( nType == STATE_CHANGE_CONTROLFOREGROUND ) ||
5970          ( nType == STATE_CHANGE_CONTROLBACKGROUND ) )
5971     {
5972         ImplInitMenuWindow( this, sal_False, sal_True );
5973         Invalidate();
5974     }
5975     else if( pMenu )
5976         pMenu->ImplKillLayoutData();
5977 
5978 }
5979 
5980 void MenuBarWindow::ImplLayoutChanged()
5981 {
5982     if( pMenu )
5983     {
5984         ImplInitMenuWindow( this, sal_True, sal_True );
5985         // Falls sich der Font geaendert hat.
5986         long nHeight = pMenu->ImplCalcSize( this ).Height();
5987 
5988         // depending on the native implementation or the displayable flag
5989         // the menubar windows is supressed (ie, height=0)
5990         if( !((MenuBar*) pMenu)->IsDisplayable() ||
5991             ( pMenu->ImplGetSalMenu() && pMenu->ImplGetSalMenu()->VisibleMenuBar() ) )
5992             nHeight = 0;
5993 
5994         SetPosSizePixel( 0, 0, 0, nHeight, WINDOW_POSSIZE_HEIGHT );
5995         GetParent()->Resize();
5996         Invalidate();
5997         Resize();
5998         if( pMenu )
5999             pMenu->ImplKillLayoutData();
6000     }
6001 }
6002 
6003 void MenuBarWindow::ImplInitStyleSettings()
6004 {
6005     if( IsNativeControlSupported( CTRL_MENUBAR, PART_MENU_ITEM ) &&
6006         IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
6007     {
6008         Color aHighlightTextColor = ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor;
6009         if( aHighlightTextColor != Color( COL_TRANSPARENT ) )
6010         {
6011             AllSettings aSettings( GetSettings() );
6012             StyleSettings aStyle( aSettings.GetStyleSettings() );
6013             aStyle.SetMenuHighlightTextColor( aHighlightTextColor );
6014             aSettings.SetStyleSettings( aStyle );
6015             OutputDevice::SetSettings( aSettings );
6016         }
6017     }
6018 }
6019 
6020 void MenuBarWindow::DataChanged( const DataChangedEvent& rDCEvt )
6021 {
6022     Window::DataChanged( rDCEvt );
6023 
6024     if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
6025          (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
6026          ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
6027           (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
6028     {
6029         ImplLayoutChanged();
6030         ImplInitStyleSettings();
6031     }
6032 }
6033 
6034 void MenuBarWindow::LoseFocus()
6035 {
6036     if ( !HasChildPathFocus( sal_True ) )
6037         ChangeHighlightItem( ITEMPOS_INVALID, sal_False, sal_False );
6038 }
6039 
6040 void MenuBarWindow::GetFocus()
6041 {
6042 	if ( nHighlightedItem == ITEMPOS_INVALID )
6043     {
6044         mbAutoPopup = sal_False;    // do not open menu when activated by focus handling like taskpane cycling
6045 		ChangeHighlightItem( 0, sal_False );
6046     }
6047 }
6048 
6049 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > MenuBarWindow::CreateAccessible()
6050 {
6051 	::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xAcc;
6052 
6053 	if ( pMenu )
6054 		xAcc = pMenu->GetAccessible();
6055 
6056 	return xAcc;
6057 }
6058 
6059 sal_uInt16 MenuBarWindow::AddMenuBarButton( const Image& i_rImage, const Link& i_rLink, const String& i_rToolTip, sal_uInt16 i_nPos )
6060 {
6061     // find first free button id
6062     sal_uInt16 nId = IID_DOCUMENTCLOSE;
6063     std::map< sal_uInt16, AddButtonEntry >::const_iterator it;
6064     if( i_nPos > m_aAddButtons.size() )
6065         i_nPos = static_cast<sal_uInt16>(m_aAddButtons.size());
6066     do
6067     {
6068         nId++;
6069         it = m_aAddButtons.find( nId );
6070     } while( it != m_aAddButtons.end() && nId < 128 );
6071     DBG_ASSERT( nId < 128, "too many addbuttons in menubar" );
6072     AddButtonEntry& rNewEntry = m_aAddButtons[nId];
6073     rNewEntry.m_nId = nId;
6074     rNewEntry.m_aSelectLink = i_rLink;
6075     aCloser.InsertItem( nId, i_rImage, 0, 0 );
6076     aCloser.calcMinSize();
6077     ShowButtons( aCloser.IsItemVisible( IID_DOCUMENTCLOSE ),
6078                  aFloatBtn.IsVisible(),
6079                  aHideBtn.IsVisible() );
6080     ImplLayoutChanged();
6081 
6082     if( pMenu->mpSalMenu )
6083         pMenu->mpSalMenu->AddMenuBarButton( SalMenuButtonItem( nId, i_rImage, i_rToolTip ) );
6084 
6085     return nId;
6086 }
6087 
6088 void MenuBarWindow::SetMenuBarButtonHighlightHdl( sal_uInt16 nId, const Link& rLink )
6089 {
6090     std::map< sal_uInt16, AddButtonEntry >::iterator it = m_aAddButtons.find( nId );
6091     if( it != m_aAddButtons.end() )
6092         it->second.m_aHighlightLink = rLink;
6093 }
6094 
6095 Rectangle MenuBarWindow::GetMenuBarButtonRectPixel( sal_uInt16 nId )
6096 {
6097     Rectangle aRect;
6098     if( m_aAddButtons.find( nId ) != m_aAddButtons.end() )
6099     {
6100         if( pMenu->mpSalMenu )
6101         {
6102             aRect = pMenu->mpSalMenu->GetMenuBarButtonRectPixel( nId, ImplGetWindowImpl()->mpFrame );
6103             if( aRect == Rectangle( Point( -1, -1 ), Size( 1, 1 ) ) )
6104             {
6105                 // system menu button is somehwere but location cannot be determined
6106                 return Rectangle();
6107             }
6108         }
6109 
6110         if( aRect.IsEmpty() )
6111         {
6112             aRect = aCloser.GetItemRect( nId );
6113             Point aOffset = aCloser.OutputToScreenPixel( Point() );
6114             aRect.Move( aOffset.X(), aOffset.Y() );
6115         }
6116     }
6117     return aRect;
6118 }
6119 
6120 void MenuBarWindow::RemoveMenuBarButton( sal_uInt16 nId )
6121 {
6122 	sal_uInt16 nPos = aCloser.GetItemPos( nId );
6123     aCloser.RemoveItem( nPos );
6124     m_aAddButtons.erase( nId );
6125     aCloser.calcMinSize();
6126     ImplLayoutChanged();
6127 
6128     if( pMenu->mpSalMenu )
6129         pMenu->mpSalMenu->RemoveMenuBarButton( nId );
6130 }
6131 
6132 bool MenuBarWindow::HandleMenuButtonEvent( sal_uInt16 i_nButtonId )
6133 {
6134     std::map< sal_uInt16, AddButtonEntry >::iterator it = m_aAddButtons.find( i_nButtonId );
6135     if( it != m_aAddButtons.end() )
6136     {
6137         MenuBar::MenuBarButtonCallbackArg aArg;
6138         aArg.nId = it->first;
6139         aArg.bHighlight = true;
6140         aArg.pMenuBar = dynamic_cast<MenuBar*>(pMenu);
6141         return it->second.m_aSelectLink.Call( &aArg );
6142     }
6143     return sal_False;
6144 }
6145 
6146 ImplMenuDelData::ImplMenuDelData( const Menu* pMenu )
6147 : mpNext( 0 )
6148 , mpMenu( 0 )
6149 {
6150 	if( pMenu )
6151 		const_cast< Menu* >( pMenu )->ImplAddDel( *this );
6152 }
6153 
6154 ImplMenuDelData::~ImplMenuDelData()
6155 {
6156 	if( mpMenu )
6157 		const_cast< Menu* >( mpMenu )->ImplRemoveDel( *this );
6158 }
6159