```MODULE WMRectangles; (** AUTHOR "TF"; PURPOSE "Basic rectangles that are used by the WM and visual components"; *) TYPE Rectangle* = RECORD l*, t*, r*, b*: LONGINT END; (* It is important to understand and respect that the point (r,b) is not included in the rectangle ! This is to ensure consistency between the continuous and discrete case *) PROCEDURE Min(a, b:LONGINT):LONGINT; BEGIN IF a<b THEN RETURN a ELSE RETURN b END; END Min; PROCEDURE Max(a, b:LONGINT):LONGINT; BEGIN IF a>b THEN RETURN a ELSE RETURN b END; END Max; (** move the rectangle by deltaX, deltaY *) PROCEDURE MoveRel*(VAR x:Rectangle; deltaX, deltaY:LONGINT); BEGIN x.l:=x.l+deltaX; x.t:=x.t+deltaY; x.r:=x.r+deltaX; x.b:=x.b+deltaY END MoveRel; PROCEDURE Bound(VAR x:LONGINT; min, max:LONGINT); BEGIN IF x<min THEN x:=min ELSE IF x>max THEN x:=max END END END Bound; (** Clip rectangle rect at the boundary bounds *) PROCEDURE ClipRect*(VAR rect, bounds : Rectangle); BEGIN Bound(rect.l, bounds.l, bounds.r);Bound(rect.r, bounds.l, bounds.r); Bound(rect.t, bounds.t, bounds.b);Bound(rect.b, bounds.t, bounds.b) END ClipRect; (** return true if rectangle x is empty *) PROCEDURE RectEmpty*(x : Rectangle) : BOOLEAN; BEGIN RETURN (x.t >= x.b) OR (x.l >= x.r) END RectEmpty; (** return true if x and y are inside rect *) PROCEDURE PointInRect*(x, y : LONGINT; rect : Rectangle) : BOOLEAN; BEGIN RETURN (x >= rect.l) & (x < rect.r) & (y >= rect.t) & (y < rect.b) END PointInRect; (** return true if the inner rectangle is completely inside the outer *) PROCEDURE IsContained*(VAR outer, inner : Rectangle) : BOOLEAN; BEGIN RETURN (outer.l <= inner.l) & (outer.r >= inner.r) & (outer.t <= inner.t) & (outer.b >= inner.b) END IsContained; PROCEDURE IsEqual*(CONST a, b : Rectangle) : BOOLEAN; BEGIN RETURN (a.l = b.l) & (a.r = b.r) & (a.t = b.t) & (a.b = b.b) END IsEqual; (** return whether a and be intersect and not only touche *) PROCEDURE Intersect*(VAR a, b : Rectangle) : BOOLEAN; BEGIN RETURN (a.l < b.r) & (a.r > b.l) & (a.t < b.b) & (a.b > b.t) END Intersect; (** Set rect to (l, t, r, b) *) PROCEDURE SetRect*(VAR rect : Rectangle; l, t, r, b : LONGINT); BEGIN rect.l := l; rect.t := t; rect.r := r; rect.b := b END SetRect; (** return the area of r. Overflow if r w * h > MAX(LONGINT) *) PROCEDURE Area*(VAR r : Rectangle) : LONGINT; BEGIN RETURN (r.r - r.l) * (r.b - r.t) END Area; (** Extend old to contain addition *) PROCEDURE ExtendRect*(VAR old, addition : Rectangle); BEGIN old.l := Min(old.l, addition.l); old.r := Max(old.r,addition.r); old.t := Min(old.t, addition.t); old.b := Max(old.b, addition.b) END ExtendRect; (** return the Rectangle (l, t, r, b) *) PROCEDURE MakeRect*(l, t, r, b: LONGINT) : Rectangle; VAR result : Rectangle; BEGIN result.l := l; result.t := t; result.r := r; result.b := b; RETURN result END MakeRect; (** extend the rectangle by units in each direction *) PROCEDURE ResizeRect*(x : Rectangle; units : LONGINT) : Rectangle; VAR t : Rectangle; BEGIN t.l := x.l - units; t.t := x.t - units; t.r := x.r + units; t.b := x.b + units; RETURN t END ResizeRect; END WMRectangles. ```