/*
 * mainloop.c   V1.5
 *
 * main event loop
 *
 * (c) 1991 by Stefan Becker
 *
 */
#include "ToolManager.h"

/* structures for quit requester */
static struct EasyStruct QuitES={sizeof(struct EasyStruct),0,MyName,
                                 "Really quit?","Ok|Cancel"};

/* Set global quit flag, if no WB tool is currently active */
/* Display a safety requester if the user wants it */
void SetQuitFlag(void)
{
 if (running=(wbactive>0))       /* Is a WB tool currently active? */
  DisplayBeep(NULL);             /* Yes, we can't quit! */
 else
  {
   struct Screen *pubsc=LockPubScreen(WBScreenName);
   struct Window *w=pubsc?pubsc->FirstWindow:NULL;

   /* Shall we show a quit requester? */
   if (ShowQuitReq)
    running=!EasyRequest(w,&QuitES,NULL,"");

   /* Check if config has changed */
   if (!running) running=ShowSaveConfigRequester(w);

   if (pubsc) UnlockPubScreen(NULL,pubsc);
  }
}

/* The main processing loop */
void mainloop(void)
{
 ULONG bsigs,psigs,csigs;   /* Buffers for signals */

 /* Init icon position */
 MyIcon->do_CurrentX=IconXPos;
 MyIcon->do_CurrentY=IconYPos;

 if (ShowIcon)                   /* Display our icon? */
  {
   /* If we have an icon, we don't need the "Open TM Window" menu entry */
   RemoveAppMenuItem(OTWAppMenuItem);
   OTWAppMenuItem=NULL;

   /* Notify Workbench about icon */
   if (!(MyAppIcon=AddAppIconA(NULL,NULL,IconName,MyMP,NULL,MyIcon,NULL)))
    cleanup(9);
  }

 /* Add TM pop up window hot key */
 AttachCxObj(MyBroker,HotKey(PopUpHotKey,MyBrokerPort,NULL));

 /* Commodities error? */
 if (CxObjError(MyBroker))
  cleanup(10);

 /* All things set up --> activate our broker */
 SetBrokerState(TRUE);

 bsigs=SIGBREAKF_CTRL_C|            /* break signals */
       SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F;
 psigs=1L<<MyMP->mp_SigBit;         /* port signal */
 csigs=1L<<MyBrokerPort->mp_SigBit; /* Commodities Broker port signal */
 globalsigs=bsigs|psigs|csigs;      /* merge signals */

 /* Open dock window */
 OpenDockWindow();
 ShowDock=TRUE;

 /* Show status window on startup? */
 if (ShowStatusWindow) OpenStatusWindow(FALSE);

 while (running)                    /* main event loop */
  {
   ULONG gotsigs;                   /* received signals */

   /* Wait for specified signals */
   gotsigs=Wait(globalsigs);

   if ((gotsigs&bsigs))             /* Got break signals and is no WB tool */
    SetQuitFlag();                  /* running? Yes, quit program */

   if (gotsigs&psigs)               /* Message arrived at message port? */
    {
     struct AppMessage *msg;        /* pointer to received message */

     while (msg=GetMsg(MyMP))       /* Yes, empty message queue */
      if (msg->am_Message.mn_Node.ln_Type==NT_REPLYMSG) /* Replied message? */
       {
        /* This is the death message from a tool we started some time ago */
        struct WBStartup *wbs=(struct WBStartup *) msg;
        struct WBArg *wa=wbs->sm_ArgList;
        int i=wbs->sm_NumArgs;

        while (i--)
         {
          UnLock(wa->wa_Lock);      /* Free WB argument */
          if (wa->wa_Name) free(wa->wa_Name);
          wa++;
         }

        if (wbs->sm_ToolWindow)     /* Free tool window specification */
         free(wbs->sm_ToolWindow);

        UnLoadSeg(wbs->sm_Segment); /* Unload code */
        free(wbs);                  /* Free WBStartup */
        wbactive--;                 /* One tool closed down */
       }
      else
       {
        switch(msg->am_Type)       /* Switch between message types */
         {
          case MTYPE_APPWINDOW:    /* Window action */
           switch(msg->am_ID)      /* Which AppWindow? */
            {
             case STATWINAPPID:    /* Status window */
                                   /* Add Workbench parameters to tool list */
              if (!WBAddToolNode(msg->am_ArgList,msg->am_NumArgs))
               DisplayBeep(NULL);
              RefreshStatusWindow(); /* Refresh status window if open */
              break;

             case DOCKWINAPPID:    /* Dock window */
              struct ToolNode *tn;
              WORD x=msg->am_MouseX,y=msg->am_MouseY;

              /* Find tool and start it with parameters */
              if (tn=FindDock(x,y))
               {
                SelectDock(tn,x,y,TRUE);
                StartTool(tn,msg);
                SelectDock(tn,x,y,FALSE);
               }
              break;
            }
           break;

          case MTYPE_APPICON:      /* Icon action */
           if (msg->am_ID)         /* Tool icon selected? */
            /* Start Tool, ID == Address of ToolNode */
            StartTool((struct ToolNode *) msg->am_ID,msg);
           else                    /* User selected program icon */
            if (msg->am_NumArgs==0) /* Did the user double click my icon? */
             OpenStatusWindow(FALSE); /* Yes! Open status window */
            else                   /* User dropped an icon on my icon */
             {                     /* Add Workbench parameters to tool list */
              if (!WBAddToolNode(msg->am_ArgList,msg->am_NumArgs))
               DisplayBeep(NULL);
              RefreshStatusWindow(); /* Refresh status window if open */
             }
           break;

          case MTYPE_APPMENUITEM:  /* Menu action */
           switch(msg->am_ID)
            {
             case 0:               /* "Quit ToolManager" menu item */
              SetQuitFlag();
              break;

             case 1:               /* "Open TM Window" menu item */
              OpenStatusWindow(FALSE);
              break;

             default:              /* Default: Tool selected */
              /* Start Tool, ID == Address of ToolNode */
              StartTool((struct ToolNode *) msg->am_ID,msg);
              break;
            }
           break;
         } /* end of switch(msg->am_Type) */

        ReplyMsg((struct Message *) msg);    /* Reply message to sender */
       } /* end of if (msg->......) */
    } /* end of if (gotsigs&psigs) */

   if (gotsigs&csigs)                   /* Got broker port signal? */
    {                                   /* Handle commodities event */
     struct CxMsg *msg;

     while (msg=GetMsg(MyBrokerPort))   /* Retrieve Messages from port */
      {
       switch(CxMsgType(msg))
        {
         case CXM_IEVENT:               /* Received a hot key event */
          struct ToolNode *tn;

          /* ID contains pointer to corresponding ToolNode */
          if (tn=(struct ToolNode *) CxMsgID(msg))
           {
            if (tn->tn_Flags&TNFLAGS_WBTF) /* Workbench Screen to front ? */
             {
              struct Screen *pubsc=LockPubScreen(WBScreenName);

              if (pubsc)
               {
                ScreenToFront(pubsc);
                UnlockPubScreen(NULL,pubsc);
               }
             }

            StartTool(tn,NULL);
           }
          else OpenStatusWindow(TRUE);  /* Pop up window hot key */
          break;

         case CXM_COMMAND:              /* Received a commodities command */
          switch(CxMsgID(msg))
           {
            case CXCMD_DISABLE:         /* Disable broker */
             SetBrokerState(FALSE);
             break;
            case CXCMD_ENABLE:          /* Enable broker */
             SetBrokerState(TRUE);
             break;
            case CXCMD_APPEAR:          /* Open status window */
             OpenStatusWindow(TRUE);
             break;
            case CXCMD_DISAPPEAR:       /* Close status window */
             CloseStatusWindow();
             break;
            case CXCMD_KILL:            /* Quit application */
             SetQuitFlag();
             break;
           }
          break;
        }

       ReplyMsg(msg);                   /* Reply message to sender */
      } /* end of while (msg=....) */
    } /* if (gotsigs&csigs) */

   if (gotsigs&statwinsig) /* Got status window signal? */
    HandleStatWinEvent();  /* Handle status window event */

   if (gotsigs&editwinsig) /* Got edit window signal? */
    HandleEditWinEvent();  /* Handle edit window event */

   if (gotsigs&hkeywinsig)   /* Got HotKeys window signal? */
    HandleHotKeysWinEvent(); /* Handle HotKeys window event */

   if (gotsigs&dockwinsig) /* Got dock window signal? */
    HandleDockWinEvent();  /* Handle dock window event */
  } /* end of main loop */

 /* If window open, close it */
 CloseStatusWindow();
 CloseEditWindow();
 CloseHotKeysWindow();
 CloseDockWindow();

 /* Exit program */
 cleanup(99);
}

