/************************************************/ /* */ /* Utility.c - Various utility routines. */ /* */ /* Revised 7/6/94 by RMR */ /* */ /************************************************/ #include #include #include #include #include "Snakes.h" /************************************************/ /* Progress Bar Routines */ /************************************************/ static Rect frameRect; static pascal Boolean ProgressFilter(DialogPtr dlog, EventRecord *evt, short *item) { return SkelDlogMapKeyToButton(dlog, evt, item, 0, iCancelButton); } static pascal void ProgressSelect(DialogPtr dlog, short item) { if (dlog == gProgressDialog && item == iCancelButton) { HideWindow(gProgressDialog); AdjustMenus(true); gTerminateFlag = true; } } Boolean InitProgressDialog(void) { return SkelDialog(gProgressDialog, ProgressFilter, ProgressSelect, nil, nil); } void InitProgressBar(StringPtr string) { gTerminateFlag = false; SetPort(gProgressDialog); SkelGetDlogRect(gProgressDialog, iProgressBar, &frameRect); RGBForeColor(&kBlack); RGBBackColor(&kWhite); SkelSetDlogStr(gProgressDialog, iProgressText, string); SkelDlogCancelItem(iCancelButton); ShowWindow(gProgressDialog); SelectWindow(gProgressDialog); AdjustMenus(false); } void DrawProgressBar(short count, short max) { GDHandle oldGD; GWorldPtr oldGW; short border; long rectWidth; Rect doneRect, toDoRect; rectWidth = frameRect.right - frameRect.left - 2; border = frameRect.left + 1 + (short)(rectWidth * count / max); doneRect = frameRect; InsetRect(&doneRect, 1, 1); toDoRect = doneRect; doneRect.right = toDoRect.left = border; GetGWorld(&oldGW, &oldGD); SetGWorld((GWorldPtr)gProgressDialog, nil); SetPort(gProgressDialog); RGBForeColor(&kBlack); RGBBackColor(&kWhite); FrameRect(&frameRect); RGBForeColor(&kRed); FillRect(&doneRect, gSolidPattern); RGBForeColor(&kGrey); FillRect(&toDoRect, gSolidPattern); RGBForeColor(&kBlack); SetGWorld(oldGW, oldGD); } void KillProgressBar(void) { HideWindow(gProgressDialog); AdjustMenus(true); } /************************************************/ /* Options Dialog Routines */ /************************************************/ static pascal Boolean OptDlogFilter(DialogPtr dlog, EventRecord *evt, short *item) { return SkelDlogMapKeyToButton(dlog, evt, item, iOptDefault, iOptDone); } static pascal void OptDlogSelect(DialogPtr dlog, short item) { long num; if (dlog == gOptionsDialog) switch (item) { case iInfoCheck: if (SkelToggleDlogCtlValue(dlog, item)) { gOptions->showInfoWindow = true; ShowWindow(gInfoWindow); } else { gOptions->showInfoWindow = false; HideWindow(gInfoWindow); } break; case iGradCheck: gOptions->showGradientModels = SkelToggleDlogCtlValue(dlog, item); KickPictWindow(); break; case iPWindCheck: gOptions->showParticleWindows = SkelToggleDlogCtlValue(dlog, item); KickPictWindow(); break; case iLoadCheck: gOptions->loadModelsWithImage = SkelToggleDlogCtlValue(dlog, item); KickPictWindow(); break; case iRungCheck: gOptions->firstRungDoesntMove = SkelToggleDlogCtlValue(dlog, item); KickPictWindow(); break; case iOptDefault: LoadDefault((Ptr *)&gOptions, (Ptr)&defaultOptions, sizeof(Options)); SkelSetDlogCtlValue(gOptionsDialog, iInfoCheck, gOptions->showInfoWindow); SkelSetDlogCtlValue(gOptionsDialog, iGradCheck, gOptions->showGradientModels); SkelSetDlogCtlValue(gOptionsDialog, iPWindCheck, gOptions->showParticleWindows); SkelSetDlogCtlValue(gOptionsDialog, iLoadCheck, gOptions->loadModelsWithImage); SkelSetDlogCtlValue(gOptionsDialog, iRungCheck, gOptions->firstRungDoesntMove); KickPictWindow(); break; case iOptDone: HideWindow(gOptionsDialog); AdjustMenus(true); } } static pascal void OptDlogClose(void) { HideWindow(gOptionsDialog); AdjustMenus(true); } static pascal void OptDlogClobber(void) { DisposeDialog(gOptionsDialog); } Boolean InitOptionsDialog(void) { return SkelDialog(gOptionsDialog, OptDlogFilter, OptDlogSelect, OptDlogClose, OptDlogClobber); } void OpenOptionsDialog(void) { NumToString((long)(gGlobalParams->threshold), gTempStr); ShowWindow(gOptionsDialog); SelectWindow(gOptionsDialog); RGBForeColor(&kBlack); RGBBackColor(&kWhite); SkelDrawButtonOutline(SkelGetDlogCtl(gOptionsDialog, iOptDefault)); SkelSetDlogCtlValue(gOptionsDialog, iInfoCheck, gOptions->showInfoWindow); SkelSetDlogCtlValue(gOptionsDialog, iGradCheck, gOptions->showGradientModels); SkelSetDlogCtlValue(gOptionsDialog, iPWindCheck, gOptions->showParticleWindows); SkelSetDlogCtlValue(gOptionsDialog, iLoadCheck, gOptions->loadModelsWithImage); SkelSetDlogCtlValue(gOptionsDialog, iRungCheck, gOptions->firstRungDoesntMove); AdjustMenus(true); } /************************************************/ /* Message Communication Routines */ /************************************************/ void DoError(Str255 errorString) { SetCursor(&arrow); ParamText(errorString, "\p", "\p", "\p"); StopAlert(kErrorAlertID, nil); SkelCleanup(); ExitToShell(); } void DoWarning(Str255 errorString) { SetCursor(&arrow); ParamText(errorString, "\p", "\p", "\p"); CautionAlert(kErrorAlertID, nil); } void ReportFreeMem(Str255 str) { GrafPtr temp; GetPort(&temp); SetDWindow(gInfoWindow); DisplayString(str); DisplayString("\p - free space: "); DisplayLong(FreeMem()); DisplayLn(); SetPort(temp); } /************************************************/ /* Image Data Transfer Routines */ /************************************************/ void CopyGWorld2Window(GWorldPtr world, WindowPtr wind, Rect *rect) { PixMapHandle pixmap; GrafPtr temp; GetPort(&temp); SetPort(wind); RGBForeColor(&kBlack); RGBBackColor(&kWhite); pixmap = GetGWorldPixMap(world); HNullCheck((Handle)pixmap); LockPixels(pixmap); CopyBits((BitMap *)*pixmap, &wind->portBits, rect, rect, srcCopy, nil); UnlockPixels(pixmap); SetPort(temp); } void CopyGWorld2Array(GWorldPtr world, Array *array, Rect *rect) { GDHandle oldGD; GWorldPtr oldGW; PixMapHandle pixmap; short x, y, rowbytes; unsigned char *rowptr, *pixptr; ValPtr vptr; GetGWorld(&oldGW, &oldGD); SetGWorld(world, nil); pixmap = GetGWorldPixMap(world); if (!LockPixels(pixmap)) DoError("\pCannot lock pixels!"); rowptr = (unsigned char*)(*pixmap)->baseAddr; rowbytes = (*pixmap)->rowBytes & 0x0fff; vptr = (ValPtr)LockArray(array); for (y = 0; y < gPictHeight; y++) { pixptr = rowptr; for (x = 0; x < gPictWidth; x++) *vptr++ = *pixptr++; rowptr += rowbytes; } UnlockArray(array); array->valid = true; UnlockPixels(pixmap); SetGWorld(oldGW, oldGD); } void CopyArray2GWorld(Array *array, GWorldPtr world, Rect *rect) { GDHandle oldGD; GWorldPtr oldGW; PixMapHandle pixmap; short x, y, rowbytes; unsigned char *rowptr, *pixptr; ValPtr vptr; if (!array->valid) DoError("\pArray is not valid!"); SetCursor(*gWatchCursor); GetGWorld(&oldGW, &oldGD); SetGWorld(world, nil); RGBForeColor(&kBlack); RGBBackColor(&kWhite); pixmap = GetGWorldPixMap(world); if (!LockPixels(pixmap)) DoError("\pCannot lock pixels!"); rowptr = (unsigned char*)(*pixmap)->baseAddr; rowbytes = (*pixmap)->rowBytes & 0x0fff; vptr = (ValPtr)LockArray(array); for (y = 0; y < gPictHeight; y++) { pixptr = rowptr; for (x = 0; x < gPictWidth; x++) *pixptr++ = *vptr++; rowptr += rowbytes; } UnlockArray(array); UnlockPixels(pixmap); SetGWorld(oldGW, oldGD); SetCursor(&arrow); } /************************************************/ /* Various Dialog Routines */ /************************************************/ void DrawDlogColorBox(DialogPtr dlog, short item, RGBColor rgb) { Rect r; SetPort(dlog); SkelGetDlogRect(dlog, item, &r); RGBForeColor(&kBlack); RGBBackColor(&kWhite); FrameRect(&r); InsetRect(&r, 1, 1); RGBForeColor(&rgb); FillRect(&r, gSolidPattern); RGBForeColor(&kBlack); } Boolean PtInDlogColorBox(Point pt, DialogPtr dlog, short item) { Rect r; SetPort(dlog); SkelGetDlogRect(dlog, item, &r); return PtInRect(pt, &r); } void PickDlogColor(StringPtr str, DialogPtr dlog, short item, RGBColor *rgbin) { RGBColor rgbout; Point p = { -1, -1 }; if (GetColor(p, str, rgbin, &rgbout)) *rgbin = rgbout; } void DrawParticleStatus(DialogPtr dlog, short item, ModelPtr model, Boolean sideB) { char buf[24]; Boolean done; short numParticles; done = sideB ? model->sideBDone : model->sideADone; numParticles = sideB ? model->sideBParticles : model->sideAParticles; sprintf(buf, "%d Particles %s", numParticles, done ? "- Done" : " "); CtoPstr(buf); SkelSetDlogStr(dlog, item, (StringPtr)buf); } /************************************************/ /* Vector Operation Routines */ /************************************************/ void SetVector(Vector *v, Scalar x, Scalar y) { v->x = x; v->y = y; } Scalar Distance(Vector v1, Vector v2) { Scalar dx, dy; dx = v1.x - v2.x; dy = v1.y - v2.y; return (Scalar)sqrt((double)(dx * dx + dy * dy)); } Scalar Magnitude(Vector v) { return (Scalar)sqrt((double)(v.x * v.x + v.y * v.y)); } void Direction(Vector vin, Vector *vout) { Scalar mag; mag = Magnitude(vin); if (mag == 0.0) mag = 0.01; vout->x = vin.x / mag; vout->y = vin.y / mag; } void VectorSum(Vector v1, Vector v2, Vector *vsum) { vsum->x = v1.x + v2.x; vsum->y = v1.y + v2.y; } void VectorDifference(Vector v1, Vector v2, Vector *vdiff) { vdiff->x = v1.x - v2.x; vdiff->y = v1.y - v2.y; } void VectorByScalar(Vector vin, Scalar s, Vector *vprod) { vprod->x = vin.x * s; vprod->y = vin.y * s; } Scalar DotProduct(Vector v1, Vector v2) { return (v1.x * v2.x) + (v1.y * v2.y); } Boolean Constrain(Vector *v, Rect r) { Boolean b = false; if (v->x > (Scalar)(r.right)) { v->x = (Scalar)(r.right); b = true; } if (v->x < (Scalar)(r.left)) { v->x = (Scalar)(r.left); b = true; } if (v->y > (Scalar)(r.bottom)) { v->y = (Scalar)(r.bottom); b = true; } if (v->y < (Scalar)(r.left)) { v->y = (Scalar)(r.left); b = true; } return b; } /************************************************/ /* Array Routines */ /************************************************/ void OpenArray(Array *array, short eSize, Size numElems) { if (array->exists) CloseArray(array); array->exists = true; array->locked = false; array->valid = false; array->elementSize = eSize; array->numberOfElements = numElems; array->base = NewHandle(eSize * numElems); if (array->base == nil) DoError("\pCannot allocate Array!"); HNullCheck(array->base); } void CloseArray(Array *array) { array->exists = false; array->locked = false; array->valid = false; array->elementSize = 0; array->numberOfElements = 0; HNullCheck(array->base); DisposeHandle(array->base); } Ptr LockArray(Array *array) { if (array->exists == false) DoError("\pCannot lock non-existent array!"); HNullCheck(array->base); if (!array->locked) { HLock(array->base); array->locked = true; } return *(array->base); } void UnlockArray(Array *array) { if (array->exists == false) DoError("\pCannot unlock non-existent array!"); array->locked = false; HNullCheck(array->base); HUnlock(array->base); } /************************************************/ /* Preferences & Resource Routines */ /************************************************/ void LoadDefault(Ptr *dest, Ptr item, Size size) { Ptr ptr; *dest = NewPtr(size); if (*dest == nil) DoError("\pDefault data allocation error!"); ptr = *dest; memcpy(ptr, item, size); } void LoadPreference(Ptr dest, Size size, ResType rType, short rID) { Handle rh; Ptr ptr1, ptr2; rh = GetResource(rType, rID); if (rh != nil) { HLock(rh); ptr1 = dest; ptr2 = *rh; memcpy(ptr1, ptr2, size); HUnlock(rh); ReleaseResource(rh); } } void SetWPos(WindowPtr wptr, short rID) { Point p; WPosHandle h; if ((h = (WPosHandle)GetResource(kWPosType, rID)) == nil) return; HLock((Handle)h); p.h = (*h)->h; p.v = (*h)->v; HUnlock((Handle)h); ReleaseResource((Handle)h); MoveWindow(wptr, p.h, p.v, false); } void SaveWPos(WindowPtr wptr, WPosHandle *wpos) { Rect r; SetPort(wptr); r = wptr->portRect; LocalToGlobal(&topLeft(r)); *wpos = (WPosHandle)NewHandle(sizeof(Point)); HLock((Handle)*wpos); (**wpos)->h = topLeft(r).h; (**wpos)->v = topLeft(r).v; HUnlock((Handle)*wpos); } void SaveResource(Handle h, ResType rType, short rID, StringPtr rName) { Size size; Handle newh; size = GetHandleSize(h); newh = NewHandle(size); HLock(h); HLock(newh); memcpy(*newh, *h, size); HUnlock(h); AddResource(newh, rType, rID, rName); if (ResError() == addResFailed) DoError("\pAdd Res Failed!"); WriteResource(newh); ReleaseResource(newh); HUnlock(newh); } void SavePtrRsrc(Ptr p, Size size, ResType rType, short rID, StringPtr rName) { Handle newh; newh = NewHandle(size); HLock(newh); memcpy(*newh, p, size); AddResource(newh, rType, rID, rName); if (ResError() == addResFailed) DoError("\pAdd Res Failed!"); WriteResource(newh); ReleaseResource(newh); HUnlock(newh); } /************************************************/ /* Miscellaneous Routines */ /************************************************/ short MinShort(short a, short b) { return (a < b ? a : b); } void AdjustMenus(Boolean enable) { if (enable) { EnableItem(gFileMenu, 0); EnableItem(gModelMenu, 0); EnableItem(gFileMenu, iOpen); EnableItem(gFileMenu, iGlobal); EnableItem(gFileMenu, iOption); EnableItem(gFileMenu, iQuit); if (((WindowPeek)gPictWindow)->visible) { EnableItem(gFileMenu, iClose); EnableItem(gFileMenu, iSave); EnableItem(gFileMenu, iSaveAs); EnableItem(gImageMenu, 0); EnableItem(gModelMenu, iPlacement); EnableItem(gModelMenu, iClearAll); EnableItem(gModelMenu, iExecute); } else { DisableItem(gFileMenu, iClose); DisableItem(gFileMenu, iSave); DisableItem(gFileMenu, iSaveAs); DisableItem(gImageMenu, 0); DisableItem(gModelMenu, iPlacement); DisableItem(gModelMenu, iClearAll); DisableItem(gModelMenu, iExecute); } } else { DisableItem(gFileMenu, 0); DisableItem(gImageMenu, 0); DisableItem(gModelMenu, 0); } DrawMenuBar(); } void HNullCheck(Handle handle) { if (handle == nil) DoError("\pNull handle!"); if (*handle == nil) DoError("\pNull de-ref handle!"); } void ScalarToPString(Scalar num, StringPtr str, char *fmt) { sprintf((char *)str, fmt, (double)num); CtoPstr((char *)str); } void PStringToScalar(StringPtr str, Scalar *num) { int numargs; double d; PtoCstr((unsigned char *)str); numargs = sscanf((char *)str, "%lg", &d); *num = (Scalar)d; } void SetCustomPalette(void) { int i; gCustPalette = GetNewPalette(kCustomPalette); for (i = 0; i < 256; i++) SetEntryUsage(gCustPalette, i, pmTolerant + pmExplicit, 300); }