home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
fish
/
keyboard
/
keymacro_436
/
keymacro-handler.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-15
|
19KB
|
952 lines
/****************************************************************************
*
* KeyMacro-Handler.c ---- KeyMacro handler.
*
* Author ---------------- Olaf Barthel, MXM
* Brabeckstrasse 35
* D-3000 Hannover 71
*
* KeyMacro © Copyright 1990 by MXM; Executable program,
* documentation and source code are shareware. If you like
* this program a small donation will entitle you to receive
* updates and new programs from MXM.
*
****************************************************************************/
/* Function prototypes. */
struct Process * CreateFuncProc(char *Name,LONG Priority,APTR InitCode,ULONG StackSize);
VOID FreeString(BPTR Byte);
BPTR CreateBSTR(char *s);
BPTR CopyPath(VOID);
VOID FakeCLI(VOID);
VOID ClearPath(BPTR InitPath);
VOID StopFakery(VOID);
VOID * DeleteMacroMsg(struct MacroMessage *scm_Msg);
VOID Executor(VOID);
struct MacroKey * FindMacroKey(LONG Code,LONG Qualifier);
struct InputEvent * EventHandler(struct InputEvent *Event);
BYTE OpenAll(VOID);
VOID CloseAll(VOID);
BYTE UStrCmp(UBYTE *a,UBYTE *b);
VOID * AllocRem(LONG ByteSize,LONG Requirements);
VOID * FreeRem(LONG *MemoryBlock);
VOID * SendMacroMsg(struct MacroMessage *scm_Msg,struct MsgPort *scm_Port);
ULONG KeyInvert(UBYTE AnsiKey,struct InputEvent *Event,struct KeyMap *KeyMap);
LONG _main(VOID);
/* The magic stuff. */
#pragma regcall(EventHandler(a0))
/* Shared library identifiers. */
extern struct ExecBase *SysBase;
struct IntuitionBase *IntuitionBase;
struct Library *LayersBase;
/* Global handshake data. */
struct MSeg *MSeg;
/* Process<->Process communication data. */
struct Process *ExecuteProc;
struct MsgPort *ExecutePort;
/* Input device data. */
struct MsgPort *InputDevPort;
struct IOStdReq *InputRequestBlock;
struct Interrupt *InputHandler;
struct InputEvent *FakeInputEvent;
/* Console device data. */
struct IOStdReq *ConsoleRequest;
struct MsgPort *ConsolePort;
/* Timer device data. */
struct timerequest *TimeRequest;
struct MsgPort *TimePort;
BYTE SigBit = -1;
/* Our current version tag. */
const char *VersionTag = "\0$VER: KeyMacro-Handler 1.8 (1 Dec 1990)\n\r";
/* _main():
*
* This is the entry point to the handler process.
*/
LONG
_main()
{
struct Process *ThatsMe;
ULONG SignalSet;
struct MacroMessage *MacroMsg;
LONG i;
/* Do I know myself? */
ThatsMe = (struct Process *)SysBase -> ThisTask;
/* Don't let anybody call us from CLI. */
if(ThatsMe -> pr_CLI)
goto Quit;
/* Can we find the global MsgPort? */
if(!(MSeg = (struct MSeg *)FindPort(PORTNAME)))
{
Forbid();
Signal(MSeg -> Father,MSeg -> RingBack);
goto Quit;
}
/* This older revision probably doesn't support
* some newer structure tags -> exit.
*/
if(MSeg -> Revision < REVISION)
{
Forbid();
Signal(MSeg -> Father,MSeg -> RingBack);
goto Quit;
}
/* The MsgPort is already owned by someone
* else.
*/
if(MSeg -> Port . mp_Flags & PA_SIGNAL)
{
Forbid();
Signal(MSeg -> Father,MSeg -> RingBack);
goto Quit;
}
/* Open the libraries. */
if(!OpenAll())
{
CloseAll();
Forbid();
Signal(MSeg -> Father,MSeg -> RingBack);
goto Quit;
}
/* Start the executing process. */
MSeg -> Child = (struct Task *)ThatsMe;
if(!(ExecuteProc = (struct Process *)CreateFuncProc("KeyMacro CLI",10,Executor,4000)))
{
CloseAll();
Forbid();
MSeg -> Child = NULL;
Signal(MSeg -> Father,MSeg -> RingBack);
goto Quit;
}
/* Wait for handshake signal. */
Wait(SIG_SHAKE);
/* Process creation failed. */
if(!ExecuteProc)
{
CloseAll();
Forbid();
MSeg -> Child = NULL;
Signal(MSeg -> Father,MSeg -> RingBack);
goto Quit;
}
/* Now we are truly running. */
Signal(MSeg -> Father,MSeg -> RingBack);
MSeg -> Father = NULL;
/* Re-init the MsgPort flags. */
MSeg -> Port . mp_Flags = PA_SIGNAL;
MSeg -> Port . mp_SigBit = SigBit;
MSeg -> Port . mp_SigTask = MSeg -> Child;
/* Wait until somebody kicks us out. */
FOREVER
{
SignalSet = Wait(SIG_CLOSE | SIG_PORT);
/* We are to shut down. */
if(SignalSet & SIG_CLOSE)
{
if(ExecuteProc)
{
Signal((struct Task *)ExecuteProc,SIG_CLOSE);
Wait(SIG_SHAKE);
}
CloseAll();
Forbid();
Signal(MSeg -> Father,SIG_CLOSE);
goto Quit;
}
/* A message arrived at our home port. */
if(SignalSet & SIG_PORT)
{
/* Walk through the list of messages. */
while(MacroMsg = (struct MacroMessage *)GetMsg(&MSeg -> Port))
{
/* Execute a keyboard macro. */
if(MacroMsg -> mm_Type == MM_INPUT)
{
struct MacroKey *TempMacroKey = MacroMsg -> mm_MacroKey;
if(TempMacroKey)
{
/* Let the execute process run the command. */
if(TempMacroKey -> mk_Type == MK_COMMAND)
{
struct MacroMessage CommandMsg;
CommandMsg . mm_Type = MM_EXECUTE;
CommandMsg . mm_FileName = TempMacroKey -> mk_String;
CommandMsg . mm_WindowName = TempMacroKey -> mk_Window;
SendMacroMsg(&CommandMsg,ExecutePort);
}
/* Build a keyboard macro. */
if(TempMacroKey -> mk_Type == MK_WORD)
{
ConsoleRequest -> io_Command = CD_ASKDEFAULTKEYMAP;
ConsoleRequest -> io_Length = sizeof(struct KeyMap);
ConsoleRequest -> io_Data = (APTR)MSeg -> DefaultKeyMap;
ConsoleRequest -> io_Flags = IOF_QUICK;
DoIO(ConsoleRequest);
InputRequestBlock -> io_Command = IND_WRITEEVENT;
InputRequestBlock -> io_Data = (APTR)FakeInputEvent;
InputRequestBlock -> io_Length = sizeof(struct InputEvent);
for(i = 0 ; i < strlen(TempMacroKey -> mk_String) ; i++)
{
if(KeyInvert(TempMacroKey -> mk_String[i],FakeInputEvent,MSeg -> DefaultKeyMap))
{
FakeInputEvent -> ie_NextEvent = NULL;
FakeInputEvent -> ie_Class = IECLASS_RAWKEY;
FakeInputEvent -> ie_SubClass = KM_SUBCLASS;
FakeInputEvent -> ie_Qualifier |= IEQUALIFIER_RELATIVEMOUSE;
TimeRequest -> tr_node . io_Command = TR_GETSYSTIME;
DoIO(TimeRequest);
FakeInputEvent -> ie_TimeStamp = TimeRequest -> tr_time;
DoIO(InputRequestBlock);
if(MSeg -> Delay)
{
TimeRequest -> tr_node . io_Command = TR_ADDREQUEST;
TimeRequest -> tr_time . tv_secs = 0;
TimeRequest -> tr_time . tv_micro = MSeg -> Delay;
DoIO(TimeRequest);
}
}
}
}
}
}
/* This is a request to update the
* macro keys.
*/
if(MacroMsg -> mm_Type == MM_UPDATE)
{
if(MSeg -> MacroList)
{
for(i = 0 ; i < MSeg -> NumMacros ; i++)
{
if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
continue;
if(MSeg -> MacroList[i] . mk_String)
FreeRem(MSeg -> MacroList[i] . mk_String);
if(MSeg -> MacroList[i] . mk_Window)
FreeRem(MSeg -> MacroList[i] . mk_Window);
}
FreeRem(MSeg -> MacroList);
}
MSeg -> NumMacros = MacroMsg -> mm_NumMacros;
MSeg -> MacroList = MacroMsg -> mm_MacroList;
}
/* Remove the message. */
DeleteMacroMsg(MacroMsg);
}
}
}
Quit: ;
}
/* UStrCmp():
*
* strcmp function which ignores case and allows to
* abbreviate the name of the source string to match
* against the destination string.
*/
BYTE
UStrCmp(UBYTE *a,UBYTE *b)
{
SHORT i;
for(i = 0 ; i < strlen(a) ; i++)
if(ToUpper(a[i]) != ToUpper(b[i]))
return(1);
return(0);
}
/* CreateFuncProc():
*
* Create an independent process from a 'C' routine.
*/
struct Process *
CreateFuncProc(char *Name,LONG Priority,APTR InitCode,ULONG StackSize)
{
struct Process *ChildProc = NULL;
struct FakeSeg
{
BPTR NextSeg;
WORD FirstCode;
APTR RealCode;
} *FakeSeg;
if(FakeSeg = (struct FakeSeg *)AllocMem(sizeof(struct FakeSeg),MEMF_PUBLIC | MEMF_CLEAR))
{
struct MsgPort *ChildPort;
FakeSeg -> FirstCode = 0x4EF9;
FakeSeg -> RealCode = InitCode;
if(ChildPort = (struct MsgPort *)CreateProc(Name,Priority,MKBADDR(FakeSeg),StackSize))
ChildProc = (struct Process *)ChildPort -> mp_SigTask;
Delay(TICKS_PER_SECOND);
FreeMem(FakeSeg,sizeof(struct FakeSeg));
}
return(ChildProc);
}
/* FreeString(Byte):
*
* Frees the memory occupied by the contents of a BSTR.
*/
VOID
FreeString(BPTR Byte)
{
LONG *Ptr = (LONG *)BADDR(Byte);
FreeMem(Ptr - 1,Ptr[-1]);
}
/* CreateBSTR(s):
*
* Allocates enough memory to hold the contents of
* a given string and makes it a BSTR.
*/
BPTR
CreateBSTR(char *s)
{
LONG BlockLength;
SHORT Length;
char *Byte;
Length = strlen(s);
BlockLength = (Length + 8) & ~3;
if(!(Byte = (char *)AllocMem(BlockLength,MEMF_PUBLIC | MEMF_CLEAR)))
return(NULL);
*(LONG *)Byte = BlockLength;
Byte[4] = Length;
strncpy(Byte + 5,s,Length);
return(MKBADDR(Byte + 4));
}
/* CopyPath():
*
* Builds a fake pathlist inherited from any valid
* CLI process or Workbench.
*/
BPTR
CopyPath()
{
BPTR *Next1,*Next2,*Last,NewPath = NULL;
struct Process *Father;
struct CommandLineInterface *CLI;
Last = &NewPath;
/* If using ARP this will also give us a valid
* pathlist.
*/
if(!(Father = (struct Process *)FindTask("Workbench")))
if(!(Father = (struct Process *)FindTask("ARP Shell Process")))
if(!(Father = (struct Process *)FindTask("New CLI")))
if(!(Father = (struct Process *)FindTask("Initial CLI")))
return(NULL);
if(CLI = (struct CommandLineInterface *)BADDR(Father -> pr_CLI))
{
for(Next1 = (BPTR *)BADDR(CLI -> cli_CommandDir) ; Next1 ; Next1 = (BPTR *)BADDR(*Next1))
{
if(!(Next2 = (BPTR *)AllocMem(2 * sizeof(BPTR),MEMF_PUBLIC | MEMF_CLEAR)))
break;
*Last = MKBADDR(Next2);
Last = Next2;
Next2[1] = (BPTR)DupLock(Next1[1]);
Next2[0] = NULL;
}
}
return(NewPath);
}
/* FakeCLI():
*
* Creates a fake CLI structure for our process. This
* includes pathlist, currentdir, prompt and stack.
*/
VOID
FakeCLI()
{
struct Process *MyProcess = (struct Process *)SysBase -> ThisTask;
struct CommandLineInterface *CLI;
if(CLI = (struct CommandLineInterface *)AllocMem(sizeof(struct CommandLineInterface),MEMF_PUBLIC | MEMF_CLEAR))
{
MyProcess -> pr_CLI = MKBADDR(CLI);
CLI -> cli_SetName = CreateBSTR("SYS:");
CLI -> cli_Prompt = CreateBSTR("%N> ");
CLI -> cli_DefaultStack = 4000;
CurrentDir(Lock("SYS:",ACCESS_READ));
CLI -> cli_CommandDir = CopyPath();
}
}
/* ClearPath(InitPath):
*
* Frees the contents of our fake pathlist.
*/
VOID
ClearPath(BPTR InitPath)
{
BPTR *Next,*Path;
for(Path = (BPTR *)BADDR(InitPath) ; Path ; Path = Next)
{
Next = (BPTR *)BADDR(Path[0]);
if(Path[1])
UnLock(Path[1]);
FreeMem(Path,2 * sizeof(BPTR));
}
}
/* StopFakery():
*
* Removes the contents of our fake CLI structure.
*/
VOID
StopFakery()
{
struct CommandLineInterface *CLI;
struct Process *MyProcess;
BPTR MyCD;
MyProcess = (struct Process *)SysBase -> ThisTask;
if(CLI = (struct CommandLineInterface *)BADDR(MyProcess -> pr_CLI))
{
if(MyCD = (BPTR)CurrentDir(NULL))
UnLock(MyCD);
FreeString(CLI -> cli_SetName);
FreeString(CLI -> cli_Prompt);
ClearPath(CLI -> cli_CommandDir);
MyProcess -> pr_CLI = NULL;
FreeMem(CLI,sizeof(struct CommandLineInterface));
}
}
/* DeleteMacroMsg(scm_Msg):
*
* Remove a message from memory.
*/
VOID *
DeleteMacroMsg(struct MacroMessage *scm_Msg)
{
if(scm_Msg && scm_Msg -> mm_Message . mn_Node . ln_Name == (char *)scm_Msg)
FreeRem(scm_Msg);
return(NULL);
}
/* Executor():
*
* This is the dummy process to execute programs.
*/
VOID
Executor()
{
ULONG SignalSet;
BPTR NIL;
struct MacroMessage *ExecuteMsg;
struct Window *TheWindow;
char TempLine[300];
struct Process *ThatsMe;
BYTE Activate;
geta4();
ThatsMe = (struct Process *)SysBase -> ThisTask;
/* These are inherited from the father process,
* we had better cleared them out.
*/
ThatsMe -> pr_WindowPtr = (APTR)-1;
/* Try to allocate a port (we can't use our builtin
* DOS port since we are actually calling DOS
* routines which may mix up the messages coming
* in).
*/
if(!(ExecutePort = (struct MsgPort *)CreatePort(NULL,0)))
{
Forbid();
ExecuteProc = NULL;
Signal(MSeg -> Child,SIG_SHAKE);
goto Quit;
}
/* Open the NULL-Handler. */
if(!(NIL = Open("NULL:",MODE_NEWFILE)))
{
Forbid();
ExecuteProc = NULL;
Signal(MSeg -> Child,SIG_SHAKE);
DeletePort(ExecutePort);
goto Quit;
}
/* Pretend to be a CLI. */
FakeCLI();
/* This path leads nowhere. */
ThatsMe -> pr_CIS = NIL;
ThatsMe -> pr_COS = NIL;
ThatsMe -> pr_ConsoleTask = (APTR)DeviceProc("NULL:");
/* We're on the scene now. */
Signal(MSeg -> Child,SIG_SHAKE);
FOREVER
{
SignalSet = Wait(SIG_CLOSE | (1 << ExecutePort -> mp_SigBit));
/* Shut down? */
if(SignalSet & SIG_CLOSE)
{
StopFakery();
Close(NIL);
DeletePort(ExecutePort);
ExecuteProc = NULL;
Forbid();
Signal(MSeg -> Child,SIG_SHAKE);
goto Quit;
}
/* Execute a command? */
while(ExecuteMsg = (struct MacroMessage *)GetMsg(ExecutePort))
{
TheWindow = NULL;
Activate = TRUE;
/* Try to find a matching window title. */
if(ExecuteMsg -> mm_WindowName)
{
ULONG IntuiLock;
struct Screen *ExScreen;
struct Window *ExWindow;
IntuiLock = LockIBase(NULL);
if(UStrCmp(ExecuteMsg -> mm_WindowName,IntuitionBase -> ActiveWindow -> Title))
{
ExScreen = IntuitionBase -> FirstScreen;
do
{
ExWindow = ExScreen -> FirstWindow;
do
{
if(!UStrCmp(ExecuteMsg -> mm_WindowName,ExWindow -> Title))
{
TheWindow = ExWindow;
break;
}
}
while((ExWindow = ExWindow -> NextWindow) && !TheWindow);
}
while((ExScreen = ExScreen -> NextScreen) && !TheWindow);
}
else
{
TheWindow = IntuitionBase -> ActiveWindow;
Activate = FALSE;
}
UnlockIBase(IntuiLock);
}
if(!TheWindow)
{
/* No chance, execute the command. */
strcpy(TempLine,"C:Run <NULL: >NULL: ");
strcat(TempLine,ExecuteMsg -> mm_FileName);
Execute(TempLine,NULL,NIL);
}
DeleteMacroMsg(ExecuteMsg);
/* Found a window? Bring it to the front. */
if(TheWindow)
{
LockLayers(TheWindow -> RPort -> Layer -> LayerInfo);
WindowToFront(TheWindow);
UnlockLayers(TheWindow -> RPort -> Layer -> LayerInfo);
ScreenToFront(TheWindow -> WScreen);
if(Activate)
ActivateWindow(TheWindow);
}
}
}
/* Finished, fall through. */
Quit: ;
}
/* FindMacroKey(Code,Qualifier):
*
* Find a macro key entry in the linked list of
* macro key structures.
*/
struct MacroKey *
FindMacroKey(LONG Code,LONG Qualifier)
{
SHORT i;
if(MSeg -> MacroList)
{
for(i = 0 ; i < MSeg -> NumMacros ; i++)
{
if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
continue;
if(MSeg -> MacroList[i] . mk_CommandKey == Code && (Qualifier & MSeg -> MacroList[i] . mk_CommandQualifier) == MSeg -> MacroList[i] . mk_CommandQualifier)
return(&MSeg -> MacroList[i]);
}
}
return(NULL);
}
/* EventHandler(Event):
*
* The input event handler.
*/
struct InputEvent *
EventHandler(struct InputEvent *Event)
{
struct MacroKey *HandlerKey;
struct InputEvent *ChainEvent;
/* This is an interrupt, let's start with the register
* saving.
*/
int_start();
for(ChainEvent = Event ; ChainEvent ; ChainEvent = ChainEvent -> ie_NextEvent)
{
if(ChainEvent -> ie_Class == IECLASS_RAWKEY && !(ChainEvent -> ie_Code & IECODE_UP_PREFIX) && ChainEvent -> ie_SubClass != KM_SUBCLASS)
{
if(HandlerKey = (struct MacroKey *)FindMacroKey(ChainEvent -> ie_Code,ChainEvent -> ie_Qualifier))
{
struct MacroMessage HandlerMsg;
HandlerMsg . mm_Type = MM_INPUT;
HandlerMsg . mm_MacroKey = HandlerKey;
SendMacroMsg(&HandlerMsg,&MSeg -> Port);
ChainEvent -> ie_Class = IECLASS_NULL;
}
}
}
/* Restore the registers. */
int_end();
return(Event);
}
/* OpenAll():
*
* Initialize the input event handler.
*/
BYTE
OpenAll()
{
if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",33)))
return(FALSE);
if(!(LayersBase = (struct Library *)OpenLibrary("layers.library",33)))
return(FALSE);
if(!(InputDevPort = (struct MsgPort *)CreatePort(NULL,0)))
return(FALSE);
if(!(InputRequestBlock = (struct IOStdReq *)CreateStdIO(InputDevPort)))
return(FALSE);
if(OpenDevice("input.device",0,(struct IORequest *)InputRequestBlock,0))
return(FALSE);
if(!(InputHandler = (struct Interrupt *)AllocMem(sizeof(struct Interrupt),MEMF_PUBLIC | MEMF_CLEAR)))
return(FALSE);
if(!(ConsolePort = (struct MsgPort *)CreatePort(NULL,0)))
return(FALSE);
if(!(ConsoleRequest = (struct IOStdReq *)CreateStdIO(ConsolePort)))
return(FALSE);
if(OpenDevice("console.device",CONU_LIBRARY,ConsoleRequest,0))
return(FALSE);
if(!(TimePort = (struct MsgPort *)CreatePort(NULL,0)))
return(FALSE);
if(!(TimeRequest = (struct timerequest *)CreateExtIO(TimePort,sizeof(struct timerequest))))
return(FALSE);
if(OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,0))
return(FALSE);
if(!(FakeInputEvent = (struct InputEvent *)AllocMem(sizeof(struct InputEvent),MEMF_PUBLIC | MEMF_CLEAR)))
return(FALSE);
if((SigBit = AllocSignal(-1)) == -1)
return(FALSE);
InputHandler -> is_Code = (APTR)EventHandler;
InputHandler -> is_Node . ln_Pri = 51;
InputHandler -> is_Node . ln_Name = "KeyMacro-Handler";
InputRequestBlock -> io_Command = IND_ADDHANDLER;
InputRequestBlock -> io_Data = (APTR)InputHandler;
if(DoIO(InputRequestBlock))
return(FALSE);
ConsoleRequest -> io_Command = CD_ASKDEFAULTKEYMAP;
ConsoleRequest -> io_Length = sizeof(struct KeyMap);
ConsoleRequest -> io_Data = (APTR)MSeg -> DefaultKeyMap;
ConsoleRequest -> io_Flags = IOF_QUICK;
if(DoIO(ConsoleRequest))
return(FALSE);
return(TRUE);
}
/* CloseAll():
*
* Remove the input event handler.
*/
VOID
CloseAll()
{
if(InputRequestBlock)
{
if(InputRequestBlock -> io_Device)
{
if(InputHandler)
{
InputRequestBlock -> io_Command = IND_REMHANDLER;
InputRequestBlock -> io_Data = (APTR)InputHandler;
DoIO(InputRequestBlock);
}
CloseDevice(InputRequestBlock);
}
DeleteStdIO(InputRequestBlock);
}
if(TimeRequest)
{
if(TimeRequest -> tr_node . io_Device)
CloseDevice(TimeRequest);
DeleteExtIO(TimeRequest);
}
if(TimePort)
DeletePort(TimePort);
if(ConsoleRequest)
{
if(ConsoleRequest -> io_Device)
CloseDevice(ConsoleRequest);
DeleteStdIO(ConsoleRequest);
}
if(FakeInputEvent)
FreeMem(FakeInputEvent,sizeof(struct InputEvent));
if(InputHandler)
FreeMem(InputHandler,sizeof(struct Interrupt));
if(InputDevPort)
DeletePort(InputDevPort);
if(ConsolePort)
DeletePort(ConsolePort);
if(SigBit != -1)
FreeSignal(SigBit);
if(LayersBase)
CloseLibrary(LayersBase);
if(IntuitionBase)
CloseLibrary(IntuitionBase);
}