use the cached method id's to improve performance.
[AROS.git] / rom / intuition / menutask.c
bloba53b816a3bc6d6f12c2ae082a09a4247dbd3dafe
1 /*
2 Copyright © 1995-2012, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
4 $Id$
5 */
7 #include <proto/exec.h>
8 #include <proto/intuition.h>
9 #include <proto/alib.h>
10 #include <proto/layers.h>
11 #include <proto/graphics.h>
12 #include <proto/keymap.h>
13 #include <proto/cybergraphics.h>
14 #include <exec/memory.h>
15 #include <exec/alerts.h>
16 #include <exec/interrupts.h>
17 #include <exec/ports.h>
18 #include <intuition/intuition.h>
19 #include <intuition/intuitionbase.h>
20 #include <intuition/imageclass.h>
21 #include <graphics/gfxmacros.h>
22 #include <graphics/rpattr.h>
23 #include <devices/inputevent.h>
24 #include <devices/input.h>
25 #include <devices/timer.h>
26 #include "inputhandler.h"
27 #include "intuition_intern.h"
28 #include <string.h>
30 #ifdef SKINS
31 #include "intuition_customize.h"
32 #endif
34 #include "menus.h"
35 #include "menutask.h"
36 #include <cybergraphx/cybergraphics.h>
38 #undef DEBUG
39 #define DEBUG 0
40 #include <aros/debug.h>
42 extern IPTR HookEntry();
44 /**************************************************************************************************/
46 /* this #defines are taken from workbench/libs/gadtools/menus.c!! */
48 #define TEXT_AMIGAKEY_SPACING 6
50 #define ITEXT_EXTRA_LEFT 2
51 #define ITEXT_EXTRA_RIGHT 2
52 #define ITEXT_EXTRA_TOP 1
53 #define ITEXT_EXTRA_BOTTOM 1
55 /**************************************************************************************************/
57 static void HandleMouseMove(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
58 static void HandleMouseClick(struct InputEvent *ie, struct MenuHandlerData *mhd,
59 struct IntuitionBase *IntuitionBase);
60 static void HandleCheckItem(struct Window *win, struct MenuItem *item,
61 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
63 static void HighlightMenuTitle(struct Menu *menu, struct MenuHandlerData *mhd,
64 struct IntuitionBase *IntuitionBase);
66 static struct Menu *FindMenu(WORD *var, struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
67 static struct MenuItem *FindItem(WORD *var, struct MenuHandlerData *mhd);
68 static struct MenuItem *FindSubItem(WORD *var, struct MenuHandlerData *mhd);
70 static void MakeMenuBarWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
71 static void KillMenuBarWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
72 static void RenderMenuBar(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
74 static void MakeMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
75 static void KillMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
76 static void RenderMenu(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
77 static void RenderMenuTitle(struct Menu *menu, struct MenuHandlerData *mhd,
78 struct IntuitionBase *IntuitionBase);
80 static void MakeSubMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
81 static void KillSubMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
82 static void RenderSubMenu(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
84 static void RenderItem(struct MenuItem *item, WORD itemtype, struct Rectangle *box,
85 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
87 static void RenderMenuBG(struct Window *win, struct MenuHandlerData *mhd,
88 struct IntuitionBase *IntuitionBase);
89 static void RenderCheckMark(struct MenuItem *item, WORD itemtype, struct MenuHandlerData *mhd,
90 struct IntuitionBase *IntuitionBase);
91 static void RenderAmigaKey(struct MenuItem *item, WORD itemtype, struct MenuHandlerData *mhd,
92 struct IntuitionBase *IntuitionBase);
93 static void RenderDisabledPattern(struct RastPort *rp, WORD x1, WORD y1, WORD x2, WORD y2,
94 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
95 static void RenderFrame(struct RastPort *rp, WORD x1, WORD y1, WORD x2, WORD y2, WORD state,
96 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
97 static void HighlightItem(struct MenuItem *item, WORD itemtype, struct MenuHandlerData *mhd,
98 struct IntuitionBase *IntuitionBase);
99 static WORD CalcMaxCommKeyWidth(struct Window *win, struct MenuHandlerData *mhd,
100 struct IntuitionBase *IntuitionBase);
101 static void AddToSelection(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase);
103 /**************************************************************************************************/
105 /***************************
106 ** DefaultMenuHandler() **
107 ***************************/
108 void DefaultMenuHandler(struct MenuTaskParams *taskparams)
110 struct IntuitionBase *IntuitionBase = taskparams->intuitionBase;
111 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
112 struct MenuHandlerData *mhd = NULL;
113 UBYTE *mem;
114 struct MsgPort *port = NULL;
115 BOOL success = FALSE;
117 if ((mem = AllocMem(sizeof(struct MsgPort) +
118 sizeof(struct MenuHandlerData), MEMF_PUBLIC | MEMF_CLEAR)))
120 port = (struct MsgPort *)mem;
122 port->mp_Node.ln_Type = NT_MSGPORT;
123 port->mp_Flags = PA_SIGNAL;
124 port->mp_SigBit = AllocSignal(-1);
125 port->mp_SigTask = FindTask(0);
126 NEWLIST(&port->mp_MsgList);
128 mhd = (struct MenuHandlerData *)(mem + sizeof(struct MsgPort));
130 success = TRUE;
132 } /* if ((mem = AllocMem(sizeof(struct MsgPort), MEMF_PUBLIC | MEMF_CLEAR))) */
134 if (success)
136 taskparams->MenuHandlerPort = port;
137 taskparams->success = TRUE;
140 Signal(taskparams->Caller, SIGF_INTUITION);
142 if (!success)
144 D(bug("DefaultMenuHandler: initialization failed. waiting for parent task to kill me.\n"));
145 Wait(0);
148 D(bug("DefaultMenuHandler: initialization ok. Now waiting for messages from Intuition.\n"));
150 for(;;)
152 struct MenuMessage *msg;
154 WaitPort(port);
155 while((msg = GetMenuMessage(port, IntuitionBase)))
157 switch(msg->code)
159 case MMCODE_START:
160 mhd->win = msg->win;
161 mhd->scr = mhd->win->WScreen;
162 mhd->dri = GetScreenDrawInfo(mhd->scr);
163 mhd->menu = msg->win->MenuStrip;
164 mhd->activemenunum = -1;
165 mhd->activeitemnum = -1;
166 mhd->activesubitemnum = -1;
167 mhd->checkmark = ((struct IntWindow *)mhd->win)->Checkmark;
168 mhd->amigakey = ((struct IntWindow *)mhd->win)->AmigaKey;
169 mhd->submenuimage = ((struct IntWindow *)mhd->win)->SubMenuImage;
170 mhd->scrmousex = mhd->scr->MouseX;
171 mhd->scrmousey = mhd->scr->MouseY;
172 mhd->firstmenupick = MENUNULL;
173 mhd->keepmenuup = TRUE;
174 mhd->TrueColor = GetBitMapAttr(mhd->scr->RastPort.BitMap, BMA_DEPTH) > 8 ? TRUE: FALSE;
176 /* close windows in the back first because
177 this is faster */
178 MakeMenuBarWin(mhd, IntuitionBase);
179 HandleMouseMove(mhd, IntuitionBase);
180 mhd->active = TRUE;
181 break;
183 case MMCODE_EVENT:
184 /* there might come additional messages from Intuition
185 even when we have already told it to make the menus
186 inactive, but since everything is async, this cannot
187 be avoided, so check if we are really active */
189 if (mhd->active)
191 switch(msg->ie.ie_Class)
193 case IECLASS_RAWMOUSE:
194 if (msg->ie.ie_Code == IECODE_NOBUTTON)
196 HandleMouseMove(mhd, IntuitionBase);
198 else
200 HandleMouseClick(&msg->ie, mhd, IntuitionBase);
202 break;
205 } /* if (mhd->active) */
206 break;
208 } /* switch(msg->code) */
210 ReplyMenuMessage(msg, IntuitionBase);
212 } /* while((msg = (struct MenuMessage *)GetMsg(port))) */
214 } /* for(;;) */
217 /**************************************************************************************************/
219 /*******************************
220 ** InitDefaultMenuHandler() **
221 *******************************/
222 BOOL InitDefaultMenuHandler(struct IntuitionBase *IntuitionBase)
224 struct MenuTaskParams params;
225 struct Task *task;
226 BOOL result = FALSE;
228 params.intuitionBase = IntuitionBase;
229 params.Caller = FindTask(NULL);
230 params.success = FALSE;
232 SetSignal(0, SIGF_INTUITION);
234 task = NewCreateTask(TASKTAG_NAME, "Intuition menu handler",
235 TASKTAG_PC , DefaultMenuHandler,
236 TASKTAG_ARG1, &params,
237 TAG_DONE);
239 if (task)
241 Wait(SIGF_INTUITION);
243 if (params.success)
245 result = TRUE;
246 GetPrivIBase(IntuitionBase)->MenuHandlerPort = params.MenuHandlerPort;
248 else
250 RemTask(task);
253 } /* if ((task = CreateMenuHandlerTask(&params, IntuitionBase))) */
255 return result;
259 /**************************************************************************************************/
261 static void HandleMouseMove(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
263 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
264 struct Layer *lay;
265 struct Window *win = NULL;
266 struct Menu *menu;
267 struct MenuItem *item;
268 WORD new_activemenunum = mhd->activemenunum;
269 WORD new_activeitemnum = mhd->activeitemnum;
270 WORD new_activesubitemnum = mhd->activesubitemnum;
272 mhd->scrmousex = mhd->scr->MouseX;
273 mhd->scrmousey = mhd->scr->MouseY;
275 LockLayerInfo(&mhd->scr->LayerInfo);
276 lay = WhichLayer(&mhd->scr->LayerInfo, mhd->scrmousex, mhd->scrmousey);
277 UnlockLayerInfo(&mhd->scr->LayerInfo);
279 if (lay)
281 win = (struct Window *)lay->Window;
283 if (win && (win == mhd->submenuwin))
285 /* Mouse over submenu box */
286 item = FindSubItem(&new_activesubitemnum, mhd);
288 if (new_activesubitemnum != mhd->activesubitemnum)
290 if (mhd->activesubitemnum != -1)
292 HighlightItem(mhd->activesubitem, ITEM_SUBITEM, mhd, IntuitionBase);
295 mhd->activesubitemnum = new_activesubitemnum;
296 mhd->activesubitem = item;
298 if (item)
300 HighlightItem(mhd->activesubitem, ITEM_SUBITEM, mhd, IntuitionBase);
305 else if (win && (win == mhd->menuwin))
307 item = FindItem(&new_activeitemnum, mhd);
309 if (new_activeitemnum != mhd->activeitemnum)
311 if (mhd->activeitemnum != -1)
313 HighlightItem(mhd->activeitem, ITEM_ITEM, mhd, IntuitionBase);
314 KillSubMenuWin(mhd, IntuitionBase);
317 mhd->activeitemnum = new_activeitemnum;
318 mhd->activeitem = item;
320 if (item)
322 HighlightItem(mhd->activeitem, ITEM_ITEM, mhd, IntuitionBase);
324 if (item->SubItem)
326 MakeSubMenuWin(mhd, IntuitionBase);
330 } /* if (win && (win == mhd->menuwin)) */
331 else if (win && (win == mhd->menubarwin))
333 /* Mouse over menu box */
335 menu = FindMenu(&new_activemenunum, mhd, IntuitionBase);
337 if (new_activemenunum != mhd->activemenunum)
340 if (mhd->activemenunum != -1)
342 HighlightMenuTitle(mhd->activemenu, mhd, IntuitionBase);
343 KillMenuWin(mhd, IntuitionBase);
344 KillSubMenuWin(mhd, IntuitionBase);
347 mhd->activemenunum = new_activemenunum;
348 mhd->activemenu = menu;
350 if (menu)
352 HighlightMenuTitle(mhd->activemenu, mhd, IntuitionBase);
353 MakeMenuWin(mhd, IntuitionBase);
357 if ((mhd->activeitemnum != -1) && (!mhd->submenuwin))
359 HighlightItem(mhd->activeitem, ITEM_ITEM, mhd, IntuitionBase);
360 mhd->activeitemnum = -1;
361 mhd->activeitem = NULL;
364 } /* if (win && (win == mhd->menubarwin)) */
365 else
367 win = NULL;
369 } /* if ((lay = WhichLayer(&mhd->scr->LayerInfo, mhd->scrmousex, mhd->scrmousey))) */
371 if (!win)
373 /* mouse outside any menu window */
375 if ((mhd->activeitemnum != -1) && (!mhd->submenuwin))
377 HighlightItem(mhd->activeitem, ITEM_ITEM, mhd, IntuitionBase);
378 mhd->activeitemnum = -1;
379 mhd->activeitem = NULL;
381 else if (mhd->activesubitemnum != -1)
383 HighlightItem(mhd->activesubitem, ITEM_SUBITEM, mhd, IntuitionBase);
384 mhd->activesubitemnum = -1;
385 mhd->activesubitem = NULL;
391 /**************************************************************************************************/
393 static void HandleSelection(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
395 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
396 struct Layer *lay;
398 LockLayerInfo(&mhd->scr->LayerInfo);
399 lay = WhichLayer(&mhd->scr->LayerInfo, mhd->scrmousex, mhd->scrmousey);
400 UnlockLayerInfo(&mhd->scr->LayerInfo);
402 if (lay)
404 struct Window *win = (struct Window *)lay->Window;
405 struct MenuItem *item = NULL;
407 if (win && (win == mhd->submenuwin) && (mhd->activesubitemnum != -1))
408 item = mhd->activesubitem;
409 else if (win && (win == mhd->menuwin) && (mhd->activeitemnum != -1))
410 item = mhd->activeitem;
412 if (item) {
413 if (item->Flags & CHECKIT)
414 HandleCheckItem(win, item, mhd, IntuitionBase);
417 AddToSelection(mhd, IntuitionBase);
421 /**************************************************************************************************/
423 static void HandleMouseClick(struct InputEvent *ie, struct MenuHandlerData *mhd,
424 struct IntuitionBase *IntuitionBase)
426 BOOL die = FALSE;
427 ULONG sticky = GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_STICKYMENUS; /* ic_Flags is ULONG */
429 switch(ie->ie_Code)
431 case MENUUP:
432 sticky = sticky && (DoubleClick(
433 GetPrivIBase(IntuitionBase)->LastMenuDownSecs,
434 GetPrivIBase(IntuitionBase)->LastMenuDownMicro,
435 ie->ie_TimeStamp.tv_secs, ie->ie_TimeStamp.tv_micro)
436 || mhd->keepmenuup);
437 if (sticky)
438 break;
440 case SELECTDOWN:
441 if (!sticky)
443 HandleSelection(mhd, IntuitionBase);
445 if (ie->ie_Code == MENUUP)
446 die = TRUE;
449 break;
451 case SELECTUP:
452 if (sticky)
454 HandleSelection(mhd, IntuitionBase);
455 die = TRUE;
457 break;
459 case MENUDOWN:
460 if (sticky)
462 if (mhd->keepmenuup)
463 mhd->keepmenuup = FALSE;
464 else {
465 HandleSelection(mhd, IntuitionBase);
466 die = TRUE;
468 GetPrivIBase(IntuitionBase)->LastMenuDownSecs =
469 ie->ie_TimeStamp.tv_secs;
470 GetPrivIBase(IntuitionBase)->LastMenuDownMicro =
471 ie->ie_TimeStamp.tv_micro;
473 break;
474 } /* switch(ie->ie_Code) */
476 if (die)
478 KillMenuBarWin(mhd, IntuitionBase);
479 KillMenuWin(mhd, IntuitionBase);
480 KillSubMenuWin(mhd, IntuitionBase);
482 if (mhd->dri)
484 FreeScreenDrawInfo(mhd->scr, mhd->dri);
485 mhd->dri = 0;
487 MH2Int_MakeMenusInactive(mhd->win, mhd->firstmenupick, IntuitionBase);
488 mhd->active = FALSE;
492 /**************************************************************************************************/
494 static void HandleCheckItem(struct Window *win, struct MenuItem *item,
495 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
497 /* Note: If you change something here, you probably must also change
498 menus.c/CheckMenuItemWasClicked() which is used when the
499 user uses the menu key shortcuts! */
501 WORD itemtype = ((win == mhd->menuwin) ? ITEM_ITEM : ITEM_SUBITEM);
503 BOOL re_render = FALSE;
505 if (item->Flags & MENUTOGGLE)
507 item->Flags ^= CHECKED;
508 re_render = TRUE;
510 else
512 if (!(item->Flags & CHECKED))
514 item->Flags |= CHECKED;
515 re_render = TRUE;
519 if (re_render)
521 BOOL toggle_hi = FALSE;
523 if ((item->Flags & HIGHITEM) &&
524 ((item->Flags & HIGHFLAGS) == HIGHCOMP)) toggle_hi = TRUE;
526 if (toggle_hi) HighlightItem(item, itemtype, mhd, IntuitionBase);
527 RenderCheckMark(item, itemtype, mhd, IntuitionBase);
528 if (toggle_hi) HighlightItem(item, itemtype, mhd, IntuitionBase);
532 if (item->MutualExclude)
534 struct MenuItem *checkitem = (itemtype == ITEM_ITEM) ? mhd->activemenu->FirstItem :
535 mhd->activeitem->SubItem;
536 BOOL toggle_hi = FALSE;
537 WORD i;
539 if ((item->Flags & HIGHITEM) &&
540 ((item->Flags & HIGHFLAGS) == HIGHBOX)) toggle_hi = TRUE;
542 if (toggle_hi) HighlightItem(item, itemtype, mhd, IntuitionBase);
544 for(i = 0; (i < 32) && checkitem; i++, checkitem = checkitem->NextItem)
546 if ((item->MutualExclude & (1L << i)) &&
547 ((checkitem->Flags & (CHECKED | CHECKIT)) == (CHECKIT | CHECKED)))
549 checkitem->Flags &= ~CHECKED;
550 RenderCheckMark(checkitem, itemtype, mhd, IntuitionBase);
554 if (toggle_hi) HighlightItem(item, itemtype, mhd, IntuitionBase);
556 } /* if (item->MutualExclude) */
559 /**************************************************************************************************/
561 static inline BOOL CustomDrawBackground(struct RastPort *rp, struct Window *win,
562 LONG itemleft, LONG itemtop, LONG itemwidth, LONG itemheight, UWORD flags,
563 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
565 struct mdpDrawBackground msg;
567 msg.MethodID = MDM_DRAWBACKGROUND;
568 msg.mdp_RPort = rp;
569 msg.mdp_TrueColor = mhd->TrueColor;
570 msg.mdp_X = 0;
571 msg.mdp_Y = 0;
572 msg.mdp_Width = win->Width - 1;
573 msg.mdp_Height = win->Height - 1;
574 msg.mdp_ItemLeft = itemleft;
575 msg.mdp_ItemTop = itemtop;
576 msg.mdp_ItemWidth = itemwidth;
577 msg.mdp_ItemHeight = itemheight;
578 msg.mdp_Flags = flags;
580 msg.mdp_MenuDecorFlags = (MENUS_UNDERMOUSE(IntuitionBase)) ? MDP_MDF_MENUS_UNDERMOUSE : 0;
581 if (win == mhd->submenuwin) { msg.mdp_UserBuffer = mhd->SubDecorUserBuffer; msg.mdp_MenuDecorFlags |= MDP_MDF_SUBITEM; }
582 else if (win == mhd->menuwin) { msg.mdp_UserBuffer = mhd->DecorUserBuffer; msg.mdp_MenuDecorFlags |= MDP_MDF_ITEM; }
583 else { msg.mdp_UserBuffer = mhd->BarDecorUserBuffer; msg.mdp_MenuDecorFlags |= MDP_MDF_MENU; }
585 return DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
588 /**************************************************************************************************/
590 static void HighlightMenuTitle(struct Menu *menu, struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
592 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
594 if ((menu->Flags & MENUENABLED) && mhd->menubarwin)
596 struct RastPort *rp = mhd->menubarwin->RPort;
597 WORD x1, x2, y1, y2;
599 if (MENUS_UNDERMOUSE(IntuitionBase))
601 WORD i;
602 struct Menu *m = mhd->menu;
604 x1 = mhd->innerleft;
606 x2 = x1 + mhd->menubaritemwidth - 1;
608 for(i = 0; m != menu; m = m->NextMenu) i++;
610 y1 = mhd->innertop + i * mhd->menubaritemheight;
611 y2 = y1 + mhd->menubaritemheight - 1;
614 else
616 x1 = menu->LeftEdge + mhd->scr->BarHBorder - mhd->scr->MenuHBorder;
617 if (x1 < 0) x1 = 0;
618 y1 = 0;
619 x2 = x1 + menu->Width - 1;
620 y2 = mhd->scr->BarHeight - 1;
623 menu->Flags ^= HIGHITEM;
624 if (CustomDrawBackground(rp, mhd->win, x1, y1, x2 - x1 + 1, y2 - y1 + 1, menu->Flags, mhd, IntuitionBase))
626 RenderMenuTitle(menu, mhd, IntuitionBase);
627 return;
630 if (MENUS_AMIGALOOK(IntuitionBase))
632 SetDrMd(rp, COMPLEMENT);
633 RectFill(rp, x1, y1, x2, y2);
635 else
637 if (!MENUS_UNDERMOUSE(IntuitionBase))
638 y1++;
640 SetDrMd(rp, JAM1);
641 SetAPen(rp, mhd->dri->dri_Pens[(menu->Flags & HIGHITEM) ? FILLPEN : BACKGROUNDPEN]);
642 RectFill(rp, x1, y1, x2, y2);
643 RenderMenuTitle(menu, mhd, IntuitionBase);
645 if ((menu->Flags & HIGHITEM))
647 if (MENUS_UNDERMOUSE(IntuitionBase))
649 RenderFrame(rp, x1, y1, x2, y2, IDS_SELECTED, mhd, IntuitionBase);
651 else
653 SetAPen(rp, mhd->dri->dri_Pens[SHINEPEN]);
654 RectFill(rp, x1, y1, x1, y2);
655 SetAPen(rp, mhd->dri->dri_Pens[SHADOWPEN]);
656 RectFill(rp, x2, y1, x2, y2);
663 /**************************************************************************************************/
665 static struct Menu *FindMenu(WORD *var, struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
667 struct Menu *menu = NULL;
668 WORD mouse_x, mouse_y, i;
670 if(mhd->menubarwin)
672 mouse_x = mhd->scrmousex - mhd->menubarwin->LeftEdge;
673 mouse_y = mhd->scrmousey - mhd->menubarwin->TopEdge;
675 if (MENUS_UNDERMOUSE(IntuitionBase))
677 menu = NULL;
679 mouse_x -= mhd->innerleft;
680 mouse_y -= mhd->innertop;
682 if ((mouse_x >= 0) && (mouse_x < mhd->menubaritemwidth) && (mouse_y >= 0))
684 i = mouse_y / mhd->menubaritemheight;
686 if ((i >= 0) && (i < mhd->nummenubaritems))
688 WORD i2 = i;
690 menu = mhd->menu;
691 while(i && menu)
693 i--;
694 menu = menu->NextMenu;
697 if (menu && (i == 0))
699 *var = i2;
704 else
706 for(menu = mhd->menu, i = 0; menu; menu = menu->NextMenu, i++)
708 if ((mouse_x >= menu->LeftEdge) &&
709 (mouse_x < menu->LeftEdge + menu->Width) &&
710 (mouse_y >= 0) &&
711 (mouse_y <= mhd->scr->BarHeight))
713 *var = i;
714 break;
719 return menu;
722 /**************************************************************************************************/
724 static struct MenuItem *FindItem(WORD *var, struct MenuHandlerData *mhd)
726 struct MenuItem *item = NULL;
727 WORD mouse_x, mouse_y, i;
729 if (mhd->menuwin)
731 mouse_x = mhd->scrmousex - mhd->menuwin->LeftEdge
732 + mhd->activemenu->JazzX - mhd->innerleft - mhd->menuinnerleft;
733 mouse_y = mhd->scrmousey - mhd->menuwin->TopEdge
734 + mhd->activemenu->JazzY - mhd->innertop - mhd->menuinnertop;
736 for(item = mhd->activemenu->FirstItem, i = 0; item; item = item->NextItem, i++)
738 if ((mouse_x >= item->LeftEdge) &&
739 (mouse_x < item->LeftEdge + item->Width) &&
740 (mouse_y >= item->TopEdge) &&
741 (mouse_y < item->TopEdge + item->Height))
743 *var = i;
744 break;
747 } /* if (mhd->menuwin) */
749 if ((item == NULL) && !mhd->submenuwin) *var = -1;
751 return item;
754 /**************************************************************************************************/
756 static struct MenuItem *FindSubItem(WORD *var, struct MenuHandlerData *mhd)
758 struct MenuItem *item = NULL;
759 WORD mouse_x, mouse_y, i;
761 if (mhd->submenuwin)
763 mouse_x = mhd->scrmousex - mhd->submenuwin->LeftEdge + mhd->submenubox.MinX - mhd->menuinnerleft;
764 mouse_y = mhd->scrmousey - mhd->submenuwin->TopEdge + mhd->submenubox.MinY - mhd->menuinnertop;
766 *var = -1;
768 for(item = mhd->activeitem->SubItem, i = 0; item; item = item->NextItem, i++)
770 if ((mouse_x >= item->LeftEdge) &&
771 (mouse_x < item->LeftEdge + item->Width) &&
772 (mouse_y >= item->TopEdge) &&
773 (mouse_y < item->TopEdge + item->Height))
775 *var = i;
776 break;
780 } /* if (mhd->menuwin) */
782 return item;
785 /**************************************************************************************************/
787 static void MakeMenuBarWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
789 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
790 struct TagItem win_tags[] =
792 {WA_Left , 0 },
793 {WA_Top , 0 },
794 {WA_Width , mhd->scr->Width },
795 {WA_Height , mhd->scr->BarHeight + 1},
796 {WA_AutoAdjust , TRUE },
797 {WA_Borderless , TRUE },
798 {WA_CustomScreen, (IPTR)mhd->scr },
799 {WA_BackFill , (IPTR)LAYERS_NOBACKFILL},
800 {TAG_DONE , 0 }
802 struct Menu *menu;
804 mhd->menubarwin = NULL;
805 /* No entry to draw ? */
806 if(mhd->menu == NULL) return;
808 if (MENUS_UNDERMOUSE(IntuitionBase))
810 struct RastPort *temprp;
811 WORD w, maxw = 0;
813 if (!(temprp = CloneRastPort(&mhd->scr->RastPort))) return;
815 mhd->nummenubaritems = 0;
816 for(menu = mhd->menu; menu; menu = menu->NextMenu)
818 w = TextLength(temprp, menu->MenuName, strlen(menu->MenuName));
819 if (w > maxw) maxw = w;
820 mhd->nummenubaritems++;
823 mhd->menubaritemwidth = maxw + mhd->submenuimage->Width +
824 TEXT_AMIGAKEY_SPACING +
825 ITEXT_EXTRA_LEFT +
826 ITEXT_EXTRA_RIGHT;
828 if (temprp->TxHeight > mhd->submenuimage->Height)
830 mhd->menubaritemheight = temprp->TxHeight;
832 else
834 mhd->menubaritemheight = mhd->submenuimage->Height;
837 mhd->menubaritemheight += (ITEXT_EXTRA_TOP + ITEXT_EXTRA_BOTTOM);
839 struct mdpGetMenuSpaces msg;
841 msg.MethodID = MDM_GETMENUSPACES;
842 msg.mdp_TrueColor = mhd->TrueColor;
843 msg.mdp_InnerLeft = mhd->scr->MenuHBorder;
844 msg.mdp_InnerTop = mhd->scr->MenuVBorder;
845 msg.mdp_InnerRight = mhd->scr->MenuHBorder;
846 msg.mdp_InnerBottom = mhd->scr->MenuVBorder;
847 msg.mdp_ItemInnerLeft = 0;
848 msg.mdp_ItemInnerTop = 0;
849 msg.mdp_ItemInnerRight = 0;
850 msg.mdp_ItemInnerBottom = 0;
851 msg.mdp_MinWidth = 0;
852 msg.mdp_MinHeight = 0;
853 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
854 mhd->innerleft = msg.mdp_InnerLeft;
855 mhd->innerright = msg.mdp_InnerRight;
856 mhd->innertop = msg.mdp_InnerTop;
857 mhd->innerbottom = msg.mdp_InnerBottom;
858 mhd->iteminnerleft = msg.mdp_ItemInnerLeft;
859 mhd->iteminnerright = msg.mdp_ItemInnerRight;
860 mhd->iteminnertop = msg.mdp_ItemInnerTop;
861 mhd->iteminnerbottom = msg.mdp_ItemInnerBottom;
862 mhd->menubaritemwidth += (mhd->iteminnerleft + mhd->iteminnerright);
863 mhd->menubaritemheight += (mhd->iteminnertop + mhd->iteminnerbottom);
865 win_tags[2].ti_Data = mhd->menubaritemwidth + mhd->innerleft + mhd->innerright;
866 win_tags[3].ti_Data = mhd->menubaritemheight * mhd->nummenubaritems + mhd->innertop + mhd->innerbottom;
868 if (win_tags[2].ti_Data < msg.mdp_MinWidth)
870 mhd->menubaritemwidth += (msg.mdp_MinWidth - win_tags[2].ti_Data);
871 win_tags[2].ti_Data = msg.mdp_MinWidth;
874 if (win_tags[3].ti_Data < msg.mdp_MinHeight)
876 win_tags[3].ti_Data = msg.mdp_MinHeight;
879 WORD PosX = mhd->scr->MouseX - win_tags[2].ti_Data / 2;
880 win_tags[1].ti_Data = mhd->scr->MouseY;
882 if ((PosX + win_tags[2].ti_Data) > mhd->scr->Width) PosX = mhd->scr->Width - win_tags[2].ti_Data;
883 if ((win_tags[1].ti_Data + win_tags[3].ti_Data) > mhd->scr->Height) win_tags[1].ti_Data = mhd->scr->Height - win_tags[3].ti_Data;
884 if (PosX < 0) PosX = 0;
885 if (win_tags[1].ti_Data > 32000) win_tags[1].ti_Data = 0;
887 win_tags[0].ti_Data = PosX;
889 FreeRastPort(temprp);
893 IPTR userbuffersize;
894 struct mdpInitMenu msg;
896 GetAttr(MDA_UserBuffer, ((struct IntScreen *)(mhd->scr))->MenuDecorObj, &userbuffersize);
898 if (userbuffersize)
900 mhd->DecorUserBufferSize = userbuffersize;
901 mhd->BarDecorUserBuffer = (IPTR) AllocMem(userbuffersize, MEMF_ANY | MEMF_CLEAR);
902 if (0 == mhd->BarDecorUserBuffer) return;
905 msg.MethodID = MDM_INITMENU;
906 msg.mdp_TrueColor = mhd->TrueColor;
907 msg.mdp_RPort = &mhd->scr->RastPort;
908 msg.mdp_Left = win_tags[0].ti_Data;
909 msg.mdp_Top = win_tags[1].ti_Data;
910 msg.mdp_Width = win_tags[2].ti_Data;
911 msg.mdp_Height = win_tags[3].ti_Data;
912 msg.mdp_UserBuffer = mhd->BarDecorUserBuffer;
913 msg.mdp_ScreenUserBuffer = ((struct IntScreen *) mhd->scr)->DecorUserBuffer;
914 msg.mdp_MenuDecorFlags = (MENUS_UNDERMOUSE(IntuitionBase)) ? MDP_MDF_MENUS_UNDERMOUSE : 0;
915 msg.mdp_MenuDecorFlags |= MDP_MDF_MENU;
917 msg.mdp_Screen = mhd->scr;
919 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
923 D(bug("MakeMenuBarWin: mhd 0x%lx\n", mhd));
925 mhd->menubarwin = OpenWindowTagList(0, win_tags);
927 for(menu = mhd->menu; menu; menu = menu->NextMenu)
929 menu->Flags &= ~HIGHITEM;
932 RenderMenuBar(mhd, IntuitionBase);
935 /**************************************************************************************************/
937 static void KillMenuBarWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
939 if (mhd->menubarwin)
941 struct mdpExitMenu msg;
943 CloseWindow(mhd->menubarwin);
944 mhd->menubarwin = NULL;
946 msg.MethodID = MDM_EXITMENU;
947 msg.mdp_UserBuffer = mhd->BarDecorUserBuffer;
948 msg.mdp_TrueColor = mhd->TrueColor;
949 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
951 if (mhd->BarDecorUserBuffer)
953 FreeMem((void *)mhd->BarDecorUserBuffer, mhd->DecorUserBufferSize);
955 mhd->BarDecorUserBuffer = 0;
960 /**************************************************************************************************/
962 static void RenderMenuBar(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
964 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
965 if (mhd->menubarwin)
967 struct Menu *menu = mhd->menu;
968 struct Window *win = mhd->menubarwin;
969 struct RastPort *rp = win->RPort;
971 SetFont(rp, mhd->dri->dri_Font);
973 /* Bar renders using different pens in Amiga mode than rest of menu */
974 if (MENUS_UNDERMOUSE(IntuitionBase))
976 RenderMenuBG(win, mhd, IntuitionBase);
978 else
980 if (!CustomDrawBackground(rp, win, 0, 0, win->Width - 1, win->Height - 1, 0, mhd, IntuitionBase))
982 if (MENUS_AMIGALOOK(IntuitionBase))
984 SetABPenDrMd(rp, mhd->dri->dri_Pens[BARBLOCKPEN], 0, JAM1);
986 else
988 SetABPenDrMd(rp, mhd->dri->dri_Pens[BACKGROUNDPEN], 0, JAM1);
991 RectFill(rp, 0, 0, win->Width - 1, win->Height - 2);
993 SetAPen(rp, mhd->dri->dri_Pens[BARTRIMPEN]);
994 RectFill(rp, 0, win->Height - 1, win->Width - 1, win->Height - 1);
996 if (!MENUS_AMIGALOOK(IntuitionBase))
998 SetAPen(rp, mhd->dri->dri_Pens[SHINEPEN]);
999 RectFill(rp, 0, 0, 0, win->Height - 2);
1000 RectFill(rp, 1, 0, win->Width - 1, 0);
1001 SetAPen(rp, mhd->dri->dri_Pens[SHADOWPEN]);
1002 RectFill(rp, win->Width - 1, 1, win->Width - 1, win->Height - 2);
1007 for(; menu; menu = menu->NextMenu)
1009 RenderMenuTitle(menu, mhd, IntuitionBase);
1014 /**************************************************************************************************/
1016 static void RenderMenuTitle(struct Menu *menu, struct MenuHandlerData *mhd,
1017 struct IntuitionBase *IntuitionBase)
1019 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1020 struct RastPort *rp;
1021 WORD len = 0;
1022 WORD x, y;
1024 if (menu->MenuName)
1025 len = strlen(menu->MenuName);
1026 else
1028 bug("Intuition: MenuEntry with missing string @ 0x%p\n", menu);
1031 if(mhd->menubarwin)
1033 rp = mhd->menubarwin->RPort;
1034 SetDrMd(rp, JAM1);
1036 if (MENUS_UNDERMOUSE(IntuitionBase))
1038 struct Menu *m;
1039 WORD yoff;
1041 yoff = 0;
1042 for(m = mhd->menu; m && (m != menu);m = m ->NextMenu)
1044 yoff++;
1047 x = mhd->innerleft + ITEXT_EXTRA_LEFT;
1048 y = mhd->innertop + ITEXT_EXTRA_TOP + yoff * mhd->menubaritemheight;
1050 else
1052 x = mhd->scr->BarHBorder + menu->LeftEdge;
1053 y = mhd->scr->BarVBorder + ((mhd->scr->BarHeight - rp->Font->tf_YSize) / 2);
1056 if (menu->MenuName)
1058 if (MENUS_AMIGALOOK(IntuitionBase))
1060 SetAPen(rp, mhd->dri->dri_Pens[BARDETAILPEN]);
1062 else
1064 SetAPen(rp, mhd->dri->dri_Pens[(menu->Flags & HIGHITEM) ? FILLTEXTPEN : TEXTPEN]);
1067 Move(rp, x, y + rp->TxBaseline);
1068 Text(rp, menu->MenuName, len);
1071 if (MENUS_UNDERMOUSE(IntuitionBase))
1073 if (menu->FirstItem)
1075 WORD x2 = mhd->scr->MenuHBorder + mhd->menubaritemwidth - ITEXT_EXTRA_RIGHT - mhd->submenuimage->Width;
1077 DrawImageState(rp, mhd->submenuimage, x2, y + ((mhd->menubaritemheight - mhd->submenuimage->Height) >> 1), IDS_NORMAL, mhd->dri);
1081 if (!(menu->Flags & MENUENABLED))
1083 WORD y2 = y + rp->TxHeight - 1;
1084 WORD x2;
1086 if (MENUS_UNDERMOUSE(IntuitionBase))
1088 x2 = mhd->scr->MenuHBorder + mhd->menubaritemwidth - 1;
1090 else if (menu->MenuName)
1092 x2 = x + TextLength(rp, menu->MenuName, len) - 1;
1093 } else {
1094 x2 = x + TextLength(rp, " ", 1) - 1;
1097 RenderDisabledPattern(rp, x, y, x2, y2, mhd, IntuitionBase);
1102 /**************************************************************************************************/
1104 static void MakeMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1106 struct MenuItem *item;
1108 WORD width = mhd->activemenu->BeatX - mhd->activemenu->JazzX + 1;
1109 WORD height = mhd->activemenu->BeatY - mhd->activemenu->JazzY + 1;
1110 WORD xpos,ypos;
1112 struct mdpGetMenuSpaces msg;
1114 msg.MethodID = MDM_GETMENUSPACES;
1115 msg.mdp_TrueColor = mhd->TrueColor;
1116 msg.mdp_InnerLeft = 0;
1117 msg.mdp_InnerTop = 0;
1118 msg.mdp_InnerRight = 0;
1119 msg.mdp_InnerBottom = 0;
1120 msg.mdp_ItemInnerLeft = 0;
1121 msg.mdp_ItemInnerTop = 0;
1122 msg.mdp_ItemInnerRight = 0;
1123 msg.mdp_ItemInnerBottom = 0;
1124 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1125 mhd->menuinnerleft = msg.mdp_InnerLeft;
1126 mhd->menuinnerright = msg.mdp_InnerRight;
1127 mhd->menuinnertop = msg.mdp_InnerTop;
1128 mhd->menuinnerbottom = msg.mdp_InnerBottom;
1130 width += (mhd->menuinnerleft + mhd->menuinnerright);
1131 height += (mhd->menuinnertop + mhd->menuinnerbottom);
1133 if (MENUS_UNDERMOUSE(IntuitionBase))
1135 xpos = mhd->menubarwin->LeftEdge + mhd->menubarwin->Width - 16;
1136 ypos = mhd->menubarwin->TopEdge;
1138 else
1140 xpos = mhd->activemenu->LeftEdge + mhd->scr->BarHBorder + mhd->activemenu->JazzX;
1142 if (MENUS_AMIGALOOK(IntuitionBase))
1144 ypos = mhd->scr->BarHeight + 1 + mhd->activemenu->JazzY;
1146 else
1148 ypos = mhd->scr->BarHeight + 1;
1153 struct TagItem win_tags[] =
1155 {WA_Left , xpos },
1156 {WA_Top , ypos },
1157 {WA_Width , width },
1158 {WA_Height , height },
1159 {WA_AutoAdjust , TRUE },
1160 {WA_Borderless , TRUE },
1161 {WA_CustomScreen, (IPTR)mhd->scr },
1162 {WA_BackFill , (IPTR)LAYERS_NOBACKFILL},
1163 {TAG_DONE , 0 }
1166 if (MENUS_UNDERMOUSE(IntuitionBase))
1168 win_tags[1].ti_Data += (mhd->menubaritemheight * mhd->activemenunum + mhd->scr->MenuVBorder) -
1169 height / 2;
1170 if (xpos + width > mhd->scr->Width)
1172 win_tags[0].ti_Data = mhd->menubarwin->LeftEdge - width + 16;
1176 if ((win_tags[0].ti_Data + win_tags[2].ti_Data) > mhd->scr->Width) win_tags[0].ti_Data = mhd->scr->Width - win_tags[2].ti_Data;
1177 if ((win_tags[1].ti_Data + win_tags[3].ti_Data) > mhd->scr->Height) win_tags[1].ti_Data = mhd->scr->Height - win_tags[3].ti_Data;
1178 if (((LONG) win_tags[0].ti_Data) < 0) win_tags[0].ti_Data = 0;
1179 if (((LONG) win_tags[1].ti_Data) < 0) win_tags[1].ti_Data = 0;
1181 if ((item = mhd->activemenu->FirstItem))
1184 while(item)
1186 item->Flags &= ~HIGHITEM;
1187 item = item->NextItem;
1190 IPTR userbuffersize;
1192 GetAttr(MDA_UserBuffer, ((struct IntScreen *)(mhd->scr))->MenuDecorObj, &userbuffersize);
1194 if (userbuffersize)
1196 mhd->DecorUserBufferSize = userbuffersize;
1197 mhd->DecorUserBuffer = (IPTR) AllocMem(userbuffersize, MEMF_ANY | MEMF_CLEAR);
1198 if (0 == mhd->DecorUserBuffer) return;
1201 struct mdpInitMenu msg;
1203 msg.MethodID = MDM_INITMENU;
1204 msg.mdp_TrueColor = mhd->TrueColor;
1205 msg.mdp_RPort = &mhd->scr->RastPort;
1206 msg.mdp_Left = win_tags[0].ti_Data;
1207 msg.mdp_Top = win_tags[1].ti_Data;
1208 msg.mdp_Width = width;
1209 msg.mdp_Height = height;
1210 msg.mdp_UserBuffer = mhd->DecorUserBuffer;
1211 msg.mdp_ScreenUserBuffer = ((struct IntScreen *) mhd->scr)->DecorUserBuffer;
1212 msg.mdp_Screen = mhd->scr;
1213 msg.mdp_MenuDecorFlags = (MENUS_UNDERMOUSE(IntuitionBase)) ? MDP_MDF_MENUS_UNDERMOUSE : 0;
1214 msg.mdp_MenuDecorFlags |= MDP_MDF_ITEM;
1216 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1218 mhd->menuwin = OpenWindowTagList(0, win_tags);
1220 mhd->maxcommkeywidth_menu = CalcMaxCommKeyWidth(mhd->menuwin, mhd, IntuitionBase);
1222 RenderMenu(mhd, IntuitionBase);
1224 mhd->activemenu->Flags |= MIDRAWN;
1229 /**************************************************************************************************/
1231 static void KillMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1233 if (mhd->menuwin)
1235 struct MenuItem *item;
1237 CloseWindow(mhd->menuwin);
1238 mhd->menuwin = NULL;
1240 TimeDelay(UNIT_VBLANK,0,20000);
1242 for(item = mhd->activemenu->FirstItem; item; item = item->NextItem)
1244 item->Flags &= ~ISDRAWN;
1246 struct mdpExitMenu msg;
1248 msg.MethodID = MDM_EXITMENU;
1249 msg.mdp_TrueColor = mhd->TrueColor;
1250 msg.mdp_UserBuffer = mhd->DecorUserBuffer;
1251 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1253 if (mhd->DecorUserBuffer)
1255 FreeMem((void *)mhd->DecorUserBuffer, mhd->DecorUserBufferSize);
1257 mhd->DecorUserBuffer = 0;
1259 mhd->activemenu->Flags &= ~MIDRAWN;
1261 mhd->activeitemnum = -1;
1262 mhd->activeitem = NULL;
1266 /**************************************************************************************************/
1268 static void RenderMenu(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1270 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1272 if (mhd->menuwin)
1274 struct MenuItem *item;
1276 RenderMenuBG(mhd->menuwin, mhd, IntuitionBase);
1278 SetFont(mhd->menuwin->RPort, mhd->dri->dri_Font);
1280 for(item = mhd->activemenu->FirstItem; item; item = item->NextItem)
1282 RenderItem(item, ITEM_ITEM, (struct Rectangle *)(&mhd->activemenu->JazzX), mhd, IntuitionBase);
1285 } /* if (mhd->menuwin) */
1288 /**************************************************************************************************/
1290 static void MakeSubMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1292 struct MenuItem *item = mhd->activeitem->SubItem;
1294 struct TagItem win_tags[] =
1296 {WA_Left , 0 },
1297 {WA_Top , 0 },
1298 {WA_Width , 0 },
1299 {WA_Height , 0 },
1300 {WA_AutoAdjust , TRUE },
1301 {WA_Borderless , TRUE },
1302 {WA_CustomScreen, (IPTR)mhd->scr },
1303 {WA_BackFill , (IPTR)LAYERS_NOBACKFILL },
1304 {TAG_DONE }
1307 if(mhd->menubarwin)
1309 GetMenuBox(mhd->menubarwin, item, &mhd->submenubox.MinX,
1310 &mhd->submenubox.MinY,
1311 &mhd->submenubox.MaxX,
1312 &mhd->submenubox.MaxY);
1315 struct mdpGetMenuSpaces msg;
1317 msg.MethodID = MDM_GETMENUSPACES;
1318 msg.mdp_TrueColor = mhd->TrueColor;
1319 msg.mdp_InnerLeft = 0;
1320 msg.mdp_InnerTop = 0;
1321 msg.mdp_InnerRight = 0;
1322 msg.mdp_InnerBottom = 0;
1324 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1325 mhd->menuinnerleft = msg.mdp_InnerLeft;
1326 mhd->menuinnerright = msg.mdp_InnerRight;
1327 mhd->menuinnertop = msg.mdp_InnerTop;
1328 mhd->menuinnerbottom = msg.mdp_InnerBottom;
1331 win_tags[0].ti_Data = mhd->menuwin->LeftEdge +
1332 mhd->activeitem->LeftEdge - mhd->activemenu->JazzX +
1333 mhd->submenubox.MinX;
1335 win_tags[1].ti_Data = mhd->menuwin->TopEdge +
1336 mhd->activeitem->TopEdge - mhd->activemenu->JazzY +
1337 mhd->submenubox.MinY;
1339 win_tags[2].ti_Data = mhd->submenubox.MaxX - mhd->submenubox.MinX + 1 + mhd->menuinnerleft + mhd->menuinnerright;
1340 win_tags[3].ti_Data = mhd->submenubox.MaxY - mhd->submenubox.MinY + 1 + mhd->menuinnertop + mhd->menuinnerbottom;
1342 if ((win_tags[0].ti_Data + win_tags[2].ti_Data) > mhd->scr->Width) win_tags[0].ti_Data = mhd->scr->Width - win_tags[2].ti_Data;
1343 if ((win_tags[1].ti_Data + win_tags[3].ti_Data) > mhd->scr->Height) win_tags[1].ti_Data = mhd->scr->Height - win_tags[3].ti_Data;
1344 if (((LONG) win_tags[0].ti_Data) < 0) win_tags[0].ti_Data = 0;
1345 if (((LONG) win_tags[1].ti_Data) < 0) win_tags[1].ti_Data = 0;
1347 while(item)
1349 item->Flags &= ~HIGHITEM;
1350 item = item->NextItem;
1353 IPTR userbuffersize;
1355 GetAttr(MDA_UserBuffer, ((struct IntScreen *)(mhd->scr))->MenuDecorObj, &userbuffersize);
1357 if (userbuffersize)
1359 mhd->DecorUserBufferSize = userbuffersize;
1360 mhd->SubDecorUserBuffer = (IPTR) AllocMem(userbuffersize, MEMF_ANY | MEMF_CLEAR);
1361 if (0 == mhd->SubDecorUserBuffer) return;
1365 struct mdpInitMenu msg;
1366 msg.MethodID = MDM_INITMENU;
1367 msg.mdp_TrueColor = mhd->TrueColor;
1368 msg.mdp_RPort = &mhd->scr->RastPort;
1369 msg.mdp_Left = win_tags[0].ti_Data;
1370 msg.mdp_Top = win_tags[1].ti_Data;
1371 msg.mdp_Width = win_tags[2].ti_Data;
1372 msg.mdp_Height = win_tags[3].ti_Data;
1373 msg.mdp_UserBuffer = mhd->SubDecorUserBuffer;
1374 msg.mdp_ScreenUserBuffer = ((struct IntScreen *) mhd->scr)->DecorUserBuffer;
1375 msg.mdp_TrueColor = mhd->TrueColor;
1376 msg.mdp_Screen = mhd->scr;
1377 msg.mdp_MenuDecorFlags = (MENUS_UNDERMOUSE(IntuitionBase)) ? MDP_MDF_MENUS_UNDERMOUSE : 0;
1378 msg.mdp_MenuDecorFlags |= MDP_MDF_SUBITEM;
1380 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1382 mhd->submenuwin = OpenWindowTagList(0, win_tags);
1384 mhd->maxcommkeywidth_submenu = CalcMaxCommKeyWidth(mhd->submenuwin, mhd, IntuitionBase);
1386 RenderSubMenu(mhd, IntuitionBase);
1390 /**************************************************************************************************/
1392 static void KillSubMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1394 if (mhd->submenuwin)
1396 CloseWindow(mhd->submenuwin);
1398 TimeDelay(UNIT_VBLANK,0,20000);
1399 struct mdpExitMenu msg;
1401 msg.MethodID = MDM_EXITMENU;
1402 msg.mdp_TrueColor = mhd->TrueColor;
1403 msg.mdp_UserBuffer = mhd->SubDecorUserBuffer;
1404 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1406 if (mhd->SubDecorUserBuffer)
1408 FreeMem((void *)mhd->SubDecorUserBuffer, mhd->DecorUserBufferSize);
1410 mhd->SubDecorUserBuffer = 0;
1412 mhd->submenuwin = NULL;
1414 mhd->activesubitemnum = -1;
1415 mhd->activesubitem = NULL;
1419 /**************************************************************************************************/
1421 static void RenderSubMenu(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1423 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1425 if (mhd->submenuwin)
1427 struct MenuItem *item;
1429 RenderMenuBG(mhd->submenuwin, mhd, IntuitionBase);
1431 SetFont(mhd->submenuwin->RPort, mhd->dri->dri_Font);
1433 for(item = mhd->activeitem->SubItem; item; item = item->NextItem)
1435 RenderItem(item, ITEM_SUBITEM, (struct Rectangle *)(&mhd->submenubox), mhd, IntuitionBase);
1438 } /* if (mhd->submenuwin) */
1441 /**************************************************************************************************/
1443 static void RenderItem(struct MenuItem *item, WORD itemtype, struct Rectangle *box,
1444 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1446 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1447 struct Window *win = ((itemtype == ITEM_ITEM) ? mhd->menuwin : mhd->submenuwin);
1448 struct RastPort *rp = win->RPort;
1449 WORD offx = -box->MinX + mhd->menuinnerleft;
1450 WORD offy = -box->MinY + mhd->menuinnertop;
1451 BOOL enabled = ((item->Flags & ITEMENABLED) &&
1452 (mhd->activemenu->Flags & MENUENABLED) &&
1453 ((itemtype == ITEM_ITEM) || (mhd->activeitem->Flags & ITEMENABLED)));
1454 BOOL item_supports_disable = FALSE;
1456 SetDrMd(rp, JAM1);
1458 if (item->ItemFill)
1461 if (item->Flags & ITEMTEXT)
1463 struct IntuiText *save = ((struct IntuiText*) item->ItemFill)->NextText;
1465 if (item->SubItem)
1467 Forbid();
1468 ((struct IntuiText*) item->ItemFill)->NextText = NULL;
1471 struct IntuiText *it = (struct IntuiText *)item->ItemFill;
1473 if (MENUS_AMIGALOOK(IntuitionBase))
1475 PrintIText(rp, it, offx + item->LeftEdge, offy + item->TopEdge);
1477 else
1479 it->FrontPen = mhd->dri->dri_Pens[(item->Flags & HIGHITEM) ? FILLTEXTPEN : TEXTPEN];
1480 it->DrawMode = JAM1;
1482 PrintIText(rp, it, offx + item->LeftEdge, offy + item->TopEdge);
1484 if (item->SubItem)
1486 DrawImageState(rp, mhd->submenuimage, offx + item->Width - mhd->submenuimage->Width, offy + item->TopEdge + ((item->Height - mhd->submenuimage->Height) >> 1), IDS_NORMAL, mhd->dri);
1487 ((struct IntuiText*) item->ItemFill)->NextText = save;
1488 Permit();
1491 else
1493 struct Image *im = (struct Image *)item->ItemFill;
1494 LONG state = IDS_NORMAL;
1496 if (!enabled && (im->Depth == CUSTOMIMAGEDEPTH))
1498 IPTR val = 0;
1500 GetAttr(IA_SupportsDisable, (Object *)im, &val);
1501 if (val)
1503 item_supports_disable = TRUE;
1504 state = IDS_DISABLED;
1508 DrawImageState(rp, im, offx + item->LeftEdge, offy + item->TopEdge, state, mhd->dri);
1511 } /* if (item->ItemFill) */
1513 RenderCheckMark(item, itemtype, mhd, IntuitionBase);
1514 RenderAmigaKey(item, itemtype, mhd, IntuitionBase);
1516 if (!enabled && !item_supports_disable)
1518 RenderDisabledPattern(rp, offx + item->LeftEdge,
1519 offy + item->TopEdge,
1520 offx + item->LeftEdge + item->Width - 1,
1521 offy + item->TopEdge + item->Height - 1,
1522 mhd,
1523 IntuitionBase);
1528 /**************************************************************************************************/
1530 static void RenderMenuBG(struct Window *win, struct MenuHandlerData *mhd,
1531 struct IntuitionBase *IntuitionBase)
1534 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1535 struct RastPort *rp = win->RPort;
1536 WORD borderx, bordery;
1538 if (CustomDrawBackground(rp, win, 0, 0, win->Width - 1, win->Height - 1, 0, mhd, IntuitionBase)) return;
1540 if (MENUS_AMIGALOOK(IntuitionBase))
1542 borderx = mhd->scr->MenuHBorder / 2;
1543 bordery = mhd->scr->MenuVBorder / 2;
1545 else
1547 borderx = 1;
1548 bordery = 1;
1551 /* White background */
1553 if (MENUS_AMIGALOOK(IntuitionBase))
1555 SetABPenDrMd(rp, mhd->dri->dri_Pens[BARBLOCKPEN], 0, JAM1);
1557 else
1559 SetABPenDrMd(rp, mhd->dri->dri_Pens[BACKGROUNDPEN], 0, JAM1);
1562 RectFill(rp, borderx,
1563 bordery,
1564 win->Width - 1 - borderx,
1565 win->Height - 1 - bordery);
1567 /* Black border frame */
1569 if (MENUS_AMIGALOOK(IntuitionBase))
1571 SetAPen(rp, mhd->dri->dri_Pens[BARDETAILPEN]);
1572 RectFill(rp, 0, 0, win->Width - 1, bordery - 1);
1573 RectFill(rp, 0, bordery, borderx - 1, win->Height - 1 - bordery);
1574 RectFill(rp, win->Width - borderx, bordery, win->Width - 1, win->Height - 1);
1575 RectFill(rp, 0, win->Height - bordery, win->Width - 1 - borderx, win->Height - 1);
1577 else
1579 RenderFrame(rp, 0, 0, win->Width - 1, win->Height - 1, IDS_NORMAL, mhd, IntuitionBase);
1583 /**************************************************************************************************/
1585 static void RenderCheckMark(struct MenuItem *item, WORD itemtype, struct MenuHandlerData *mhd,
1586 struct IntuitionBase *IntuitionBase)
1588 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1589 struct Window *win = ((itemtype == ITEM_ITEM) ? mhd->menuwin : mhd->submenuwin);
1590 struct RastPort *rp = win->RPort;
1591 struct Rectangle *box = ((itemtype == ITEM_ITEM) ? ((struct Rectangle *)&mhd->activemenu->JazzX) : &mhd->submenubox);
1592 WORD offx = -box->MinX + mhd->menuinnerleft;
1593 WORD offy = -box->MinY + mhd->menuinnertop;
1594 WORD state = ((item->Flags & HIGHITEM) &&
1595 ((item->Flags & HIGHFLAGS) == HIGHCOMP)) ? IDS_SELECTED : IDS_NORMAL;
1597 if (item->Flags & CHECKIT)
1599 WORD x1, y1, x2, y2;
1601 x1 = item->LeftEdge + offx;
1602 y1 = item->TopEdge + offy + (item->Height - mhd->checkmark->Height) / 2;
1603 x2 = x1 + mhd->checkmark->Width - 1;
1604 y2 = y1 + mhd->checkmark->Height - 1;
1606 SetDrMd(rp, JAM1);
1608 if (item->Flags & CHECKED)
1610 DrawImageState(rp, mhd->checkmark, x1, y1, state, mhd->dri);
1612 else
1614 if (MENUS_AMIGALOOK(IntuitionBase))
1616 SetAPen(rp, mhd->dri->dri_Pens[BARBLOCKPEN]);
1618 else
1620 SetAPen(rp, mhd->dri->dri_Pens[(state == IDS_SELECTED) ? FILLPEN : BACKGROUNDPEN]);
1623 if (!CustomDrawBackground(rp, win, x1, y1, x2 - x1 + 1, y2 - y1 + 1, item->Flags, mhd, IntuitionBase)) RectFill(rp, x1, y1, x2, y2);
1629 /**************************************************************************************************/
1631 static void RenderAmigaKey(struct MenuItem *item, WORD itemtype, struct MenuHandlerData *mhd,
1632 struct IntuitionBase *IntuitionBase)
1634 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1635 struct Window *win = ((itemtype == ITEM_ITEM) ? mhd->menuwin : mhd->submenuwin);
1636 struct RastPort *rp = win->RPort;
1637 struct Rectangle *box = ((itemtype == ITEM_ITEM) ? ((struct Rectangle *)&mhd->activemenu->JazzX) : &mhd->submenubox);
1638 WORD commkeywidth = ((itemtype == ITEM_ITEM) ? mhd->maxcommkeywidth_menu : mhd->maxcommkeywidth_submenu);
1639 WORD offx = -box->MinX + mhd->menuinnerleft;
1640 WORD offy = -box->MinY + mhd->menuinnertop;
1641 WORD state = ((item->Flags & HIGHITEM) &&
1642 ((item->Flags & HIGHFLAGS) == HIGHCOMP)) ? IDS_SELECTED : IDS_NORMAL;
1644 if (item->Flags & COMMSEQ)
1646 struct TextFont *oldfont = rp->Font;
1647 struct TextFont *newfont = NULL;
1649 WORD x1, y1;
1651 if (item->Flags & ITEMTEXT)
1653 struct IntuiText *it = (struct IntuiText *)item->ItemFill;
1655 if (it->ITextFont)
1657 if ((newfont = OpenFont(it->ITextFont)))
1659 SetFont(rp, newfont);
1664 x1 = item->LeftEdge + offx + item->Width - AMIGAKEY_BORDER_SPACING -
1665 mhd->amigakey->Width - AMIGAKEY_KEY_SPACING - commkeywidth;
1666 y1 = item->TopEdge + offy + (item->Height - mhd->amigakey->Height + 1) / 2;
1668 SetDrMd(rp, JAM1);
1670 DrawImageState(rp, mhd->amigakey, x1, y1, state, mhd->dri);
1672 x1 += mhd->amigakey->Width + AMIGAKEY_KEY_SPACING;
1674 if (MENUS_AMIGALOOK(IntuitionBase))
1676 SetAPen(rp, mhd->dri->dri_Pens[BARDETAILPEN]);
1678 else
1680 SetAPen(rp, mhd->dri->dri_Pens[(item->Flags & HIGHITEM) ? FILLTEXTPEN : TEXTPEN]);
1683 Move(rp, x1, item->TopEdge + offy + (item->Height - rp->TxHeight) / 2 +
1684 rp->TxBaseline);
1685 Text(rp, &item->Command, 1);
1687 if (newfont)
1689 CloseFont(newfont);
1690 SetFont(rp, oldfont);
1693 } /* if (item->Flags & COMMSEQ) */
1696 /**************************************************************************************************/
1698 static void RenderDisabledPattern(struct RastPort *rp, WORD x1, WORD y1, WORD x2, WORD y2,
1699 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1701 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1702 static CONST UWORD pattern [] = {0x8888, 0x2222};
1704 SetDrMd(rp, JAM1);
1706 if (MENUS_AMIGALOOK(IntuitionBase))
1708 SetAPen(rp, mhd->dri->dri_Pens[BARBLOCKPEN]);
1710 else
1712 SetAPen(rp, mhd->dri->dri_Pens[BACKGROUNDPEN]);
1715 SetAfPt(rp, pattern, 1);
1717 RectFill(rp, x1, y1, x2, y2);
1719 SetAfPt(rp, NULL, 0);
1723 /**************************************************************************************************/
1725 static void RenderFrame(struct RastPort *rp, WORD x1, WORD y1, WORD x2, WORD y2, WORD state,
1726 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1728 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1730 SetAPen(rp, mhd->dri->dri_Pens[(state == IDS_SELECTED) ? SHADOWPEN : SHINEPEN]);
1732 RectFill(rp, x1, y1, x2, y1);
1733 RectFill(rp, x1, y1 + 1, x1, y2);
1735 SetAPen(rp, mhd->dri->dri_Pens[(state == IDS_SELECTED) ? SHINEPEN : SHADOWPEN]);
1736 RectFill(rp, x2, y1 + 1, x2, y2);
1737 RectFill(rp, x1 + 1, y2, x2 - 1, y2);
1739 /**************************************************************************************************/
1741 static void HighlightItem(struct MenuItem *item, WORD itemtype, struct MenuHandlerData *mhd,
1742 struct IntuitionBase *IntuitionBase)
1744 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1745 struct Window *win = ((itemtype == ITEM_ITEM) ? mhd->menuwin : mhd->submenuwin);
1746 struct RastPort *rp = win->RPort;
1747 struct Rectangle *box = ((itemtype == ITEM_ITEM) ? ((struct Rectangle *)&mhd->activemenu->JazzX) : &mhd->submenubox);
1748 APTR fill;
1749 WORD offx = -box->MinX + mhd->menuinnerleft;
1750 WORD offy = -box->MinY + mhd->menuinnertop;
1751 WORD x1, y1, x2, y2;
1752 BOOL enabled;
1754 enabled = (item->Flags & ITEMENABLED) ? TRUE : FALSE;
1755 if (!(mhd->activemenu->Flags & MENUENABLED)) enabled = FALSE;
1756 if ((itemtype == ITEM_SUBITEM) && !(mhd->activeitem->Flags & ITEMENABLED)) enabled = FALSE;
1758 if (enabled)
1760 item->Flags ^= HIGHITEM;
1762 fill = item->ItemFill;
1763 if ((item->Flags & HIGHITEM) && (item->SelectFill)) fill = item->SelectFill;
1765 x1 = offx + item->LeftEdge;
1766 y1 = offy + item->TopEdge;
1767 x2 = x1 + item->Width - 1;
1768 y2 = y1 + item->Height - 1;
1770 if (CustomDrawBackground(rp, win, x1, y1, x2 - x1 + 1, y2 - y1 + 1, item->Flags, mhd, IntuitionBase)) {
1771 SetDrMd(rp, JAM1);
1773 if(item->Flags & ITEMTEXT)
1775 struct IntuiText *save = ((struct IntuiText*) fill)->NextText;
1777 if (item->SubItem)
1779 Forbid();
1780 ((struct IntuiText*) fill)->NextText = NULL;
1783 if (MENUS_AMIGALOOK(IntuitionBase))
1785 PrintIText(rp, (struct IntuiText *)fill, x1, y1);
1787 else
1789 struct IntuiText *it = (struct IntuiText *)fill;
1791 it->FrontPen = mhd->dri->dri_Pens[TEXTPEN];
1792 it->DrawMode = JAM1;
1794 PrintIText(rp, it, x1, y1);
1796 if (item->SubItem)
1798 DrawImageState(rp, mhd->submenuimage, offx + item->Width - mhd->submenuimage->Width, offy + item->TopEdge + ((item->Height - mhd->submenuimage->Height) >> 1), IDS_NORMAL, mhd->dri);
1799 ((struct IntuiText*) fill)->NextText = save;
1800 Permit();
1803 else
1805 EraseImage(rp, (struct Image *)fill, x1, y1);
1806 DrawImageState(rp, (struct Image *)fill, x1, y1, IDS_SELECTED, mhd->dri);
1808 RenderItem(item, itemtype, box, mhd, IntuitionBase);
1809 return;
1812 switch(item->Flags & HIGHFLAGS)
1814 case HIGHIMAGE:
1815 SetDrMd(rp, JAM1);
1817 if(item->Flags & ITEMTEXT)
1819 struct IntuiText *save = ((struct IntuiText*) fill)->NextText;
1821 if (item->SubItem)
1823 Forbid();
1824 ((struct IntuiText*) fill)->NextText = NULL;
1826 if (MENUS_AMIGALOOK(IntuitionBase))
1828 PrintIText(rp, (struct IntuiText *)fill, x1, y1);
1830 else
1832 struct IntuiText *it = (struct IntuiText *)fill;
1834 it->FrontPen = mhd->dri->dri_Pens[TEXTPEN];
1835 it->DrawMode = JAM1;
1837 PrintIText(rp, it, x1, y1);
1839 if (item->SubItem)
1841 DrawImageState(rp, mhd->submenuimage, offx + item->Width - mhd->submenuimage->Width, offy + item->TopEdge + ((item->Height - mhd->submenuimage->Height) >> 1), IDS_NORMAL, mhd->dri);
1842 ((struct IntuiText*) fill)->NextText = save;
1843 Permit();
1846 else
1848 EraseImage(rp, (struct Image *)fill, x1, y1);
1849 DrawImageState(rp, (struct Image *)fill, x1, y1, IDS_SELECTED, mhd->dri);
1851 break;
1853 case HIGHCOMP:
1854 if (MENUS_AMIGALOOK(IntuitionBase))
1856 SetDrMd(rp, COMPLEMENT);
1857 RectFill(rp, x1, y1, x2, y2);
1859 else
1861 WORD state = (item->Flags & HIGHITEM) ? IDS_SELECTED : IDS_NORMAL;
1863 SetDrMd(rp, JAM1);
1864 SetAPen(rp, mhd->dri->dri_Pens[(state == IDS_SELECTED) ? FILLPEN : BACKGROUNDPEN]);
1865 RectFill(rp, x1, y1, x2, y2);
1867 RenderItem(item, itemtype, box, mhd, IntuitionBase);
1869 if (state == IDS_SELECTED)
1871 RenderFrame(rp, x1, y1, x2, y2, state, mhd, IntuitionBase);
1874 break;
1876 case HIGHBOX:
1877 SetDrMd(rp, COMPLEMENT);
1878 offx = mhd->scr->MenuHBorder;
1879 offy = mhd->scr->MenuVBorder;
1881 x1 -= offx;
1882 x2 += offx;
1883 y1 -= offy;
1884 y2 += offy;
1886 RectFill(rp, x1, y1, x2, y1 + offy - 1);
1887 RectFill(rp, x2 - offx + 1, y1 + offy, x2, y2);
1888 RectFill(rp, x1, y2 - offy + 1, x2 - offx, y2);
1889 RectFill(rp, x1, y1 + offy, x1 + offx - 1,y2 - offy);
1890 break;
1892 case HIGHNONE:
1893 /* Do nothing */
1894 break;
1896 } /* switch(item->Flags & HIGHFLAGS) */
1898 } /* if (enabled) */
1902 /**************************************************************************************************/
1904 static WORD CalcMaxCommKeyWidth(struct Window *win, struct MenuHandlerData *mhd,
1905 struct IntuitionBase *IntuitionBase)
1907 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1908 struct TextExtent te;
1909 WORD maxwidth;
1911 FontExtent(mhd->dri->dri_Font, &te);
1912 maxwidth = te.te_Width;
1914 if (win)
1916 struct MenuItem *item;
1918 if ((win == mhd->menuwin))
1920 item = mhd->activemenu->FirstItem;
1922 else
1924 item = mhd->activeitem->SubItem;
1927 for(; item; item = item->NextItem)
1929 if (item->Flags & ITEMTEXT)
1931 struct IntuiText *it = (struct IntuiText *)item->ItemFill;
1933 if (it->ITextFont)
1935 struct TextFont *font;
1937 if ((font = OpenFont(it->ITextFont)))
1939 FontExtent(font, &te);
1940 if (te.te_Width > maxwidth) maxwidth = te.te_Width;
1942 CloseFont(font);
1946 } /* if (item->Flags & ITEMTEXT) */
1948 } /* for(; item; item = item->NextItem); */
1950 } /* if (win) */
1952 return maxwidth;
1955 /**************************************************************************************************/
1957 static void AddToSelection(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1959 if ((mhd->activemenunum != -1) && (mhd->activemenu->Flags & MENUENABLED) &&
1960 (mhd->activeitemnum != -1) && (mhd->activeitem->Flags & ITEMENABLED))
1962 struct MenuItem *item = NULL;
1963 UWORD men = FULLMENUNUM(mhd->activemenunum, mhd->activeitemnum, mhd->activesubitemnum);
1965 if (mhd->activesubitemnum != -1)
1967 if (mhd->activesubitem->Flags & ITEMENABLED) item = mhd->activesubitem;
1969 else if (!mhd->activeitem->SubItem)
1971 item = mhd->activeitem;
1974 if (item && (ItemAddress(mhd->menu, men) == item))
1976 UWORD men = FULLMENUNUM(mhd->activemenunum, mhd->activeitemnum, mhd->activesubitemnum);
1978 if (mhd->firstmenupick == MENUNULL)
1980 mhd->firstmenupick = men;
1982 else if (men != mhd->lastmenupick)
1984 struct MenuItem *checkitem, *prevcheckitem = NULL;
1985 UWORD checkmen = mhd->firstmenupick;
1987 /* Remove men from pick queue, if it was already in there
1988 and then add it at the end of the pick queue */
1990 while(checkmen != MENUNULL)
1992 checkitem = ItemAddress(mhd->menu, checkmen);
1994 if (checkmen == men)
1996 if (prevcheckitem == NULL)
1998 mhd->firstmenupick = checkitem->NextSelect;
2000 else
2002 prevcheckitem->NextSelect = checkitem->NextSelect;
2006 checkmen = checkitem->NextSelect;
2007 prevcheckitem = checkitem;
2009 } /* while(checkmen != MENUNULL) */
2011 checkitem->NextSelect = men;
2013 } /* else if (men != mhd->lastmenupick) */
2015 mhd->lastmenupick = men;
2016 item->NextSelect = MENUNULL;
2018 } /* if (item) */
2020 } /* if ((mhd->activemenunum != -1) && (mhd->activeitemnum != -1)) */