/* @(#)center_vis.c	17.1 (ESO-IPG) 01/25/02 17:26:32 */
/*---------------------------------------------------------------------
 * $Date: 2003-06-04 14:49:18 $             $Revision: 1.1.1.1 $
 *---------------------------------------------------------------------
 * 
 *
 *             Copyright (c) 1992, Visual Edge Software Ltd.
 *
 * ALL  RIGHTS  RESERVED.  Permission  to  use,  copy,  modify,  and
 * distribute  this  software  and its documentation for any purpose
 * and  without  fee  is  hereby  granted,  provided  that the above
 * copyright  notice  appear  in  all  copies  and  that  both  that
 * copyright  notice and this permission notice appear in supporting
 * documentation,  and that  the name of Visual Edge Software not be
 * used  in advertising  or publicity  pertaining to distribution of
 * the software without specific, written prior permission. The year
 * included in the notice is the year of the creation of the work.
 *-------------------------------------------------------------------*/

/*---------------------------------------------------------------------
 * FILE:	center_vis.c
 *
 * CONTENTS:	
 *	widget placement utilities
 *		UxCenterVisibly
 *		UxCenterWidgetVisibly
 * 
 * Shared between design and runtime systems.
 *--------------------------------------------------------------------*/

#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include "valloc.h"
  
#ifdef	MOTIF_WIDGETS
#include <Xm/DialogS.h>
#include <Xm/BulletinB.h>
#endif /* MOTIF_WIDGETS */
 
#include "UxLib.h"
#include "global.h"
  
#include "unit.h"
#include "uimx_cat.h"
#include "misc1_ds.h"


/* X/OPEN message catalog macros. */
#define CGETS(ms,ds_ms)                 UxCatGets(MC_MISC1,ms,ds_ms)

/* Allowances made for decoration when ensuring that
 * widgets stay onscreen.
 */

#define DECORATION_X 10
#define DECORATION_Y 10


/*-----------------------------------------------------------------------------
 * GLOBAL
 *-----------------------------------------------------------------------------
 * NAME:	void	UxCenterWidgetVisibly (rs, parent)
 * INPUT:	swidget	rs		- swidget to center on
 *		swidget	parent		- swidget to move
 *
 * DESCRIPTION:	Center 'rs' under the cursor by moving 'parent'. If 'parent'
 * 		would have to be partly off the screen then 'parent' is moved
 * 		as far as possible on the screen, and if MOTIF widgets are
 *		NOT being used the cursor is warped to the center of 'rs'.
 *		
 * REVISON:	Last revision: bugfix 2605
 *-----------------------------------------------------------------------------*/

void UxCenterWidgetVisibly (child, parent)
     Widget	child;
     Widget	parent;
{
  Window	rp, wp;
  int		xoff, yoff;
  int		rx, ry, wx= 0, wy= 0;
  int		px, py;
  Position	x, y;
  Dimension	w, h, bw;
  unsigned char	unittype=0;
  Widget	widget;
  unsigned int  mask;
  
  /* Initialize offsets with center of child.
   */
  XtVaGetValues (child,
		 XmNwidth, &w,
  		 XmNheight, &h,
		 NULL);
  unittype = UxFindUnitType (child);
  UxConvertDimension (child, unittype, w, h, XmPIXELS, &w, &h);

  xoff = w / 2;
  yoff = h / 2;

  /* Add each containing widget offset until we reach parent.
   */
  
  widget = child;
  
  while (widget != parent) {
      if (( widget == NULL) || XtIsSubclass (widget, wmShellWidgetClass)) {
	  char    *msg_ptr;

	  msg_ptr = UxCopyString (CGETS(MS_MISC1_PARM_ERR, DS_MS_MISC1_PARM_ERR));
          UxStandardError (msg_ptr);
	  UxFree (msg_ptr);
	  return;
      }

      XtVaGetValues (widget,
		     XmNx, &x,
		     XmNy, &y,
		     XmNborderWidth, &bw,
		     NULL);
      unittype = UxFindUnitType (widget);

      if(!XtIsSubclass(widget, xmBulletinBoardWidgetClass)) {
	UxConvertPosition (widget, unittype, x, y, XmPIXELS, &x, &y);
        bw = XmConvertUnits (widget,XmHORIZONTAL,unittype,(int)bw,XmPIXELS);
      }

      xoff+= x + bw;
      yoff+= y + bw;
      
      widget = XtParent (widget);
  }
  
#ifdef MOTIF_WIDGETS
  /* If the parent is a XmDialogShell then its child will have
   * an X and Y position that are the same as that of the dialogShell.
   * In other words, we have to correct for the distance we already
   * subtracted (all other shell children have an X and Y of 0).
   */
  if (XtClass (parent) == xmDialogShellWidgetClass) {
      xoff -= (x+bw);
      yoff -= (y+bw);
  }
#endif /* MOTIF_WIDGETS */
  
  XQueryPointer (UxDisplay, UxRootWindow, &rp, &wp, 
		 &rx, &ry, 
		 &px, &py, 
		 &mask);
  
#if defined (UX_FORCE_CENTER_VISIBLY)
  {
      /* If the resources used to force the center of the parent
       * widget are set, use them instead. This makes it possible
       * to perform Automated testing with HP's Synergy Tool
       */
      XrmValue	resX, resY;
      char	*type;
      extern char *	UxProgramName;

      if (UxGetAnyResource(UxProgramName, 
	    "centerVisX", &type, &resX)  == True) {
	    rx = atoi(resX.addr);
      }
      if (UxGetAnyResource(UxProgramName, 
	    "centerVisY", &type, &resY)  == True) {
	    ry = atoi(resY.addr);
      }
  }
#endif

  rx -= xoff;
  ry -= yoff;
  
  /* rx and ry are our tentative coordinates for parent.
   * Make sure we don't put parent offscreen (even partially),
   * leaving margin all round for window decoration.
   * If we adjust rx or ry, we set wx or wy to the amount
   * we must warp the cursor so it shows up centered in rs.
   */

  XtVaGetValues (parent,
		 XmNwidth, &w,
		 XmNheight, &h,
		 NULL);
  unittype = UxFindUnitType (parent);
  UxConvertDimension (parent, unittype, w, h, XmPIXELS, &w, &h);

  
  if (rx-DECORATION_X < 0) {	
      wx = DECORATION_X - rx;
      rx = DECORATION_X;
  } else if (rx+w+DECORATION_X > DisplayWidth (UxDisplay, UxScreen)) {	
      wx = DisplayWidth (UxDisplay, UxScreen) - (rx + w);
      rx = DisplayWidth (UxDisplay, UxScreen) - (w + DECORATION_X);
  }
  
  if (ry-DECORATION_Y < 0) {	
      wy = DECORATION_Y - ry;
      ry = DECORATION_Y;
  } else if (ry+h+DECORATION_Y > DisplayHeight (UxDisplay,UxScreen)) {	
      wy = DisplayHeight (UxDisplay, UxScreen) - (ry + h);
      ry = DisplayHeight (UxDisplay, UxScreen) - (h + DECORATION_Y);
  }
  
#ifndef	MOTIF_WIDGETS
  if ((wy != 0) || (wx != 0)) {
      XWarpPointer (UxDisplay,UxRootWindow,UxRootWindow,
		    px,py,
		    DisplayWidth (UxDisplay,UxScreen), 
		    DisplayHeight (UxDisplay, UxScreen), 
		    wx+px, wy+py);
  }
#endif	/* MOTIF_WIDGETS */
  
  UxConvertPosition (parent, XmPIXELS, rx, ry, unittype, &x, &y);  

  XtVaSetValues (parent,
		 XmNx, x,
		 XmNy, y,
		 NULL);

#ifdef	OL_WIDGETS
  /* Set the window manager size hints to position shells properly.
   * These are obsolete in X11R4, but are needed for pre-R4 managers.
   * This code used to modify the parent WMShell size_hints member, 
   * but that struct is under the complete control of the WMShell 
   * implementation in Motif.
   * The code also used to set USSize hints, for no apparent reason.
   */

   if (XtIsSubclass (parent, wmShellWidgetClass)
       &&
       XtIsRealized (parent))
   {
       XSizeHints	size_hints;

       size_hints.x	= rx;
       size_hints.y	= ry;
       size_hints.flags	= USPosition;

       XSetNormalHints (UxDisplay, XtWindow (parent), &size_hints);
   }
#endif	/* OL_WIDGETS */
  
}

/*-----------------------------------------------------------------------------
 * GLOBAL
 *-----------------------------------------------------------------------------
 * NAME:	void	UxCenterVisibly (rs, parent)
 * INPUT:	swidget	*rs	- swidget to center on
 *		swidget	*parent	- ancestor to move
 *
 * DESCRIPTION:	
 * 	Center 'rs' under the cursor by moving 'parent'. If 'parent'
 *	would have to be partly off the screen then 'parent' is moved
 *	as far as possible to the edge of the screen, and if MOTIF
 *	widgets are NOT being used, the pointer is warped 
 *      to the center of 'rs'.
 *
 *      Last revision: bugfix 2605
 *---------------------------------------------------------------------------*/

void UxCenterVisibly (rs, parent)
     swidget	rs;
     swidget	parent;
{
  
#ifndef RUNTIME
  if (UxIsInvalidObject (rs, "UxCenterVisibly"))
    return;
  
  if (UxIsInvalidObject (parent, "UxCenterVisibly"))
    return;
#endif /* RUNTIME */
  
  UxCenterWidgetVisibly (UxGetWidget (rs), UxRealWidget (parent));
}

#ifndef RUNTIME

/* Alternate name used in UIMX interface code. */

UxCenter_visibly (rs, par)
     swidget	rs, par;
{
  UxCenterVisibly (rs, par);
}

#endif

