home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff225.lzh / MyMenu / Mon.c < prev    next >
C/C++ Source or Header  |  1989-06-24  |  6KB  |  191 lines

  1. /* Copyright ) Darin Johnson, 1989 */
  2.  
  3. /* This file has routines to allow us to 'monitor' an Intuition port */
  4.  
  5. /* What happens, is that we create a port, myPort, and set things up */
  6. /* so that GetMsg works normally for myPort, and the original port,  */
  7. /* winPort.  However, PutMsg to myPort will put the new message      */
  8. /* on winPort, and vice-versa.  Basically, the heads of both message */
  9. /* lists are normal, but the two tails have been swapped.  Since     */
  10. /* GetMsg uses the head of the list, it acts normally.  PutMsg uses  */
  11. /* the tail of the list, so it acts differently.  (the sigBit and    */
  12. /* sigTasks have also been swapped)                                  */
  13.  
  14. /* What this means, is that anything PutMsg'ed to the winPort, will  */
  15. /* signal us, and we can GetMsg it.  When we are finished looking at */
  16. /* that message, we can give it to winPort by PutMsg'ing to myPort.  */
  17.  
  18. #include <exec/ports.h>
  19. #include <libraries/dos.h>
  20. #include <libraries/dosextens.h>
  21. #include <intuition/intuitionbase.h>
  22. #include <devices/inputevent.h>
  23. #include <functions.h>
  24. #include "mymenu.h"
  25.  
  26. #ifdef DO_WB
  27. extern struct MsgPort *wb_reply_port;
  28. extern int wb_cnt;
  29. #endif
  30.  
  31. static struct MsgPort *winPort;
  32. static struct List *winMsgList;
  33. static LONG winSignal, our_signal;
  34. static LONG winMask;
  35. static BYTE orig_pri;
  36.  
  37. /* our port */
  38. static struct MsgPort myPort =
  39. {
  40.    {NULL, NULL, NT_MSGPORT, 0, NULL},
  41.    PA_SIGNAL,
  42.    0,
  43.    NULL,
  44.    {NULL, NULL, NULL, NT_MESSAGE, 0}
  45. };
  46.  
  47. static struct List *myMsgList = &(myPort.mp_MsgList);
  48.  
  49. /* fiddle with the two ports, setting things up */
  50. make_MsgPort()
  51. {
  52.   Forbid();
  53.     /* get the info we need */
  54.   winPort    = MM->WBWindow->UserPort;
  55.   winMsgList = &(winPort->mp_MsgList);
  56.   winSignal  = winPort->mp_SigBit;
  57.   winMask    = 1L << winSignal;
  58.  
  59.     /* setup our port */  
  60.   myPort.mp_SigBit    = winSignal;
  61.   myPort.mp_SigTask   = winPort->mp_SigTask;
  62.  
  63.     /* flip things around */
  64.   winPort->mp_SigTask = MM->handler_task;
  65.   myMsgList->lh_Head = (struct Node *)&(winMsgList->lh_Tail);
  66.   myMsgList->lh_TailPred = winMsgList->lh_TailPred;
  67.   winMsgList->lh_TailPred = (struct Node *)&(myMsgList->lh_Head);
  68.   myMsgList->lh_TailPred->ln_Succ = (struct Node *)&(myMsgList->lh_Tail);
  69.  
  70.   Permit();
  71.  
  72.     /* prevent deadlocks */
  73.   orig_pri = SetTaskPri(MM->handler_task,
  74.         myPort.mp_SigTask->tc_Node.ln_Pri+1);
  75. }
  76.  
  77. /* Restore things the way they were before make_MsgPort()           */
  78. /* Note that we don't refer to winPort.  This is because we         */
  79. /* may have had someone else 'monitor' this port (such as MonIDCMP) */
  80. /* besides us.                                                      */
  81. del_MsgPort() {
  82.   struct Message *tmpMsg;
  83.   struct MsgPort *tmpPort;
  84.   
  85.   Forbid();
  86.     /* clean out our list */
  87.   while ((tmpMsg = GetMsg(&myPort)) != NULL) PutMsg(&myPort, tmpMsg);
  88.  
  89.      /* find MsgPort that myMsgList->lh_Head belongs to */
  90.      /*      (the port we've been PutMsg'ing to)        */
  91.   tmpPort = (struct MsgPort *) (
  92.     (UBYTE*) &myPort - (UBYTE*) &(myPort.mp_MsgList.lh_Tail)
  93.     + (UBYTE*)myMsgList->lh_Head);
  94.  
  95.     /* restore things */
  96.   myMsgList->lh_Head->ln_Pred = myMsgList->lh_TailPred;
  97.   myMsgList->lh_TailPred->ln_Succ = myMsgList->lh_Head;
  98.   tmpPort->mp_SigTask = myPort.mp_SigTask;
  99.   Permit();
  100.   
  101.   SetTaskPri(MM->handler_task, orig_pri);
  102. }
  103.  
  104. /* do all appropriate initialization of monitor */
  105. BOOL setup_mon()
  106. {
  107.   make_MsgPort();
  108.     /* we need to allocate the same signal, so that it doesn't get
  109.        allocated to something else, messing us up */
  110.   our_signal = AllocSignal(winSignal);
  111.   if (our_signal != winSignal) {
  112.     finish_mon();
  113.     return FALSE;
  114.   }
  115.   return TRUE;
  116. }
  117.  
  118. /* clean up everything */
  119. finish_mon() {
  120.   del_MsgPort();
  121.   FreeSignal(our_signal);
  122. }
  123.  
  124. /* See if we handle this event.  If so, return ext_MenuItem structure */
  125. struct ext_MenuItem *
  126. match_item(Class, Code)
  127.   ULONG Class;
  128.   USHORT Code;
  129. {
  130.   register struct ext_MenuItem *tmp;
  131.   if (Class != MENUPICK || Code == MENUNULL)
  132.     return NULL;
  133.   for (tmp = MM->item_list; tmp; tmp=tmp->next_item)
  134.     if (tmp->id == Code)
  135.       return tmp;
  136.   return NULL;
  137. }
  138.  
  139. /* The actual monitor.  Just keep waiting for messages, and acting on them */
  140. /* Note that if we don't use a certain IDCMP message, we PutMsg it to get  */
  141. /* it back to the window it was meant for.                                 */
  142. monitor()
  143. {
  144.   register struct IntuiMessage *msg;
  145.   register void *item;
  146.   register ULONG mask, wb_mask;
  147.  
  148. #ifdef DO_WB
  149.   winMask |= (wb_mask = (1L << wb_reply_port->mp_SigBit));
  150. #endif
  151.  
  152.   winMask |= SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D;
  153.  
  154.   while (TRUE) {
  155.     mask = Wait(winMask);
  156.     if (mask & SIGBREAKF_CTRL_C) {
  157.     /* caught ^C, time to close up */
  158.       break;
  159.     }
  160.     if (mask & SIGBREAKF_CTRL_D) {
  161.         /* reparse menus */
  162.       del_menu_strip();
  163.       Signal(MM->parent_task, (1 << MM->parent_sig));
  164.       Wait(SIGBREAKF_CTRL_D);
  165.       add_menu_strip();
  166.       continue;
  167.     }
  168. #ifdef DO_WB
  169.     if (mask & wb_mask) {
  170.         /* caught a reply from a WorkBench program exitting */
  171.       register struct Message *wb_msg;
  172.       while ((wb_msg = GetMsg(wb_reply_port)) != NULL) {
  173.         wbfree(wb_msg);
  174.     wb_cnt = (wb_cnt>0 ? (wb_cnt-1) : 0);
  175.       }
  176.       continue;
  177.     }
  178. #endif
  179.       /* if we got here, we have an IDCMP message */
  180.     while ((msg = (struct IntuiMessage *)GetMsg(&myPort)) != NULL) {
  181.           /* check if we deal with this or not */
  182.       if ((item=(void *)match_item(msg->Class, msg->Code))!=NULL) {
  183.         ReplyMsg(msg);        /* always reply */
  184.         run_item(item);        /* run the indicated program */
  185.       } else {
  186.         PutMsg(&myPort, msg);    /* pass on to original destination */
  187.       }
  188.     }
  189.   }
  190. }
  191.