home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- **
- ** C++ Class Library for the Amiga© system software.
- **
- ** Copyright (C) 1994 by Armin Vogt ** EMail: armin@uni-paderborn.de
- ** All Rights Reserved.
- **
- ** $Source: apphome:APlusPlus/RCS/libsource/WindowCV.cxx,v $
- ** $Revision: 1.4 $
- ** $Date: 1994/05/05 22:11:19 $
- ** $Author: Armin_Vogt $
- **
- ******************************************************************************/
-
-
- extern "C" {
- #ifdef __GNUG__
- #include <inline/intuition.h>
- #include <inline/gadtools.h>
- #endif
-
- #ifdef __SASC
- #include <proto/intuition.h>
- #include <proto/gadtools.h>
- #endif
- }
-
- #include <APlusPlus/intuition/WindowCV.h>
-
-
- volatile static char rcs_id[] = "$Id: WindowCV.cxx,v 1.4 1994/05/05 22:11:19 Armin_Vogt Exp Armin_Vogt $";
-
-
- /*************************************************************************************************
- WindowCV methods
- *************************************************************************************************/
-
-
- WindowCV::WindowCV(IntuiObject *owner,AttrList& attrs) : GraphicObject((GraphicObject*)owner,attrs)
- {
- ULONG IDCMPflags = 0;
-
- // initialise for safety
- window_rsp = (IntuitionResponder*)NULL;
- AttrManipulator next(intuiAttrs());
-
- _dout("WindowCV::WindowCV("<<status()<<")\n");
- if (next.findTagItem(WCV_SharePortWithWindow))
- {
- // share IDCMP port with another window.
- WindowCV *shareWindow;
-
- if ( (shareWindow = (WindowCV*)(next.data()))->isKindOf(IOTYPE_WINDOWCV) )
- {
- // if the port sharing window has no port, create an own UserPort.
- if (NULL == (window_rsp = shareWindow->getIntuiResponder()))
- {
- cerr << "window to share port with has no port.\n";
- }
- else
- {
- if (next.findTagItem(WA_IDCMP))
- {
- IDCMPflags = next.data();
- next.writeData(0L); // prevent Intuition from creating a userport for our window
- }
- }
- }
- else cerr << "WindowCV: object to share port with is no WindowCV type.\n";
- }
- _dout("getting root screen..\n");
-
- ScreenC *screen = (ScreenC*)findRootOfType(IOTYPE_SCREEN);
- if (screen==NULL){ cerr << "FATAL ERROR: no screen available!\n"; return; }
- else
- {
- // make sure that these tags are present in the attribute tag list..
- intuiAttrs().addAttrs(AttrList(WA_CustomScreen,0, WA_IDCMP,0, TAG_END));
- // and initialise them..
- intuiAttrs().updateAttrs(AttrList(WA_CustomScreen,screen->screenPtr(),
- WA_IDCMP,IDCMPflags|=CLASS_CLOSEWINDOW,TAG_END));
- _dout("Root screen found.\n");
-
- // open window
- if (NULL != (wPtr() = OpenWindowTagList(NULL,intuiAttrs()) ) )
- {
- window()->UserData = (BYTE*)this; // store the covering object in the window structure
- {
- if (window_rsp) // window uses another intuition responder
- {
- // get the userport from the shared IntuitionResponder and tell him we are sharing
- window()->UserPort = ((IntuitionResponder*)(window_rsp->participate()))->getMsgPort();
- ModifyIDCMP(window(),IDCMPflags); // now Intuition shall create a windowport
- }
- else if (window()->UserPort) // create intui rsp only if the window has an IDCMP port.
- {
- /* create own IntuitionResponder for the window userport
- * other windows may share this port but IntuitionResponder class handles this.
- */
- window_rsp = new IntuitionResponder(window()->UserPort);
- if (!APPOK(window_rsp))
- _ierror(OUT_OF_MEMORY);
- }
- else _dout("WindowCV without IDCMP created.\n");
- }
- newsize(NULL);
-
- _dout("WindowCV status = "<<IntuiObject::status()<<endl);
- setIOType(IOTYPE_WINDOWCV);
- _dout("\tWindowCV("<<IntuiObject::status()<<"): object at "<<window()<<" created.\n");
- }
- else _ierror(WINDOWCV_OPENWINDOW_FAILED);
- }
- }
-
- WindowCV::~WindowCV()
- {
- _dout("WindowCV::~WindowCV()\n");
-
- if (window())
- {
- if (window_rsp) // window may share user port
- {
- // release will reply all messages for our window still in the queue, so forbid sending more
- Forbid();
-
- /* It is explicitly allowed to destruct a WindowCV within a message callback.
- ** But the replying after message processing, done in actionCallback(), must then be inhibited.
- */
- if (window_rsp->msgInProcess)
- {
- GT_ReplyIMsg(window_rsp->msgInProcess);
- window_rsp->msgInProcess = NULL; //prevent from being replied twice.
- _dout(" msg in process replied.\n");
- }
-
- if (window_rsp->release(window())>0) // our intuition responder has more participating windows
- {
- window()->UserPort = NULL; // the shared IDCMP port is still used by other windows!
- ModifyIDCMP(window(),NULL); // let Intuition close its WindowPort
- }
- Permit(); // our UserPort is gone..
- }
- if ((WindowCV*)window()->UserData==this)
- {
- window()->UserData = NULL;
- _dout("closing window "<<window()<<" ..\n");
- CloseWindow(window());
- _dout("..done\n");
- }
- else cerr << "WindowCV: invalid window pointer!\n";
- }
- _dout("WindowCV::~WindowCV done\n");
- }
-
- ULONG WindowCV::setAttributes(AttrList& attrs)
- {
- AttrIterator next(attrs);
-
- while (next())
- {
- switch (next.tag())
- {
- case WA_Title :
- SetWindowTitles(window(),(UBYTE*)next.data(),(UBYTE*)-1);
- break;
-
- case WA_ScreenTitle :
- SetWindowTitles(window(),(UBYTE*)-1,(UBYTE*)next.data());
- break;
- }
- }
-
- return GraphicObject::setAttributes(attrs);
- }
-
- ULONG WindowCV::getAttribute(Tag attr,ULONG& dataStore)
- {
- switch (attr)
- {
- case WA_Title : return (dataStore=(ULONG)window()->Title);
- case WA_ScreenTitle : return (dataStore=(ULONG)window()->ScreenTitle);
- default : return GraphicObject::getAttribute(attr,dataStore);
- }
- }
-
- void WindowCV::modifyIDCMP(ULONG flags)
- {
- ModifyIDCMP(window(),(ULONG)window()->IDCMPFlags|flags);
- }
-
- void WindowCV::handleIntuiMsg(const IntuiMessageC *msg)
- /* Default IDCMP message handler used with all Window classes in this library.
- Each derived class has to call the inherited WindowCV class ::handleIntuiMsg()
- if it overloads handleIntuiMsg(). This assures that all handleIntuiMsg() methods
- get called and can do their class specific work.
- */
- {
- /* This version no longer works with the IDCMPMapper!!! */
- if (msg->getClass()==CLASS_NEWSIZE) newsize(msg);
- }
-
- void WindowCV::newsize(const IntuiMessageC *dummy)
- /* Has to be called from a derived class NEWSIZE callback.
- */
- {
- /* GraphicObject holds the position to the window origin and dimensions of the inner window area.
- */
- setRect( window()->BorderLeft,
- window()->BorderTop,
- window()->Width-1-window()->BorderRight,
- window()->Height-1-window()->BorderBottom);
-
- }
- /********************* friends of WindowCV *********************************/
-
- ostream& operator << (ostream& OS,struct Window *w)
- {
- OS << "{"<<w->LeftEdge<<","<<w->TopEdge<<","<<w->Width<<","<<w->Height<<", UserPort at "<<w->UserPort<<"}";
- return OS;
- }
-
- ostream& operator << (ostream& OS,WindowCV *win)
- {
- OS << "WindowCV::window=" << win->window() << endl;
- OS << "window_rsp at "<<win->window_rsp<<endl;
- return OS;
- }
-
-
- /*************************************************************************************************
- WindowCV::IntuitionResponder methods
- *************************************************************************************************/
- IntuitionResponder::IntuitionResponder(struct MsgPort *IPort)
- : SignalResponder(IPort->mp_SigBit,50)
- {
- _dout("IntuitionResponder::\n");
- userPort = IPort;
- msgInProcess = NULL;
- }
-
- IntuitionResponder::~IntuitionResponder()
- {
- msgInProcess = NULL; // indicate userport check.
- userPort = NULL; // indicate userport no longer available.
- }
-
- WORD IntuitionResponder::release(Window *win)
- /* unlink a window from this IntuitionResponder in replying all messages addressed to
- that window and decreasing the window participating counter.
- */
- {
- struct IntuiMessage *msg;
- struct Node *succ;
-
- if (NULL != (msg = (struct IntuiMessage*)userPort->mp_MsgList.lh_Head))
- while (NULL != (succ = msg->ExecMessage.mn_Node.ln_Succ))
- {
- if (msg->IDCMPWindow == win)
- {
- Remove((struct Node*)msg);
- ReplyMsg((struct Message*)msg);
- }
- msg = (struct IntuiMessage*)succ;
- }
-
- return Shared::release(); // delete IntuitionResponder instance
- }
-
- void IntuitionResponder::actionCallback()
- /* is invoked on a signal on the IDCMP port.
- */
- {
- WindowCV *winC;
-
- while (NULL != (msgInProcess = GT_GetIMsg(userPort)) )
- {
- // delegate to the IDCMPWindow
- if (NULL != (winC = ((const IntuiMessageC *)msgInProcess)->decodeWindowCV()))
- {
- winC->handleIntuiMsg((const IntuiMessageC *) msgInProcess ); // virtual callback
- }
- // reply only if not already replied through ~WindowCV().
- if (msgInProcess) GT_ReplyIMsg(msgInProcess);
- else { _dout("actionCallback(): msg already replied.\n");
- if (userPort==NULL) break; // do not get a message from userport == null !!
- }
- }
- }
- void WindowCV::default_IMsgCallback(const IntuiMessageC *msg)
- {
- _dout("**WindowCV::default_IMsgCallback called.\n");
- }
-