@@ -314,7 +314,6 @@ MCButton::MCButton()
314314 menucontrol = MENUCONTROL_NONE;
315315 menulines = DEFAULT_MENU_LINES;
316316 menuhasitemtags = false ;
317- menu = NULL ; // stack based menu
318317 m_system_menu = NULL ;
319318 entry = NULL ;
320319 tabs = MCValueRetain (kMCEmptyArray );
@@ -354,7 +353,6 @@ MCButton::MCButton(const MCButton &bref) : MCControl(bref)
354353 menucontrol = bref.menucontrol ;
355354 menuhasitemtags = bref.menuhasitemtags ;
356355 menustring = MCValueRetain (bref.menustring );
357- menu = NULL ;
358356 m_system_menu = NULL ;
359357 entry = NULL ;
360358 tabs = MCValueRetain (kMCEmptyArray );
@@ -412,8 +410,11 @@ MCButton::~MCButton()
412410
413411void MCButton::removelink (MCObject *optr)
414412{
415- if (optr == menu)
416- menu = NULL ;
413+ if (menu.IsBound () && optr == menu)
414+ {
415+ MCValueAssign (menuname, kMCEmptyName );
416+ menu = nil;
417+ }
417418}
418419
419420bool MCButton::imagechanged (MCImage *p_image, bool p_deleting)
@@ -497,8 +498,8 @@ void MCButton::open()
497498 break ;
498499 default :
499500 findmenu (true );
500- if (!MCNameIsEmpty (menuname) && menu != NULL )
501- menu->installaccels (getstack ());
501+ if (!MCNameIsEmpty (menuname) && menu. IsValid () )
502+ menu. GetAs <MCStack>() ->installaccels (getstack ());
502503 break ;
503504 }
504505 }
@@ -715,15 +716,15 @@ Boolean MCButton::kdown(MCStringRef p_string, KeySym key)
715716 case XK_WheelUp:
716717 case XK_WheelLeft:
717718 case XK_WheelRight:
718- if (menu -> getcontrols () -> gettype () == CT_FIELD)
719- if (menu -> getcontrols () -> kdown (p_string, key))
719+ if (menu. GetAs <MCStack>() -> getcontrols () -> gettype () == CT_FIELD)
720+ if (menu. GetAs <MCStack>() -> getcontrols () -> kdown (p_string, key))
720721 return True;
721722 break ;
722723 case XK_space:
723724 case XK_Return:
724725 case XK_KP_Enter:
725726 closemenu (False, True);
726- menu->menukdown (p_string, key, &t_pick, menuhistory);
727+ menu. GetAs <MCStack>() ->menukdown (p_string, key, &t_pick, menuhistory);
727728
728729 // This check must be for null (not empty) because an empty pick
729730 // indicates that the function succeeded while a null pick means
@@ -757,7 +758,7 @@ Boolean MCButton::kdown(MCStringRef p_string, KeySym key)
757758 MCmenuobjectptr = NULL ;
758759 return True;
759760 default :
760- MCButton *mbptr = menu->findmnemonic (t_char);
761+ MCButton *mbptr = menu. GetAs <MCStack>() ->findmnemonic (t_char);
761762 if (mbptr != NULL )
762763 {
763764 closemenu (False, True);
@@ -771,7 +772,7 @@ Boolean MCButton::kdown(MCStringRef p_string, KeySym key)
771772 else
772773 t_label = mbptr->getlabeltext ();
773774
774- menu->menukdown (p_string, key, &t_pick, menuhistory);
775+ menu. GetAs <MCStack>() ->menukdown (p_string, key, &t_pick, menuhistory);
775776 Exec_stat es = handlemenupick (t_label, nil);
776777 if (es == ES_NOT_HANDLED || es == ES_PASS)
777778 message_with_args (MCM_mouse_up, menubutton);
@@ -856,7 +857,10 @@ Boolean MCButton::mfocus(int2 x, int2 y)
856857 if ( sptr == NULL )
857858 return False;
858859
859- sptr->translatecoords (menu, tx, ty);
860+ if (!(menu.IsValid ()))
861+ return False;
862+
863+ sptr->translatecoords (menu.GetAs <MCStack>(), tx, ty);
860864 MCRectangle trect = sptr->getrect ();
861865 Boolean handled = menu->mfocus (tx, ty);
862866 tx = x + trect.x ;
@@ -936,7 +940,7 @@ Boolean MCButton::mfocus(int2 x, int2 y)
936940 {
937941 uint2 fheight;
938942 fheight = gettextheight ();
939- MCField *fptr = (MCField *)menu->getcontrols ();
943+ MCField *fptr = (MCField *)menu. GetAs <MCStack>() ->getcontrols ();
940944 fptr->vscroll (my < rect.y + rect.height ? -fheight : fheight, True);
941945 fptr->resetscrollbars (True);
942946 }
@@ -1140,6 +1144,9 @@ Boolean MCButton::mdown(uint2 which)
11401144 state |= CS_MFOCUSED;
11411145 if (state & CS_SUBMENU && (menubutton == 0 || (uint1)which == menubutton))
11421146 {
1147+ if (!(menu.IsValid ()))
1148+ return False;
1149+
11431150 // SN-2014-08-26: [[ Bug 13201 ]] mx/my are now related to the button's rectangle,
11441151 // not the stack's rectangle anymore.
11451152 // SN-2014-10-17: [[ Bug 13675 ]] mx/my refer to the button's rectangle on Mac only
@@ -1164,7 +1171,7 @@ Boolean MCButton::mdown(uint2 which)
11641171 return mfocus (mx, my);
11651172 }
11661173 }
1167- if ((!MCNameIsEmpty (menuname) || menu != NULL || getstyleint (flags) == F_MENU)
1174+ if ((!MCNameIsEmpty (menuname) || menu. IsValid () || getstyleint (flags) == F_MENU)
11681175 && (menubutton == 0 || (uint1)which == menubutton)
11691176 && (entry == NULL || !MCU_point_in_rect (entry->getrect (), mx, my))
11701177 && (getstack ()->gettool (this ) == T_BROWSE
@@ -1294,7 +1301,11 @@ Boolean MCButton::mup(uint2 which, bool p_release)
12941301 }
12951302
12961303 state &= ~CS_MFOCUSED;
1297- if (state & CS_FIELD_GRAB)
1304+
1305+ if (!(menu.IsValid ()))
1306+ return False;
1307+
1308+ if (state & CS_FIELD_GRAB)
12981309 {
12991310 state &= ~CS_FIELD_GRAB;
13001311 if (state & CS_SUBMENU)
@@ -1343,7 +1354,7 @@ Boolean MCButton::mup(uint2 which, bool p_release)
13431354 // MW-2008-03-27; [[ Bug 6225 ]] Make sure we send a mouseUp in this case
13441355 // by setting the menupoppedup global.
13451356 MCmenupoppedup = true ;
1346- menu->menumup (which, &t_pick, menuhistory);
1357+ menu. GetAs <MCStack>() ->menumup (which, &t_pick, menuhistory);
13471358 MCmenupoppedup = false ;
13481359 if (state & CS_IGNORE_MENU)
13491360 closemenu (True, True);
@@ -1601,7 +1612,7 @@ Boolean MCButton::doubledown(uint2 which)
16011612{
16021613 int2 tx = mx;
16031614 int2 ty = my;
1604- if (menu)
1615+ if (menu. IsValid () )
16051616 {
16061617 MCStack *sptr = MCmousestackptr;
16071618 MCRectangle trect = sptr->getrect ();
@@ -1618,7 +1629,7 @@ Boolean MCButton::doubledown(uint2 which)
16181629 state |= CS_FIELD_GRAB;
16191630 return entry->doubledown (which);
16201631 }
1621- else if (state & CS_SUBMENU && menu && MCU_point_in_rect (menu->getrect (), tx, ty))
1632+ else if (state & CS_SUBMENU && menu. IsValid () && MCU_point_in_rect (menu->getrect (), tx, ty))
16221633 {
16231634 state |= CS_FIELD_GRAB;
16241635 return menu->doubledown (which);
@@ -1637,7 +1648,7 @@ Boolean MCButton::doubleup(uint2 which)
16371648 state &= ~CS_FIELD_GRAB;
16381649 if (entry != NULL )
16391650 return entry->doubleup (which);
1640- else if (state & CS_SUBMENU && menu)
1651+ else if (state & CS_SUBMENU && menu. IsValid () )
16411652 return menu -> doubleup (which);
16421653 }
16431654 return MCControl::doubleup (which);
@@ -1710,7 +1721,7 @@ void MCButton::applyrect(const MCRectangle &nrect)
17101721
17111722 // MW-2010-06-07: [[ Bug 8746 ]] Make sure we rebuild the menu after freeing it,
17121723 // thus ensuring accelerators are not lost.
1713- if (menu != NULL )
1724+ if (menu. IsValid () )
17141725 {
17151726 freemenu (False);
17161727 findmenu (true );
@@ -1740,19 +1751,22 @@ void MCButton::closemenu(Boolean kfocus, Boolean disarm)
17401751 }
17411752 // MW-2011-08-18: [[ Layers ]] Invalidate the whole object.
17421753 layer_redrawall ();
1743- if (kfocus && !(state & CS_MFOCUSED ))
1744- {
1745- menu-> setstate (True, CS_KFOCUSED); // override state
1746- menu-> kunfocus ();
1747- }
1748- MCButton *focused = (MCButton *) menu->getcurcard ()-> getmfocused ();
1749- if (focused != NULL && focused-> gettype () == CT_BUTTON
1750- && focused-> getmenumode () == WM_CASCADE)
1751- focused-> closemenu (kfocus, disarm );
1752-
1753- menu -> mode_closeasmenu ();
1754- menu-> close ( );
1754+ if (menu. IsValid ( ))
1755+ {
1756+ if (kfocus && !( state & CS_MFOCUSED))
1757+ {
1758+ menu-> setstate (True, CS_KFOCUSED); // override state
1759+ menu->kunfocus ();
1760+ }
1761+
1762+ MCButton * focused = (MCButton *)menu. GetAs <MCStack>()-> getcurcard ()-> getmfocused ( );
1763+ if (focused != NULL && focused-> gettype () == CT_BUTTON
1764+ && focused-> getmenumode () == WM_CASCADE)
1765+ focused-> closemenu (kfocus, disarm );
17551766
1767+ menu.GetAs <MCStack>() -> mode_closeasmenu ();
1768+ menu->close ();
1769+ }
17561770 state &= ~(CS_SUBMENU | CS_MOUSE_UP_MENU);
17571771 menudepth--;
17581772 }
@@ -1942,8 +1956,8 @@ void MCButton::activate(Boolean notify, KeySym p_key)
19421956 t_disabled = false ;
19431957 MCAutoStringRef t_pick;
19441958
1945- if (menu != NULL )
1946- menu->findaccel (p_key, &t_pick, t_disabled);
1959+ if (menu. IsValid () )
1960+ menu. GetAs <MCStack>() ->findaccel (p_key, &t_pick, t_disabled);
19471961#ifdef _MAC_DESKTOP
19481962 else if (m_system_menu != nil)
19491963 getmacmenuitemtextfromaccelerator (m_system_menu, p_key, MCmodifierstate, &t_pick, false );
@@ -2336,10 +2350,15 @@ void MCButton::makemenu(sublist *bstack, int2 &stackdepth, uint2 menuflags, MCFo
23362350 newmenu->menuwindow = True;
23372351 MCdispatcher->appendpanel (newmenu);
23382352 if (m->parent == this )
2339- menu = newmenu;
2353+ {
2354+ menu = newmenu->GetHandle ();
2355+ newmenu -> addneed (this );
2356+ }
23402357 else
23412358 {
2342- m->parent ->menu = newmenu;
2359+ m->parent ->menu = newmenu->GetHandle ();
2360+ newmenu -> addneed (m->parent );
2361+
23432362 m->parent ->menumode = WM_CASCADE;
23442363 if (getstyleint (menuflags) == F_CHECK || getstyleint (menuflags) == F_RADIO)
23452364 m->parent ->leftmargin += CHECK_SIZE + leftmargin;
@@ -2560,13 +2579,16 @@ Boolean MCButton::findmenu(bool p_just_for_accel)
25602579 Boolean isunicode = hasunicode ();
25612580 if (!MCNameIsEmpty (menuname))
25622581 {
2563- if (menu == NULL )
2582+ if (!( menu. IsValid ()) )
25642583 {
25652584 MCerrorlock++;
2566- menu = getstack ()->findstackname (menuname);
2567- MCerrorlock--;
2568- if (menu != NULL )
2569- menu->addneed (this );
2585+ MCStack * t_stack = getstack ()->findstackname (menuname);
2586+ MCerrorlock--;
2587+ if (t_stack != nil)
2588+ {
2589+ menu = t_stack->GetHandle ();
2590+ t_stack->addneed (this );
2591+ }
25702592 }
25712593 }
25722594 else if (!MCStringIsEmpty (menustring) && getstyleint (flags) == F_MENU)
@@ -2576,7 +2598,7 @@ Boolean MCButton::findmenu(bool p_just_for_accel)
25762598 MCValueRelease (tabs);
25772599 /* UNCHECKED */ MCStringSplit (menustring, MCSTR (" \n " ), nil, kMCStringOptionCompareExact , tabs);
25782600 }
2579- else if (menu == NULL )
2601+ else if (!( menu. IsValid ()) )
25802602 {
25812603 uint2 fheight;
25822604 fheight = gettextheight ();
@@ -2603,11 +2625,15 @@ Boolean MCButton::findmenu(bool p_just_for_accel)
26032625 MCU_set_rect (trect, 0 , 0 , rect.width , height + 4 );
26042626 trect = MCU_reduce_rect (trect, MClook == LF_MOTIF ? DEFAULT_BORDER : 1 );
26052627 fptr->setrect (trect);
2606- /* UNCHECKED */ MCStackSecurityCreateStack (menu);
2607-
2608- menu->setparent (this );
2609- menu->createmenu (fptr, rect.width , height + 4 );
2610- MCdispatcher->appendpanel (menu);
2628+ MCStack * t_menu;
2629+ if (!MCStackSecurityCreateStack (t_menu))
2630+ return False;
2631+
2632+ t_menu->setparent (this );
2633+ t_menu->createmenu (fptr, rect.width , height + 4 );
2634+ MCdispatcher->appendpanel (t_menu);
2635+ menu = t_menu->GetHandle ();
2636+ t_menu -> addneed (this );
26112637 }
26122638 else
26132639 {
@@ -2653,7 +2679,7 @@ Boolean MCButton::findmenu(bool p_just_for_accel)
26532679 MCValueAssign (tabs, kMCEmptyArray );
26542680 }
26552681 }
2656- return menu != NULL ;
2682+ return menu. IsValid () ;
26572683}
26582684
26592685void MCButton::setmenuhandler (MCButtonMenuHandler *p_handler)
@@ -2734,7 +2760,7 @@ void MCButton::openmenu(Boolean grab)
27342760 && cascade_sptr->getmode () < WM_PULLDOWN)
27352761 {
27362762 MCmousestackptr->kfocusset (this );
2737- if (menu == NULL && !findmenu ())
2763+ if (!( menu. IsValid ()) && !findmenu ())
27382764 return ;
27392765 }
27402766 if (IsMacLFAM () &&
@@ -2785,17 +2811,17 @@ void MCButton::openmenu(Boolean grab)
27852811 }
27862812 rel.x += labelwidth;
27872813 rel.width -= labelwidth;
2788- menu->menuset (menuhistory, rect.height >> 1 );
2814+ menu. GetAs <MCStack>() ->menuset (menuhistory, rect.height >> 1 );
27892815 }
27902816
2791- menu->openrect (rel, (Window_mode)menumode, NULL , WP_DEFAULT, OP_NONE);
2792- menu -> mode_openasmenu (t_did_grab ? sptr : NULL );
2817+ menu. GetAs <MCStack>() ->openrect (rel, (Window_mode)menumode, NULL , WP_DEFAULT, OP_NONE);
2818+ menu. GetAs <MCStack>() -> mode_openasmenu (t_did_grab ? sptr : NULL );
27932819
27942820 // MW-2014-03-11: [[ Bug 11893 ]] Make sure we don't do anything to a stack panel.
27952821 if (menumode == WM_OPTION && MCNameIsEmpty (menuname))
27962822 {
27972823 MCField *t_field = NULL ;
2798- MCObjptr *t_obj = menu->getcurcard ()->getrefs ();
2824+ MCObjptr *t_obj = menu. GetAs <MCStack>() ->getcurcard ()->getrefs ();
27992825 MCObjptr *t_iter = t_obj;
28002826 do
28012827 {
@@ -2816,9 +2842,9 @@ void MCButton::openmenu(Boolean grab)
28162842 }
28172843 int2 tx = mx;
28182844 int2 ty = my;
2819- sptr->translatecoords (menu, tx, ty);
2845+ sptr->translatecoords (menu. GetAs <MCStack>() , tx, ty);
28202846 menu->mfocus (tx, ty);
2821- menu->resetcursor (True);
2847+ menu. GetAs <MCStack>() ->resetcursor (True);
28222848 if (!(state & CS_MFOCUSED))
28232849 menu->kfocusnext (True);
28242850 // MW-2011-08-18: [[ Layers ]] Invalidate the whole object.
@@ -2833,24 +2859,23 @@ void MCButton::freemenu(Boolean force)
28332859#ifdef _MAC_DESKTOP
28342860 macfreemenu ();
28352861#endif
2836- if (menu != NULL && !(state & CS_SUBMENU))
2862+ if (menu. IsValid () && !(state & CS_SUBMENU))
28372863 {
28382864 if (!MCNameIsEmpty (menuname))
28392865 {
2840- menu->removeaccels (getstack ());
2841- menu->removeneed (this );
2842- menu = NULL ;
2866+ menu. GetAs <MCStack>() ->removeaccels (getstack ());
2867+ menu. GetAs <MCStack>() ->removeneed (this );
2868+ menu = nil ;
28432869 }
28442870 else
28452871 {
28462872 if (!MCStringIsEmpty (menustring) || force)
28472873 {
28482874 closemenu (False, True);
2849- MCdispatcher->removepanel (menu);
2875+ MCdispatcher->removepanel (menu. GetAs <MCStack>() );
28502876 MCstacks->deleteaccelerator (this , NULL );
2851- menu->removeneed (this );
2852- delete menu;
2853- menu = NULL ;
2877+ menu.GetAs <MCStack>()->removeneed (this );
2878+ menu = nil;
28542879 }
28552880 }
28562881 }
@@ -2918,7 +2943,7 @@ bool MCButton::menuisopen()
29182943#ifdef _MAC_DESKTOP
29192944 return macmenuisopen ();
29202945#else
2921- return menu != nil && menu->getopened ();
2946+ return menu. IsValid () && menu->getopened ();
29222947#endif
29232948}
29242949
@@ -3865,6 +3890,11 @@ IO_stat MCButton::load(IO_handle stream, uint32_t version)
38653890 return IO_NORMAL;
38663891}
38673892
3893+ MCStack * MCButton::getmenu ()
3894+ {
3895+ return menu.GetAs <MCStack>();
3896+ }
3897+
38683898// //////////////////////////////////////////////////////////////////////////////
38693899
38703900MCPlatformControlType MCButton::getcontroltype ()
0 commit comments