home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d128 / wkeys.lha / wKeys / wKeys.c < prev    next >
C/C++ Source or Header  |  1988-01-02  |  10KB  |  308 lines

  1. /*
  2.  *  wKeys.c    Moves and activates windows and screens via keystrokes.
  3.  *
  4.  *             Copyright (c) 1987 by Davide P. Cervone
  5.  *  You may use this code provided this copyright notice is left intact.
  6.  */
  7.  
  8. #include <exec/types.h>
  9. #include <libraries/dos.h>
  10. #include <exec/io.h>
  11. #include <exec/memory.h>
  12. #include <exec/interrupts.h>
  13. #include <devices/input.h>
  14. #include <devices/inputevent.h>
  15.  
  16. #include "wKeys.h"
  17.  
  18. static char *program  = "wKeys";
  19. static int   version  = 1;
  20. static char *date     = "August 1987";
  21. static char *author   = "Copyright (c) 1987 by Davide P. Cervone";
  22. static int   hversion = 0;
  23.  
  24. static char *PortName = "wKeysPort";
  25. static char *handler  = "L:wKeys-Handler";           /* the handler file */
  26. #define HANDLER            &(handler[2])       /* without the "L:" */
  27.  
  28.  
  29. /*
  30.  *  This is the structure that holds the handler information between calls
  31.  *  to wKeys.  We create a named, public message-port that points to
  32.  *  an instance of this structure so that we can find this information
  33.  *  when we are asked to remove the handler.  The PortName is stored here 
  34.  *  (NamedPort->mp_Node.ln_Name uses this area for it's name).   The other 
  35.  *  data are what we need in order to remove the handler and clean up properly.
  36.  */
  37.  
  38. struct HandlerBlock
  39. {
  40.    char *PortName;                  /* name of the public, named message-port */
  41.    struct Interrupt Handler;        /* the handler added to the handler chain */
  42.    struct IntuitionBase *Ibase;     /* an error if the handler can't be found */
  43.    struct LayersBase *Lbase;        /* library base used by the handler */
  44.    long Segment;                    /* pointer from LoadSeg() */
  45.    struct HotKey *Keys;             /* pointer to Key array */
  46.    int KeyCount;                    /* size of Key array */
  47. };
  48. #define HANDLERINFOSIZE     sizeof(struct HandlerBlock)
  49. #define NAMESIZE            (strlen(PortName)+1)
  50.  
  51. extern struct MsgPort *CreatePort();
  52. extern struct IOStdReq *CreateStdIO();
  53. extern struct MsgPort *FindPort(), *CreatePort();
  54. extern APTR AllocMem();
  55. extern long LoadSeg();
  56.  
  57. #define INTUITION_REV   0L
  58. #define LAYERS_REV      0L
  59.  
  60. struct IntuitionBase  *IntuitionBase = NULL;
  61. struct LayersBase     *LayersBase    = NULL;
  62. extern struct SysBase *SysBase;
  63.  
  64. struct MsgPort *InputPort = NULL;     /* Port used to talk to Input.Device */
  65. struct IOStdReq *InputBlock = NULL;   /* request block used with Input.Device */
  66. LONG InputDevice = 0;                 /* flag whether Input.Device is open */
  67. struct MsgPort *NamedPort = NULL;     /* holds info needed to remove handler */
  68. struct HandlerBlock *HandlerInfo = NULL; /* holds info stored in NamedPort */
  69.  
  70. extern struct HotKeyItem *KeyList;
  71. extern struct HotKey *KeyArray;
  72. extern int KeyCount;
  73. #define KEYARRAYSIZE    (KeyCount*sizeof(struct HotKey))
  74. extern void GetKeyArray();
  75.  
  76.  
  77. /*
  78.  *  DoExit()
  79.  *
  80.  *  General purpose exit routine.  If 's' is not NULL, then print an
  81.  *  error message with up to three parameters.  Free any memory, close
  82.  *  any open device, delete any ports, close any libraries, etc.
  83.  */
  84.  
  85. void DoExit(s,x1,x2,x3)
  86. char *s, *x1, *x2, *x3;
  87. {
  88.    long status = RETURN_OK;
  89.    struct HotKeyItem *TempKey;
  90.    
  91.    if (s != NULL)
  92.    {
  93.       printf(s,x1,x2,x3);
  94.       printf("\n");
  95.       status = RETURN_ERROR;
  96.    }
  97.    if (InputDevice)   CloseDevice(InputBlock);
  98.    if (InputBlock)    DeleteStdIO(InputBlock);
  99.    if (InputPort)     DeletePort(InputPort);
  100.    if (NamedPort)     DeletePort(NamedPort);
  101.    if (HandlerInfo)
  102.    {
  103.       if (HandlerInfo->PortName) FreeMem(HandlerInfo->PortName,NAMESIZE);
  104.       FreeMem(HandlerInfo,HANDLERINFOSIZE);
  105.    }
  106.    if (KeyArray)      FreeMem(KeyArray,KEYARRAYSIZE);
  107.    while (KeyList)
  108.    {
  109.       TempKey = KeyList;
  110.       KeyList = KeyList->Next;
  111.       FreeMem(TempKey,sizeof(*TempKey));
  112.    }
  113.    if (IntuitionBase) CloseLibrary(IntuitionBase);
  114.    if (LayersBase)    CloseLibrary(LayersBase);
  115.    exit(status);
  116. }
  117.  
  118.  
  119. /*
  120.  *  CheckLibOpen()
  121.  *
  122.  *  General library open routine.  It opens a library and sets a pointer
  123.  *  to it.  It checks that the library was openned successfully.
  124.  */
  125.  
  126. static void CheckLibOpen(lib,name,rev)
  127. APTR *lib;
  128. char *name;
  129. int rev;
  130. {
  131.    extern APTR OpenLibrary();
  132.  
  133.    if ((*lib = OpenLibrary(name,(LONG)rev)) == NULL)
  134.       DoExit("Can't open '%s'\n",name);
  135. }
  136.  
  137.  
  138. /*
  139.  *  Macros that make memory allocation easier.
  140.  */
  141. #define NEW(s,var)      (var = (struct s *)New("var",sizeof(struct s)))
  142. #define NEWCHAR(var,s)  (var = (char *)New("var",s))
  143.  
  144.  
  145. /*
  146.  *  New()
  147.  *
  148.  *  Allocate public memory of a given size and set it to all zeros.  If there
  149.  *  is not enough memory, then exit with an error, otherwise return the
  150.  *  pointer to the newly allocated memory.
  151.  */
  152.  
  153. APTR New(name,size)
  154. char *name;
  155. int size;
  156. {
  157.    APTR ptr;
  158.    
  159.    if ((ptr = AllocMem(size,MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  160.       DoExit("Can't Get Memory for '%s'");
  161.    return(ptr);
  162. }
  163.  
  164.  
  165. /*
  166.  *  TellInputDevice()
  167.  *
  168.  *  Create a port and I/O block, and open the input device.  Set up the
  169.  *  I/O block to add or remove the input handler, and send the request
  170.  *  to the input device.  Finally, close the device and delete the
  171.  *  I/O block and port.
  172.  */
  173.  
  174. static void TellInputDevice(function)
  175. int function;
  176. {
  177.    long status;
  178.  
  179.    if ((InputPort = CreatePort(0,0)) == NULL) DoExit("Can't Create Port");
  180.    if ((InputBlock = CreateStdIO(InputPort)) == NULL)
  181.       DoExit("Can't Create Standard IO Block");
  182.    InputDevice = (OpenDevice("input.device",0,InputBlock,0) == 0);
  183.    if (InputDevice == FALSE) DoExit("Can't Open 'input.device'");
  184.    
  185.    InputBlock->io_Command = (long) function;
  186.    InputBlock->io_Data    = (APTR) &(HandlerInfo->Handler);
  187.    if (status = DoIO(InputBlock)) DoExit("Error from DoIO:  %ld",status);
  188.  
  189.    CloseDevice(InputBlock);
  190.    DeleteStdIO(InputBlock);
  191.    DeletePort(InputPort);
  192. }
  193.  
  194.  
  195. /*
  196.  *  CreateHandler()
  197.  *
  198.  *  Open the libraries needed by the input handler and store their locations
  199.  *  in the HandlerInfo structure (so we can close them later).  Try to 
  200.  *  LoadSeg() the handler.  If it is not in the current directory, try the
  201.  *  L: directory.  Exit with an error if the handler can't be found.
  202.  *  Convert the segment pointer into a pointer to the Setup() routine (the
  203.  *  first routine in the handler executable).  Call Setup() and pass it
  204.  *  the pointers to the libraries that it will need to use.  Setup() returns
  205.  *  a pointer to the actual handler routine that should be added into the
  206.  *  input handler chain.  Store this in the HandlerInfo structure so we
  207.  *  can use it to remove the handler later.  Set the handler priority to
  208.  *  51 so that it is ahead of Intuition.
  209.  *
  210.  *  Finally, add the handler in the chain and tell the user that the
  211.  *  handler has been installed.
  212.  */
  213.  
  214. static void CreateHandler()
  215. {
  216.    long (*Setup)();
  217.  
  218.    CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
  219.    CheckLibOpen(&LayersBase,"layers.library",LAYERS_REV);
  220.    
  221.    HandlerInfo->Ibase = IntuitionBase;
  222.    HandlerInfo->Lbase = LayersBase;
  223.    if ((HandlerInfo->Segment = LoadSeg(HANDLER)) == NULL)
  224.       if ((HandlerInfo->Segment = LoadSeg(handler)) == NULL)
  225.          DoExit("Can't Load '%s'",handler);
  226.    Setup = (long (*)()) ((HandlerInfo->Segment << 2) + 4);
  227.    HandlerInfo->Handler.is_Code = 
  228.       (void (*)()) ((*Setup)(IntuitionBase,LayersBase,SysBase,
  229.                              KeyArray,KeyCount,&hversion));
  230.    HandlerInfo->Handler.is_Node.ln_Pri = 51;
  231.    HandlerInfo->Keys = KeyArray;
  232.    HandlerInfo->KeyCount = KeyCount;
  233.  
  234.    TellInputDevice(IND_ADDHANDLER);
  235.    printf("%s v%d.%d (%s) Installed\n",program,version,hversion,date);
  236. }
  237.  
  238.  
  239. /*
  240.  *  Delete Handler()
  241.  *
  242.  *  Retreive the library pointers fro mthe HandlerInfo structure, where
  243.  *  we stored them when we originally installed the handler, then remove
  244.  *  the handler from the input handler chain.  Tell the user that the
  245.  *  handler is gone, and then close the libraries that are no longer needed.
  246.  */
  247.  
  248. static void DeleteHandler()
  249. {
  250.    IntuitionBase = HandlerInfo->Ibase;
  251.    LayersBase    = HandlerInfo->Lbase;
  252.    KeyArray      = HandlerInfo->Keys;
  253.    KeyCount      = HandlerInfo->KeyCount;
  254.  
  255.    TellInputDevice(IND_REMHANDLER);
  256.    UnLoadSeg(HandlerInfo->Segment);
  257.    printf("%s Removed\n",program);
  258.    
  259.    FreeMem(KeyArray,KEYARRAYSIZE);
  260.    CloseLibrary(IntuitionBase);
  261.    CloseLibrary(LayersBase);
  262. }
  263.  
  264.  
  265. /*
  266.  *  main()
  267.  *
  268.  *  Check if a message port with our name already exists.
  269.  *  If not, then the handler is not already installed, so:
  270.  *    Allocate a new HandlerInfo structure and initialize the port name.
  271.  *    Create a public, named message-port (we will look for this the next
  272.  *      time wKeys is called).
  273.  *    Make the message port point to the HandlerInfo structure so we
  274.  *      can use it later when the user asks us to remove the handler.
  275.  *      Note that the port is not actually used for putting and getting
  276.  *      messages, so the Task field is never used, so we can take it for
  277.  *      our own uses.
  278.  *    Finally, add the input handler into the chain.
  279.  *  Otherwise, the port exists, so wKeys already is installed:
  280.  *    Retreive the HandlerInfo poiner from the port, and remove the 
  281.  *      handler from the input handler chain.
  282.  *    Free the memory used by the HandlerInfo, and delete the message port.
  283.  */
  284.  
  285. void main(argc,argv)
  286. int argc;
  287. char **argv;
  288. {
  289.    NamedPort = FindPort(PortName);
  290.    if (NamedPort == NULL)
  291.    {
  292.       NEW(HandlerBlock,HandlerInfo);
  293.       NEWCHAR(HandlerInfo->PortName,NAMESIZE);
  294.       strcpy(HandlerInfo->PortName,PortName);
  295.       if ((NamedPort = CreatePort(HandlerInfo->PortName,0)) == NULL)
  296.          DoExit("Can't Create Message Port '%s'",PortName);
  297.       NamedPort->mp_SigTask = (struct Task *)HandlerInfo;
  298.       GetKeyArray(argc,argv);
  299.       CreateHandler();
  300.    } else {
  301.       HandlerInfo = (struct HandlerBlock *)(NamedPort->mp_SigTask);
  302.       DeleteHandler();
  303.       FreeMem(HandlerInfo->PortName,NAMESIZE);
  304.       FreeMem(HandlerInfo,HANDLERINFOSIZE);
  305.       DeletePort(NamedPort);
  306.    }
  307. }
  308.