xenocara/app/fvwm/modules/FvwmButtons/misc.c

162 lines
3.8 KiB
C

/*
FvwmButtons v2.0.41-plural-Z-alpha, copyright 1996, Jarl Totland
* This module, and the entire GoodStuff program, and the concept for
* interfacing this module to the Window Manager, are all original work
* by Robert Nation
*
* Copyright 1993, Robert Nation. No guarantees or warantees or anything
* are provided or implied in any way whatsoever. Use this program at your
* own risk. Permission to use this program for any purpose is given,
* as long as the copyright is kept intact.
*/
#include "misc.h"
/**
*** ConstrainSize()
*** Adjust a given width and height to account for the constraints imposed by
*** size hints.
*** The general algorithm, especially the aspect ratio stuff, is borrowed from
*** uwm's CheckConsistency routine.
**/
void ConstrainSize (XSizeHints *hints, int *widthp, int *heightp)
{
#define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
int baseWidth, baseHeight;
int dwidth = *widthp, dheight = *heightp;
if(hints->flags & PMinSize)
{
minWidth = hints->min_width;
minHeight = hints->min_height;
if(hints->flags & PBaseSize)
{
baseWidth = hints->base_width;
baseHeight = hints->base_height;
}
else
{
baseWidth = hints->min_width;
baseHeight = hints->min_height;
}
}
else if(hints->flags & PBaseSize)
{
minWidth = hints->base_width;
minHeight = hints->base_height;
baseWidth = hints->base_width;
baseHeight = hints->base_height;
}
else
{
minWidth = 1;
minHeight = 1;
baseWidth = 1;
baseHeight = 1;
}
if(hints->flags & PMaxSize)
{
maxWidth = hints->max_width;
maxHeight = hints->max_height;
}
else
{
maxWidth = 10000;
maxHeight = 10000;
}
if(hints->flags & PResizeInc)
{
xinc = hints->width_inc;
yinc = hints->height_inc;
}
else
{
xinc = 1;
yinc = 1;
}
/*
* First, clamp to min and max values
*/
if (dwidth < minWidth) dwidth = minWidth;
if (dheight < minHeight) dheight = minHeight;
if (dwidth > maxWidth) dwidth = maxWidth;
if (dheight > maxHeight) dheight = maxHeight;
/*
* Second, fit to base + N * inc
*/
dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
/*
* Third, adjust for aspect ratio
*/
#define maxAspectX hints->max_aspect.x
#define maxAspectY hints->max_aspect.y
#define minAspectX hints->min_aspect.x
#define minAspectY hints->min_aspect.y
/*
* The math looks like this:
*
* minAspectX dwidth maxAspectX
* ---------- <= ------- <= ----------
* minAspectY dheight maxAspectY
*
* If that is multiplied out, then the width and height are
* invalid in the following situations:
*
* minAspectX * dheight > minAspectY * dwidth
* maxAspectX * dheight < maxAspectY * dwidth
*
*/
if (hints->flags & PAspect)
{
if (minAspectX * dheight > minAspectY * dwidth)
{
delta = makemult(minAspectX * dheight / minAspectY - dwidth,
xinc);
if (dwidth + delta <= maxWidth)
dwidth += delta;
else
{
delta = makemult(dheight - dwidth*minAspectY/minAspectX,
yinc);
if (dheight - delta >= minHeight) dheight -= delta;
}
}
if (maxAspectX * dheight < maxAspectY * dwidth)
{
delta = makemult(dwidth * maxAspectY / maxAspectX - dheight,
yinc);
if (dheight + delta <= maxHeight)
dheight += delta;
else
{
delta = makemult(dwidth - maxAspectX*dheight/maxAspectY,
xinc);
if (dwidth - delta >= minWidth) dwidth -= delta;
}
}
}
*widthp = dwidth;
*heightp = dheight;
return;
#undef makemult
#undef maxAspectX
#undef maxAspectY
#undef minAspectX
#undef minAspectY
}