/*
 *	$Source: /u1/Xr/src/Xrlib/Dialog/RCS/panelmgr.c,v $
 *	$Header: panelmgr.c,v 1.1 86/12/17 08:58:52 swick Exp $
 */

#ifndef lint
static char *rcsid_panelmgr_c = "$Header: panelmgr.c,v 1.1 86/12/17 08:58:52 swick Exp $";
#endif	lint

#include <Xr/xr-copyright.h>

/* $Header: panelmgr.c,v 1.1 86/12/17 08:58:52 swick Exp $ */
/* Copyright 1986, Hewlett-Packard Company */
/* Copyright 1986, Massachussetts Institute of Technology */

static char rcsid[] = "$Header: panelmgr.c,v 1.1 86/12/17 08:58:52 swick Exp $";
/*************************************<+>*************************************
 *****************************************************************************
 **
 **   File:        panelmgr.c
 **
 **   Project:     X-ray Toolbox
 **
 **   Description: X-ray Toolbox panel manager.
 **
 **
 **
 **   ------------------------ MODIFICATION RECORD   ------------------------
 *
 * $Log:	panelmgr.c,v $
 * Revision 1.1  86/12/17  08:58:52  swick
 * Initial revision
 * 
 * Revision 7.0  86/11/13  08:31:36  08:31:36  ed ()
 * Final QA release
 * 
 * Revision 6.1  86/11/11  15:54:08  15:54:08  ed ()
 * Fixed:  Now sets editor to current editor on unknown editor input.
 *         returns in one location only. (MSG_EDIT)
 *         removed dereferencing NULL pointer
 * 
 * Revision 6.0  86/11/10  15:29:04  15:29:04  ed ()
 * QA #2 release
 * 
 * Revision 5.6  86/11/10  15:27:29  15:27:29  ed ()
 * modified ifdef for berkeley UN*X
 * 
 * Revision 5.5  86/11/10  09:04:42  09:04:42  ed ()
 * Added check for ExposeWindow source in MSG_EDIT.
 * 
 * Revision 5.4  86/11/07  13:49:30  13:49:30  ed ()
 * Added procedure headers, new copyright stuff.
 * 
 * Revision 5.3  86/11/06  11:43:52  11:43:52  ed ()
 * Changed to use value2 and value3.
 * 
 * Revision 5.2  86/10/30  12:15:45  12:15:45  ed ()
 * Added MSG_SIZE.
 * 
 * Revision 5.1  86/10/30  10:26:08  10:26:08  ed ()
 * Fixed: MSG_SHOW returns TRUE on success.
 *        Added padding (fontInfo -> width * 2) on panel edges.
 *        MSG_RESIZE uses RECTANGLE structure instead of SIZE structure.
 * 
 * Revision 5.0  86/10/28  08:30:45  08:30:45  ed ()
 * QA #1.1 release
 * 
 * Revision 4.5  86/10/26  16:30:03  16:30:03  ed ()
 * Now uses cursor from panel context when creating a panel.
 * 
 * Revision 4.4  86/10/24  08:50:53  08:50:53  ed ()
 * Added check for unknown input from editors.
 * 
 * Revision 4.3  86/10/23  17:50:47  17:50:47  ed ()
 * Added XSelectInput back to MSG_SHOW.
 * 
 * Revision 4.2  86/10/23  15:08:13  15:08:13  ed ()
 * Linted, added register variables, prepared for Beta release.
 * 
 * Revision 4.1  86/10/22  20:13:00  20:13:00  ed ()
 * Added subpanels, MSG_RESIZE.
 * 
 * Revision 4.0  86/10/20  12:13:08  12:13:08  ed ()
 * QA #1 release
 * 
 * Revision 3.2  86/10/08  09:30:18  09:30:18  ed ()
 * Modified MSG_GETPANELCONTEXT to reflect new context.
 * 
 * Revision 3.1  86/10/07  16:09:28  16:09:28  ed ()
 * Modified to use new panel context structure.
 * 
 * Revision 3.0  86/10/02  16:04:42  16:04:42  ed ()
 * Alpha Release set to 3.0
 * 
 * Revision 1.4  86/09/29  19:42:02  19:42:02  ed ()
 * Added check for size, Added redraw on exposure events.
 * 
 * Revision 1.3  86/09/25  18:56:00  18:56:00  ed ()
 * Added MSG_CURRENTEDITOR, check for showflag, added process flag code
 * 
 * Revision 1.2  86/09/14  15:01:06  15:01:06  ed ()
 * Temporary bug fix for message box manager.
 * 
 * Revision 1.1  86/09/03  10:16:17  10:16:17  ed ()
 * Initial revision
 * 
 *
 *****************************************************************************
 *************************************<+>*************************************/




#include <X/Xlib.h>
#include <Xr/defs.h>
#include <Xr/types.h>

#ifdef BSD
#include <sys/time.h>
#else
#include <time.h>
#endif


/*************************************<->*************************************
 *
 *  XrPanel(panelInstance, message, data)
 *
 *     xrPanel   * panelInstance;
 *     INT32       message;
 *     INT8      * data;
 *
 *   Description:
 *   -----------
 *     This is the panel manager.  It provides the environment to
 *     compose a group, or set of editor groups into a window.
 *     The routine is one module, but is divided into independent
 *     sections by a large switch statement.  The major commands
 *     are MSG_NEW and MSG_EDIT.  MSG_NEW creates a panel structure
 *     the panels window, creates the editors, and displays the 
 *     panel is indicated.  MSG_EDIT blocks on input while waiting
 *     for a panel to be edited.
 *
 *     The other messages support the modification and query of the
 *     panel structure.  For a complete description of the panel
 *     manager, refer to the X-ray toolbox manual.
 *
 *
 *   Inputs:
 *   ------
 *     panelInstance = This value indicates to the panel manager, 
 *                     which panel should be dealt with.
 *
 *     message = Contains the command to be executed.
 *
 *     data    = Varies depending upon the message.  But is generally
 *               a pointer to a structure.
 *
 * 
 *   Outputs:
 *   -------
 *
 *     panelInstance = Returned from MSG_NEW.
 *
 *     TRUE    = Returned upon successful completion of a message.
 *
 *     NULL    = Returned if something went wrong.
 *
 *     data    = Several of the messages return information in the
 *               structure pointed at by data.
 *
 *     xrError = The error variable is set to one of several values
 *               upon failure of this routine.
 *
 *
 *   Procedures Called
 *   -----------------
 *   MSG_NEW:
 *     (* xrMalloc)()
 *     (* xrFree)()
 *     XCreateWindow()  - XLib
 *     XDefineCursor()  - XLib
 *     XrCopyRect()     - calc.c
 *     XrInput()        - input.c
 *     XrEditorGroup()  - group.c
 *     XrUnionRect()    - calc.c
 *     XChangeWindow()  - XLib
 *     XrOffsetRect()   - calc.c
 *     XMapWindow()     - XLib
 *     XrEditor()       - editor.c
 *     XFlush()         - XLib
 *     XSelectInput()   - XLib
 *
 *   MSG_EDIT:
 *     XrInput()        - input.c
 *     XrEditor()       - editor.c
 *
 *   MSG_FREE:
 *     (*xrFree)()
 *     XUnmapWindow()   - XLib.c
 *     XrInput()        - input.c
 *     XDestroyWindow() - XLib
 *
 *   MSG_MOVE:
 *     XQueryWindow()   - XLib
 *     XMoveWindow()    - XLib
 *
 *   MSG_RESIZE:
 *     XChangeWindow()  - XLib
 *
 *   MSG_HIDE:
 *     XUnmapWindow()   - XLib
 *
 *   MSG_SHOW:
 *     XSelectInput()   - XLib
 *     XMapWindow()     - XLib
 *     XrEditor()       - editor.c
 *     XFlush()         - XLib
 *
 *   MSG_REDRAW:
 *     XrEditor()       - editor.c
 *     XFlush()         - XLib
 *
 *   MSG_NEWSUBPANEL:
 *     (* xrFree)()
 *     (* xrMalloc)()
 *     XrEditorGroup()  - group.c
 *
 *   MSG_FREESUBPANEL:
 *     XrEditorGroup()  - group.c
 *     (* xrFree)()
 *
 *   MSG_SHOWSUBPANEL:
 *     XrEditorGroup()  - group.c
 *
 *   MSG_HIDESUBPANEL:
 *     XrEditorGroup()  - group.c
 *  
 *     
 *     
 *
 *************************************<->***********************************/



xrPanel * 
XrPanel (panelInstance, message, data)
register xrPanel   * panelInstance;
INT32       message;
INT8      * data;
 
{

  /******************************************************************
   *
   *   Process the messages sent to the panel manager.
   *
   ******************************************************************/


   switch (message) {

   case MSG_NEW:
   {
      register xrPanel           * pnlInstance;
      register INT32               i;
      register xrPanelInfo       * pnlInfo;
               xrEditorTemplate  * currentTemplate;
               xrWindowData        pnlWindowData;
               xrPanelField      * tmpFieldPtr;


      /*  coerce data to proper type for MSG_NEW  */
      pnlInfo = (xrPanelInfo *) data; 

      /*  validate panel infomation pointer      */
      if ( pnlInfo == NULL ) {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }

      if (pnlInfo -> numFields == 0)
      {
         xrErrno = XrINVALIDPARM;
         return ((xrPanel *) NULL);
      }


      /* malloc space for the panel structure   */
      if ((pnlInstance = (xrPanel *) (*xrMalloc)(sizeof(xrPanel))) == NULL) {
         xrErrno = XrOUTOFMEM;
         return ((xrPanel *) NULL);
      }

      if ((pnlInstance -> subPanel = 
        (xrPanel **) (*xrMalloc)(sizeof(xrPanel *) * XrMAXSUBPANELS)) 
        == NULL)
      {
         (* xrFree)(pnlInstance);
         xrErrno = XrOUTOFMEM;
         return ((xrPanel *) NULL);
      }

      if ((pnlInstance -> editorInstance = 
        (xrEditor **) (*xrMalloc)(sizeof(xrEditor *) * pnlInfo -> numFields)) 
        == NULL)
      {
         (* xrFree)(pnlInstance -> subPanel);
         (* xrFree)(pnlInstance);
         xrErrno = XrOUTOFMEM;
         return ((xrPanel *) NULL);
      }


      for (i=0; i < XrMAXSUBPANELS; i++)
      {
         pnlInstance -> subPanel[i] = NULL;
      }
      


      /***************************************************************
       *
       *   Fill out the panel structure created above by transferring
       *   the info structure information.
       *
       ****************************************************************/      

      /*  Set the relativeTo member of the new panel */

      if ((pnlInfo -> relativeTo) == NULL)
         pnlInstance -> relativeTo = RootWindow;
      else
         pnlInstance -> relativeTo = pnlInfo -> relativeTo;

      /*  Set the new panel's context pointer        */

      if (pnlInfo -> panelContext == NULL)
         pnlInstance ->panelContext  = &xrPanelContextDefaults;
      else
         pnlInstance -> panelContext = pnlInfo -> panelContext;


       /* Copy the number of fields, panelId         */
       /* into the new panel structure.              */

       pnlInstance -> numFields = pnlInfo -> numFields;
       pnlInstance -> panelId = pnlInfo -> panelId;




       
       /* create the window for the panel, it will have */
       /* a bogus size at first.                        */

       if ( (pnlInstance -> panelWindow = 
	     XCreateWindow(RootWindow, 
	                   pnlInfo -> panelOrigin.x,
		           pnlInfo -> panelOrigin.y,
                           1,1,
                           pnlInstance -> panelContext -> borderWidth,
			   pnlInstance -> panelContext -> winForeground,
			   pnlInstance -> panelContext -> winBackground))
              == 0)
           {
              /* The X window create failed, free the  */
              /* panel instance, set errno, and return */

              (* xrFree) (pnlInstance -> subPanel);
              (* xrFree) (pnlInstance -> editorInstance);
              (* xrFree) (pnlInstance);
              xrErrno = XrXCALLFAILED;
              return ((xrPanel *) NULL);
           }
              

       XDefineCursor(pnlInstance -> panelWindow, 
                     pnlInstance -> panelContext -> cursor);

       /*  Set up dummy window to register panel window     */
       
       XrCopyRect(&xrZeroRect, &pnlInstance -> panelRect);
       XrCopyRect(&xrZeroRect, &pnlInstance -> panelZeroRect);
       XrCopyRect(&xrZeroRect, &pnlWindowData.windowRect);
       pnlWindowData.foreTile = pnlInstance -> panelContext -> winForeground;
       pnlWindowData.backTile = pnlInstance -> panelContext -> winBackground;


       if ((XrInput(pnlInstance -> panelWindow, 
            MSG_ADDWINDOW, 
            &pnlWindowData)) == FALSE)
          {
              (* xrFree) (pnlInstance);
              /* XrInput sets xrErrno */
              return ((xrPanel *) NULL);
          }





      /* the zeroth subpanel is the main panel */

      pnlInstance -> subPanel[0] = pnlInstance;
      pnlInstance -> numSubPanels = 1;
      pnlInstance -> editorGroup = XrEditorGroup(NULL, MSG_GETDEFAULTGROUP,
                                                 pnlInstance -> panelWindow);
       /*  Set up the editors in the registered window  */


       tmpFieldPtr = pnlInfo -> fieldList;
       for (i=0; i < pnlInfo -> numFields; i++) {
          currentTemplate = (xrEditorTemplate *) 
                            (tmpFieldPtr -> editorData);
          currentTemplate -> editorWindowId = pnlInstance -> panelWindow;
          tmpFieldPtr -> editorInstance = ( * tmpFieldPtr -> editorFunct)
                                          (NULL, MSG_NEW, currentTemplate);
          pnlInstance -> editorInstance[i] = tmpFieldPtr -> editorInstance;
          tmpFieldPtr++;
       }

       /* If width or height is 0, determine the size of the panel */
       /* Otherwise, use the size passed in in the info structure. */

       if ((pnlInfo -> panelSize.width == 0) || 
           (pnlInfo -> panelSize.height == 0))
       {
          tmpFieldPtr = pnlInfo -> fieldList;
          for (i=0; i < pnlInfo -> numFields; i++)
          {
          currentTemplate = (xrEditorTemplate *) 
                            (tmpFieldPtr -> editorData);
          XrUnionRect(&pnlInstance -> panelRect,
                      &currentTemplate -> editorRect,
                      &pnlInstance -> panelRect);
          tmpFieldPtr++;
          }
          pnlInstance -> panelRect.height += 
             (pnlInstance -> panelContext -> fontInfo ->width) * 2;
          pnlInstance -> panelRect.width += 
             (pnlInstance -> panelContext -> fontInfo ->width) * 2;

       }
       else
       {
          pnlInstance -> panelRect.height = pnlInfo -> panelSize.height;
          pnlInstance -> panelRect.width = pnlInfo -> panelSize.width;
       }

      /* set the real window size, location etc....  */

      pnlWindowData.windowRect.width = pnlInstance -> panelRect.width;
      pnlWindowData.windowRect.height = pnlInstance -> panelRect.height;
      pnlInstance -> panelZeroRect.width = pnlInstance -> panelRect.width;
      pnlInstance -> panelZeroRect.height = pnlInstance -> panelRect.height;

      XChangeWindow(pnlInstance -> panelWindow, 
                    pnlInstance -> panelRect.width,
                    pnlInstance -> panelRect.height);

      /* Set up location and size of the panel rectangle  */

      XrOffsetRect(&pnlInstance -> panelRect,
                   pnlInfo->panelOrigin.x,
                   pnlInfo->panelOrigin.y);

      XrInput(pnlInstance -> panelWindow, MSG_SETWINDOWDATA, &pnlWindowData);
      XrInput(pnlInstance -> panelWindow, MSG_CLEARPROCESSFLAG, 
             (INT8 *) XrEditor);

      if (pnlInstance -> panelContext -> showFlag)
      {
         XMapWindow(pnlInstance -> panelWindow);
         /* set the select mask. Should this be in globals?  */
   
         XrEditor(pnlInstance -> panelWindow, 
                  MSG_REDRAW, &pnlInstance -> panelZeroRect);
         XFlush();

         if (pnlInstance -> panelContext -> initFunct)
            (* pnlInstance -> panelContext ->initFunct)();

      }
   
      XSelectInput(pnlInstance -> panelWindow,
               KeyPressed | ButtonPressed | ButtonReleased | ExposeWindow
               | EnterWindow | LeaveWindow );



      /* return the panel instance created */
      return (pnlInstance);
      break;
   }




    case MSG_EDIT:
    {
       register xrEvent * returnEvent;
       register INT32     i,ii,editorIndex;
       register xrPanel          * currentPanel;
                xrEvent   currentEvent;
       struct   timeval   panelTime;
       struct   timeval   savedTime;
       xrEditor         * currentEd;


      /*  coerce data to proper type for MSG_EDIT  */
      returnEvent = (xrEvent *) data; 


      /*  validate panel infomation pointer      */
      if ( (returnEvent == NULL) || (panelInstance == NULL) ) {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }

       if(!panelInstance -> panelContext -> showFlag)
       {
         xrErrno = XrINVALIDPARM;
         return ((xrPanel *) NULL);
       }

      /* Set the process flag so editors will be called on a hot read */

      XrInput(panelInstance -> panelWindow, MSG_SETPROCESSFLAG, 
             (INT8 *) XrEditor);


      /* Set up the timer if it is set  */

       if (panelInstance -> panelContext -> timer > -1)
       {
          panelTime.tv_sec = panelInstance -> panelContext -> timer;
          panelTime.tv_usec = 0;
          XrInput(NULL, MSG_GETTIMEOUT, &savedTime);
          XrInput(NULL, MSG_SETTIMEOUT, &panelTime);
       }




       /*  Set up the panel event to return                   */

       returnEvent -> type = XrXRAY;
       returnEvent -> source = panelInstance -> panelWindow;
       returnEvent -> inputType = XrPANEL;
       returnEvent -> inputCode = -1;
       returnEvent -> value1 = 0;
       returnEvent -> value2 = -1;
       returnEvent -> value3 = -1;
       returnEvent -> valuePtr = (INT32) panelInstance;


       /* Activate the current editor if one is specified     */

       if ((currentEd = panelInstance -> panelContext -> currentEditor)
            != NULL)
       {
           (* currentEd -> editorFunct)(currentEd, MSG_ACTIVATE, NULL);
       }

       /*  do a read to get input from the panel              */


       if (XrInput(NULL, MSG_BLKHOTREAD, &currentEvent))
       {
          if((currentEvent.type & XrXRAY) && 
             (currentEvent.inputType == XrEDITOR) &&
             (currentEvent.value1 == XrUNKNOWN_EVENT))
          {
             panelInstance -> panelContext -> currentEditor =
                 (xrEditor *) currentEvent.valuePtr;
             XrInput(NULL, MSG_PEEKEVENT, &currentEvent);
          }
          else
          {
             XrInput(NULL, MSG_PUSHEVENT, &currentEvent);
          }

          if(currentEvent.type == ExposeWindow)
          {
             if (currentEvent.source == panelInstance -> panelWindow)
             {
                XrEditor(panelInstance -> panelWindow, 
                     MSG_REDRAW, &panelInstance -> panelZeroRect);
             }

          }
          if((currentEvent.type & XrXRAY) && 
             (currentEvent.inputType == XrEDITOR))

          /* find the index of the editor edited              */
          /* loop through the main panel and subpanels (if any) */
          /* until the editor is found.                       */
          { 

             editorIndex = -1;
             for(i=0; i<XrMAXSUBPANELS; i++)
             {
                if(currentPanel = panelInstance -> subPanel[i])
                {
                   for(ii=0; ii < currentPanel -> numFields; ii++)
                   {
                      if(currentPanel -> editorInstance[ii] ==
                         (xrEditor *) currentEvent.valuePtr)
                      {
                         editorIndex = ii;
                         break;
                      }
                    }
                    if(editorIndex != -1)
                       break;
                 }
              }

            
              /* If the editor index was found, return it.     */

              if (editorIndex > -1)
              {
                  returnEvent -> inputCode = XrPANELEDITOR;
                  returnEvent -> value2 = currentPanel -> panelId;
                  returnEvent -> value3 = editorIndex;
               }
               else
               {
                  returnEvent -> inputCode = XrPANELINPUT;
                  returnEvent -> value2 = panelInstance -> panelId;
               }

          }

          /* Event was not editor, set return event accordingly */
          else
          {
             returnEvent -> inputCode = XrPANELINPUT;
             returnEvent -> value2 = panelInstance -> panelId;

          }

       /*  XrInput failed: timer timed out                    */
       }
       else
       {
          returnEvent -> inputCode = XrPANELTIMER;
          returnEvent -> value2 = panelInstance -> panelId;

       }


       /* Reset the timer to the value when MSG_EDIT was entered. */

       if (panelInstance -> panelContext -> timer > -1)
       {
          XrInput(NULL, MSG_SETTIMEOUT, &savedTime);
       }

      XrInput(panelInstance -> panelWindow, MSG_CLEARPROCESSFLAG, 
             (INT8 *) XrEditor);

       return((xrPanel *) TRUE);
       break;

   }

   case MSG_SIZE:
   {
      register INT32               i;
      register xrPanelInfo       * pnlInfo;
               xrEditorTemplate  * currentTemplate;
               xrPanelField      * tmpFieldPtr;
               RECTANGLE           sizeRect;
               xrPanelContext    * sizeContext;


      /*  coerce data to proper type for MSG_SIZE  */
      pnlInfo = (xrPanelInfo *) data; 

      /*  validate panel infomation pointer      */
      if ( pnlInfo == NULL ) {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }

      if (pnlInfo -> numFields == 0)
      {
         xrErrno = XrINVALIDPARM;
         return ((xrPanel *) NULL);
      }

       if(pnlInfo -> panelContext == NULL)
          sizeContext = &xrPanelContextDefaults;
       else
          sizeContext = pnlInfo -> panelContext;

       XrCopyRect(&xrZeroRect, &sizeRect);

       tmpFieldPtr = pnlInfo -> fieldList;
       for (i=0; i < pnlInfo -> numFields; i++)
       {
       currentTemplate = (xrEditorTemplate *) 
                         (tmpFieldPtr -> editorData);
       XrUnionRect(&sizeRect,
                   &currentTemplate -> editorRect,
                   &sizeRect);
       tmpFieldPtr++;
       }

       sizeRect.height += (sizeContext -> fontInfo ->width) * 2;
       sizeRect.width += (sizeContext -> fontInfo ->width) * 2;

       pnlInfo -> panelSize.height = sizeRect.height;
       pnlInfo -> panelSize.width = sizeRect.width;

     return((xrPanel *) TRUE);


   }


    case MSG_FREE:
    {
      register INT32     keepWindow, i;
      xrPanel          * currentPanel;

      /*  coerce data to proper type for MSG_FREE  */
      keepWindow = (INT32) data; 


      /*  validate panel infomation pointer      */
      if (panelInstance == NULL) {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }

       /* remove the space created for any subpanels */
       /* The first panel is always the main panel.  */


       for(i=1; i<XrMAXSUBPANELS; i++)
       {
          if(currentPanel = panelInstance -> subPanel[i])
          {
             (*xrFree) (currentPanel -> editorInstance);
             (*xrFree) (currentPanel);
          }
       }

       /* Free the main panel    */

       (*xrFree) (panelInstance -> editorInstance);
       (*xrFree) (panelInstance -> subPanel);
       (*xrFree) (panelInstance);

       /* check to see if the window and its editors should  */
       /* be kept around.                                    */

       if (keepWindow)
       {
         return ((xrPanel * ) TRUE);
       }

       XUnmapWindow(panelInstance -> panelWindow);
       XrInput(panelInstance -> panelWindow, MSG_REMOVEWINDOW, NULL);
       XDestroyWindow(panelInstance -> panelWindow);

       return ((xrPanel *) TRUE);
       break;
    }


    case MSG_MOVE:
    {
      register  POINT       * newPoint;
                WindowInfo    panelWinInfo;


      /*  coerce data to proper type for MSG_MOVE  */
      newPoint = (POINT *) data; 


      /*  validate panel infomation pointer      */
      if ( (newPoint == NULL) || (panelInstance == NULL) ) {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }

      /* get the origin of relativTo window       */

      if (!(XQueryWindow(panelInstance -> relativeTo, &panelWinInfo)))
      {
         xrErrno = XrXCALLFAILED;
         return ((xrPanel *) NULL);
      }

      /* set the new origin of the panel then add the */
      /* new point passed in.                         */

      panelInstance -> panelRect.x = panelWinInfo.x + newPoint -> x;
      panelInstance -> panelRect.y = panelWinInfo.y + newPoint -> y;

      XMoveWindow(panelInstance -> panelWindow,
                  panelInstance -> panelRect.x,
                  panelInstance -> panelRect.y);

      return ((xrPanel *) TRUE);
      break;

   }

    case MSG_RESIZE:
    {
      register  RECTANGLE       * newSize;

      /*  coerce data to proper type for MSG_RESIZE  */
      newSize = (RECTANGLE *) data; 


      /*  validate panel infomation pointer      */
      if ( (newSize == NULL) || (panelInstance == NULL) ) {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }

      panelInstance -> panelRect.x = newSize -> x;
      panelInstance -> panelRect.y = newSize -> y;

      panelInstance -> panelRect.height = newSize -> height;
      panelInstance -> panelRect.width = newSize -> width;

      panelInstance -> panelZeroRect.height = newSize -> height;
      panelInstance -> panelZeroRect.width = newSize -> width;

      XUnmapWindow(panelInstance -> panelWindow);
      XMoveWindow(panelInstance -> panelWindow,
                  panelInstance -> panelRect.x,
                  panelInstance -> panelRect.y);


      XChangeWindow(panelInstance -> panelWindow,
                  panelInstance -> panelRect.width,
                  panelInstance -> panelRect.height);
      XMapWindow(panelInstance -> panelWindow);

      return ((xrPanel *) TRUE);
      break;

   }



    case MSG_HIDE:
    {

      /*  validate panel infomation pointer      */
      if (panelInstance == NULL) {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }

       if (panelInstance -> panelContext -> showFlag)
       {
          XUnmapWindow(panelInstance -> panelWindow);
       }

       panelInstance -> panelContext -> showFlag = FALSE;
       return((xrPanel *) TRUE);
       break;

     }


    case MSG_SHOW:
    {

      /*  validate panel infomation pointer      */
      if (panelInstance == NULL) {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }

      XSelectInput(panelInstance -> panelWindow,NULL);


       if ( ! (panelInstance -> panelContext -> showFlag))
       {
          XMapWindow(panelInstance -> panelWindow);
          XrEditor(panelInstance -> panelWindow, 
                   MSG_REDRAW, &panelInstance -> panelZeroRect);
       XFlush();

       if (panelInstance -> panelContext -> initFunct)
            (* panelInstance -> panelContext ->initFunct)();
       }

      XSelectInput(panelInstance -> panelWindow,
               KeyPressed | ButtonPressed | ButtonReleased | ExposeWindow
               | EnterWindow | LeaveWindow );

       panelInstance -> panelContext -> showFlag = TRUE;
       return((xrPanel *) TRUE);
       break;

    }

    case MSG_REDRAW:
    {

      /*  validate panel infomation pointer      */
      if (panelInstance == NULL) {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }

      XrEditor(panelInstance -> panelWindow, 
               MSG_REDRAW, &panelInstance -> panelZeroRect);
      XFlush();

       return((xrPanel *) TRUE);
       break;
     }



    case MSG_GETPANELCONTEXT:
    {
       register xrPanelContext  * returnContext;


      /*  coerce data to proper type for MSG_GETPANELCONTEXT  */
      returnContext = (xrPanelContext *) data; 


      /*  validate panel infomation pointer      */
      if (  returnContext == NULL ) {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }


       returnContext -> borderWidth = xrPanelContextDefaults.borderWidth;
       returnContext -> winBackground = xrPanelContextDefaults.winBackground;
       returnContext -> winForeground = xrPanelContextDefaults.winForeground;
       returnContext -> foregroundColor = 
                      xrPanelContextDefaults.foregroundColor;
       returnContext -> backgroundColor = 
                      xrPanelContextDefaults.backgroundColor;
       returnContext -> fontInfo = 
                      xrPanelContextDefaults.fontInfo;
       returnContext -> cursor = 
                      xrPanelContextDefaults.cursor;


       returnContext -> showFlag = xrPanelContextDefaults.showFlag;
       returnContext -> currentEditor = xrPanelContextDefaults.currentEditor;
       returnContext -> timer = xrPanelContextDefaults.timer;
       returnContext -> initFunct = xrPanelContextDefaults.initFunct;

       return ((xrPanel *) TRUE);
       break;
     }


   case MSG_CURRENTEDITOR:

      /*  validate panel infomation pointer      */
      if (panelInstance == NULL) {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }

      panelInstance -> panelContext -> currentEditor = (xrEditor *) data; 
      return ((xrPanel *) TRUE);
      break;




   case MSG_NEWSUBPANEL:
   {
      register xrPanelInfo       * subInfo;
      register xrPanel           * subInstance;
      register INT32               i;
               xrEditorTemplate  * currentTemplate;
               xrPanelField      * tmpFieldPtr;


      /*  validate panel infomation pointer      */
      if ( panelInstance == NULL ) 
      {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }

      if(panelInstance -> numSubPanels + 1 > XrMAXSUBPANELS)
      {
         xrErrno = XrOUTOFMEM;
         return ((xrPanel *) NULL);
       }


      /*  coerce data to proper type for MSG_NEW  */
      subInfo = (xrPanelInfo *) data; 


      /*  validate panel infomation pointer      */
      if (subInfo == NULL ) {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }

      if ((subInstance = 
          (xrPanel *) (*xrMalloc)(sizeof(xrPanel))) == NULL)
      {
         xrErrno = XrOUTOFMEM;
         return ((xrPanel *) NULL);
      }

      if ((subInstance -> editorInstance = 
        (xrEditor **) (*xrMalloc)(sizeof(xrEditor *) * subInfo -> numFields)) 
        == NULL)
      {
         (* xrFree)(subInstance);
         xrErrno = XrOUTOFMEM;
         return ((xrPanel *) NULL);
      }


      /***************************************************************
       *
       *   Fill out the subpanel structure created above by transferring
       *   the info structure information.
       *
       ****************************************************************/      



       /* Copy the number of fields, panelId         */
       /* into the new panel structure.              */

       subInstance -> numFields = subInfo -> numFields;
       subInstance -> panelId = subInfo -> panelId;
       subInstance -> panelWindow = panelInstance -> panelWindow;
       


       subInstance -> editorGroup = 
                 XrEditorGroup(NULL, MSG_NEW, subInstance -> panelWindow);
       

       tmpFieldPtr = subInfo -> fieldList;
       for (i=0; i < subInfo -> numFields; i++) {
          currentTemplate = (xrEditorTemplate *) 
                            (tmpFieldPtr -> editorData);
          currentTemplate -> editorWindowId = subInstance -> panelWindow;
          tmpFieldPtr -> editorInstance = ( * tmpFieldPtr -> editorFunct)
                                          (NULL, MSG_NEW, currentTemplate);
          subInstance -> editorInstance[i] = tmpFieldPtr -> editorInstance;
          tmpFieldPtr++;
       }

       panelInstance -> numSubPanels++;
       for(i=0; i < XrMAXSUBPANELS; i++)
       {
         if(!panelInstance -> subPanel[i])
            panelInstance -> subPanel[i] = subInstance;
       }



      /* return the panel instance created */
      return (subInstance);
      break;
   }

    case MSG_FREESUBPANEL:
    {
      register xrPanel *  subInstance;
      register INT32      panelFound;
      register INT32      i;

      /*  validate panel infomation pointer      */
      if ( panelInstance == NULL ) 
      {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }


      if((subInstance = (xrPanel *) data) == NULL)
      {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }

       panelFound = 0;
       for (i = 0; i < XrMAXSUBPANELS; i++)
       {
          if(panelInstance -> subPanel[i] == subInstance)
          {
             panelInstance -> subPanel[i] = NULL;
             panelFound = 1;
             break;
          }
       }

       if(! panelFound)
        {
          xrErrno = XrINVALIDPTR;
          return((xrPanel *) NULL);
        }

       XrEditorGroup(subInstance -> editorGroup, MSG_FREE, NULL);
       (*xrFree) (subInstance -> editorInstance);
       (*xrFree) (subInstance);
       panelInstance -> numSubPanels--;
       return((xrPanel *) TRUE);

       break;
     }


    case MSG_SHOWSUBPANEL:
      {
      register xrPanel *  subInstance;
      register INT32      panelFound;
      register INT32      i;

      /*  validate panel infomation pointer      */
      if ( panelInstance == NULL ) 
      {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }


      if((subInstance = (xrPanel *) data) == NULL)
      {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }

       panelFound = 0;
       for (i = 0; i < XrMAXSUBPANELS; i++)
       {
          if(panelInstance -> subPanel[i] == subInstance)
          {
             panelFound = 1;
             break;
          }
       }

       if(!panelFound)
       {
          xrErrno = XrINVALIDPTR;
          return((xrPanel *) NULL);
       }

       XrEditorGroup(subInstance -> editorGroup, MSG_SETSTATE, 
                     XrSENSITIVE | XrVISIBLE);

       return((xrPanel *) TRUE);
       break;
       }


    case MSG_HIDESUBPANEL:
    {

      register xrPanel *  subInstance;
      register INT32      panelFound;
      register INT32      i;

      /*  validate panel infomation pointer      */
      if ( panelInstance == NULL ) 
      {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }


      if((subInstance = (xrPanel *) data) == NULL)
      {
         xrErrno = XrINVALIDPTR;
         return ((xrPanel *) NULL);
       }

       panelFound = 0;
       for (i = 0; i < XrMAXSUBPANELS; i++)
       {
          if(panelInstance -> subPanel[i] == subInstance)
          {
             panelFound = 1;
             break;
          }
       }

       if(!panelFound)
       {
          xrErrno = XrINVALIDPTR;
          return((xrPanel *) NULL);
       }

       XrEditorGroup(subInstance -> editorGroup, MSG_SETSTATE, NULL);

       return((xrPanel *) TRUE);
       break;
       }

    default:
      xrErrno = XrINVALIDMSG;
      return((xrPanel *) NULL);
   }
   return((xrPanel *) NULL);
}

