home *** CD-ROM | disk | FTP | other *** search
- #include "PopUpMenu.h"
- #include "Version.h"
-
- #define REPLYPORTNAME "Reply"
- #define IMPDEVPORTNAME "ImpDev"
- #define TIMERPORTNAME "Timer"
- #define QUITPORTNAME "Quit"
- #define INPHANDLNAME PopUpTaskName
- #define SEMAPHORENAME PopUpTaskName
-
- #define POPUPMSG "\x9B0;33mPopUpMenu\x9B0m "
- #define KILLMSG "removed.\n"
- #define STARTMSG "installed.\n\xA9 Martin Adrian 1990\n"
- #define FAILMSG "failed.\n"
- #define DELAYTIME 150
-
- #define INPHANDLPRI 53
- /* Must use kickstart 1.2 or higher */
- #define LIBVERSION 33
-
- /* don't know how to find these in C */
- #define LVOSetMenuStrip -0x108
- #define LVOClearMenuStrip -0x36
- #define LVOOnMenu -0xc0
- #define LVOOffMenu -0xb4
-
- /* this is for errors in proto/exec.h */
- #undef RemSemaphore
- #pragma syscall RemSemaphore 25e 901
-
- extern VOID InitPopUpMenu(VOID);
- extern VOID MySetMenuStrip();
- extern VOID MyClearMenuStrip();
- extern VOID MyOnMenu();
- extern VOID MyOffMenu();
-
- VOID InitPopUpMenu()
- {
-
- IMPORT struct DosLibrary *DosBase;
- IMPORT struct IntuitionBase *IntuitionBase;
- IMPORT struct GfxBase *GfxBase;
- IMPORT struct LayersBase *LayersBase;
-
- IMPORT struct IOStdReq *InputReqBlock;
- IMPORT struct timerequest *TimerReqBlock;
- IMPORT struct SignalSemaphore PopUpSemaphore;
- IMPORT __fptr OldSetMenuStrip, OldClearMenuStrip, OldOnMenu, OldOffMenu;
- IMPORT BPTR StdOut;
- IMPORT BPTR PopUpSeg;
-
- IMPORT STRPTR far PopUpTaskName; /* Pointer to the string "PopUpMenu" */
-
- struct MsgPort *ReplyPort;
- struct MsgPort *InputDevPort;
- struct MsgPort *TimerPort;
- struct Interrupt InputReqData;
- struct SignalData InputSignals;
- LONG MenuUpSigNum, MenuDownSigNum;
- LONG MouseMovedSigNum, SelectDownSigNum;
-
- geta4(); /* load global database */
-
- Write(StdOut,POPUPMSG,sizeof(POPUPMSG));
-
- /***********************************
- * see if we are already installed *
- ***********************************/
- if (!(ReplyPort = FindPort(REPLYPORTNAME))) {
- if (!(ReplyPort = CreatePort(REPLYPORTNAME,0)))
- goto CleanUp13;
- }
- else {
- /* yes, popupmenues already installed, tell running task to quit */
- struct MsgPort *const QuitPort = CreatePort(QUITPORTNAME,0);
- struct IntuiMessage *Message;
-
- if (QuitPort) {
- if (Message = BuildIntuiMsg(QuitPort,QUITPOPUPMENU,NULL)) {
- /* Send quitmessage */
- PutMsg(ReplyPort, (struct Message *)Message);
- /* Wait for reply */
- WaitPort(QuitPort);
- /* get rid of the message */
- GetMsg(QuitPort);
- FreeMem(Message,(LONG)Message->ExecMessage.mn_Length +
- sizeof(struct Message));
-
- WriteAndClose(KILLMSG, sizeof(KILLMSG));
- }
- DeletePort(QuitPort);
- }
- goto CleanUp13;
- }
-
- /******************
- * open libraries *
- ******************/
- if (!(IntuitionBase = (struct IntuitionBase *)
- OpenLibrary("intuition.library", LIBVERSION)))
- goto CleanUp12;
- if (!(GfxBase = (struct GfxBase *)
- OpenLibrary("graphics.library", LIBVERSION)))
- goto CleanUp11;
- if (!(LayersBase = (struct LayersBase *)
- OpenLibrary("layers.library", LIBVERSION)))
- goto CleanUp10;
-
- /************************
- * Allocate our signals *
- ************************/
- if ((MenuUpSigNum = AllocSignal(-1)) == -1)
- goto CleanUp9;
- if ((MenuDownSigNum = AllocSignal(-1)) == -1)
- goto CleanUp8;
- if ((MouseMovedSigNum = AllocSignal(-1)) == -1)
- goto CleanUp7;
- if ((SelectDownSigNum = AllocSignal(-1)) == -1)
- goto CleanUp6;
-
- /****************************************
- * Build connection to the input.device *
- ****************************************/
- if (!(InputDevPort = CreatePort(IMPDEVPORTNAME,0)))
- goto CleanUp5;
- if ((InputReqBlock = (struct IOStdReq *)
- AllocMem(sizeof(struct IOStdReq),
- MEMF_CLEAR | MEMF_PUBLIC)) == NULL)
- goto CleanUp4;
-
- InputReqBlock->io_Message.mn_Node.ln_Type = NT_MESSAGE;
- InputReqBlock->io_Message.mn_Length = sizeof(struct IOStdReq);
- InputReqBlock->io_Message.mn_ReplyPort = InputDevPort;
-
- if (OpenDevice("input.device",0,(struct IORequest *)InputReqBlock,0))
- goto CleanUp3;
-
- /****************************************
- * Bulid connection to the timer.device *
- ****************************************/
- if (!(TimerPort = CreatePort(TIMERPORTNAME,0)))
- goto CleanUp3x3;
- if (!(TimerReqBlock = (struct timerequest *)
- AllocMem(sizeof(struct timerequest),
- MEMF_CLEAR | MEMF_PUBLIC)))
- goto CleanUp3x2;
-
- TimerReqBlock->tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
- TimerReqBlock->tr_node.io_Message.mn_Length = sizeof(struct timerequest);
- TimerReqBlock->tr_node.io_Message.mn_ReplyPort = TimerPort;
-
- if (OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)TimerReqBlock,0))
- goto CleanUp3x1;
-
- /* Start Timer (just to be sure that at least one request is sent. */
- /* CheckIO doesn't work otherwise, i think) */
-
- QueueTimer();
-
- /********************
- * Make a semaphore *
- ********************/
- PopUpSemaphore.ss_Link.ln_Name = SEMAPHORENAME;
- PopUpSemaphore.ss_Link.ln_Pri = 0;
- AddSemaphore(&PopUpSemaphore);
-
- /**************************************************
- * patch intuition functions to use our semaphore *
- **************************************************/
- if (!(OldSetMenuStrip = SetFunction((struct Library *)IntuitionBase,
- LVOSetMenuStrip,MySetMenuStrip)))
- goto CleanUp2x4;
- if (!(OldClearMenuStrip = SetFunction((struct Library *)IntuitionBase,
- LVOClearMenuStrip,MyClearMenuStrip)))
- goto CleanUp2x3;
- if (!(OldOnMenu = SetFunction((struct Library *)IntuitionBase,
- LVOOnMenu,MyOnMenu)))
- goto CleanUp2x2;
- if (!(OldOffMenu = SetFunction((struct Library *)IntuitionBase,
- LVOOffMenu,MyOffMenu)))
- goto CleanUp2x1;
-
- /**********************************
- * init data for the inputhandler *
- **********************************/
- InputSignals.PopUpMenuTask = FindTask(0);
- InputSignals.MenuUpSig = 1L << MenuUpSigNum;
- InputSignals.MenuDownSig = 1L << MenuDownSigNum;
- InputSignals.MouseMovedSig = 1L << MouseMovedSigNum;
- InputSignals.SelectDownSig = 1L << SelectDownSigNum;
- InputSignals.Down = FALSE; /* menubutton is not down. (who cares) */
-
- /****************************
- * startup the inputhandler *
- ****************************/
- InputReqData.is_Node.ln_Pri = INPHANDLPRI; /* must come before intuition */
- InputReqData.is_Node.ln_Name = INPHANDLNAME;
-
- InputReqData.is_Data = (APTR)&InputSignals;
- InputReqData.is_Code = (VOID *)PopUpHandler;
-
- InputReqBlock->io_Command = IND_ADDHANDLER;
- InputReqBlock->io_Data = (APTR)&InputReqData;
-
- DoIO((struct IORequest *)InputReqBlock);
-
- /***************************************
- * tell the user that everything is ok *
- ***************************************/
- WriteAndClose(VERSION STARTMSG, sizeof(VERSION STARTMSG));
-
- PopUpMainLoop(&InputSignals,ReplyPort);
-
- CleanUp1:
-
- /* remove inputhandler */
- InputReqBlock->io_Command = IND_REMHANDLER;
- InputReqBlock->io_Data = (APTR)&InputReqData;
-
- DoIO((struct IORequest *)InputReqBlock);
-
- /* restore intuition functions */
- SetFunction((struct Library *)IntuitionBase,LVOOffMenu,OldOffMenu);
- CleanUp2x1:
- SetFunction((struct Library *)IntuitionBase,LVOOnMenu,OldOnMenu);
- CleanUp2x2:
- SetFunction((struct Library *)IntuitionBase,LVOClearMenuStrip,OldClearMenuStrip);
- CleanUp2x3:
- SetFunction((struct Library *)IntuitionBase,LVOSetMenuStrip,OldSetMenuStrip);
- CleanUp2x4:
-
- /* remove semaphore */
- RemSemaphore(&PopUpSemaphore);
-
- /* close timer.device */
- CloseDevice((struct IORequest *)TimerReqBlock);
- CleanUp3x1:
- FreeMem(TimerReqBlock,sizeof(struct timerequest));
- CleanUp3x2:
- DeletePort(TimerPort);
- CleanUp3x3:
-
- /* close input.device */
- CloseDevice((struct IORequest *)InputReqBlock);
- CleanUp3:
- DeleteStdIO(InputReqBlock);
- CleanUp4:
- DeletePort(InputDevPort);
- CleanUp5:
-
- /* Free allocated signals */
- FreeSignal(SelectDownSigNum);
- CleanUp6:
- FreeSignal(MouseMovedSigNum);
- CleanUp7:
- FreeSignal(MenuDownSigNum);
- CleanUp8:
- FreeSignal(MenuUpSigNum);
- CleanUp9:
-
- /* close libraries */
- CloseLibrary((struct Library *)LayersBase);
- CleanUp10:
- CloseLibrary((struct Library *)GfxBase);
- CleanUp11:
- CloseLibrary((struct Library *)IntuitionBase);
- CleanUp12:
- DeletePort(ReplyPort);
- CleanUp13:
- if (StdOut)
- WriteAndClose(FAILMSG,sizeof(FAILMSG));
- if (PopUpSeg) {
- /* if loaded from CLI unload us */
- Forbid();
- UnLoadSeg(PopUpSeg);
- }
- CloseLibrary((struct Library *)DOSBase);
- }
-
- /***************************************
- * WriteAndClose(Text,Length) *
- * *
- * Input: *
- * Text - Text to write to StdOut. *
- * Length *
- ***************************************/
- VOID WriteAndClose(Text, Length)
- STRPTR Text;
- ULONG Length;
- {
- IMPORT BPTR StdOut;
-
- Write(StdOut,Text,Length);
- Delay(DELAYTIME);
- Close(StdOut);
- StdOut = NULL;
- }
-
- /************************************************
- * PopUpMainLoop(InputSignals,ReplyPort) *
- * *
- * Input: *
- * InputSignals - Allocated signals. *
- * ReplyPort - Port for MENUVERIFY replies *
- * Output: *
- * none *
- ************************************************/
- VOID PopUpMainLoop(InputSignals,ReplyPort)
- struct SignalData *const InputSignals;
- struct MsgPort *const ReplyPort;
- {
- IMPORT struct Window *ActiveWindow;
- IMPORT struct Screen *Screen;
- IMPORT struct Menu *Menues;
-
- const LONGBITS ReplySig = 1L << (LONG)ReplyPort->mp_SigBit;
- const LONGBITS MenuUpSig = InputSignals->MenuUpSig;
- const LONGBITS MenuDownSig = InputSignals->MenuDownSig;
- const LONGBITS AllSignals = ReplySig | MenuUpSig | MenuDownSig;
-
- WORD NrOfMessages = 0;
- BOOL QuitPopUpMenu = FALSE;
- BOOL VerifyOK = FALSE;
-
- FOREVER {
- const LONGBITS SignalBits = Wait(AllSignals);
-
- if (SignalBits & MenuUpSig) {
- ActiveWindow = NULL;
- VerifyOK = FALSE;
- }
-
- if (SignalBits & ReplySig) {
- struct IntuiMessage *Message;
-
- while (Message = (struct IntuiMessage *)GetMsg(ReplyPort)) {
- if (Message->Class == MENUVERIFY) {
- if (Message->IDCMPWindow == ActiveWindow)
- VerifyOK = (Message->Code != MENUCANCEL);
- NrOfMessages--;
- FreeMem(Message,(LONG)Message->ExecMessage.mn_Length +
- sizeof(struct Message));
- }
- else { /* Message->Class == QUITPOPUPMENU or some strange message */
- ReplyMsg((struct Message *)Message); /* Message does not belong to this task */
- QuitPopUpMenu = TRUE;
- }
-
- } /* while */
- if (NrOfMessages == 0) {
- if (QuitPopUpMenu)
- break;
- if (VerifyOK) {
- PopUpMenu(InputSignals);
- VerifyOK = FALSE;
- }
- }
- }
-
- if ((SignalBits & (MenuUpSig | MenuDownSig)) == MenuDownSig) {
- const LONG Lock = LockIBase(0);
-
- if ((ActiveWindow = IntuitionBase->ActiveWindow) AND
- !(ActiveWindow->Flags & RMBTRAP) AND
- (ActiveWindow->MenuStrip)) {
- Screen = ActiveWindow->WScreen;
- UnlockIBase(Lock);
- if ((NrOfMessages = SendMessage(ReplyPort)) == 0)
- PopUpMenu(InputSignals);
- else
- VerifyOK = TRUE;
- }
- else
- UnlockIBase(Lock);
- }
- } /* FOREVER */
- }
-