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);

Reply via email to