home *** CD-ROM | disk | FTP | other *** search
/ Dream 57 / Amiga_Dream_57.iso / Amiga / Programmation / c / Extensions / APPSource.lha / APlusPlus / libsource / WindowCV.cxx < prev   
Encoding:
C/C++ Source or Header  |  1994-08-29  |  9.3 KB  |  301 lines

  1. /******************************************************************************
  2.  **
  3.  **   C++ Class Library for the Amiga⌐ system software.
  4.  **
  5.  **   Copyright (C) 1994 by Armin Vogt  **  EMail: armin@uni-paderborn.de
  6.  **   All Rights Reserved.
  7.  **
  8.  **   $Source: apphome:RCS/libsource/WindowCV.cxx,v $
  9.  **   $Revision: 1.12 $
  10.  **   $Date: 1994/08/02 18:02:27 $
  11.  **   $Author: Armin_Vogt $
  12.  **
  13.  ******************************************************************************/
  14.  
  15.  
  16. extern "C" {
  17. #ifdef __GNUG__
  18. #include <inline/intuition.h>
  19. #include <inline/gadtools.h>
  20. #endif
  21.  
  22. #ifdef __SASC
  23. #include <proto/intuition.h>
  24. #include <proto/gadtools.h>
  25. #endif
  26. }
  27.  
  28. #include <APlusPlus/intuition/WindowCV.h>
  29. #include <APlusPlus/intuition/ScreenC.h>
  30. #include <APlusPlus/intuition/IntuiMessageC.h>
  31.  
  32.  
  33. static const char rcs_id[] = "$Id: WindowCV.cxx,v 1.12 1994/08/02 18:02:27 Armin_Vogt Exp Armin_Vogt $";
  34.  
  35. //runtime type inquiry support
  36. intui_typeinfo(WindowCV, derived(from(GraphicObject)), rcs_id)
  37.  
  38.  
  39. /*************************************************************************************************
  40.       WindowCV methods
  41.  *************************************************************************************************/
  42.  
  43.  
  44. WindowCV::WindowCV(IntuiObject* owner,AttrList& attrs) : GraphicObject((GraphicObject*)owner,attrs)
  45. {
  46.    ULONG IDCMPflags = 0;
  47.  
  48.    // initialise for safety
  49.    window_rsp = (IntuitionResponder*)NULL;
  50.    AttrManipulator next(intuiAttrs());
  51.  
  52.    if (next.findTagItem(WCV_SharePortWithWindow))
  53.    {
  54.       // share IDCMP port with another window.
  55.       WindowCV* shareWindow;
  56.  
  57.       // cast 'next.data()' into the type that was 'confirmed' with WindowCV::confirm()!
  58.       if ( NULL != (shareWindow = ptr_cast(WindowCV, (WindowCV*)next.data())) )
  59.       {
  60.          // if the port sharing window has no port, create an own UserPort.
  61.          if (NULL == (window_rsp = shareWindow->getIntuiResponder()))
  62.          {
  63.             puterr("window to share port with has no port.");
  64.          }
  65.          else
  66.          {
  67.             if (next.findTagItem(WA_IDCMP))
  68.             {
  69.                IDCMPflags = next.data();
  70.                next.writeData(0L);   // prevent Intuition from creating a userport for our window
  71.             }
  72.          }
  73.       }
  74.       else puterr("WindowCV: object to share port with is no WindowCV type.");
  75.    }
  76.  
  77.    _dprintf("getting root screen..\n");
  78.    ScreenC* screen = screenC();
  79.    if (screen==NULL)
  80.    { 
  81.       puterr("FATAL ERROR: no screen available!"); 
  82.       _ierror(WINDOWCV_OPENWINDOW_FAILED);
  83.       return; 
  84.    }
  85.    else
  86.    {
  87.  
  88.       // Make sure that these tags are present in the attribute tag list.
  89.       // If the following attributes are not specified, add them with
  90.       // these default values..
  91.       applyDefaultAttrs( attrs,AttrList(
  92.          WA_CustomScreen,0,
  93.          WA_IDCMP,0,
  94.          WA_SmartRefresh,0,
  95.          WA_DragBar, TRUE,
  96.          WA_SizeGadget, TRUE,
  97.          WA_DepthGadget, TRUE,
  98.          WA_CloseGadget, TRUE,
  99.          TAG_END ));
  100.  
  101.       // and initialise those who shall be overwritten..
  102.       intuiAttrs().updateAttrs( AttrList(
  103.          WA_CustomScreen,screen->screenPtr(),
  104.          WA_IDCMP,IDCMPflags|=CLASS_CLOSEWINDOW,
  105.          WA_SmartRefresh, TRUE,
  106.          TAG_END));
  107.  
  108.       _dprintf("Root screen found.\n");
  109.  
  110.       // open window
  111.       if (NULL != (window_ref() = OpenWindowTagList(NULL,intuiAttrs()) ) )
  112.       {
  113.          window()->UserData = (BYTE*)this;
  114.          // store the covering C++ object in the window structure
  115.          {
  116.             if (window_rsp)   // window uses another intuition responder
  117.             {
  118.                // get the userport from the shared IntuitionResponder
  119.                // and tell him we are sharing
  120.                window()->UserPort = ((IntuitionResponder*)
  121.                      (window_rsp->participate()))->getMsgPort();
  122.  
  123.                ModifyIDCMP(window(),IDCMPflags);
  124.                // now Intuition shall create a windowport
  125.             }
  126.             else if (window()->UserPort)  // create intui rsp only if the window has an IDCMP port.
  127.             {
  128.                /* create own IntuitionResponder for the window userport
  129.                 * other windows may share this port but IntuitionResponder class handles this.
  130.                 */
  131.                window_rsp = new IntuitionResponder(window()->UserPort);
  132.                if (!APPOK(window_rsp))
  133.                   _ierror(OUT_OF_MEMORY);
  134.             }
  135.             else _dprintf("WindowCV without IDCMP created.\n");
  136.          }
  137.          newsize(NULL);
  138.  
  139.          _dprintf( ("WindowCV status = %ld\n",status()) );
  140.          setIOType(IOTYPE_WINDOWCV);
  141.          _dprintf( ("\tWindowCV(status=%ld) object at %lx created.\n",status(),(APTR)window()) );
  142.       }
  143.       else _ierror(WINDOWCV_OPENWINDOW_FAILED);
  144.    }
  145. }
  146.  
  147. WindowCV::~WindowCV()
  148. {
  149.    _dprintf("WindowCV::~WindowCV()\n");
  150.  
  151.    if (window())
  152.    {
  153.       if (window_rsp)   // window may share user port
  154.       {
  155.          // release will reply all messages for our window still in the queue, so forbid sending more
  156.          Forbid();
  157.  
  158.          /* It is explicitly allowed to destruct a WindowCV within a message callback.
  159.          ** But the replying after message processing, done in actionCallback(), must then be inhibited.
  160.          */
  161.          if (window_rsp->msgInProcess)
  162.          {
  163.             GT_ReplyIMsg(window_rsp->msgInProcess);
  164.             window_rsp->msgInProcess = NULL;          //prevent from being replied twice.
  165.             _dprintf("  msg in process replied.\n");
  166.          }
  167.  
  168.          if (window_rsp->release(window())>0)  // our intuition responder has more participating windows
  169.          {
  170.             window()->UserPort = NULL;   // the shared IDCMP port is still used by other windows!
  171.             ModifyIDCMP(window(),NULL);  // let Intuition close its WindowPort
  172.          }
  173.          Permit();   // our UserPort is gone..
  174.       }
  175.       if ((WindowCV*)window()->UserData==this)
  176.       {
  177.          window()->UserData = NULL;
  178.          _dprintf( ("closing window(%lx)\n",(APTR)window()) );
  179.          CloseWindow(window());
  180.          _dprintf("..done\n");
  181.       }
  182.       else puterr("WindowCV: invalid window pointer!");
  183.    }
  184.    _dprintf("WindowCV::~WindowCV done\n");
  185. }
  186.  
  187. ULONG WindowCV::setAttributes(AttrList& attrs)
  188. {
  189.    AttrIterator next(attrs);
  190.  
  191.    while (next())
  192.    {
  193.       switch (next.tag())
  194.       {
  195.          case WA_Title :
  196.             SetWindowTitles(window(),(UBYTE*)next.data(),(UBYTE*)-1);
  197.             break;
  198.  
  199.          case WA_ScreenTitle :
  200.             SetWindowTitles(window(),(UBYTE*)-1,(UBYTE*)next.data());
  201.             break;
  202.       }
  203.    }
  204.  
  205.    return GraphicObject::setAttributes(attrs);
  206. }
  207.  
  208. ULONG WindowCV::getAttribute(Tag attr,ULONG& dataStore)
  209. {
  210.    switch (attr)
  211.    {
  212.       case WA_Title : return (dataStore=(ULONG)window()->Title);
  213.       case WA_ScreenTitle : return (dataStore=(ULONG)window()->ScreenTitle);
  214.       default : return GraphicObject::getAttribute(attr,dataStore);
  215.    }
  216. }
  217.  
  218. ScreenC* WindowCV::screenC() 
  219.    // returns the ScreenC object the window is in.
  220.    return findRootOfClass(ScreenC); 
  221. }
  222.  
  223. void WindowCV::modifyIDCMP(ULONG flags)
  224. {
  225.    ModifyIDCMP(window(),(ULONG)window()->IDCMPFlags|flags);
  226. }
  227.  
  228. void WindowCV::newsize(const IntuiMessageC* dummy)
  229.    /* Has to be called from a derived class NEWSIZE callback.
  230.    */
  231. {
  232.    /* GraphicObject holds the position to the window origin and dimensions of the inner window area.
  233.    */
  234.    setRect( window()->BorderLeft,
  235.             window()->BorderTop,
  236.             window()->Width-1-window()->BorderRight,
  237.             window()->Height-1-window()->BorderBottom);
  238.  
  239. }
  240.  
  241. /*************************************************************************************************
  242.       WindowCV::IntuitionResponder methods
  243.  *************************************************************************************************/
  244. IntuitionResponder::IntuitionResponder(struct MsgPort* IPort)
  245.       : SignalResponder(IPort->mp_SigBit,50)
  246. {
  247.    _dprintf("IntuitionResponder::\n");
  248.    userPort = IPort;
  249.    msgInProcess = NULL;
  250. }
  251.  
  252. IntuitionResponder::~IntuitionResponder()
  253. {
  254.    msgInProcess = NULL;    // indicate userport check.
  255.    userPort = NULL;        // indicate userport no longer available.
  256. }
  257.  
  258. WORD IntuitionResponder::release(Window* win)
  259.    /* unlink a window from this IntuitionResponder in replying all messages addressed to
  260.       that window and  decreasing the window participating counter.
  261.    */
  262. {
  263.    struct IntuiMessage* msg;
  264.    struct Node* succ;
  265.  
  266.    if (NULL != (msg = (struct IntuiMessage*)userPort->mp_MsgList.lh_Head))
  267.    while (NULL != (succ = msg->ExecMessage.mn_Node.ln_Succ))
  268.    {
  269.       if (msg->IDCMPWindow == win)
  270.       {
  271.          Remove((struct Node*)msg);
  272.          ReplyMsg((struct Message*)msg);
  273.       }
  274.       msg = (struct IntuiMessage*)succ;
  275.    }
  276.  
  277.    return Shared::release();  // delete IntuitionResponder instance
  278. }
  279.  
  280. void IntuitionResponder::actionCallback()
  281.    /* is invoked on a signal on the IDCMP port.
  282.    */
  283. {
  284.    WindowCV* winC;
  285.  
  286.    while (NULL != (msgInProcess = GT_GetIMsg(userPort)) )
  287.    {
  288.       // delegate to the IDCMPWindow
  289.       if (NULL != (winC = ((const IntuiMessageC* )msgInProcess)->decodeWindowCV()))
  290.       {
  291.          winC->handleIntuiMsg((const IntuiMessageC* ) msgInProcess );  // virtual callback
  292.       }
  293.       // reply only if not already replied through ~WindowCV().
  294.       if (msgInProcess) GT_ReplyIMsg(msgInProcess);
  295.       else { _dprintf("actionCallback(): msg already replied.\n");
  296.          if (userPort==NULL) break; // do not get a message from userport == null !!
  297.       }
  298.    }
  299. }
  300.