Removed __startup attribute. It is already present in AROS_SHxx definition, and doubl...
[AROS.git] / rom / intuition / menutask.c
blobb78128d3ad5923a0b1ba4106c40827b7dea724a8
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->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 if ((lay = WhichLayer(&mhd->scr->LayerInfo, mhd->scrmousex, mhd->scrmousey)))
277 win = (struct Window *)lay->Window;
279 if (win && (win == mhd->submenuwin))
281 /* Mouse over submenu box */
282 item = FindSubItem(&new_activesubitemnum, mhd);
284 if (new_activesubitemnum != mhd->activesubitemnum)
286 if (mhd->activesubitemnum != -1)
288 HighlightItem(mhd->activesubitem, ITEM_SUBITEM, mhd, IntuitionBase);
291 mhd->activesubitemnum = new_activesubitemnum;
292 mhd->activesubitem = item;
294 if (item)
296 HighlightItem(mhd->activesubitem, ITEM_SUBITEM, mhd, IntuitionBase);
301 else if (win && (win == mhd->menuwin))
303 item = FindItem(&new_activeitemnum, mhd);
305 if (new_activeitemnum != mhd->activeitemnum)
307 if (mhd->activeitemnum != -1)
309 HighlightItem(mhd->activeitem, ITEM_ITEM, mhd, IntuitionBase);
310 KillSubMenuWin(mhd, IntuitionBase);
313 mhd->activeitemnum = new_activeitemnum;
314 mhd->activeitem = item;
316 if (item)
318 HighlightItem(mhd->activeitem, ITEM_ITEM, mhd, IntuitionBase);
320 if (item->SubItem)
322 MakeSubMenuWin(mhd, IntuitionBase);
326 } /* if (win && (win == mhd->menuwin)) */
327 else if (win && (win == mhd->menubarwin))
329 /* Mouse over menu box */
331 menu = FindMenu(&new_activemenunum, mhd, IntuitionBase);
333 if (new_activemenunum != mhd->activemenunum)
336 if (mhd->activemenunum != -1)
338 HighlightMenuTitle(mhd->activemenu, mhd, IntuitionBase);
339 KillMenuWin(mhd, IntuitionBase);
340 KillSubMenuWin(mhd, IntuitionBase);
343 mhd->activemenunum = new_activemenunum;
344 mhd->activemenu = menu;
346 if (menu)
348 HighlightMenuTitle(mhd->activemenu, mhd, IntuitionBase);
349 MakeMenuWin(mhd, IntuitionBase);
353 if ((mhd->activeitemnum != -1) && (!mhd->submenuwin))
355 HighlightItem(mhd->activeitem, ITEM_ITEM, mhd, IntuitionBase);
356 mhd->activeitemnum = -1;
357 mhd->activeitem = NULL;
360 } /* if (win && (win == mhd->menubarwin)) */
361 else
363 win = NULL;
365 } /* if ((lay = WhichLayer(&mhd->scr->LayerInfo, mhd->scrmousex, mhd->scrmousey))) */
367 if (!win)
369 /* mouse outside any menu window */
371 if ((mhd->activeitemnum != -1) && (!mhd->submenuwin))
373 HighlightItem(mhd->activeitem, ITEM_ITEM, mhd, IntuitionBase);
374 mhd->activeitemnum = -1;
375 mhd->activeitem = NULL;
377 else if (mhd->activesubitemnum != -1)
379 HighlightItem(mhd->activesubitem, ITEM_SUBITEM, mhd, IntuitionBase);
380 mhd->activesubitemnum = -1;
381 mhd->activesubitem = NULL;
387 /**************************************************************************************************/
389 static void HandleSelection(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
391 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
392 struct Layer *lay;
394 LockLayerInfo(&mhd->scr->LayerInfo);
395 lay = WhichLayer(&mhd->scr->LayerInfo, mhd->scrmousex, mhd->scrmousey);
396 UnlockLayerInfo(&mhd->scr->LayerInfo);
398 if (lay)
400 struct Window *win = (struct Window *)lay->Window;
401 struct MenuItem *item = NULL;
403 if (win && (win == mhd->submenuwin) && (mhd->activesubitemnum != -1))
404 item = mhd->activesubitem;
405 else if (win && (win == mhd->menuwin) && (mhd->activeitemnum != -1))
406 item = mhd->activeitem;
408 if (item) {
409 if (item->Flags & CHECKIT)
410 HandleCheckItem(win, item, mhd, IntuitionBase);
413 AddToSelection(mhd, IntuitionBase);
417 /**************************************************************************************************/
419 static void HandleMouseClick(struct InputEvent *ie, struct MenuHandlerData *mhd,
420 struct IntuitionBase *IntuitionBase)
422 BOOL die = FALSE;
423 ULONG sticky = GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_STICKYMENUS; /* ic_Flags is ULONG */
425 switch(ie->ie_Code)
427 case MENUUP:
428 sticky = sticky && (DoubleClick(
429 GetPrivIBase(IntuitionBase)->LastMenuDownSecs,
430 GetPrivIBase(IntuitionBase)->LastMenuDownMicro,
431 ie->ie_TimeStamp.tv_secs, ie->ie_TimeStamp.tv_micro)
432 || mhd->keepmenuup);
433 if (sticky)
434 break;
436 case SELECTDOWN:
437 if (!sticky)
439 HandleSelection(mhd, IntuitionBase);
441 if (ie->ie_Code == MENUUP)
442 die = TRUE;
445 break;
447 case SELECTUP:
448 if (sticky)
450 HandleSelection(mhd, IntuitionBase);
451 die = TRUE;
453 break;
455 case MENUDOWN:
456 if (sticky)
458 if (mhd->keepmenuup)
459 mhd->keepmenuup = FALSE;
460 else {
461 HandleSelection(mhd, IntuitionBase);
462 die = TRUE;
464 GetPrivIBase(IntuitionBase)->LastMenuDownSecs =
465 ie->ie_TimeStamp.tv_secs;
466 GetPrivIBase(IntuitionBase)->LastMenuDownMicro =
467 ie->ie_TimeStamp.tv_micro;
469 break;
470 } /* switch(ie->ie_Code) */
472 if (die)
474 KillMenuBarWin(mhd, IntuitionBase);
475 KillMenuWin(mhd, IntuitionBase);
476 KillSubMenuWin(mhd, IntuitionBase);
478 if (mhd->dri)
480 FreeScreenDrawInfo(mhd->scr, mhd->dri);
481 mhd->dri = 0;
483 MH2Int_MakeMenusInactive(mhd->win, mhd->firstmenupick, IntuitionBase);
484 mhd->active = FALSE;
488 /**************************************************************************************************/
490 static void HandleCheckItem(struct Window *win, struct MenuItem *item,
491 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
493 /* Note: If you change something here, you probably must also change
494 menus.c/CheckMenuItemWasClicked() which is used when the
495 user uses the menu key shortcuts! */
497 WORD itemtype = ((win == mhd->menuwin) ? ITEM_ITEM : ITEM_SUBITEM);
499 BOOL re_render = FALSE;
501 if (item->Flags & MENUTOGGLE)
503 item->Flags ^= CHECKED;
504 re_render = TRUE;
506 else
508 if (!(item->Flags & CHECKED))
510 item->Flags |= CHECKED;
511 re_render = TRUE;
515 if (re_render)
517 BOOL toggle_hi = FALSE;
519 if ((item->Flags & HIGHITEM) &&
520 ((item->Flags & HIGHFLAGS) == HIGHCOMP)) toggle_hi = TRUE;
522 if (toggle_hi) HighlightItem(item, itemtype, mhd, IntuitionBase);
523 RenderCheckMark(item, itemtype, mhd, IntuitionBase);
524 if (toggle_hi) HighlightItem(item, itemtype, mhd, IntuitionBase);
528 if (item->MutualExclude)
530 struct MenuItem *checkitem = (itemtype == ITEM_ITEM) ? mhd->activemenu->FirstItem :
531 mhd->activeitem->SubItem;
532 BOOL toggle_hi = FALSE;
533 WORD i;
535 if ((item->Flags & HIGHITEM) &&
536 ((item->Flags & HIGHFLAGS) == HIGHBOX)) toggle_hi = TRUE;
538 if (toggle_hi) HighlightItem(item, itemtype, mhd, IntuitionBase);
540 for(i = 0; (i < 32) && checkitem; i++, checkitem = checkitem->NextItem)
542 if ((item->MutualExclude & (1L << i)) &&
543 ((checkitem->Flags & (CHECKED | CHECKIT)) == (CHECKIT | CHECKED)))
545 checkitem->Flags &= ~CHECKED;
546 RenderCheckMark(checkitem, itemtype, mhd, IntuitionBase);
550 if (toggle_hi) HighlightItem(item, itemtype, mhd, IntuitionBase);
552 } /* if (item->MutualExclude) */
555 /**************************************************************************************************/
557 static inline BOOL CustomDrawBackground(struct RastPort *rp, struct Window *win,
558 LONG itemleft, LONG itemtop, LONG itemwidth, LONG itemheight, UWORD flags,
559 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
561 struct mdpDrawBackground msg;
563 msg.MethodID = MDM_DRAWBACKGROUND;
564 msg.mdp_RPort = rp;
565 msg.mdp_TrueColor = mhd->TrueColor;
566 msg.mdp_X = 0;
567 msg.mdp_Y = 0;
568 msg.mdp_Width = win->Width - 1;
569 msg.mdp_Height = win->Height - 1;
570 msg.mdp_ItemLeft = itemleft;
571 msg.mdp_ItemTop = itemtop;
572 msg.mdp_ItemWidth = itemwidth;
573 msg.mdp_ItemHeight = itemheight;
574 msg.mdp_Flags = flags;
576 msg.mdp_MenuDecorFlags = (MENUS_UNDERMOUSE(IntuitionBase)) ? MDP_MDF_MENUS_UNDERMOUSE : 0;
577 if (win == mhd->submenuwin) { msg.mdp_UserBuffer = mhd->SubDecorUserBuffer; msg.mdp_MenuDecorFlags |= MDP_MDF_SUBITEM; }
578 else if (win == mhd->menuwin) { msg.mdp_UserBuffer = mhd->DecorUserBuffer; msg.mdp_MenuDecorFlags |= MDP_MDF_ITEM; }
579 else { msg.mdp_UserBuffer = mhd->BarDecorUserBuffer; msg.mdp_MenuDecorFlags |= MDP_MDF_MENU; }
581 return DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
584 /**************************************************************************************************/
586 static void HighlightMenuTitle(struct Menu *menu, struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
588 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
590 if ((menu->Flags & MENUENABLED) && mhd->menubarwin)
592 struct RastPort *rp = mhd->menubarwin->RPort;
593 WORD x1, x2, y1, y2;
595 if (MENUS_UNDERMOUSE(IntuitionBase))
597 WORD i;
598 struct Menu *m = mhd->menu;
600 x1 = mhd->innerleft;
602 x2 = x1 + mhd->menubaritemwidth - 1;
604 for(i = 0; m != menu; m = m->NextMenu) i++;
606 y1 = mhd->innertop + i * mhd->menubaritemheight;
607 y2 = y1 + mhd->menubaritemheight - 1;
610 else
612 x1 = menu->LeftEdge + mhd->scr->BarHBorder - mhd->scr->MenuHBorder;
613 if (x1 < 0) x1 = 0;
614 y1 = 0;
615 x2 = x1 + menu->Width - 1;
616 y2 = mhd->scr->BarHeight - 1;
619 menu->Flags ^= HIGHITEM;
620 if (CustomDrawBackground(rp, mhd->win, x1, y1, x2 - x1 + 1, y2 - y1 + 1, menu->Flags, mhd, IntuitionBase))
622 RenderMenuTitle(menu, mhd, IntuitionBase);
623 return;
626 if (MENUS_AMIGALOOK(IntuitionBase))
628 SetDrMd(rp, COMPLEMENT);
629 RectFill(rp, x1, y1, x2, y2);
631 else
633 if (!MENUS_UNDERMOUSE(IntuitionBase)) y1++;
635 SetDrMd(rp, JAM1);
636 SetAPen(rp, mhd->dri->dri_Pens[(menu->Flags & HIGHITEM) ? FILLPEN : BACKGROUNDPEN]);
637 RectFill(rp, x1, y1, x2, y2);
638 RenderMenuTitle(menu, mhd, IntuitionBase);
640 if ((menu->Flags & HIGHITEM))
642 if (MENUS_UNDERMOUSE(IntuitionBase))
644 RenderFrame(rp, x1, y1, x2, y2, IDS_SELECTED, mhd, IntuitionBase);
646 else
648 SetAPen(rp, mhd->dri->dri_Pens[SHINEPEN]);
649 RectFill(rp, x1, y1, x1, y2);
650 SetAPen(rp, mhd->dri->dri_Pens[SHADOWPEN]);
651 RectFill(rp, x2, y1, x2, y2);
658 /**************************************************************************************************/
660 static struct Menu *FindMenu(WORD *var, struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
662 struct Menu *menu = NULL;
663 WORD mouse_x, mouse_y, i;
665 if(mhd->menubarwin)
667 mouse_x = mhd->scrmousex - mhd->menubarwin->LeftEdge;
668 mouse_y = mhd->scrmousey - mhd->menubarwin->TopEdge;
670 if (MENUS_UNDERMOUSE(IntuitionBase))
672 menu = NULL;
674 mouse_x -= mhd->innerleft;
675 mouse_y -= mhd->innertop;
677 if ((mouse_x >= 0) && (mouse_x < mhd->menubaritemwidth) && (mouse_y >= 0))
679 i = mouse_y / mhd->menubaritemheight;
681 if ((i >= 0) && (i < mhd->nummenubaritems))
683 WORD i2 = i;
685 menu = mhd->menu;
686 while(i && menu)
688 i--;
689 menu = menu->NextMenu;
692 if (menu && (i == 0))
694 *var = i2;
699 else
701 for(menu = mhd->menu, i = 0; menu; menu = menu->NextMenu, i++)
703 if ((mouse_x >= menu->LeftEdge) &&
704 (mouse_x < menu->LeftEdge + menu->Width) &&
705 (mouse_y >= 0) &&
706 (mouse_y <= mhd->scr->BarHeight))
708 *var = i;
709 break;
714 return menu;
717 /**************************************************************************************************/
719 static struct MenuItem *FindItem(WORD *var, struct MenuHandlerData *mhd)
721 struct MenuItem *item = NULL;
722 WORD mouse_x, mouse_y, i;
724 if (mhd->menuwin)
726 mouse_x = mhd->scrmousex - mhd->menuwin->LeftEdge
727 + mhd->activemenu->JazzX - mhd->innerleft - mhd->menuinnerleft;
728 mouse_y = mhd->scrmousey - mhd->menuwin->TopEdge
729 + mhd->activemenu->JazzY - mhd->innertop - mhd->menuinnertop;
731 for(item = mhd->activemenu->FirstItem, i = 0; item; item = item->NextItem, i++)
733 if ((mouse_x >= item->LeftEdge) &&
734 (mouse_x < item->LeftEdge + item->Width) &&
735 (mouse_y >= item->TopEdge) &&
736 (mouse_y < item->TopEdge + item->Height))
738 *var = i;
739 break;
742 } /* if (mhd->menuwin) */
744 if ((item == NULL) && !mhd->submenuwin) *var = -1;
746 return item;
749 /**************************************************************************************************/
751 static struct MenuItem *FindSubItem(WORD *var, struct MenuHandlerData *mhd)
753 struct MenuItem *item = NULL;
754 WORD mouse_x, mouse_y, i;
756 if (mhd->submenuwin)
758 mouse_x = mhd->scrmousex - mhd->submenuwin->LeftEdge + mhd->submenubox.MinX - mhd->menuinnerleft;
759 mouse_y = mhd->scrmousey - mhd->submenuwin->TopEdge + mhd->submenubox.MinY - mhd->menuinnertop;
761 *var = -1;
763 for(item = mhd->activeitem->SubItem, i = 0; item; item = item->NextItem, i++)
765 if ((mouse_x >= item->LeftEdge) &&
766 (mouse_x < item->LeftEdge + item->Width) &&
767 (mouse_y >= item->TopEdge) &&
768 (mouse_y < item->TopEdge + item->Height))
770 *var = i;
771 break;
775 } /* if (mhd->menuwin) */
777 return item;
780 /**************************************************************************************************/
782 static void MakeMenuBarWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
784 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
785 struct TagItem win_tags[] =
787 {WA_Left , 0 },
788 {WA_Top , 0 },
789 {WA_Width , mhd->scr->Width },
790 {WA_Height , mhd->scr->BarHeight + 1},
791 {WA_AutoAdjust , TRUE },
792 {WA_Borderless , TRUE },
793 {WA_CustomScreen, (IPTR)mhd->scr },
794 {WA_BackFill , (IPTR)LAYERS_NOBACKFILL},
795 {TAG_DONE , 0 }
797 struct Menu *menu;
799 mhd->menubarwin = NULL;
800 /* No entry to draw ? */
801 if(mhd->menu == NULL) return;
803 if (MENUS_UNDERMOUSE(IntuitionBase))
805 struct RastPort *temprp;
806 WORD w, maxw = 0;
808 if (!(temprp = CloneRastPort(&mhd->scr->RastPort))) return;
810 mhd->nummenubaritems = 0;
811 for(menu = mhd->menu; menu; menu = menu->NextMenu)
813 w = TextLength(temprp, menu->MenuName, strlen(menu->MenuName));
814 if (w > maxw) maxw = w;
815 mhd->nummenubaritems++;
818 mhd->menubaritemwidth = maxw + mhd->submenuimage->Width +
819 TEXT_AMIGAKEY_SPACING +
820 ITEXT_EXTRA_LEFT +
821 ITEXT_EXTRA_RIGHT;
823 if (temprp->TxHeight > mhd->submenuimage->Height)
825 mhd->menubaritemheight = temprp->TxHeight;
827 else
829 mhd->menubaritemheight = mhd->submenuimage->Height;
832 mhd->menubaritemheight += (ITEXT_EXTRA_TOP + ITEXT_EXTRA_BOTTOM);
834 struct mdpGetMenuSpaces msg;
836 msg.MethodID = MDM_GETMENUSPACES;
837 msg.mdp_TrueColor = mhd->TrueColor;
838 msg.mdp_InnerLeft = mhd->scr->MenuHBorder;
839 msg.mdp_InnerTop = mhd->scr->MenuVBorder;
840 msg.mdp_InnerRight = mhd->scr->MenuHBorder;
841 msg.mdp_InnerBottom = mhd->scr->MenuVBorder;
842 msg.mdp_ItemInnerLeft = 0;
843 msg.mdp_ItemInnerTop = 0;
844 msg.mdp_ItemInnerRight = 0;
845 msg.mdp_ItemInnerBottom = 0;
846 msg.mdp_MinWidth = 0;
847 msg.mdp_MinHeight = 0;
848 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
849 mhd->innerleft = msg.mdp_InnerLeft;
850 mhd->innerright = msg.mdp_InnerRight;
851 mhd->innertop = msg.mdp_InnerTop;
852 mhd->innerbottom = msg.mdp_InnerBottom;
853 mhd->iteminnerleft = msg.mdp_ItemInnerLeft;
854 mhd->iteminnerright = msg.mdp_ItemInnerRight;
855 mhd->iteminnertop = msg.mdp_ItemInnerTop;
856 mhd->iteminnerbottom = msg.mdp_ItemInnerBottom;
857 mhd->menubaritemwidth += (mhd->iteminnerleft + mhd->iteminnerright);
858 mhd->menubaritemheight += (mhd->iteminnertop + mhd->iteminnerbottom);
860 win_tags[2].ti_Data = mhd->menubaritemwidth + mhd->innerleft + mhd->innerright;
861 win_tags[3].ti_Data = mhd->menubaritemheight * mhd->nummenubaritems + mhd->innertop + mhd->innerbottom;
863 if (win_tags[2].ti_Data < msg.mdp_MinWidth)
865 mhd->menubaritemwidth += (msg.mdp_MinWidth - win_tags[2].ti_Data);
866 win_tags[2].ti_Data = msg.mdp_MinWidth;
869 if (win_tags[3].ti_Data < msg.mdp_MinHeight)
871 win_tags[3].ti_Data = msg.mdp_MinHeight;
874 WORD PosX = mhd->scr->MouseX - win_tags[2].ti_Data / 2;
875 win_tags[1].ti_Data = mhd->scr->MouseY;
877 if ((PosX + win_tags[2].ti_Data) > mhd->scr->Width) PosX = mhd->scr->Width - win_tags[2].ti_Data;
878 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;
879 if (PosX < 0) PosX = 0;
880 if (win_tags[1].ti_Data > 32000) win_tags[1].ti_Data = 0;
882 win_tags[0].ti_Data = PosX;
884 FreeRastPort(temprp);
888 IPTR userbuffersize;
889 struct mdpInitMenu msg;
891 GetAttr(MDA_UserBuffer, ((struct IntScreen *)(mhd->scr))->MenuDecorObj, &userbuffersize);
893 if (userbuffersize)
895 mhd->DecorUserBufferSize = userbuffersize;
896 mhd->BarDecorUserBuffer = (IPTR) AllocMem(userbuffersize, MEMF_ANY | MEMF_CLEAR);
897 if (0 == mhd->BarDecorUserBuffer) return;
900 msg.MethodID = MDM_INITMENU;
901 msg.mdp_TrueColor = mhd->TrueColor;
902 msg.mdp_RPort = &mhd->scr->RastPort;
903 msg.mdp_Left = win_tags[0].ti_Data;
904 msg.mdp_Top = win_tags[1].ti_Data;
905 msg.mdp_Width = win_tags[2].ti_Data;
906 msg.mdp_Height = win_tags[3].ti_Data;
907 msg.mdp_UserBuffer = mhd->BarDecorUserBuffer;
908 msg.mdp_ScreenUserBuffer = ((struct IntScreen *) mhd->scr)->DecorUserBuffer;
909 msg.mdp_MenuDecorFlags = (MENUS_UNDERMOUSE(IntuitionBase)) ? MDP_MDF_MENUS_UNDERMOUSE : 0;
910 msg.mdp_MenuDecorFlags |= MDP_MDF_MENU;
912 msg.mdp_Screen = mhd->scr;
914 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
918 D(bug("MakeMenuBarWin: mhd 0x%lx\n", mhd));
920 mhd->menubarwin = OpenWindowTagList(0, win_tags);
922 for(menu = mhd->menu; menu; menu = menu->NextMenu)
924 menu->Flags &= ~HIGHITEM;
927 RenderMenuBar(mhd, IntuitionBase);
930 /**************************************************************************************************/
932 static void KillMenuBarWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
934 if (mhd->menubarwin)
936 struct mdpExitMenu msg;
938 CloseWindow(mhd->menubarwin);
939 mhd->menubarwin = NULL;
941 msg.MethodID = MDM_EXITMENU;
942 msg.mdp_UserBuffer = mhd->BarDecorUserBuffer;
943 msg.mdp_TrueColor = mhd->TrueColor;
944 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
946 if (mhd->BarDecorUserBuffer)
948 FreeMem((void *)mhd->BarDecorUserBuffer, mhd->DecorUserBufferSize);
950 mhd->BarDecorUserBuffer = 0;
955 /**************************************************************************************************/
957 static void RenderMenuBar(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
959 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
960 if (mhd->menubarwin)
962 struct Menu *menu = mhd->menu;
963 struct Window *win = mhd->menubarwin;
964 struct RastPort *rp = win->RPort;
966 SetFont(rp, mhd->dri->dri_Font);
968 /* Bar renders using different pens in Amiga mode than rest of menu */
969 if (MENUS_UNDERMOUSE(IntuitionBase))
971 RenderMenuBG(win, mhd, IntuitionBase);
973 else
975 if (!CustomDrawBackground(rp, win, 0, 0, win->Width - 1, win->Height - 1, 0, mhd, IntuitionBase))
977 if (MENUS_AMIGALOOK(IntuitionBase))
979 SetABPenDrMd(rp, mhd->dri->dri_Pens[BARBLOCKPEN], 0, JAM1);
981 else
983 SetABPenDrMd(rp, mhd->dri->dri_Pens[BACKGROUNDPEN], 0, JAM1);
986 RectFill(rp, 0, 0, win->Width - 1, win->Height - 2);
988 SetAPen(rp, mhd->dri->dri_Pens[BARTRIMPEN]);
989 RectFill(rp, 0, win->Height - 1, win->Width - 1, win->Height - 1);
991 if (!MENUS_AMIGALOOK(IntuitionBase))
993 SetAPen(rp, mhd->dri->dri_Pens[SHINEPEN]);
994 RectFill(rp, 0, 0, 0, win->Height - 2);
995 RectFill(rp, 1, 0, win->Width - 1, 0);
996 SetAPen(rp, mhd->dri->dri_Pens[SHADOWPEN]);
997 RectFill(rp, win->Width - 1, 1, win->Width - 1, win->Height - 2);
1002 for(; menu; menu = menu->NextMenu)
1004 RenderMenuTitle(menu, mhd, IntuitionBase);
1009 /**************************************************************************************************/
1011 static void RenderMenuTitle(struct Menu *menu, struct MenuHandlerData *mhd,
1012 struct IntuitionBase *IntuitionBase)
1014 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1015 struct RastPort *rp;
1016 WORD len = strlen(menu->MenuName);
1017 WORD x, y;
1019 if(mhd->menubarwin)
1021 rp = mhd->menubarwin->RPort;
1022 SetDrMd(rp, JAM1);
1024 if (MENUS_UNDERMOUSE(IntuitionBase))
1026 struct Menu *m;
1027 WORD yoff;
1029 yoff = 0;
1030 for(m = mhd->menu; m && (m != menu);m = m ->NextMenu)
1032 yoff++;
1035 x = mhd->innerleft + ITEXT_EXTRA_LEFT;
1036 y = mhd->innertop + ITEXT_EXTRA_TOP + yoff * mhd->menubaritemheight;
1038 else
1040 x = mhd->scr->BarHBorder + menu->LeftEdge;
1041 y = mhd->scr->BarVBorder + ((mhd->scr->BarHeight - rp->Font->tf_YSize) / 2);
1044 if (MENUS_AMIGALOOK(IntuitionBase))
1046 SetAPen(rp, mhd->dri->dri_Pens[BARDETAILPEN]);
1048 else
1050 SetAPen(rp, mhd->dri->dri_Pens[(menu->Flags & HIGHITEM) ? FILLTEXTPEN : TEXTPEN]);
1053 Move(rp, x, y + rp->TxBaseline);
1054 Text(rp, menu->MenuName, len);
1056 if (MENUS_UNDERMOUSE(IntuitionBase))
1058 if (menu->FirstItem)
1060 WORD x2 = mhd->scr->MenuHBorder + mhd->menubaritemwidth - ITEXT_EXTRA_RIGHT - mhd->submenuimage->Width;
1062 DrawImageState(rp, mhd->submenuimage, x2, y + ((mhd->menubaritemheight - mhd->submenuimage->Height) >> 1), IDS_NORMAL, mhd->dri);
1066 if (!(menu->Flags & MENUENABLED))
1068 WORD y2 = y + rp->TxHeight - 1;
1069 WORD x2;
1071 if (MENUS_UNDERMOUSE(IntuitionBase))
1073 x2 = mhd->scr->MenuHBorder + mhd->menubaritemwidth - 1;
1075 else
1077 x2 = x + TextLength(rp, menu->MenuName, len) - 1;
1080 RenderDisabledPattern(rp, x, y, x2, y2, mhd, IntuitionBase);
1085 /**************************************************************************************************/
1087 static void MakeMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1089 struct MenuItem *item;
1091 WORD width = mhd->activemenu->BeatX - mhd->activemenu->JazzX + 1;
1092 WORD height = mhd->activemenu->BeatY - mhd->activemenu->JazzY + 1;
1093 WORD xpos,ypos;
1095 struct mdpGetMenuSpaces msg;
1097 msg.MethodID = MDM_GETMENUSPACES;
1098 msg.mdp_TrueColor = mhd->TrueColor;
1099 msg.mdp_InnerLeft = 0;
1100 msg.mdp_InnerTop = 0;
1101 msg.mdp_InnerRight = 0;
1102 msg.mdp_InnerBottom = 0;
1103 msg.mdp_ItemInnerLeft = 0;
1104 msg.mdp_ItemInnerTop = 0;
1105 msg.mdp_ItemInnerRight = 0;
1106 msg.mdp_ItemInnerBottom = 0;
1107 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1108 mhd->menuinnerleft = msg.mdp_InnerLeft;
1109 mhd->menuinnerright = msg.mdp_InnerRight;
1110 mhd->menuinnertop = msg.mdp_InnerTop;
1111 mhd->menuinnerbottom = msg.mdp_InnerBottom;
1113 width += (mhd->menuinnerleft + mhd->menuinnerright);
1114 height += (mhd->menuinnertop + mhd->menuinnerbottom);
1116 if (MENUS_UNDERMOUSE(IntuitionBase))
1118 xpos = mhd->menubarwin->LeftEdge + mhd->menubarwin->Width - 16;
1119 ypos = mhd->menubarwin->TopEdge;
1121 else
1123 xpos = mhd->activemenu->LeftEdge + mhd->scr->BarHBorder + mhd->activemenu->JazzX;
1125 if (MENUS_AMIGALOOK(IntuitionBase))
1127 ypos = mhd->scr->BarHeight + 1 + mhd->activemenu->JazzY;
1129 else
1131 ypos = mhd->scr->BarHeight + 1;
1136 struct TagItem win_tags[] =
1138 {WA_Left , xpos },
1139 {WA_Top , ypos },
1140 {WA_Width , width },
1141 {WA_Height , height },
1142 {WA_AutoAdjust , TRUE },
1143 {WA_Borderless , TRUE },
1144 {WA_CustomScreen, (IPTR)mhd->scr },
1145 {WA_BackFill , (IPTR)LAYERS_NOBACKFILL},
1146 {TAG_DONE , 0 }
1149 if (MENUS_UNDERMOUSE(IntuitionBase))
1151 win_tags[1].ti_Data += (mhd->menubaritemheight * mhd->activemenunum + mhd->scr->MenuVBorder) -
1152 height / 2;
1153 if (xpos + width > mhd->scr->Width)
1155 win_tags[0].ti_Data = mhd->menubarwin->LeftEdge - width + 16;
1159 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;
1160 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;
1161 if (((LONG) win_tags[0].ti_Data) < 0) win_tags[0].ti_Data = 0;
1162 if (((LONG) win_tags[1].ti_Data) < 0) win_tags[1].ti_Data = 0;
1164 if ((item = mhd->activemenu->FirstItem))
1167 while(item)
1169 item->Flags &= ~HIGHITEM;
1170 item = item->NextItem;
1173 IPTR userbuffersize;
1175 GetAttr(MDA_UserBuffer, ((struct IntScreen *)(mhd->scr))->MenuDecorObj, &userbuffersize);
1177 if (userbuffersize)
1179 mhd->DecorUserBufferSize = userbuffersize;
1180 mhd->DecorUserBuffer = (IPTR) AllocMem(userbuffersize, MEMF_ANY | MEMF_CLEAR);
1181 if (0 == mhd->DecorUserBuffer) return;
1184 struct mdpInitMenu msg;
1186 msg.MethodID = MDM_INITMENU;
1187 msg.mdp_TrueColor = mhd->TrueColor;
1188 msg.mdp_RPort = &mhd->scr->RastPort;
1189 msg.mdp_Left = win_tags[0].ti_Data;
1190 msg.mdp_Top = win_tags[1].ti_Data;
1191 msg.mdp_Width = width;
1192 msg.mdp_Height = height;
1193 msg.mdp_UserBuffer = mhd->DecorUserBuffer;
1194 msg.mdp_ScreenUserBuffer = ((struct IntScreen *) mhd->scr)->DecorUserBuffer;
1195 msg.mdp_Screen = mhd->scr;
1196 msg.mdp_MenuDecorFlags = (MENUS_UNDERMOUSE(IntuitionBase)) ? MDP_MDF_MENUS_UNDERMOUSE : 0;
1197 msg.mdp_MenuDecorFlags |= MDP_MDF_ITEM;
1199 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1201 mhd->menuwin = OpenWindowTagList(0, win_tags);
1203 mhd->maxcommkeywidth_menu = CalcMaxCommKeyWidth(mhd->menuwin, mhd, IntuitionBase);
1205 RenderMenu(mhd, IntuitionBase);
1207 mhd->activemenu->Flags |= MIDRAWN;
1212 /**************************************************************************************************/
1214 static void KillMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1216 if (mhd->menuwin)
1218 struct MenuItem *item;
1220 CloseWindow(mhd->menuwin);
1221 mhd->menuwin = NULL;
1223 TimeDelay(UNIT_VBLANK,0,20000);
1225 for(item = mhd->activemenu->FirstItem; item; item = item->NextItem)
1227 item->Flags &= ~ISDRAWN;
1229 struct mdpExitMenu msg;
1231 msg.MethodID = MDM_EXITMENU;
1232 msg.mdp_TrueColor = mhd->TrueColor;
1233 msg.mdp_UserBuffer = mhd->DecorUserBuffer;
1234 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1236 if (mhd->DecorUserBuffer)
1238 FreeMem((void *)mhd->DecorUserBuffer, mhd->DecorUserBufferSize);
1240 mhd->DecorUserBuffer = 0;
1242 mhd->activemenu->Flags &= ~MIDRAWN;
1244 mhd->activeitemnum = -1;
1245 mhd->activeitem = NULL;
1249 /**************************************************************************************************/
1251 static void RenderMenu(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1253 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1255 if (mhd->menuwin)
1257 struct MenuItem *item;
1259 RenderMenuBG(mhd->menuwin, mhd, IntuitionBase);
1261 SetFont(mhd->menuwin->RPort, mhd->dri->dri_Font);
1263 for(item = mhd->activemenu->FirstItem; item; item = item->NextItem)
1265 RenderItem(item, ITEM_ITEM, (struct Rectangle *)(&mhd->activemenu->JazzX), mhd, IntuitionBase);
1268 } /* if (mhd->menuwin) */
1271 /**************************************************************************************************/
1273 static void MakeSubMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1275 struct MenuItem *item = mhd->activeitem->SubItem;
1277 struct TagItem win_tags[] =
1279 {WA_Left , 0 },
1280 {WA_Top , 0 },
1281 {WA_Width , 0 },
1282 {WA_Height , 0 },
1283 {WA_AutoAdjust , TRUE },
1284 {WA_Borderless , TRUE },
1285 {WA_CustomScreen, (IPTR)mhd->scr },
1286 {WA_BackFill , (IPTR)LAYERS_NOBACKFILL },
1287 {TAG_DONE }
1290 if(mhd->menubarwin)
1292 GetMenuBox(mhd->menubarwin, item, &mhd->submenubox.MinX,
1293 &mhd->submenubox.MinY,
1294 &mhd->submenubox.MaxX,
1295 &mhd->submenubox.MaxY);
1298 struct mdpGetMenuSpaces msg;
1300 msg.MethodID = MDM_GETMENUSPACES;
1301 msg.mdp_TrueColor = mhd->TrueColor;
1302 msg.mdp_InnerLeft = 0;
1303 msg.mdp_InnerTop = 0;
1304 msg.mdp_InnerRight = 0;
1305 msg.mdp_InnerBottom = 0;
1307 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1308 mhd->menuinnerleft = msg.mdp_InnerLeft;
1309 mhd->menuinnerright = msg.mdp_InnerRight;
1310 mhd->menuinnertop = msg.mdp_InnerTop;
1311 mhd->menuinnerbottom = msg.mdp_InnerBottom;
1314 win_tags[0].ti_Data = mhd->menuwin->LeftEdge +
1315 mhd->activeitem->LeftEdge - mhd->activemenu->JazzX +
1316 mhd->submenubox.MinX;
1318 win_tags[1].ti_Data = mhd->menuwin->TopEdge +
1319 mhd->activeitem->TopEdge - mhd->activemenu->JazzY +
1320 mhd->submenubox.MinY;
1322 win_tags[2].ti_Data = mhd->submenubox.MaxX - mhd->submenubox.MinX + 1 + mhd->menuinnerleft + mhd->menuinnerright;
1323 win_tags[3].ti_Data = mhd->submenubox.MaxY - mhd->submenubox.MinY + 1 + mhd->menuinnertop + mhd->menuinnerbottom;
1325 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;
1326 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;
1327 if (((LONG) win_tags[0].ti_Data) < 0) win_tags[0].ti_Data = 0;
1328 if (((LONG) win_tags[1].ti_Data) < 0) win_tags[1].ti_Data = 0;
1330 while(item)
1332 item->Flags &= ~HIGHITEM;
1333 item = item->NextItem;
1336 IPTR userbuffersize;
1338 GetAttr(MDA_UserBuffer, ((struct IntScreen *)(mhd->scr))->MenuDecorObj, &userbuffersize);
1340 if (userbuffersize)
1342 mhd->DecorUserBufferSize = userbuffersize;
1343 mhd->SubDecorUserBuffer = (IPTR) AllocMem(userbuffersize, MEMF_ANY | MEMF_CLEAR);
1344 if (0 == mhd->SubDecorUserBuffer) return;
1348 struct mdpInitMenu msg;
1349 msg.MethodID = MDM_INITMENU;
1350 msg.mdp_TrueColor = mhd->TrueColor;
1351 msg.mdp_RPort = &mhd->scr->RastPort;
1352 msg.mdp_Left = win_tags[0].ti_Data;
1353 msg.mdp_Top = win_tags[1].ti_Data;
1354 msg.mdp_Width = win_tags[2].ti_Data;
1355 msg.mdp_Height = win_tags[3].ti_Data;
1356 msg.mdp_UserBuffer = mhd->SubDecorUserBuffer;
1357 msg.mdp_ScreenUserBuffer = ((struct IntScreen *) mhd->scr)->DecorUserBuffer;
1358 msg.mdp_TrueColor = mhd->TrueColor;
1359 msg.mdp_Screen = mhd->scr;
1360 msg.mdp_MenuDecorFlags = (MENUS_UNDERMOUSE(IntuitionBase)) ? MDP_MDF_MENUS_UNDERMOUSE : 0;
1361 msg.mdp_MenuDecorFlags |= MDP_MDF_SUBITEM;
1363 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1365 mhd->submenuwin = OpenWindowTagList(0, win_tags);
1367 mhd->maxcommkeywidth_submenu = CalcMaxCommKeyWidth(mhd->submenuwin, mhd, IntuitionBase);
1369 RenderSubMenu(mhd, IntuitionBase);
1373 /**************************************************************************************************/
1375 static void KillSubMenuWin(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1377 if (mhd->submenuwin)
1379 CloseWindow(mhd->submenuwin);
1381 TimeDelay(UNIT_VBLANK,0,20000);
1382 struct mdpExitMenu msg;
1384 msg.MethodID = MDM_EXITMENU;
1385 msg.mdp_TrueColor = mhd->TrueColor;
1386 msg.mdp_UserBuffer = mhd->SubDecorUserBuffer;
1387 DoMethodA(((struct IntScreen *)(mhd->scr))->MenuDecorObj, (Msg)&msg);
1389 if (mhd->SubDecorUserBuffer)
1391 FreeMem((void *)mhd->SubDecorUserBuffer, mhd->DecorUserBufferSize);
1393 mhd->SubDecorUserBuffer = 0;
1395 mhd->submenuwin = NULL;
1397 mhd->activesubitemnum = -1;
1398 mhd->activesubitem = NULL;
1402 /**************************************************************************************************/
1404 static void RenderSubMenu(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1406 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1408 if (mhd->submenuwin)
1410 struct MenuItem *item;
1412 RenderMenuBG(mhd->submenuwin, mhd, IntuitionBase);
1414 SetFont(mhd->submenuwin->RPort, mhd->dri->dri_Font);
1416 for(item = mhd->activeitem->SubItem; item; item = item->NextItem)
1418 RenderItem(item, ITEM_SUBITEM, (struct Rectangle *)(&mhd->submenubox), mhd, IntuitionBase);
1421 } /* if (mhd->submenuwin) */
1424 /**************************************************************************************************/
1426 static void RenderItem(struct MenuItem *item, WORD itemtype, struct Rectangle *box,
1427 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1429 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1430 struct Window *win = ((itemtype == ITEM_ITEM) ? mhd->menuwin : mhd->submenuwin);
1431 struct RastPort *rp = win->RPort;
1432 WORD offx = -box->MinX + mhd->menuinnerleft;
1433 WORD offy = -box->MinY + mhd->menuinnertop;
1434 BOOL enabled = ((item->Flags & ITEMENABLED) &&
1435 (mhd->activemenu->Flags & MENUENABLED) &&
1436 ((itemtype == ITEM_ITEM) || (mhd->activeitem->Flags & ITEMENABLED)));
1437 BOOL item_supports_disable = FALSE;
1439 SetDrMd(rp, JAM1);
1441 if (item->ItemFill)
1444 if (item->Flags & ITEMTEXT)
1446 struct IntuiText *save = ((struct IntuiText*) item->ItemFill)->NextText;
1448 if (item->SubItem)
1450 Forbid();
1451 ((struct IntuiText*) item->ItemFill)->NextText = NULL;
1454 struct IntuiText *it = (struct IntuiText *)item->ItemFill;
1456 if (MENUS_AMIGALOOK(IntuitionBase))
1458 PrintIText(rp, it, offx + item->LeftEdge, offy + item->TopEdge);
1460 else
1462 it->FrontPen = mhd->dri->dri_Pens[(item->Flags & HIGHITEM) ? FILLTEXTPEN : TEXTPEN];
1463 it->DrawMode = JAM1;
1465 PrintIText(rp, it, offx + item->LeftEdge, offy + item->TopEdge);
1467 if (item->SubItem)
1469 DrawImageState(rp, mhd->submenuimage, offx + item->Width - mhd->submenuimage->Width, offy + item->TopEdge + ((item->Height - mhd->submenuimage->Height) >> 1), IDS_NORMAL, mhd->dri);
1470 ((struct IntuiText*) item->ItemFill)->NextText = save;
1471 Permit();
1474 else
1476 struct Image *im = (struct Image *)item->ItemFill;
1477 LONG state = IDS_NORMAL;
1479 if (!enabled && (im->Depth == CUSTOMIMAGEDEPTH))
1481 IPTR val = 0;
1483 GetAttr(IA_SupportsDisable, (Object *)im, &val);
1484 if (val)
1486 item_supports_disable = TRUE;
1487 state = IDS_DISABLED;
1491 DrawImageState(rp, im, offx + item->LeftEdge, offy + item->TopEdge, state, mhd->dri);
1494 } /* if (item->ItemFill) */
1496 RenderCheckMark(item, itemtype, mhd, IntuitionBase);
1497 RenderAmigaKey(item, itemtype, mhd, IntuitionBase);
1499 if (!enabled && !item_supports_disable)
1501 RenderDisabledPattern(rp, offx + item->LeftEdge,
1502 offy + item->TopEdge,
1503 offx + item->LeftEdge + item->Width - 1,
1504 offy + item->TopEdge + item->Height - 1,
1505 mhd,
1506 IntuitionBase);
1511 /**************************************************************************************************/
1513 static void RenderMenuBG(struct Window *win, struct MenuHandlerData *mhd,
1514 struct IntuitionBase *IntuitionBase)
1517 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1518 struct RastPort *rp = win->RPort;
1519 WORD borderx, bordery;
1521 if (CustomDrawBackground(rp, win, 0, 0, win->Width - 1, win->Height - 1, 0, mhd, IntuitionBase)) return;
1523 if (MENUS_AMIGALOOK(IntuitionBase))
1525 borderx = mhd->scr->MenuHBorder / 2;
1526 bordery = mhd->scr->MenuVBorder / 2;
1528 else
1530 borderx = 1;
1531 bordery = 1;
1534 /* White background */
1536 if (MENUS_AMIGALOOK(IntuitionBase))
1538 SetABPenDrMd(rp, mhd->dri->dri_Pens[BARBLOCKPEN], 0, JAM1);
1540 else
1542 SetABPenDrMd(rp, mhd->dri->dri_Pens[BACKGROUNDPEN], 0, JAM1);
1545 RectFill(rp, borderx,
1546 bordery,
1547 win->Width - 1 - borderx,
1548 win->Height - 1 - bordery);
1550 /* Black border frame */
1552 if (MENUS_AMIGALOOK(IntuitionBase))
1554 SetAPen(rp, mhd->dri->dri_Pens[BARDETAILPEN]);
1555 RectFill(rp, 0, 0, win->Width - 1, bordery - 1);
1556 RectFill(rp, 0, bordery, borderx - 1, win->Height - 1 - bordery);
1557 RectFill(rp, win->Width - borderx, bordery, win->Width - 1, win->Height - 1);
1558 RectFill(rp, 0, win->Height - bordery, win->Width - 1 - borderx, win->Height - 1);
1560 else
1562 RenderFrame(rp, 0, 0, win->Width - 1, win->Height - 1, IDS_NORMAL, mhd, IntuitionBase);
1566 /**************************************************************************************************/
1568 static void RenderCheckMark(struct MenuItem *item, WORD itemtype, struct MenuHandlerData *mhd,
1569 struct IntuitionBase *IntuitionBase)
1571 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1572 struct Window *win = ((itemtype == ITEM_ITEM) ? mhd->menuwin : mhd->submenuwin);
1573 struct RastPort *rp = win->RPort;
1574 struct Rectangle *box = ((itemtype == ITEM_ITEM) ? ((struct Rectangle *)&mhd->activemenu->JazzX) : &mhd->submenubox);
1575 WORD offx = -box->MinX + mhd->menuinnerleft;
1576 WORD offy = -box->MinY + mhd->menuinnertop;
1577 WORD state = ((item->Flags & HIGHITEM) &&
1578 ((item->Flags & HIGHFLAGS) == HIGHCOMP)) ? IDS_SELECTED : IDS_NORMAL;
1580 if (item->Flags & CHECKIT)
1582 WORD x1, y1, x2, y2;
1584 x1 = item->LeftEdge + offx;
1585 y1 = item->TopEdge + offy + (item->Height - mhd->checkmark->Height) / 2;
1586 x2 = x1 + mhd->checkmark->Width - 1;
1587 y2 = y1 + mhd->checkmark->Height - 1;
1589 SetDrMd(rp, JAM1);
1591 if (item->Flags & CHECKED)
1593 DrawImageState(rp, mhd->checkmark, x1, y1, state, mhd->dri);
1595 else
1597 if (MENUS_AMIGALOOK(IntuitionBase))
1599 SetAPen(rp, mhd->dri->dri_Pens[BARBLOCKPEN]);
1601 else
1603 SetAPen(rp, mhd->dri->dri_Pens[(state == IDS_SELECTED) ? FILLPEN : BACKGROUNDPEN]);
1606 if (!CustomDrawBackground(rp, win, x1, y1, x2 - x1 + 1, y2 - y1 + 1, item->Flags, mhd, IntuitionBase)) RectFill(rp, x1, y1, x2, y2);
1612 /**************************************************************************************************/
1614 static void RenderAmigaKey(struct MenuItem *item, WORD itemtype, struct MenuHandlerData *mhd,
1615 struct IntuitionBase *IntuitionBase)
1617 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1618 struct Window *win = ((itemtype == ITEM_ITEM) ? mhd->menuwin : mhd->submenuwin);
1619 struct RastPort *rp = win->RPort;
1620 struct Rectangle *box = ((itemtype == ITEM_ITEM) ? ((struct Rectangle *)&mhd->activemenu->JazzX) : &mhd->submenubox);
1621 WORD commkeywidth = ((itemtype == ITEM_ITEM) ? mhd->maxcommkeywidth_menu : mhd->maxcommkeywidth_submenu);
1622 WORD offx = -box->MinX + mhd->menuinnerleft;
1623 WORD offy = -box->MinY + mhd->menuinnertop;
1624 WORD state = ((item->Flags & HIGHITEM) &&
1625 ((item->Flags & HIGHFLAGS) == HIGHCOMP)) ? IDS_SELECTED : IDS_NORMAL;
1627 if (item->Flags & COMMSEQ)
1629 struct TextFont *oldfont = rp->Font;
1630 struct TextFont *newfont = NULL;
1632 WORD x1, y1;
1634 if (item->Flags & ITEMTEXT)
1636 struct IntuiText *it = (struct IntuiText *)item->ItemFill;
1638 if (it->ITextFont)
1640 if ((newfont = OpenFont(it->ITextFont)))
1642 SetFont(rp, newfont);
1647 x1 = item->LeftEdge + offx + item->Width - AMIGAKEY_BORDER_SPACING -
1648 mhd->amigakey->Width - AMIGAKEY_KEY_SPACING - commkeywidth;
1649 y1 = item->TopEdge + offy + (item->Height - mhd->amigakey->Height + 1) / 2;
1651 SetDrMd(rp, JAM1);
1653 DrawImageState(rp, mhd->amigakey, x1, y1, state, mhd->dri);
1655 x1 += mhd->amigakey->Width + AMIGAKEY_KEY_SPACING;
1657 if (MENUS_AMIGALOOK(IntuitionBase))
1659 SetAPen(rp, mhd->dri->dri_Pens[BARDETAILPEN]);
1661 else
1663 SetAPen(rp, mhd->dri->dri_Pens[(item->Flags & HIGHITEM) ? FILLTEXTPEN : TEXTPEN]);
1666 Move(rp, x1, item->TopEdge + offy + (item->Height - rp->TxHeight) / 2 +
1667 rp->TxBaseline);
1668 Text(rp, &item->Command, 1);
1670 if (newfont)
1672 CloseFont(newfont);
1673 SetFont(rp, oldfont);
1676 } /* if (item->Flags & COMMSEQ) */
1679 /**************************************************************************************************/
1681 static void RenderDisabledPattern(struct RastPort *rp, WORD x1, WORD y1, WORD x2, WORD y2,
1682 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1684 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1685 static CONST UWORD pattern [] = {0x8888, 0x2222};
1687 SetDrMd(rp, JAM1);
1689 if (MENUS_AMIGALOOK(IntuitionBase))
1691 SetAPen(rp, mhd->dri->dri_Pens[BARBLOCKPEN]);
1693 else
1695 SetAPen(rp, mhd->dri->dri_Pens[BACKGROUNDPEN]);
1698 SetAfPt(rp, pattern, 1);
1700 RectFill(rp, x1, y1, x2, y2);
1702 SetAfPt(rp, NULL, 0);
1706 /**************************************************************************************************/
1708 static void RenderFrame(struct RastPort *rp, WORD x1, WORD y1, WORD x2, WORD y2, WORD state,
1709 struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1711 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1713 SetAPen(rp, mhd->dri->dri_Pens[(state == IDS_SELECTED) ? SHADOWPEN : SHINEPEN]);
1715 RectFill(rp, x1, y1, x2, y1);
1716 RectFill(rp, x1, y1 + 1, x1, y2);
1718 SetAPen(rp, mhd->dri->dri_Pens[(state == IDS_SELECTED) ? SHINEPEN : SHADOWPEN]);
1719 RectFill(rp, x2, y1 + 1, x2, y2);
1720 RectFill(rp, x1 + 1, y2, x2 - 1, y2);
1722 /**************************************************************************************************/
1724 static void HighlightItem(struct MenuItem *item, WORD itemtype, struct MenuHandlerData *mhd,
1725 struct IntuitionBase *IntuitionBase)
1727 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1728 struct Window *win = ((itemtype == ITEM_ITEM) ? mhd->menuwin : mhd->submenuwin);
1729 struct RastPort *rp = win->RPort;
1730 struct Rectangle *box = ((itemtype == ITEM_ITEM) ? ((struct Rectangle *)&mhd->activemenu->JazzX) : &mhd->submenubox);
1731 APTR fill;
1732 WORD offx = -box->MinX + mhd->menuinnerleft;
1733 WORD offy = -box->MinY + mhd->menuinnertop;
1734 WORD x1, y1, x2, y2;
1735 BOOL enabled;
1737 enabled = (item->Flags & ITEMENABLED) ? TRUE : FALSE;
1738 if (!(mhd->activemenu->Flags & MENUENABLED)) enabled = FALSE;
1739 if ((itemtype == ITEM_SUBITEM) && !(mhd->activeitem->Flags & ITEMENABLED)) enabled = FALSE;
1741 if (enabled)
1743 item->Flags ^= HIGHITEM;
1745 fill = item->ItemFill;
1746 if ((item->Flags & HIGHITEM) && (item->SelectFill)) fill = item->SelectFill;
1748 x1 = offx + item->LeftEdge;
1749 y1 = offy + item->TopEdge;
1750 x2 = x1 + item->Width - 1;
1751 y2 = y1 + item->Height - 1;
1753 if (CustomDrawBackground(rp, win, x1, y1, x2 - x1 + 1, y2 - y1 + 1, item->Flags, mhd, IntuitionBase)) {
1754 SetDrMd(rp, JAM1);
1756 if(item->Flags & ITEMTEXT)
1758 struct IntuiText *save = ((struct IntuiText*) fill)->NextText;
1760 if (item->SubItem)
1762 Forbid();
1763 ((struct IntuiText*) fill)->NextText = NULL;
1766 if (MENUS_AMIGALOOK(IntuitionBase))
1768 PrintIText(rp, (struct IntuiText *)fill, x1, y1);
1770 else
1772 struct IntuiText *it = (struct IntuiText *)fill;
1774 it->FrontPen = mhd->dri->dri_Pens[TEXTPEN];
1775 it->DrawMode = JAM1;
1777 PrintIText(rp, it, x1, y1);
1779 if (item->SubItem)
1781 DrawImageState(rp, mhd->submenuimage, offx + item->Width - mhd->submenuimage->Width, offy + item->TopEdge + ((item->Height - mhd->submenuimage->Height) >> 1), IDS_NORMAL, mhd->dri);
1782 ((struct IntuiText*) fill)->NextText = save;
1783 Permit();
1786 else
1788 EraseImage(rp, (struct Image *)fill, x1, y1);
1789 DrawImageState(rp, (struct Image *)fill, x1, y1, IDS_SELECTED, mhd->dri);
1791 RenderItem(item, itemtype, box, mhd, IntuitionBase);
1792 return;
1795 switch(item->Flags & HIGHFLAGS)
1797 case HIGHIMAGE:
1798 SetDrMd(rp, JAM1);
1800 if(item->Flags & ITEMTEXT)
1802 struct IntuiText *save = ((struct IntuiText*) fill)->NextText;
1804 if (item->SubItem)
1806 Forbid();
1807 ((struct IntuiText*) fill)->NextText = NULL;
1809 if (MENUS_AMIGALOOK(IntuitionBase))
1811 PrintIText(rp, (struct IntuiText *)fill, x1, y1);
1813 else
1815 struct IntuiText *it = (struct IntuiText *)fill;
1817 it->FrontPen = mhd->dri->dri_Pens[TEXTPEN];
1818 it->DrawMode = JAM1;
1820 PrintIText(rp, it, x1, y1);
1822 if (item->SubItem)
1824 DrawImageState(rp, mhd->submenuimage, offx + item->Width - mhd->submenuimage->Width, offy + item->TopEdge + ((item->Height - mhd->submenuimage->Height) >> 1), IDS_NORMAL, mhd->dri);
1825 ((struct IntuiText*) fill)->NextText = save;
1826 Permit();
1829 else
1831 EraseImage(rp, (struct Image *)fill, x1, y1);
1832 DrawImageState(rp, (struct Image *)fill, x1, y1, IDS_SELECTED, mhd->dri);
1834 break;
1836 case HIGHCOMP:
1837 if (MENUS_AMIGALOOK(IntuitionBase))
1839 SetDrMd(rp, COMPLEMENT);
1840 RectFill(rp, x1, y1, x2, y2);
1842 else
1844 WORD state = (item->Flags & HIGHITEM) ? IDS_SELECTED : IDS_NORMAL;
1846 SetDrMd(rp, JAM1);
1847 SetAPen(rp, mhd->dri->dri_Pens[(state == IDS_SELECTED) ? FILLPEN : BACKGROUNDPEN]);
1848 RectFill(rp, x1, y1, x2, y2);
1850 RenderItem(item, itemtype, box, mhd, IntuitionBase);
1852 if (state == IDS_SELECTED)
1854 RenderFrame(rp, x1, y1, x2, y2, state, mhd, IntuitionBase);
1857 break;
1859 case HIGHBOX:
1860 SetDrMd(rp, COMPLEMENT);
1861 offx = mhd->scr->MenuHBorder;
1862 offy = mhd->scr->MenuVBorder;
1864 x1 -= offx;
1865 x2 += offx;
1866 y1 -= offy;
1867 y2 += offy;
1869 RectFill(rp, x1, y1, x2, y1 + offy - 1);
1870 RectFill(rp, x2 - offx + 1, y1 + offy, x2, y2);
1871 RectFill(rp, x1, y2 - offy + 1, x2 - offx, y2);
1872 RectFill(rp, x1, y1 + offy, x1 + offx - 1,y2 - offy);
1873 break;
1875 case HIGHNONE:
1876 /* Do nothing */
1877 break;
1879 } /* switch(item->Flags & HIGHFLAGS) */
1881 } /* if (enabled) */
1885 /**************************************************************************************************/
1887 static WORD CalcMaxCommKeyWidth(struct Window *win, struct MenuHandlerData *mhd,
1888 struct IntuitionBase *IntuitionBase)
1890 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
1891 struct TextExtent te;
1892 WORD maxwidth;
1894 FontExtent(mhd->dri->dri_Font, &te);
1895 maxwidth = te.te_Width;
1897 if (win)
1899 struct MenuItem *item;
1901 if ((win == mhd->menuwin))
1903 item = mhd->activemenu->FirstItem;
1905 else
1907 item = mhd->activeitem->SubItem;
1910 for(; item; item = item->NextItem)
1912 if (item->Flags & ITEMTEXT)
1914 struct IntuiText *it = (struct IntuiText *)item->ItemFill;
1916 if (it->ITextFont)
1918 struct TextFont *font;
1920 if ((font = OpenFont(it->ITextFont)))
1922 FontExtent(font, &te);
1923 if (te.te_Width > maxwidth) maxwidth = te.te_Width;
1925 CloseFont(font);
1929 } /* if (item->Flags & ITEMTEXT) */
1931 } /* for(; item; item = item->NextItem); */
1933 } /* if (win) */
1935 return maxwidth;
1938 /**************************************************************************************************/
1940 static void AddToSelection(struct MenuHandlerData *mhd, struct IntuitionBase *IntuitionBase)
1942 if ((mhd->activemenunum != -1) && (mhd->activemenu->Flags & MENUENABLED) &&
1943 (mhd->activeitemnum != -1) && (mhd->activeitem->Flags & ITEMENABLED))
1945 struct MenuItem *item = NULL;
1946 UWORD men = FULLMENUNUM(mhd->activemenunum, mhd->activeitemnum, mhd->activesubitemnum);
1948 if (mhd->activesubitemnum != -1)
1950 if (mhd->activesubitem->Flags & ITEMENABLED) item = mhd->activesubitem;
1952 else if (!mhd->activeitem->SubItem)
1954 item = mhd->activeitem;
1957 if (item && (ItemAddress(mhd->menu, men) == item))
1959 UWORD men = FULLMENUNUM(mhd->activemenunum, mhd->activeitemnum, mhd->activesubitemnum);
1961 if (mhd->firstmenupick == MENUNULL)
1963 mhd->firstmenupick = men;
1965 else if (men != mhd->lastmenupick)
1967 struct MenuItem *checkitem, *prevcheckitem = NULL;
1968 UWORD checkmen = mhd->firstmenupick;
1970 /* Remove men from pick queue, if it was already in there
1971 and then add it at the end of the pick queue */
1973 while(checkmen != MENUNULL)
1975 checkitem = ItemAddress(mhd->menu, checkmen);
1977 if (checkmen == men)
1979 if (prevcheckitem == NULL)
1981 mhd->firstmenupick = checkitem->NextSelect;
1983 else
1985 prevcheckitem->NextSelect = checkitem->NextSelect;
1989 checkmen = checkitem->NextSelect;
1990 prevcheckitem = checkitem;
1992 } /* while(checkmen != MENUNULL) */
1994 checkitem->NextSelect = men;
1996 } /* else if (men != mhd->lastmenupick) */
1998 mhd->lastmenupick = men;
1999 item->NextSelect = MENUNULL;
2001 } /* if (item) */
2003 } /* if ((mhd->activemenunum != -1) && (mhd->activeitemnum != -1)) */