;/* sc resopt link optimize debug=line idir=include: nostartup nostackcheck opt data=far sharedidcmp.c quit */ /* ** Shared IDCMP Port Window Example ** ** Written by Harry "Piru" Sintonen ** Public Domain. ** */ #include #include #include #include #include #define __USE_SYSBASE #include #include #include #include struct LocalData { struct ExecBase *ld_SysBase; struct DosLibrary *ld_DOSBase; struct IntuitionBase *ld_IntuitionBase; struct MsgPort *ld_WinPort; }; #define SysBase ld->ld_SysBase #define DOSBase ld->ld_DOSBase #define IntuitionBase ld->ld_IntuitionBase #define WinPort ld->ld_WinPort int testcode(struct LocalData *ld); struct Window *OpenWindowSafely(struct LocalData *ld, ULONG idcmpflags, struct TagItem *tags); void CloseWindowSafely(struct LocalData *ld, struct Window *win); void StripIntuiMessages(struct LocalData *ld, struct MsgPort *mp, struct Window *win); int main(void) { struct LocalData _ld = {0}, *ld = &_ld; int ret = RETURN_FAIL; SysBase = *((struct ExecBase **) 4); DOSBase = (APTR) OpenLibrary("dos.library", 37); if (DOSBase) { WinPort = CreateMsgPort(); if (WinPort) { IntuitionBase = (APTR) OpenLibrary("intuition.library", 37); if (IntuitionBase) { ret = testcode(ld); CloseLibrary((struct Library *) IntuitionBase); } else { Printf("Could not open intuition.library!\n"); } DeleteMsgPort(WinPort); } else { Printf("Could not create msgport!\n"); } CloseLibrary((struct Library *) DOSBase); } return ret; } #define NUMWINS 6 int testcode(struct LocalData *ld) { int i, openwindows; struct Window *win[NUMWINS] = {NULL}; struct TagItem owTags[] = { {WA_Left, 0}, {WA_Top, 20}, {WA_InnerWidth, 160}, {WA_InnerHeight, 100}, {WA_MinWidth, 80}, {WA_MaxWidth, -1}, {WA_MinHeight, 40}, {WA_MaxHeight, -1}, {WA_IDCMP, 0}, /* <- NOTE: Must be 0! Set with ModifyIDCMP! */ {WA_Flags, WFLG_NOCAREREFRESH | WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_SIZEGADGET | WFLG_DEPTHGADGET | WFLG_RMBTRAP | WFLG_NEWLOOKMENUS}, {WA_Title, (ULONG) "sharedidcmp"}, {WA_AutoAdjust, TRUE}, {TAG_DONE} }; /* ** open the windows */ openwindows = 0; for (i = 0; i < NUMWINS; i++) { owTags[0].ti_Data = i * 200; win[i] = OpenWindowSafely(ld, IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY, owTags); if (win[i]) { /* ** keep index information for easy table access */ win[i]->UserData = (BYTE *) i; openwindows++; } else { for (i = 0; i < openwindows; i++) { CloseWindowSafely(ld, win[i]); } /* ** failed, exit now */ return RETURN_ERROR; } } Printf("activate any of the windows and hit some keys...\n" "close all windows or hit CTRL-C to quit.\n"); /* ** while any windows open */ while (openwindows) { ULONG sigmask; ULONG winportmask = 1UL << WinPort->mp_SigBit; struct IntuiMessage *msg; /* ** wait for signals to arrive */ sigmask = Wait(winportmask | SIGBREAKF_CTRL_C); /* ** process all WinPort IDCMP messages */ if (sigmask & winportmask) { while ((msg = (struct IntuiMessage *) GetMsg(WinPort))) { struct IntuiMessage cmsg; /* ** copy the message and reply as soon as possible */ cmsg = *msg; switch (cmsg.Class) { case IDCMP_SIZEVERIFY: case IDCMP_NEWSIZE: case IDCMP_REFRESHWINDOW: case IDCMP_REQVERIFY: case IDCMP_REQCLEAR: /* ** these are not replied immeditially */ break; default: ReplyMsg(&msg->ExecMessage); msg = NULL; break; } /* ** get window index */ i = (int) cmsg.IDCMPWindow->UserData; /* ** sanitycheck */ if ((unsigned int) i < NUMWINS && cmsg.IDCMPWindow == win[i]) { switch (cmsg.Class) { case IDCMP_CLOSEWINDOW: CloseWindowSafely(ld, win[i]); win[i] = NULL; openwindows--; break; case IDCMP_VANILLAKEY: Printf("window %ld (0x%lx) char %ld '%lc'\n", i, (ULONG) win[i], cmsg.Code, cmsg.Code); break; } } /* ** reply the message unless already replied */ if (msg) { ReplyMsg(&msg->ExecMessage); } } } if (sigmask & SIGBREAKF_CTRL_C) { break; } } /* ** close remaining open windows, if any */ for (i = 0; i < NUMWINS; i++) { if (win[i]) { CloseWindowSafely(ld, win[i]); win[i] = NULL; } } return RETURN_OK; } struct Window *OpenWindowSafely(struct LocalData *ld, ULONG idcmpflags, struct TagItem *tags) { struct Window *ret; ret = OpenWindowTagList(NULL, tags); if (ret) { /* ** set the global idcmp msgport */ ret->UserPort = WinPort; /* ** enable the requested idmcp messages */ if (!ModifyIDCMP(ret, idcmpflags)) { /* ** failure, clean up! */ ret->UserPort = NULL; CloseWindow(ret); ret = NULL; } } return ret; } void CloseWindowSafely(struct LocalData *ld, struct Window *win) { if (!win) { return; } /* ** we forbid here to keep out of race conditions with Intuition */ Forbid(); /* ** send back any messages for this window ** that have not yet been processed */ StripIntuiMessages(ld, win->UserPort, win); /* ** clear UserPort so Intuition will not free it */ win->UserPort = NULL; /* ** tell Intuition to stop sending more messages */ ModifyIDCMP(win, 0UL); /* ** turn multitasking back on */ Permit(); /* ** and really close the window */ CloseWindow(win); } void StripIntuiMessages(struct LocalData *ld, struct MsgPort *mp, struct Window *win) { struct IntuiMessage *msg; struct Node *succ; msg = (struct IntuiMessage *) mp->mp_MsgList.lh_Head; while ((succ = msg->ExecMessage.mn_Node.ln_Succ)) { if (msg->IDCMPWindow == win) { /* ** Intuition is about to free this message. ** Make sure that we have politely sent it back. */ Remove(&msg->ExecMessage.mn_Node); ReplyMsg(&msg->ExecMessage); } msg = (struct IntuiMessage *) succ; } }