/************************************************/ /* */ /* PictFiles.c - Pict handler routines. */ /* */ /* Revised 7/6/94 by RMR */ /* */ /************************************************/ #include #include #include "Snakes.h" /************************************************/ /* PICT File Handling */ /************************************************/ StandardFileReply gReply; void CheckFileCompatibility(void) { long feature; if (Gestalt(gestaltStandardFileAttr, &feature) != noErr) DoError("\pError returned by Gestalt!"); if (feature & (1 << gestaltStandardFile58) == 0) DoError("\pStandard File routines are not supported!"); if (Gestalt(gestaltFSAttr, &feature) != noErr) DoError("\pError returned by Gestalt!"); if (feature & (1 << gestaltHasFSSpecCalls) == 0) DoError("\pFSSpec File Manager Routines not supported!"); } static PicHandle LoadPictFile(void) { PicHandle picture; char pictHeader[kPictHeaderSize]; Size pictSize, headerSize; SFTypeList typeList; short numTypes, srcFile, oldRefNum; FInfo myInfo; ClearModel(gRefModel); ClearModel(gTestModel); typeList[0] = kImageFileType; numTypes = 1; StandardGetFile(nil, numTypes, typeList, &gReply); if (!gReply.sfGood) return nil; if (FSpOpenDF(&(gReply.sfFile), fsRdPerm, &srcFile) != noErr) DoError("\pCan't open file..."); if (GetEOF(srcFile, &pictSize) != noErr) DoError("\pError returned by GetEOF()..."); headerSize = kPictHeaderSize; if (FSRead(srcFile, &headerSize, pictHeader) != noErr) DoError("\pError reading header file..."); pictSize -= kPictHeaderSize; if ((picture = (PicHandle)NewHandle(pictSize)) == nil) DoError("\pNot enough memory to read picture..."); HNullCheck((Handle)picture); HLock((Handle)picture); if (FSRead(srcFile, &pictSize, *picture) != noErr) DoError("\pError returned by FSRead()..."); HUnlock((Handle)picture); FSClose(srcFile); if (gOptions->loadModelsWithImage) { if (FSpGetFInfo(&(gReply.sfFile), &myInfo) != noErr) { DoWarning("\pCannot get finder info!"); return picture; } if (myInfo.fdCreator == kCreatorID) { if ((srcFile = FSpOpenResFile(&(gReply.sfFile), fsRdWrPerm)) == -1) DoWarning("\pCannot open model resource fork!"); else { oldRefNum = CurResFile(); UseResFile(srcFile); LoadPreference((Ptr)gGlobalParams, sizeof(GlobalParams), kGlobalParamType, kGlobalParams); LoadPreference((Ptr)gRefModel, sizeof(Model), kModelType, kRefModel); LoadPreference((Ptr)gTestModel, sizeof(Model), kModelType, kTestModel); CloseResFile(srcFile); UseResFile(oldRefNum); } } } return picture; } static void SavePictFile(Boolean replace) { PicHandle picture; char pictHeader[kPictHeaderSize]; FSSpec tempSpec; short i, myVRef, tempRefNum, oldRefNum; long count; OSErr err; err = FSMakeFSSpec(gReply.sfFile.vRefNum, gReply.sfFile.parID, "\pImage.tmp", &tempSpec); if (err == noErr) FSpDelete(&tempSpec); FSMakeFSSpec(gReply.sfFile.vRefNum, gReply.sfFile.parID, "\pImage.tmp", &tempSpec); FSpCreate(&tempSpec, kCreatorID, kImageFileType, 0); if (FSpOpenDF(&tempSpec, fsRdWrPerm, &tempRefNum) != noErr) DoError("\pCannot open temp image file!"); for (i = 0; i < kPictHeaderSize; i++) pictHeader[i] = '\0'; strcpy(pictHeader, "Snakes v1.30 PICT file."); count = (long)kPictHeaderSize; if (FSWrite(tempRefNum, &count, pictHeader) != noErr) DoError("\pCannot write file header!"); DisplayString("\pSaving image.\r\r"); picture = MakePicture(gPictWorld); HNullCheck((Handle)picture); HLock((Handle)picture); count = (long)GetHandleSize((Handle)picture); if (FSWrite(tempRefNum, &count, *picture) != noErr) DoError("\pCannot write picture file!"); HUnlock((Handle)picture); DisposeHandle((Handle)picture); FSClose(tempRefNum); oldRefNum = CurResFile(); FSpCreateResFile(&tempSpec, kCreatorID, kImageFileType, 0); if ((tempRefNum = FSpOpenResFile(&tempSpec, fsRdWrPerm)) == -1) DoError("\pCannot open PICT resource fork!"); UseResFile(tempRefNum); if ((err = ResError()) != noErr) DoError("\pCannot use resource fork!"); SavePtrRsrc((Ptr)gGlobalParams, sizeof(GlobalParams), kGlobalParamType, kGlobalParams, "\pGlobal Parameters"); SavePtrRsrc((Ptr)gRefModel, sizeof(Model), kModelType, kRefModel, "\pReference Model"); SavePtrRsrc((Ptr)gTestModel, sizeof(Model), kModelType, kTestModel, "\pTest Model"); UpdateResFile(tempRefNum); CloseResFile(tempRefNum); if (gReply.sfReplacing || replace) { if (FSpExchangeFiles(&(gReply.sfFile), &tempSpec) != noErr) DoWarning("\pCannot swap temp and image files!"); if ((err = FSpDelete(&tempSpec)) != noErr) DoWarning("\pCannot delete old temp file!"); } else if (FSpRename(&tempSpec, gReply.sfFile.name) != noErr) DoWarning("\pCannot rename temp file!"); } /************************************************/ /* PICT Window and Gworld Routines */ /************************************************/ PicHandle MakePicture(GWorldPtr world) { PixMapHandle pixmap; PicHandle picture; GDHandle oldGD; GWorldPtr oldGW; GetGWorld(&oldGW, &oldGD); SetGWorld(world, nil); RGBForeColor(&kBlack); RGBBackColor(&kWhite); pixmap = GetGWorldPixMap(world); if (!LockPixels(pixmap)) DoError("\pCannot lock pixels!"); HNullCheck((Handle)pixmap); ClipRect(&gPictRect); picture = OpenPicture(&gPictRect); if (picture == nil) DoError("\pCannot allocate picture buffer!"); CopyBits((BitMap *)*pixmap, (BitMap *)*pixmap, &gPictRect, &gPictRect, srcCopy, nil); ClosePicture(); UnlockPixels(pixmap); SetGWorld(oldGW, oldGD); return picture; } static void LoadPictGWorld(PicHandle picture) { GDHandle oldGD; GWorldPtr oldGW; PixMapHandle pixmap; HNullCheck((Handle)picture); gPictRect = (**picture).picFrame; gPictWidth = gPictRect.right - gPictRect.left; gPictHeight = gPictRect.bottom - gPictRect.top; GetGWorld(&oldGW, &oldGD); if (NewGWorld(&gPictWorld, 8, &gPictRect, GetCTable(GRAY_RAMP + 8), nil, 0) != noErr) DoError( "\pCannot create new pict GWorld!"); pixmap = GetGWorldPixMap(gPictWorld); if (!LockPixels(pixmap)) DoError("\pCannot lock pixels!"); SetGWorld(gPictWorld, nil); RGBForeColor(&kBlack); RGBBackColor(&kWhite); EraseRect(&gPictRect); DrawPicture(picture, &gPictRect); gPictArray.valid = true; SetGWorld(oldGW, oldGD); UnlockPixels(pixmap); } static void ShowPictStats(void) { GrafPtr temp; GetPort(&temp); SetPort(gInfoWindow); SetDWindow(gInfoWindow); DisplayString("\pImage Width: "); DisplayLong(gPictWidth); DisplayLn(); DisplayString("\pImage Height: "); DisplayLong(gPictHeight); DisplayLn(); DisplayString("\pImage Area: "); DisplayLong((Size)gPictWidth * (Size)gPictHeight); DisplayLn(); DisplayLn(); SetPort(temp); } void ShowPictWindow(void) { GrafPtr temp; GetPort(&temp); SetPort(gPictWindow); CopyGWorld2Window(gPictWorld, gPictWindow, &gPictRect); DrawModel(gRefModel, gPictWindow); DrawModel(gTestModel, gPictWindow); if (((WindowPeek)(gHistDialog))->visible && !gHistArray.valid) DrawHistDialog(); SetPort(temp); } static pascal void PictMouse(Point where, long when, short modifiers) { PictPoint(where, gPictWindow); KickPictWindow(); } static pascal void PictKey(short c, short code, short modifiers) { if (((WindowPeek)gExecDialog)->visible) { if (c == 0x1b) CloseExecDialog(); else if (c == ' ' && gModelStatus == sPaused) ExecuteOneCycle(); } else if (((WindowPeek)gPlaceDialog)->visible) { switch (c) { case '\n': case '\r': SetPlaceDone(); DrawPlaceDialog(); BuildSpringsFromParticles(gRefModel); BuildSpringsFromParticles(gTestModel); KickPictWindow(); break; case 0x08: case 0x7f: PlaceDelOne(); DrawPlaceDialog(); BuildSpringsFromParticles(gRefModel); BuildSpringsFromParticles(gTestModel); KickPictWindow(); break; case ' ': switch (gModelStatus) { case sPlaceRefA: gModelStatus = sPlaceRefB; break; case sPlaceRefB: gModelStatus = sPlaceTestA; break; case sPlaceTestA: gModelStatus = sPlaceTestB; break; case sPlaceTestB: gModelStatus = sPlaceRefA; } DrawPlaceDialog(); break; case 0x1b: ClosePlaceDialog(); } } else SysBeep(10); } static pascal void PictUpdate(Boolean resized) { ShowPictWindow(); } static pascal void PictActivate(Boolean active) { if (active) ShowPictWindow(); AdjustMenus(true); } void ClosePictWindow(void) { CloseGradWindow(); CloseThrsWindow(); ClosePlaceDialog(); CloseExecDialog(); CloseHistDialog(); if (((WindowPeek)gPictWindow)->visible) { HideWindow(gPictWindow); DisposeGWorld(gPictWorld); CloseArray(&gPictArray); CloseArray(&gTempArray); CloseArray(&gHistArray); } } static pascal void PictClose(void) { ClosePictWindow(); } static pascal void PictClobber(void) { DisposeWindow(gPictWindow); } static pascal void PictIdle(void) { if (gModelStatus == sRunning) ExecuteOneCycle(); } Boolean InitPictWindow(void) { return SkelWindow(gPictWindow, PictMouse, PictKey, PictUpdate, PictActivate, PictClose, PictClobber, PictIdle, true); } void OpenPictWindow(void) { PicHandle picture; if (((WindowPeek)gPictWindow)->visible) ClosePictWindow(); if ((picture = LoadPictFile()) == nil) return; DisplayString("\pLoading image.\r"); SetCursor(*gWatchCursor); gPictRect = (**picture).picFrame; gPictWidth = (int)(gPictRect.right - gPictRect.left); gPictHeight = (int)(gPictRect.bottom - gPictRect.top); LoadPictGWorld(picture); KillPicture(picture); SetPort(gPictWindow); PortSize(gPictWidth, gPictHeight); ClipRect(&gPictRect); ShowWindow(gPictWindow); SetWTitle(gPictWindow, gReply.sfFile.name); OpenArray(&gPictArray, sizeof(Value), (Size)gPictHeight * gPictWidth); OpenArray(&gTempArray, sizeof(Value), (Size)gPictHeight * gPictWidth); OpenArray(&gHistArray, sizeof(long), (Size)256); CopyGWorld2Array(gPictWorld, &gPictArray, &gPictRect); BuildSpringsFromParticles(gRefModel); BuildSpringsFromParticles(gTestModel); SelectWindow(gPictWindow); ShowPictStats(); SetCursor(&arrow); } void KickPictWindow(void) { GrafPtr temp; GetPort(&temp); if (((WindowPeek)gPictWindow)->visible) ShowPictWindow(); if (((WindowPeek)gGradWindow)->visible) ShowGradWindow(); if (((WindowPeek)gHistDialog)->visible) DrawHistDialog(); SetPort(temp); } void SavePictWindowAs(void) { PicHandle picture; if (!((WindowPeek)gPictWindow)->visible) { SysBeep(10); return; } StandardPutFile("\pSave Image...", gReply.sfFile.name, &gReply); if (!gReply.sfGood) return; SetCursor(*gWatchCursor); SavePictFile(false); SetWTitle(gPictWindow, gReply.sfFile.name); SetCursor(&arrow); } void SavePictWindow(void) { PicHandle picture; if (!((WindowPeek)gPictWindow)->visible) { SysBeep(10); return; } if (!gReply.sfGood) StandardPutFile("\pSave Image.", "\pImage.snk", &gReply); SetCursor(*gWatchCursor); SavePictFile(true); SetCursor(&arrow); if (!gReply.sfGood) return; SetWTitle(gPictWindow, gReply.sfFile.name); }