/* * CALC Provides a calculator that opens on the active screen when * you press a specific key sequence. Otherwise, the program * waits quitely in the background. * * Copyright 1989 by Davide P. Cervone. * You may use this code, provided this copywrite notice is kept intact. */ #define INTUITION_PREFERENCES_H /* don't need 'em */ #include #include #include #include #include #include #include "cHandler.h" #include "cSetup.h" extern struct Process *FindTask(); #define GETSTARTUP(p) ((struct StartupMessage *)GetMsg(p)) #define ONE 1L #define SIGBREAKF_ANY\ (SIGBREAKF_CTRL_C| SIGBREAKF_CTRL_D| SIGBREAKF_CTRL_E| SIGBREAKF_CTRL_F) extern void myHandlerStub(); #ifndef SWINDOWS extern void aCloseScreen(); extern void cCloseScreen(); long OldCloseScreen; #endif LONG CalcSMask; /* Signal for calc to open on active screen */ static LONG CalcSSignal; /* Signal number for CalcSMask */ #ifndef SWINDOWS LONG CalcCMask; /* Signal for screen close */ static LONG CalcCSignal; /* Signal number for CalcCMask */ #endif struct Task *CalcTask; /* Pointer to Calc task */ static struct Task *ParentTask; /* Pointer to parent task */ extern UWORD KeyCode; /* KeyCode to activate Calc */ extern UWORD Qualifiers; /* and required qualifiers */ static struct Interrupt Calc_Interrupt = /* the Interrupt needed to add a */ { /* handler to the input chain */ {NULL, NULL, 0, 51, NULL}, /* ln_Pri = 51 (before Intuition) */ NULL, &myHandlerStub /* the handler to add */ }; static struct HandlerData cHandlerData = { { /* the MsgPort is pre-setup */ {NULL,NULL, NT_MSGPORT, 0, PORTNAME}, /* to include the name and */ PA_IGNORE, 0, NULL, /* type so that it can just */ {NULL,NULL,NULL, 0,0} /* be added to the port list */ }, /* so it can be found later */ MAJVERS,MINVERS, MINLOADVER, /* the handler versio numbers */ NULL, /* the handler code segment */ &IntuitionBase, /* pointer to IntuitionBase and */ &GfxBase, /* GfxBase (set up by loader) */ &Calc_Interrupt, /* the interrupt used by Input.Device */ &ParentTask, /* so we know who to signal later */ &KeyCode, /* the KeyCode to acticate calc */ &Qualifiers, /* and required qualifiers */ #ifndef SWINDOWS &aCloseScreen, /* ASM CloseScreen stub */ &OldCloseScreen, /* result of SetFunction */ #else NULL,NULL #endif }; /* * cExit() * * End CalcTask from running. Forbid() so that we are not unloaded until * after we're done exiting. Signal the parent that we are done running, * and exit. */ void cExit() { Forbid(); if (ParentTask) Signal(ParentTask,ENDSIGNAL); Exit(0); } /* * GetSignal() * * Allocate a signal (error if none available) and set the mask to * the proper value. */ #define DEFAULTSIGNAL 20 void GetSignal(theSignal,theMask) LONG *theSignal, *theMask; { LONG signal; if ((signal = AllocSignal(-ONE)) == -ONE) signal = DEFAULTSIGNAL; *theSignal = signal; *theMask = (ONE << signal); } /* * WaitForStartup() * * Find our task pointer and wait for a startup message passed buy the loader. * (This structure is non-standard and is defined in cSetup.h). Check that * we have not been signaled to end (in case the user executed the handler * as a command, for example). Otherwise, once we have received the * startup message, get the parent task pointer from the message, and * check the loader version number. If OK, then set the HandlerData so * the loader can do its thing. Finally, reply to the message to inform * the loader that everything is ready for it. */ static void WaitForStartup() { struct Process *cTask = FindTask(NULL); struct MsgPort *cPort = &cTask->pr_MsgPort; struct StartupMessage *sMessage = NULL; ULONG Mask = (ONE << cPort->mp_SigBit); ULONG signals; CalcTask = (struct Task *)cTask; while (sMessage == NULL) { signals = Wait(Mask|ENDSIGNAL); if (signals & ENDSIGNAL) cExit(); sMessage = GETSTARTUP(cPort); } ParentTask = sMessage->sm_ParentTask; if (sMessage->sm_LoadVers < MINLOADVER) sMessage->sm_HandlerData = NULL; else sMessage->sm_HandlerData = &cHandlerData; ReplyMsg(sMessage); } /* * InitCalc() * * Clear any pending signals, and wait for the startup message from the * loader. Then wait for the loader to signal us that it is finished * setting things up for us. If it signaled an END, then exit, otherwise * allocate the signals that we will need */ void InitCalc() { ULONG signals; SetSignal(0L,SIGBREAKF_ANY); WaitForStartup(); signals = Wait(STARTSIGNAL | ENDSIGNAL); if (signals & ENDSIGNAL) cExit(); GetSignal(&CalcSSignal,&CalcSMask); #ifndef SWINDOWS GetSignal(&CalcCSignal,&CalcCMask); #endif } /* * ConfirmExit() * * Called when the loader tries to unload the handler. First we signal * the loader that everything is ready for it to try to deinstall us. * Then we wait for it to signal that everything has be removed properly. * If it signals us with ENDSIGNAL we can safely end (it has been able to * remove everything). Otherwise, we must continue to run. */ int ConfirmExit() { ULONG signals; int NotDone = TRUE; if (ParentTask) { Signal(ParentTask,ENDSIGNAL); signals = Wait(ENDSIGNAL | STARTSIGNAL); if (signals & ENDSIGNAL) NotDone = FALSE; } return(NotDone); }