home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- *
- * THIS FILE USES 4 COLUMN TAB STOPS.
- *
- *
- * This is the Intuition Message processor for Leach Ver 1.3
- *
- ******************************************************************************/
-
- #include <functions.h>
- #include <exec/ports.h>
- #include <exec/libraries.h>
- #include <graphics/gfx.h>
- #include <graphics/rastport.h>
- #include <graphics/text.h>
- #include <intuition/intuitionbase.h>
- #include <stdio.h>
-
- /*----------------------------------------------------------------------------*
- * gad.h is a real mixed bag. It defines (allocates storage for) many gadget
- * related variables. It also declares the char array "statustext".
- *----------------------------------------------------------------------------*/
-
- #include "gad.h"
-
-
- /* Stuff in globals.h is defined globally and initialized in main.c. */
-
- #define GLOBAL extern
- #include "globals.h"
-
- extern short endpoints[]; /* End point coordinates for ruler */
-
- #define x1 0 /* endpoints array indexes. */
- #define y1 1 /* Note LOWER CASE! */
- #define x2 2
- #define y2 3
-
- extern struct Border ruler; /* Border struct for ruler. */
-
- /************ VARIABLES USED JUST INSIDE THIS FILE ********************/
-
- short mx, my; /* Mouse coordinates. */
- short trac; /* TRUE if in the middle of MOUSEBUTTONS pair */
- short update; /* Flag means status display needs refreshing. */
- short ruler_color = 3;
- short moving = 0; /* Nonzero if ruler should be tracking mouse*/
- short sizing = 0; /* 0 if the ruler is not being sized/moved */
- /* 1 if the first endpoint is being moved. */
- /* 2 if the second endpoint is being moved. */
-
-
- /*******************************************************************************
- * LOOP MONITORING MENU EVENTS
- *
- * This routine sleeps, waiting for an IntuiMsg for either the Host or for
- * the Leach's status window or for a message being returned by the Host to
- * "MyPort". There are separate processor routines for each of these message
- * types. Note that ALL MESSAGES IN THE HOST IDCMP ARE PROCESSED BEFORE ANY
- * OF THE LEACH MESSAGES ARE PROCESSED. Hopefully this means that there
- * won't be any msgs for Leach in the Host's queue when Leach processes
- * a CLOSEWINDOW event from its queue. Eventually one of the processors will
- * fail to return because it terminated the program. event_processor() will
- * never return to its caller.
- *
- * Also remember that Leach is running at a higher priority than the Host
- * so, Leach will get first crack at the incoming messages even if
- * the Host is processing its msg queue when a msg arrives at the port.
- ******************************************************************************/
-
- event_processor()
- {
-
- ULONG sigfor, StatMask, HostMask, MyMask;
-
- StatMask = 1L << StatWind->UserPort->mp_SigBit;
- HostMask = 1L << HostSig;
- MyMask = 1L << MySig;
-
- FOREVER
- {
- sigfor = Wait(HostMask | StatMask | MyMask);
-
- if (sigfor & MyMask) /* Replying to IntuiMsgs gets top priority. */
- myport_event();
- if (sigfor & HostMask)
- host_event();
- if (sigfor & StatMask)
- stat_event();
- if (sigfor & ~(HostMask | StatMask) )
- {
- puts("event_processor(): RECEIVED AN UNEXPECTED SIGNAL BIT.");
- cleanup(202);
- }
-
- } /* end of FOREVER */
-
- } /* End of event_processor() */
-
-
- /*****************************************************************************
- * CHECKMSG()
- *
- * This routine looks at the messages in the Host IDCMP's input queue and
- * returns the address of the next message to be processed by host_event().
- * It always starts at the first msg in the queue, walking the linked list
- * until it finds a msg whose mn_ReplyPort is not "MyPort". It sets the
- * mn_ReplyPort to MyPort in messages that have been processed. It has to
- * work this way cause you never know when a new msg might arrive or what
- * the Host has been doing to the list since you last looked at it.
- *
- * Returns address of current message or Null if there are no new messages.
- *
- * FYI: This is what an IntuiMessage looks like.
- *
- * struct IntuiMessage
- * {
- * struct Message ExecMessage
- * {
- * struct Node mn_Node
- * {
- * struct Node *ln_Succ;
- * struct Node *ln_Pred;
- * UBYTE ln_Type;
- * BYTE ln_Pri; NOT ALWAYS INITIALIZED TO ZERO!
- * char *ln_Name;
- * }
- * struct MsgPort *mn_ReplyPort;
- * UWORD mn_Length;
- * }
- * ULONG Class;
- * USHORT Code;
- * USHORT Qualifier;
- * APTR IAddress;
- * SHORT MouseX, MouseY;
- * ULONG Seconds, Micros;
- * struct Window *IDCMPWindow;
- * struct IntuiMessage *SpecialLisk; Don't ever mess with this
- * }
- *
- * struct MsgPort
- * {
- * struct Node mp_Node;
- * UBYTE mp_Flags;
- * UBYTE mp_SigBit;
- * struct Task *mp_SigTask;
- * struct List mp_MsgList;
- * };
- *****************************************************************************/
-
- struct IntuiMessage *checkmsg(port)
- struct MsgPort *port; /* Port to be examined */
- {
-
- register struct IntuiMessage *message;
-
- short cnt; /* cnt & check_flags are for debugging */
- short check_flags;
-
-
- /* These #defines are only used for debugging. */
-
- #define NO_MSG 0x0001
- #define NULL_HEAD 0x0004
- #define NO_NEW 0x0008
-
- cnt = check_flags = 0;
- Forbid(); /*########## MULTITASKING DISABLED ##########*/
-
-
- /*-------------------------------------------------------------------------*
- * Aim message pointer at the first node in the list. lh_Head should never
- * be NULL, but we'll check anyway. If Head is pointing at the Tail, the
- * msg queue is empty. This could be an error but probably isn't. It
- * happens when disposemsg() Remove()s the only message in the queue. In
- * this case, checkmsg() returned a valid message address so, the while
- * loop in host_event() takes another look at the message queue, which is
- * now empty.
- *-------------------------------------------------------------------------*/
-
- message = (struct IntuiMessage *) port->mp_MsgList.lh_Head;
- if (!message)
- check_flags |= NULL_HEAD;
- else if (message == &(port->mp_MsgList.lh_Tail) )
- {
- check_flags |= NO_MSG;
- message = NULL;
- }
- while (message)
- {
- ++cnt;
- if (message->ExecMessage.mn_ReplyPort != MyPort)
- {
- /*--------------------------------------------------------------------*
- * Found unprocessed message. I hate altering the IntuiMessage like
- * this but, you can't count on the date stamps uniquely identifying
- * the messages. I had to mark them somehow.
- *--------------------------------------------------------------------*/
- if (!HostIPort)
- {
- HostIPort = message->ExecMessage.mn_ReplyPort;
- }
- else if (message->ExecMessage.mn_ReplyPort != HostIPort)
- {
- /* Aegis Images triggers this error message sometimes. */
- puts("CHECKMSG(): Found an unexpected mn_ReplyPort.");
- }
- message->ExecMessage.mn_ReplyPort = MyPort;
- break;
- }
- else /* Leach has already seen this msg. Try next msg in the queue. */
- {
- message = message->ExecMessage.mn_Node.ln_Succ;
- if (message == &(port->mp_MsgList.lh_Tail) )
- {
- message = NULL; /* Reached end of msg list. */
- check_flags |= NO_NEW;
- }
- }
- } /* end of while (message) */
-
-
- /*------------------------------------------------------------------------*
- * Re-enabling multitasking here feels vaguely dangerous. I am about to
- * pass around a pointer to a msg that I don't own. However, host_event()
- * will make a copy of the message data as soon as checkmsg() returns.
- *------------------------------------------------------------------------*/
-
- Permit(); /*########### MULTITASKING ENABLED ###########*/
-
- /*****************************************************************************
- *** If any of the "error" conditions occurred, now's the time to speak up. *
-
- if (check_flags)
- {
- if (check_flags & NO_MSG)
- {
- puts("No msg in Host's UserPort.");
- }
- if (check_flags & NULL_HEAD)
- {
- puts(" SOME HOW, LH_HEAD IS NULL.");
- }
- if (check_flags & NO_NEW)
- {
- printf("EOQ #%d.\n", cnt);
- }
- check_flags = 0;
- }
- else
- {
- printf("checkmsg(): Msg #%d new.\n", cnt);
- }
- printf("checkmsg(): Returning msg addr $%lx.\n", message);
- *****************************************************************************
- *****************************************************************************/
-
- return(message);
-
- } /* End of checkmsg() */
-
-
-
- /*****************************************************************************
- * This routine identifies messages that Leach is not going to pass on
- * to the Host, Remove()'s them, restores mn_ReplyPort to Intuition's Port
- * address & ReplyMsg()'s to them. It is also responsible for Signal()'ing
- * the Host for msgs that are not consumed by Leach.
- *****************************************************************************/
-
- disposemsg(msg)
- struct IntuiMessage *msg;
- {
-
- register ULONG class;
- register USHORT code;
-
- class = msg->Class;
- code = msg->Code;
-
- /*---------------------------------------------------------------------------*
- * If any of 3 criteria for consuming a msg is met the msg is removed from
- * the queue and replied to. The criteria are:
- * 1) A MOUSEBUTTONS event while the ruler is in "move" mode.
- * 2) A MOUSEMOVE event while the ruler is tracking the mouse.
- * 3) A menu selection has been made from the menu Leach installed
- * at the end of the Host's first menu.
- *---------------------------------------------------------------------------*/
-
- if ( ( (MOVEGAD.Flags & SELECTED) && (class == MOUSEBUTTONS) ) ||
- ( (trac == TRUE) && (class == MOUSEMOVE ) ) ||
- ( (class == MENUPICK) && (code != MENUNULL) &&
- ( MENUNUM(code) == L_menu_num) && (ITEMNUM(code) == L_menuitem_num) ) )
- {
- Forbid();
- Remove( &(msg->ExecMessage.mn_Node) ); /* For Leach only. */
- Permit();
- msg->ExecMessage.mn_ReplyPort = HostIPort;
- ReplyMsg(msg);
- }
- else
- {
- Signal(HostTask, 1L << HostSig);
- }
-
- return;
-
- } /* End of disposemsg() */
-
-
- /*****************************************************************************
- * HOST INTUITION EVENT PROCESSOR
- * This routine examins all the messages waiting at the Host's IDCMP. The
- * messages have to be examined in place so that they can be passed on to
- * the Host, if necessary. Messages intended exclusively for Leach are
- * removed from the message queue.
- *****************************************************************************/
-
- host_event()
- {
-
- ULONG class; /* Class of IntuiMessage. */
- USHORT code; /* Code of IntuiMessage. */
-
- static UBYTE act_flag = 0; /* Set when Host receives ACTIVEWINDOW msg. */
-
- USHORT MenuNum, ItemNum, SubNum; /* Menu, MenuItem and Subitem numbers */
- short mmflag;
- struct IntuiMessage *message;
-
- /*----------------------------------------------------------------------*
- * Note that checkmsg() is periodically called when there are no msgs in
- * the queue. This happens when disposemsg() removes the only msg in the
- * queue or when the end of the queue is reached. checkmsg() gets called
- * one last time and finds the cupboard is bare. This is not an error.
- *----------------------------------------------------------------------*/
-
- while( message = checkmsg(HostUPort) )
- {
- class = message->Class;
- code = message->Code;
- mx = message->MouseX;
- my = message->MouseY;
-
- /* printf("H_event: Class = $%lx. Code = $%x.\n\n", class, code); */
-
- disposemsg(message); /* ReplyMsg()s to Leach msgs and Signals */
- /* the Host for pass through msgs. */
-
-
- if (class == ACTIVEWINDOW)
- act_flag = 2; /* Ignore next SELECT UP/DOWN pair. */
-
- /*--------------------- HOST MENU EVENTS -------------------------*
- *------------------------------------------------------------------*/
-
- else if (class == MENUPICK && code != MENUNULL)
- {
- MenuNum = MENUNUM(code);
- ItemNum = ITEMNUM(code);
- SubNum = SUBNUM(code);
-
- /* If Leach's MenuItem... */
- if (MenuNum == L_menu_num && ItemNum == L_menuitem_num)
- {
- switch (SubNum)
- {
- case 0: /* Leach screen to front */
- ScreenToFront(StatScreen);
- break;
-
- case 1: /* Leach screen to back */
- ScreenToBack(StatScreen);
- break;
- }
- }
- else /* Not Leach Menu */
- {
- /*----------------------------------------------------------*
- * The only Host menu event that we take special interest in
- * is QUIT. All other Host menu events are treated the same
- * way. Namely, Leach tries to make itself as inconspicuous
- * as possible.
- *----------------------------------------------------------*/
-
- if ( (MenuNum == H_quit_menu) && (ItemNum == H_quit_item) &&
- (H_found_quit) )
- {
- cleanup(204);
- }
- else
- {
- if (SHOWGAD.Flags & SELECTED) /* If in show mode... */
- {
- hide_ruler();
- }
- ScreenToBack(StatScreen);
- break;
- }
- }
-
- } /* End of if (class == MENUPICK && code != MENUNULL) */
-
-
- /*------------------- SELECT BUTTON EVENTS -----------------------*
- * Select button events while the MOVE gadget is selected are the
- * exclusive property of Leach. They control movement and sizing of
- * the ruler. If the Host window activation flag is set, we want to
- * ignore the next mouse click.
- *------------------------------------------------------------------*/
-
- else if ( (class == MOUSEBUTTONS) && (MOVEGAD.Flags & SELECTED) )
- {
- if (act_flag)
- --act_flag;
- else if (code == SELECTDOWN)
- {
- HostFlagsmods |= REPORTMOUSE;
- HostWind->Flags = HostFlags | HostFlagsmods;
-
- HostIDCMPmods |= MOUSEMOVE;
- ModifyIDCMP(HostWind, HostIDCMPflags | HostIDCMPmods);
-
- trac = TRUE;
-
- /* If the mouse is near the first endpoint, then move it. */
-
- if ( (mx > endpoints[x1] - 4) && (mx < endpoints[x1] + 4) &&
- (my > endpoints[y1] - 5) && (my < endpoints[y1] + 5) )
- {
- sizing = 1;
- moving = 0;
- size_ruler();
- }
-
- /* Or, if the mouse is near the second endpoint, then move it. */
-
- else if ( (mx > endpoints[x2] - 4) && (mx < endpoints[x2] + 4) &&
- (my > endpoints[y2] - 5) && (my < endpoints[y2] + 5) )
- {
- sizing = 2;
- moving = 0;
- size_ruler();
- }
-
- /* By default we'll move the entire ruler. The first endpoint */
- /* will jump to the mouse position. */
-
- else
- {
- sizing = 0;
- moving = 1;
- move_ruler();
- }
- } /* end of if ( (code == SELECTDOWN) && etc ) */
-
- else if (code == SELECTUP)
- {
- /*----------------------------------------------------------*
- * If we're done moving, shut off reports on mouse movement.
- * There may be other mouse movement msgs at the IDCMP but,
- * we'll process/ignore them later.
- *----------------------------------------------------------*/
-
- HostFlagsmods &= ~REPORTMOUSE;
- HostWind->Flags = HostFlags | HostFlagsmods;
-
- HostIDCMPmods &= ~MOUSEMOVE;
- ModifyIDCMP(HostWind, HostIDCMPflags | HostIDCMPmods);
- trac = FALSE;
- }
- } /* end of else if ( (class == MOUSEBUTTONS) && etc) */
-
-
- /*---------------------- RULER MOVEMENT -----------------------------*
- * If the ruler is tracking the mouse, all we do is note that the mouse
- * has moved. We don't actually move the ruler until we've processed
- * all the messages in the queue, other wise we couldn't handle the
- * flood of MOUSEMOVE messages that come in.
- *---------------------------------------------------------------------*/
-
- else if ( (class == MOUSEMOVE) && (trac == TRUE) )
- {
- mmflag = TRUE;
-
- } /* end of else if (class == MOUSEMOVE && etc) */
-
- } /* End of while(message = checkmsg(HostUPort)) */
-
-
- /*----------------------------------------------------------------------------*
- * At this point we have processed all of the new msgs that were found in the
- * Host's message queue. If we have encountered any MOUSEMOVE msgs during this
- * pass through the list that were for Leach, we'll now actually move the
- * ruler and change the status display.
- *----------------------------------------------------------------------------*/
-
- if (mmflag) /* If there have been requests for line movement. */
- {
- if (moving)
- move_ruler();
- else if (sizing)
- size_ruler();
-
- mmflag = FALSE;
- }
- /*---------------------------------------------------------------------------*
- * trac is cleared when a SELECTUP event is detected. This tells disposemsg()
- * to stop scarfing MOUSEMOVE msgs. However, there may still be a move
- * pending as indicated by moving or sizing. Well, we just finished that
- * move, so now we can finally turn these indicators off.
- *---------------------------------------------------------------------------*/
-
- if (!trac)
- {
- moving = sizing = 0;
- }
-
- if (update)
- {
- update_status();
- update = 0;
- }
-
- return;
-
- } /* End of host_event */
-
-
- /******************************************************************************
- * LEACH INTUITION EVENT PROCESSOR
- * This routine is a more conventional message processor for the Status
- * Display Window. We're expecting only Close Window and Gadget events
- * at the moment.
- *
- ******************************************************************************/
-
- stat_event()
- {
-
- ULONG class; /* Class of IntuiMessage. */
- USHORT code; /* Code of IntuiMessage & MenuItem number. */
- struct Gadget *gad_addr; /* Address of toggled gadget. */
-
- struct IntuiMessage *message;
-
- while ( message = (struct IntuiMessage *) GetMsg(StatWind->UserPort) )
- {
- class = message->Class;
- code = message->Code;
- mx = message->MouseX;
- my = message->MouseY;
- gad_addr = (struct Gadget *) message->IAddress;
-
- ReplyMsg(message);
-
- if (class == CLOSEWINDOW)
- {
- cleanup(206);
- }
- else if (class == GADGETUP)
- {
- /******************* Toggle the SHOW/HIDE" Gadget ? ***************/
-
- if (gad_addr == &SHOWGAD) /* If the show/hide gadget */
- {
- /* If ruler just got deselected enter hide mode. */
- if (! (SHOWGAD.Flags & SELECTED) )
- {
- hide_ruler();
- }
- else
- {
- /*----------------------------------------------------------*
- * S/H has just changed to show mode. Change displayed text
- * Draw ruler. Make sure that M/F gadget is enabled
- *----------------------------------------------------------*/
-
- swap_gtext(gad_addr);
- draw_line(HostRPort, ruler_color, endpoints[x1], endpoints[y1],
- endpoints[x2], endpoints[y2]);
- OnGadget(&MOVEGAD, StatWind, NULL);
- }
- } /* end of if (gad_addr == &SHOWGAD) */
-
-
- /************* Toggled the "MOVE/FREEZE" Gadget ? *****************/
-
- else if (gad_addr == &MOVEGAD)
- {
- swap_gtext(&MOVEGAD);
-
- if (MOVEGAD.Flags & SELECTED) /* Entering move mode. */
- {
- /* Enable selectbutton reports. */
- HostIDCMPmods |= MOUSEBUTTONS;
- ModifyIDCMP(HostWind, HostIDCMPflags | HostIDCMPmods);
- set_pointer();
- }
- else /* Entering freeze mode. Text = "Move" */
- {
- HostIDCMPmods &= ~(MOUSEBUTTONS | MOUSEMOVE);
- ModifyIDCMP(HostWind, HostIDCMPflags | HostIDCMPmods);
- restore_pointer();
- }
- }
- else if (gad_addr == &swind_gad[2]) /* If the left color gadget */
- {
- if (SHOWGAD.Flags & SELECTED) /* If ruler is visible... */
- {
- restore_line();
- --ruler_color;
- draw_line(HostRPort, ruler_color, endpoints[x1], endpoints[y1],
- endpoints[x2], endpoints[y2]);
- }
- }
- else if (gad_addr == &swind_gad[3]) /* If the rite color gadget */
- {
- if (SHOWGAD.Flags & SELECTED) /* If ruler is visible... */
- {
- restore_line();
- ++ruler_color;
- draw_line(HostRPort, ruler_color, endpoints[x1], endpoints[y1],
- endpoints[x2], endpoints[y2]);
- }
- }
- else
- {
- puts("Leach received a funny gadget address.");
- }
-
- RefreshGadgets(swind_gad, StatWind, NULL);
-
- } /* end of else if (class == GADGETUP) */
-
- else if (class == REFRESHWINDOW) /* Shouldn't get any of these, */
- { /* but what the Hell. */
- BeginRefresh(StatWind);
- EndRefresh(StatWind, TRUE);
- update_status();
- RefreshGadgets(swind_gad, StatWind, NULL);
- update = 0;
- }
- else
- {
- puts("stat_event(): Received unexpected Msg class.");
- }
- } /* end of while (message = etc.) */
-
- return;
-
- } /* End of stat_event() */
-
-
- /**************************************************************************
- * Restore the mn_ReplyPort address in a message returned by the Host and
- * forward to Intuition.
- **************************************************************************/
-
- myport_event()
- {
- struct IntuiMessage *msg;
-
- while ( msg = (struct IntuiMessage *) GetMsg(MyPort) )
- {
- if (HostIPort)
- {
- msg->ExecMessage.mn_ReplyPort = HostIPort;
- ReplyMsg(msg);
- }
- else
- puts("MYPORT_EVENT(): Trouble in River City.");
- }
- return;
-
- } /* End of myport_event() */
-
-
- /**************************************************************************
- * Exchange gadget IntuiText text pointer with gadget's UserData pointer
- * which, in this case, points to the alternate text string.
- **************************************************************************/
-
- swap_gtext(gad_addr)
- struct Gadget *gad_addr;
- {
-
- UBYTE *itext; /* Temp storage for alternate text pointer during swap. */
-
- itext = gad_addr->UserData;
- gad_addr->UserData = gad_addr->GadgetText->IText;
- gad_addr->GadgetText->IText = itext;
-
- return;
-
- } /* End of swap_gtext() */
-
- /********************* END OF EVENT.C FOR LEACH PROGRAM *********************/
-