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