home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 408.lha / MyMenu_v1.1 / sources / Mon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-04  |  5.9 KB  |  206 lines

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