home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 367.lha / netkeys_v2.0 / netkeys.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-02  |  14.8 KB  |  519 lines

  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  2. /* |_o_o|\\ Copyright (c) 1990 The Software Distillery.  All Rights Reserved.*/
  3. /* |. o.| || This program may not be distributed without the permission of   */
  4. /* | .  | || the authors.                                                    */
  5. /* | o  | ||                                                                 */
  6. /* |  . |// Written by Doug Walker                                           */
  7. /* ======          BBS:(919)-471-6436      VOICE:(919)-467-4764              */ 
  8. /*                 BIX: djwalker           USENET: ...!mcnc!rti!sas!walker   */
  9. /*                 405 B3 Gooseneck Dr, Cary, NC 27513, USA                  */
  10. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  11. /*
  12.  * Based on POPCLI III, written by John Toebes
  13.  * Uses Matt Dillon's DNET
  14.  */
  15.  
  16. #include "netkeys.h"
  17. #include <intuition/intuitionbase.h>
  18. #include <proto/intuition.h>
  19.  
  20. #ifdef DEBUG
  21. #undef DEBUG
  22. #endif
  23.  
  24. #define DEBUG 0
  25.  
  26. #if DEBUG
  27. #define BUG(x) if(_Backstdout) MSG(_Backstdout, x);
  28. #else
  29. #define BUG(x) ;
  30. #endif
  31.  
  32. /* Declarations for CBACK */
  33. extern BPTR _Backstdout;         /* standard output when run in background */
  34. long _BackGroundIO = 1;          /* Flag to tell it we want to do I/O      */
  35. long _stack = 4000;              /* Amount of stack space our task needs   */
  36. char *_procname = "NetKeys II";  /* The name of the task to create         */
  37. long _priority = 20;             /* The priority to run us at              */
  38.  
  39. int InitDevice(GLOBAL_DATA *, int);
  40. int TermDevice(GLOBAL_DATA *);
  41.  
  42. struct InputEvent * __regargs myhandler(struct InputEvent *ev, GLOBAL_DATA *gptr)
  43. {
  44.    struct InputEvent *ep, *laste;
  45.    struct NETKEYMSG *nkm;
  46.    int msgtype;
  47.  
  48.    if(gptr->state < EM_DOIT) return(ev);  /* In the process of quitting */
  49.  
  50.    /* run down the list of events to see if they pressed the magic button */
  51.    for (ep = ev, laste = NULL; ep != NULL; ep = ep->ie_NextEvent)
  52.    {
  53.       msgtype = NKM_NONE;
  54.       if(gptr->state == EM_RELURK)
  55.       {
  56.          gptr->state = EM_LURK;
  57.          msgtype = NKM_ACK;
  58.       }
  59.       else if(ep->ie_Class == IECLASS_RAWKEY || ep->ie_Class == IECLASS_RAWMOUSE)
  60.       {
  61.          if(
  62.              (
  63.                ep->ie_Class == IECLASS_RAWKEY                  &&
  64.                ep->ie_Code  == gptr->dokey                     &&
  65.                (ep->ie_Qualifier & IEQUALIFIER_LCOMMAND)
  66.              ) 
  67.              ||
  68.              (
  69.                gptr->state == EM_LURK                                         &&
  70.                ep->ie_Class == IECLASS_RAWMOUSE                               &&
  71.                (ep->ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE)                 &&
  72.                (ep->ie_Code == IECODE_NOBUTTON)                               &&
  73.                ((gptr->ibase->MouseX == 0 && ep->ie_X < 0 && 
  74.                     (gptr->exit & IECODE_NKLEFT)) ||
  75.                 (gptr->ibase->MouseX == gptr->swidth && ep->ie_X > 0 &&
  76.                     (gptr->exit & IECODE_NKRIGHT))
  77.                )
  78.              )
  79.            )
  80.          {
  81.             /* Remove the event from the chain */
  82.             if (laste == NULL)
  83.                ev = ep->ie_NextEvent;
  84.             else
  85.                laste->ie_NextEvent = ep->ie_NextEvent;
  86.  
  87.             /* Telling us to toggle... */
  88.             if(gptr->state == EM_DOIT)
  89.             {
  90.                gptr->state = EM_LURK;
  91.                msgtype = NKM_WEBEDONE;
  92.             }
  93.             else
  94.             {
  95.                gptr->state = EM_DOIT;
  96.                msgtype = NKM_HEREWEGO;
  97.             }
  98.          }
  99.          else if(gptr->state != EM_LURK)
  100.          {
  101.             /* Remove the event from the chain */
  102.             if (laste == NULL)
  103.                ev = ep->ie_NextEvent;
  104.             else
  105.                laste->ie_NextEvent = ep->ie_NextEvent;
  106.  
  107.             msgtype = NKM_IEVENT;
  108.          }
  109.       }
  110.       else
  111.          laste = ep;
  112.  
  113.       if(msgtype != NKM_NONE)
  114.       {
  115.          if(!(nkm=(struct NETKEYMSG *)GetMsg(gptr->rtnp)))
  116.          {
  117.             if(gptr->nmsgs <= MAXMSGS)
  118.                nkm=AllocMem(NKMSZ, MEMF_CLEAR|MEMF_PUBLIC);
  119.          }
  120.          if(nkm)
  121.          {
  122.             nkm->msgtype = msgtype;
  123.             if(msgtype == NKM_IEVENT || msgtype == NKM_HEREWEGO) nkm->ie = *ep;
  124.             PutMsg((struct MsgPort *)gptr->nkmp, (struct Message *)nkm);
  125.          }
  126.       }
  127.    }
  128.  
  129.    /* pass on the pointer to the event */
  130.    return(ev);
  131. }
  132.  
  133. #if DEBUG > 1
  134. BPTR _Backstdout = NULL;
  135. char *cmd;
  136. #define DCLMAIN int main(int argc, char *argv[])
  137. #else
  138. #define DCLMAIN int _main(char *cmd)
  139. #endif
  140.  
  141. DCLMAIN
  142. {
  143.    struct MsgPort  *inputDevPort = NULL;
  144.    struct MsgPort  *oldport;
  145.    struct IOStdReq *inputRequestBlock = NULL;
  146.    struct Interrupt handlerStuff;
  147.    GLOBAL_DATA global;
  148.    struct NETKEYMSG *msg, *oldmsg, *tmpmsg;
  149.    int quit = 0;
  150.    UWORD smooth = 2;
  151.    struct Screen wbdat;
  152.    struct IntuitionBase *IntuitionBase;
  153.    struct GfxBase *GfxBase = NULL;
  154.    UWORD *NoSprData = NULL;
  155.    ULONG IBaseLock;
  156.  
  157. #if DEBUG > 1
  158.    /* Not really linked with cback */
  159.    cmd = argv[1];
  160.    _Backstdout = Output();
  161. #endif
  162.  
  163.    MSG(_Backstdout, BANNER);
  164.  
  165.    memset(&global, 0, sizeof(global));
  166.    global.buddy = FindTask(0L);
  167.    global.dokey  = DEFDOKEY;
  168.    global.state = EM_LURK;
  169.  
  170.    if(!(global.rtnp = CreatePort(0,0)))
  171.    {
  172.       MSG(_Backstdout, "Can't CreatePort\n");
  173.       goto abort;
  174.    }
  175.  
  176.    oldport = FindPort(NKMPNAME);
  177.  
  178.    if(cmd)
  179.    {
  180.       long tmpl = DEFDOKEY;
  181.       while(*cmd)
  182.       {
  183.          while(*cmd != ' ' && *cmd != '\0') cmd++;
  184.          while(*cmd == ' ') cmd++;
  185.  
  186.          switch(cmd[0])
  187.          {
  188.             case '\0': 
  189.             case '\n':
  190.                break;
  191.  
  192.             case '0':
  193.                if(cmd[1] == 'x')
  194.                {
  195.                   stch_l(cmd+2, &tmpl);
  196.                   global.dokey = tmpl;
  197.                }
  198.                break;
  199.  
  200.             case 'F': case 'f':
  201.                smooth = 0;
  202.                break;
  203.  
  204.             case 'L': case 'l':
  205.                global.exit = IECODE_NKLEFT;
  206.                break;
  207.  
  208.             case 'Q': case 'q':
  209.                quit = 1;
  210.                break;
  211.  
  212.             case 'R': case 'r':
  213.                global.exit = IECODE_NKRIGHT;
  214.                break;
  215.  
  216.             case 'S': case 's':
  217.                smooth = 1;
  218.                break;
  219.  
  220.             case 'W': case 'w':
  221.                global.exit = IECODE_NKLEFT|IECODE_NKRIGHT;
  222.                break;
  223.  
  224.             default:
  225.                MSG(_Backstdout, 
  226.                 "USAGE: NetKeys [0xkey] [F|S] [L|R|W] [Q]\n");
  227.                MSG(_Backstdout, "   [0xkey]  - RAW key code for hotkey\n");
  228.                MSG(_Backstdout, "   [F|S]    - FAST or SMOOTH mode\n");
  229.                MSG(_Backstdout, 
  230.                   "   [L|R|W]  - Mouse cursor exits LEFT, RIGHT or WRAPs\n");
  231.                MSG(_Backstdout, "   [Quit]   - Terminate NetKeys\n");
  232.                goto abort;
  233.          }
  234.       }
  235.    }
  236.  
  237.    if(!(oldmsg = AllocMem(NKMSZ, MEMF_CLEAR|MEMF_PUBLIC)))
  238.    {
  239.       MSG(_Backstdout, "No memory\n");
  240.       goto abort;
  241.    }
  242.    if(quit)
  243.    {
  244.       if(!oldport)
  245.       {
  246.          MSG(_Backstdout, "Netkeys not installed\n");
  247.          goto abort;
  248.       }
  249.       else
  250.       {
  251.          oldmsg->msgtype = NKM_QUIT;
  252.          oldmsg->m.mn_Node.ln_Type = NT_MESSAGE;
  253.          oldmsg->m.mn_ReplyPort = global.rtnp;
  254.  
  255.          PutMsg(oldport, (struct Message *)oldmsg);
  256.          while(!GetMsg(global.rtnp))
  257.             WaitPort(global.rtnp);
  258.          GetMsg(global.rtnp);
  259.  
  260.          MSG(_Backstdout, "NetKeys removed\n");
  261.          goto abort;      
  262.       }
  263.    }
  264.  
  265.    if(oldport)
  266.    {
  267.       /* Modify the parms for the existing guy */
  268.       oldmsg->msgtype = NKM_CONTROL;
  269.       oldmsg->m.mn_Node.ln_Type = NT_MESSAGE;
  270.       oldmsg->m.mn_ReplyPort = global.rtnp;
  271.       oldmsg->ie.ie_Class = global.dokey;
  272.       oldmsg->ie.ie_SubClass = global.exit;
  273.       oldmsg->ie.ie_Code = smooth;
  274.       PutMsg(oldport, (struct Message *)oldmsg);
  275.  
  276.       while(!GetMsg(global.rtnp))
  277.          WaitPort(global.rtnp);
  278.       GetMsg(global.rtnp);
  279.  
  280.       MSG(_Backstdout, "Parameters modified on existing NetKeys command\n");
  281.       goto abort;
  282.    }
  283.    FreeMem(oldmsg, NKMSZ);
  284.    oldmsg = NULL;
  285.  
  286.    MSG(_Backstdout, INSTR);
  287.  
  288.    if(global.exit == 0) global.exit = IECODE_NKLEFT|IECODE_NKRIGHT;
  289.  
  290.    if(smooth == 2) smooth = 0;
  291.  
  292.    if (
  293.        ((global.nkmp = CreatePort(NKMPNAME, 0)) == NULL) ||
  294.        ((inputDevPort = CreatePort(0,0)) == NULL)        ||
  295.         InitDevice(&global, NKM_HANDLER)                 ||
  296.         ((inputRequestBlock = 
  297.                CreateIOReq(inputDevPort, sizeof(struct IOStdReq))) == NULL) ||
  298.  
  299.        !(global.ibase = (struct IntuitionBase *)
  300.                        OpenLibrary("intuition.library", 0))                 ||
  301.  
  302.        !(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0))    ||
  303.  
  304.        !(NoSprData = AllocMem(12, MEMF_PUBLIC|MEMF_CHIP|MEMF_CLEAR))        ||
  305.  
  306.       OpenDevice("input.device",0,(struct IORequest *)inputRequestBlock,0))
  307.       {
  308.          MSG(_Backstdout, "Can't initialize - check DNET connection\n");
  309.          goto abort;
  310.       }
  311.  
  312.    MSG(_Backstdout, "NetKeys installed\n");
  313.  
  314. #if DEBUG < 1
  315.    if(_Backstdout) Close(_Backstdout);
  316.    _Backstdout = 0;
  317. #endif
  318.  
  319.    IntuitionBase = global.ibase;
  320.    NoSprData[0] = 0xFE00;
  321.    NoSprData[1] = 0xFF00;
  322.  
  323.    /* If we have an appropriate version of intuition, ask for info */
  324.    /* about the workbench screen                                   */
  325.    if(IntuitionBase->LibNode.lib_Version < 33
  326.       || !(GetScreenData((char *)&wbdat, sizeof(struct Screen), 
  327.                               WBENCHSCREEN, NULL)))
  328.    {
  329.       /* Either we're running on an old version of the system, or the */
  330.       /* GetScreenData call failed for some reason.  In either case,  */
  331.       /* simply assume a 640x200 screen and be done with it.          */
  332.       global.swidth  = 639;
  333.    }
  334.    else
  335.    {
  336.       /* Use the wb width, and STDSCREENHEIGHT. */
  337.       global.swidth  = wbdat.Width-1;
  338.    }
  339.  
  340.    handlerStuff.is_Data = (APTR)&global;
  341.    handlerStuff.is_Code = (VOID (*)()) myhandler;
  342.    handlerStuff.is_Node.ln_Pri = 52;
  343.  
  344.    inputRequestBlock->io_Command = IND_ADDHANDLER;
  345.    inputRequestBlock->io_Data    = (APTR)&handlerStuff;
  346.  
  347.    DoIO((struct IORequest *)inputRequestBlock);
  348.  
  349.    while(global.state >= EM_DOIT && 
  350.         !(SIGBREAKF_CTRL_C & Wait((1<<global.nkmp->mp_SigBit) | SIGBREAKF_CTRL_C)))
  351.    {
  352.       while(msg=(struct NETKEYMSG *)GetMsg(global.nkmp))
  353.       {
  354.          if(msg->msgtype == NKM_QUIT)          /* Msg from another invocation */
  355.          {
  356.             ReplyMsg((struct Message *)msg);
  357.             goto abort;
  358.          }
  359.          else if(msg->msgtype == NKM_CONTROL)  /* Msg from another invocation */
  360.          {
  361.             global.dokey = msg->ie.ie_Class;
  362.             if(msg->ie.ie_SubClass)
  363.                global.exit = msg->ie.ie_SubClass;
  364.             if(msg->ie.ie_Code != 2)
  365.                smooth = msg->ie.ie_Code;
  366.             ReplyMsg((struct Message *)msg);
  367.             continue;
  368.          }
  369.          else if(msg->msgtype == NKM_HEREWEGO) /* From handler - start sending */
  370.          {
  371.             if(msg->ie.ie_Class == IECLASS_RAWMOUSE)
  372.                msg->ie.ie_Code = global.exit;
  373.             else
  374.                msg->ie.ie_Code = global.exit|IECODE_NKHOTKEY;
  375.  
  376.             msg->ie.ie_Class = IECLASS_NKCONTROL;
  377.  
  378.             msg->ie.ie_Y = IntuitionBase->MouseY;
  379.             msg->ie.ie_X = IntuitionBase->MouseX;
  380.  
  381.             mshow(GfxBase, NoSprData, 0);  /* Blank mouse */
  382.          }
  383.          else if(msg->msgtype == NKM_WEBEDONE) /* From handler - quit sending*/
  384.          {
  385.             mshow(GfxBase, NoSprData, 1);  /* Unblank mouse */
  386.             msg->ie.ie_Class = IECLASS_NKCONTROL;
  387.             msg->ie.ie_Code  = IECODE_NKHOTQUIT|global.exit;
  388.             msg->ie.ie_Y = IntuitionBase->MouseY;
  389.             msg->ie.ie_X = IntuitionBase->MouseX;
  390.          }
  391.  
  392.          tmpmsg = NULL;
  393.          if( !smooth &&
  394.              msg->ie.ie_Class == IECLASS_RAWMOUSE &&
  395.              msg->ie.ie_Code == IECODE_NOBUTTON)
  396.          {
  397.             while((tmpmsg = (struct NETKEYMSG *)GetMsg(global.nkmp)) &&
  398.                    tmpmsg->msgtype == NKM_IEVENT &&
  399.                    tmpmsg->ie.ie_Class == IECLASS_RAWMOUSE &&
  400.                    tmpmsg->ie.ie_Code == IECODE_NOBUTTON &&
  401.                    (tmpmsg->ie.ie_Qualifier & IEQUALIFIER_RELATIVEMOUSE))
  402.             {
  403.                tmpmsg->ie.ie_X += msg->ie.ie_X;
  404.                tmpmsg->ie.ie_Y += msg->ie.ie_Y;
  405.                PutMsg(global.rtnp, (struct Message *)msg);
  406.                msg = tmpmsg;
  407.                tmpmsg = NULL;
  408.             }
  409.          }
  410. putit:
  411.          if(DWrite(global.chan, (char *)&msg->ie, IESZ) != IESZ)
  412.             break;
  413.  
  414.          PutMsg(global.rtnp, (struct Message *)msg);
  415.  
  416.          if(DNRead(global.chan, (char *)&msg->ie, IESZ) == IESZ)
  417.          {
  418.             while(DNRead(global.chan, (char *)&msg->ie, IESZ) == IESZ);
  419.  
  420.             IBaseLock = LockIBase(0);
  421.             IntuitionBase->MouseY = msg->ie.ie_Y;
  422.             IntuitionBase->MouseX = (msg->ie.ie_X == 0 ? global.swidth-1 : 1);
  423.             UnlockIBase(IBaseLock);
  424.  
  425.             /* Set global state to RELURK and wait for handler to acknowledge */
  426.             global.state = EM_RELURK;
  427.             do
  428.             {
  429.                if(!(msg=(struct NETKEYMSG *)GetMsg(global.nkmp))) 
  430.                   WaitPort(global.nkmp);
  431.             }
  432.             while(!msg || msg->msgtype != NKM_ACK);
  433.             mshow(GfxBase, NoSprData, 1);
  434.          }
  435.          else if(tmpmsg)
  436.          {
  437.             msg = tmpmsg;
  438.             tmpmsg = NULL;
  439.             goto putit;
  440.          }
  441.       }
  442.    }
  443.  
  444. abort:
  445.    if(global.ibase) CloseLibrary((struct Library *)global.ibase);
  446.  
  447.    if(GfxBase)
  448.    {
  449.       if(NoSprData)
  450.       {
  451.          mshow(GfxBase, NoSprData, 1);
  452.          FreeMem(NoSprData, 12);
  453.       }
  454.       CloseLibrary((struct Library *)GfxBase);
  455.    }
  456.  
  457.    TermDevice(&global);
  458.  
  459.    if (inputRequestBlock != NULL)
  460.    {
  461.       if (inputRequestBlock->io_Device != NULL)
  462.       {
  463.          inputRequestBlock->io_Command = IND_REMHANDLER;
  464.          inputRequestBlock->io_Data = (APTR)&handlerStuff;
  465.          DoIO((struct IORequest *)inputRequestBlock);
  466.  
  467.          CloseDevice((struct IORequest *)inputRequestBlock);
  468.       }
  469.       DeleteIOReq(inputRequestBlock);
  470.    }
  471.  
  472.    if (inputDevPort != NULL)  DeletePort(inputDevPort);
  473.  
  474.    if(global.nkmp)
  475.    {
  476.       while(msg=(struct NETKEYMSG *)GetMsg(global.nkmp)) FreeMem(msg, NKMSZ);
  477.       DeletePort(global.nkmp);
  478.    }
  479.  
  480.    if(global.rtnp)
  481.    {
  482.       while(msg=(struct NETKEYMSG *)GetMsg(global.rtnp)) FreeMem(msg, NKMSZ);
  483.       DeletePort(global.rtnp);
  484.    }
  485.  
  486.    if(_Backstdout) Close(_Backstdout);
  487.  
  488.    return(0);
  489. }
  490.  
  491. int InitDevice(GLOBAL_DATA *global, int which)
  492. {
  493.  
  494.    if(global->active) return(1);
  495.    global->active = 1;
  496.  
  497.    if(!(global->chan=(struct DChannel *)
  498.       DOpen(NULL, (uword)(PORT_NETKEYS), 127, 127)))
  499.          return(1);
  500.  
  501.    return(0);
  502. }
  503.  
  504. int TermDevice(GLOBAL_DATA *global)
  505. {
  506.    if(!global->active) return(1);
  507.  
  508.    global->active = 0;
  509.  
  510.    if(global->chan) DClose(global->chan);
  511.  
  512.    global->chan = NULL;
  513.  
  514.    return(0);
  515. }
  516.  
  517. void MemCleanup(void);
  518. void MemCleanup(){}
  519.