/*
 * MMB_Shift
 * ---------
 *
 * Copyright © 1994 by Andreas M. Kirchwitz, Seesener Str. 69, D-10709 Berlin
 *                                   E-Mail: amk@zikzak.in-berlin.de, Germany
 */

#include <exec/libraries.h>
#include <libraries/commodities.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/commodities_protos.h>
#include <devices/inputevent.h>

static const char version[] = "$VER: MMB_Shift 2.0 " __AMIGADATE__;

#ifdef __SASC
__regargs int _CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
__regargs void __chkabort(void) { return; }  /* really */
#endif

void main(int, char **);
void ProcessMsg(void);
void CxFunction(CxMsg *, CxObj *);

struct Library *CxBase, *IconBase;
struct MsgPort *broker_mp;
CxObj *broker, *cocustom;

struct NewBroker newbroker =
{
    NB_VERSION,
    "MMB_Shift",		/* string to identify this broker */
    "MMB_Shift 2.0 © 1994 A. M. Kirchwitz",
    "map MMB+LMB to LSHIFT+MMB+LMB",
    NBU_UNIQUE | NBU_NOTIFY,	/* don't want any new commodities starting with this name. */
    0, 0, 0, 0			/* if someone tries it, let me know                        */
};

ULONG cxsigflag;

IX middleix = {
   IX_VERSION,				/* required                      */
   IECLASS_RAWMOUSE,
   IECODE_LBUTTON,			/* Code                          */
   0x00FF & (~IECODE_UP_PREFIX),	/* CodeMask                      */
   IEQUALIFIER_MIDBUTTON,		/* qualifier I am interested in  */
   IEQUALIFIER_MIDBUTTON,		/* QualMask                      */
   0					/* synonyms irrelevant           */
};

void main(int argc, char **argv)
{
    UBYTE **ttypes;
    CxMsg *msg;
    CxObj *mfilter;

    if (CxBase = OpenLibrary("commodities.library", 37L))
    {
        /* open the icon.library for support library functions, ArgArrayInit() and ArgArrayDone() */
        if (IconBase = OpenLibrary("icon.library", 36L))
        {
            if (broker_mp = CreateMsgPort())
            {
                newbroker.nb_Port = broker_mp;
                cxsigflag = 1L << broker_mp->mp_SigBit;

                /* ArgArrayInit() is a support library function (in the 2.0 version of amiga.lib) */
                /* that makes it easy to read arguments from either a CLI or from Workbench's     */
                /* ToolTypes. Because it uses icon.library, the library has to be open before     */
                /* before calling this function.  ArgArrayDone() cleans up after this function.   */
                ttypes = ArgArrayInit((long)argc, argv);

                /* ArgInt() (in amiga.lib) searches through the array set up by ArgArrayInit()    */
                /* for a specific ToolType.  If it finds one, it returns the numeric value of the */
                /* number that followed the ToolType (i.e., CX_PRIORITY=7).  If it  doesn't find  */
                /* the ToolType, it returns the default value (the third argument)                */
                newbroker.nb_Pri = (BYTE)ArgInt(ttypes, "CX_PRIORITY", 0);

                if (broker = CxBroker(&newbroker, NULL))
                {
                    if (mfilter = CxFilter(NULL))
                    {
                        SetFilterIX(mfilter, &middleix);

                        if (!CxObjError(mfilter))
                        {
                            AttachCxObj(broker, mfilter);

                            /* CxCustom() takes two arguments, a pointer to the custom function           */
                            /* and an ID. Commodities Exchange will assign that ID to any CxMsg           */
                            /* passed to the custom  function.                                            */

                            if (cocustom = CxCustom(CxFunction, 0L))
                            {
                                AttachCxObj(mfilter, cocustom);
                                ActivateCxObj(broker, 1L);
                                ProcessMsg();
                            }
                        }
                        else
                        {
                            DeleteCxObj(mfilter);
                        }
                    }

                    /* DeleteCxObjAll() is a commodities.library function that not only deletes   */
                    /* the CxObject pointed to in its argument, but it deletes all of the         */
                    /* CxObjects that are attached to it.                                         */
                    DeleteCxObjAll(broker);

                    /* Empty the port of all CxMsgs */
                    while(msg = (CxMsg *)GetMsg(broker_mp))
                        ReplyMsg((struct Message *)msg);
                }
                DeletePort(broker_mp);
            }
            ArgArrayDone();   /* this amiga.lib function cleans up after ArgArrayInit()           */
            CloseLibrary(IconBase);
        }
        CloseLibrary(CxBase);
    }
}

void ProcessMsg(void)
{
    extern struct MsgPort *broker_mp;
    extern CxObj *broker;
    extern ULONG cxsigflag;
    CxMsg *msg;
    ULONG sigrcvd, msgid;
    LONG returnvalue = 1L;

    while (returnvalue)
    {
        sigrcvd = Wait(SIGBREAKF_CTRL_C | cxsigflag);

        while(msg = (CxMsg *)GetMsg(broker_mp))
        {
            msgid = CxMsgID(msg);
            ReplyMsg((struct Message *)msg);

            switch(msgid)
            {
                case CXCMD_DISABLE:
                    ActivateCxObj(broker, 0L);
                    break;
                case CXCMD_ENABLE:
                    ActivateCxObj(broker, 1L);
                    break;
                case CXCMD_KILL:
                    returnvalue = 0L;
                    break;
                case CXCMD_UNIQUE:
                    returnvalue = 0L;
                    break;
            }
        }

        if (sigrcvd & SIGBREAKF_CTRL_C) returnvalue = 0L;
    }
}


/*
 *  The custom function for the custom CxObject.  Any code for a
 *  custom CxObj must be short and sweet because it runs as part
 *  of the input.device task.
 */
void CxFunction(register CxMsg *cxm, CxObj *co)
{
    struct InputEvent *ie;

    ie = (struct InputEvent *)CxMsgData(cxm);
    ie->ie_Qualifier |= IEQUALIFIER_LSHIFT;

#if 0
    ie->ie_Qualifier &= ~(IEQUALIFIER_MIDBUTTON);
    ie->ie_Code &= ~(IECODE_MBUTTON);
#endif

    /* DisplayBeep(NULL); */
}

