/* * 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 copyright notice is kept intact. */ #define INTUITION_PREFERENCES_H /* don't need 'em */ #include #include #include #include #include "cHandler.h" #include "cSetup.h" #include "cKeys.h" #define SCREENTITLE\ "Screen Calculator v3.1 Copyright (c) 1989 by Davide P. Cervone" #define SIGNALCLOSE TRUE #define NOSIGNAL FALSE #define INTUITION_REV 0 #define GRAPHICS_REV 0 #define ERROR_EXIT 10 #define GADGFLAGS WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH #define IDCMPFLAGS\ CLOSEWINDOW | GADGETUP | GADGETDOWN | VANILLAKEY |\ NOCAREREFRESH | ACTIVEWINDOW struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; static struct NewWindow NewWindow = { -1,-1, WINDW,WINDH, -1,-1, IDCMPFLAGS, SIMPLE_REFRESH | ACTIVATE | GADGFLAGS, NULL, NULL, #ifdef SWINDOWS "::", #else NULL, #endif NULL, NULL, 20,20, -1,-1, WBENCHSCREEN }; struct Screen *CalcScreen; /* the screen containing the calculator */ struct Window *CalcWindow; /* the calculator window */ struct RastPort *rp; /* the windows' rast port */ static LONG CalcWMask; /* the calculator handler task */ /* * CloseCalcWindow() * * If the window is open, save the calculator position for later, and * close the window. Clear the pointers to the screen and window, and * forget which signal we used to use for the window. * * If we were supposed to let someone know when the window was closed, * then signal the proper task. */ void CloseCalcWindow(signal) int signal; { if (CalcWindow != NULL) { NewWindow.LeftEdge = CalcWindow->LeftEdge; NewWindow.TopEdge = CalcWindow->TopEdge; CloseWindow(CalcWindow); CalcWindow = NULL; CalcScreen = NULL; CalcWMask = 0; } #ifndef SWINDOWS if (signal) SignalClosed(); #endif } /* * OpenCalcWindow() * * If we have a screen to open on, then set the window type and screen * pointer. Check that the calculator is positioned within the given * screen size. Open the calulator. If we were successful, then get the * rastport pointer, and set the mask for the message port. */ static void OpenCalcWindow(theScreen) struct Screen *theScreen; { extern struct Window *OpenWindow(); if (theScreen) { CalcScreen = theScreen; #ifndef NL_DAEMON if (theScreen->BitMap.Depth == 1) { NewWindow.DetailPen = 0; NewWindow.BlockPen = 1; } else { NewWindow.DetailPen = DARKPEN; NewWindow.BlockPen = BACKPEN; } #endif #ifndef SWINDOWS NewWindow.Screen = CalcScreen; NewWindow.Type = CUSTOMSCREEN; #endif if (NewWindow.LeftEdge < 0 || NewWindow.TopEdge < 0 || NewWindow.LeftEdge + NewWindow.Width > CalcScreen->Width || NewWindow.TopEdge + NewWindow.Height > CalcScreen->Height) { NewWindow.LeftEdge = (CalcScreen->Width - NewWindow.Width)/2; NewWindow.TopEdge = (CalcScreen->Height - NewWindow.Height)/2; if (NewWindow.LeftEdge < 0) NewWindow.LeftEdge = 0; if (NewWindow.TopEdge < 0) NewWindow.TopEdge = 0; } if ((CalcWindow = OpenWindow(&NewWindow)) != NULL) { rp = CalcWindow->RPort; CalcWMask = (1<UserPort->mp_SigBit); CalcScreen = CalcWindow->WScreen; } else { DisplayBeep(theScreen); } } } /* * SetupGadgets() * * This fixes the standard Intuition gadgets so that their images are * the New Look images. This makes the Calulator look cool. Once * the changes have been made, refresh the window frame so that the new * gadgets show up, then add the rest of the Calc gadgets into the window, * and refresh them so that they show up. */ static void SetupGadgets() { #ifndef NL_DAEMON struct Gadget *theGadget = CalcWindow->FirstGadget; extern struct Image UpFrontImage,DownBackImage,CloseImage; while (theGadget) { switch(theGadget->GadgetType & ~SYSGADGET) { case WUPFRONT: if (CalcScreen->BitMap.Depth > 1) { theGadget->GadgetRender = (APTR)&UpFrontImage; theGadget->LeftEdge = -UpFrontImage.Width + 1; theGadget->Width = UpFrontImage.Width; } break; case WDOWNBACK: if (CalcScreen->BitMap.Depth > 1) { theGadget->GadgetRender = (APTR)&DownBackImage; theGadget->LeftEdge = -UpFrontImage.Width-DownBackImage.Width+1; theGadget->Width = DownBackImage.Width; } break; case CLOSE: theGadget->GadgetRender = (APTR)&CloseImage; theGadget->LeftEdge = 0; theGadget->Width = CloseImage.Width; break; } theGadget = theGadget->NextGadget; } RefreshWindowFrame(CalcWindow); #endif AddGList(CalcWindow,&CalcGadget[0],-1,GADGET_COUNT,NULL); RefreshGadgets(&CalcGadget[0],CalcWindow,NULL); } #define CloseCalculator CloseCalcWindow /* * OpenCalculator() * * If the active screen is not the one where the calculator already exists, * then if the calculator is already open, close it (don't signal anyone). * Open the calculator on the new screen. If the calculator opened OK, * the setup the gadgets and set the screen title. */ static void OpenCalculator() { if (IntuitionBase->ActiveScreen != CalcScreen) { if (CalcWindow) CloseCalculator(NOSIGNAL); OpenCalcWindow(IntuitionBase->ActiveScreen); if (CalcWindow) { SetupGadgets(); SetWindowTitles(CalcWindow,-1,SCREENTITLE); } } } /* * WaitForAction() * * The main Calculator event loop. * * While we have not been asked to exit, * if the calc window is open somewhere, * Check for new messages from the calculator window. * If any (and the calculator hasn't been closed or asked to exit) then * get the class code and gadget pointer from the IntuiMessage, * and reply the message. * For CLOSWINDOW events, set the flag indicating we should close. * For keyboard messages, do the appropriate action. * For gadget messages, do the proper gadget action. * For activation events, refresh the lines in the Drag Bar. * When all the messages have been processed, * if we were asked to close the window, then do so. * If we haven't been asked to exit, then wait for more messages. * If we get an ENDSIGNAL from the loader, set the done flag. * If we get a signal to open the calculator, then do so. * If we get a signal to close the calculator (from a CloseScreen * call), then do so. */ #define NEWMESSAGE (theMessage = GetMsg(CalcWindow->UserPort)) #ifndef SWINDOWS #define MESSAGEWAIT Wait(CalcSMask|CalcCMask|CalcWMask|ENDSIGNAL) #else #define MESSAGEWAIT Wait(CalcSMask|CalcWMask|ENDSIGNAL) #endif static void WaitForAction() { struct IntuiMessage *theMessage; extern struct IntuiMessage *GetMsg(); int Class, Code; struct Gadget *theGadget; LONG Signals; int NotClosed; int NotDone = TRUE; while (NotDone) { if (CalcWindow) { NotClosed = TRUE; while (NEWMESSAGE && NotDone && NotClosed) { Class = theMessage->Class; Code = theMessage->Code; theGadget = (struct Gadget *)theMessage->IAddress; ReplyMsg(theMessage); switch(Class) { case CLOSEWINDOW: NotClosed = FALSE; break; case VANILLAKEY: NotClosed = DoKey(Code); break; case GADGETUP: case GADGETDOWN: DoGadget(theGadget); break; case ACTIVEWINDOW: RefreshGList(&CalcGadget[GADG_BRDR],CalcWindow,NULL,1); break; } } if (NotClosed == FALSE) CloseCalculator(NOSIGNAL); } if (NotDone) Signals = MESSAGEWAIT; if (Signals & ENDSIGNAL) NotDone = FALSE; if (Signals & CalcSMask) OpenCalculator(); #ifndef SWINDOWS if (Signals & CalcCMask) CloseCalculator(SIGNALCLOSE); #endif } } /* * _main() * * Initialize the calculator. * As long as we have not been asked to exit, do the main event loop. * Once the main event loop end, we have been asked to exit this task. * close the calculator if it is open, and try to confirm with the loader * that we can exit properly. If not, then keep running, otherwise * call our exit routine. */ void _main() { int NotDone = TRUE; InitCalc(); while (NotDone) { WaitForAction(); CloseCalculator(NOSIGNAL); NotDone = ConfirmExit(); } cExit(); }