11ab64890Smrg/*
21ab64890Smrg
31ab64890SmrgCopyright 1989, 1998  The Open Group
41ab64890Smrg
51ab64890SmrgPermission to use, copy, modify, distribute, and sell this software and its
61ab64890Smrgdocumentation for any purpose is hereby granted without fee, provided that
71ab64890Smrgthe above copyright notice appear in all copies and that both that
81ab64890Smrgcopyright notice and this permission notice appear in supporting
91ab64890Smrgdocumentation.
101ab64890Smrg
111ab64890SmrgThe above copyright notice and this permission notice shall be included in
121ab64890Smrgall copies or substantial portions of the Software.
131ab64890Smrg
141ab64890SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
151ab64890SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
161ab64890SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
171ab64890SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
181ab64890SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
191ab64890SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
201ab64890Smrg
211ab64890SmrgExcept as contained in this notice, the name of The Open Group shall not be
221ab64890Smrgused in advertising or otherwise to promote the sale, use or other dealings
231ab64890Smrgin this Software without prior written authorization from The Open Group.
241ab64890Smrg
251ab64890Smrg*/
261ab64890Smrg
271ab64890Smrg#ifdef HAVE_CONFIG_H
281ab64890Smrg#include <config.h>
291ab64890Smrg#endif
301ab64890Smrg#include "Xlibint.h"
311ab64890Smrg#include "Xutil.h"
321ab64890Smrg
331ab64890Smrgstatic int _GeometryMaskToGravity(
341ab64890Smrg    int mask);
351ab64890Smrg
361ab64890Smrg/*
371ab64890Smrg * This routine given a user supplied positional argument and a default
381ab64890Smrg * argument (fully qualified) will return the position the window should take
391ab64890Smrg * as well as the gravity to be set in the WM_NORMAL_HINTS size hints.
401ab64890Smrg * Always sets all return values and returns a mask describing which fields
411ab64890Smrg * were set by the user or'ed with whether or not the x and y values should
421ab64890Smrg * be considered "negative".
431ab64890Smrg */
441ab64890Smrg
451ab64890Smrgint
461ab64890SmrgXWMGeometry (
471ab64890Smrg    Display *dpy,			/* user's display connection */
481ab64890Smrg    int screen,				/* screen on which to do computation */
491ab64890Smrg    _Xconst char *user_geom,		/* user provided geometry spec */
501ab64890Smrg    _Xconst char *def_geom,		/* default geometry spec for window */
511ab64890Smrg    unsigned int bwidth,		/* border width */
521ab64890Smrg    XSizeHints *hints,			/* usually WM_NORMAL_HINTS */
531ab64890Smrg    int *x_return,			/* location of window */
541ab64890Smrg    int *y_return,			/* location of window */
551ab64890Smrg    int *width_return,			/* size of window */
561ab64890Smrg    int *height_return,			/* size of window */
571ab64890Smrg    int *gravity_return)		/* gravity of window */
581ab64890Smrg{
591ab64890Smrg    int ux, uy;				/* returned values from parse */
601ab64890Smrg    unsigned int uwidth, uheight;	/* returned values from parse */
611ab64890Smrg    int umask;				/* parse mask of returned values */
621ab64890Smrg    int dx, dy;				/* default values from parse */
631ab64890Smrg    unsigned int dwidth, dheight;	/* default values from parse */
641ab64890Smrg    int dmask;				/* parse mask of returned values */
651ab64890Smrg    int base_width, base_height;	/* valid amounts */
661ab64890Smrg    int min_width, min_height;		/* valid amounts */
671ab64890Smrg    int width_inc, height_inc;		/* valid amounts */
681ab64890Smrg    int rx, ry, rwidth, rheight;	/* return values */
691ab64890Smrg    int rmask;				/* return mask */
701ab64890Smrg
711ab64890Smrg    /*
721ab64890Smrg     * Get the base sizes and increments.  Section 4.1.2.3 of the ICCCM
731ab64890Smrg     * states that the base and minimum sizes are defaults for each other.
741ab64890Smrg     * If neither is given, then the base sizes should be 0.  These parameters
7561b2299dSmrg     * control the sets of sizes that window managers should allow for the
761ab64890Smrg     * window according to the following formulae:
771ab64890Smrg     *
781ab64890Smrg     *          width = base_width  + (i * width_inc)
791ab64890Smrg     *         height = base_height + (j * height_inc)
801ab64890Smrg     */
8161b2299dSmrg    base_width =  ((hints->flags & PBaseSize) ? hints->base_width :
821ab64890Smrg		   ((hints->flags & PMinSize) ? hints->min_width : 0));
831ab64890Smrg    base_height = ((hints->flags & PBaseSize) ? hints->base_height :
841ab64890Smrg		   ((hints->flags & PMinSize) ? hints->min_height : 0));
851ab64890Smrg    min_width = ((hints->flags & PMinSize) ? hints->min_width : base_width);
861ab64890Smrg    min_height = ((hints->flags & PMinSize) ? hints->min_height : base_height);
871ab64890Smrg    width_inc = (hints->flags & PResizeInc) ? hints->width_inc : 1;
881ab64890Smrg    height_inc = (hints->flags & PResizeInc) ? hints->height_inc : 1;
891ab64890Smrg
901ab64890Smrg
911ab64890Smrg    /*
921ab64890Smrg     * parse the two geometry masks
931ab64890Smrg     */
941ab64890Smrg    rmask = umask = XParseGeometry (user_geom, &ux, &uy, &uwidth, &uheight);
951ab64890Smrg    dmask = XParseGeometry (def_geom, &dx, &dy, &dwidth, &dheight);
961ab64890Smrg
971ab64890Smrg
981ab64890Smrg    /*
991ab64890Smrg     * get the width and height:
1001ab64890Smrg     *     1.  if user-specified, then take that value
1011ab64890Smrg     *     2.  else, if program-specified, then take that value
1021ab64890Smrg     *     3.  else, take 1
1031ab64890Smrg     *     4.  multiply by the size increment
1041ab64890Smrg     *     5.  and add to the base size
1051ab64890Smrg     */
10661b2299dSmrg    rwidth = ((((umask & WidthValue) ? uwidth :
1071ab64890Smrg		((dmask & WidthValue) ? dwidth : 1)) * width_inc) +
1081ab64890Smrg	      base_width);
10961b2299dSmrg    rheight = ((((umask & HeightValue) ? uheight :
11061b2299dSmrg		 ((dmask & HeightValue) ? dheight : 1)) * height_inc) +
1111ab64890Smrg	       base_height);
1121ab64890Smrg
1131ab64890Smrg    /*
1141ab64890Smrg     * Make sure computed size is within limits.  Note that we always do the
1151ab64890Smrg     * lower bounds check since the base size (which defaults to 0) should
1161ab64890Smrg     * be used if a minimum size isn't specified.
1171ab64890Smrg     */
1181ab64890Smrg    if (rwidth < min_width) rwidth = min_width;
1191ab64890Smrg    if (rheight < min_height) rheight = min_height;
1201ab64890Smrg
1211ab64890Smrg    if (hints->flags & PMaxSize) {
1221ab64890Smrg	if (rwidth > hints->max_width) rwidth = hints->max_width;
1231ab64890Smrg	if (rheight > hints->max_height) rheight = hints->max_height;
1241ab64890Smrg    }
1251ab64890Smrg
1261ab64890Smrg
1271ab64890Smrg    /*
1281ab64890Smrg     * Compute the location.  Set the negative flags in the return mask
1291ab64890Smrg     * (and watch out for borders), if necessary.
1301ab64890Smrg     */
1311ab64890Smrg    if (umask & XValue) {
1321ab64890Smrg	rx = ((umask & XNegative) ?
1331ab64890Smrg	      (DisplayWidth (dpy, screen) + ux - rwidth - 2 * bwidth) : ux);
1341ab64890Smrg    } else if (dmask & XValue) {
1351ab64890Smrg	if (dmask & XNegative) {
1361ab64890Smrg	    rx = (DisplayWidth (dpy, screen) + dx - rwidth - 2 * bwidth);
1371ab64890Smrg	    rmask |= XNegative;
13861b2299dSmrg	} else
1391ab64890Smrg	  rx = dx;
1401ab64890Smrg    } else {
1411ab64890Smrg	rx = 0;				/* gotta choose something... */
1421ab64890Smrg    }
1431ab64890Smrg
1441ab64890Smrg    if (umask & YValue) {
1451ab64890Smrg	ry = ((umask & YNegative) ?
1461ab64890Smrg	      (DisplayHeight(dpy, screen) + uy - rheight - 2 * bwidth) : uy);
1471ab64890Smrg    } else if (dmask & YValue) {
1481ab64890Smrg	if (dmask & YNegative) {
1491ab64890Smrg	    ry = (DisplayHeight(dpy, screen) + dy - rheight - 2 * bwidth);
1501ab64890Smrg	    rmask |= YNegative;
15161b2299dSmrg	} else
1521ab64890Smrg	  ry = dy;
1531ab64890Smrg    } else {
1541ab64890Smrg	ry = 0;				/* gotta choose something... */
1551ab64890Smrg    }
1561ab64890Smrg
1571ab64890Smrg
1581ab64890Smrg    /*
1591ab64890Smrg     * All finished, so set the return variables.
1601ab64890Smrg     */
1611ab64890Smrg    *x_return = rx;
1621ab64890Smrg    *y_return = ry;
1631ab64890Smrg    *width_return = rwidth;
1641ab64890Smrg    *height_return = rheight;
1651ab64890Smrg    *gravity_return = _GeometryMaskToGravity (rmask);
1661ab64890Smrg    return rmask;
1671ab64890Smrg}
1681ab64890Smrg
1691ab64890Smrg
1701ab64890Smrgstatic int _GeometryMaskToGravity(
1711ab64890Smrg    int mask)
1721ab64890Smrg{
1731ab64890Smrg    switch (mask & (XNegative|YNegative)) {
1741ab64890Smrg      case 0:
1751ab64890Smrg        return NorthWestGravity;
1761ab64890Smrg      case XNegative:
1771ab64890Smrg        return NorthEastGravity;
1781ab64890Smrg      case YNegative:
1791ab64890Smrg        return SouthWestGravity;
1801ab64890Smrg      default:
1811ab64890Smrg        return SouthEastGravity;
1821ab64890Smrg    }
1831ab64890Smrg}
184