This diff supersedes
http://marc.info/?l=openbsd-bugs&m=124471413424140
and attempts to handle the PAspect flag.
The output of
egrep '__int(32|64)_t;' /usr/src/sys/arch/*/include/_types.h
seems to indicate that 'long long' is twice as big as 'int' on all
supported platforms. The code relies on that to prevent arithmetic
overflow.
Comments?
I grant this diff to the public domain.
Index: mousefunc.c
===================================================================
RCS file: /cvs/xenocara/app/cwm/mousefunc.c,v
retrieving revision 1.12
diff -u -r1.12 mousefunc.c
--- mousefunc.c 20 Jun 2009 00:55:42 -0000 1.12
+++ mousefunc.c 23 Jun 2009 17:38:42 -0000
@@ -25,6 +25,42 @@
static int mousefunc_sweep_calc(struct client_ctx *, int, int, int, int);
static void mousefunc_sweep_draw(struct client_ctx *);
+/* greater-than for fractions of ints with positive denominator */
+#define GTF(a,b, c,d) ((long long)(a) * (d) > (long long)(b) * (c))
+
+/* ceiling(a/b), if a>0 and b>0 */
+#define CEILDIV(a, b) ((((a) - 1) / (b)) + 1)
+
+static void
+aspect_calc(int *wp, int *hp, int fl, int wi, int hi,
+ int a, int b, int c, int d)
+{
+ int w = *wp, h = *hp, n;
+
+ if (!fl || wi < 1)
+ wi = 1;
+ if (!fl || hi < 1)
+ hi = 1;
+ if (w < 1 || h < 1 || a < 1 || b < 1 || c < 1 || d < 1 ||
+ GTF(a,b, c,d))
+ return;
+ if (GTF(a,b, w,h)) {
+ /* the least n such that a/b <= (w + n*wi)/h */
+ n = CEILDIV(CEILDIV((long long)h * a, b) - w, wi);
+ w += n * wi;
+ if (GTF(w,h, c,d))
+ w -= wi;
+ *wp = w;
+ } else if (GTF(w,h, c,d)) {
+ /* the least n such that w/(h + n*hi) <= c/d */
+ n = CEILDIV(CEILDIV((long long)w * d, c) - h, hi);
+ h += n * hi;
+ if (GTF(a,b, w,h))
+ h -= hi;
+ *hp = h;
+ }
+}
+
static int
mousefunc_sweep_calc(struct client_ctx *cc, int x, int y, int mx, int my)
{
@@ -39,6 +75,13 @@
cc->geom.height -=
(cc->geom.height - cc->geom.min_dy) % cc->size->height_inc;
}
+
+ if (cc->size->flags & PAspect)
+ aspect_calc(&cc->geom.width, &cc->geom.height,
+ (cc->size->flags & PResizeInc) != 0,
+ cc->size->width_inc, cc->size->height_inc,
+ cc->size->min_aspect.x, cc->size->min_aspect.y,
+ cc->size->max_aspect.x, cc->size->max_aspect.y);
if (cc->size->flags & PMinSize) {
cc->geom.width = MAX(cc->geom.width, cc->size->min_width);