home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d500 / wiconify.lha / wIconify / wKeys.lzh / Source / wKeys.c < prev    next >
C/C++ Source or Header  |  1991-04-21  |  12KB  |  368 lines

  1. /*
  2.  *  wKeys.c    Moves and activates windows and screens via keystrokes.
  3.  *
  4.  *             Copyright (c) 1987,1988 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  = 2;
  20. static char *date     = "April 1991";
  21. static char *author   = "Copyright (c) 1987,1988,1991 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.    struct MsgPort *ReplyPort;       /* the reply port for CLOSE-WINDOW */
  47.    int KeyCount;                    /* size of Key array */
  48. };
  49. #define HANDLERINFOSIZE     sizeof(struct HandlerBlock)
  50. #define NAMESIZE            (strlen(PortName)+1)
  51.  
  52. /*extern struct MsgPort *CreatePort();*/
  53. extern struct IOStdReq *CreateStdIO();
  54. extern struct MsgPort *FindPort(), *CreatePort();
  55. extern APTR AllocMem();
  56. extern long LoadSeg();
  57.  
  58. #define INTUITION_REV   0L
  59. #define LAYERS_REV      0L
  60.  
  61. struct IntuitionBase  *IntuitionBase = NULL;
  62. struct LayersBase     *LayersBase    = NULL;
  63. extern struct SysBase *SysBase;
  64.  
  65. struct MsgPort *InputPort = NULL;     /* Port used to talk to Input.Device */
  66. struct IOStdReq *InputBlock = NULL;   /* request block used with Input.Device */
  67. LONG InputDevice = 0;                 /* flag whether Input.Device is open */
  68. struct MsgPort *NamedPort = NULL;     /* holds info needed to remove handler */
  69. struct MsgPort *ReplyPort = NULL;     /* reply port for CLOSE-WINDOW */
  70. struct HandlerBlock *HandlerInfo = NULL; /* holds info stored in NamedPort */
  71.  
  72. extern struct HotKeyItem *KeyList;
  73. extern struct HotKey *KeyArray;
  74. extern int KeyCount;
  75. #define KEYARRAYSIZE    (KeyCount*sizeof(struct HotKey))
  76. extern void GetKeyArray();
  77.  
  78.  
  79. /*
  80.  *  DeleteNonSigPort()
  81.  *
  82.  *  Deletes a message port with signal type PA_IGNORE.  Based on
  83.  *  DeletePort() from the exec support functions documented in the RKM
  84.  */
  85.  
  86. void DeleteNonSigPort(thePort)
  87. struct MsgPort *thePort;
  88. {
  89.    if (thePort->mp_Node.ln_Name) RemPort(thePort);
  90.    thePort->mp_Node.ln_Type = 0xFF;
  91.    thePort->mp_MsgList.lh_Head = (struct Node *) -1;
  92.    FreeMem(thePort,(ULONG)sizeof(struct MsgPort));
  93. }
  94.  
  95.  
  96. /*
  97.  *  CreateNonSigPort()
  98.  *
  99.  *  Creates a message port with signal type PA_IGNORE.  Based on
  100.  *  CreatePort() from the exec support functions documented in the RKM.
  101.  */
  102.  
  103. struct MsgPort *CreateNonSigPort(name,pri)
  104. char *name;
  105. BYTE pri;
  106. {
  107.    struct MsgPort *thePort;
  108.    
  109.    thePort = (struct MsgPort *)AllocMem((ULONG)sizeof(struct MsgPort),
  110.                                          MEMF_PUBLIC | MEMF_CLEAR);
  111.    if (thePort)
  112.    {
  113.       thePort->mp_Node.ln_Name = name;
  114.       thePort->mp_Node.ln_Pri  = pri;
  115.       thePort->mp_Node.ln_Type = NT_MSGPORT;
  116.       
  117.       thePort->mp_Flags = PA_IGNORE;
  118.       thePort->mp_SigBit = 0;
  119.       thePort->mp_SigTask = NULL;
  120.       
  121.       if (name)
  122.          AddPort(thePort);
  123.         else
  124.          NewList(&(thePort->mp_MsgList));
  125.    }
  126.    return(thePort);
  127. }
  128.  
  129.  
  130. /*
  131.  *  DoExit()
  132.  *
  133.  *  General purpose exit routine.  If 's' is not NULL, then print an
  134.  *  error message with up to three parameters.  Free any memory, close
  135.  *  any open device, delete any ports, close any libraries, etc.
  136.  */
  137.  
  138. void DoExit(s,x1,x2,x3)
  139. char *s, *x1, *x2, *x3;
  140. {
  141.    long status = RETURN_OK;
  142.    struct HotKeyItem *TempKey;
  143.    
  144.    if (s != NULL)
  145.    {
  146.       printf(s,x1,x2,x3);
  147.       printf("\n");
  148.       status = RETURN_ERROR;
  149.    }
  150.    if (InputDevice)   CloseDevice(InputBlock);
  151.    if (InputBlock)    DeleteStdIO(InputBlock);
  152.    if (InputPort)     DeletePort(InputPort);
  153.    if (NamedPort)     DeleteNonSigPort(NamedPort);
  154.    if (ReplyPort)     DeleteNonSigPort(ReplyPort);
  155.    if (HandlerInfo)
  156.    {
  157.       if (HandlerInfo->PortName) FreeMem(HandlerInfo->PortName,NAMESIZE);
  158.       FreeMem(HandlerInfo,HANDLERINFOSIZE);
  159.    }
  160.    if (KeyArray)      FreeMem(KeyArray,KEYARRAYSIZE);
  161.    while (KeyList)
  162.    {
  163.       TempKey = KeyList;
  164.       KeyList = KeyList->Next;
  165.       FreeMem(TempKey,sizeof(*TempKey));
  166.    }
  167.    if (IntuitionBase) CloseLibrary(IntuitionBase);
  168.    if (LayersBase)    CloseLibrary(LayersBase);
  169.    exit(status);
  170. }
  171.  
  172.  
  173. /*
  174.  *  CheckLibOpen()
  175.  *
  176.  *  General library open routine.  It opens a library and sets a pointer
  177.  *  to it.  It checks that the library was openned successfully.
  178.  */
  179.  
  180. static void CheckLibOpen(lib,name,rev)
  181. APTR *lib;
  182. char *name;
  183. int rev;
  184. {
  185.    extern APTR OpenLibrary();
  186.  
  187.    if ((*lib = OpenLibrary(name,(LONG)rev)) == NULL)
  188.       DoExit("Can't open '%s'\n",name);
  189. }
  190.  
  191.  
  192. /*
  193.  *  Macros that make memory allocation easier.
  194.  */
  195. #define NEW(s,var)      (var = (struct s *)New("var",sizeof(struct s)))
  196. #define NEWCHAR(var,s)  (var = (char *)New("var",s))
  197.  
  198.  
  199. /*
  200.  *  New()
  201.  *
  202.  *  Allocate public memory of a given size and set it to all zeros.  If there
  203.  *  is not enough memory, then exit with an error, otherwise return the
  204.  *  pointer to the newly allocated memory.
  205.  */
  206.  
  207. APTR New(name,size)
  208. char *name;
  209. int size;
  210. {
  211.    APTR ptr;
  212.    
  213.    if ((ptr = AllocMem(size,MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  214.       DoExit("Can't Get Memory for '%s'",name);
  215.    return(ptr);
  216. }
  217.  
  218.  
  219. /*
  220.  *  TellInputDevice()
  221.  *
  222.  *  Create a port and I/O block, and open the input device.  Set up the
  223.  *  I/O block to add or remove the input handler, and send the request
  224.  *  to the input device.  Finally, close the device and delete the
  225.  *  I/O block and port.
  226.  */
  227.  
  228. static void TellInputDevice(function)
  229. int function;
  230. {
  231.    long status;
  232.  
  233.    if ((InputPort = CreatePort(0,0)) == NULL) DoExit("Can't Create Port");
  234.    if ((InputBlock = CreateStdIO(InputPort)) == NULL)
  235.       DoExit("Can't Create Standard IO Block");
  236.    InputDevice = (OpenDevice("input.device",0,InputBlock,0) == 0);
  237.    if (InputDevice == FALSE) DoExit("Can't Open 'input.device'");
  238.    
  239.    InputBlock->io_Command = (long) function;
  240.    InputBlock->io_Data    = (APTR) &(HandlerInfo->Handler);
  241.    if (status = DoIO(InputBlock)) DoExit("Error from DoIO:  %ld",status);
  242.  
  243.    CloseDevice(InputBlock);
  244.    DeleteStdIO(InputBlock);
  245.    DeletePort(InputPort);
  246. }
  247.  
  248.  
  249. /*
  250.  *  CreateHandler()
  251.  *
  252.  *  Open the libraries needed by the input handler and store their locations
  253.  *  in the HandlerInfo structure (so we can close them later).  Try to 
  254.  *  LoadSeg() the handler.  If it is not in the current directory, try the
  255.  *  L: directory.  Exit with an error if the handler can't be found.
  256.  *  Convert the segment pointer into a pointer to the Setup() routine (the
  257.  *  first routine in the handler executable).  Call Setup() and pass it
  258.  *  the pointers to the libraries that it will need to use.  Setup() returns
  259.  *  a pointer to the actual handler routine that should be added into the
  260.  *  input handler chain.  Store this in the HandlerInfo structure so we
  261.  *  can use it to remove the handler later.  Set the handler priority to
  262.  *  51 so that it is ahead of Intuition.
  263.  *
  264.  *  Finally, add the handler in the chain and tell the user that the
  265.  *  handler has been installed.
  266.  */
  267.  
  268. static void CreateHandler()
  269. {
  270.    long (*Setup)();
  271.  
  272.    CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
  273.    CheckLibOpen(&LayersBase,"layers.library",LAYERS_REV);
  274.    
  275.    HandlerInfo->Ibase = IntuitionBase;
  276.    HandlerInfo->Lbase = LayersBase;
  277.    if ((HandlerInfo->Segment = LoadSeg(HANDLER)) == NULL)
  278.       if ((HandlerInfo->Segment = LoadSeg(handler)) == NULL)
  279.          DoExit("Can't Load '%s'",handler);
  280.    Setup = (long (*)()) ((HandlerInfo->Segment << 2) + 4);
  281.    HandlerInfo->Handler.is_Code = 
  282.       (void (*)()) ((*Setup)(IntuitionBase,LayersBase,SysBase,
  283.                              KeyArray,KeyCount,ReplyPort,&hversion));
  284.    HandlerInfo->Handler.is_Node.ln_Pri = 51;
  285.    HandlerInfo->Keys = KeyArray;
  286.    HandlerInfo->KeyCount = KeyCount;
  287.    HandlerInfo->ReplyPort = ReplyPort;
  288.  
  289.    TellInputDevice(IND_ADDHANDLER);
  290.    printf("%s v%d.%d (%s) Installed\n",program,version,hversion,date);
  291. }
  292.  
  293.  
  294. /*
  295.  *  Delete Handler()
  296.  *
  297.  *  Retreive the library pointers from the HandlerInfo structure, where
  298.  *  we stored them when we originally installed the handler, then remove
  299.  *  the handler from the input handler chain.  Tell the user that the
  300.  *  handler is gone, and then close the libraries that are no longer needed.
  301.  */
  302.  
  303. static void DeleteHandler()
  304. {
  305.    IntuitionBase = HandlerInfo->Ibase;
  306.    LayersBase    = HandlerInfo->Lbase;
  307.    KeyArray      = HandlerInfo->Keys;
  308.    KeyCount      = HandlerInfo->KeyCount;
  309.    ReplyPort     = HandlerInfo->ReplyPort;
  310.  
  311.    TellInputDevice(IND_REMHANDLER);
  312.    UnLoadSeg(HandlerInfo->Segment);
  313.    printf("%s Removed\n",program);
  314.    
  315.    FreeMem(KeyArray,KEYARRAYSIZE);
  316.    CloseLibrary(IntuitionBase);
  317.    CloseLibrary(LayersBase);
  318. }
  319.  
  320.  
  321. /*
  322.  *  main()
  323.  *
  324.  *  Check if a message port with our name already exists.
  325.  *  If not, then the handler is not already installed, so:
  326.  *    Allocate a new HandlerInfo structure and initialize the port name.
  327.  *    Create a public, named message-port (we will look for this the next
  328.  *      time wKeys is called).
  329.  *    Make the message port point to the HandlerInfo structure so we
  330.  *      can use it later when the user asks us to remove the handler.
  331.  *      Note that the port is not actually used for putting and getting
  332.  *      messages, so the Task field is never used, so we can take it for
  333.  *      our own uses.
  334.  *    Get a port to use as a reply port for CLOSE-WINDOW intuimessages.
  335.  *    Finally, add the input handler into the chain.
  336.  *  Otherwise, the port exists, so wKeys already is installed:
  337.  *    Retreive the HandlerInfo poiner from the port, and remove the 
  338.  *      handler from the input handler chain.
  339.  *    Free the memory used by the HandlerInfo, and delete the message ports.
  340.  */
  341.  
  342. void main(argc,argv)
  343. int argc;
  344. char **argv;
  345. {
  346.    NamedPort = FindPort(PortName);
  347.    if (NamedPort == NULL)
  348.    {
  349.       NEW(HandlerBlock,HandlerInfo);
  350.       NEWCHAR(HandlerInfo->PortName,NAMESIZE);
  351.       strcpy(HandlerInfo->PortName,PortName);
  352.       if ((NamedPort = CreateNonSigPort(HandlerInfo->PortName,0)) == NULL)
  353.          DoExit("Can't Create Message Port '%s'",PortName);
  354.       if ((ReplyPort = CreateNonSigPort(NULL,0)) == NULL)
  355.          DoExit("Can't Create Reply Port");
  356.       NamedPort->mp_SigTask = (struct Task *)HandlerInfo;
  357.       GetKeyArray(argc,argv);
  358.       CreateHandler();
  359.    } else {
  360.       HandlerInfo = (struct HandlerBlock *)(NamedPort->mp_SigTask);
  361.       DeleteHandler();
  362.       FreeMem(HandlerInfo->PortName,NAMESIZE);
  363.       FreeMem(HandlerInfo,HANDLERINFOSIZE);
  364.       DeleteNonSigPort(ReplyPort);
  365.       DeleteNonSigPort(NamedPort);
  366.    }
  367. }
  368.