// base.c // // This is the lowest level of the "Common" toolbox. It acts as an interface with the // various managers in the Mac toolbox by putting together calls which often appear in a // certain pattern, and which I tire of repeatedly typing out. The routines in "base.c" do // not allocate memory explicitly, and do not take any action on their own to report errors. // // by John D. de Boer #include "abcdefg.h" #include "base.h" // Integer utility functions bool range(SInt64 N, SInt64 RANGE) { return N>=0 && N=LOWER && N<=UPPER; } SInt64 mod(SInt64 N, SInt64 DIV) { N%=DIV; if (N<0) N+=DIV; return N; } SInt64 gtr(SInt64 N, SInt64 LOWER) { return NUPPER ? UPPER : N; } SInt64 between(SInt64 N, SInt64 LOWER, SInt64 UPPER) { if (NUPPER) return UPPER; return N; } SInt64 abso(SInt64 X) { return X>=0 ? X : -X; } // Random-number functions static double Seed; void setseed(double S) { Seed=S; } void randomise(void) { double U; U=CFAbsoluteTimeGetCurrent(); setseed(U); } double randfrac(void) { return randomx(&Seed) / (double)2147483647.0; } long randzb(long N) { ulong X; X=randomx(&Seed); return X % N; } int die(int D) { return randzb(D) + 1; } int dice(int N, int D) { int X=0; while (--N>=0) X+=die(D); return X; } bool pc(int P) { return P > randzb(100); } bool onein(int N) { return randzb(N)==0; } // string conversion functions void pascalstring(const char *S, Str255 R) { char *E; int L; if (!S || !R) return; E=(char *)S; while (*E) E++; L= E - S; if (L>255) L=255; R[0]=L; BlockMove(S,R + 1,L); } void str255to63(const Str255 A, Str63 B) { int L; if (!A || !B) return; L=lsr(A[0],63); B[0]=L; BlockMove(A + 1,B + 1,L); } void copypascal(const Str255 A, Str255 B) { int L; L= A[0] + 1; BlockMove(A,B,L); } CFStringRef macstring(const char *S) { return CFStringCreateWithCString(NULL,S,kCFStringEncodingMacRoman); } // kCFAllocatorNull ? // O-S interface routines void beep(void) { SysBeep(1); } void quit(void) { ExitToShell(); } // QuickDraw interface routines void savegraf(grafvars *V) { GetGWorld(&(V->port),&(V->dev)); } void restoregraf(const grafvars *V) { SetGWorld(V->port,V->dev); } void localtoglobal(WindowRef WP, Point *Pt) { grafvars G; if (!WP || !Pt) return; savegraf(&G); SetPortWindowPort(WP); LocalToGlobal(Pt); restoregraf(&G); } void globaltolocal(WindowRef WP, Point *Pt) { grafvars G; if (!WP || !Pt) return; savegraf(&G); SetPortWindowPort(WP); GlobalToLocal(Pt); restoregraf(&G); } int rectwidth(const Rect *R) { if (!R) return 0; return R->right - R->left; } int rectheight(const Rect *R) { if (!R) return 0; return R->bottom - R->top; } // Quartz points and rectangles bool equalpoints(point A, point B) { return A.x==B.x && A.y==B.y; } void setrect(rect *Q, float X, float Y, float W, float H) { if (!Q) return; Q->origin.x=X; Q->origin.y=Y; Q->size.width=W; Q->size.height=H; } void setlbrt(rect *Q, float L, float B, float R, float T) { if (!Q) return; Q->origin.x=L; Q->origin.y=B; Q->size.width= R - L; Q->size.height= T - B; } void cgrect(const Rect *R, CGRect *Q) { if (!R || !Q) return; Q->origin.x=R->left; Q->origin.y=0.0; // calling procedure has to sort vertical position out Q->size.width= R->right - R->left; Q->size.height= R->bottom - R->top; } void setpenrect(rect *R, point P, float Width) { if (!R) return; setrect(R,P.x - (Width / 2.0),P.y - (Width / 2.0),Width,Width); } void setleft(rect *R, float L) { float Rt; if (!R) return; Rt=right(*R); R->origin.x=L; R->size.width= Rt - L; } void setright(rect *R, float Rt) { if (!R) return; R->size.width= Rt - R->origin.x; } void setbottom(rect *R, float B) { float T; if (!R) return; T=top(*R); R->origin.y=B; R->size.height= T - B; } void settop(rect *R, float T) { if (!R) return; R->size.height= T - R->origin.y; } void scalerect(rect *R, float F) { if (!R) return; R->origin.x*=F; R->origin.y*=F; R->size.width*=F; R->size.height*=F; } void offsetrect(rect *R, float DX, float DY) { if (!R) return; R->origin.x+=DX; R->origin.y+=DY; } void alignrect(rect *R, float L, float T) { if (!R) return; R->origin.x=L; R->origin.y= T - R->size.height; } float left(rect R) { return R.origin.x; } float right(rect R) { return R.origin.x + R.size.width; } float top(rect R) { return R.origin.y + R.size.height; } float bottom(rect R) { return R.origin.y; } float width(rect R) { return R.size.width; } float height(rect R) { return R.size.height; } point middle(rect R) { CGPoint P; P.x= R.origin.x + (R.size.width / 2.0); P.y= R.origin.y + (R.size.height / 2.0); return P; } bool emptyrect(rect R) { return width(R)<=0.0 || height(R)<=0.0; } bool pointinrect(point P, rect R) { return CGRectContainsPoint(R,P); } void inset(rect *R, float F) { rect S; if (!R) return; S=CGRectInset(*R,F,F); *R=S; } point mappoint(point P, rect A, rect B) { float F; F= (P.x - left(A)) / width(A); P.x= left(B) + (F * width(B)); F= (P.y - right(A)) / height(A); P.y= right(B) + (F * height(B)); return P; } void centrerect(rect *R, point P) { if (!R) return; R->origin.x= P.x - (R->size.width / 2.0); R->origin.y= P.y - (R->size.height / 2.0); } void stretchrect(rect *R, point P) { if (!R) return; if (P.xright(*R)) setright(R,P.x); if (P.ytop(*R)) settop(R,P.y); } void shrinkpointtorect(rect R, point *P) { if (!P) return; if (P->xx=left(R); if (P->x>right(R)) P->x=right(R); if (P->yy=bottom(R); if (P->y>top(R)) P->y=top(R); } rect rectintersection(rect A, rect B) { return CGRectIntersection(A,B); } rect rectunion(rect A, rect B) { return CGRectUnion(A,B); }