Tabs to spaces; more consistent and conventional formatting.
[AROS.git] / rom / intuition / menutask.c
blob2b93f00a9a118dcb434c93ab31d4850f60b3eb7d
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)) y1++;
639 SetDrMd(rp, JAM1);
640 SetAPen(rp, mhd->dri->dri_Pens[(menu->Flags & HIGHITEM) ? FILLPEN : BACKGROUNDPEN]);
641 RectFill(rp, x1, y1, x2, y2);
642 RenderMenuTitle(menu, mhd, IntuitionBase);
644 if ((menu->Flags & HIGHITEM))
646 if (MENUS_UNDERMOUSE(IntuitionBase))
648 RenderFrame(rp, x1, y1, x2, y2, IDS_SELECTED, mhd, IntuitionBase);
650 else
652 SetAPen(rp, mhd->dri->dri_Pens[SHINEPEN]);
653 RectFill(rp, x1, y1, x1, y2);
654 SetAPen(rp, mhd->dri->dri_Pens[SHADOWPEN]);
655 RectFill(rp, x2, y1, x2, y2);
662 /**************************************************************************************************/
664 static struct Menu *FindMenu(WORD *var, struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
666 struct Menu *menu = NULL;
667 WORD mouse_x, mouse_y, i;
669 if(mhd->menubarwin)
671 mouse_x = mhd->scrmousex - mhd->menubarwin->LeftEdge;
672 mouse_y = mhd->scrmousey - mhd->menubarwin->TopEdge;
674 if (MENUS_UNDERMOUSE(IntuitionBase))
676 menu = NULL;
678 mouse_x -= mhd->innerleft;
679 mouse_y -= mhd->innertop;
681 if ((mouse_x >= 0) && (mouse_x < mhd->menubaritemwidth) && (mouse_y >= 0))
683 i = mouse_y / mhd->menubaritemheight;
685 if ((i >= 0) && (i < mhd->nummenubaritems))
687 WORD i2 = i;
689 menu = mhd->menu;
690 while(i && menu)
692 i--;
693 menu = menu->NextMenu;
696 if (menu && (i == 0))
698 *var = i2;
703 else
705 for(menu = mhd->menu, i = 0; menu; menu = menu->NextMenu, i++)
707 if ((mouse_x >= menu->LeftEdge) &&
708 (mouse_x < menu->LeftEdge + menu->Width) &&
709 (mouse_y >= 0) &&
710 (mouse_y <= mhd->scr->BarHeight))
712 *var = i;
713 break;
718 return menu;
721 /**************************************************************************************************/
723 static struct MenuItem *FindItem(WORD *var, struct MenuHandlerData *mhd)
725 struct MenuItem *item = NULL;
726 WORD mouse_x, mouse_y, i;
728 if (mhd->menuwin)
730 mouse_x = mhd->scrmousex - mhd->menuwin->LeftEdge
731 + mhd->activemenu->JazzX - mhd->innerleft - mhd->menuinnerleft;
732 mouse_y = mhd->scrmousey - mhd->menuwin->TopEdge
733 + mhd->activemenu->JazzY - mhd->innertop - mhd->menuinnertop;
735 for(item = mhd->activemenu->FirstItem, i = 0; item; item = item->NextItem, i++)
737 if ((mouse_x >= item->LeftEdge) &&
738 (mouse_x < item->LeftEdge + item->Width) &&
739 (mouse_y >= item->TopEdge) &&
740 (mouse_y < item->TopEdge + item->Height))
742 *var = i;
743 break;
746 } /* if (mhd->menuwin) */
748 if ((item == NULL) && !mhd->submenuwin) *var = -1;
750 return item;
753 /**************************************************************************************************/
755 static struct MenuItem *FindSubItem(WORD *var, struct MenuHandlerData *mhd)
757 struct MenuItem *item = NULL;
758 WORD mouse_x, mouse_y, i;
760 if (mhd->submenuwin)
762 mouse_x = mhd->scrmousex - mhd->submenuwin->LeftEdge + mhd->submenubox.MinX - mhd->menuinnerleft;
763 mouse_y = mhd->scrmousey - mhd->submenuwin->TopEdge + mhd->submenubox.MinY - mhd->menuinnertop;
765 *var = -1;
767 for(item = mhd->activeitem->SubItem, i = 0; item; item = item->NextItem, i++)
769 if ((mouse_x >= item->LeftEdge) &&
770 (mouse_x < item->LeftEdge + item->Width) &&
771 (mouse_y >= item->TopEdge) &&
772 (mouse_y < item->TopEdge + item->Height))
774 *var = i;
775 break;
779 } /* if (mhd->menuwin) */
781 return item;
784 /**************************************************************************************************/
786 static void MakeMenuBarWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
788 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
789 struct TagItem win_tags[] =
791 {WA_Left , 0 },
792 {WA_Top , 0 },
793 {WA_Width , mhd->scr->Width },
794 {WA_Height , mhd->scr->BarHeight + 1},
795 {WA_AutoAdjust , TRUE },
796 {WA_Borderless , TRUE },
797 {WA_CustomScreen, (IPTR)mhd->scr },
798 {WA_BackFill , (IPTR)LAYERS_NOBACKFILL},
799 {TAG_DONE , 0 }
801 struct Menu *menu;
803 mhd->menubarwin = NULL;
804 /* No entry to draw ? */
805 if(mhd->menu == NULL) return;
807 if (MENUS_UNDERMOUSE(IntuitionBase))
809 struct RastPort *temprp;
810 WORD w, maxw = 0;
812 if (!(temprp = CloneRastPort(&mhd->scr->RastPort))) return;
814 mhd->nummenubaritems = 0;
815 for(menu = mhd->menu; menu; menu = menu->NextMenu)
817 w = TextLength(temprp, menu->MenuName, strlen(menu->MenuName));
818 if (w > maxw) maxw = w;
819 mhd->nummenubaritems++;
822 mhd->menubaritemwidth = maxw + mhd->submenuimage->Width +
823 TEXT_AMIGAKEY_SPACING +
824 ITEXT_EXTRA_LEFT +
825 ITEXT_EXTRA_RIGHT;
827 if (temprp->TxHeight > mhd->submenuimage->Height)
829 mhd->menubaritemheight = temprp->TxHeight;
831 else
833 mhd->menubaritemheight = mhd->submenuimage->Height;
836 mhd->menubaritemheight += (ITEXT_EXTRA_TOP + ITEXT_EXTRA_BOTTOM);
838 struct mdpGetMenuSpaces msg;
840 msg.MethodID = MDM_GETMENUSPACES;
841 msg.mdp_TrueColor = mhd->TrueColor;
842 msg.mdp_InnerLeft = mhd->scr->MenuHBorder;
843 msg.mdp_InnerTop = mhd->scr->MenuVBorder;
844 msg.mdp_InnerRight = mhd->scr->MenuHBorder;
845 msg.mdp_InnerBottom = mhd->scr->MenuVBorder;
846 msg.mdp_ItemInnerLeft = 0;
847 msg.mdp_ItemInnerTop = 0;
848 msg.mdp_ItemInnerRight = 0;
849 msg.mdp_ItemInnerBottom = 0;
850 msg.mdp_MinWidth = 0;
851 msg.mdp_MinHeight = 0;
852 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
853 mhd->innerleft = msg.mdp_InnerLeft;
854 mhd->innerright = msg.mdp_InnerRight;
855 mhd->innertop = msg.mdp_InnerTop;
856 mhd->innerbottom = msg.mdp_InnerBottom;
857 mhd->iteminnerleft = msg.mdp_ItemInnerLeft;
858 mhd->iteminnerright = msg.mdp_ItemInnerRight;
859 mhd->iteminnertop = msg.mdp_ItemInnerTop;
860 mhd->iteminnerbottom = msg.mdp_ItemInnerBottom;
861 mhd->menubaritemwidth += (mhd->iteminnerleft + mhd->iteminnerright);
862 mhd->menubaritemheight += (mhd->iteminnertop + mhd->iteminnerbottom);
864 win_tags[2].ti_Data = mhd->menubaritemwidth + mhd->innerleft + mhd->innerright;
865 win_tags[3].ti_Data = mhd->menubaritemheight * mhd->nummenubaritems + mhd->innertop + mhd->innerbottom;
867 if (win_tags[2].ti_Data < msg.mdp_MinWidth)
869 mhd->menubaritemwidth += (msg.mdp_MinWidth - win_tags[2].ti_Data);
870 win_tags[2].ti_Data = msg.mdp_MinWidth;
873 if (win_tags[3].ti_Data < msg.mdp_MinHeight)
875 win_tags[3].ti_Data = msg.mdp_MinHeight;
878 WORD PosX = mhd->scr->MouseX - win_tags[2].ti_Data / 2;
879 win_tags[1].ti_Data = mhd->scr->MouseY;
881 if ((PosX + win_tags[2].ti_Data) > mhd->scr->Width) PosX = mhd->scr->Width - win_tags[2].ti_Data;
882 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;
883 if (PosX < 0) PosX = 0;
884 if (win_tags[1].ti_Data > 32000) win_tags[1].ti_Data = 0;
886 win_tags[0].ti_Data = PosX;
888 FreeRastPort(temprp);
892 IPTR userbuffersize;
893 struct mdpInitMenu msg;
895 GetAttr(MDA_UserBuffer, ((struct IntScreen *)(mhd->scr))->MenuDecorObj, &userbuffersize);
897 if (userbuffersize)
899 mhd->DecorUserBufferSize = userbuffersize;
900 mhd->BarDecorUserBuffer = (IPTR) AllocMem(userbuffersize, MEMF_ANY | MEMF_CLEAR);
901 if (0 == mhd->BarDecorUserBuffer) return;
904 msg.MethodID = MDM_INITMENU;
905 msg.mdp_TrueColor = mhd->TrueColor;
906 msg.mdp_RPort = &mhd->scr->RastPort;
907 msg.mdp_Left = win_tags[0].ti_Data;
908 msg.mdp_Top = win_tags[1].ti_Data;
909 msg.mdp_Width = win_tags[2].ti_Data;
910 msg.mdp_Height = win_tags[3].ti_Data;
911 msg.mdp_UserBuffer = mhd->BarDecorUserBuffer;
912 msg.mdp_ScreenUserBuffer = ((struct IntScreen *) mhd->scr)->DecorUserBuffer;
913 msg.mdp_MenuDecorFlags = (MENUS_UNDERMOUSE(IntuitionBase)) ? MDP_MDF_MENUS_UNDERMOUSE : 0;
914 msg.mdp_MenuDecorFlags |= MDP_MDF_MENU;
916 msg.mdp_Screen = mhd->scr;
918 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
922 D(bug("MakeMenuBarWin: mhd 0x%lx\n", mhd));
924 mhd->menubarwin = OpenWindowTagList(0, win_tags);
926 for(menu = mhd->menu; menu; menu = menu->NextMenu)
928 menu->Flags &= ~HIGHITEM;
931 RenderMenuBar(mhd, IntuitionBase);
934 /**************************************************************************************************/
936 static void KillMenuBarWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
938 if (mhd->menubarwin)
940 struct mdpExitMenu msg;
942 CloseWindow(mhd->menubarwin);
943 mhd->menubarwin = NULL;
945 msg.MethodID = MDM_EXITMENU;
946 msg.mdp_UserBuffer = mhd->BarDecorUserBuffer;
947 msg.mdp_TrueColor = mhd->TrueColor;
948 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
950 if (mhd->BarDecorUserBuffer)
952 FreeMem((void *)mhd->BarDecorUserBuffer, mhd->DecorUserBufferSize);
954 mhd->BarDecorUserBuffer = 0;
959 /**************************************************************************************************/
961 static void RenderMenuBar(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
963 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
964 if (mhd->menubarwin)
966 struct Menu *menu = mhd->menu;
967 struct Window *win = mhd->menubarwin;
968 struct RastPort *rp = win->RPort;
970 SetFont(rp, mhd->dri->dri_Font);
972 /* Bar renders using different pens in Amiga mode than rest of menu */
973 if (MENUS_UNDERMOUSE(IntuitionBase))
975 RenderMenuBG(win, mhd, IntuitionBase);
977 else
979 if (!CustomDrawBackground(rp, win, 0, 0, win->Width - 1, win->Height - 1, 0, mhd, IntuitionBase))
981 if (MENUS_AMIGALOOK(IntuitionBase))
983 SetABPenDrMd(rp, mhd->dri->dri_Pens[BARBLOCKPEN], 0, JAM1);
985 else
987 SetABPenDrMd(rp, mhd->dri->dri_Pens[BACKGROUNDPEN], 0, JAM1);
990 RectFill(rp, 0, 0, win->Width - 1, win->Height - 2);
992 SetAPen(rp, mhd->dri->dri_Pens[BARTRIMPEN]);
993 RectFill(rp, 0, win->Height - 1, win->Width - 1, win->Height - 1);
995 if (!MENUS_AMIGALOOK(IntuitionBase))
997 SetAPen(rp, mhd->dri->dri_Pens[SHINEPEN]);
998 RectFill(rp, 0, 0, 0, win->Height - 2);
999 RectFill(rp, 1, 0, win->Width - 1, 0);
1000 SetAPen(rp, mhd->dri->dri_Pens[SHADOWPEN]);
1001 RectFill(rp, win->Width - 1, 1, win->Width - 1, win->Height - 2);
1006 for(; menu; menu = menu->NextMenu)
1008 RenderMenuTitle(menu, mhd, IntuitionBase);
1013 /**************************************************************************************************/
1015 static void RenderMenuTitle(struct Menu *menu, struct MenuHandlerData *mhd,
1016 struct IntuitionBase *IntuitionBase)
1018 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1019 struct RastPort *rp;
1020 WORD len = strlen(menu->MenuName);
1021 WORD x, y;
1023 if(mhd->menubarwin)
1025 rp = mhd->menubarwin->RPort;
1026 SetDrMd(rp, JAM1);
1028 if (MENUS_UNDERMOUSE(IntuitionBase))
1030 struct Menu *m;
1031 WORD yoff;
1033 yoff = 0;
1034 for(m = mhd->menu; m && (m != menu);m = m ->NextMenu)
1036 yoff++;
1039 x = mhd->innerleft + ITEXT_EXTRA_LEFT;
1040 y = mhd->innertop + ITEXT_EXTRA_TOP + yoff * mhd->menubaritemheight;
1042 else
1044 x = mhd->scr->BarHBorder + menu->LeftEdge;
1045 y = mhd->scr->BarVBorder + ((mhd->scr->BarHeight - rp->Font->tf_YSize) / 2);
1048 if (MENUS_AMIGALOOK(IntuitionBase))
1050 SetAPen(rp, mhd->dri->dri_Pens[BARDETAILPEN]);
1052 else
1054 SetAPen(rp, mhd->dri->dri_Pens[(menu->Flags & HIGHITEM) ? FILLTEXTPEN : TEXTPEN]);
1057 Move(rp, x, y + rp->TxBaseline);
1058 Text(rp, menu->MenuName, len);
1060 if (MENUS_UNDERMOUSE(IntuitionBase))
1062 if (menu->FirstItem)
1064 WORD x2 = mhd->scr->MenuHBorder + mhd->menubaritemwidth - ITEXT_EXTRA_RIGHT - mhd->submenuimage->Width;
1066 DrawImageState(rp, mhd->submenuimage, x2, y + ((mhd->menubaritemheight - mhd->submenuimage->Height) >> 1), IDS_NORMAL, mhd->dri);
1070 if (!(menu->Flags & MENUENABLED))
1072 WORD y2 = y + rp->TxHeight - 1;
1073 WORD x2;
1075 if (MENUS_UNDERMOUSE(IntuitionBase))
1077 x2 = mhd->scr->MenuHBorder + mhd->menubaritemwidth - 1;
1079 else
1081 x2 = x + TextLength(rp, menu->MenuName, len) - 1;
1084 RenderDisabledPattern(rp, x, y, x2, y2, mhd, IntuitionBase);
1089 /**************************************************************************************************/
1091 static void MakeMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1093 struct MenuItem *item;
1095 WORD width = mhd->activemenu->BeatX - mhd->activemenu->JazzX + 1;
1096 WORD height = mhd->activemenu->BeatY - mhd->activemenu->JazzY + 1;
1097 WORD xpos,ypos;
1099 struct mdpGetMenuSpaces msg;
1101 msg.MethodID = MDM_GETMENUSPACES;
1102 msg.mdp_TrueColor = mhd->TrueColor;
1103 msg.mdp_InnerLeft = 0;
1104 msg.mdp_InnerTop = 0;
1105 msg.mdp_InnerRight = 0;
1106 msg.mdp_InnerBottom = 0;
1107 msg.mdp_ItemInnerLeft = 0;
1108 msg.mdp_ItemInnerTop = 0;
1109 msg.mdp_ItemInnerRight = 0;
1110 msg.mdp_ItemInnerBottom = 0;
1111 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1112 mhd->menuinnerleft = msg.mdp_InnerLeft;
1113 mhd->menuinnerright = msg.mdp_InnerRight;
1114 mhd->menuinnertop = msg.mdp_InnerTop;
1115 mhd->menuinnerbottom = msg.mdp_InnerBottom;
1117 width += (mhd->menuinnerleft + mhd->menuinnerright);
1118 height += (mhd->menuinnertop + mhd->menuinnerbottom);
1120 if (MENUS_UNDERMOUSE(IntuitionBase))
1122 xpos = mhd->menubarwin->LeftEdge + mhd->menubarwin->Width - 16;
1123 ypos = mhd->menubarwin->TopEdge;
1125 else
1127 xpos = mhd->activemenu->LeftEdge + mhd->scr->BarHBorder + mhd->activemenu->JazzX;
1129 if (MENUS_AMIGALOOK(IntuitionBase))
1131 ypos = mhd->scr->BarHeight + 1 + mhd->activemenu->JazzY;
1133 else
1135 ypos = mhd->scr->BarHeight + 1;
1140 struct TagItem win_tags[] =
1142 {WA_Left , xpos },
1143 {WA_Top , ypos },
1144 {WA_Width , width },
1145 {WA_Height , height },
1146 {WA_AutoAdjust , TRUE },
1147 {WA_Borderless , TRUE },
1148 {WA_CustomScreen, (IPTR)mhd->scr },
1149 {WA_BackFill , (IPTR)LAYERS_NOBACKFILL},
1150 {TAG_DONE , 0 }
1153 if (MENUS_UNDERMOUSE(IntuitionBase))
1155 win_tags[1].ti_Data += (mhd->menubaritemheight * mhd->activemenunum + mhd->scr->MenuVBorder) -
1156 height / 2;
1157 if (xpos + width > mhd->scr->Width)
1159 win_tags[0].ti_Data = mhd->menubarwin->LeftEdge - width + 16;
1163 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;
1164 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;
1165 if (((LONG) win_tags[0].ti_Data) < 0) win_tags[0].ti_Data = 0;
1166 if (((LONG) win_tags[1].ti_Data) < 0) win_tags[1].ti_Data = 0;
1168 if ((item = mhd->activemenu->FirstItem))
1171 while(item)
1173 item->Flags &= ~HIGHITEM;
1174 item = item->NextItem;
1177 IPTR userbuffersize;
1179 GetAttr(MDA_UserBuffer, ((struct IntScreen *)(mhd->scr))->MenuDecorObj, &userbuffersize);
1181 if (userbuffersize)
1183 mhd->DecorUserBufferSize = userbuffersize;
1184 mhd->DecorUserBuffer = (IPTR) AllocMem(userbuffersize, MEMF_ANY | MEMF_CLEAR);
1185 if (0 == mhd->DecorUserBuffer) return;
1188 struct mdpInitMenu msg;
1190 msg.MethodID = MDM_INITMENU;
1191 msg.mdp_TrueColor = mhd->TrueColor;
1192 msg.mdp_RPort = &mhd->scr->RastPort;
1193 msg.mdp_Left = win_tags[0].ti_Data;
1194 msg.mdp_Top = win_tags[1].ti_Data;
1195 msg.mdp_Width = width;
1196 msg.mdp_Height = height;
1197 msg.mdp_UserBuffer = mhd->DecorUserBuffer;
1198 msg.mdp_ScreenUserBuffer = ((struct IntScreen *) mhd->scr)->DecorUserBuffer;
1199 msg.mdp_Screen = mhd->scr;
1200 msg.mdp_MenuDecorFlags = (MENUS_UNDERMOUSE(IntuitionBase)) ? MDP_MDF_MENUS_UNDERMOUSE : 0;
1201 msg.mdp_MenuDecorFlags |= MDP_MDF_ITEM;
1203 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1205 mhd->menuwin = OpenWindowTagList(0, win_tags);
1207 mhd->maxcommkeywidth_menu = CalcMaxCommKeyWidth(mhd->menuwin, mhd, IntuitionBase);
1209 RenderMenu(mhd, IntuitionBase);
1211 mhd->activemenu->Flags |= MIDRAWN;
1216 /**************************************************************************************************/
1218 static void KillMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1220 if (mhd->menuwin)
1222 struct MenuItem *item;
1224 CloseWindow(mhd->menuwin);
1225 mhd->menuwin = NULL;
1227 TimeDelay(UNIT_VBLANK,0,20000);
1229 for(item = mhd->activemenu->FirstItem; item; item = item->NextItem)
1231 item->Flags &= ~ISDRAWN;
1233 struct mdpExitMenu msg;
1235 msg.MethodID = MDM_EXITMENU;
1236 msg.mdp_TrueColor = mhd->TrueColor;
1237 msg.mdp_UserBuffer = mhd->DecorUserBuffer;
1238 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1240 if (mhd->DecorUserBuffer)
1242 FreeMem((void *)mhd->DecorUserBuffer, mhd->DecorUserBufferSize);
1244 mhd->DecorUserBuffer = 0;
1246 mhd->activemenu->Flags &= ~MIDRAWN;
1248 mhd->activeitemnum = -1;
1249 mhd->activeitem = NULL;
1253 /**************************************************************************************************/
1255 static void RenderMenu(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1257 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1259 if (mhd->menuwin)
1261 struct MenuItem *item;
1263 RenderMenuBG(mhd->menuwin, mhd, IntuitionBase);
1265 SetFont(mhd->menuwin->RPort, mhd->dri->dri_Font);
1267 for(item = mhd->activemenu->FirstItem; item; item = item->NextItem)
1269 RenderItem(item, ITEM_ITEM, (struct Rectangle *)(&mhd->activemenu->JazzX), mhd, IntuitionBase);
1272 } /* if (mhd->menuwin) */
1275 /**************************************************************************************************/
1277 static void MakeSubMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1279 struct MenuItem *item = mhd->activeitem->SubItem;
1281 struct TagItem win_tags[] =
1283 {WA_Left , 0 },
1284 {WA_Top , 0 },
1285 {WA_Width , 0 },
1286 {WA_Height , 0 },
1287 {WA_AutoAdjust , TRUE },
1288 {WA_Borderless , TRUE },
1289 {WA_CustomScreen, (IPTR)mhd->scr },
1290 {WA_BackFill , (IPTR)LAYERS_NOBACKFILL },
1291 {TAG_DONE }
1294 if(mhd->menubarwin)
1296 GetMenuBox(mhd->menubarwin, item, &mhd->submenubox.MinX,
1297 &mhd->submenubox.MinY,
1298 &mhd->submenubox.MaxX,
1299 &mhd->submenubox.MaxY);
1302 struct mdpGetMenuSpaces msg;
1304 msg.MethodID = MDM_GETMENUSPACES;
1305 msg.mdp_TrueColor = mhd->TrueColor;
1306 msg.mdp_InnerLeft = 0;
1307 msg.mdp_InnerTop = 0;
1308 msg.mdp_InnerRight = 0;
1309 msg.mdp_InnerBottom = 0;
1311 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1312 mhd->menuinnerleft = msg.mdp_InnerLeft;
1313 mhd->menuinnerright = msg.mdp_InnerRight;
1314 mhd->menuinnertop = msg.mdp_InnerTop;
1315 mhd->menuinnerbottom = msg.mdp_InnerBottom;
1318 win_tags[0].ti_Data = mhd->menuwin->LeftEdge +
1319 mhd->activeitem->LeftEdge - mhd->activemenu->JazzX +
1320 mhd->submenubox.MinX;
1322 win_tags[1].ti_Data = mhd->menuwin->TopEdge +
1323 mhd->activeitem->TopEdge - mhd->activemenu->JazzY +
1324 mhd->submenubox.MinY;
1326 win_tags[2].ti_Data = mhd->submenubox.MaxX - mhd->submenubox.MinX + 1 + mhd->menuinnerleft + mhd->menuinnerright;
1327 win_tags[3].ti_Data = mhd->submenubox.MaxY - mhd->submenubox.MinY + 1 + mhd->menuinnertop + mhd->menuinnerbottom;
1329 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;
1330 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;
1331 if (((LONG) win_tags[0].ti_Data) < 0) win_tags[0].ti_Data = 0;
1332 if (((LONG) win_tags[1].ti_Data) < 0) win_tags[1].ti_Data = 0;
1334 while(item)
1336 item->Flags &= ~HIGHITEM;
1337 item = item->NextItem;
1340 IPTR userbuffersize;
1342 GetAttr(MDA_UserBuffer, ((struct IntScreen *)(mhd->scr))->MenuDecorObj, &userbuffersize);
1344 if (userbuffersize)
1346 mhd->DecorUserBufferSize = userbuffersize;
1347 mhd->SubDecorUserBuffer = (IPTR) AllocMem(userbuffersize, MEMF_ANY | MEMF_CLEAR);
1348 if (0 == mhd->SubDecorUserBuffer) return;
1352 struct mdpInitMenu msg;
1353 msg.MethodID = MDM_INITMENU;
1354 msg.mdp_TrueColor = mhd->TrueColor;
1355 msg.mdp_RPort = &mhd->scr->RastPort;
1356 msg.mdp_Left = win_tags[0].ti_Data;
1357 msg.mdp_Top = win_tags[1].ti_Data;
1358 msg.mdp_Width = win_tags[2].ti_Data;
1359 msg.mdp_Height = win_tags[3].ti_Data;
1360 msg.mdp_UserBuffer = mhd->SubDecorUserBuffer;
1361 msg.mdp_ScreenUserBuffer = ((struct IntScreen *) mhd->scr)->DecorUserBuffer;
1362 msg.mdp_TrueColor = mhd->TrueColor;
1363 msg.mdp_Screen = mhd->scr;
1364 msg.mdp_MenuDecorFlags = (MENUS_UNDERMOUSE(IntuitionBase)) ? MDP_MDF_MENUS_UNDERMOUSE : 0;
1365 msg.mdp_MenuDecorFlags |= MDP_MDF_SUBITEM;
1367 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1369 mhd->submenuwin = OpenWindowTagList(0, win_tags);
1371 mhd->maxcommkeywidth_submenu = CalcMaxCommKeyWidth(mhd->submenuwin, mhd, IntuitionBase);
1373 RenderSubMenu(mhd, IntuitionBase);
1377 /**************************************************************************************************/
1379 static void KillSubMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1381 if (mhd->submenuwin)
1383 CloseWindow(mhd->submenuwin);
1385 TimeDelay(UNIT_VBLANK,0,20000);
1386 struct mdpExitMenu msg;
1388 msg.MethodID = MDM_EXITMENU;
1389 msg.mdp_TrueColor = mhd->TrueColor;
1390 msg.mdp_UserBuffer = mhd->SubDecorUserBuffer;
1391 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1393 if (mhd->SubDecorUserBuffer)
1395 FreeMem((void *)mhd->SubDecorUserBuffer, mhd->DecorUserBufferSize);
1397 mhd->SubDecorUserBuffer = 0;
1399 mhd->submenuwin = NULL;
1401 mhd->activesubitemnum = -1;
1402 mhd->activesubitem = NULL;
1406 /**************************************************************************************************/
1408 static void RenderSubMenu(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1410 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1412 if (mhd->submenuwin)
1414 struct MenuItem *item;
1416 RenderMenuBG(mhd->submenuwin, mhd, IntuitionBase);
1418 SetFont(mhd->submenuwin->RPort, mhd->dri->dri_Font);
1420 for(item = mhd->activeitem->SubItem; item; item = item->NextItem)
1422 RenderItem(item, ITEM_SUBITEM, (struct Rectangle *)(&mhd->submenubox), mhd, IntuitionBase);
1425 } /* if (mhd->submenuwin) */
1428 /**************************************************************************************************/
1430 static void RenderItem(struct MenuItem *item, WORD itemtype, struct Rectangle *box,
1431 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1433 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1434 struct Window *win = ((itemtype == ITEM_ITEM) ? mhd->menuwin : mhd->submenuwin);
1435 struct RastPort *rp = win->RPort;
1436 WORD offx = -box->MinX + mhd->menuinnerleft;
1437 WORD offy = -box->MinY + mhd->menuinnertop;
1438 BOOL enabled = ((item->Flags & ITEMENABLED) &&
1439 (mhd->activemenu->Flags & MENUENABLED) &&
1440 ((itemtype == ITEM_ITEM) || (mhd->activeitem->Flags & ITEMENABLED)));
1441 BOOL item_supports_disable = FALSE;
1443 SetDrMd(rp, JAM1);
1445 if (item->ItemFill)
1448 if (item->Flags & ITEMTEXT)
1450 struct IntuiText *save = ((struct IntuiText*) item->ItemFill)->NextText;
1452 if (item->SubItem)
1454 Forbid();
1455 ((struct IntuiText*) item->ItemFill)->NextText = NULL;
1458 struct IntuiText *it = (struct IntuiText *)item->ItemFill;
1460 if (MENUS_AMIGALOOK(IntuitionBase))
1462 PrintIText(rp, it, offx + item->LeftEdge, offy + item->TopEdge);
1464 else
1466 it->FrontPen = mhd->dri->dri_Pens[(item->Flags & HIGHITEM) ? FILLTEXTPEN : TEXTPEN];
1467 it->DrawMode = JAM1;
1469 PrintIText(rp, it, offx + item->LeftEdge, offy + item->TopEdge);
1471 if (item->SubItem)
1473 DrawImageState(rp, mhd->submenuimage, offx + item->Width - mhd->submenuimage->Width, offy + item->TopEdge + ((item->Height - mhd->submenuimage->Height) >> 1), IDS_NORMAL, mhd->dri);
1474 ((struct IntuiText*) item->ItemFill)->NextText = save;
1475 Permit();
1478 else
1480 struct Image *im = (struct Image *)item->ItemFill;
1481 LONG state = IDS_NORMAL;
1483 if (!enabled && (im->Depth == CUSTOMIMAGEDEPTH))
1485 IPTR val = 0;
1487 GetAttr(IA_SupportsDisable, (Object *)im, &val);
1488 if (val)
1490 item_supports_disable = TRUE;
1491 state = IDS_DISABLED;
1495 DrawImageState(rp, im, offx + item->LeftEdge, offy + item->TopEdge, state, mhd->dri);
1498 } /* if (item->ItemFill) */
1500 RenderCheckMark(item, itemtype, mhd, IntuitionBase);
1501 RenderAmigaKey(item, itemtype, mhd, IntuitionBase);
1503 if (!enabled && !item_supports_disable)
1505 RenderDisabledPattern(rp, offx + item->LeftEdge,
1506 offy + item->TopEdge,
1507 offx + item->LeftEdge + item->Width - 1,
1508 offy + item->TopEdge + item->Height - 1,
1509 mhd,
1510 IntuitionBase);
1515 /**************************************************************************************************/
1517 static void RenderMenuBG(struct Window *win, struct MenuHandlerData *mhd,
1518 struct IntuitionBase *IntuitionBase)
1521 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1522 struct RastPort *rp = win->RPort;
1523 WORD borderx, bordery;
1525 if (CustomDrawBackground(rp, win, 0, 0, win->Width - 1, win->Height - 1, 0, mhd, IntuitionBase)) return;
1527 if (MENUS_AMIGALOOK(IntuitionBase))
1529 borderx = mhd->scr->MenuHBorder / 2;
1530 bordery = mhd->scr->MenuVBorder / 2;
1532 else
1534 borderx = 1;
1535 bordery = 1;
1538 /* White background */
1540 if (MENUS_AMIGALOOK(IntuitionBase))
1542 SetABPenDrMd(rp, mhd->dri->dri_Pens[BARBLOCKPEN], 0, JAM1);
1544 else
1546 SetABPenDrMd(rp, mhd->dri->dri_Pens[BACKGROUNDPEN], 0, JAM1);
1549 RectFill(rp, borderx,
1550 bordery,
1551 win->Width - 1 - borderx,
1552 win->Height - 1 - bordery);
1554 /* Black border frame */
1556 if (MENUS_AMIGALOOK(IntuitionBase))
1558 SetAPen(rp, mhd->dri->dri_Pens[BARDETAILPEN]);
1559 RectFill(rp, 0, 0, win->Width - 1, bordery - 1);
1560 RectFill(rp, 0, bordery, borderx - 1, win->Height - 1 - bordery);
1561 RectFill(rp, win->Width - borderx, bordery, win->Width - 1, win->Height - 1);
1562 RectFill(rp, 0, win->Height - bordery, win->Width - 1 - borderx, win->Height - 1);
1564 else
1566 RenderFrame(rp, 0, 0, win->Width - 1, win->Height - 1, IDS_NORMAL, mhd, IntuitionBase);
1570 /**************************************************************************************************/
1572 static void RenderCheckMark(struct MenuItem *item, WORD itemtype, struct MenuHandlerData *mhd,
1573 struct IntuitionBase *IntuitionBase)
1575 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1576 struct Window *win = ((itemtype == ITEM_ITEM) ? mhd->menuwin : mhd->submenuwin);
1577 struct RastPort *rp = win->RPort;
1578 struct Rectangle *box = ((itemtype == ITEM_ITEM) ? ((struct Rectangle *)&mhd->activemenu->JazzX) : &mhd->submenubox);
1579 WORD offx = -box->MinX + mhd->menuinnerleft;
1580 WORD offy = -box->MinY + mhd->menuinnertop;
1581 WORD state = ((item->Flags & HIGHITEM) &&
1582 ((item->Flags & HIGHFLAGS) == HIGHCOMP)) ? IDS_SELECTED : IDS_NORMAL;
1584 if (item->Flags & CHECKIT)
1586 WORD x1, y1, x2, y2;
1588 x1 = item->LeftEdge + offx;
1589 y1 = item->TopEdge + offy + (item->Height - mhd->checkmark->Height) / 2;
1590 x2 = x1 + mhd->checkmark->Width - 1;
1591 y2 = y1 + mhd->checkmark->Height - 1;
1593 SetDrMd(rp, JAM1);
1595 if (item->Flags & CHECKED)
1597 DrawImageState(rp, mhd->checkmark, x1, y1, state, mhd->dri);
1599 else
1601 if (MENUS_AMIGALOOK(IntuitionBase))
1603 SetAPen(rp, mhd->dri->dri_Pens[BARBLOCKPEN]);
1605 else
1607 SetAPen(rp, mhd->dri->dri_Pens[(state == IDS_SELECTED) ? FILLPEN : BACKGROUNDPEN]);
1610 if (!CustomDrawBackground(rp, win, x1, y1, x2 - x1 + 1, y2 - y1 + 1, item->Flags, mhd, IntuitionBase)) RectFill(rp, x1, y1, x2, y2);
1616 /**************************************************************************************************/
1618 static void RenderAmigaKey(struct MenuItem *item, WORD itemtype, struct MenuHandlerData *mhd,
1619 struct IntuitionBase *IntuitionBase)
1621 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1622 struct Window *win = ((itemtype == ITEM_ITEM) ? mhd->menuwin : mhd->submenuwin);
1623 struct RastPort *rp = win->RPort;
1624 struct Rectangle *box = ((itemtype == ITEM_ITEM) ? ((struct Rectangle *)&mhd->activemenu->JazzX) : &mhd->submenubox);
1625 WORD commkeywidth = ((itemtype == ITEM_ITEM) ? mhd->maxcommkeywidth_menu : mhd->maxcommkeywidth_submenu);
1626 WORD offx = -box->MinX + mhd->menuinnerleft;
1627 WORD offy = -box->MinY + mhd->menuinnertop;
1628 WORD state = ((item->Flags & HIGHITEM) &&
1629 ((item->Flags & HIGHFLAGS) == HIGHCOMP)) ? IDS_SELECTED : IDS_NORMAL;
1631 if (item->Flags & COMMSEQ)
1633 struct TextFont *oldfont = rp->Font;
1634 struct TextFont *newfont = NULL;
1636 WORD x1, y1;
1638 if (item->Flags & ITEMTEXT)
1640 struct IntuiText *it = (struct IntuiText *)item->ItemFill;
1642 if (it->ITextFont)
1644 if ((newfont = OpenFont(it->ITextFont)))
1646 SetFont(rp, newfont);
1651 x1 = item->LeftEdge + offx + item->Width - AMIGAKEY_BORDER_SPACING -
1652 mhd->amigakey->Width - AMIGAKEY_KEY_SPACING - commkeywidth;
1653 y1 = item->TopEdge + offy + (item->Height - mhd->amigakey->Height + 1) / 2;
1655 SetDrMd(rp, JAM1);
1657 DrawImageState(rp, mhd->amigakey, x1, y1, state, mhd->dri);
1659 x1 += mhd->amigakey->Width + AMIGAKEY_KEY_SPACING;
1661 if (MENUS_AMIGALOOK(IntuitionBase))
1663 SetAPen(rp, mhd->dri->dri_Pens[BARDETAILPEN]);
1665 else
1667 SetAPen(rp, mhd->dri->dri_Pens[(item->Flags & HIGHITEM) ? FILLTEXTPEN : TEXTPEN]);
1670 Move(rp, x1, item->TopEdge + offy + (item->Height - rp->TxHeight) / 2 +
1671 rp->TxBaseline);
1672 Text(rp, &item->Command, 1);
1674 if (newfont)
1676 CloseFont(newfont);
1677 SetFont(rp, oldfont);
1680 } /* if (item->Flags & COMMSEQ) */
1683 /**************************************************************************************************/
1685 static void RenderDisabledPattern(struct RastPort *rp, WORD x1, WORD y1, WORD x2, WORD y2,
1686 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1688 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1689 static CONST UWORD pattern [] = {0x8888, 0x2222};
1691 SetDrMd(rp, JAM1);
1693 if (MENUS_AMIGALOOK(IntuitionBase))
1695 SetAPen(rp, mhd->dri->dri_Pens[BARBLOCKPEN]);
1697 else
1699 SetAPen(rp, mhd->dri->dri_Pens[BACKGROUNDPEN]);
1702 SetAfPt(rp, pattern, 1);
1704 RectFill(rp, x1, y1, x2, y2);
1706 SetAfPt(rp, NULL, 0);
1710 /**************************************************************************************************/
1712 static void RenderFrame(struct RastPort *rp, WORD x1, WORD y1, WORD x2, WORD y2, WORD state,
1713 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1715 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1717 SetAPen(rp, mhd->dri->dri_Pens[(state == IDS_SELECTED) ? SHADOWPEN : SHINEPEN]);
1719 RectFill(rp, x1, y1, x2, y1);
1720 RectFill(rp, x1, y1 + 1, x1, y2);
1722 SetAPen(rp, mhd->dri->dri_Pens[(state == IDS_SELECTED) ? SHINEPEN : SHADOWPEN]);
1723 RectFill(rp, x2, y1 + 1, x2, y2);
1724 RectFill(rp, x1 + 1, y2, x2 - 1, y2);
1726 /**************************************************************************************************/
1728 static void HighlightItem(struct MenuItem *item, WORD itemtype, struct MenuHandlerData *mhd,
1729 struct IntuitionBase *IntuitionBase)
1731 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1732 struct Window *win = ((itemtype == ITEM_ITEM) ? mhd->menuwin : mhd->submenuwin);
1733 struct RastPort *rp = win->RPort;
1734 struct Rectangle *box = ((itemtype == ITEM_ITEM) ? ((struct Rectangle *)&mhd->activemenu->JazzX) : &mhd->submenubox);
1735 APTR fill;
1736 WORD offx = -box->MinX + mhd->menuinnerleft;
1737 WORD offy = -box->MinY + mhd->menuinnertop;
1738 WORD x1, y1, x2, y2;
1739 BOOL enabled;
1741 enabled = (item->Flags & ITEMENABLED) ? TRUE : FALSE;
1742 if (!(mhd->activemenu->Flags & MENUENABLED)) enabled = FALSE;
1743 if ((itemtype == ITEM_SUBITEM) && !(mhd->activeitem->Flags & ITEMENABLED)) enabled = FALSE;
1745 if (enabled)
1747 item->Flags ^= HIGHITEM;
1749 fill = item->ItemFill;
1750 if ((item->Flags & HIGHITEM) && (item->SelectFill)) fill = item->SelectFill;
1752 x1 = offx + item->LeftEdge;
1753 y1 = offy + item->TopEdge;
1754 x2 = x1 + item->Width - 1;
1755 y2 = y1 + item->Height - 1;
1757 if (CustomDrawBackground(rp, win, x1, y1, x2 - x1 + 1, y2 - y1 + 1, item->Flags, mhd, IntuitionBase)) {
1758 SetDrMd(rp, JAM1);
1760 if(item->Flags & ITEMTEXT)
1762 struct IntuiText *save = ((struct IntuiText*) fill)->NextText;
1764 if (item->SubItem)
1766 Forbid();
1767 ((struct IntuiText*) fill)->NextText = NULL;
1770 if (MENUS_AMIGALOOK(IntuitionBase))
1772 PrintIText(rp, (struct IntuiText *)fill, x1, y1);
1774 else
1776 struct IntuiText *it = (struct IntuiText *)fill;
1778 it->FrontPen = mhd->dri->dri_Pens[TEXTPEN];
1779 it->DrawMode = JAM1;
1781 PrintIText(rp, it, x1, y1);
1783 if (item->SubItem)
1785 DrawImageState(rp, mhd->submenuimage, offx + item->Width - mhd->submenuimage->Width, offy + item->TopEdge + ((item->Height - mhd->submenuimage->Height) >> 1), IDS_NORMAL, mhd->dri);
1786 ((struct IntuiText*) fill)->NextText = save;
1787 Permit();
1790 else
1792 EraseImage(rp, (struct Image *)fill, x1, y1);
1793 DrawImageState(rp, (struct Image *)fill, x1, y1, IDS_SELECTED, mhd->dri);
1795 RenderItem(item, itemtype, box, mhd, IntuitionBase);
1796 return;
1799 switch(item->Flags & HIGHFLAGS)
1801 case HIGHIMAGE:
1802 SetDrMd(rp, JAM1);
1804 if(item->Flags & ITEMTEXT)
1806 struct IntuiText *save = ((struct IntuiText*) fill)->NextText;
1808 if (item->SubItem)
1810 Forbid();
1811 ((struct IntuiText*) fill)->NextText = NULL;
1813 if (MENUS_AMIGALOOK(IntuitionBase))
1815 PrintIText(rp, (struct IntuiText *)fill, x1, y1);
1817 else
1819 struct IntuiText *it = (struct IntuiText *)fill;
1821 it->FrontPen = mhd->dri->dri_Pens[TEXTPEN];
1822 it->DrawMode = JAM1;
1824 PrintIText(rp, it, x1, y1);
1826 if (item->SubItem)
1828 DrawImageState(rp, mhd->submenuimage, offx + item->Width - mhd->submenuimage->Width, offy + item->TopEdge + ((item->Height - mhd->submenuimage->Height) >> 1), IDS_NORMAL, mhd->dri);
1829 ((struct IntuiText*) fill)->NextText = save;
1830 Permit();
1833 else
1835 EraseImage(rp, (struct Image *)fill, x1, y1);
1836 DrawImageState(rp, (struct Image *)fill, x1, y1, IDS_SELECTED, mhd->dri);
1838 break;
1840 case HIGHCOMP:
1841 if (MENUS_AMIGALOOK(IntuitionBase))
1843 SetDrMd(rp, COMPLEMENT);
1844 RectFill(rp, x1, y1, x2, y2);
1846 else
1848 WORD state = (item->Flags & HIGHITEM) ? IDS_SELECTED : IDS_NORMAL;
1850 SetDrMd(rp, JAM1);
1851 SetAPen(rp, mhd->dri->dri_Pens[(state == IDS_SELECTED) ? FILLPEN : BACKGROUNDPEN]);
1852 RectFill(rp, x1, y1, x2, y2);
1854 RenderItem(item, itemtype, box, mhd, IntuitionBase);
1856 if (state == IDS_SELECTED)
1858 RenderFrame(rp, x1, y1, x2, y2, state, mhd, IntuitionBase);
1861 break;
1863 case HIGHBOX:
1864 SetDrMd(rp, COMPLEMENT);
1865 offx = mhd->scr->MenuHBorder;
1866 offy = mhd->scr->MenuVBorder;
1868 x1 -= offx;
1869 x2 += offx;
1870 y1 -= offy;
1871 y2 += offy;
1873 RectFill(rp, x1, y1, x2, y1 + offy - 1);
1874 RectFill(rp, x2 - offx + 1, y1 + offy, x2, y2);
1875 RectFill(rp, x1, y2 - offy + 1, x2 - offx, y2);
1876 RectFill(rp, x1, y1 + offy, x1 + offx - 1,y2 - offy);
1877 break;
1879 case HIGHNONE:
1880 /* Do nothing */
1881 break;
1883 } /* switch(item->Flags & HIGHFLAGS) */
1885 } /* if (enabled) */
1889 /**************************************************************************************************/
1891 static WORD CalcMaxCommKeyWidth(struct Window *win, struct MenuHandlerData *mhd,
1892 struct IntuitionBase *IntuitionBase)
1894 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1895 struct TextExtent te;
1896 WORD maxwidth;
1898 FontExtent(mhd->dri->dri_Font, &te);
1899 maxwidth = te.te_Width;
1901 if (win)
1903 struct MenuItem *item;
1905 if ((win == mhd->menuwin))
1907 item = mhd->activemenu->FirstItem;
1909 else
1911 item = mhd->activeitem->SubItem;
1914 for(; item; item = item->NextItem)
1916 if (item->Flags & ITEMTEXT)
1918 struct IntuiText *it = (struct IntuiText *)item->ItemFill;
1920 if (it->ITextFont)
1922 struct TextFont *font;
1924 if ((font = OpenFont(it->ITextFont)))
1926 FontExtent(font, &te);
1927 if (te.te_Width > maxwidth) maxwidth = te.te_Width;
1929 CloseFont(font);
1933 } /* if (item->Flags & ITEMTEXT) */
1935 } /* for(; item; item = item->NextItem); */
1937 } /* if (win) */
1939 return maxwidth;
1942 /**************************************************************************************************/
1944 static void AddToSelection(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1946 if ((mhd->activemenunum != -1) && (mhd->activemenu->Flags & MENUENABLED) &&
1947 (mhd->activeitemnum != -1) && (mhd->activeitem->Flags & ITEMENABLED))
1949 struct MenuItem *item = NULL;
1950 UWORD men = FULLMENUNUM(mhd->activemenunum, mhd->activeitemnum, mhd->activesubitemnum);
1952 if (mhd->activesubitemnum != -1)
1954 if (mhd->activesubitem->Flags & ITEMENABLED) item = mhd->activesubitem;
1956 else if (!mhd->activeitem->SubItem)
1958 item = mhd->activeitem;
1961 if (item && (ItemAddress(mhd->menu, men) == item))
1963 UWORD men = FULLMENUNUM(mhd->activemenunum, mhd->activeitemnum, mhd->activesubitemnum);
1965 if (mhd->firstmenupick == MENUNULL)
1967 mhd->firstmenupick = men;
1969 else if (men != mhd->lastmenupick)
1971 struct MenuItem *checkitem, *prevcheckitem = NULL;
1972 UWORD checkmen = mhd->firstmenupick;
1974 /* Remove men from pick queue, if it was already in there
1975 and then add it at the end of the pick queue */
1977 while(checkmen != MENUNULL)
1979 checkitem = ItemAddress(mhd->menu, checkmen);
1981 if (checkmen == men)
1983 if (prevcheckitem == NULL)
1985 mhd->firstmenupick = checkitem->NextSelect;
1987 else
1989 prevcheckitem->NextSelect = checkitem->NextSelect;
1993 checkmen = checkitem->NextSelect;
1994 prevcheckitem = checkitem;
1996 } /* while(checkmen != MENUNULL) */
1998 checkitem->NextSelect = men;
2000 } /* else if (men != mhd->lastmenupick) */
2002 mhd->lastmenupick = men;
2003 item->NextSelect = MENUNULL;
2005 } /* if (item) */
2007 } /* if ((mhd->activemenunum != -1) && (mhd->activeitemnum != -1)) */