//============================================================================ //---------------------------------------------------------------------------- // Utilities.c //---------------------------------------------------------------------------- //============================================================================ #include #include #include #include #include #include #include "Externs.h" #include "Utilities.h" GDHandle thisGDevice; UInt32 theSeed; extern Boolean switchedOut; //============================================================== Functions //-------------------------------------------------------------- MyGetGlobalMouse // Returns the position of the mouse in global coordinates. Point MyGetGlobalMouse (void) { Point localWhere; GetMouse(&localWhere); LocalToGlobal(&localWhere); return (localWhere); } //-------------------------------------------------------------- ToolBoxInit // The standard ToolBox intialization that must happen when any MacÉ // program first launches. void ToolBoxInit (void) { #if !TARGET_CARBON InitGraf(&qd.thePort); InitFonts(); FlushEvents(everyEvent, 0); InitWindows(); InitMenus(); TEInit(); InitDialogs(nil); MaxApplZone(); MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters(); GetDateTime((UInt32 *)&qd.randSeed); #endif InitCursor(); switchedOut = false; } //-------------------------------------------------------------- RandomInt // Returns a random integer (short) within "range". short RandomInt (short range) { register long rawResult; rawResult = Random(); if (rawResult < 0L) rawResult *= -1L; rawResult = (rawResult * (long)range) / 32768L; return ((short)rawResult); } //-------------------------------------------------------------- RandomLong // Returns a random long interger within "range". long RandomLong (long range) { register long highWord, lowWord; register long rawResultHi, rawResultLo; highWord = (range & 0xFFFF0000) >> 16; lowWord = range & 0x0000FFFF; rawResultHi = Random(); if (rawResultHi < 0L) rawResultHi *= -1L; rawResultHi = (rawResultHi * highWord) / 32768L; rawResultLo = Random(); if (rawResultLo < 0L) rawResultLo *= -1L; rawResultLo = (rawResultLo * lowWord) / 32768L; rawResultHi = (rawResultHi << 16) + rawResultLo; return (rawResultHi); } //-------------------------------------------------------------- InitRandomLongQUS // Initializes random seed for quick & dirty long random number function (below). void InitRandomLongQUS (void) { GetDateTime(&theSeed); } //-------------------------------------------------------------- RandomLongQUS // Very simple (but fast) pseudo-random number generator. UInt32 RandomLongQUS (void) { theSeed = theSeed * 1103515245 + 12345; return (theSeed); } //-------------------------------------------------------------- RedAlert // Called when we must quit app. Brings up a dialog informing userÉ // of the problem and the exits to shell. void RedAlert (short errorNumber) { #define rDeathAlertID 170 // alert res. ID for death error #define rErrTitleID 170 // string ID for death error title #define rErrMssgID 171 // string ID for death error message short dummyInt; Str255 errTitle, errMessage, errNumberString; InitCursor(); if (errorNumber > 1) // <= 0 is unaccounted for { GetIndString(errTitle, rErrTitleID, errorNumber); GetIndString(errMessage, rErrMssgID, errorNumber); } else { GetIndString(errTitle, rErrTitleID, 1); GetIndString(errMessage, rErrMssgID, 1); } NumToString((long)errorNumber, errNumberString); ParamText(errTitle, errMessage, errNumberString, "\p"); // CenterAlert(rDeathAlertID); dummyInt = Alert(rDeathAlertID, nil); ExitToShell(); } //-------------------------------------------------------------- FindOurDevice // Finds the main device (monitor with the menu bar on it). void FindOurDevice (void) { thisGDevice = GetMainDevice(); if (thisGDevice == nil) RedAlert(kErrFailedGetDevice); } //-------------------------------------------------------------- CreateOffScreenBitMap // Creates an offscreen bit map (b&w - 1 bit depth). /* void CreateOffScreenBitMap (Rect *theRect, GrafPtr *offScreen) { GrafPtr theBWPort; BitMap theBitMap; long theRowBytes; theBWPort = (GrafPtr)(NewPtr(sizeof(GrafPort))); OpenPort(theBWPort); theRowBytes = (long)((theRect->right - theRect->left + 15L) / 16L) * 2L; theBitMap.rowBytes = (short)theRowBytes; theBitMap.baseAddr = NewPtr((long)theBitMap.rowBytes * (theRect->bottom - theRect->top)); if (theBitMap.baseAddr == nil) RedAlert(kErrNoMemory); theBitMap.bounds = *theRect; if (MemError() != noErr) RedAlert(kErrNoMemory); SetPortBits(&theBitMap); ClipRect(theRect); RectRgn(theBWPort->visRgn, theRect); EraseRect(theRect); *offScreen = theBWPort; } */ //-------------------------------------------------------------- CreateOffScreenPixMap // Creates an offscreen pix map using the depth of the current device. /* void CreateOffScreenPixMap (Rect *theRect, CGrafPtr *offScreen) { CTabHandle thisColorTable; GDHandle oldDevice; CGrafPtr newCGrafPtr; Ptr theseBits; long sizeOfOff, offRowBytes; OSErr theErr; short thisDepth; char wasState; oldDevice = GetGDevice(); SetGDevice(thisGDevice); newCGrafPtr = nil; newCGrafPtr = (CGrafPtr)NewPtr(sizeof(CGrafPort)); if (newCGrafPtr != nil) { OpenCPort(newCGrafPtr); thisDepth = (**(*newCGrafPtr).portPixMap).pixelSize; offRowBytes = ((((long)thisDepth * (long)(theRect->right - theRect->left)) + 15L) >> 4L) << 1L; sizeOfOff = (long)(theRect->bottom - theRect->top + 1) * offRowBytes; // sizeOfOff = (long)(theRect->bottom - theRect->top) * offRowBytes; OffsetRect(theRect, -theRect->left, -theRect->top); theseBits = NewPtr(sizeOfOff); if (theseBits != nil) { // workaround (**(*newCGrafPtr).portPixMap).baseAddr = theseBits + offRowBytes; // (**(*newCGrafPtr).portPixMap).baseAddr = theseBits; (**(*newCGrafPtr).portPixMap).rowBytes = (short)offRowBytes + 0x8000; (**(*newCGrafPtr).portPixMap).bounds = *theRect; wasState = HGetState((Handle)thisGDevice); HLock((Handle)thisGDevice); thisColorTable = (**(**thisGDevice).gdPMap).pmTable; HSetState((Handle)thisGDevice, wasState); theErr = HandToHand((Handle *)&thisColorTable); (**(*newCGrafPtr).portPixMap).pmTable = thisColorTable; ClipRect(theRect); RectRgn(newCGrafPtr->visRgn, theRect); ForeColor(blackColor); BackColor(whiteColor); EraseRect(theRect); } else { CloseCPort(newCGrafPtr); DisposePtr((Ptr)newCGrafPtr); newCGrafPtr = nil; RedAlert(kErrNoMemory); } } else RedAlert(kErrNoMemory); *offScreen = newCGrafPtr; SetGDevice(oldDevice); } */ //-------------------------------------------------------------------- CreateOffScreenGWorld // Creates an offscreen GWorldÊusing the depth passed in. OSErr CreateOffScreenGWorld (GWorldPtr *theGWorld, Rect *bounds, short depth) { OSErr theErr; theErr = NewGWorld(theGWorld, depth, bounds, nil, nil, useTempMem); if (theErr) theErr = NewGWorld(theGWorld, depth, bounds, nil, nil, 0); LockPixels(GetGWorldPixMap(*theGWorld)); return theErr; } //-------------------------------------------------------------- KillOffScreenPixMap // Destroys memory allocated by an offscreen pix map. /* void KillOffScreenPixMap (CGrafPtr offScreen) { Ptr theseBits; if (offScreen != nil) { theseBits = (**(*offScreen).portPixMap).baseAddr; theseBits -= (**(*offScreen).portPixMap).rowBytes & 0x7FFF; // workaround DisposePtr(theseBits); DisposeHandle((Handle)(**(*offScreen).portPixMap).pmTable); CloseCPort(offScreen); DisposePtr((Ptr)offScreen); } } */ //-------------------------------------------------------------- KillOffScreenBitMap // Destroys memory allocated by an offscreen bit map. /* void KillOffScreenBitMap (GrafPtr offScreen) { if (offScreen != nil) { DisposePtr((Ptr)(offScreen->portBits.baseAddr)); ClosePort(offScreen); DisposePtr((Ptr)offScreen); } } */ //-------------------------------------------------------------- LoadGraphic // Function loads the specified 'PICT' from disk and draws it toÉ // the current port (no scaling, clipping, etc, are done). AlwaysÉ // draws in the upper left corner of current port. void LoadGraphic (short resID) { Rect bounds; PicHandle thePicture; thePicture = GetPicture(resID); if (thePicture == nil) RedAlert(kErrFailedGraphicLoad); HLock((Handle)thePicture); bounds = (*thePicture)->picFrame; HUnlock((Handle)thePicture); OffsetRect(&bounds, -bounds.left, -bounds.top); DrawPicture(thePicture, &bounds); ReleaseResource((Handle)thePicture); } //-------------------------------------------------------------- LoadScaledGraphic // Loads the specified 'PICT' and draws it mapped to the rectangleÉ // specified. If this rect isn't the same size of the 'PICT', scalingÉ // will occur. void LoadScaledGraphic (short resID, Rect *theRect) { PicHandle thePicture; thePicture = GetPicture(resID); if (thePicture == nil) RedAlert(kErrFailedGraphicLoad); DrawPicture(thePicture, theRect); ReleaseResource((Handle)thePicture); } //-------------------------------------------------------------- PlotSICN // Draws a small icon (16 x 16 pixels). /* void PlotSICN (Rect *theRect, SICNHand theSICN, long theIndex) { char state; BitMap srcBits; if ((theSICN != nil) && ((GetHandleSize((Handle)theSICN) / sizeof(SICN)) > theIndex)) { state = HGetState((Handle)theSICN); HLock((Handle)theSICN); srcBits.baseAddr = (Ptr)(*theSICN)[theIndex]; srcBits.rowBytes = 2; SetRect(&srcBits.bounds, 0, 0, 16, 16); CopyBits(&srcBits,&(*qd.thePort).portBits, &srcBits.bounds, theRect, srcCopy, nil); HSetState((Handle) theSICN, state); } } */ //-------------------------------------------------------------- LargeIconPlot // Draws a standard b&w icon (32 x 32) - resource is an 'ICON'. void LargeIconPlot (Rect *theRect, short theID) { OSErr theErr; Handle theSuite; theErr = GetIconSuite(&theSuite, theID, svAllLargeData); if (theErr == noErr) theErr = PlotIconSuite(theRect, atNone, ttNone, theSuite); } //-------------------------------------------------------------- DrawCIcon // Draws a standard color icon (32 x 32) - resource is a 'CICN'. void DrawCIcon (short theID, short h, short v) { CIconHandle theIcon; Rect theRect; theIcon = GetCIcon(theID); if (theIcon != nil) { SetRect(&theRect, 0, 0, 32, 32); OffsetRect(&theRect, h, v); PlotCIcon(&theRect, theIcon); DisposeCIcon(theIcon); } } //-------------------------------------------------------------- LongSquareRoot // This is a quick and dirty square root function that returns prettyÉ // accurate long integer results. It uses no transcendental functions orÉ // floating point. long LongSquareRoot (long theNumber) { long currentAnswer; long nextTrial; if (theNumber <= 1L) return (theNumber); nextTrial = theNumber / 2; do { currentAnswer = nextTrial; nextTrial = (nextTrial + theNumber / nextTrial) / 2; } while (nextTrial < currentAnswer); return(currentAnswer); } //-------------------------------------------------------------- WaitForInputEvent // Wait for either a key to be hit or the mouse button to be clicked. // Also has a "timeout" parameter ("seconds"). Boolean WaitForInputEvent (short seconds) { EventRecord theEvent; KeyMap theKeys; long timeToBail; Boolean waiting, didResume; timeToBail = TickCount() + 60L * (long)seconds; FlushEvents(everyEvent, 0); waiting = true; didResume = false; while (waiting) { GetKeys(theKeys); if ((BitTst(&theKeys, kCommandKeyMap)) || (BitTst(&theKeys, kOptionKeyMap)) || (BitTst(&theKeys, kShiftKeyMap)) || (BitTst(&theKeys, kControlKeyMap))) waiting = false; if (GetNextEvent(everyEvent, &theEvent)) { if ((theEvent.what == mouseDown) || (theEvent.what == keyDown)) waiting = false; else if ((theEvent.what == osEvt) && (theEvent.message & 0x01000000)) { if (theEvent.message & 0x00000001) // resuming { didResume = true; waiting = false; } else // suspending { InitCursor(); } } } if ((seconds != -1) && (TickCount() >= timeToBail)) waiting = false; } FlushEvents(everyEvent, 0); return (didResume); } //-------------------------------------------------------------- WaitCommandQReleased // Waits until the Command-Q key combination is released. void WaitCommandQReleased (void) { KeyMap theKeys; Boolean waiting; waiting = true; while (waiting) { GetKeys(theKeys); if ((!BitTst(&theKeys, kCommandKeyMap)) || (!BitTst(&theKeys, kQKeyMap))) waiting = false; } FlushEvents(everyEvent, 0); } //-------------------------------------------------------------- KeyMapOffsetFromRawKey // Converts a raw key code to keymap offset (ugly stuff). char KeyMapOffsetFromRawKey (char rawKeyCode) { char hiByte, loByte, theOffset; hiByte = rawKeyCode & 0xF0; loByte = rawKeyCode & 0x0F; if (loByte <= 0x07) theOffset = hiByte + (0x07 - loByte); else theOffset = hiByte + (0x17 - loByte); return (theOffset); } //-------------------------------------------------------------- GetKeyMapFromMessage // Gets the key map offset from a keyDown event's message field. char GetKeyMapFromMessage (long message) { long theVirtual; char offset; theVirtual = (message & keyCodeMask) >> 8; offset = KeyMapOffsetFromRawKey((char)theVirtual); return (offset); } //-------------------------------------------------------------- GetKeyName // Given a keyDown event (it's message field), this function returnsÉ // a string with that key's name (so we get "Shift" and "Esc", etc.). void GetKeyName (long message, StringPtr theName) { long theASCII, theVirtual; theASCII = message & charCodeMask; theVirtual = (message & keyCodeMask) >> 8; if ((theASCII >= kExclamationASCII) && (theASCII <= kZKeyASCII)) { if ((theVirtual >= 0x0041) && (theVirtual <= 0x005C)) { PasStringCopy("\p( )", theName); theName[2] = (char)theASCII; } else { PasStringCopy("\p key", theName); theName[1] = (char)theASCII; } } else { switch (theASCII) { case kHomeKeyASCII: PasStringCopy("\phome", theName); break; case kEnterKeyASCII: PasStringCopy("\penter", theName); break; case kEndKeyASCII: PasStringCopy("\pend", theName); break; case kHelpKeyASCII: PasStringCopy("\phelp", theName); break; case kDeleteKeyASCII: PasStringCopy("\pdelete", theName); break; case kTabKeyASCII: PasStringCopy("\ptab", theName); break; case kPageUpKeyASCII: PasStringCopy("\ppg up", theName); break; case kPageDownKeyASCII: PasStringCopy("\ppg dn", theName); break; case kReturnKeyASCII: PasStringCopy("\preturn", theName); break; case kFunctionKeyASCII: switch (theVirtual) { case 0x0060: PasStringCopy("\pF5", theName); break; case 0x0061: PasStringCopy("\pF6", theName); break; case 0x0062: PasStringCopy("\pF7", theName); break; case 0x0063: PasStringCopy("\pF3", theName); break; case 0x0064: PasStringCopy("\pF8", theName); break; case 0x0065: PasStringCopy("\pF9", theName); break; case 0x0067: PasStringCopy("\pF11", theName); break; case 0x0069: PasStringCopy("\pF13", theName); break; case 0x006B: PasStringCopy("\pF14", theName); break; case 0x006D: PasStringCopy("\pF10", theName); break; case 0x006F: PasStringCopy("\pF12", theName); break; case 0x0071: PasStringCopy("\pF15", theName); break; case 0x0076: PasStringCopy("\pF4", theName); break; case 0x0078: PasStringCopy("\pF2", theName); break; case 0x007A: PasStringCopy("\pF1", theName); break; default: NumToString(theVirtual, theName); break; } break; case kClearKeyASCII: PasStringCopy("\pclear", theName); break; case kEscapeKeyASCII: if (theVirtual == 0x0047) PasStringCopy("\pclear", theName); else PasStringCopy("\pesc", theName); break; case kLeftArrowKeyASCII: PasStringCopy("\plf arrow", theName); break; case kRightArrowKeyASCII: PasStringCopy("\prt arrow", theName); break; case kUpArrowKeyASCII: PasStringCopy("\pup arrow", theName); break; case kDownArrowKeyASCII: PasStringCopy("\pdn arrow", theName); break; case kSpaceBarASCII: PasStringCopy("\pspace", theName); break; case kForwardDeleteASCII: PasStringCopy("\pfrwd del", theName); break; default: PasStringCopy("\p????", theName); break; } } } //-------------------------------------------------------------- OptionKeyDown // Returns true is the Option key is being held down. Boolean OptionKeyDown (void) { KeyMap theKeys; GetKeys(theKeys); if (BitTst(&theKeys, kOptionKeyMap)) return (true); else return (false); } //-------------------------------------------------------------- ExtractCTSeed // Very esoteric - gets the "color table seed" from a specified graf port. /* long ExtractCTSeed (CGrafPtr porter) { long theSeed; theSeed = (**((**(porter->portPixMap)).pmTable)).ctSeed; return(theSeed); } */ //-------------------------------------------------------------- ForceCTSeed // Forces the "color table seed" from a specified graf port to aÉ // specified value. /* void ForceCTSeed (CGrafPtr porter, long newSeed) { (**((**(porter->portPixMap)).pmTable)).ctSeed = newSeed; } */ //-------------------------------------------------------------- DelayTicks // Lil' function that just sits and waits a specified number ofÉ // Ticks (1/60 of a second). void DelayTicks (long howLong) { UInt32 whoCares; Delay(howLong, &whoCares); } //-------------------------------------------------------------- UnivGetSoundVolume // Returns the speaker volume (as set by the user) in the range ofÉ // zero to seven (handles Sound Manager 3 case as well). void UnivGetSoundVolume (short *volume, Boolean hasSM3) { #pragma unused (hasSM3) long longVol; OSErr theErr; // if (hasSM3) // { theErr = GetDefaultOutputVolume(&longVol); *volume = LoWord(longVol) / 0x0024; // } // else // GetSoundVol(volume); if (*volume > 7) *volume = 7; else if (*volume < 0) *volume = 0; } //-------------------------------------------------------------- UnivSetSoundVolume // Sets the speaker volume to a specified value (in the range ofÉ // zero to seven (handles Sound Manager 3 case as well). void UnivSetSoundVolume (short volume, Boolean hasSM3) { #pragma unused (hasSM3) long longVol; OSErr theErr; if (volume > 7) volume = 7; else if (volume < 0) volume = 0; // if (hasSM3) // { longVol = (long)volume * 0x0025; if (longVol > 0x00000100) longVol = 0x00000100; longVol = longVol + (longVol << 16); theErr = SetDefaultOutputVolume(longVol); // } // else // SetSoundVol(volume); }