home *** CD-ROM | disk | FTP | other *** search
- /* Copyright ) Darin Johnson, 1989 */
-
- /* This file has routines to allow us to 'monitor' an Intuition port */
-
- /* What happens, is that we create a port, myPort, and set things up */
- /* so that GetMsg works normally for myPort, and the original port, */
- /* winPort. However, PutMsg to myPort will put the new message */
- /* on winPort, 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 winPort, will */
- /* signal us, and we can GetMsg it. When we are finished looking at */
- /* that message, we can give it to winPort by PutMsg'ing to myPort. */
-
- #include <exec/ports.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <intuition/intuitionbase.h>
- #include <devices/inputevent.h>
- #include <functions.h>
- #include "mymenu.h"
-
- #ifdef DO_WB
- extern struct MsgPort *wb_reply_port;
- extern int wb_cnt;
- #endif
-
- static struct MsgPort *winPort;
- static struct List *winMsgList;
- static LONG winSignal, our_signal;
- static LONG winMask;
- static BYTE orig_pri;
-
- /* our port */
- static struct MsgPort myPort =
- {
- {NULL, NULL, NT_MSGPORT, 0, NULL},
- PA_SIGNAL,
- 0,
- NULL,
- {NULL, NULL, NULL, NT_MESSAGE, 0}
- };
-
- static struct List *myMsgList = &(myPort.mp_MsgList);
-
- /* fiddle with the two ports, setting things up */
- make_MsgPort()
- {
- Forbid();
- /* get the info we need */
- winPort = MM->WBWindow->UserPort;
- winMsgList = &(winPort->mp_MsgList);
- winSignal = winPort->mp_SigBit;
- winMask = 1L << winSignal;
-
- /* setup our port */
- myPort.mp_SigBit = winSignal;
- myPort.mp_SigTask = winPort->mp_SigTask;
-
- /* flip things around */
- winPort->mp_SigTask = MM->handler_task;
- myMsgList->lh_Head = (struct Node *)&(winMsgList->lh_Tail);
- myMsgList->lh_TailPred = winMsgList->lh_TailPred;
- winMsgList->lh_TailPred = (struct Node *)&(myMsgList->lh_Head);
- myMsgList->lh_TailPred->ln_Succ = (struct Node *)&(myMsgList->lh_Tail);
-
- Permit();
-
- /* prevent deadlocks */
- orig_pri = SetTaskPri(MM->handler_task,
- myPort.mp_SigTask->tc_Node.ln_Pri+1);
- }
-
- /* 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. */
- del_MsgPort() {
- struct Message *tmpMsg;
- struct MsgPort *tmpPort;
-
- Forbid();
- /* clean out our list */
- while ((tmpMsg = GetMsg(&myPort)) != NULL) PutMsg(&myPort, tmpMsg);
-
- /* find MsgPort that myMsgList->lh_Head belongs to */
- /* (the port we've been PutMsg'ing to) */
- tmpPort = (struct MsgPort *) (
- (UBYTE*) &myPort - (UBYTE*) &(myPort.mp_MsgList.lh_Tail)
- + (UBYTE*)myMsgList->lh_Head);
-
- /* restore things */
- myMsgList->lh_Head->ln_Pred = myMsgList->lh_TailPred;
- myMsgList->lh_TailPred->ln_Succ = myMsgList->lh_Head;
- tmpPort->mp_SigTask = myPort.mp_SigTask;
- Permit();
-
- SetTaskPri(MM->handler_task, orig_pri);
- }
-
- /* do all appropriate initialization of monitor */
- BOOL setup_mon()
- {
- make_MsgPort();
- /* we need to allocate the same signal, so that it doesn't get
- allocated to something else, messing us up */
- our_signal = AllocSignal(winSignal);
- if (our_signal != winSignal) {
- finish_mon();
- return FALSE;
- }
- return TRUE;
- }
-
- /* clean up everything */
- finish_mon() {
- del_MsgPort();
- FreeSignal(our_signal);
- }
-
- /* See if we handle this event. If so, return ext_MenuItem structure */
- struct ext_MenuItem *
- match_item(Class, Code)
- ULONG Class;
- USHORT Code;
- {
- register struct ext_MenuItem *tmp;
- if (Class != MENUPICK || Code == MENUNULL)
- return NULL;
- for (tmp = MM->item_list; tmp; tmp=tmp->next_item)
- if (tmp->id == Code)
- return tmp;
- return NULL;
- }
-
- /* 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. */
- monitor()
- {
- register struct IntuiMessage *msg;
- register void *item;
- register ULONG mask, wb_mask;
-
- #ifdef DO_WB
- winMask |= (wb_mask = (1L << wb_reply_port->mp_SigBit));
- #endif
-
- winMask |= SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D;
-
- while (TRUE) {
- mask = Wait(winMask);
- if (mask & SIGBREAKF_CTRL_C) {
- /* caught ^C, time to close up */
- break;
- }
- if (mask & SIGBREAKF_CTRL_D) {
- /* reparse menus */
- del_menu_strip();
- Signal(MM->parent_task, (1 << MM->parent_sig));
- Wait(SIGBREAKF_CTRL_D);
- add_menu_strip();
- continue;
- }
- #ifdef DO_WB
- if (mask & wb_mask) {
- /* caught a reply from a WorkBench program exitting */
- register struct Message *wb_msg;
- while ((wb_msg = GetMsg(wb_reply_port)) != NULL) {
- wbfree(wb_msg);
- wb_cnt = (wb_cnt>0 ? (wb_cnt-1) : 0);
- }
- continue;
- }
- #endif
- /* if we got here, we have an IDCMP message */
- while ((msg = (struct IntuiMessage *)GetMsg(&myPort)) != NULL) {
- /* check if we deal with this or not */
- if ((item=(void *)match_item(msg->Class, msg->Code))!=NULL) {
- ReplyMsg(msg); /* always reply */
- run_item(item); /* run the indicated program */
- } else {
- PutMsg(&myPort, msg); /* pass on to original destination */
- }
- }
- }
- }
-