home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
372.lha
/
PopUpMenu_3.2
/
Source
/
PopUpMenu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-06
|
7KB
|
249 lines
#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);
}