#include #include #include #include "DSDialogs.h" #include "DSUserProcs.h" #include "DSUtilsASG.h" PrefsHandle gPrefs = nil; Prefs gDefaultPrefs = { kVersion, false, false, { 0, 0 }, { 0, 0 } }; Handle gMapResource = nil; extern void DoMenu ( long retVal ); #define kPrefsFileName "\puuUndo Preferences" static Fixed gProgressPercent = 0; //===================================================================================== // pascal OSErr GenericProgress(short theMessage, Fixed thePercent, long refCon) //===================================================================================== // Generic progress procedure, which displays a dialog with a progress bar and a cancel // button. This function can be called as often as desired; the display is never // updated more than 6 times/second. //===================================================================================== pascal OSErr GenericProgress(short theMessage, Fixed thePercent, long refCon) { static UserItemUPP gUpdateBar = nil; static DialogPtr gTheDialog = nil; static long gLastTime; OSErr theErr = noErr; GrafPtr oldPort; Point thePoint; long ticks; GetPort(&oldPort); switch (theMessage) { case codecProgressOpen: if (gTheDialog = GetNewDialog(rProgressDialog, nil, (WindowPtr)-1)) { SetPort(gTheDialog); // set up the user item handler, either for indefinite progress // (thePercent == kIndefProgress) or for standard progress if (!gUpdateBar) gUpdateBar = NewUserItemProc((ProcPtr)UpdateBar); SetItemHandle(gTheDialog, progressUser, (Handle)gUpdateBar); SetWindowPosition(gTheDialog, (*gPrefs)->progressLoc); UserDialogActivate(FrontWindow(), false); ShowWindow(gTheDialog); DrawDialog(gTheDialog); } // reset the last time so that we draw right away, and update the initial // percentage gLastTime = 0; theErr = GenericProgress(codecProgressForceUpdatePercent, 0, refCon); break; case codecProgressForceUpdatePercent: gLastTime = 0; case codecProgressUpdatePercent: if (gTheDialog) { // update our user item no more than 3x a second; do this by setting the // gProgressPercent global, and forcing an update of the bar userItem if ((TickCount() - gLastTime) < 10L) break; gLastTime = TickCount(); gProgressPercent = thePercent; UpdateDialogItem(gTheDialog, progressUser); } break; case codecProgressClose: // display the final percentage and delay for an instant GenericProgress(codecProgressForceUpdatePercent, 0x10000, refCon); Delay(1, &ticks); GetWindowPosition(gTheDialog, &thePoint); (*gPrefs)->progressLoc = thePoint; if (gTheDialog) DisposeDialog(gTheDialog); gTheDialog = nil; UserDialogActivate(FrontWindow(), true); break; } // restore the original port and check for aborts SetPort(oldPort); if (theErr == noErr && theMessage != codecProgressForceUpdatePercent) theErr = (CheckAbort()) ? codecAbortErr : noErr; // if there was an abort signalled, and the dialog is visible, hide it immediately // to give better user feedback if (theErr == codecAbortErr && gTheDialog && ((WindowPeek)gTheDialog)->visible) HideWindow(gTheDialog); return theErr; } /* * CheckAbort() * * Purpose: Scans the event queue for an aborting keypress * Inputs: none * Returns: true if we should abort * */ Boolean CheckAbort() { static long gLastTime = 0; Boolean aborted = false, callWNE = false; EventRecord theEvent; GrafPtr oldPort; // if we're not in the background, ensure that we get at least 2 ticks of continuous // operation before giving up a full amount of time to others if ((TickCount() - gLastTime) >= 5) callWNE = true; GetPort(&oldPort); SetPort(FrontWindow()); // get the next event; if sleepTime is zero, check event availability first if (callWNE || EventAvail(everyEvent, &theEvent)) { // handle any pending events normally while (WaitNextEvent(everyEvent, &theEvent, 0, nil)) { // dispatch the event as appropriate switch (theEvent.what) { case mouseDown: aborted = HandleAbortMouseDown(&theEvent); break; case keyDown: case autoKey: aborted = HandleAbortKeyDown(&theEvent); break; case updateEvt: SetPort((WindowPtr)theEvent.message); BeginUpdate((WindowPtr)theEvent.message); if (((WindowPeek)theEvent.message)->windowKind == dialogKind) UpdtDialog((DialogPtr)theEvent.message, ((DialogPtr)theEvent.message)->visRgn); EndUpdate((WindowPtr)theEvent.message); break; case kHighLevelEvent: gProcessing = true; AEProcessAppleEvent(&theEvent); gProcessing = false; break; } } if (callWNE) gLastTime = TickCount(); } SetPort(oldPort); return aborted; } Boolean GiveTime() { EventRecord theEvent; GrafPtr oldPort; GetPort(&oldPort); SetPort(FrontWindow()); // handle any pending events normally while (WaitNextEvent(everyEvent & ~(mDownMask + keyDownMask + autoKeyMask), &theEvent, 0, nil)) { // dispatch the event as appropriate switch (theEvent.what) { case updateEvt: SetPort((WindowPtr)theEvent.message); BeginUpdate((WindowPtr)theEvent.message); if (((WindowPeek)theEvent.message)->windowKind == dialogKind) UpdtDialog((DialogPtr)theEvent.message, ((DialogPtr)theEvent.message)->visRgn); EndUpdate((WindowPtr)theEvent.message); break; case kHighLevelEvent: gProcessing = true; AEProcessAppleEvent(&theEvent); gProcessing = false; break; } } SetPort(oldPort); return true; } Boolean HandleAbortMouseDown(EventRecord *theEvent) { Boolean aborted = false; // handle dialog events properly; if button 3 was hit on the progress dialog, // we abort the drawing if (IsDialogEvent(theEvent)) { DialogPtr theDialog; short itemHit; SetCursor(&qd.arrow); if (DialogSelect(theEvent, &theDialog, &itemHit)) { if (GetWRefCon(theDialog) == kProgressDialogID && itemHit == progressCancel) return true; return false; } } // otherwise, do it the hard way.... else { WindowPtr theWindow; short thePart = FindWindow(theEvent->where, &theWindow); // track dragging and menus as normal; check specially for clicks in // the slide show controls floating window, and beep about everything else switch (thePart) { case inDrag: if (theWindow == FrontWindow()) DragWindow(theWindow, theEvent->where, &qd.screenBits.bounds); break; case inMenuBar: SetCursor(&qd.arrow); DoMenu ( MenuSelect ( theEvent->where )); break; default: SysBeep(1); break; } } return aborted; } Boolean HandleAbortKeyDown(EventRecord *theEvent) { char theChar = theEvent->message & charCodeMask; DialogPtr theDialog = FrontWindow(); Boolean aborted = false; if (GetWRefCon(theDialog) == kProgressDialogID) { // if escape, set the proper abort flag if (((theEvent->modifiers & cmdKey) && theChar == '.') || theChar == 0x1b) { long ticks; aborted = true; HiliteDControl(theDialog, progressCancel, 1); Delay(8, &ticks); HiliteDControl(theDialog, progressCancel, 0); } } return aborted; } //===================================================================================== // pascal void UpdateBar(DialogPtr theDialog, short theItem) //===================================================================================== // Draws the progress bar for the generic progress dialog, according to the percentage // stored in the global gProgressPercent. //===================================================================================== pascal void UpdateBar(DialogPtr theDialog, short theItem) { static RGBColor gBarBackground = { 0xcccc, 0xcccc, 0xffff }; static RGBColor gBarForeground = { 0x4000, 0x4000, 0x4000 }; static RGBColor gBlack = { 0x0000, 0x0000, 0x0000 }; static RGBColor gWhite = { 0xffff, 0xffff, 0xffff }; Boolean useBW = !(((CGrafPtr)theDialog)->portVersion & 0xc000) || (*((CGrafPtr)theDialog)->portPixMap)->pixelSize == 1; Rect itemRect, leftRect, rightRect; Handle itemHandle; GrafPtr oldPort; Fixed thePercent; short itemType; GetPort(&oldPort); SetPort(theDialog); thePercent = gProgressPercent; GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); PenSize(1, 1); if (useBW) PenPat(&qd.black); else RGBForeColor(&gBlack); FrameRect(&itemRect); InsetRect(&itemRect, 1, 1); rightRect = leftRect = itemRect; leftRect.right = itemRect.left + FixRound(FixMul(thePercent, Long2Fix(itemRect.right - itemRect.left))); rightRect.left = leftRect.right; if (leftRect.right > leftRect.left) { if (useBW) PenPat(&qd.black); else RGBForeColor(&gBarForeground); PaintRect(&leftRect); } if (rightRect.left < rightRect.right) { if (useBW) PenPat(&qd.white); else RGBForeColor(&gBarBackground); PaintRect(&rightRect); } if (useBW) PenPat(&qd.black); else RGBForeColor(&gBlack); SetPort(oldPort); } void SetItemHandle(DialogPtr theDialog, short theItem, Handle newHandle) { Handle itemHandle; short itemType; Rect itemRect; GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); SetDItem(theDialog, theItem, itemType, newHandle, &itemRect); } Handle GetItemHandle(DialogPtr theDialog, short theItem) { Handle itemHandle; short itemType; Rect itemRect; GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); return itemHandle; } void UpdateDialogItem(DialogPtr theDialog, short theItem) { Handle itemHandle; RgnHandle theRgn; short itemType; Rect itemRect; GrafPtr oldPort; if (theRgn = NewRgn()) { GetPort(&oldPort); SetPort(theDialog); GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); RectRgn(theRgn, &itemRect); UpdateDialog(theDialog, theRgn); SetPort(oldPort); DisposeRgn(theRgn); } } void HiliteDControl(DialogPtr theDialog, short theItem, short theVal) { Handle itemHandle; short itemType; Rect itemRect; GrafPtr oldPort; GetPort(&oldPort); SetPort(theDialog); GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); HiliteControl((ControlHandle)itemHandle, theVal); SetPort(oldPort); } //================================================================================================================================== // OSErr LoadPrefsHandle(OSType type, short index, Handle *theHandle) //================================================================================================================================== // Reads the specified resource from the Pathmaker preferences file. //================================================================================================================================== OSErr LoadPrefsHandle(OSType type, short index, Handle *theHandle) { return LoadHandleFromResource(GetPrefsSpec(), type, index, theHandle); } //================================================================================================================================== // OSErr SavePrefsHandle(OSType type, short index, Handle theHandle, short *id) //================================================================================================================================== // Saves the specified handle to the Pathmaker preferences file as a resource. //================================================================================================================================== OSErr SavePrefsHandle(OSType type, short index, Handle theHandle, short *id) { return SaveHandleAsResource(GetPrefsSpec(), 'pref', type, index, theHandle, id); } //================================================================================================================================== // OSErr LoadHandleFromResource(FSSpec *file, OSType type, short index, Handle *theHandle) // OSErr LoadHandleFromResource(short theFile, OSType type, short index, Handle *theHandle) //================================================================================================================================== // Reads the specified resource from the given file file and detaches it. //================================================================================================================================== OSErr LoadHandleFromResource(FSSpec *file, OSType type, short index, Handle *theHandle) { OSErr theErr = noErr; short theFile = FSpOpenResFile(file, fsRdPerm); if (theFile != -1) { theErr = LoadHandleFromResource(theFile, type, index, theHandle); CloseResFile(theFile); } else theErr = ResError(); return theErr; } OSErr LoadHandleFromResource(short theFile, OSType type, short index, Handle *theHandle) { short oldRes = CurResFile(); UseResFile(theFile); OSErr theErr = noErr; if (*theHandle = Get1Resource(type, index)) DetachResource(*theHandle); else theErr = fnfErr; // need to signal something since ResError() == 0 UseResFile(oldRes); return theErr; } //================================================================================================================================== // OSErr SaveHandleAsResource(FSSpec *file, OSType fileType, OSType type, short index, Handle *theHandle, short *id) // OSErr SaveHandleAsResource(short theFile, OSType type, short index, Handle theHandle, short *id) //================================================================================================================================== // Writes the specified handle to the given file as a resource. //================================================================================================================================== OSErr SaveHandleAsResource(FSSpec *file, OSType fileType, OSType type, short index, Handle theHandle, short *id) { OSErr theErr = noErr; FSpCreateResFile(file, kCreator, fileType, 0); short theFile = FSpOpenResFile(file, fsRdWrPerm); if (theFile != -1) { theErr = SaveHandleAsResource(theFile, type, index, theHandle, id); CloseResFile(theFile); } else theErr = ResError(); return theErr; } OSErr SaveHandleAsResource(short theFile, OSType type, short index, Handle theHandle, short *id) { short oldRes = CurResFile(); UseResFile(theFile); OSErr theErr = noErr; if (id) *id = index; Handle oldResource = Get1Resource(type, index); if (oldResource) { RmveResource(oldResource); theErr = ResError(); if (theErr == noErr) { DisposeHandle(oldResource); UpdateResFile(theFile); } else ReleaseResource(oldResource); } if (theErr == noErr) { AddResource(theHandle, type, index, (StringPtr)"\p"); theErr = ResError(); if (theErr == noErr) { WriteResource(theHandle); theErr = ResError(); if (theErr == noErr) { UpdateResFile(theFile); theErr = ResError(); } DetachResource(theHandle); } } UseResFile(oldRes); return theErr; } //================================================================================================================================== // FSSpec *GetPrefsSpec(void) //================================================================================================================================== // Returns an FSSpec pointing to our preferences file. //================================================================================================================================== FSSpec *GetPrefsSpec(void) { static FSSpec theSpec = { 0, 0, "\p" }; if (!*theSpec.name) { FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder, &theSpec.vRefNum, &theSpec.parID); FSMakeFSSpec(theSpec.vRefNum, theSpec.parID, kPrefsFileName, &theSpec); } return &theSpec; } void LoadPrefs(void) { Handle theHandle; OSErr theErr = LoadPrefsHandle('Pref', 0, &theHandle); if (theErr != noErr) { theErr = PtrToHand(&gDefaultPrefs, &theHandle, sizeof(Prefs)); theErr = SavePrefsHandle('Pref', 0, theHandle); } gPrefs = (PrefsHandle)theHandle; theErr = LoadPrefsHandle('E2Ty', 0, &theHandle); if (theErr != noErr) { theHandle = Get1Resource('E2Ty', 0); if (theHandle) { DetachResource(theHandle); theErr = SavePrefsHandle('E2Ty', 0, theHandle); } } gMapResource = theHandle; } void SavePrefs(void) { OSErr theErr = SavePrefsHandle('Pref', 0, (Handle)gPrefs); if (theErr == noErr) theErr = SavePrefsHandle('E2Ty', 0, gMapResource); } void SetWindowPosition(WindowPtr theWindow, Point thePosition) { Point centerPos; Rect monRect; if (gHasCQD) monRect = (*GetMainDevice())->gdRect; else monRect = qd.screenBits.bounds; centerPos.h = (monRect.right - monRect.left) - (theWindow->portRect.right - theWindow->portRect.left); centerPos.v = (monRect.bottom - monRect.top) - (theWindow->portRect.bottom - theWindow->portRect.top); centerPos.h /= 2; centerPos.v /= 3; centerPos.h += monRect.left; centerPos.v += monRect.top + 20; if (thePosition.h || thePosition.v) { Rect newRect = theWindow->portRect; RgnHandle theRgn; OffsetRect(&newRect, thePosition.h - newRect.left, thePosition.v - newRect.top); if (theRgn = NewRgn()) { SetRectRgn(theRgn, newRect.left + 4, newRect.top - 20 + 4, newRect.right - 4, newRect.top - 4); SectRgn(theRgn, GetGrayRgn(), theRgn); if (EmptyRgn(theRgn)) thePosition = centerPos; DisposeRgn(theRgn); } } else thePosition = centerPos; MoveWindow(theWindow, thePosition.h, thePosition.v, false); } void GetWindowPosition(WindowPtr theWindow, Point *thePosition) { GrafPtr oldPort; GetPort(&oldPort); SetPort(theWindow); thePosition->h = thePosition->v = 0; LocalToGlobal(thePosition); SetPort(oldPort); } void ForceFolderUpdate(long dirID, short vRefNum) { static CInfoPBRec block; block.hFileInfo.ioCompletion = nil; block.hFileInfo.ioNamePtr = nil; block.hFileInfo.ioVRefNum = vRefNum; block.hFileInfo.ioDirID = dirID; block.hFileInfo.ioFDirIndex = -1; PBGetCatInfoAsync(&block); while (block.hFileInfo.ioResult == 1) GiveTime(); GetDateTime(&block.dirInfo.ioDrMdDat); PBSetCatInfoAsync(&block); // while (block.hFileInfo.ioResult == 1) GiveTime(); }