home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
530b.lha
/
AMenu_v1.3
/
Mon.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-03
|
7KB
|
220 lines
/*********************************************************************\
** ________________________________ **
** A n t h o n y |________ __ __ ________| **
** | |o_| |o_| | **
** T h y s s e n __| __ __ |__ **
** __| __| | | |__ |__ **
** `` Dragon Computing ! '' __| __| | | |__ |__ **
** |_____| |__| |_____| **
** **
\*********************************************************************/
/* This file has routines to allow us to 'monitor' an Intuition port
**
** What happens, is that we create a port, `OurPort', and set things
** up so that GetMsg() works normally for OurPort, and the original
** port, WBPort. However, PutMsg() to OurPort will put the new message
** on WBPort, and vice-versa. Basically, the heads of both message
** lists are normal, but the two tails have been swapped. Since
** GetMsg() uses the head of the list, it acts normally. PutMsg() uses
** the tail of the list, so it acts differently. (the sigBit and
** sigTasks have also been swapped)
**
** What this means, is that anything PutMsg()'ed to the WBPort (an
** intuiMessage for the Workbench), will signal us, and we can then
** GetMsg() it. When we are finished looking at that message, we can
** give it to WBPort by a PutMsg() to OurPort.
*/
#include "AMenu.h"
extern struct MsgPort *WBReplyPort;
extern int WBMenus, WBProcesses;
extern BOOL AddMenuStrip();
extern void DelMenuStrip(), WBFree(), RunItem();
static struct MsgPort *WBPort;
static struct List *WBMsgList;
static LONG WBSignal, OurSignal;
static BYTE OrigPri;
/* our port */
static struct MsgPort OurPort = {
{NULL, NULL, NT_MSGPORT, 0, NULL},
PA_SIGNAL, 0, NULL,
{NULL, NULL, NULL, NT_MESSAGE, 0}
};
static struct List *OurMsgList = &(OurPort.mp_MsgList);
/*-----------------------------------------------------*/
void
AttachMsgPort()
/* fiddle with the two ports, setting things up */
{
Forbid();
/* get the info we need */
WBPort = M->WBWindow->UserPort;
WBMsgList = &(WBPort->mp_MsgList);
WBSignal = WBPort->mp_SigBit;
/* setup our port */
OurPort.mp_SigBit = WBSignal;
OurPort.mp_SigTask = WBPort->mp_SigTask;
/* flip things around */
WBPort->mp_SigTask = M->Handler;
OurMsgList->lh_Head = (struct Node *)&(WBMsgList->lh_Tail);
OurMsgList->lh_TailPred = WBMsgList->lh_TailPred;
WBMsgList->lh_TailPred = (struct Node *)&(OurMsgList->lh_Head);
OurMsgList->lh_TailPred->ln_Succ = (struct Node *)&(OurMsgList->lh_Tail);
Permit();
/* prevent deadlocks - adjust our Prioity above that of Workbench */
OrigPri = SetTaskPri(M->Handler, OurPort.mp_SigTask->tc_Node.ln_Pri+1);
}
void
DeleteMsgPort()
/* Restore things the way they were before make_MsgPort()
** Note that we don't refer to winPort. This is because we
** may have had someone else 'monitor' this port (such as MonIDCMP)
** besides us, since we attached to it.
*/
{
register struct Message *TmpMsg;
register struct MsgPort *TmpPort;
Forbid();
/* clean out our list */
while ((TmpMsg = GetMsg(&OurPort)) != NULL) PutMsg(&OurPort, TmpMsg);
/* find MsgPort that OurMsgList->lh_Head belongs to */
/* (the port we've been PutMsg'ing to) */
TmpPort = (struct MsgPort *) (
(UBYTE*) &OurPort - (UBYTE*) &(OurPort.mp_MsgList.lh_Tail)
+ (UBYTE*)OurMsgList->lh_Head);
/* restore things */
OurMsgList->lh_Head->ln_Pred = OurMsgList->lh_TailPred;
OurMsgList->lh_TailPred->ln_Succ = OurMsgList->lh_Head;
TmpPort->mp_SigTask = OurPort.mp_SigTask;
Permit();
SetTaskPri(M->Handler, OrigPri); /* return prioity to normal */
}
void
FinishMonitor()
/* clean up everything */
{
DeleteMsgPort();
FreeSignal(OurSignal);
}
BOOL
StartMonitor()
/* do all appropriate initialization of monitor */
{
AttachMsgPort();
/* we need to allocate the same signal, so that it doesn't get
allocated to something else, messing us up */
OurSignal = AllocSignal(WBSignal);
if (OurSignal != WBSignal) {
FinishMonitor();
return FALSE;
}
return TRUE;
}
/* Check if Menu code is from our menu items */
struct ExtMenuItem *
MatchItem(Code)
USHORT Code;
{
if( MENUNUM( Code ) < WBMenus )
return NULL; /* a workbench menu */
return (struct ExtMenuItem *) ItemAddress(M->WBWindow->MenuStrip, Code);
}
/* The actual monitor. Just keep waiting for messages, and acting on them
* Note that if we don't use a certain IDCMP message, we PutMsg it to get
* it back to the window it was meant for.
*/
#define CtrlC SIGBREAKF_CTRL_C /* Exit Signal */
#define CtrlD SIGBREAKF_CTRL_D /* Update Signal */
#define CtrlMask (CtrlC|CtrlD)
void
Monitor()
{
register struct IntuiMessage *Msg;
register struct ExtMenuItem *EItem;
register ULONG RetMask, WaitMask, WBReplyMask;
WBReplyMask = 1L << WBReplyPort->mp_SigBit;
WaitMask = (1L << WBSignal) | WBReplyMask | CtrlMask;
while( TRUE ) {
RetMask = Wait(WaitMask);
if( RetMask & CtrlC ) /* ^C - RemoveHandler in progress */
break;
if( RetMask & CtrlD ) { /* ^D - Update menus */
DB( FPrintf(DBWindow, "AMenu Update\n"); )
DelMenuStrip();
DB( FPrintf(DBWindow, " Signaling Parent ready to update\n"); )
Signal(M->Parent, (1 << M->ParentSig));
if( Wait(CtrlMask) & CtrlC )
break; /* if ^C - RemoveHandler in progress - else continue */
DB( FPrintf(DBWindow, " Parent Signals Update complete\n"); )
AddMenuStrip(); /* ignore return - it always does it */
continue;
}
if( RetMask & WBReplyMask ) { /* a WB program Replied */
register struct Message *WBMsg;
DB( FPrintf(DBWindow, "WB Program Exited -- Freeing Message\n"); )
while ((WBMsg = GetMsg(WBReplyPort)) != NULL)
WBFree(WBMsg);
continue;
}
/* Intercepted a WB IDCMP message */
while( Msg = (struct IntuiMessage *)GetMsg(&OurPort) ) {
switch( Msg->Class ) {
case MENUPICK:
if( EItem = MatchItem(Msg->Code) ) {
/* Found one of our menu selections */
ReplyMsg((struct Message *)Msg); /* reply directly */
DB( FPrintf(DBWindow, "Menu selection `%s'\n",
((struct IntuiText *)EItem->MenuItem.ItemFill)->IText); )
RunItem(EItem); /* run the indicated program */
} else
PutMsg(&OurPort, (struct Message *)Msg); /* pass on to WB */
break;
case NEWPREFS:
DB( FPrintf(DBWindow, "NewPrefs recieved - reattaching\n"); )
PutMsg(&OurPort, (struct Message *)Msg); /* pass on to WB */
/* loop until menus detached by WB and then we reattach them */
while( !AddMenuStrip() )
Delay(30);
DB( FPrintf(DBWindow, "-- DONE\n"); )
break;
default:
PutMsg(&OurPort, (struct Message *)Msg); /* pass on to WB */
}
}
}
}