home *** CD-ROM | disk | FTP | other *** search
- #include "PopUpMenu.h"
-
- /****************************************
- * PopUpMenu(InputSignals) *
- * *
- * Input: *
- * InputSignals - Allocated signals. *
- * Output: *
- * none *
- ****************************************/
- VOID PopUpMenu(InputSignals)
- struct SignalData *const InputSignals;
- {
- IMPORT struct WindowData MenuWindow, ItemWindow, SubWindow;
- IMPORT struct RastPort Rp;
- IMPORT struct Window *ActiveWindow;
- IMPORT struct Screen *Screen;
- IMPORT struct Menu *Menues;
- IMPORT UWORD CurrentMenuNr;
- IMPORT UWORD MenuFontSize;
- IMPORT WORD MouseX,MouseY;
- IMPORT struct SignalSemaphore PopUpSemaphore;
- IMPORT struct timerequest *TimerReqBlock;
- IMPORT struct Window *LastWindow;
- IMPORT WORDBITS LastSelected;
- IMPORT struct IntuitionBase *IntuitionBase;
-
- WORDBITS MenuNumber;
-
- ObtainSemaphore(&PopUpSemaphore);
-
- /* be sure that the window to use is still active */
- if (IntuitionBase->ActiveWindow != ActiveWindow)
- goto Abort;
-
- #ifndef NOLOCKING
- LockLayers(&Screen->LayerInfo); /* puh! now we are safe (I hope) */
- #endif
- InitGlobals();
-
- /* try to open menues */
- if ((Menues) AND
- (OpenMenuWindow((ActiveWindow == LastWindow)?
- (UWORD)(MENUNUM(LastSelected)) * MenuFontSize: 0))) {
-
- const LONGBITS MenuButtonSignals = InputSignals->MenuUpSig |
- InputSignals->MenuDownSig;
- const LONGBITS MouseMovedSignal = InputSignals->MouseMovedSig;
- const LONGBITS ButtonSignals = MenuButtonSignals |
- InputSignals->SelectDownSig;
-
- BOOL Waiting = FALSE;
- struct MsgPort *const TimerPort =
- TimerReqBlock->tr_node.io_Message.mn_ReplyPort;
- const LONGBITS TimerSignal = 1L << TimerPort->mp_SigBit;
-
- /* menuwindow opened ok */
- MenuNumber = LastSelected = MENUNULL;
-
- /* start timer */
-
- SetSignal(0,TimerSignal); /* clear old timermessages */
- if (CheckIO((struct IORequest *)TimerReqBlock) == NULL) {
- WaitIO((struct IORequest *)TimerReqBlock);
- GetMsg(TimerPort); /* get rid of the message */
- }
- QueueTimer();
-
- FOREVER {
- const LONGBITS SignalBits = Wait(MouseMovedSignal |
- ButtonSignals |
- TimerSignal);
-
- if (SignalBits & MouseMovedSignal) {
- Waiting = FALSE;
- if ((MouseX != Screen->MouseX) OR (MouseY != Screen->MouseY)) {
- MouseX = Screen->MouseX;
- MouseY = Screen->MouseY;
- SelectItem();
- }
- }
- if (SignalBits & ButtonSignals) {
- const WORDBITS Selected = FinalSelect();
-
- Waiting = FALSE;
- /* do multiple select */
- if (Selected != LastSelected) { /* same => do nothing */
- if (MenuNumber == MENUNULL)
- MenuNumber = Selected; /* first selectiom */
- else
- (ItemAddress(Menues,(LONG)LastSelected))->NextSelect = Selected;
- LastSelected = Selected;
- }
-
- if (SignalBits & MenuButtonSignals) /* Menubutton -> final selection */
- break;
- }
-
- if (SignalBits & TimerSignal) {
- GetMsg(TimerPort); /* get rid of the message */
-
- if (Waiting) {
-
- /* the input.device has stopped, unlock the screen and wait */
-
- SwapBits(&SubWindow);
- SwapBits(&ItemWindow);
- SwapBits(&MenuWindow);
-
- #ifndef NOLOCKING
- UnlockLayers(&Screen->LayerInfo);
- #endif
- Wait(MouseMovedSignal);
- #ifndef NOLOCKING
- LockLayers(&Screen->LayerInfo); /* let's hope the screen is still here */
- #endif
- SwapBits(&MenuWindow);
- SwapBits(&ItemWindow);
- SwapBits(&SubWindow);
- }
-
- /* start timer again */
- QueueTimer();
- Waiting = !Waiting;
- }
- } /* FOREVER */
-
- /* close all windows */
- CloseItemWindow(&SubWindow);
- CloseItemWindow(&ItemWindow);
- CloseItemWindow(&MenuWindow);
- }
-
- /* remember last menu selected */
- LastWindow = ActiveWindow;
-
- #ifndef NOLOCKING
- UnlockLayers(&Screen->LayerInfo);
- #endif
- /* tell the window the good news (MENUPICK) */
- TellWindow(MenuNumber);
- Abort:
- ReleaseSemaphore(&PopUpSemaphore);
- }
-
- /*****************************************
- * TellWindow() - Send Fake Menu Event. *
- * *
- * Input: *
- * none *
- * Output: *
- * none *
- *****************************************/
- VOID TellWindow(MenuNumber)
- WORDBITS MenuNumber;
- {
- IMPORT struct Window *const ActiveWindow;
- IMPORT struct IOStdReq *const InputReqBlock;
- IMPORT struct IntuitionBase *const IntuitionBase;
-
- STATIC struct InputEvent MyFakeEvent;
-
- /* get the current time */
- CurrentTime(&MyFakeEvent.ie_TimeStamp.tv_secs,
- &MyFakeEvent.ie_TimeStamp.tv_micro);
-
- MyFakeEvent.ie_Class = IECLASS_MENULIST;
- MyFakeEvent.ie_Code = MenuNumber;
- MyFakeEvent.ie_Qualifier = 0;
- MyFakeEvent.ie_NextEvent = NULL;
- MyFakeEvent.ie_EventAddress = NULL;
-
- InputReqBlock->io_Command = IND_WRITEEVENT;
- InputReqBlock->io_Flags = 0;
- InputReqBlock->io_Length = sizeof(struct InputEvent);
- InputReqBlock->io_Data = (APTR)&MyFakeEvent;
-
- /* be sure the right window will get the message. */
- ActivateWindow(ActiveWindow);
-
- DoIO(InputReqBlock);
- }
- /****************************************************
- * InitGlobals() - Init the needed global variables *
- * *
- * Input: *
- * none *
- * Output: *
- * none *
- ****************************************************/
- VOID InitGlobals()
- {
- IMPORT struct WindowData MenuWindow, ItemWindow, SubWindow;
- IMPORT UWORD CurrentMenuNr;
- IMPORT struct Menu *CurrentMenuPtr;
- IMPORT struct MenuItem *CurrentItem, *CurrentSubItem;
-
- IMPORT struct Screen *Screen;
- IMPORT struct Menu *Menues;
- IMPORT struct RastPort Rp;
- IMPORT struct Window *const ActiveWindow;
- IMPORT UWORD MenuFontSize;
- IMPORT BOOL ScreenType;
-
- /* no window is open */
- ItemWindow.BitMapOk = FALSE;
- SubWindow.BitMapOk = FALSE;
- MenuWindow.BitMapOk = FALSE;
-
- /* no menu is selected */
- CurrentMenuNr = 0;
- CurrentMenuPtr = NULL;
- CurrentItem = NULL;
- CurrentSubItem = NULL;
-
- Menues = ActiveWindow->MenuStrip;
-
- /* set up a rastport for the screen */
- InitRastPort(&Rp);
-
- SetFont(&Rp,Screen->RastPort.Font);
- Rp.BitMap = &Screen->BitMap;
-
- /* default font height */
- MenuFontSize = Rp.TxHeight + 2;
-
- /* Size of screen */
- ScreenType = (Screen->ViewPort.Modes & HIRES) == 0;
- }
-
- /******************************************************
- * QueueTimer() - Queue the timer to go of after 0.2s *
- * *
- * Input: *
- * none *
- * Output: *
- * none: *
- ******************************************************/
- VOID QueueTimer()
- {
- IMPORT struct timerequest *TimerReqBlock;
-
- TimerReqBlock->tr_node.io_Command = TR_ADDREQUEST;
- TimerReqBlock->tr_time.tv_secs = 0;
- TimerReqBlock->tr_time.tv_micro = 200000L;
- SendIO((struct IORequest *)TimerReqBlock);
- }
-
-