/*
 *  ClipTool (Udklipsværktøj) - A Commodities Exchange Application
 *  Copyright (C) 1994 Torsten Poulin
 *
 *  handleevents.c
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *             The author can be contacted by mail at
 *               Torsten Poulin
 *               Banebrinken 99, 2, 77
 *               DK-2400 Copenhagen NV
 *               Denmark
 *             or via email: torsten@diku.dk
 *
 * $Log:	handleevents.c,v $
 * Revision 1.1  94/02/20  21:32:26  Torsten
 * Initial revision
 * 
 */

static char const RCSid[] = "$Id: handleevents.c,v 1.1 94/02/20 21:32:26 Torsten Exp $";

#include "cliptool.h"

static BOOL handleIntui(void);
static BOOL handleCX(void);
static void handleAppWin(void);
static void handleAppIcon(void);
static BOOL handleARexx(void);
static long rxcmd(long, UBYTE *, struct CSource *, struct RexxMsg *);

void handleevents(void)
{
  BOOL killed = FALSE;
  ULONG sigrcvd, winsigflag, flags;

  /* Should the window be opened initially? */
  if (nothidden)
    if (!opengui()) closegui();

  while (!killed) {
    winsigflag = 0;

    ghosting();

    flags = SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F | cxsigflag | rxsigflag;
    if (guiwin) {
      flags |= winsigflag = 1L << guiwin->UserPort->mp_SigBit;
      if (appwin)
	flags |= awsigflag;
    }
    if (appicon) flags |= aisigflag;

    sigrcvd = Wait(flags);

    if (guiwin) {
      if (appwin)
	if (sigrcvd & awsigflag) handleAppWin();
      if (sigrcvd & winsigflag) killed = handleIntui();
    }
    if (sigrcvd & cxsigflag) killed = handleCX();
    if (appicon && (sigrcvd & aisigflag)) handleAppIcon();
    if (sigrcvd & rxsigflag) killed = handleARexx();
    if (sigrcvd & SIGBREAKF_CTRL_F)
      if(!opengui()) closegui();
    if (sigrcvd & SIGBREAKF_CTRL_C) killed = TRUE; /* bye ... */
  }
}


static BOOL handleIntui(void)
{
  struct IntuiMessage *gtimsg;
  ULONG gtimsgclass;
  UWORD gtimsgcode;
  UWORD menunumber;
  ULONG menuselection;
  struct MenuItem *menuitem;
  struct Gadget *button;
  BOOL disappear = FALSE;
  BOOL killed = FALSE;

  while (!killed && !disappear && (gtimsg = GT_GetIMsg(guiwin->UserPort))) {
    gtimsgclass = gtimsg->Class;
    gtimsgcode = gtimsg->Code;
    button = (struct Gadget *) gtimsg->IAddress;
    GT_ReplyIMsg(gtimsg);

    switch (gtimsgclass) {
    case IDCMP_REFRESHWINDOW:
      GT_BeginRefresh(guiwin);
      GT_EndRefresh(guiwin, TRUE);
      if (!newsize()) disappear = TRUE;
      else showtext();
      break;
    case IDCMP_MENUPICK:
      menunumber = gtimsgcode;
      while (!killed && !disappear && menunumber != MENUNULL) {
	menuitem = ItemAddress(ctmenustrip, menunumber);
	menuselection = (ULONG) GTMENUITEM_USERDATA(menuitem);
	switch (menuselection) {
	case CTM_OPENTEXT: loadtext(FALSE); break;
	case CTM_OPENFTXT: loadtext(TRUE); break;
	case CTM_SAVETEXT: savetext(FALSE); break;
	case CTM_SAVEFTXT: savetext(TRUE); break;
	case CTM_ABOUT: about(); break;
	case CTM_HIDE: disappear = TRUE; break;
	case CTM_QUIT: killed = TRUE; break;
	case CTM_CUT: cut(); break;
	case CTM_COPY: copy(); break;
	case CTM_PASTE: paste(); break;
	case CTM_KILL: freetext(); break;
	case CTM_PREV: prevtext(); break;
	case CTM_NEXT: nexttext(); break;
	case CTM_ICONS: createicons = (menuitem->Flags & CHECKED); break;
	case CTM_APPICON: usedropicon = (menuitem->Flags & CHECKED); break;
	case CTM_UNIT: getunitnumber(); break;
	}
	menunumber = menuitem->NextSelect;
      }
      break;
    case IDCMP_GADGETUP:
      switch (button->GadgetID) {
      case BBGD_OPEN: loadtext(FALSE); break;
      case BBGD_SAVE: savetext(FALSE); break;
      case BBGD_CUT: cut(); break;
      case BBGD_COPY: copy(); break;
      case BBGD_PASTE: paste(); break;
      case BBGD_KILL: freetext(); break;
      case BBGD_PREV: prevtext(); break;
      case BBGD_NEXT: nexttext(); break;
      }
      break;
    case IDCMP_CLOSEWINDOW: disappear = TRUE; break;
    }
  }

  if (usedropicon) {
    if (!appicon) opendropicon();
  }
  else closedropicon();
  if (disappear) closegui();
  return killed;
}


/*
 * Handle Commodities Exchange events
 */

static BOOL handleCX(void)
{
  CxObj *cxmsg;
  ULONG cxmsgid, cxmsgtype;
  BOOL killed = FALSE;

  while (cxmsg = (CxMsg *) GetMsg(broker_mp)) {
    cxmsgid = CxMsgID(cxmsg);
    cxmsgtype = CxMsgType(cxmsg);
    ReplyMsg((struct Message *) cxmsg);

    switch (cxmsgtype) {
    case CXM_IEVENT:
      if (cxmsgid == EVENT_HOTKEY)
	if (!opengui()) closegui();
      break;
    case CXM_COMMAND:
      switch (cxmsgid) {
      case CXCMD_DISABLE: ActivateCxObj(broker, 0L); break;
      case CXCMD_ENABLE: ActivateCxObj(broker, 1L); break;
      case CXCMD_APPEAR: if (!opengui()) closegui(); break;
      case CXCMD_DISAPPEAR: closegui(); break;
      case CXCMD_KILL: killed = TRUE; break; /* goodbye ... */
      case CXCMD_UNIQUE: if (!opengui()) closegui(); break;
      }
      break;
    }
  }
  return killed;
}


/*
 * Handle AppWindow events.
 */

static void handleAppWin(void)
{
  struct AppMessage *awmsg;
  struct WBArg *args;
  long i;

  while (awmsg = (struct AppMessage *) GetMsg(appwin_mp)) {
    args = awmsg->am_ArgList;
    for (i = 0; i < awmsg->am_NumArgs; i++, args++)
      loaddropped(args->wa_Name, args->wa_Lock);
    ReplyMsg((struct Message *) awmsg);
  }
}


/*
 * Handle AppIcon events.
 */

static void handleAppIcon(void)
{
  struct AppMessage *aimsg;
  struct WBArg *args;
  long i;

  while (aimsg = (struct AppMessage *) GetMsg(appicon_mp)) {
    args = aimsg->am_ArgList;

    if (aimsg->am_NumArgs == 0) {
      /*
       * User double-clicked the AppIcon.
       */
      if (!opengui()) closegui();
    }
    else if (aimsg->am_NumArgs > 0)
      for (i = 0; i < aimsg->am_NumArgs; i++, args++)
	loaddropped(args->wa_Name, args->wa_Lock);
    ReplyMsg((struct Message *) aimsg);
  }
}


#define RXCMD_CREATEICONS (1)
#define RXCMD_APPICON     (2)
#define RXCMD_GETUNIT     (3)
#define RXCMD_SETUNIT     (4)
#define RXCMD_OPEN        (5)
#define RXCMD_SAVEAS      (6)
#define RXCMD_GETNUM      (7)
#define RXCMD_GETCUR      (8)
#define RXCMD_GETCI       (9)

static long rxcmd(long cmd, UBYTE *template, struct CSource *cs,
		  struct RexxMsg *rxmsg)
{
  struct MenuItem *mi;
  struct RDArgs *rdargs;
  UBYTE *arglist, sval[20], *s, *sptr, *valptr;
  long val[3];
  long result = 0;

  val[0] = val[1] = val[2] = 0;

  if (arglist = malloc(strlen(&cs->CS_Buffer[cs->CS_CurChr])+2)) {
    strcpy(arglist, &cs->CS_Buffer[cs->CS_CurChr]);
    strcat(arglist, "\n");	/* ReadArgs() needs this */

    if (rdargs = (struct RDArgs *) AllocDosObject(DOS_RDARGS, NULL)) {
      rdargs->RDA_Source.CS_Buffer = arglist;
      rdargs->RDA_Source.CS_Length = strlen(arglist);
      rdargs->RDA_Flags = RDAF_NOPROMPT;

      if (ReadArgs(template, val, rdargs)) {
	switch (cmd) {
	case RXCMD_CREATEICONS:
	case RXCMD_APPICON:
	  if (val[0] == val[1])
	    result = 20;		/* bogus combination! */
	  else if (val[0]) {		/* ON */
	    if (guiwin) {
	      ClearMenuStrip(guiwin);
	      mi = findmenuitem(ctmenustrip, (cmd == RXCMD_APPICON
					      ? CTM_APPICON
					      : CTM_ICONS));
	      mi->Flags |= CHECKED;
	      ResetMenuStrip(guiwin, ctmenustrip);
	    }
	    if (cmd == RXCMD_APPICON) {
	      usedropicon = TRUE;
	      if (!appicon) opendropicon();
	    }
	    else createicons = TRUE;
	  }
	  else {		/* OFF */
	    if (guiwin) {
	      ClearMenuStrip(guiwin);
	      mi = findmenuitem(ctmenustrip, (cmd == RXCMD_APPICON
					      ? CTM_APPICON
					      : CTM_ICONS));
	      mi->Flags &= ~CHECKED;
	      ResetMenuStrip(guiwin, ctmenustrip);
	    }
	    if (cmd == RXCMD_APPICON) {
	      usedropicon = FALSE;
	      closedropicon();
	    }
	    else createicons = FALSE;
	  }
	  break;
	case RXCMD_GETUNIT:
	case RXCMD_GETNUM:
	case RXCMD_GETCUR:
	case RXCMD_GETCI:
	  /* ARexx names must be uppercase */
	  valptr = (UBYTE *) val[0];
	  if (s = sptr = malloc(strlen(valptr) + 1)) {
	    for (; *valptr; *valptr++)
	      *sptr++ = toupper(*valptr);
	    *sptr = '\0';
	    if (cmd == RXCMD_GETCI) {
	      synchronizechecked();
	      if (createicons) 
		SetRexxVar((struct Message *) rxmsg, s, "ON", 2L);
	      else
		SetRexxVar((struct Message *) rxmsg, s, "OFF", 3L);
	    }
	    else {
	      if (cmd == RXCMD_GETCUR) sprintf(sval, "%ld", ncurrent);
	      else if (cmd == RXCMD_GETNUM) sprintf(sval, "%ld", ntotal);
	      else sprintf(sval, "%ld", unitnumber);
	      SetRexxVar((struct Message *) rxmsg, s, sval, strlen(sval));
	    }
	    free(s);
	  }
	  else result = 20;
	  break;
	case RXCMD_SETUNIT:
	  if (*(long *)val[0] < 0 || *(long *)val[0] > 255) result = 20;
	  else unitnumber = *(long *)val[0];
	  break;
	case RXCMD_OPEN:
	  s = (val[1] ? (UBYTE *) val[1] : (UBYTE *) ""); /* directory */
	  rxload((UBYTE *) val[0], s);
	  break;
	case RXCMD_SAVEAS:
	  s = (val[2] ? (UBYTE *) val[2] : (UBYTE *) ""); /* directory */
	  rxsave((UBYTE *) val[0], s, (BOOL) val[1]);
	  break;
	}
	FreeArgs(rdargs);
      }
      else result = 20;
      FreeDosObject(DOS_RDARGS, rdargs);
    }
    free(arglist);
  }
  else result = 20;
  return result;
}


/*
 * Handle requests from ARexx.
 */

static BOOL handleARexx(void)
{
  struct RexxMsg *rxmsg;
  struct CSource cs;
  UBYTE buf[16];
  BOOL killed = FALSE;
  UBYTE *s;
  long r1;

  while (!killed && (rxmsg = (struct RexxMsg *) GetMsg(arexx_mp))) {
    if (CheckRexxMsg((struct Message *) rxmsg)) {
      cs.CS_Buffer = rxmsg->rm_Args[0];
      cs.CS_Length = strlen(cs.CS_Buffer);
      cs.CS_CurChr = 0;
      if (ReadItem(buf, 15L, &cs) == ITEM_ERROR)
	r1 = 20;
      else {
	r1 = 0;
	if (stricmp(buf, "QUIT") == 0) killed = TRUE;
	else if (stricmp(buf, "CUT") == 0) cut();
	else if (stricmp(buf, "COPY") == 0) copy();
	else if (stricmp(buf, "PASTE") == 0) paste();
	else if (stricmp(buf, "ERASE") == 0) freetext();
	else if (stricmp(buf, "PREVIOUS") == 0) prevtext();
	else if (stricmp(buf, "NEXT") == 0) nexttext();
	else if (stricmp(buf, "SHOW") == 0 ||
		 stricmp(buf, "ACTIVATE") == 0) {
	  if (!opengui()) closegui();
	}
	else if (stricmp(buf, "HIDE") == 0 ||
		 stricmp(buf, "DEACTIVATE") == 0) closegui();
	else if (stricmp(buf, "CREATEICONS") == 0)
	  r1 = rxcmd(RXCMD_CREATEICONS, "ON/S,OFF/S", &cs, rxmsg);
	else if (stricmp(buf, "GETCREATEICONS") == 0)
	  r1 = rxcmd(RXCMD_GETCI, "VAR/K/A", &cs, rxmsg);
	else if (stricmp(buf, "APPICON") == 0)
	  r1 = rxcmd(RXCMD_APPICON, "ON/S,OFF/S", &cs, rxmsg);
	else if (stricmp(buf, "GETUNIT") == 0)
	  r1 = rxcmd(RXCMD_GETUNIT, "VAR/K/A", &cs, rxmsg);
	else if (stricmp(buf, "SETUNIT") == 0)
	  r1 = rxcmd(RXCMD_SETUNIT, "/N/A", &cs, rxmsg);
	else if (stricmp(buf, "GETNUMBER") == 0)
	  r1 = rxcmd(RXCMD_GETNUM, "VAR/K/A", &cs, rxmsg);
	else if (stricmp(buf, "GETCURRENT") == 0)
	  r1 = rxcmd(RXCMD_GETCUR, "VAR/K/A", &cs, rxmsg);
	else if (stricmp(buf, "OPEN") == 0)
	  r1 = rxcmd(RXCMD_OPEN, "NAME=FILENAME/K/A,DIR/K", &cs, rxmsg);
	else if (stricmp(buf, "SAVEAS") == 0)
	  r1 = rxcmd(RXCMD_SAVEAS, "NAME/K/A,FTXT/S,DIR/K", &cs, rxmsg);
	else r1 = 20;
      }
      rxmsg->rm_Result1 = r1;
      rxmsg->rm_Result2 = (long) NULL;
      if (rxmsg->rm_Action & RXFF_RESULT) {
	if (s = CreateArgstring("0", 1L)) rxmsg->rm_Result2 = (long) s;
	else rxmsg->rm_Result1 = 20;
      }
    }
    ReplyMsg((struct Message *) rxmsg);
  }
  return killed;
}
