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

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

#include <Xr/xr-copyright.h>

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

static char rcsid[] = "$Header: MsgBox.c,v 1.1 86/12/17 08:58:39 swick Exp $";
/*************************************<+>*************************************
 *****************************************************************************
 **
 **   File:        MsgBox.c
 **
 **   Project:     X-ray Toolbox
 **
 **   Description: X-ray Toolbox message box manager.
 **
 **
 **
 **   ------------------------ MODIFICATION RECORD   ------------------------
 *
 * $Log:	MsgBox.c,v $
 * Revision 1.1  86/12/17  08:58:39  swick
 * Initial revision
 * 
 * Revision 7.0  86/11/13  08:30:07  08:30:07  ed ()
 * Final QA release
 * 
 * Revision 6.0  86/11/10  15:34:32  15:34:32  ed ()
 * QA #2 release
 * 
 * Revision 5.4  86/11/10  15:33:52  15:33:52  ed ()
 * Removed reference to time.h
 * 
 * Revision 5.3  86/11/07  13:57:40  13:57:40  ed ()
 * Added procedure headers, new copyright.
 * 
 * Revision 5.2  86/11/06  12:00:19  12:00:19  ed ()
 * Fixed:  Message boxes account for imbedded newlines etc.
 *        Now return FALSE on failure.
 * 
 * Revision 5.1  86/10/30  12:46:33  12:46:33  ed ()
 * Fixed:  Border width for buttons.
 *         Enhanced check for raster height and width.
 *         Fixed error messages returned by message box manager.
 * 
 * Revision 5.0  86/10/28  08:28:00  08:28:00  ed ()
 * QA #1.1 release
 * 
 * Revision 4.1  86/10/26  15:43:54  15:43:54  ed ()
 * Added editor placement heuristic, prepared for QA release.
 * 
 * Revision 4.0  86/10/20  12:17:24  12:17:24  ed ()
 * QA #1 release
 * 
 * Revision 3.0  86/10/02  16:01:22  16:01:22  ed ()
 * Alpha Release set to 3.0
 * 
 * Revision 1.4  86/09/29  19:46:29  19:46:29  ed ()
 * Added panel size (currently uses panel default).
 * 
 * Revision 1.3  86/09/29  08:45:36  08:45:36  ed ()
 * Changed structure name to match types.h
 * 
 * Revision 1.2  86/09/24  19:03:04  19:03:04  ed ()
 * Updated to use new style push buttons.
 * 
 * 
 * Revision 1.1  86/09/14  15:00:25  15:00:25  ed ()
 * Initial revision
 * 
 *****************************************************************************
 *************************************<+>*************************************/




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


/*************************************<->*************************************
 *
 *  XrMessageBox(msgInfo, message, data)
 *
 *     xrMsgBoxInfo   * msgInfo;
 *     INT32            message;
 *     INT8           * data;
 *
 *   Description:
 *   -----------
 *     This is the message box manager.  It takes an xrMessageBox info 
 *     structure and creates a panel with any combination of a static
 *     raster, static text, and push button editor.  The message box 
 *     exits when the user presses a keyboard key, presses a push button
 *     or the panel timer (if set) times out.
 *
 *
 *   Inputs:
 *   ------
 *     msgInfo = This is a pointer to an xrMessageBox information
 *               structure.  It contains the information used to
 *               create the editors used in the message box and the
 *               message box itself.
 *
 *     message = Contains either MSG_EDIT, or MSG_SIZE.
 *
 *     data    = A pointer to an xrEvent structure or a rectangle
 *               structure depending on the message sent.
 *
 * 
 *   Outputs:
 *   -------
 *     TRUE    = Returned if the dialog with the user is successful.
 *
 *     FALSE   = Returned if the message box could not be created or
 *               sized.
 *
 *     data    = With MSG_NEW
 *
 *   Procedures Called
 *   -----------------
 *      XrPanel()        - panelmgr.c
 *      XrStaticRaster() - SRaster.c
 *      XrStaticText()   - StaticText.c
 *      XrPushButton()   - PushButton.c
 *      XrCopyPt()       - calc.c
 *      XrInput()        - input.c
 *
 *************************************<->***********************************/


INT32
XrMessageBox (msgInfo, message, data)

register xrMsgBoxInfo   * msgInfo;
         INT32           message;
         INT8           * data;
 
{
   xrStaticRasterInfo      msgRaster;
   xrStaticTextInfo        msgText;
   xrPushButtonInfo        msgButtons;
   xrPanelContext          msgContext;
   RECTANGLE             * msgRect;
   register xrEvent      * msgEvent;

   xrPanelField       msgFields[3];
   INT32              numMsgFields;
   xrPanelInfo        msgPanelInfo;
   xrPanel          * msgPanel;
   xrEvent            msgPanelEvent, msgEditorEvent;
   register INT32     horizPad, vertPad, editorX, editorY, editMessageBox;
   INT32              maxHeight;
   INT32              lineWidth;
   INT32              i, currenti, strLength;

   /*  validate message box information pointer              */
   if (msgInfo == NULL) {
      xrErrno = XrINVALIDPTR;
      return(FALSE);
   }

   if (data == NULL) {
      xrErrno = XrINVALIDPTR;
      return(FALSE);
   }

   if((msgInfo -> messageButtons) && (msgInfo -> numButtons < 1))
   {
      xrErrno = XrINVALIDPARM;
      return(FALSE);
   }

   if((msgInfo -> rasterId) && (msgInfo -> rasterHeight < 1 ||
                                msgInfo -> rasterWidth < 1))
   {
      xrErrno = XrINVALIDPARM;
      return(FALSE);
   }


   switch(message)
   {
      case MSG_EDIT:
         msgEvent = (xrEvent *) data;
         break;

      case MSG_SIZE:
         msgRect = (RECTANGLE *) data;
         break;

      default:
         xrErrno = XrINVALIDMSG;
         return(FALSE);

    }

   /*  Copy the message context into a local context so that  */
   /*  only valid message box parameters will be used.        */

   XrPanel(NULL, MSG_GETPANELCONTEXT, &msgContext);

   if (msgInfo -> messageContext)
   {
      msgContext.winBackground = 
               msgInfo -> messageContext -> winBackground;
      msgContext.winForeground = 
               msgInfo -> messageContext -> winForeground;
      msgContext.borderWidth = msgInfo -> messageContext -> borderWidth;
      msgContext.foregroundColor =
               msgInfo -> messageContext -> foregroundColor;
      msgContext.backgroundColor =
               msgInfo -> messageContext -> backgroundColor;
      msgContext.fontInfo = msgInfo -> messageContext -> fontInfo;
      msgContext.cursor = msgInfo -> messageContext -> cursor;
      msgContext.timer = msgInfo -> messageContext -> timer;
      msgContext.initFunct = msgInfo -> messageContext -> initFunct;
    }

   /********************************************************
    *  
    *  Prepare the editors to be used in the message
    *  box manager.
    *
    ********************************************************/

    lineWidth = msgContext.fontInfo -> height/8;

    numMsgFields = 0;

    if (msgInfo -> rasterId)
    {
       msgRaster.editorRect.x = 0;
       msgRaster.editorRect.y = 0;
       msgRaster.editorState = XrVISIBLE;
       msgRaster.editorFGColor = msgContext.foregroundColor;
       msgRaster.editorBGColor = msgContext.backgroundColor;
       msgRaster.rasterHeight = msgInfo -> rasterHeight;
       msgRaster.rasterWidth = msgInfo -> rasterWidth;
       msgRaster.rasterId = msgInfo -> rasterId;

       if(XrStaticRaster(NULL, MSG_SIZE, &msgRaster)) {
          msgFields[numMsgFields].editorFunct = XrStaticRaster;
          msgFields[numMsgFields].editorData = (INT8 *) & msgRaster;
          numMsgFields++;
       }
     }


     if (msgInfo -> messageText)
     {
       
       INT32  tmpLength;


       strLength = strlen(msgInfo -> messageText);
       tmpLength = 0;
       currenti = 0;

       for (i=0; i < strLength; i++)
       {
          if((msgInfo -> messageText[i] <= 13) && 
             (msgInfo -> messageText[i] >= 10))
          {
             if((i - currenti) > tmpLength)
             {
                tmpLength = i - currenti;
             }
             currenti = i + 1;

          }
       }

       if ((i - currenti) > tmpLength)
          tmpLength = i - currenti;
       

       if (tmpLength < 35)
         msgText.editorRect.width = 
                 (tmpLength+1) * (msgContext.fontInfo ->width);
       else
         msgText.editorRect.width = 35 * (msgContext.fontInfo -> width);
       

       msgText.editorRect.x = 0;
       msgText.editorRect.y = 0;
       msgText.editorState = XrVISIBLE;
       msgText.editorFGColor = msgContext.foregroundColor;
       msgText.editorBGColor = msgContext.backgroundColor;
       msgText.editorFont = msgContext.fontInfo;
       msgText.string = msgInfo -> messageText;
       msgText.alignment = XrLEFT_ALIGNED;

       if (XrStaticText(NULL, MSG_SIZE, &msgText))
       {
          msgFields[numMsgFields].editorFunct = XrStaticText;
          msgFields[numMsgFields].editorData = (INT8 *) & msgText;
          numMsgFields++;
       }

      }

      if (msgInfo -> messageButtons) {

       msgButtons.editorRect.x = 0;
       msgButtons.editorRect.y = 0;
       msgButtons.editorState = (XrVISIBLE | XrSENSITIVE);
       msgButtons.editorFGColor = msgContext.foregroundColor;
       msgButtons.editorBGColor = msgContext.backgroundColor;
       msgButtons.editorFont = msgContext.fontInfo;
       msgButtons.numFields = msgInfo -> numButtons;
       msgButtons.numCols = 1;

       msgButtons.numCols = (msgInfo -> numButtons)/4;
       if((msgInfo -> numButtons) % 4)
          msgButtons.numCols++;
       msgButtons.defaultButton = 0;
       msgButtons.borderWidth = lineWidth;
       if(msgButtons.borderWidth == 0)
         msgButtons.borderWidth = 1;
       msgButtons.labels = msgInfo -> messageButtons;
       msgButtons.stateFlags = NULL;

       if(XrPushButton(NULL, MSG_SIZE, &msgButtons));
       {
          msgFields[numMsgFields].editorFunct = XrPushButton;
          msgFields[numMsgFields].editorData = (INT8 *) & msgButtons;
          numMsgFields++;
        }

       }


   /*******************************************************************
    *
    *  Determine the locations of the editors in the panel.
    *
    *******************************************************************/

    if (numMsgFields == 0)
    {
       xrErrno = XrINVALIDPARM;
       return(FALSE);
    }

    horizPad = msgContext.fontInfo -> width * 4;
    vertPad = msgContext.fontInfo -> width * 4;
    editorX = horizPad;
    editorY = vertPad;
    maxHeight = 0;

    if (msgInfo -> rasterId) {
       msgRaster.editorRect.x = editorX;
       msgRaster.editorRect.y = editorY;
       if (msgRaster.editorRect.height > maxHeight)
          maxHeight = msgRaster.editorRect.height;
       editorX += (msgRaster.rasterWidth + horizPad);
    }

    if (msgInfo -> messageText) {
       msgText.editorRect.x = editorX;
       msgText.editorRect.y = editorY;
       if (msgText.editorRect.height > maxHeight)
          maxHeight = msgText.editorRect.height;
       editorX += (msgText.editorRect.width + horizPad);
    }

    if (msgInfo -> messageButtons) {
       msgButtons.editorRect.x = editorX;
       msgButtons.editorRect.y = editorY;
       if (msgButtons.editorRect.height > maxHeight)
          maxHeight = msgButtons.editorRect.height;
       editorX += (msgButtons.editorRect.width + horizPad);
    }



    /********************************************************************
     *
     *  Set up the panel, create, and start it going.
     *
     ********************************************************************/

    if (message == MSG_EDIT)
    {
       msgPanelInfo.panelSize.height = maxHeight + (vertPad * 2);
       msgPanelInfo.panelSize.width = editorX;
    }
    else
    {
       msgRect -> y = 0;
       msgRect -> x = 0;
       msgRect -> height = maxHeight + (vertPad * 2);
       msgRect -> width = editorX;
       return(TRUE);
    }

    if (msgInfo -> rasterId)
    {
       msgRaster.editorRect.y = (msgPanelInfo.panelSize.height -
                                 msgRaster.editorRect.height) / 2;
    }

    if (msgInfo -> messageText)
    {
       msgText.editorRect.y = (msgPanelInfo.panelSize.height -
                                 msgText.editorRect.height) / 2;
    }

    if (msgInfo -> messageButtons)
    {
       msgButtons.editorRect.y = (msgPanelInfo.panelSize.height -
                                 msgButtons.editorRect.height) / 2;
    }



    XrCopyPt(& msgInfo -> messageOrigin, & msgPanelInfo.panelOrigin);
    /* set the size here */
    msgPanelInfo.relativeTo = msgInfo -> relativeTo;
    msgPanelInfo.panelContext = &msgContext;

    msgPanelInfo.fieldList = (xrPanelField *) msgFields;
    msgPanelInfo.numFields = numMsgFields;
    msgPanelInfo.panelId = 0;

    msgPanel = XrPanel(NULL, MSG_NEW, &msgPanelInfo);

    
    
    msgEvent -> type = XrXRAY;
    msgEvent -> inputType = XrMESSAGEBOX;


    editMessageBox = 1;
    while(editMessageBox)
    {
       XrPanel(msgPanel, MSG_EDIT, &msgPanelEvent);

       switch(msgPanelEvent.inputCode) {

       case XrPANELTIMER:
       {
          msgEvent -> inputCode = XrPANELTIMER;
          msgEvent -> value1 = -1;
          msgEvent -> value3 = -1;
          editMessageBox = 0;
          break;
        }

       case XrPANELEDITOR:
       {
          XrInput(NULL, MSG_NONBLKREAD, &msgEditorEvent);
          if ((msgEditorEvent.inputCode == XrPUSHBUTTON) &&
              (msgEditorEvent.value1))
          {
             msgEvent -> inputCode = XrPUSHBUTTON;
             msgEvent -> value1 = msgEditorEvent.value2;
             msgEvent -> value3 = msgEditorEvent.value2;
             editMessageBox = 0;
          }
          break;
        }

       case XrPANELINPUT:
       {
          XrInput(NULL, MSG_NONBLKREAD, &msgEditorEvent);
          if(msgEditorEvent.type == KeyPressed)
          {
             msgEvent -> inputCode = XrPUSHBUTTON;
             msgEvent -> value1 = 0;
             msgEvent -> value3 = 0;
             editMessageBox = 0;
          }
          break;
       }

       default:
          XrInput(NULL, MSG_NONBLKREAD, &msgEditorEvent);
          break;

    }   
    }


    XrPanel(msgPanel, MSG_FREE, NULL);
    return(TRUE);



}
