ref: d488fabe62aabd0d42421eb3e423a9308ae1fa13
dir: /src/OSGLUOSX.c/
/* OSGLUOSX.c Copyright (C) 2009 Philip Cummins, Richard F. Bannister, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* Operating System GLUe for macintosh OS X All operating system dependent code for the Macintosh platform should go here. This code is descended from Richard F. Bannister's Macintosh port of vMac, by Philip Cummins. The main entry point 'main' is at the end of this file. */ #include "CNFGRAPI.h" #include "SYSDEPNS.h" #include "ENDIANAC.h" #include "MYOSGLUE.h" /* --- adapting to API/ABI version differences --- */ /* if UsingCarbonLib, instead of native Macho, then some APIs are missing */ #ifndef UsingCarbonLib #define UsingCarbonLib 0 #endif LOCALVAR CFBundleRef AppServBunRef; LOCALVAR blnr DidApplicationServicesBun = falseblnr; LOCALFUNC blnr HaveApplicationServicesBun(void) { if (! DidApplicationServicesBun) { AppServBunRef = CFBundleGetBundleWithIdentifier( CFSTR("com.apple.ApplicationServices")); DidApplicationServicesBun = trueblnr; } return (AppServBunRef != NULL); } #if MayFullScreen || UsingCarbonLib LOCALVAR CFBundleRef HIToolboxBunRef; LOCALVAR blnr DidHIToolboxBunRef = falseblnr; LOCALFUNC blnr HaveHIToolboxBunRef(void) { if (! DidHIToolboxBunRef) { HIToolboxBunRef = CFBundleGetBundleWithIdentifier( CFSTR("com.apple.HIToolbox")); DidHIToolboxBunRef = trueblnr; } return (HIToolboxBunRef != NULL); } #endif LOCALVAR CFBundleRef AGLBunRef; LOCALVAR blnr DidAGLBunRef = falseblnr; LOCALFUNC blnr HaveAGLBunRef(void) { if (! DidAGLBunRef) { AGLBunRef = CFBundleGetBundleWithIdentifier( CFSTR("com.apple.agl")); DidAGLBunRef = trueblnr; } return (AGLBunRef != NULL); } #if MayFullScreen /* SetSystemUIModeProcPtr API always not available */ typedef UInt32 MySystemUIMode; typedef OptionBits MySystemUIOptions; enum { MykUIModeNormal = 0, MykUIModeAllHidden = 3 }; enum { MykUIOptionAutoShowMenuBar = 1 << 0, MykUIOptionDisableAppleMenu = 1 << 2, MykUIOptionDisableProcessSwitch = 1 << 3, MykUIOptionDisableForceQuit = 1 << 4, MykUIOptionDisableSessionTerminate = 1 << 5, MykUIOptionDisableHide = 1 << 6 }; typedef OSStatus (*SetSystemUIModeProcPtr) (MySystemUIMode inMode, MySystemUIOptions inOptions); LOCALVAR SetSystemUIModeProcPtr MySetSystemUIMode = NULL; LOCALVAR blnr DidSetSystemUIMode = falseblnr; LOCALFUNC blnr HaveMySetSystemUIMode(void) { if (! DidSetSystemUIMode) { if (HaveHIToolboxBunRef()) { MySetSystemUIMode = (SetSystemUIModeProcPtr) CFBundleGetFunctionPointerForName( HIToolboxBunRef, CFSTR("SetSystemUIMode")); } DidSetSystemUIMode = trueblnr; } return (MySetSystemUIMode != NULL); } #endif /* In 10.1 or later */ typedef OSStatus (*LSCopyDisplayNameForRefProcPtr) (const FSRef *inRef, CFStringRef *outDisplayName); LOCALVAR LSCopyDisplayNameForRefProcPtr MyLSCopyDisplayNameForRef = NULL; LOCALVAR blnr DidLSCopyDisplayNameForRef = falseblnr; LOCALFUNC blnr HaveMyLSCopyDisplayNameForRef(void) { if (! DidLSCopyDisplayNameForRef) { if (HaveApplicationServicesBun()) { MyLSCopyDisplayNameForRef = (LSCopyDisplayNameForRefProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("LSCopyDisplayNameForRef")); } DidLSCopyDisplayNameForRef = trueblnr; } return (MyLSCopyDisplayNameForRef != NULL); } /* In 10.5 or later */ typedef GLboolean (*aglSetWindowRefProcPtr) (AGLContext ctx, WindowRef window); LOCALVAR aglSetWindowRefProcPtr MyaglSetWindowRef = NULL; LOCALVAR blnr DidaglSetWindowRef = falseblnr; LOCALFUNC blnr HaveMyaglSetWindowRef(void) { if (! DidaglSetWindowRef) { if (HaveAGLBunRef()) { MyaglSetWindowRef = (aglSetWindowRefProcPtr) CFBundleGetFunctionPointerForName( AGLBunRef, CFSTR("aglSetWindowRef")); } DidaglSetWindowRef = trueblnr; } return (MyaglSetWindowRef != NULL); } /* Deprecated as of 10.5 */ typedef CGrafPtr My_AGLDrawable; typedef GLboolean (*aglSetDrawableProcPtr) (AGLContext ctx, My_AGLDrawable draw); LOCALVAR aglSetDrawableProcPtr MyaglSetDrawable = NULL; LOCALVAR blnr DidaglSetDrawable = falseblnr; LOCALFUNC blnr HaveMyaglSetDrawable(void) { if (! DidaglSetDrawable) { if (HaveAGLBunRef()) { MyaglSetDrawable = (aglSetDrawableProcPtr) CFBundleGetFunctionPointerForName( AGLBunRef, CFSTR("aglSetDrawable")); } DidaglSetDrawable = trueblnr; } return (MyaglSetDrawable != NULL); } /* routines not in carbon lib */ #if UsingCarbonLib typedef CGDisplayErr (*CGGetActiveDisplayListProcPtr) ( CGDisplayCount maxDisplays, CGDirectDisplayID * activeDspys, CGDisplayCount * dspyCnt); LOCALVAR CGGetActiveDisplayListProcPtr MyCGGetActiveDisplayList = NULL; LOCALVAR blnr DidCGGetActiveDisplayList = falseblnr; LOCALFUNC blnr HaveMyCGGetActiveDisplayList(void) { if (! DidCGGetActiveDisplayList) { if (HaveApplicationServicesBun()) { MyCGGetActiveDisplayList = (CGGetActiveDisplayListProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("CGGetActiveDisplayList")); } DidCGGetActiveDisplayList = trueblnr; } return (MyCGGetActiveDisplayList != NULL); } #else #define HaveMyCGGetActiveDisplayList() trueblnr #define MyCGGetActiveDisplayList CGGetActiveDisplayList #endif /* ! UsingCarbonLib */ #if UsingCarbonLib typedef CGRect (*CGDisplayBoundsProcPtr) (CGDirectDisplayID display); LOCALVAR CGDisplayBoundsProcPtr MyCGDisplayBounds = NULL; LOCALVAR blnr DidCGDisplayBounds = falseblnr; LOCALFUNC blnr HaveMyCGDisplayBounds(void) { if (! DidCGDisplayBounds) { if (HaveApplicationServicesBun()) { MyCGDisplayBounds = (CGDisplayBoundsProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("CGDisplayBounds")); } DidCGDisplayBounds = trueblnr; } return (MyCGDisplayBounds != NULL); } #else #define HaveMyCGDisplayBounds() trueblnr #define MyCGDisplayBounds CGDisplayBounds #endif /* ! UsingCarbonLib */ #if UsingCarbonLib typedef size_t (*CGDisplayPixelsWideProcPtr) (CGDirectDisplayID display); LOCALVAR CGDisplayPixelsWideProcPtr MyCGDisplayPixelsWide = NULL; LOCALVAR blnr DidCGDisplayPixelsWide = falseblnr; LOCALFUNC blnr HaveMyCGDisplayPixelsWide(void) { if (! DidCGDisplayPixelsWide) { if (HaveApplicationServicesBun()) { MyCGDisplayPixelsWide = (CGDisplayPixelsWideProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("CGDisplayPixelsWide")); } DidCGDisplayPixelsWide = trueblnr; } return (MyCGDisplayPixelsWide != NULL); } #else #define HaveMyCGDisplayPixelsWide() trueblnr #define MyCGDisplayPixelsWide CGDisplayPixelsWide #endif /* ! UsingCarbonLib */ #if UsingCarbonLib typedef size_t (*CGDisplayPixelsHighProcPtr) (CGDirectDisplayID display); LOCALVAR CGDisplayPixelsHighProcPtr MyCGDisplayPixelsHigh = NULL; LOCALVAR blnr DidCGDisplayPixelsHigh = falseblnr; LOCALFUNC blnr HaveMyCGDisplayPixelsHigh(void) { if (! DidCGDisplayPixelsHigh) { if (HaveApplicationServicesBun()) { MyCGDisplayPixelsHigh = (CGDisplayPixelsHighProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("CGDisplayPixelsHigh")); } DidCGDisplayPixelsHigh = trueblnr; } return (MyCGDisplayPixelsHigh != NULL); } #else #define HaveMyCGDisplayPixelsHigh() trueblnr #define MyCGDisplayPixelsHigh CGDisplayPixelsHigh #endif /* ! UsingCarbonLib */ #if UsingCarbonLib typedef CGDisplayErr (*CGDisplayHideCursorProcPtr) (CGDirectDisplayID display); LOCALVAR CGDisplayHideCursorProcPtr MyCGDisplayHideCursor = NULL; LOCALVAR blnr DidCGDisplayHideCursor = falseblnr; LOCALFUNC blnr HaveMyCGDisplayHideCursor(void) { if (! DidCGDisplayHideCursor) { if (HaveApplicationServicesBun()) { MyCGDisplayHideCursor = (CGDisplayHideCursorProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("CGDisplayHideCursor")); } DidCGDisplayHideCursor = trueblnr; } return (MyCGDisplayHideCursor != NULL); } #else #define HaveMyCGDisplayHideCursor() trueblnr #define MyCGDisplayHideCursor CGDisplayHideCursor #endif /* ! UsingCarbonLib */ #if UsingCarbonLib typedef CGDisplayErr (*CGDisplayShowCursorProcPtr) (CGDirectDisplayID display); LOCALVAR CGDisplayShowCursorProcPtr MyCGDisplayShowCursor = NULL; LOCALVAR blnr DidCGDisplayShowCursor = falseblnr; LOCALFUNC blnr HaveMyCGDisplayShowCursor(void) { if (! DidCGDisplayShowCursor) { if (HaveApplicationServicesBun()) { MyCGDisplayShowCursor = (CGDisplayShowCursorProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("CGDisplayShowCursor")); } DidCGDisplayShowCursor = trueblnr; } return (MyCGDisplayShowCursor != NULL); } #else #define HaveMyCGDisplayShowCursor() trueblnr #define MyCGDisplayShowCursor CGDisplayShowCursor #endif /* ! UsingCarbonLib */ #if 0 typedef CGDisplayErr (*CGDisplayMoveCursorToPointProcPtr) (CGDirectDisplayID display, CGPoint point); LOCALVAR CGDisplayMoveCursorToPointProcPtr MyCGDisplayMoveCursorToPoint = NULL; LOCALVAR blnr DidCGDisplayMoveCursorToPoint = falseblnr; LOCALFUNC blnr HaveMyCGDisplayMoveCursorToPoint(void) { if (! DidCGDisplayMoveCursorToPoint) { if (HaveApplicationServicesBun()) { MyCGDisplayMoveCursorToPoint = (CGDisplayMoveCursorToPointProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("CGDisplayMoveCursorToPoint")); } DidCGDisplayMoveCursorToPoint = trueblnr; } return (MyCGDisplayMoveCursorToPoint != NULL); } #endif /* 0 */ #if UsingCarbonLib typedef CGEventErr (*CGWarpMouseCursorPositionProcPtr) (CGPoint newCursorPosition); LOCALVAR CGWarpMouseCursorPositionProcPtr MyCGWarpMouseCursorPosition = NULL; LOCALVAR blnr DidCGWarpMouseCursorPosition = falseblnr; LOCALFUNC blnr HaveMyCGWarpMouseCursorPosition(void) { if (! DidCGWarpMouseCursorPosition) { if (HaveApplicationServicesBun()) { MyCGWarpMouseCursorPosition = (CGWarpMouseCursorPositionProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("CGWarpMouseCursorPosition")); } DidCGWarpMouseCursorPosition = trueblnr; } return (MyCGWarpMouseCursorPosition != NULL); } #else #define HaveMyCGWarpMouseCursorPosition() trueblnr #define MyCGWarpMouseCursorPosition CGWarpMouseCursorPosition #endif /* ! UsingCarbonLib */ #if UsingCarbonLib typedef CGEventErr (*CGSetLocalEventsSuppressionIntervalProcPtr) (CFTimeInterval seconds); LOCALVAR CGSetLocalEventsSuppressionIntervalProcPtr MyCGSetLocalEventsSuppressionInterval = NULL; LOCALVAR blnr DidCGSetLocalEventsSuppressionInterval = falseblnr; LOCALFUNC blnr HaveMyCGSetLocalEventsSuppressionInterval(void) { if (! DidCGSetLocalEventsSuppressionInterval) { if (HaveApplicationServicesBun()) { MyCGSetLocalEventsSuppressionInterval = (CGSetLocalEventsSuppressionIntervalProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("CGSetLocalEventsSuppressionInterval")); } DidCGSetLocalEventsSuppressionInterval = trueblnr; } return (MyCGSetLocalEventsSuppressionInterval != NULL); } #else #define HaveMyCGSetLocalEventsSuppressionInterval() trueblnr #define MyCGSetLocalEventsSuppressionInterval \ CGSetLocalEventsSuppressionInterval #endif /* ! UsingCarbonLib */ #if UsingCarbonLib typedef OSStatus (*CreateStandardAlertProcPtr) ( AlertType alertType, CFStringRef error, CFStringRef explanation, const AlertStdCFStringAlertParamRec * param, DialogRef * outAlert ); LOCALVAR CreateStandardAlertProcPtr MyCreateStandardAlert = NULL; LOCALVAR blnr DidCreateStandardAlert = falseblnr; LOCALFUNC blnr HaveMyCreateStandardAlert(void) { if (! DidCreateStandardAlert) { if (HaveHIToolboxBunRef()) { MyCreateStandardAlert = (CreateStandardAlertProcPtr) CFBundleGetFunctionPointerForName( HIToolboxBunRef, CFSTR("CreateStandardAlert")); } DidCreateStandardAlert = trueblnr; } return (MyCreateStandardAlert != NULL); } #else #define HaveMyCreateStandardAlert() trueblnr #define MyCreateStandardAlert CreateStandardAlert #endif /* ! UsingCarbonLib */ #if UsingCarbonLib typedef OSStatus (*RunStandardAlertProcPtr) ( DialogRef inAlert, ModalFilterUPP filterProc, DialogItemIndex * outItemHit ); LOCALVAR RunStandardAlertProcPtr MyRunStandardAlert = NULL; LOCALVAR blnr DidRunStandardAlert = falseblnr; LOCALFUNC blnr HaveMyRunStandardAlert(void) { if (! DidRunStandardAlert) { if (HaveHIToolboxBunRef()) { MyRunStandardAlert = (RunStandardAlertProcPtr) CFBundleGetFunctionPointerForName( HIToolboxBunRef, CFSTR("RunStandardAlert")); } DidRunStandardAlert = trueblnr; } return (MyRunStandardAlert != NULL); } #else #define HaveMyRunStandardAlert() trueblnr #define MyRunStandardAlert RunStandardAlert #endif /* ! UsingCarbonLib */ typedef CGDirectDisplayID (*CGMainDisplayIDProcPtr)(void); LOCALVAR CGMainDisplayIDProcPtr MyCGMainDisplayID = NULL; LOCALVAR blnr DidCGMainDisplayID = falseblnr; LOCALFUNC blnr HaveMyCGMainDisplayID(void) { if (! DidCGMainDisplayID) { if (HaveApplicationServicesBun()) { MyCGMainDisplayID = (CGMainDisplayIDProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("CGMainDisplayID")); } DidCGMainDisplayID = trueblnr; } return (MyCGMainDisplayID != NULL); } #ifndef kCGNullDirectDisplay /* not in MPW Headers */ #define kCGNullDirectDisplay ((CGDirectDisplayID)0) #endif typedef CGError (*CGDisplayRegisterReconfigurationCallbackProcPtr) ( CGDisplayReconfigurationCallBack proc, void *userInfo ); LOCALVAR CGDisplayRegisterReconfigurationCallbackProcPtr MyCGDisplayRegisterReconfigurationCallback = NULL; LOCALVAR blnr DidCGDisplayRegisterReconfigurationCallback = falseblnr; LOCALFUNC blnr HaveMyCGDisplayRegisterReconfigurationCallback(void) { if (! DidCGDisplayRegisterReconfigurationCallback) { if (HaveApplicationServicesBun()) { MyCGDisplayRegisterReconfigurationCallback = (CGDisplayRegisterReconfigurationCallbackProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("CGDisplayRegisterReconfigurationCallback")); } DidCGDisplayRegisterReconfigurationCallback = trueblnr; } return (MyCGDisplayRegisterReconfigurationCallback != NULL); } typedef CGError (*CGDisplayRemoveReconfigurationCallbackProcPtr) ( CGDisplayReconfigurationCallBack proc, void *userInfo ); LOCALVAR CGDisplayRemoveReconfigurationCallbackProcPtr MyCGDisplayRemoveReconfigurationCallback = NULL; LOCALVAR blnr DidCGDisplayRemoveReconfigurationCallback = falseblnr; LOCALFUNC blnr HaveMyCGDisplayRemoveReconfigurationCallback(void) { if (! DidCGDisplayRemoveReconfigurationCallback) { if (HaveApplicationServicesBun()) { MyCGDisplayRemoveReconfigurationCallback = (CGDisplayRemoveReconfigurationCallbackProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("CGDisplayRemoveReconfigurationCallback")); } DidCGDisplayRemoveReconfigurationCallback = trueblnr; } return (MyCGDisplayRemoveReconfigurationCallback != NULL); } typedef boolean_t (*CGCursorIsVisibleProcPtr)(void); LOCALVAR CGCursorIsVisibleProcPtr MyCGCursorIsVisible = NULL; LOCALVAR blnr DidCGCursorIsVisible = falseblnr; LOCALFUNC blnr HaveMyCGCursorIsVisible(void) { if (! DidCGCursorIsVisible) { if (HaveApplicationServicesBun()) { MyCGCursorIsVisible = (CGCursorIsVisibleProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("CGCursorIsVisible")); } DidCGCursorIsVisible = trueblnr; } return (MyCGCursorIsVisible != NULL); } /* --- end of adapting to API/ABI version differences --- */ /* --- some simple utilities --- */ GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount) { (void) memcpy((char *)destPtr, (char *)srcPtr, byteCount); } LOCALPROC PStrFromChar(ps3p r, char x) { r[0] = 1; r[1] = (char)x; } /* --- mac style errors --- */ #define CheckSavetMacErr(result) (mnvm_noErr == (err = (result))) /* where 'err' is a variable of type tMacErr in the function this is used in */ #define To_tMacErr(result) ((tMacErr)(ui4b)(result)) #define CheckSaveMacErr(result) (CheckSavetMacErr(To_tMacErr(result))) #include "STRCONST.h" #define NeedCell2UnicodeMap 1 #include "INTLCHAR.h" LOCALPROC UniCharStrFromSubstCStr(int *L, UniChar *x, char *s) { int i; int L0; ui3b ps[ClStrMaxLength]; ClStrFromSubstCStr(&L0, ps, s); for (i = 0; i < L0; ++i) { x[i] = Cell2UnicodeMap[ps[i]]; } *L = L0; } #define NotAfileRef (-1) LOCALFUNC tMacErr MyMakeFSRefUniChar(FSRef *ParentRef, UniCharCount fileNameLength, const UniChar *fileName, blnr *isFolder, FSRef *ChildRef) { tMacErr err; Boolean isFolder0; Boolean isAlias; if (CheckSaveMacErr(FSMakeFSRefUnicode(ParentRef, fileNameLength, fileName, kTextEncodingUnknown, ChildRef))) if (CheckSaveMacErr(FSResolveAliasFile(ChildRef, TRUE, &isFolder0, &isAlias))) { *isFolder = isFolder0; } return err; } LOCALFUNC tMacErr MyMakeFSRefC(FSRef *ParentRef, char *fileName, blnr *isFolder, FSRef *ChildRef) { int L; UniChar x[ClStrMaxLength]; UniCharStrFromSubstCStr(&L, x, fileName); return MyMakeFSRefUniChar(ParentRef, L, x, isFolder, ChildRef); } #if UseActvFile LOCALFUNC tMacErr OpenNamedFileInFolderRef(FSRef *ParentRef, char *fileName, short *refnum) { tMacErr err; blnr isFolder; FSRef ChildRef; HFSUniStr255 forkName; if (CheckSavetMacErr(MyMakeFSRefC(ParentRef, fileName, &isFolder, &ChildRef))) if (CheckSaveMacErr(FSGetDataForkName(&forkName))) if (CheckSaveMacErr(FSOpenFork(&ChildRef, forkName.length, forkName.unicode, fsRdPerm, refnum))) { /* ok */ } return err; } #endif #if dbglog_HAVE || UseActvFile LOCALFUNC tMacErr OpenWriteNamedFileInFolderRef(FSRef *ParentRef, char *fileName, short *refnum) { tMacErr err; blnr isFolder; FSRef ChildRef; HFSUniStr255 forkName; int L; UniChar x[ClStrMaxLength]; UniCharStrFromSubstCStr(&L, x, fileName); err = MyMakeFSRefUniChar(ParentRef, L, x, &isFolder, &ChildRef); if (mnvm_fnfErr == err) { err = To_tMacErr(FSCreateFileUnicode(ParentRef, L, x, 0, NULL, &ChildRef, NULL)); } if (mnvm_noErr == err) { if (CheckSaveMacErr(FSGetDataForkName(&forkName))) if (CheckSaveMacErr(FSOpenFork(&ChildRef, forkName.length, forkName.unicode, fsRdWrPerm, refnum))) { /* ok */ } } return err; } #endif LOCALFUNC tMacErr FindNamedChildRef(FSRef *ParentRef, char *ChildName, FSRef *ChildRef) { tMacErr err; blnr isFolder; if (CheckSavetMacErr(MyMakeFSRefC(ParentRef, ChildName, &isFolder, ChildRef))) { if (! isFolder) { err = mnvm_miscErr; } } return err; } #if UseActvFile || (IncludeSonyNew && ! SaveDialogEnable) LOCALFUNC tMacErr FindOrMakeNamedChildRef(FSRef *ParentRef, char *ChildName, FSRef *ChildRef) { tMacErr err; blnr isFolder; int L; UniChar x[ClStrMaxLength]; UniCharStrFromSubstCStr(&L, x, ChildName); if (CheckSavetMacErr(MyMakeFSRefUniChar(ParentRef, L, x, &isFolder, ChildRef))) { if (! isFolder) { err = mnvm_miscErr; } } if (mnvm_fnfErr == err) { err = To_tMacErr(FSCreateDirectoryUnicode( ParentRef, L, x, kFSCatInfoNone, NULL, ChildRef, NULL, NULL)); } return err; } #endif LOCALVAR FSRef MyDatDirRef; LOCALVAR CFStringRef MyAppName = NULL; LOCALPROC UnInitMyApplInfo(void) { if (MyAppName != NULL) { CFRelease(MyAppName); } } LOCALFUNC blnr InitMyApplInfo(void) { ProcessSerialNumber currentProcess = {0, kCurrentProcess}; FSRef fsRef; FSRef parentRef; if (noErr == GetProcessBundleLocation(¤tProcess, &fsRef)) if (noErr == FSGetCatalogInfo(&fsRef, kFSCatInfoNone, NULL, NULL, NULL, &parentRef)) { FSRef ContentsRef; FSRef DatRef; MyDatDirRef = parentRef; if (mnvm_noErr == FindNamedChildRef(&fsRef, "Contents", &ContentsRef)) if (mnvm_noErr == FindNamedChildRef(&ContentsRef, "mnvm_dat", &DatRef)) { MyDatDirRef = DatRef; } if (HaveMyLSCopyDisplayNameForRef()) { if (noErr == MyLSCopyDisplayNameForRef(&fsRef, &MyAppName)) { return trueblnr; } } if (noErr == CopyProcessName(¤tProcess, &MyAppName)) { return trueblnr; } } return falseblnr; } /* --- sending debugging info to file --- */ #if dbglog_HAVE LOCALVAR SInt16 dbglog_File = NotAfileRef; LOCALFUNC blnr dbglog_open0(void) { tMacErr err; err = OpenWriteNamedFileInFolderRef(&MyDatDirRef, "dbglog.txt", &dbglog_File); return (mnvm_noErr == err); } LOCALPROC dbglog_write0(char *s, uimr L) { ByteCount actualCount; if (dbglog_File != NotAfileRef) { (void) FSWriteFork( dbglog_File, fsFromMark, 0, L, s, &actualCount); } } LOCALPROC dbglog_close0(void) { if (dbglog_File != NotAfileRef) { (void) FSSetForkSize(dbglog_File, fsFromMark, 0); (void) FSCloseFork(dbglog_File); dbglog_File = NotAfileRef; } } #endif #if 1 /* (0 != vMacScreenDepth) && (vMacScreenDepth < 4) */ #define WantColorTransValid 1 #endif #include "COMOSGLU.h" /* --- time, date --- */ /* be sure to avoid getting confused if TickCount overflows and wraps. */ #define dbglog_TimeStuff (0 && dbglog_HAVE) LOCALVAR ui5b TrueEmulatedTime = 0; LOCALVAR EventTime NextTickChangeTime; #define MyTickDuration (kEventDurationSecond / 60.14742) LOCALPROC UpdateTrueEmulatedTime(void) { EventTime LatestTime = GetCurrentEventTime(); EventTime TimeDiff = LatestTime - NextTickChangeTime; if (TimeDiff >= 0.0) { if (TimeDiff > 16 * MyTickDuration) { /* emulation interrupted, forget it */ ++TrueEmulatedTime; NextTickChangeTime = LatestTime + MyTickDuration; #if dbglog_TimeStuff dbglog_writelnNum("emulation interrupted", TrueEmulatedTime); #endif } else { do { ++TrueEmulatedTime; TimeDiff -= MyTickDuration; NextTickChangeTime += MyTickDuration; } while (TimeDiff >= 0.0); } } } GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void) { UpdateTrueEmulatedTime(); return TrueEmulatedTime == OnTrueTime; } /* LOCALVAR EventTime ETimeBase; */ LOCALVAR CFAbsoluteTime ATimeBase; LOCALVAR ui5b TimeSecBase; LOCALFUNC blnr CheckDateTime(void) { ui5b NewMacDateInSecond = TimeSecBase + (ui5b)(CFAbsoluteTimeGetCurrent() - ATimeBase); /* ui5b NewMacDateInSecond = TimeSecBase + (ui5b)(GetCurrentEventTime() - ETimeBase); */ /* ui5b NewMacDateInSecond = ((ui5b)(CFAbsoluteTimeGetCurrent())) + 3061137600UL; */ if (CurMacDateInSeconds != NewMacDateInSecond) { CurMacDateInSeconds = NewMacDateInSecond; return trueblnr; } else { return falseblnr; } } /* --- parameter buffers --- */ #include "PBUFSTDC.h" /* --- drives --- */ LOCALVAR SInt16 Drives[NumDrives]; /* open disk image files */ GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer, tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *Sony_ActCount) { ByteCount actualCount; tMacErr result; if (IsWrite) { result = To_tMacErr(FSWriteFork( Drives[Drive_No], fsFromStart, Sony_Start, Sony_Count, Buffer, &actualCount)); } else { result = To_tMacErr(FSReadFork( Drives[Drive_No], fsFromStart, Sony_Start, Sony_Count, Buffer, &actualCount)); } if (nullpr != Sony_ActCount) { *Sony_ActCount = actualCount; } return result; } GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count) { SInt64 forkSize; tMacErr err = To_tMacErr( FSGetForkSize(Drives[Drive_No], &forkSize)); *Sony_Count = forkSize; return err; } GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No) { SInt16 refnum = Drives[Drive_No]; Drives[Drive_No] = NotAfileRef; DiskEjectedNotify(Drive_No); (void) FSCloseFork(refnum); return mnvm_noErr; } #if IncludeSonyNew GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No) { FSRef ref; tMacErr err0; tMacErr err; err0 = To_tMacErr(FSGetForkCBInfo(Drives[Drive_No], 0, NULL /* iterator */, NULL /* actualRefNum */, NULL /* forkInfo */, &ref /* ref */, NULL /* outForkName */)); err = vSonyEject(Drive_No); if (mnvm_noErr != err0) { err = err0; } else { (void) FSDeleteObject(&ref); } return err; } #endif #if IncludeSonyGetName GLOBALOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r) { FSRef ref; HFSUniStr255 outName; CFStringRef DiskName; tMacErr err; if (CheckSaveMacErr(FSGetForkCBInfo(Drives[Drive_No], 0, NULL /* iterator */, NULL /* actualRefNum */, NULL /* forkInfo */, &ref /* ref */, NULL /* outForkName */))) if (CheckSaveMacErr(FSGetCatalogInfo(&ref, kFSCatInfoNone /* whichInfo */, NULL /* catalogInfo */, &outName /* outName */, NULL /* fsSpec */, NULL /* parentRef */))) { DiskName = CFStringCreateWithCharacters( kCFAllocatorDefault, outName.unicode, outName.length); if (NULL != DiskName) { tPbuf i; if (CheckSavetMacErr(PbufNew(outName.length, &i))) { if (CFStringGetBytes(DiskName, CFRangeMake(0, outName.length), kCFStringEncodingMacRoman, '?', false, PbufDat[i], outName.length, NULL) != outName.length) { err = mnvm_miscErr; } if (mnvm_noErr != err) { PbufDispose(i); } else { *r = i; } } CFRelease(DiskName); } } return err; } #endif #if IncludeHostTextClipExchange GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i) { tMacErr err; ScrapRef scrapRef; if (CheckSaveMacErr(ClearCurrentScrap())) if (CheckSaveMacErr(GetCurrentScrap(&scrapRef))) if (CheckSaveMacErr(PutScrapFlavor( scrapRef, FOUR_CHAR_CODE('TEXT'), kScrapFlavorMaskNone, PbufSize[i], PbufDat[i]))) { /* ok */ } PbufDispose(i); return err; } #endif #if IncludeHostTextClipExchange GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r) { tMacErr err; ScrapRef scrap; ScrapFlavorFlags flavorFlags; Size byteCount; tPbuf i; if (CheckSaveMacErr(GetCurrentScrap(&scrap))) if (CheckSaveMacErr(GetScrapFlavorFlags(scrap, 'TEXT', &flavorFlags))) if (CheckSaveMacErr(GetScrapFlavorSize(scrap, 'TEXT', &byteCount))) if (CheckSavetMacErr(PbufNew(byteCount, &i))) { Size byteCount2 = byteCount; if (CheckSaveMacErr(GetScrapFlavorData(scrap, 'TEXT', &byteCount2, PbufDat[i]))) { if (byteCount != byteCount2) { err = mnvm_miscErr; } } if (mnvm_noErr != err) { PbufDispose(i); } else { *r = i; } } return err; } #endif #if EmLocalTalk #include "BPFILTER.h" #endif /* --- control mode and internationalization --- */ #define WantKeyboard_RemapMac 1 #include "CONTROLM.h" /* --- video out --- */ LOCALVAR WindowPtr gMyMainWindow = NULL; LOCALVAR WindowPtr gMyOldWindow = NULL; #if MayFullScreen LOCALVAR short hOffset; LOCALVAR short vOffset; #endif #if MayFullScreen LOCALVAR blnr GrabMachine = falseblnr; #endif #if VarFullScreen LOCALVAR blnr UseFullScreen = (WantInitFullScreen != 0); #endif #if EnableMagnify LOCALVAR blnr UseMagnify = (WantInitMagnify != 0); #endif #if EnableMagnify LOCALPROC MyScaleRect(Rect *r) { r->left *= MyWindowScale; r->right *= MyWindowScale; r->top *= MyWindowScale; r->bottom *= MyWindowScale; } #endif LOCALPROC SetScrnRectFromCoords(Rect *r, si4b top, si4b left, si4b bottom, si4b right) { r->left = left; r->right = right; r->top = top; r->bottom = bottom; #if VarFullScreen if (UseFullScreen) #endif #if MayFullScreen { OffsetRect(r, - ViewHStart, - ViewVStart); } #endif #if EnableMagnify if (UseMagnify) { MyScaleRect(r); } #endif #if VarFullScreen if (UseFullScreen) #endif #if MayFullScreen { OffsetRect(r, hOffset, vOffset); } #endif } LOCALVAR ui3p ScalingBuff = nullpr; LOCALVAR ui3p CLUT_final; #define CLUT_finalsz1 (256 * 8) #if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) #define CLUT_finalClrSz (256 << (5 - vMacScreenDepth)) #define CLUT_finalsz ((CLUT_finalClrSz > CLUT_finalsz1) \ ? CLUT_finalClrSz : CLUT_finalsz1) #else #define CLUT_finalsz CLUT_finalsz1 #endif #define ScrnMapr_DoMap UpdateBWLuminanceCopy #define ScrnMapr_Src GetCurDrawBuff() #define ScrnMapr_Dst ScalingBuff #define ScrnMapr_SrcDepth 0 #define ScrnMapr_DstDepth 3 #define ScrnMapr_Map CLUT_final #include "SCRNMAPR.h" #if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) #define ScrnMapr_DoMap UpdateMappedColorCopy #define ScrnMapr_Src GetCurDrawBuff() #define ScrnMapr_Dst ScalingBuff #define ScrnMapr_SrcDepth vMacScreenDepth #define ScrnMapr_DstDepth 5 #define ScrnMapr_Map CLUT_final #include "SCRNMAPR.h" #endif #if vMacScreenDepth >= 4 #define ScrnTrns_DoTrans UpdateTransColorCopy #define ScrnTrns_Src GetCurDrawBuff() #define ScrnTrns_Dst ScalingBuff #define ScrnTrns_SrcDepth vMacScreenDepth #define ScrnTrns_DstDepth 5 #define ScrnTrns_DstZLo 1 #include "SCRNTRNS.h" #endif LOCALPROC UpdateLuminanceCopy(si4b top, si4b left, si4b bottom, si4b right) { int i; #if 0 != vMacScreenDepth if (UseColorMode) { #if vMacScreenDepth < 4 if (! ColorTransValid) { int j; int k; ui5p p4; p4 = (ui5p)CLUT_final; for (i = 0; i < 256; ++i) { for (k = 1 << (3 - vMacScreenDepth); --k >= 0; ) { j = (i >> (k << vMacScreenDepth)) & (CLUT_size - 1); *p4++ = (((long)CLUT_reds[j] & 0xFF00) << 16) | (((long)CLUT_greens[j] & 0xFF00) << 8) | ((long)CLUT_blues[j] & 0xFF00); } } ColorTransValid = trueblnr; } UpdateMappedColorCopy(top, left, bottom, right); #else UpdateTransColorCopy(top, left, bottom, right); #endif } else #endif { if (! ColorTransValid) { int k; ui3p p4 = (ui3p)CLUT_final; for (i = 0; i < 256; ++i) { for (k = 8; --k >= 0; ) { *p4++ = ((i >> k) & 0x01) - 1; } } ColorTransValid = trueblnr; } UpdateBWLuminanceCopy(top, left, bottom, right); } } LOCALVAR AGLContext ctx = NULL; LOCALVAR short GLhOffset; LOCALVAR short GLvOffset; #ifndef UseAGLdoublebuff #define UseAGLdoublebuff 0 #endif LOCALPROC MyDrawWithOpenGL(ui4r top, ui4r left, ui4r bottom, ui4r right) { if (NULL == ctx) { /* oops */ } else if (GL_TRUE != aglSetCurrentContext(ctx)) { /* err = aglReportError() */ } else { si4b top2; si4b left2; #if UseAGLdoublebuff /* redraw all */ top = 0; left = 0; bottom = vMacScreenHeight; right = vMacScreenWidth; #endif #if VarFullScreen if (UseFullScreen) #endif #if MayFullScreen { if (top < ViewVStart) { top = ViewVStart; } if (left < ViewHStart) { left = ViewHStart; } if (bottom > ViewVStart + ViewVSize) { bottom = ViewVStart + ViewVSize; } if (right > ViewHStart + ViewHSize) { right = ViewHStart + ViewHSize; } if ((top >= bottom) || (left >= right)) { goto label_exit; } } #endif top2 = top; left2 = left; #if VarFullScreen if (UseFullScreen) #endif #if MayFullScreen { left2 -= ViewHStart; top2 -= ViewVStart; } #endif #if EnableMagnify if (UseMagnify) { top2 *= MyWindowScale; left2 *= MyWindowScale; } #endif #if 0 glClear(GL_COLOR_BUFFER_BIT); glBitmap(vMacScreenWidth, vMacScreenHeight, 0, 0, 0, 0, (const GLubyte *)GetCurDrawBuff()); #endif #if 1 UpdateLuminanceCopy(top, left, bottom, right); glRasterPos2i(GLhOffset + left2, GLvOffset - top2); #if 0 != vMacScreenDepth if (UseColorMode) { glDrawPixels(right - left, bottom - top, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ScalingBuff + (left + top * vMacScreenWidth) * 4 ); } else #endif { glDrawPixels(right - left, bottom - top, GL_LUMINANCE, GL_UNSIGNED_BYTE, ScalingBuff + (left + top * vMacScreenWidth) ); } #endif #if 0 /* a very quick and dirty check of where drawing */ glDrawPixels(right - left, 1, GL_RED, GL_UNSIGNED_BYTE, ScalingBuff + (left + top * vMacScreenWidth) ); glDrawPixels(1, bottom - top, GL_RED, GL_UNSIGNED_BYTE, ScalingBuff + (left + top * vMacScreenWidth) ); #endif #if UseAGLdoublebuff aglSwapBuffers(ctx); #else glFlush(); #endif } #if MayFullScreen label_exit: ; #endif } LOCALPROC Update_Screen(void) { MyDrawWithOpenGL(0, 0, vMacScreenHeight, vMacScreenWidth); } LOCALPROC MyDrawChangesAndClear(void) { if (ScreenChangedBottom > ScreenChangedTop) { MyDrawWithOpenGL(ScreenChangedTop, ScreenChangedLeft, ScreenChangedBottom, ScreenChangedRight); ScreenClearChanges(); } } LOCALVAR blnr MouseIsOutside = falseblnr; /* MouseIsOutside true if sure mouse outside our window. If in our window, or not sure, set false. */ LOCALVAR blnr WantCursorHidden = falseblnr; LOCALPROC MousePositionNotify(Point NewMousePos) { /* Not MouseIsOutside includes in the title bar, etc, so have to check if in content area. */ Rect r; blnr ShouldHaveCursorHidden = ! MouseIsOutside; GetWindowBounds(gMyMainWindow, kWindowContentRgn, &r); NewMousePos.h -= r.left; NewMousePos.v -= r.top; #if VarFullScreen if (UseFullScreen) #endif #if MayFullScreen { NewMousePos.h -= hOffset; NewMousePos.v -= vOffset; } #endif #if EnableMagnify if (UseMagnify) { NewMousePos.h /= MyWindowScale; NewMousePos.v /= MyWindowScale; } #endif #if VarFullScreen if (UseFullScreen) #endif #if MayFullScreen { NewMousePos.h += ViewHStart; NewMousePos.v += ViewVStart; } #endif #if EnableFSMouseMotion if (HaveMouseMotion) { MyMousePositionSetDelta(NewMousePos.h - SavedMouseH, NewMousePos.v - SavedMouseV); SavedMouseH = NewMousePos.h; SavedMouseV = NewMousePos.v; } else #endif { if (NewMousePos.h < 0) { NewMousePos.h = 0; ShouldHaveCursorHidden = falseblnr; } else if (NewMousePos.h >= vMacScreenWidth) { NewMousePos.h = vMacScreenWidth - 1; ShouldHaveCursorHidden = falseblnr; } if (NewMousePos.v < 0) { NewMousePos.v = 0; ShouldHaveCursorHidden = falseblnr; } else if (NewMousePos.v >= vMacScreenHeight) { NewMousePos.v = vMacScreenHeight - 1; ShouldHaveCursorHidden = falseblnr; } /* if (ShouldHaveCursorHidden || CurMouseButton) */ /* for a game like arkanoid, would like mouse to still move even when outside window in one direction */ MyMousePositionSet(NewMousePos.h, NewMousePos.v); } WantCursorHidden = ShouldHaveCursorHidden; } LOCALPROC CheckMouseState(void) { Point NewMousePos; GetGlobalMouse(&NewMousePos); /* Deprecated, but haven't found usable replacement. Between window deactivate and then reactivate, mouse can move without getting kEventMouseMoved. Also no way to get initial position. (Also don't get kEventMouseMoved after using menu bar. Or while using menubar, but that isn't too important.) */ MousePositionNotify(NewMousePos); } LOCALVAR blnr gLackFocusFlag = falseblnr; LOCALVAR blnr gWeAreActive = falseblnr; GLOBALOSGLUPROC DoneWithDrawingForTick(void) { #if EnableFSMouseMotion if (HaveMouseMotion) { AutoScrollScreen(); } #endif MyDrawChangesAndClear(); } LOCALVAR blnr CurSpeedStopped = trueblnr; /* --- keyboard --- */ LOCALVAR UInt32 SavedModifiers = 0; LOCALPROC MyUpdateKeyboardModifiers(UInt32 theModifiers) { UInt32 ChangedModifiers = theModifiers ^ SavedModifiers; if (0 != ChangedModifiers) { if (0 != (ChangedModifiers & shiftKey)) { Keyboard_UpdateKeyMap2(MKC_formac_Shift, (shiftKey & theModifiers) != 0); } if (0 != (ChangedModifiers & cmdKey)) { Keyboard_UpdateKeyMap2(MKC_formac_Command, (cmdKey & theModifiers) != 0); } if (0 != (ChangedModifiers & alphaLock)) { Keyboard_UpdateKeyMap2(MKC_formac_CapsLock, (alphaLock & theModifiers) != 0); } if (0 != (ChangedModifiers & optionKey)) { Keyboard_UpdateKeyMap2(MKC_formac_Option, (optionKey & theModifiers) != 0); } if (0 != (ChangedModifiers & controlKey)) { Keyboard_UpdateKeyMap2(MKC_formac_Control, (controlKey & theModifiers) != 0); } SavedModifiers = theModifiers; } } LOCALPROC ReconnectKeyCodes3(void) { /* turn off any modifiers (other than alpha) that were turned on by drag and drop, unless still being held down. */ UInt32 theModifiers = GetCurrentKeyModifiers(); MyUpdateKeyboardModifiers(theModifiers & (SavedModifiers | alphaLock)); SavedModifiers = theModifiers; } /* --- display utilities --- */ /* DoForEachDisplay adapted from Apple Technical Q&A QA1168 */ typedef void (*ForEachDisplayProcPtr) (CGDirectDisplayID display); LOCALPROC DoForEachDisplay0(CGDisplayCount dspCount, CGDirectDisplayID *displays, ForEachDisplayProcPtr p) { CGDisplayCount i; if (noErr == MyCGGetActiveDisplayList(dspCount, displays, &dspCount)) { for (i = 0; i < dspCount; ++i) { p(displays[i]); } } } LOCALPROC DoForEachDisplay(ForEachDisplayProcPtr p) { CGDisplayCount dspCount = 0; if (HaveMyCGGetActiveDisplayList() && (noErr == MyCGGetActiveDisplayList(0, NULL, &dspCount))) { if (dspCount <= 2) { CGDirectDisplayID displays[2]; DoForEachDisplay0(dspCount, displays, p); } else { CGDirectDisplayID *displays = calloc((size_t)dspCount, sizeof(CGDirectDisplayID)); if (NULL != displays) { DoForEachDisplay0(dspCount, displays, p); free(displays); } } } } LOCALVAR void *datp; LOCALPROC MyMainDisplayIDProc(CGDirectDisplayID display) { CGDirectDisplayID *p = (CGDirectDisplayID *)datp; if (kCGNullDirectDisplay == *p) { *p = display; } } LOCALFUNC CGDirectDisplayID MyMainDisplayID(void) { if (HaveMyCGMainDisplayID()) { return MyCGMainDisplayID(); } else { /* for before OS X 10.2 */ CGDirectDisplayID r = kCGNullDirectDisplay; void *savedatp = datp; datp = (void *)&r; DoForEachDisplay(MyMainDisplayIDProc); datp = savedatp; return r; } } /* --- cursor hiding --- */ #if 0 LOCALPROC MyShowCursorProc(CGDirectDisplayID display) { (void) CGDisplayShowCursor(display); } #endif LOCALPROC MyShowCursor(void) { #if 0 /* ShowCursor(); deprecated */ DoForEachDisplay(MyShowCursorProc); #endif if (HaveMyCGDisplayShowCursor()) { (void) MyCGDisplayShowCursor(MyMainDisplayID()); /* documentation now claims argument ignored */ } } #if 0 LOCALPROC MyHideCursorProc(CGDirectDisplayID display) { (void) CGDisplayHideCursor(display); } #endif LOCALPROC MyHideCursor(void) { #if 0 /* HideCursor(); deprecated */ DoForEachDisplay(MyHideCursorProc); #endif if (HaveMyCGDisplayHideCursor()) { (void) MyCGDisplayHideCursor(MyMainDisplayID()); /* documentation now claims argument ignored */ } } LOCALVAR blnr HaveCursorHidden = falseblnr; LOCALPROC ForceShowCursor(void) { if (HaveCursorHidden) { HaveCursorHidden = falseblnr; MyShowCursor(); } } /* --- cursor moving --- */ LOCALPROC SetCursorArrow(void) { SetThemeCursor(kThemeArrowCursor); } #if EnableMoveMouse LOCALFUNC blnr MyMoveMouse(si4b h, si4b v) { Point CurMousePos; Rect r; #if VarFullScreen if (UseFullScreen) #endif #if MayFullScreen { h -= ViewHStart; v -= ViewVStart; } #endif #if EnableMagnify if (UseMagnify) { h *= MyWindowScale; v *= MyWindowScale; } #endif #if VarFullScreen if (UseFullScreen) #endif #if MayFullScreen { h += hOffset; v += vOffset; } #endif GetWindowBounds(gMyMainWindow, kWindowContentRgn, &r); CurMousePos.h = r.left + h; CurMousePos.v = r.top + v; /* This method from SDL_QuartzWM.m, "Simple DirectMedia Layer", Copyright (C) 1997-2003 Sam Lantinga */ if (HaveMyCGSetLocalEventsSuppressionInterval()) { if (noErr != MyCGSetLocalEventsSuppressionInterval(0.0)) { /* don't use MacMsg which can call MyMoveMouse */ } } if (HaveMyCGWarpMouseCursorPosition()) { CGPoint pt; pt.x = CurMousePos.h; pt.y = CurMousePos.v; if (noErr != MyCGWarpMouseCursorPosition(pt)) { /* don't use MacMsg which can call MyMoveMouse */ } } #if 0 if (HaveMyCGDisplayMoveCursorToPoint()) { CGPoint pt; pt.x = CurMousePos.h; pt.y = CurMousePos.v; if (noErr != MyCGDisplayMoveCursorToPoint( MyMainDisplayID(), pt)) { /* don't use MacMsg which can call MyMoveMouse */ } } #endif return trueblnr; } #endif #if EnableFSMouseMotion LOCALPROC AdjustMouseMotionGrab(void) { if (gMyMainWindow != NULL) { #if MayFullScreen if (GrabMachine) { /* if magnification changes, need to reset, even if HaveMouseMotion already true */ if (MyMoveMouse(ViewHStart + (ViewHSize / 2), ViewVStart + (ViewVSize / 2))) { SavedMouseH = ViewHStart + (ViewHSize / 2); SavedMouseV = ViewVStart + (ViewVSize / 2); HaveMouseMotion = trueblnr; } } else #endif { if (HaveMouseMotion) { (void) MyMoveMouse(CurMouseH, CurMouseV); HaveMouseMotion = falseblnr; } } } } #endif #if EnableFSMouseMotion LOCALPROC MyMouseConstrain(void) { si4b shiftdh; si4b shiftdv; if (SavedMouseH < ViewHStart + (ViewHSize / 4)) { shiftdh = ViewHSize / 2; } else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4)) { shiftdh = - ViewHSize / 2; } else { shiftdh = 0; } if (SavedMouseV < ViewVStart + (ViewVSize / 4)) { shiftdv = ViewVSize / 2; } else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4)) { shiftdv = - ViewVSize / 2; } else { shiftdv = 0; } if ((shiftdh != 0) || (shiftdv != 0)) { SavedMouseH += shiftdh; SavedMouseV += shiftdv; if (! MyMoveMouse(SavedMouseH, SavedMouseV)) { HaveMouseMotion = falseblnr; } } } #endif #if 0 LOCALFUNC blnr InitMousePosition(void) { /* Since there doesn't seem to be any nondeprecated way to get initial cursor position, instead start by moving cursor to known position. */ #if VarFullScreen if (! UseFullScreen) #endif #if MayNotFullScreen { CurMouseH = 16; CurMouseV = 16; WantCursorHidden = trueblnr; (void) MyMoveMouse(CurMouseH, CurMouseV); } #endif return trueblnr; } #endif /* --- time, date, location, part 2 --- */ #include "DATE2SEC.h" LOCALFUNC blnr InitLocationDat(void) { #if AutoLocation || AutoTimeZone MachineLocation loc; ReadLocation(&loc); #if AutoLocation CurMacLatitude = (ui5b)loc.latitude; CurMacLongitude = (ui5b)loc.longitude; #endif #if AutoTimeZone CurMacDelta = (ui5b)loc.u.gmtDelta; #endif #endif { CFTimeZoneRef tz = CFTimeZoneCopySystem(); if (tz) { /* CFAbsoluteTime */ ATimeBase = CFAbsoluteTimeGetCurrent(); /* ETimeBase = GetCurrentEventTime(); */ { CFGregorianDate d = CFAbsoluteTimeGetGregorianDate( ATimeBase, tz); double floorsec = floor(d.second); ATimeBase -= (d.second - floorsec); /* ETimeBase -= (d.second - floorsec); */ TimeSecBase = Date2MacSeconds(floorsec, d.minute, d.hour, d.day, d.month, d.year); (void) CheckDateTime(); } CFRelease(tz); } } OnTrueTime = TrueEmulatedTime; return trueblnr; } LOCALPROC StartUpTimeAdjust(void) { NextTickChangeTime = GetCurrentEventTime() + MyTickDuration; } /* --- sound --- */ #if MySoundEnabled #define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */ #define kSoundBuffers (1 << kLn2SoundBuffers) #define kSoundBuffMask (kSoundBuffers - 1) #define DesiredMinFilledSoundBuffs 3 /* if too big then sound lags behind emulation. if too small then sound will have pauses. */ #define kLnOneBuffLen 9 #define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen) #define kOneBuffLen (1UL << kLnOneBuffLen) #define kAllBuffLen (1UL << kLnAllBuffLen) #define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3) #define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3) #define kOneBuffSz (1UL << kLnOneBuffSz) #define kAllBuffSz (1UL << kLnAllBuffSz) #define kOneBuffMask (kOneBuffLen - 1) #define kAllBuffMask (kAllBuffLen - 1) #define dbhBufferSize (kAllBuffSz + kOneBuffSz) #define dbglog_SoundStuff (0 && dbglog_HAVE) #define dbglog_SoundBuffStats (0 && dbglog_HAVE) LOCALVAR tpSoundSamp TheSoundBuffer = nullpr; volatile static ui4b ThePlayOffset; volatile static ui4b TheFillOffset; volatile static ui4b MinFilledSoundBuffs; #if dbglog_SoundBuffStats LOCALVAR ui4b MaxFilledSoundBuffs; #endif LOCALVAR ui4b TheWriteOffset; LOCALPROC MySound_Start0(void) { /* Reset variables */ ThePlayOffset = 0; TheFillOffset = 0; TheWriteOffset = 0; MinFilledSoundBuffs = kSoundBuffers + 1; #if dbglog_SoundBuffStats MaxFilledSoundBuffs = 0; #endif } GLOBALOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL) { ui4b ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset); ui4b WriteBuffContig = kOneBuffLen - (TheWriteOffset & kOneBuffMask); if (WriteBuffContig < n) { n = WriteBuffContig; } if (ToFillLen < n) { /* overwrite previous buffer */ #if dbglog_SoundStuff dbglog_writeln("sound buffer over flow"); #endif TheWriteOffset -= kOneBuffLen; } *actL = n; return TheSoundBuffer + (TheWriteOffset & kAllBuffMask); } #if 4 == kLn2SoundSampSz LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p) { int i; for (i = kOneBuffLen; --i >= 0; ) { *p++ -= 0x8000; } } #else #define ConvertSoundBlockToNative(p) #endif LOCALPROC MySound_WroteABlock(void) { #if (4 == kLn2SoundSampSz) ui4b PrevWriteOffset = TheWriteOffset - kOneBuffLen; tpSoundSamp p = TheSoundBuffer + (PrevWriteOffset & kAllBuffMask); #endif #if dbglog_SoundStuff dbglog_writeln("enter MySound_WroteABlock"); #endif ConvertSoundBlockToNative(p); TheFillOffset = TheWriteOffset; #if dbglog_SoundBuffStats { ui4b ToPlayLen = TheFillOffset - ThePlayOffset; ui4b ToPlayBuffs = ToPlayLen >> kLnOneBuffLen; if (ToPlayBuffs > MaxFilledSoundBuffs) { MaxFilledSoundBuffs = ToPlayBuffs; } } #endif } LOCALFUNC blnr MySound_EndWrite0(ui4r actL) { blnr v; TheWriteOffset += actL; if (0 != (TheWriteOffset & kOneBuffMask)) { v = falseblnr; } else { /* just finished a block */ MySound_WroteABlock(); v = trueblnr; } return v; } LOCALPROC MySound_SecondNotify0(void) { if (MinFilledSoundBuffs <= kSoundBuffers) { if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) { #if dbglog_SoundStuff dbglog_writeln("MinFilledSoundBuffs too high"); #endif NextTickChangeTime += MyTickDuration; } else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) { #if dbglog_SoundStuff dbglog_writeln("MinFilledSoundBuffs too low"); #endif ++TrueEmulatedTime; } #if dbglog_SoundBuffStats dbglog_writelnNum("MinFilledSoundBuffs", MinFilledSoundBuffs); dbglog_writelnNum("MaxFilledSoundBuffs", MaxFilledSoundBuffs); MaxFilledSoundBuffs = 0; #endif MinFilledSoundBuffs = kSoundBuffers + 1; } } LOCALPROC RampSound(tpSoundSamp p, trSoundSamp BeginVal, trSoundSamp EndVal) { int i; ui5r v = (((ui5r)BeginVal) << kLnOneBuffLen) + (kLnOneBuffLen >> 1); for (i = kOneBuffLen; --i >= 0; ) { *p++ = v >> kLnOneBuffLen; v = v + EndVal - BeginVal; } } #if 4 == kLn2SoundSampSz #define ConvertSoundSampleFromNative(v) ((v) + 0x8000) #else #define ConvertSoundSampleFromNative(v) (v) #endif struct MySoundR { tpSoundSamp fTheSoundBuffer; volatile ui4b (*fPlayOffset); volatile ui4b (*fFillOffset); volatile ui4b (*fMinFilledSoundBuffs); volatile blnr PlayingBuffBlock; volatile trSoundSamp lastv; volatile blnr wantplaying; volatile blnr StartingBlocks; CmpSoundHeader /* ExtSoundHeader */ soundHeader; }; typedef struct MySoundR MySoundR; /* Some of this code descended from CarbonSndPlayDB, an example from Apple, as found being used in vMac for Mac OS. */ LOCALPROC InsertSndDoCommand(SndChannelPtr chan, SndCommand * newCmd) { if (-1 == chan->qHead) { chan->qHead = chan->qTail; } if (1 <= chan->qHead) { chan->qHead--; } else { chan->qHead = chan->qTail; } chan->queue[chan->qHead] = *newCmd; } /* call back */ static pascal void MySound_CallBack(SndChannelPtr theChannel, SndCommand * theCallBackCmd) { MySoundR *datp = (MySoundR *)(theCallBackCmd->param2); blnr wantplaying0 = datp->wantplaying; trSoundSamp v0 = datp->lastv; #if dbglog_SoundStuff dbglog_writeln("Enter MySound_CallBack"); #endif if (datp->PlayingBuffBlock) { /* finish with last sample */ #if dbglog_SoundStuff dbglog_writeln("done with sample"); #endif *datp->fPlayOffset += kOneBuffLen; datp->PlayingBuffBlock = falseblnr; } if ((! wantplaying0) && (kCenterSound == v0)) { #if dbglog_SoundStuff dbglog_writeln("terminating"); #endif } else { SndCommand playCmd; tpSoundSamp p; trSoundSamp v1 = v0; blnr WantRamp = falseblnr; ui4b CurPlayOffset = *datp->fPlayOffset; ui4b ToPlayLen = *datp->fFillOffset - CurPlayOffset; ui4b FilledSoundBuffs = ToPlayLen >> kLnOneBuffLen; if (FilledSoundBuffs < *datp->fMinFilledSoundBuffs) { *datp->fMinFilledSoundBuffs = FilledSoundBuffs; } if (! wantplaying0) { #if dbglog_SoundStuff dbglog_writeln("playing end transistion"); #endif v1 = kCenterSound; WantRamp = trueblnr; } else if (datp->StartingBlocks) { #if dbglog_SoundStuff dbglog_writeln("playing start block"); #endif if ((ToPlayLen >> kLnOneBuffLen) < 12) { datp->StartingBlocks = falseblnr; #if dbglog_SoundStuff dbglog_writeln("have enough samples to start"); #endif p = datp->fTheSoundBuffer + (CurPlayOffset & kAllBuffMask); v1 = ConvertSoundSampleFromNative(*p); } WantRamp = trueblnr; } else if (0 == FilledSoundBuffs) { #if dbglog_SoundStuff dbglog_writeln("playing under run"); #endif WantRamp = trueblnr; } else { /* play next sample */ p = datp->fTheSoundBuffer + (CurPlayOffset & kAllBuffMask); datp->PlayingBuffBlock = trueblnr; v1 = ConvertSoundSampleFromNative(*(p + kOneBuffLen - 1)); #if dbglog_SoundStuff dbglog_writeln("playing sample"); #endif } if (WantRamp) { p = datp->fTheSoundBuffer + kAllBuffLen; #if dbglog_SoundStuff dbglog_writelnNum("v0", v0); dbglog_writelnNum("v1", v1); #endif RampSound(p, v0, v1); ConvertSoundBlockToNative(p); } datp->soundHeader.samplePtr = (Ptr)p; datp->soundHeader.numFrames = (unsigned long)kOneBuffLen; /* Insert our callback command */ InsertSndDoCommand (theChannel, theCallBackCmd); #if 0 { int i; tpSoundSamp pS = (tpSoundSamp)datp->soundHeader.samplePtr; for (i = datp->soundHeader.numFrames; --i >= 0; ) { fprintf(stderr, "%d\n", *pS++); } } #endif /* Play the next buffer */ playCmd.cmd = bufferCmd; playCmd.param1 = 0; playCmd.param2 = (long)&(datp->soundHeader); InsertSndDoCommand (theChannel, &playCmd); datp->lastv = v1; } } LOCALVAR MySoundR cur_audio; LOCALVAR SndCallBackUPP gCarbonSndPlayDoubleBufferCallBackUPP = NULL; LOCALVAR SndChannelPtr sndChannel = NULL; /* our sound channel */ LOCALPROC MySound_Start(void) { #if dbglog_SoundStuff dbglog_writeln("MySound_Start"); #endif if (NULL == sndChannel) { SndCommand callBack; SndChannelPtr chan = NULL; cur_audio.wantplaying = falseblnr; cur_audio.StartingBlocks = falseblnr; MySound_Start0(); SndNewChannel(&chan, sampledSynth, initMono, nil); if (NULL != chan) { sndChannel = chan; cur_audio.PlayingBuffBlock = falseblnr; cur_audio.lastv = kCenterSound; cur_audio.StartingBlocks = trueblnr; cur_audio.wantplaying = trueblnr; callBack.cmd = callBackCmd; callBack.param1 = 0; /* unused */ callBack.param2 = (long)&cur_audio; sndChannel->callBack = gCarbonSndPlayDoubleBufferCallBackUPP; (void) SndDoCommand (sndChannel, &callBack, true); } } } LOCALPROC MySound_Stop(void) { #if dbglog_SoundStuff dbglog_writeln("enter MySound_Stop"); #endif if (NULL != sndChannel) { ui4r retry_limit = 50; /* half of a second */ SCStatus r; cur_audio.wantplaying = falseblnr; #if dbglog_SoundStuff dbglog_writeln("cleared wantplaying"); #endif label_retry: r.scChannelBusy = falseblnr; /* what is this for? */ if (noErr != SndChannelStatus(sndChannel, sizeof(SCStatus), &r)) { /* fail */ } else if ((! r.scChannelBusy) && (kCenterSound == cur_audio.lastv)) { /* done */ /* observed reporting not busy unexpectedly, so also check lastv. */ } else if (0 == --retry_limit) { #if dbglog_SoundStuff dbglog_writeln("retry limit reached"); #endif /* don't trust SndChannelStatus, make sure don't get in infinite loop. */ /* done */ } else { /* give time back, particularly important if got here on a suspend event. */ struct timespec rqt; struct timespec rmt; #if dbglog_SoundStuff dbglog_writeln("busy, so sleep"); #endif rqt.tv_sec = 0; rqt.tv_nsec = 10000000; (void) nanosleep(&rqt, &rmt); goto label_retry; } SndDisposeChannel(sndChannel, true); sndChannel = NULL; } #if dbglog_SoundStuff dbglog_writeln("leave MySound_Stop"); #endif } #define SOUND_SAMPLERATE rate22khz /* = 0x56EE8BA3 = (7833600 * 2 / 704) << 16 */ LOCALFUNC blnr MySound_Init(void) { #if dbglog_SoundStuff dbglog_writeln("enter MySound_Init"); #endif cur_audio.fTheSoundBuffer = TheSoundBuffer; cur_audio.fPlayOffset = &ThePlayOffset; cur_audio.fFillOffset = &TheFillOffset; cur_audio.fMinFilledSoundBuffs = &MinFilledSoundBuffs; cur_audio.wantplaying = falseblnr; /* Init basic per channel information */ cur_audio.soundHeader.sampleRate = SOUND_SAMPLERATE; /* sample rate */ cur_audio.soundHeader.numChannels = 1; /* one channel */ cur_audio.soundHeader.loopStart = 0; cur_audio.soundHeader.loopEnd = 0; cur_audio.soundHeader.encode = cmpSH /* extSH */; cur_audio.soundHeader.baseFrequency = kMiddleC; cur_audio.soundHeader.numFrames = (unsigned long)kOneBuffLen; /* cur_audio.soundHeader.AIFFSampleRate = 0; */ /* unused */ cur_audio.soundHeader.markerChunk = nil; cur_audio.soundHeader.futureUse2 = 0; cur_audio.soundHeader.stateVars = nil; cur_audio.soundHeader.leftOverSamples = nil; cur_audio.soundHeader.compressionID = 0; /* no compression */ cur_audio.soundHeader.packetSize = 0; /* no compression */ cur_audio.soundHeader.snthID = 0; cur_audio.soundHeader.sampleSize = (1 << kLn2SoundSampSz); /* 8 or 16 bits per sample */ cur_audio.soundHeader.sampleArea[0] = 0; #if 3 == kLn2SoundSampSz cur_audio.soundHeader.format = kSoundNotCompressed; #elif 4 == kLn2SoundSampSz cur_audio.soundHeader.format = k16BitNativeEndianFormat; #else #error "unsupported kLn2SoundSampSz" #endif cur_audio.soundHeader.samplePtr = (Ptr)TheSoundBuffer; gCarbonSndPlayDoubleBufferCallBackUPP = NewSndCallBackUPP(MySound_CallBack); if (gCarbonSndPlayDoubleBufferCallBackUPP != NULL) { MySound_Start(); /* This should be taken care of by LeaveSpeedStopped, but since takes a while to get going properly, start early. */ return trueblnr; } return falseblnr; } GLOBALOSGLUPROC MySound_EndWrite(ui4r actL) { if (MySound_EndWrite0(actL)) { } } LOCALPROC MySound_SecondNotify(void) { if (sndChannel != NULL) { MySound_SecondNotify0(); } } #endif LOCALPROC MyAdjustGLforSize(int h, int v) { if (GL_TRUE != aglSetCurrentContext(ctx)) { /* err = aglReportError() */ } else { glClearColor (0.0, 0.0, 0.0, 1.0); #if 1 glViewport(0, 0, h, v); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, h, 0, v, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); #endif glColor3f(0.0, 0.0, 0.0); #if EnableMagnify if (UseMagnify) { glPixelZoom(MyWindowScale, - MyWindowScale); } else #endif { glPixelZoom(1, -1); } glPixelStorei(GL_UNPACK_ROW_LENGTH, vMacScreenWidth); glClear(GL_COLOR_BUFFER_BIT); if (GL_TRUE != aglSetCurrentContext(NULL)) { /* err = aglReportError() */ } ScreenChangedAll(); } } LOCALVAR blnr WantScreensChangedCheck = falseblnr; LOCALPROC MyUpdateOpenGLContext(void) { if (NULL == ctx) { /* oops */ } else if (GL_TRUE != aglSetCurrentContext(ctx)) { /* err = aglReportError() */ } else { aglUpdateContext(ctx); } } #if 0 /* some experiments */ LOCALVAR CGrafPtr GrabbedPort = NULL; #endif #if 0 LOCALPROC AdjustMainScreenGrab(void) { if (GrabMachine) { if (NULL == GrabbedPort) { /* CGDisplayCapture(MyMainDisplayID()); */ CGCaptureAllDisplays(); /* CGDisplayHideCursor( MyMainDisplayID() ); */ GrabbedPort = CreateNewPortForCGDisplayID((UInt32)MyMainDisplayID()); LockPortBits (GrabbedPort); } } else { if (GrabbedPort != NULL) { UnlockPortBits (GrabbedPort); /* CGDisplayShowCursor( MyMainDisplayID() ); */ /* CGDisplayRelease(MyMainDisplayID()); */ CGReleaseAllDisplays(); GrabbedPort = NULL; } } } #endif #if 0 typedef CGDisplayErr (*CGReleaseAllDisplaysProcPtr) (void); LOCALPROC MyReleaseAllDisplays(void) { if (HaveApplicationServicesBun()) { CGReleaseAllDisplaysProcPtr ReleaseAllDisplaysProc = (CGReleaseAllDisplaysProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("CGReleaseAllDisplays")); if (ReleaseAllDisplaysProc != NULL) { ReleaseAllDisplaysProc(); } } } typedef CGDisplayErr (*CGCaptureAllDisplaysProcPtr) (void); LOCALPROC MyCaptureAllDisplays(void) { if (HaveApplicationServicesBun()) { CGCaptureAllDisplaysProcPtr CaptureAllDisplaysProc = (CGCaptureAllDisplaysProcPtr) CFBundleGetFunctionPointerForName( AppServBunRef, CFSTR("CGCaptureAllDisplays")); if (CaptureAllDisplaysProc != NULL) { CaptureAllDisplaysProc(); } } } #endif LOCALVAR AGLPixelFormat window_fmt = NULL; LOCALVAR AGLContext window_ctx = NULL; #ifndef UseAGLfullscreen #define UseAGLfullscreen 0 #endif #if UseAGLfullscreen LOCALVAR AGLPixelFormat fullscreen_fmt = NULL; LOCALVAR AGLContext fullscreen_ctx = NULL; #endif #if UseAGLfullscreen LOCALPROC MaybeFullScreen(void) { if ( #if VarFullScreen UseFullScreen && #endif (NULL == fullscreen_ctx) && HaveMyCGDisplayPixelsWide() && HaveMyCGDisplayPixelsHigh()) { static const GLint fullscreen_attrib[] = {AGL_RGBA, AGL_NO_RECOVERY, AGL_FULLSCREEN, AGL_SINGLE_RENDERER, AGL_ACCELERATED, #if UseAGLdoublebuff AGL_DOUBLEBUFFER, #endif AGL_NONE}; GDHandle theDevice; CGDirectDisplayID CurMainDisplayID = MyMainDisplayID(); DMGetGDeviceByDisplayID( (DisplayIDType)CurMainDisplayID, &theDevice, false); fullscreen_fmt = aglChoosePixelFormat( &theDevice, 1, fullscreen_attrib); if (NULL == fullscreen_fmt) { /* err = aglReportError() */ } else { fullscreen_ctx = aglCreateContext(fullscreen_fmt, NULL); if (NULL == fullscreen_ctx) { /* err = aglReportError() */ } else { /* MyCaptureAllDisplays(); */ if (GL_TRUE != aglSetFullScreen(fullscreen_ctx, 0, 0, 0, 0)) { /* err = aglReportError() */ } else { Rect r; int h = MyCGDisplayPixelsWide(CurMainDisplayID); int v = MyCGDisplayPixelsHigh(CurMainDisplayID); GetWindowBounds(gMyMainWindow, kWindowContentRgn, &r); GLhOffset = r.left + hOffset; GLvOffset = v - (r.top + vOffset); ctx = fullscreen_ctx; MyAdjustGLforSize(h, v); return; } /* MyReleaseAllDisplays(); */ if (GL_TRUE != aglDestroyContext(fullscreen_ctx)) { /* err = aglReportError() */ } fullscreen_ctx = NULL; } aglDestroyPixelFormat (fullscreen_fmt); fullscreen_fmt = NULL; } } } #endif #if UseAGLfullscreen LOCALPROC NoFullScreen(void) { if (fullscreen_ctx != NULL) { Rect r; int h; int v; GetWindowBounds(gMyMainWindow, kWindowContentRgn, &r); h = r.right - r.left; v = r.bottom - r.top; GLhOffset = hOffset; GLvOffset = v - vOffset; ctx = window_ctx; MyAdjustGLforSize(h, v); Update_Screen(); if (fullscreen_ctx != NULL) { if (GL_TRUE != aglDestroyContext(fullscreen_ctx)) { /* err = aglReportError() */ } fullscreen_ctx = NULL; } if (fullscreen_fmt != NULL) { aglDestroyPixelFormat(fullscreen_fmt); fullscreen_fmt = NULL; } } } #endif #if UseAGLfullscreen LOCALPROC AdjustOpenGLGrab(void) { if (GrabMachine) { MaybeFullScreen(); } else { NoFullScreen(); } } #endif #if MayFullScreen LOCALPROC AdjustMachineGrab(void) { #if EnableFSMouseMotion AdjustMouseMotionGrab(); #endif #if UseAGLfullscreen AdjustOpenGLGrab(); #endif #if 0 AdjustMainScreenGrab(); #endif } #endif #if MayFullScreen LOCALPROC UngrabMachine(void) { GrabMachine = falseblnr; AdjustMachineGrab(); } #endif LOCALPROC ClearWeAreActive(void) { if (gWeAreActive) { gWeAreActive = falseblnr; DisconnectKeyCodes2(); SavedModifiers &= alphaLock; MyMouseButtonSet(falseblnr); #if MayFullScreen UngrabMachine(); #endif ForceShowCursor(); } } /* --- basic dialogs --- */ LOCALFUNC CFStringRef CFStringCreateFromSubstCStr(char *s) { int L; UniChar x[ClStrMaxLength]; UniCharStrFromSubstCStr(&L, x, s); return CFStringCreateWithCharacters(kCFAllocatorDefault, x, L); } #define kMyStandardAlert 128 LOCALPROC CheckSavedMacMsg(void) { /* called only on quit, if error saved but not yet reported */ if (nullpr != SavedBriefMsg) { if (HaveMyCreateStandardAlert() && HaveMyRunStandardAlert()) { CFStringRef briefMsgu = CFStringCreateFromSubstCStr( SavedBriefMsg); if (NULL != briefMsgu) { CFStringRef longMsgu = CFStringCreateFromSubstCStr( SavedLongMsg); if (NULL != longMsgu) { DialogRef TheAlert; OSStatus err = MyCreateStandardAlert( (SavedFatalMsg) ? kAlertStopAlert : kAlertCautionAlert, briefMsgu, longMsgu, NULL, &TheAlert); if (noErr == err) { (void) MyRunStandardAlert(TheAlert, NULL, NULL); } CFRelease(longMsgu); } CFRelease(briefMsgu); } } SavedBriefMsg = nullpr; } } LOCALVAR blnr gTrueBackgroundFlag = falseblnr; LOCALPROC MyBeginDialog(void) { ClearWeAreActive(); } LOCALPROC MyEndDialog(void) { } /* --- hide/show menubar --- */ #if MayFullScreen LOCALPROC My_HideMenuBar(void) { if (HaveMySetSystemUIMode()) { (void) MySetSystemUIMode(MykUIModeAllHidden, MykUIOptionDisableAppleMenu #if GrabKeysFullScreen | MykUIOptionDisableProcessSwitch #if GrabKeysMaxFullScreen /* dangerous !! */ | MykUIOptionDisableForceQuit | MykUIOptionDisableSessionTerminate #endif #endif ); } else { if (IsMenuBarVisible()) { HideMenuBar(); } } } #endif #if MayFullScreen LOCALPROC My_ShowMenuBar(void) { if (HaveMySetSystemUIMode()) { (void) MySetSystemUIMode(MykUIModeNormal, 0); } else { if (! IsMenuBarVisible()) { ShowMenuBar(); } } } #endif /* --- drives, part 2 --- */ LOCALPROC InitDrives(void) { /* This isn't really needed, Drives[i] need not have valid value when not vSonyIsInserted[i]. */ tDrive i; for (i = 0; i < NumDrives; ++i) { Drives[i] = NotAfileRef; } } LOCALPROC UnInitDrives(void) { tDrive i; for (i = 0; i < NumDrives; ++i) { if (vSonyIsInserted(i)) { (void) vSonyEject(i); } } } LOCALFUNC tMacErr Sony_Insert0(SInt16 refnum, blnr locked) { tDrive Drive_No; if (! FirstFreeDisk(&Drive_No)) { (void) FSCloseFork(refnum); return mnvm_tmfoErr; } else { Drives[Drive_No] = refnum; DiskInsertNotify(Drive_No, locked); return mnvm_noErr; } } LOCALPROC ReportStandardOpenDiskError(tMacErr err) { if (mnvm_noErr != err) { if (mnvm_tmfoErr == err) { MacMsg(kStrTooManyImagesTitle, kStrTooManyImagesMessage, falseblnr); } else if (mnvm_opWrErr == err) { MacMsg(kStrImageInUseTitle, kStrImageInUseMessage, falseblnr); } else { MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr); } } } LOCALFUNC tMacErr InsertADiskFromFSRef(FSRef *theRef) { tMacErr err; HFSUniStr255 forkName; SInt16 refnum; blnr locked = falseblnr; if (CheckSaveMacErr(FSGetDataForkName(&forkName))) { err = To_tMacErr(FSOpenFork(theRef, forkName.length, forkName.unicode, fsRdWrPerm, &refnum)); switch (err) { case mnvm_permErr: case mnvm_wrPermErr: case mnvm_afpAccessDenied: locked = trueblnr; err = To_tMacErr(FSOpenFork(theRef, forkName.length, forkName.unicode, fsRdPerm, &refnum)); break; default: break; } if (mnvm_noErr == err) { err = Sony_Insert0(refnum, locked); } } return err; } LOCALFUNC tMacErr LoadMacRomFromRefNum(SInt16 refnum) { tMacErr err; ByteCount actualCount; if (mnvm_noErr != (err = To_tMacErr( FSReadFork(refnum, fsFromStart, 0, kROM_Size, ROM, &actualCount)))) { if (mnvm_eofErr == err) { MacMsgOverride(kStrShortROMTitle, kStrShortROMMessage); } else { MacMsgOverride(kStrNoReadROMTitle, kStrNoReadROMMessage); } } else { err = ROM_IsValid(); } return err; } LOCALFUNC tMacErr LoadMacRomFromFSRef(FSRef *theRef) { tMacErr err; HFSUniStr255 forkName; SInt16 refnum; if (mnvm_noErr == (err = To_tMacErr(FSGetDataForkName(&forkName)))) if (mnvm_noErr == (err = To_tMacErr( FSOpenFork(theRef, forkName.length, forkName.unicode, fsRdPerm, &refnum)))) { err = LoadMacRomFromRefNum(refnum); (void) FSCloseFork(refnum); } return err; } LOCALFUNC tMacErr InsertADiskFromFSRef1(FSRef *theRef) { tMacErr err; if (! ROM_loaded) { err = LoadMacRomFromFSRef(theRef); } else { err = InsertADiskFromFSRef(theRef); } return err; } LOCALFUNC tMacErr InsertDisksFromDocList(AEDescList *docList) { tMacErr err = mnvm_noErr; long itemsInList; long index; AEKeyword keyword; DescType typeCode; FSRef theRef; Size actualSize; if (CheckSaveMacErr(AECountItems(docList, &itemsInList))) { for (index = 1; index <= itemsInList; ++index) { if (CheckSaveMacErr(AEGetNthPtr(docList, index, typeFSRef, &keyword, &typeCode, (Ptr)&theRef, sizeof(FSRef), &actualSize))) if (CheckSavetMacErr(InsertADiskFromFSRef1(&theRef))) { } if (mnvm_noErr != err) { goto label_fail; } } } label_fail: return err; } LOCALFUNC tMacErr InsertADiskFromNameEtc(FSRef *ParentRef, char *fileName) { tMacErr err; blnr isFolder; FSRef ChildRef; if (CheckSavetMacErr(MyMakeFSRefC(ParentRef, fileName, &isFolder, &ChildRef))) { if (isFolder) { err = mnvm_miscErr; } else { if (CheckSavetMacErr(InsertADiskFromFSRef(&ChildRef))) { /* ok */ } } } return err; } #if IncludeSonyNew LOCALFUNC tMacErr WriteZero(SInt16 refnum, ui5b L) { #define ZeroBufferSize 2048 tMacErr err = mnvm_noErr; ui5b i; ui3b buffer[ZeroBufferSize]; ByteCount actualCount; ui5b offset = 0; memset(&buffer, 0, ZeroBufferSize); while (L > 0) { i = (L > ZeroBufferSize) ? ZeroBufferSize : L; if (! CheckSaveMacErr(FSWriteFork(refnum, fsFromStart, offset, i, buffer, &actualCount))) { goto label_fail; } L -= i; offset += i; } label_fail: return err; } #endif #if IncludeSonyNew LOCALFUNC tMacErr MyCreateFileCFStringRef(FSRef *saveFileParent, CFStringRef saveFileName, FSRef *NewRef) { tMacErr err; UniChar buffer[255]; CFIndex len = CFStringGetLength(saveFileName); if (len > 255) { len = 255; } CFStringGetCharacters(saveFileName, CFRangeMake(0, len), buffer); err = To_tMacErr(FSMakeFSRefUnicode(saveFileParent, len, buffer, kTextEncodingUnknown, NewRef)); if (mnvm_fnfErr == err) { /* file is not there yet - create it */ err = To_tMacErr(FSCreateFileUnicode(saveFileParent, len, buffer, 0, NULL, NewRef, NULL)); } return err; } #endif #if IncludeSonyNew LOCALFUNC tMacErr MakeNewDisk0(FSRef *saveFileParent, CFStringRef saveFileName, ui5b L) { tMacErr err; FSRef NewRef; HFSUniStr255 forkName; SInt16 refnum; if (CheckSavetMacErr( MyCreateFileCFStringRef(saveFileParent, saveFileName, &NewRef))) { if (CheckSaveMacErr(FSGetDataForkName(&forkName))) if (CheckSaveMacErr(FSOpenFork(&NewRef, forkName.length, forkName.unicode, fsRdWrPerm, &refnum))) { SInt64 forkSize = L; if (CheckSaveMacErr( FSSetForkSize(refnum, fsFromStart, forkSize))) /* zero out fork. It looks like this is already done, but documentation says this isn't guaranteed. */ if (CheckSavetMacErr(WriteZero(refnum, L))) { err = Sony_Insert0(refnum, falseblnr); refnum = NotAfileRef; } if (NotAfileRef != refnum) { (void) FSCloseFork(refnum); } } if (mnvm_noErr != err) { (void) FSDeleteObject(&NewRef); } } return err; } #endif #if IncludeSonyNameNew LOCALFUNC CFStringRef CFStringCreateWithPbuf(tPbuf i) { return CFStringCreateWithBytes(NULL, (UInt8 *)PbufDat[i], PbufSize[i], kCFStringEncodingMacRoman, false); } #endif pascal Boolean NavigationFilterProc( AEDesc* theItem, void* info, void* NavCallBackUserData, NavFilterModes theNavFilterModes); pascal Boolean NavigationFilterProc( AEDesc* theItem, void* info, void* NavCallBackUserData, NavFilterModes theNavFilterModes) { /* NavFileOrFolderInfo* theInfo = (NavFileOrFolderInfo*)info; */ UnusedParam(theItem); UnusedParam(info); UnusedParam(theNavFilterModes); UnusedParam(NavCallBackUserData); return true; /* display all items */ } pascal void NavigationEventProc( NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *NavCallBackUserData); pascal void NavigationEventProc( NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *NavCallBackUserData) { UnusedParam(NavCallBackUserData); switch (callBackSelector) { case kNavCBEvent: /* probably not needed in os x */ switch (callBackParms->eventData.eventDataParms.event->what) { case updateEvt: { WindowPtr which = (WindowPtr)callBackParms ->eventData.eventDataParms.event ->message; BeginUpdate(which); if (which == gMyMainWindow) { Update_Screen(); } EndUpdate(which); } break; } break; #if 0 case kNavCBUserAction: { NavUserAction userAction = NavDialogGetUserAction( callBackParms->context); switch (userAction) { case kNavUserActionOpen: { /* got something to open */ break; } } } break; case kNavCBTerminate: break; #endif } } LOCALPROC InsertADisk0(void) { NavDialogRef theOpenDialog; NavDialogCreationOptions dialogOptions; NavReplyRecord theReply; NavTypeListHandle openList = NULL; NavEventUPP gEventProc = NewNavEventUPP(NavigationEventProc); NavObjectFilterUPP filterUPP = NewNavObjectFilterUPP(NavigationFilterProc); if (noErr == NavGetDefaultDialogCreationOptions(&dialogOptions)) { dialogOptions.modality = kWindowModalityAppModal; dialogOptions.optionFlags |= kNavDontAutoTranslate; dialogOptions.optionFlags &= ~ kNavAllowPreviews; if (noErr == NavCreateGetFileDialog(&dialogOptions, (NavTypeListHandle)openList, gEventProc, NULL, filterUPP, NULL, &theOpenDialog)) { MyBeginDialog(); (void) NavDialogRun(theOpenDialog); MyEndDialog(); if (noErr == NavDialogGetReply(theOpenDialog, &theReply)) { if (theReply.validRecord) { ReportStandardOpenDiskError( InsertDisksFromDocList(&theReply.selection)); } (void) NavDisposeReply(&theReply); } NavDialogDispose(theOpenDialog); } } DisposeNavEventUPP(gEventProc); DisposeNavObjectFilterUPP(filterUPP); } #if IncludeSonyNew LOCALPROC MakeNewDisk(ui5b L, CFStringRef NewDiskName) { #if SaveDialogEnable NavDialogRef theSaveDialog; NavDialogCreationOptions dialogOptions; NavReplyRecord theReply; NavEventUPP gEventProc = NewNavEventUPP(NavigationEventProc); if (noErr == NavGetDefaultDialogCreationOptions(&dialogOptions)) { dialogOptions.modality = kWindowModalityAppModal; dialogOptions.saveFileName = NewDiskName; if (noErr == NavCreatePutFileDialog(&dialogOptions, 'TEXT', 'MPS ', gEventProc, NULL, &theSaveDialog)) { MyBeginDialog(); (void) NavDialogRun(theSaveDialog); MyEndDialog(); if (noErr == NavDialogGetReply(theSaveDialog, &theReply)) { if (theReply.validRecord) { long itemsInList; AEKeyword keyword; DescType typeCode; FSRef theRef; Size actualSize; if (noErr == AECountItems( &theReply.selection, &itemsInList)) { if (itemsInList == 1) { if (noErr == AEGetNthPtr( &theReply.selection, 1, typeFSRef, &keyword, &typeCode, (Ptr)&theRef, sizeof(FSRef), &actualSize)) { ReportStandardOpenDiskError( MakeNewDisk0(&theRef, theReply.saveFileName, L)); } } } } (void) NavDisposeReply(&theReply); } NavDialogDispose(theSaveDialog); } } DisposeNavEventUPP(gEventProc); #else /* SaveDialogEnable */ FSRef OutRef; if (mnvm_noErr == FindOrMakeNamedChildRef(&MyDatDirRef, "out", &OutRef)) { MakeNewDisk0(&OutRef, NewDiskName, L); } #endif /* SaveDialogEnable */ } #endif LOCALFUNC tMacErr LoadMacRomFromNameFolder(FSRef *ParentRef, char *fileName) { tMacErr err; blnr isFolder; FSRef ChildRef; if (mnvm_noErr == (err = MyMakeFSRefC(ParentRef, fileName, &isFolder, &ChildRef))) if (mnvm_noErr == (err = LoadMacRomFromFSRef(&ChildRef))) { } return err; } LOCALFUNC tMacErr LoadMacRomFromPrefDir(void) { tMacErr err; FSRef PrefRef; FSRef GryphelRef; FSRef ROMsRef; if (mnvm_noErr == (err = To_tMacErr(FSFindFolder(kUserDomain, kPreferencesFolderType, kDontCreateFolder, &PrefRef)))) if (mnvm_noErr == (err = FindNamedChildRef(&PrefRef, "Gryphel", &GryphelRef))) if (mnvm_noErr == (err = FindNamedChildRef(&GryphelRef, "mnvm_rom", &ROMsRef))) if (mnvm_noErr == (err = LoadMacRomFromNameFolder(&ROMsRef, RomFileName))) { /* ok */ } return err; } LOCALFUNC blnr LoadMacRom(void) { tMacErr err; if (mnvm_fnfErr == (err = LoadMacRomFromNameFolder(&MyDatDirRef, RomFileName))) if (mnvm_fnfErr == (err = LoadMacRomFromPrefDir())) { } return trueblnr; /* keep launching Mini vMac, regardless */ } LOCALFUNC blnr Sony_InsertIth(int i) { tMacErr err = mnvm_noErr; if ((i > 9) || ! FirstFreeDisk(nullpr)) { return falseblnr; } else { char s[16] = "disk?.dsk"; s[4] = '0' + i; if (! CheckSavetMacErr(InsertADiskFromNameEtc(&MyDatDirRef, s))) { if (mnvm_fnfErr != err) { ReportStandardOpenDiskError(err); } /* stop on first error (including file not found) */ return falseblnr; } } return trueblnr; } LOCALFUNC blnr LoadInitialImages(void) { int i; for (i = 1; Sony_InsertIth(i); ++i) { /* stop on first error (including file not found) */ } return trueblnr; } #if UseActvFile #define ActvCodeFileName "act_1" LOCALFUNC tMacErr OpenActvCodeFile(SInt16 *refnum) { tMacErr err; FSRef PrefRef; FSRef GryphelRef; FSRef ActRef; if (CheckSaveMacErr(FSFindFolder(kUserDomain, kPreferencesFolderType, kDontCreateFolder, &PrefRef))) if (CheckSavetMacErr(FindNamedChildRef(&PrefRef, "Gryphel", &GryphelRef))) if (CheckSavetMacErr(FindNamedChildRef(&GryphelRef, "mnvm_act", &ActRef))) if (CheckSavetMacErr(OpenNamedFileInFolderRef(&ActRef, ActvCodeFileName, refnum))) { /* ok */ } return err; } LOCALFUNC tMacErr ActvCodeFileLoad(ui3p p) { tMacErr err; SInt16 refnum; if (CheckSavetMacErr(OpenActvCodeFile(&refnum))) { ByteCount actualCount; err = To_tMacErr(FSReadFork(refnum, fsFromStart, 0, ActvCodeFileLen, p, &actualCount)); (void) FSCloseFork(refnum); } return err; } LOCALFUNC tMacErr ActvCodeFileSave(ui3p p) { tMacErr err; SInt16 refnum; FSRef PrefRef; FSRef GryphelRef; FSRef ActRef; ByteCount count = ActvCodeFileLen; if (CheckSaveMacErr(FSFindFolder(kUserDomain, kPreferencesFolderType, kDontCreateFolder, &PrefRef))) if (CheckSavetMacErr(FindOrMakeNamedChildRef(&PrefRef, "Gryphel", &GryphelRef))) if (CheckSavetMacErr(FindOrMakeNamedChildRef(&GryphelRef, "mnvm_act", &ActRef))) if (CheckSavetMacErr(OpenWriteNamedFileInFolderRef(&ActRef, ActvCodeFileName, &refnum))) { ByteCount actualCount; err = To_tMacErr(FSWriteFork(refnum, fsFromStart, 0, count, p, &actualCount)); (void) FSCloseFork(refnum); } return err; } #endif /* UseActvFile */ /* --- utilities for adapting to the environment --- */ LOCALPROC MyGetScreenBitsBounds(Rect *r) { if (HaveMyCGDisplayBounds()) { CGRect cgr = MyCGDisplayBounds(MyMainDisplayID()); r->left = cgr.origin.x; r->top = cgr.origin.y; r->right = cgr.origin.x + cgr.size.width; r->bottom = cgr.origin.y + cgr.size.height; } } #if MayNotFullScreen LOCALPROC InvalWholeWindow(WindowRef mw) { Rect bounds; GetWindowPortBounds(mw, &bounds); InvalWindowRect(mw, &bounds); } #endif #if MayNotFullScreen LOCALPROC MySetMacWindContRect(WindowRef mw, Rect *r) { (void) SetWindowBounds (mw, kWindowContentRgn, r); InvalWholeWindow(mw); } #endif #if MayNotFullScreen LOCALFUNC blnr MyGetWindowTitleBounds(WindowRef mw, Rect *r) { return (noErr == GetWindowBounds(mw, kWindowTitleBarRgn, r)); } #endif #if EnableRecreateW && MayNotFullScreen LOCALFUNC blnr MyGetWindowContBounds(WindowRef mw, Rect *r) { return (noErr == GetWindowBounds(mw, kWindowContentRgn, r)); } #endif LOCALPROC MyGetGrayRgnBounds(Rect *r) { GetRegionBounds(GetGrayRgn(), (Rect *)r); } #define openOnly 1 #define openPrint 2 LOCALFUNC blnr GotRequiredParams(AppleEvent *theAppleEvent) { DescType typeCode; Size actualSize; OSErr theErr; theErr = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard, &typeCode, NULL, 0, &actualSize); if (errAEDescNotFound == theErr) { /* No more required params. */ return trueblnr; } else if (noErr == theErr) { /* More required params! */ return /* CheckSysCode(errAEEventNotHandled) */ falseblnr; } else { /* Unexpected Error! */ return /* CheckSysCode(theErr) */ falseblnr; } } LOCALFUNC blnr GotRequiredParams0(AppleEvent *theAppleEvent) { DescType typeCode; Size actualSize; OSErr theErr; theErr = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard, &typeCode, NULL, 0, &actualSize); if (errAEDescNotFound == theErr) { /* No more required params. */ return trueblnr; } else if (noErr == theErr) { /* More required params! */ return trueblnr; /* errAEEventNotHandled; */ /*^*/ } else { /* Unexpected Error! */ return /* CheckSysCode(theErr) */ falseblnr; } } /* call back */ static pascal OSErr OpenOrPrintFiles( AppleEvent *theAppleEvent, AppleEvent *reply, long aRefCon) { /* Adapted from IM VI: AppleEvent Manager: Handling Required AppleEvents */ AEDescList docList; UnusedParam(reply); UnusedParam(aRefCon); /* put the direct parameter (a list of descriptors) into docList */ if (noErr == (AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList))) { if (GotRequiredParams0(theAppleEvent)) { /* Check for missing required parameters */ /* printIt = (openPrint == aRefCon) */ ReportStandardOpenDiskError( InsertDisksFromDocList(&docList)); } /* vCheckSysCode */ (void) (AEDisposeDesc(&docList)); } return /* GetASysResultCode() */ 0; } /* call back */ static pascal OSErr DoOpenEvent( AppleEvent *theAppleEvent, AppleEvent *reply, long aRefCon) /* This is the alternative to getting an open document event on startup. */ { UnusedParam(reply); UnusedParam(aRefCon); if (GotRequiredParams0(theAppleEvent)) { } return /* GetASysResultCode() */ 0; /* Make sure there are no additional "required" parameters. */ } /* call back */ static pascal OSErr DoQuitEvent( AppleEvent *theAppleEvent, AppleEvent *reply, long aRefCon) { UnusedParam(reply); UnusedParam(aRefCon); if (GotRequiredParams(theAppleEvent)) { RequestMacOff = trueblnr; } return /* GetASysResultCode() */ 0; } LOCALFUNC blnr MyInstallEventHandler(AEEventClass theAEEventClass, AEEventID theAEEventID, ProcPtr p, long handlerRefcon, blnr isSysHandler) { return noErr == (AEInstallEventHandler(theAEEventClass, theAEEventID, NewAEEventHandlerUPP((AEEventHandlerProcPtr)p), handlerRefcon, isSysHandler)); } LOCALPROC InstallAppleEventHandlers(void) { if (noErr == AESetInteractionAllowed(kAEInteractWithLocal)) if (MyInstallEventHandler(kCoreEventClass, kAEOpenApplication, (ProcPtr)DoOpenEvent, 0, falseblnr)) if (MyInstallEventHandler(kCoreEventClass, kAEOpenDocuments, (ProcPtr)OpenOrPrintFiles, openOnly, falseblnr)) if (MyInstallEventHandler(kCoreEventClass, kAEPrintDocuments, (ProcPtr)OpenOrPrintFiles, openPrint, falseblnr)) if (MyInstallEventHandler(kCoreEventClass, kAEQuitApplication, (ProcPtr)DoQuitEvent, 0, falseblnr)) { } } static pascal OSErr GlobalTrackingHandler(DragTrackingMessage message, WindowRef theWindow, void *handlerRefCon, DragReference theDragRef) { RgnHandle hilightRgn; Rect Bounds; UnusedParam(theWindow); UnusedParam(handlerRefCon); switch(message) { case kDragTrackingEnterWindow: hilightRgn = NewRgn(); if (hilightRgn != NULL) { SetScrnRectFromCoords(&Bounds, 0, 0, vMacScreenHeight, vMacScreenWidth); RectRgn(hilightRgn, &Bounds); ShowDragHilite(theDragRef, hilightRgn, true); DisposeRgn(hilightRgn); } break; case kDragTrackingLeaveWindow: HideDragHilite(theDragRef); break; } return noErr; } LOCALFUNC tMacErr InsertADiskOrAliasFromFSRef(FSRef *theRef) { tMacErr err; Boolean isFolder; Boolean isAlias; if (CheckSaveMacErr(FSResolveAliasFile(theRef, true, &isFolder, &isAlias))) { err = InsertADiskFromFSRef1(theRef); } return err; } LOCALFUNC tMacErr InsertADiskOrAliasFromSpec(FSSpec *spec) { tMacErr err; FSRef newRef; if (CheckSaveMacErr(FSpMakeFSRef(spec, &newRef))) if (CheckSavetMacErr(InsertADiskOrAliasFromFSRef(&newRef))) { /* ok */ } return err; } static pascal OSErr GlobalReceiveHandler(WindowRef pWindow, void *handlerRefCon, DragReference theDragRef) { SInt16 mouseUpModifiers; unsigned short items; unsigned short index; ItemReference theItem; Size SentSize; HFSFlavor r; UnusedParam(pWindow); UnusedParam(handlerRefCon); if (noErr == GetDragModifiers(theDragRef, NULL, NULL, &mouseUpModifiers)) { MyUpdateKeyboardModifiers(mouseUpModifiers); } if (noErr == CountDragItems(theDragRef, &items)) { for (index = 1; index <= items; ++index) { if (noErr == GetDragItemReferenceNumber(theDragRef, index, &theItem)) if (noErr == GetFlavorDataSize(theDragRef, theItem, flavorTypeHFS, &SentSize)) /* On very old macs SentSize might only be big enough to hold the actual file name. Have not seen this in OS X, but still leave the check as '<=' instead of '=='. */ if (SentSize <= sizeof(HFSFlavor)) if (noErr == GetFlavorData(theDragRef, theItem, flavorTypeHFS, (Ptr)&r, &SentSize, 0)) { ReportStandardOpenDiskError( InsertADiskOrAliasFromSpec(&r.fileSpec)); } } #if 1 if (gTrueBackgroundFlag) { ProcessSerialNumber currentProcess = {0, kCurrentProcess}; (void) SetFrontProcess(¤tProcess); } #endif } return noErr; } LOCALVAR DragTrackingHandlerUPP gGlobalTrackingHandler = NULL; LOCALVAR DragReceiveHandlerUPP gGlobalReceiveHandler = NULL; LOCALPROC UnPrepareForDragging(void) { if (NULL != gGlobalReceiveHandler) { RemoveReceiveHandler(gGlobalReceiveHandler, gMyMainWindow); DisposeDragReceiveHandlerUPP(gGlobalReceiveHandler); gGlobalReceiveHandler = NULL; } if (NULL != gGlobalTrackingHandler) { RemoveTrackingHandler(gGlobalTrackingHandler, gMyMainWindow); DisposeDragTrackingHandlerUPP(gGlobalTrackingHandler); gGlobalTrackingHandler = NULL; } } LOCALFUNC blnr PrepareForDragging(void) { blnr IsOk = falseblnr; gGlobalTrackingHandler = NewDragTrackingHandlerUPP( GlobalTrackingHandler); if (gGlobalTrackingHandler != NULL) { gGlobalReceiveHandler = NewDragReceiveHandlerUPP( GlobalReceiveHandler); if (gGlobalReceiveHandler != NULL) { if (noErr == InstallTrackingHandler(gGlobalTrackingHandler, gMyMainWindow, nil)) { if (noErr == InstallReceiveHandler( gGlobalReceiveHandler, gMyMainWindow, nil)) { IsOk = trueblnr; } } } } return IsOk; } LOCALPROC HandleEventLocation(EventRef theEvent) { Point NewMousePos; if (! gWeAreActive) { return; } if (noErr == GetEventParameter(theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(NewMousePos), NULL, &NewMousePos)) { MousePositionNotify(NewMousePos); } } LOCALPROC HandleEventModifiers(EventRef theEvent) { UInt32 theModifiers; if (gWeAreActive) { GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(typeUInt32), NULL, &theModifiers); MyUpdateKeyboardModifiers(theModifiers); } } LOCALVAR blnr IsOurMouseMove; static pascal OSStatus windowEventHandler( EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) { OSStatus result = eventNotHandledErr; UInt32 eventClass = GetEventClass(theEvent); UInt32 eventKind = GetEventKind(theEvent); UnusedParam(nextHandler); UnusedParam(userData); switch(eventClass) { case kEventClassWindow: switch(eventKind) { case kEventWindowClose: RequestMacOff = trueblnr; result = noErr; break; case kEventWindowDrawContent: Update_Screen(); result = noErr; break; case kEventWindowClickContentRgn: MouseIsOutside = falseblnr; HandleEventLocation(theEvent); HandleEventModifiers(theEvent); MyMouseButtonSet(trueblnr); result = noErr; break; case kEventWindowFocusAcquired: gLackFocusFlag = falseblnr; result = noErr; break; case kEventWindowFocusRelinquish: { WindowRef window; (void) GetEventParameter(theEvent, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window); if ((window == gMyMainWindow) && (window != gMyOldWindow)) { ClearWeAreActive(); gLackFocusFlag = trueblnr; } } result = noErr; break; } break; case kEventClassMouse: switch(eventKind) { case kEventMouseMoved: case kEventMouseDragged: MouseIsOutside = falseblnr; #if 0 /* don't bother, CheckMouseState will take care of it, better */ HandleEventLocation(theEvent); HandleEventModifiers(theEvent); #endif IsOurMouseMove = trueblnr; result = noErr; break; } break; } return result; } LOCALFUNC blnr MyCreateNewWindow(Rect *Bounds, WindowPtr *theWindow) { WindowPtr ResultWin; blnr IsOk = falseblnr; if (noErr == CreateNewWindow( #if VarFullScreen UseFullScreen ? #endif #if MayFullScreen /* appears not to work properly with aglSetWindowRef at least in OS X 10.5.5 also doesn't seem to be needed. maybe dates from when didn't cover all screens in full screen mode. */ /* Oops, no, kDocumentWindowClass doesn't seem to work quite right if made immediately after launch, title bar gets moved onscreen. At least in Intel 10.5.6, doesn't happen in PowerPC 10.4.11. Oddly, this problem doesn't happen if icon already in dock before launch, but perhaps that is just a timing issue. So use kPlainWindowClass after all. */ kPlainWindowClass #endif #if VarFullScreen : #endif #if MayNotFullScreen kDocumentWindowClass #endif , #if VarFullScreen UseFullScreen ? #endif #if MayFullScreen /* kWindowStandardHandlerAttribute */ 0 #endif #if VarFullScreen : #endif #if MayNotFullScreen kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute #endif , Bounds, &ResultWin )) { #if VarFullScreen if (! UseFullScreen) #endif #if MayNotFullScreen { SetWindowTitleWithCFString(ResultWin, MyAppName /* CFSTR("Mini vMac") */); } #endif InstallStandardEventHandler(GetWindowEventTarget(ResultWin)); { static const EventTypeSpec windowEvents[] = { {kEventClassWindow, kEventWindowClose}, {kEventClassWindow, kEventWindowDrawContent}, {kEventClassWindow, kEventWindowClickContentRgn}, {kEventClassMouse, kEventMouseMoved}, {kEventClassMouse, kEventMouseDragged}, {kEventClassWindow, kEventWindowFocusAcquired}, {kEventClassWindow, kEventWindowFocusRelinquish} }; InstallWindowEventHandler(ResultWin, NewEventHandlerUPP(windowEventHandler), GetEventTypeCount(windowEvents), windowEvents, 0, NULL); } *theWindow = ResultWin; IsOk = trueblnr; } return IsOk; } LOCALPROC CloseAglCurrentContext(void) { if (ctx != NULL) { /* Only because MyDrawWithOpenGL doesn't bother to do this. No one uses the CurrentContext without settting it first. */ if (GL_TRUE != aglSetCurrentContext(NULL)) { /* err = aglReportError() */ } ctx = NULL; } } LOCALPROC CloseMainWindow(void) { UnPrepareForDragging(); if (window_ctx != NULL) { if (GL_TRUE != aglDestroyContext(window_ctx)) { /* err = aglReportError() */ } window_ctx = NULL; } if (window_fmt != NULL) { aglDestroyPixelFormat(window_fmt); window_fmt = NULL; } if (gMyMainWindow != NULL) { DisposeWindow(gMyMainWindow); gMyMainWindow = NULL; } } enum { kMagStateNormal, #if EnableMagnify kMagStateMagnifgy, #endif kNumMagStates }; #define kMagStateAuto kNumMagStates #if MayNotFullScreen LOCALVAR int CurWinIndx; LOCALVAR blnr HavePositionWins[kNumMagStates]; LOCALVAR Point WinPositionWins[kNumMagStates]; #endif LOCALFUNC blnr CreateMainWindow(void) { #if MayNotFullScreen int WinIndx; #endif Rect MainScrnBounds; Rect AllScrnBounds; Rect NewWinRect; short leftPos; short topPos; short NewWindowHeight = vMacScreenHeight; short NewWindowWidth = vMacScreenWidth; blnr IsOk = falseblnr; #if VarFullScreen if (UseFullScreen) { My_HideMenuBar(); } else { My_ShowMenuBar(); } #else #if MayFullScreen My_HideMenuBar(); #endif #endif MyGetGrayRgnBounds(&AllScrnBounds); MyGetScreenBitsBounds(&MainScrnBounds); #if EnableMagnify if (UseMagnify) { NewWindowHeight *= MyWindowScale; NewWindowWidth *= MyWindowScale; } #endif leftPos = MainScrnBounds.left + ((MainScrnBounds.right - MainScrnBounds.left) - NewWindowWidth) / 2; topPos = MainScrnBounds.top + ((MainScrnBounds.bottom - MainScrnBounds.top) - NewWindowHeight) / 2; if (leftPos < MainScrnBounds.left) { leftPos = MainScrnBounds.left; } if (topPos < MainScrnBounds.top) { topPos = MainScrnBounds.top; } #if VarFullScreen if (UseFullScreen) #endif #if MayFullScreen { ViewHSize = MainScrnBounds.right - MainScrnBounds.left; ViewVSize = MainScrnBounds.bottom - MainScrnBounds.top; #if EnableMagnify if (UseMagnify) { ViewHSize /= MyWindowScale; ViewVSize /= MyWindowScale; } #endif if (ViewHSize >= vMacScreenWidth) { ViewHStart = 0; ViewHSize = vMacScreenWidth; } else { ViewHSize &= ~ 1; } if (ViewVSize >= vMacScreenHeight) { ViewVStart = 0; ViewVSize = vMacScreenHeight; } else { ViewVSize &= ~ 1; } } #endif /* Create window rectangle and centre it on the screen */ SetRect(&MainScrnBounds, 0, 0, NewWindowWidth, NewWindowHeight); OffsetRect(&MainScrnBounds, leftPos, topPos); #if VarFullScreen if (UseFullScreen) #endif #if MayFullScreen { NewWinRect = AllScrnBounds; } #endif #if VarFullScreen else #endif #if MayNotFullScreen { #if EnableMagnify if (UseMagnify) { WinIndx = kMagStateMagnifgy; } else #endif { WinIndx = kMagStateNormal; } if (! HavePositionWins[WinIndx]) { WinPositionWins[WinIndx].h = leftPos; WinPositionWins[WinIndx].v = topPos; HavePositionWins[WinIndx] = trueblnr; NewWinRect = MainScrnBounds; } else { SetRect(&NewWinRect, 0, 0, NewWindowWidth, NewWindowHeight); OffsetRect(&NewWinRect, WinPositionWins[WinIndx].h, WinPositionWins[WinIndx].v); } } #endif #if MayNotFullScreen CurWinIndx = WinIndx; #endif #if VarFullScreen if (UseFullScreen) #endif #if MayFullScreen { hOffset = MainScrnBounds.left - AllScrnBounds.left; vOffset = MainScrnBounds.top - AllScrnBounds.top; } #endif if (MyCreateNewWindow(&NewWinRect, &gMyMainWindow)) { static const GLint window_attrib[] = {AGL_RGBA, #if UseAGLdoublebuff AGL_DOUBLEBUFFER, #endif /* AGL_DEPTH_SIZE, 16, */ AGL_NONE}; #if 0 != vMacScreenDepth ColorModeWorks = trueblnr; #endif window_fmt = aglChoosePixelFormat(NULL, 0, window_attrib); if (NULL == window_fmt) { /* err = aglReportError() */ } else { window_ctx = aglCreateContext(window_fmt, NULL); if (NULL == window_ctx) { /* err = aglReportError() */ } else { ShowWindow(gMyMainWindow); if (GL_TRUE != ( /* aglSetDrawable is deprecated, but use it anyway if at all possible, because aglSetWindowRef doesn't seeem to work properly on a kPlainWindowClass window. Should move to Cocoa. */ HaveMyaglSetDrawable() ? MyaglSetDrawable(window_ctx, GetWindowPort(gMyMainWindow)) : HaveMyaglSetWindowRef() ? MyaglSetWindowRef(window_ctx, gMyMainWindow) : GL_FALSE)) { /* err = aglReportError() */ } else { ctx = window_ctx; #if VarFullScreen if (UseFullScreen) #endif #if MayFullScreen { int h = NewWinRect.right - NewWinRect.left; int v = NewWinRect.bottom - NewWinRect.top; GLhOffset = hOffset; GLvOffset = v - vOffset; MyAdjustGLforSize(h, v); } #endif #if VarFullScreen else #endif #if MayNotFullScreen { GLhOffset = 0; GLvOffset = NewWindowHeight; MyAdjustGLforSize(NewWindowWidth, NewWindowHeight); } #endif #if UseAGLdoublebuff && 1 { GLint agSwapInterval = 1; if (GL_TRUE != aglSetInteger( window_ctx, AGL_SWAP_INTERVAL, &agSwapInterval)) { MacMsg("oops", "aglSetInteger failed", falseblnr); } else { /* MacMsg("good", "aglSetInteger ok", falseblnr); */ } } #endif #if VarFullScreen if (! UseFullScreen) #endif #if MayNotFullScreen { /* check if window rect valid */ Rect tr; if (MyGetWindowTitleBounds(gMyMainWindow, &tr)) { if (! RectInRgn(&tr, GetGrayRgn())) { MySetMacWindContRect(gMyMainWindow, &MainScrnBounds); if (MyGetWindowTitleBounds( gMyMainWindow, &tr)) { if (! RectInRgn(&tr, GetGrayRgn())) { OffsetRect(&MainScrnBounds, 0, AllScrnBounds.top - tr.top); MySetMacWindContRect( gMyMainWindow, &MainScrnBounds); } } } } } #endif (void) PrepareForDragging(); IsOk = trueblnr; } } } } return IsOk; } #if EnableRecreateW LOCALPROC ZapMyWState(void) { gMyMainWindow = NULL; window_fmt = NULL; window_ctx = NULL; gGlobalReceiveHandler = NULL; gGlobalTrackingHandler = NULL; } #endif #if EnableRecreateW struct MyWState { WindowPtr f_MainWindow; AGLPixelFormat f_fmt; AGLContext f_ctx; #if MayFullScreen short f_hOffset; short f_vOffset; ui4r f_ViewHSize; ui4r f_ViewVSize; ui4r f_ViewHStart; ui4r f_ViewVStart; #endif #if VarFullScreen blnr f_UseFullScreen; #endif #if EnableMagnify blnr f_UseMagnify; #endif #if MayNotFullScreen int f_CurWinIndx; #endif short f_GLhOffset; short f_GLvOffset; DragTrackingHandlerUPP f_gGlobalTrackingHandler; DragReceiveHandlerUPP f_gGlobalReceiveHandler; }; typedef struct MyWState MyWState; #endif #if EnableRecreateW LOCALPROC GetMyWState(MyWState *r) { r->f_MainWindow = gMyMainWindow; r->f_fmt = window_fmt; r->f_ctx = window_ctx; #if MayFullScreen r->f_hOffset = hOffset; r->f_vOffset = vOffset; r->f_ViewHSize = ViewHSize; r->f_ViewVSize = ViewVSize; r->f_ViewHStart = ViewHStart; r->f_ViewVStart = ViewVStart; #endif #if VarFullScreen r->f_UseFullScreen = UseFullScreen; #endif #if EnableMagnify r->f_UseMagnify = UseMagnify; #endif #if MayNotFullScreen r->f_CurWinIndx = CurWinIndx; #endif r->f_GLhOffset = GLhOffset; r->f_GLvOffset = GLvOffset; r->f_gGlobalTrackingHandler = gGlobalTrackingHandler; r->f_gGlobalReceiveHandler = gGlobalReceiveHandler; } #endif #if EnableRecreateW LOCALPROC SetMyWState(MyWState *r) { gMyMainWindow = r->f_MainWindow; window_fmt = r->f_fmt; window_ctx = r->f_ctx; #if MayFullScreen hOffset = r->f_hOffset; vOffset = r->f_vOffset; ViewHSize = r->f_ViewHSize; ViewVSize = r->f_ViewVSize; ViewHStart = r->f_ViewHStart; ViewVStart = r->f_ViewVStart; #endif #if VarFullScreen UseFullScreen = r->f_UseFullScreen; #endif #if EnableMagnify UseMagnify = r->f_UseMagnify; #endif #if MayNotFullScreen CurWinIndx = r->f_CurWinIndx; #endif GLhOffset = r->f_GLhOffset; GLvOffset = r->f_GLvOffset; gGlobalTrackingHandler = r->f_gGlobalTrackingHandler; gGlobalReceiveHandler = r->f_gGlobalReceiveHandler; ctx = window_ctx; } #endif #if EnableRecreateW LOCALFUNC blnr ReCreateMainWindow(void) { MyWState old_state; MyWState new_state; #if VarFullScreen if (! UseFullScreen) #endif #if MayNotFullScreen { /* save old position */ if (gMyMainWindow != NULL) { Rect r; if (MyGetWindowContBounds(gMyMainWindow, &r)) { WinPositionWins[CurWinIndx].h = r.left; WinPositionWins[CurWinIndx].v = r.top; } } } #endif #if MayFullScreen UngrabMachine(); #endif CloseAglCurrentContext(); gMyOldWindow = gMyMainWindow; GetMyWState(&old_state); ZapMyWState(); #if VarFullScreen UseFullScreen = WantFullScreen; #endif #if EnableMagnify UseMagnify = WantMagnify; #endif if (! CreateMainWindow()) { gMyOldWindow = NULL; CloseMainWindow(); SetMyWState(&old_state); #if VarFullScreen if (UseFullScreen) { My_HideMenuBar(); } else { My_ShowMenuBar(); } #endif /* avoid retry */ #if VarFullScreen WantFullScreen = UseFullScreen; #endif #if EnableMagnify WantMagnify = UseMagnify; #endif return falseblnr; } else { GetMyWState(&new_state); SetMyWState(&old_state); CloseMainWindow(); gMyOldWindow = NULL; SetMyWState(&new_state); if (HaveCursorHidden) { (void) MyMoveMouse(CurMouseH, CurMouseV); WantCursorHidden = trueblnr; } else { MouseIsOutside = falseblnr; /* don't know */ } return trueblnr; } } #endif #if VarFullScreen && EnableMagnify enum { kWinStateWindowed, #if EnableMagnify kWinStateFullScreen, #endif kNumWinStates }; #endif #if VarFullScreen && EnableMagnify LOCALVAR int WinMagStates[kNumWinStates]; #endif LOCALPROC ZapWinStateVars(void) { #if MayNotFullScreen { int i; for (i = 0; i < kNumMagStates; ++i) { HavePositionWins[i] = falseblnr; } } #endif #if VarFullScreen && EnableMagnify { int i; for (i = 0; i < kNumWinStates; ++i) { WinMagStates[i] = kMagStateAuto; } } #endif } #if VarFullScreen LOCALPROC ToggleWantFullScreen(void) { WantFullScreen = ! WantFullScreen; #if EnableMagnify { int OldWinState = UseFullScreen ? kWinStateFullScreen : kWinStateWindowed; int OldMagState = UseMagnify ? kMagStateMagnifgy : kMagStateNormal; int NewWinState = WantFullScreen ? kWinStateFullScreen : kWinStateWindowed; int NewMagState = WinMagStates[NewWinState]; WinMagStates[OldWinState] = OldMagState; if (kMagStateAuto != NewMagState) { WantMagnify = (kMagStateMagnifgy == NewMagState); } else { WantMagnify = falseblnr; if (WantFullScreen && HaveMyCGDisplayPixelsWide() && HaveMyCGDisplayPixelsHigh()) { CGDirectDisplayID CurMainDisplayID = MyMainDisplayID(); if ((MyCGDisplayPixelsWide(CurMainDisplayID) >= vMacScreenWidth * MyWindowScale) && (MyCGDisplayPixelsHigh(CurMainDisplayID) >= vMacScreenHeight * MyWindowScale) ) { WantMagnify = trueblnr; } } } } #endif } #endif LOCALPROC LeaveSpeedStopped(void) { #if MySoundEnabled MySound_Start(); #endif StartUpTimeAdjust(); } LOCALPROC EnterSpeedStopped(void) { #if MySoundEnabled MySound_Stop(); #endif } LOCALPROC DoNotInBackgroundTasks(void) { #if 0 if (HaveMyCGCursorIsVisible()) { HaveCursorHidden = ! MyCGCursorIsVisible(); /* This shouldn't be needed, but have seen cursor state get messed up in 10.4. If the os x hide count gets off, this should fix it within a few ticks. oops, no, doesn't seem to be accurate, and makes things worse. particularly if cursor in obscured state after typing into dialog. */ /* trying a different approach further below */ } #endif if (HaveCursorHidden != ( #if MayNotFullScreen (WantCursorHidden #if VarFullScreen || UseFullScreen #endif ) && #endif gWeAreActive && ! CurSpeedStopped)) { HaveCursorHidden = ! HaveCursorHidden; if (HaveCursorHidden) { MyHideCursor(); } else { /* kludge for OS X, where mouse over Dock devider changes cursor, and never sets it back. */ SetCursorArrow(); MyShowCursor(); } } /* check if actual cursor visibility is what it should be */ if (HaveMyCGCursorIsVisible()) { /* but only in OS X 10.3 and later */ if (MyCGCursorIsVisible()) { if (HaveCursorHidden) { MyHideCursor(); if (MyCGCursorIsVisible()) { /* didn't work, attempt undo so that hide cursor count won't get large */ MyShowCursor(); } } } else { if (! HaveCursorHidden) { MyShowCursor(); /* don't check if worked, assume can't decrement hide cursor count below 0 */ } } } } LOCALPROC CheckForSavedTasks(void) { if (MyEvtQNeedRecover) { MyEvtQNeedRecover = falseblnr; /* attempt cleanup, MyEvtQNeedRecover may get set again */ MyEvtQTryRecoverFromFull(); } #if EnableFSMouseMotion if (HaveMouseMotion) { MyMouseConstrain(); } #endif if (RequestMacOff) { RequestMacOff = falseblnr; if (AnyDiskInserted()) { MacMsgOverride(kStrQuitWarningTitle, kStrQuitWarningMessage); } else { ForceMacOff = trueblnr; } } if (! gWeAreActive) { if (! (gTrueBackgroundFlag || gLackFocusFlag)) { gWeAreActive = trueblnr; ReconnectKeyCodes3(); SetCursorArrow(); } } #if VarFullScreen if (gTrueBackgroundFlag && WantFullScreen) { ToggleWantFullScreen(); } #endif if (CurSpeedStopped != (SpeedStopped || (gTrueBackgroundFlag && ! RunInBackground #if EnableAutoSlow && 0 && (QuietSubTicks >= 4092) #endif ))) { CurSpeedStopped = ! CurSpeedStopped; if (CurSpeedStopped) { EnterSpeedStopped(); } else { LeaveSpeedStopped(); } } #if EnableRecreateW if (gWeAreActive) { if (0 #if EnableMagnify || (UseMagnify != WantMagnify) #endif #if VarFullScreen || (UseFullScreen != WantFullScreen) #endif ) { (void) ReCreateMainWindow(); } } #endif #if MayFullScreen if (GrabMachine != ( #if VarFullScreen UseFullScreen && #endif gWeAreActive && ! CurSpeedStopped)) { GrabMachine = ! GrabMachine; AdjustMachineGrab(); } #endif if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) { MacMsgDisplayOn(); } if (WantScreensChangedCheck) { WantScreensChangedCheck = falseblnr; MyUpdateOpenGLContext(); } if (NeedWholeScreenDraw) { NeedWholeScreenDraw = falseblnr; ScreenChangedAll(); } if (! gWeAreActive) { /* dialog during drag and drop hangs if in background and don't want recursive dialogs so wait til later to display dialog */ } else { #if IncludeSonyNew if (vSonyNewDiskWanted) { #if IncludeSonyNameNew if (vSonyNewDiskName != NotAPbuf) { CFStringRef NewDiskName = CFStringCreateWithPbuf(vSonyNewDiskName); MakeNewDisk(vSonyNewDiskSize, NewDiskName); if (NewDiskName != NULL) { CFRelease(NewDiskName); } PbufDispose(vSonyNewDiskName); vSonyNewDiskName = NotAPbuf; } else #endif { MakeNewDisk(vSonyNewDiskSize, NULL); } vSonyNewDiskWanted = falseblnr; /* must be done after may have gotten disk */ } #endif if (RequestInsertDisk) { RequestInsertDisk = falseblnr; InsertADisk0(); } } #if NeedRequestIthDisk if (0 != RequestIthDisk) { Sony_InsertIth(RequestIthDisk); RequestIthDisk = 0; } #endif if (gWeAreActive) { DoNotInBackgroundTasks(); } } #define CheckItem CheckMenuItem /* Menu Constants */ #define kAppleMenu 128 #define kFileMenu 129 #define kSpecialMenu 130 enum { kCmdIdNull, kCmdIdMoreCommands, kNumCmdIds }; LOCALFUNC OSStatus MyProcessCommand(MenuCommand inCommandID) { OSStatus result = noErr; switch (inCommandID) { case kHICommandAbout: DoAboutMsg(); break; case kHICommandQuit: RequestMacOff = trueblnr; break; case kHICommandOpen: RequestInsertDisk = trueblnr; break; case kCmdIdMoreCommands: DoMoreCommandsMsg(); break; default: result = eventNotHandledErr; break; } return result; } LOCALFUNC OSStatus Keyboard_UpdateKeyMap3(EventRef theEvent, blnr down) { UInt32 uiKeyCode; HandleEventModifiers(theEvent); GetEventParameter(theEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(uiKeyCode), NULL, &uiKeyCode); Keyboard_UpdateKeyMap2(Keyboard_RemapMac(uiKeyCode & 0x000000FF), down); return noErr; } static pascal OSStatus MyEventHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void * userData) { OSStatus result = eventNotHandledErr; UInt32 eventClass = GetEventClass(theEvent); UInt32 eventKind = GetEventKind(theEvent); UnusedParam(userData); switch (eventClass) { case kEventClassMouse: switch (eventKind) { case kEventMouseDown: #if MayFullScreen if (GrabMachine) { HandleEventLocation(theEvent); HandleEventModifiers(theEvent); MyMouseButtonSet(trueblnr); result = noErr; } else #endif { result = CallNextEventHandler( nextHandler, theEvent); } break; case kEventMouseUp: HandleEventLocation(theEvent); HandleEventModifiers(theEvent); MyMouseButtonSet(falseblnr); #if MayFullScreen if (GrabMachine) { result = noErr; } else #endif { result = CallNextEventHandler( nextHandler, theEvent); } break; case kEventMouseMoved: case kEventMouseDragged: IsOurMouseMove = falseblnr; result = CallNextEventHandler( nextHandler, theEvent); /* Actually, mousing over window does't seem to go through here, it goes directly to the window routine. But since not documented either way, leave the check in case this changes. */ if (! IsOurMouseMove) { MouseIsOutside = trueblnr; #if 0 /* don't bother, CheckMouseState will take care of it, better */ HandleEventLocation(theEvent); HandleEventModifiers(theEvent); #endif } break; } break; case kEventClassApplication: switch (eventKind) { case kEventAppActivated: gTrueBackgroundFlag = falseblnr; result = noErr; break; case kEventAppDeactivated: gTrueBackgroundFlag = trueblnr; result = noErr; ClearWeAreActive(); break; } break; case kEventClassCommand: switch (eventKind) { case kEventProcessCommand: { HICommand hiCommand; GetEventParameter(theEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &hiCommand); result = MyProcessCommand(hiCommand.commandID); } break; } break; case kEventClassKeyboard: if (! gWeAreActive) { return CallNextEventHandler(nextHandler, theEvent); } else { switch (eventKind) { case kEventRawKeyDown: result = Keyboard_UpdateKeyMap3( theEvent, trueblnr); break; case kEventRawKeyUp: result = Keyboard_UpdateKeyMap3( theEvent, falseblnr); break; case kEventRawKeyModifiersChanged: HandleEventModifiers(theEvent); result = noErr; break; default: break; } } break; default: break; } return result; } LOCALPROC AppendMenuConvertCStr( MenuRef menu, MenuCommand inCommandID, char *s) { CFStringRef cfStr = CFStringCreateFromSubstCStr(s); if (NULL != cfStr) { AppendMenuItemTextWithCFString(menu, cfStr, 0, inCommandID, NULL); CFRelease(cfStr); } } LOCALPROC AppendMenuSep(MenuRef menu) { AppendMenuItemTextWithCFString(menu, NULL, kMenuItemAttrSeparator, 0, NULL); } LOCALFUNC MenuRef NewMenuFromConvertCStr(short menuID, char *s) { MenuRef menu = NULL; CFStringRef cfStr = CFStringCreateFromSubstCStr(s); if (NULL != cfStr) { OSStatus err = CreateNewMenu(menuID, 0, &menu); if (err != noErr) { menu = NULL; } else { (void) SetMenuTitleWithCFString(menu, cfStr); } CFRelease(cfStr); } return menu; } LOCALPROC RemoveCommandKeysInMenu(MenuRef theMenu) { MenuRef outHierMenu; int i; UInt16 n = CountMenuItems(theMenu); for (i = 1; i <= n; ++i) { SetItemCmd(theMenu, i, 0); if (noErr == GetMenuItemHierarchicalMenu( theMenu, i, &outHierMenu) && (NULL != outHierMenu)) { RemoveCommandKeysInMenu(outHierMenu); } } } LOCALFUNC blnr InstallOurMenus(void) { MenuRef menu; Str255 s; PStrFromChar(s, (char)20); menu = NewMenu(kAppleMenu, s); if (menu != NULL) { AppendMenuConvertCStr(menu, kHICommandAbout, kStrMenuItemAbout); AppendMenuSep(menu); InsertMenu(menu, 0); } menu = NewMenuFromConvertCStr(kFileMenu, kStrMenuFile); if (menu != NULL) { AppendMenuConvertCStr(menu, kHICommandOpen, kStrMenuItemOpen ";ll"); InsertMenu(menu, 0); } menu = NewMenuFromConvertCStr(kSpecialMenu, kStrMenuSpecial); if (menu != NULL) { AppendMenuConvertCStr(menu, kCmdIdMoreCommands, kStrMenuItemMore ";ll"); InsertMenu(menu, 0); } { MenuRef outMenu; MenuItemIndex outIndex; if (noErr == GetIndMenuItemWithCommandID( NULL, kHICommandQuit, 1, &outMenu, &outIndex)) { RemoveCommandKeysInMenu(outMenu); } } DrawMenuBar(); return trueblnr; } LOCALFUNC blnr InstallOurAppearanceClient(void) { RegisterAppearanceClient(); /* maybe not needed ? */ return trueblnr; } LOCALVAR blnr DisplayRegistrationCallBackSuccessful = falseblnr; static void DisplayRegisterReconfigurationCallback( CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *userInfo) { UnusedParam(display); UnusedParam(userInfo); if (0 != (flags & kCGDisplayBeginConfigurationFlag)) { /* fprintf(stderr, "kCGDisplayBeginConfigurationFlag\n"); */ } else { #if 0 if (0 != (flags & kCGDisplayMovedFlag)) { fprintf(stderr, "kCGDisplayMovedFlag\n"); } if (0 != (flags & kCGDisplaySetMainFlag)) { fprintf(stderr, "kCGDisplaySetMainFlag\n"); } if (0 != (flags & kCGDisplaySetModeFlag)) { fprintf(stderr, "kCGDisplaySetModeFlag\n"); } if (0 != (flags & kCGDisplayAddFlag)) { fprintf(stderr, "kCGDisplayAddFlag\n"); } if (0 != (flags & kCGDisplayRemoveFlag)) { fprintf(stderr, "kCGDisplayRemoveFlag\n"); } if (0 != (flags & kCGDisplayEnabledFlag)) { fprintf(stderr, "kCGDisplayEnabledFlag\n"); } if (0 != (flags & kCGDisplayDisabledFlag)) { fprintf(stderr, "kCGDisplayDisabledFlag\n"); } if (0 != (flags & kCGDisplayMirrorFlag)) { fprintf(stderr, "kCGDisplayMirrorFlag\n"); } if (0 != (flags & kCGDisplayUnMirrorFlag)) { fprintf(stderr, "kCGDisplayMirrorFlag\n"); } #endif WantScreensChangedCheck = trueblnr; #if VarFullScreen if (WantFullScreen) { ToggleWantFullScreen(); } #endif } } LOCALFUNC blnr InstallOurEventHandlers(void) { EventTypeSpec eventTypes[] = { {kEventClassMouse, kEventMouseDown}, {kEventClassMouse, kEventMouseUp}, {kEventClassMouse, kEventMouseMoved}, {kEventClassMouse, kEventMouseDragged}, {kEventClassKeyboard, kEventRawKeyModifiersChanged}, {kEventClassKeyboard, kEventRawKeyDown}, {kEventClassKeyboard, kEventRawKeyUp}, {kEventClassApplication, kEventAppActivated}, {kEventClassApplication, kEventAppDeactivated}, {kEventClassCommand, kEventProcessCommand} }; InstallApplicationEventHandler( NewEventHandlerUPP(MyEventHandler), GetEventTypeCount(eventTypes), eventTypes, NULL, NULL); InitKeyCodes(); InstallAppleEventHandlers(); if (HaveMyCGDisplayRegisterReconfigurationCallback()) { if (kCGErrorSuccess == MyCGDisplayRegisterReconfigurationCallback( DisplayRegisterReconfigurationCallback, NULL)) { DisplayRegistrationCallBackSuccessful = trueblnr; } } /* (void) SetMouseCoalescingEnabled(false, NULL); */ return trueblnr; } LOCALPROC UnInstallOurEventHandlers(void) { if (DisplayRegistrationCallBackSuccessful) { if (HaveMyCGDisplayRemoveReconfigurationCallback()) { MyCGDisplayRemoveReconfigurationCallback( DisplayRegisterReconfigurationCallback, NULL); } } } GLOBALOSGLUPROC WaitForNextTick(void) { OSStatus err; EventRef theEvent; ui3r NumChecks; EventTimeout inTimeout; EventTargetRef theTarget = GetEventDispatcherTarget(); inTimeout = kEventDurationNoWait; label_retry: NumChecks = 0; while ((NumChecks < 32) && (noErr == (err = ReceiveNextEvent(0, NULL, inTimeout, true, &theEvent)))) { (void) SendEventToEventTarget(theEvent, theTarget); ReleaseEvent(theEvent); inTimeout = kEventDurationNoWait; ++NumChecks; } CheckForSavedTasks(); if (ForceMacOff) { return; } if (CurSpeedStopped) { DoneWithDrawingForTick(); inTimeout = kEventDurationForever; goto label_retry; } if (ExtraTimeNotOver()) { inTimeout = NextTickChangeTime - GetCurrentEventTime(); if (inTimeout > 0.0) { #if 1 struct timespec rqt; struct timespec rmt; rqt.tv_sec = 0; rqt.tv_nsec = inTimeout / kEventDurationNanosecond; (void) nanosleep(&rqt, &rmt); inTimeout = kEventDurationNoWait; goto label_retry; #elif 1 usleep(inTimeout / kEventDurationMicrosecond); inTimeout = kEventDurationNoWait; goto label_retry; #else /* This has higher overhead. */ goto label_retry; #endif } } if (CheckDateTime()) { #if MySoundEnabled MySound_SecondNotify(); #endif #if EnableDemoMsg DemoModeSecondNotify(); #endif } if (gWeAreActive) { CheckMouseState(); } OnTrueTime = TrueEmulatedTime; #if dbglog_TimeStuff dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime); #endif } /* --- platform independent code can be thought of as going here --- */ #include "PROGMAIN.h" LOCALPROC ReserveAllocAll(void) { #if dbglog_HAVE dbglog_ReserveAlloc(); #endif ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr); ReserveAllocOneBlock(&screencomparebuff, vMacScreenNumBytes, 5, trueblnr); ReserveAllocOneBlock(&CntrlDisplayBuff, vMacScreenNumBytes, 5, falseblnr); ReserveAllocOneBlock(&ScalingBuff, vMacScreenNumPixels #if 0 != vMacScreenDepth * 4 #endif , 5, falseblnr); ReserveAllocOneBlock(&CLUT_final, CLUT_finalsz, 5, falseblnr); #if MySoundEnabled ReserveAllocOneBlock((ui3p *)&TheSoundBuffer, dbhBufferSize, 5, falseblnr); #endif EmulationReserveAlloc(); } LOCALFUNC blnr AllocMyMemory(void) { uimr n; blnr IsOk = falseblnr; ReserveAllocOffset = 0; ReserveAllocBigBlock = nullpr; ReserveAllocAll(); n = ReserveAllocOffset; ReserveAllocBigBlock = (ui3p)calloc(1, n); if (NULL == ReserveAllocBigBlock) { MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr); } else { ReserveAllocOffset = 0; ReserveAllocAll(); if (n != ReserveAllocOffset) { /* oops, program error */ } else { IsOk = trueblnr; } } return IsOk; } LOCALFUNC blnr InitOSGLU(void) { if (AllocMyMemory()) if (InitMyApplInfo()) #if dbglog_HAVE if (dbglog_open()) #endif #if MySoundEnabled if (MySound_Init()) #endif if (InstallOurAppearanceClient()) if (InstallOurEventHandlers()) if (InstallOurMenus()) if (CreateMainWindow()) if (LoadMacRom()) if (LoadInitialImages()) #if UseActvCode if (ActvCodeInit()) #endif #if EmLocalTalk if (InitLocalTalk()) #endif if (InitLocationDat()) if (WaitForRom()) { return trueblnr; } return falseblnr; } #if dbglog_HAVE && 0 IMPORTPROC DoDumpTable(void); #endif #if dbglog_HAVE && 0 IMPORTPROC DumpRTC(void); #endif LOCALPROC UnInitOSGLU(void) { #if dbglog_HAVE && 0 DoDumpTable(); #endif #if dbglog_HAVE && 0 DumpRTC(); #endif if (MacMsgDisplayed) { MacMsgDisplayOff(); } #if MayFullScreen UngrabMachine(); #endif #if MySoundEnabled MySound_Stop(); #endif CloseAglCurrentContext(); CloseMainWindow(); #if MayFullScreen My_ShowMenuBar(); #endif #if IncludePbufs UnInitPbufs(); #endif UnInitDrives(); if (! gTrueBackgroundFlag) { CheckSavedMacMsg(); } UnInstallOurEventHandlers(); #if dbglog_HAVE dbglog_close(); #endif UnInitMyApplInfo(); ForceShowCursor(); } LOCALPROC ZapOSGLUVars(void) { InitDrives(); ZapWinStateVars(); } /* adapted from Apple "Technical Q&A QA1061" */ static pascal OSStatus EventLoopEventHandler( EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) /* This code contains the standard Carbon event dispatch loop, as per "Inside Macintosh: Handling Carbon Events", Listing 3-10, except: o this loop supports yielding to cooperative threads based on the application maintaining the gNumberOfRunningThreads global variable, and o it also works around a problem with the Inside Macintosh code which unexpectedly quits when run on traditional Mac OS 9. See RunApplicationEventLoopWithCooperativeThreadSupport for an explanation of why this is inside a Carbon event handler. The code in Inside Mac has a problem in that it quits the event loop when ReceiveNextEvent returns an error. This is wrong because ReceiveNextEvent can return eventLoopQuitErr when you call WakeUpProcess on traditional Mac OS. So, rather than relying on an error from ReceiveNextEvent, this routine tracks whether the application is really quitting by installing a customer handler for the kEventClassApplication/kEventAppQuit Carbon event. All the custom handler does is call through to the previous handler and, if it returns noErr (which indicates the application is quitting, it sets quitNow so that our event loop quits. Note that this approach continues to support QuitApplicationEventLoop, which is a simple wrapper that just posts a kEventClassApplication/kEventAppQuit event to the event loop. */ { UnusedParam(inHandlerCallRef); UnusedParam(inEvent); UnusedParam(inUserData); ProgramMain(); QuitApplicationEventLoop(); return noErr; } LOCALPROC RunApplicationEventLoopWithCooperativeThreadSupport(void) /* A reimplementation of RunApplicationEventLoop that supports yielding time to cooperative threads. */ { static const EventTypeSpec eventSpec = {'KWIN', 'KWIN'}; EventHandlerUPP theEventLoopEventHandlerUPP = nil; EventHandlerRef installedHandler = NULL; EventRef dummyEvent = nil; /* Install EventLoopEventHandler, create a dummy event and post it, and then call RunApplicationEventLoop. The rationale for this is as follows: We want to unravel RunApplicationEventLoop so that we can can yield to cooperative threads. In fact, the core code for RunApplicationEventLoop is pretty easy (you can see it above in EventLoopEventHandler). However, if you just execute this code you miss out on all the standard event handlers. These are relatively easy to reproduce (handling the quit event and so on), but doing so is a pain because a) it requires a bunch boilerplate code, and b) if Apple extends the list of standard event handlers, your application wouldn't benefit. So, we execute our event loop from within a Carbon event handler that we cause to be executed by explicitly posting an event to our event loop. Thus, the standard event handlers are installed while our event loop runs. */ if (nil == (theEventLoopEventHandlerUPP = NewEventHandlerUPP(EventLoopEventHandler))) { /* fail */ } else if (noErr != InstallEventHandler(GetApplicationEventTarget(), theEventLoopEventHandlerUPP, 1, &eventSpec, nil, &installedHandler)) { /* fail */ } else if (noErr != MacCreateEvent(nil, 'KWIN', 'KWIN', GetCurrentEventTime(), kEventAttributeNone, &dummyEvent)) { /* fail */ } else if (noErr != PostEventToQueue(GetMainEventQueue(), dummyEvent, kEventPriorityHigh)) { /* fail */ } else { RunApplicationEventLoop(); } if (nil != dummyEvent) { ReleaseEvent(dummyEvent); } if (NULL != installedHandler) { (void) RemoveEventHandler(installedHandler); } } int main(void) { ZapOSGLUVars(); if (InitOSGLU()) { RunApplicationEventLoopWithCooperativeThreadSupport(); } UnInitOSGLU(); return 0; }