this repo has no description
1/*
2 OSGLUOSX.c
3
4 Copyright (C) 2009 Philip Cummins, Richard F. Bannister,
5 Paul C. Pratt
6
7 You can redistribute this file and/or modify it under the terms
8 of version 2 of the GNU General Public License as published by
9 the Free Software Foundation. You should have received a copy
10 of the license along with this file; see the file COPYING.
11
12 This file is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 license for more details.
16*/
17
18/*
19 Operating System GLUe for macintosh OS X
20
21 (uses Carbon API. the more recent
22 OSGLUCCO.m uses the Cocoa API)
23
24 All operating system dependent code for the
25 Macintosh platform should go here.
26
27 This code is descended from Richard F. Bannister's Macintosh
28 port of vMac, by Philip Cummins.
29
30 The main entry point 'main' is at the end of this file.
31*/
32
33#include "OSGCOMUI.h"
34#include "OSGCOMUD.h"
35
36#ifdef WantOSGLUOSX
37
38
39/* --- adapting to API/ABI version differences --- */
40
41/*
42 if UsingCarbonLib, instead of native Macho,
43 then some APIs are missing
44*/
45#ifndef UsingCarbonLib
46#define UsingCarbonLib 0
47#endif
48
49LOCALVAR CFBundleRef AppServBunRef;
50
51LOCALVAR blnr DidApplicationServicesBun = falseblnr;
52
53LOCALFUNC blnr HaveApplicationServicesBun(void)
54{
55 if (! DidApplicationServicesBun) {
56 AppServBunRef = CFBundleGetBundleWithIdentifier(
57 CFSTR("com.apple.ApplicationServices"));
58 DidApplicationServicesBun = trueblnr;
59 }
60 return (AppServBunRef != NULL);
61}
62
63#if MayFullScreen || UsingCarbonLib
64
65LOCALVAR CFBundleRef HIToolboxBunRef;
66
67LOCALVAR blnr DidHIToolboxBunRef = falseblnr;
68
69LOCALFUNC blnr HaveHIToolboxBunRef(void)
70{
71 if (! DidHIToolboxBunRef) {
72 HIToolboxBunRef = CFBundleGetBundleWithIdentifier(
73 CFSTR("com.apple.HIToolbox"));
74 DidHIToolboxBunRef = trueblnr;
75 }
76 return (HIToolboxBunRef != NULL);
77}
78
79#endif
80
81LOCALVAR CFBundleRef AGLBunRef;
82
83LOCALVAR blnr DidAGLBunRef = falseblnr;
84
85LOCALFUNC blnr HaveAGLBunRef(void)
86{
87 if (! DidAGLBunRef) {
88 AGLBunRef = CFBundleGetBundleWithIdentifier(
89 CFSTR("com.apple.agl"));
90 DidAGLBunRef = trueblnr;
91 }
92 return (AGLBunRef != NULL);
93}
94
95
96#if MayFullScreen
97
98/* SetSystemUIModeProcPtr API always not available */
99
100typedef UInt32 MySystemUIMode;
101typedef OptionBits MySystemUIOptions;
102
103enum {
104 MykUIModeNormal = 0,
105 MykUIModeAllHidden = 3
106};
107
108enum {
109 MykUIOptionAutoShowMenuBar = 1 << 0,
110 MykUIOptionDisableAppleMenu = 1 << 2,
111 MykUIOptionDisableProcessSwitch = 1 << 3,
112 MykUIOptionDisableForceQuit = 1 << 4,
113 MykUIOptionDisableSessionTerminate = 1 << 5,
114 MykUIOptionDisableHide = 1 << 6
115};
116
117typedef OSStatus (*SetSystemUIModeProcPtr)
118 (MySystemUIMode inMode, MySystemUIOptions inOptions);
119LOCALVAR SetSystemUIModeProcPtr MySetSystemUIMode = NULL;
120LOCALVAR blnr DidSetSystemUIMode = falseblnr;
121
122LOCALFUNC blnr HaveMySetSystemUIMode(void)
123{
124 if (! DidSetSystemUIMode) {
125 if (HaveHIToolboxBunRef()) {
126 MySetSystemUIMode =
127 (SetSystemUIModeProcPtr)
128 CFBundleGetFunctionPointerForName(
129 HIToolboxBunRef, CFSTR("SetSystemUIMode"));
130 }
131 DidSetSystemUIMode = trueblnr;
132 }
133 return (MySetSystemUIMode != NULL);
134}
135
136#endif
137
138/* In 10.1 or later */
139
140typedef OSStatus (*LSCopyDisplayNameForRefProcPtr)
141 (const FSRef *inRef, CFStringRef *outDisplayName);
142LOCALVAR LSCopyDisplayNameForRefProcPtr MyLSCopyDisplayNameForRef
143 = NULL;
144LOCALVAR blnr DidLSCopyDisplayNameForRef = falseblnr;
145
146LOCALFUNC blnr HaveMyLSCopyDisplayNameForRef(void)
147{
148 if (! DidLSCopyDisplayNameForRef) {
149 if (HaveApplicationServicesBun()) {
150 MyLSCopyDisplayNameForRef =
151 (LSCopyDisplayNameForRefProcPtr)
152 CFBundleGetFunctionPointerForName(
153 AppServBunRef, CFSTR("LSCopyDisplayNameForRef"));
154 }
155 DidLSCopyDisplayNameForRef = trueblnr;
156 }
157 return (MyLSCopyDisplayNameForRef != NULL);
158}
159
160/* In 10.5 or later */
161
162typedef GLboolean (*aglSetWindowRefProcPtr)
163 (AGLContext ctx, WindowRef window);
164LOCALVAR aglSetWindowRefProcPtr MyaglSetWindowRef = NULL;
165LOCALVAR blnr DidaglSetWindowRef = falseblnr;
166
167LOCALFUNC blnr HaveMyaglSetWindowRef(void)
168{
169 if (! DidaglSetWindowRef) {
170 if (HaveAGLBunRef()) {
171 MyaglSetWindowRef =
172 (aglSetWindowRefProcPtr)
173 CFBundleGetFunctionPointerForName(
174 AGLBunRef, CFSTR("aglSetWindowRef"));
175 }
176 DidaglSetWindowRef = trueblnr;
177 }
178 return (MyaglSetWindowRef != NULL);
179}
180
181/* Deprecated as of 10.5 */
182
183typedef CGrafPtr My_AGLDrawable;
184typedef GLboolean (*aglSetDrawableProcPtr)
185 (AGLContext ctx, My_AGLDrawable draw);
186LOCALVAR aglSetDrawableProcPtr MyaglSetDrawable = NULL;
187LOCALVAR blnr DidaglSetDrawable = falseblnr;
188
189LOCALFUNC blnr HaveMyaglSetDrawable(void)
190{
191 if (! DidaglSetDrawable) {
192 if (HaveAGLBunRef()) {
193 MyaglSetDrawable =
194 (aglSetDrawableProcPtr)
195 CFBundleGetFunctionPointerForName(
196 AGLBunRef, CFSTR("aglSetDrawable"));
197 }
198 DidaglSetDrawable = trueblnr;
199 }
200 return (MyaglSetDrawable != NULL);
201}
202
203/* routines not in carbon lib */
204
205
206#if UsingCarbonLib
207
208typedef CGDisplayErr
209(*CGGetActiveDisplayListProcPtr) (
210 CGDisplayCount maxDisplays,
211 CGDirectDisplayID * activeDspys,
212 CGDisplayCount * dspyCnt);
213LOCALVAR CGGetActiveDisplayListProcPtr MyCGGetActiveDisplayList = NULL;
214LOCALVAR blnr DidCGGetActiveDisplayList = falseblnr;
215
216LOCALFUNC blnr HaveMyCGGetActiveDisplayList(void)
217{
218 if (! DidCGGetActiveDisplayList) {
219 if (HaveApplicationServicesBun()) {
220 MyCGGetActiveDisplayList =
221 (CGGetActiveDisplayListProcPtr)
222 CFBundleGetFunctionPointerForName(
223 AppServBunRef, CFSTR("CGGetActiveDisplayList"));
224 }
225 DidCGGetActiveDisplayList = trueblnr;
226 }
227 return (MyCGGetActiveDisplayList != NULL);
228}
229
230#else
231
232#define HaveMyCGGetActiveDisplayList() trueblnr
233#define MyCGGetActiveDisplayList CGGetActiveDisplayList
234
235#endif /* ! UsingCarbonLib */
236
237
238#if UsingCarbonLib
239
240typedef CGRect
241(*CGDisplayBoundsProcPtr) (CGDirectDisplayID display);
242LOCALVAR CGDisplayBoundsProcPtr MyCGDisplayBounds = NULL;
243LOCALVAR blnr DidCGDisplayBounds = falseblnr;
244
245LOCALFUNC blnr HaveMyCGDisplayBounds(void)
246{
247 if (! DidCGDisplayBounds) {
248 if (HaveApplicationServicesBun()) {
249 MyCGDisplayBounds =
250 (CGDisplayBoundsProcPtr)
251 CFBundleGetFunctionPointerForName(
252 AppServBunRef, CFSTR("CGDisplayBounds"));
253 }
254 DidCGDisplayBounds = trueblnr;
255 }
256 return (MyCGDisplayBounds != NULL);
257}
258
259#else
260
261#define HaveMyCGDisplayBounds() trueblnr
262#define MyCGDisplayBounds CGDisplayBounds
263
264#endif /* ! UsingCarbonLib */
265
266
267#if UsingCarbonLib
268
269typedef size_t
270(*CGDisplayPixelsWideProcPtr) (CGDirectDisplayID display);
271LOCALVAR CGDisplayPixelsWideProcPtr MyCGDisplayPixelsWide = NULL;
272LOCALVAR blnr DidCGDisplayPixelsWide = falseblnr;
273
274LOCALFUNC blnr HaveMyCGDisplayPixelsWide(void)
275{
276 if (! DidCGDisplayPixelsWide) {
277 if (HaveApplicationServicesBun()) {
278 MyCGDisplayPixelsWide =
279 (CGDisplayPixelsWideProcPtr)
280 CFBundleGetFunctionPointerForName(
281 AppServBunRef, CFSTR("CGDisplayPixelsWide"));
282 }
283 DidCGDisplayPixelsWide = trueblnr;
284 }
285 return (MyCGDisplayPixelsWide != NULL);
286}
287
288#else
289
290#define HaveMyCGDisplayPixelsWide() trueblnr
291#define MyCGDisplayPixelsWide CGDisplayPixelsWide
292
293#endif /* ! UsingCarbonLib */
294
295
296#if UsingCarbonLib
297
298typedef size_t
299(*CGDisplayPixelsHighProcPtr) (CGDirectDisplayID display);
300LOCALVAR CGDisplayPixelsHighProcPtr MyCGDisplayPixelsHigh = NULL;
301LOCALVAR blnr DidCGDisplayPixelsHigh = falseblnr;
302
303LOCALFUNC blnr HaveMyCGDisplayPixelsHigh(void)
304{
305 if (! DidCGDisplayPixelsHigh) {
306 if (HaveApplicationServicesBun()) {
307 MyCGDisplayPixelsHigh =
308 (CGDisplayPixelsHighProcPtr)
309 CFBundleGetFunctionPointerForName(
310 AppServBunRef, CFSTR("CGDisplayPixelsHigh"));
311 }
312 DidCGDisplayPixelsHigh = trueblnr;
313 }
314 return (MyCGDisplayPixelsHigh != NULL);
315}
316
317#else
318
319#define HaveMyCGDisplayPixelsHigh() trueblnr
320#define MyCGDisplayPixelsHigh CGDisplayPixelsHigh
321
322#endif /* ! UsingCarbonLib */
323
324
325#if UsingCarbonLib
326
327typedef CGDisplayErr
328(*CGDisplayHideCursorProcPtr) (CGDirectDisplayID display);
329LOCALVAR CGDisplayHideCursorProcPtr MyCGDisplayHideCursor = NULL;
330LOCALVAR blnr DidCGDisplayHideCursor = falseblnr;
331
332LOCALFUNC blnr HaveMyCGDisplayHideCursor(void)
333{
334 if (! DidCGDisplayHideCursor) {
335 if (HaveApplicationServicesBun()) {
336 MyCGDisplayHideCursor =
337 (CGDisplayHideCursorProcPtr)
338 CFBundleGetFunctionPointerForName(
339 AppServBunRef, CFSTR("CGDisplayHideCursor"));
340 }
341 DidCGDisplayHideCursor = trueblnr;
342 }
343 return (MyCGDisplayHideCursor != NULL);
344}
345
346#else
347
348#define HaveMyCGDisplayHideCursor() trueblnr
349#define MyCGDisplayHideCursor CGDisplayHideCursor
350
351#endif /* ! UsingCarbonLib */
352
353
354#if UsingCarbonLib
355
356typedef CGDisplayErr
357(*CGDisplayShowCursorProcPtr) (CGDirectDisplayID display);
358LOCALVAR CGDisplayShowCursorProcPtr MyCGDisplayShowCursor = NULL;
359LOCALVAR blnr DidCGDisplayShowCursor = falseblnr;
360
361LOCALFUNC blnr HaveMyCGDisplayShowCursor(void)
362{
363 if (! DidCGDisplayShowCursor) {
364 if (HaveApplicationServicesBun()) {
365 MyCGDisplayShowCursor =
366 (CGDisplayShowCursorProcPtr)
367 CFBundleGetFunctionPointerForName(
368 AppServBunRef, CFSTR("CGDisplayShowCursor"));
369 }
370 DidCGDisplayShowCursor = trueblnr;
371 }
372 return (MyCGDisplayShowCursor != NULL);
373}
374
375#else
376
377#define HaveMyCGDisplayShowCursor() trueblnr
378#define MyCGDisplayShowCursor CGDisplayShowCursor
379
380#endif /* ! UsingCarbonLib */
381
382
383#if 0
384
385typedef CGDisplayErr (*CGDisplayMoveCursorToPointProcPtr)
386 (CGDirectDisplayID display, CGPoint point);
387LOCALVAR CGDisplayMoveCursorToPointProcPtr MyCGDisplayMoveCursorToPoint
388 = NULL;
389LOCALVAR blnr DidCGDisplayMoveCursorToPoint = falseblnr;
390
391LOCALFUNC blnr HaveMyCGDisplayMoveCursorToPoint(void)
392{
393 if (! DidCGDisplayMoveCursorToPoint) {
394 if (HaveApplicationServicesBun()) {
395 MyCGDisplayMoveCursorToPoint =
396 (CGDisplayMoveCursorToPointProcPtr)
397 CFBundleGetFunctionPointerForName(
398 AppServBunRef, CFSTR("CGDisplayMoveCursorToPoint"));
399 }
400 DidCGDisplayMoveCursorToPoint = trueblnr;
401 }
402 return (MyCGDisplayMoveCursorToPoint != NULL);
403}
404
405#endif /* 0 */
406
407
408#if UsingCarbonLib
409
410typedef CGEventErr
411(*CGWarpMouseCursorPositionProcPtr) (CGPoint newCursorPosition);
412LOCALVAR CGWarpMouseCursorPositionProcPtr MyCGWarpMouseCursorPosition
413 = NULL;
414LOCALVAR blnr DidCGWarpMouseCursorPosition = falseblnr;
415
416LOCALFUNC blnr HaveMyCGWarpMouseCursorPosition(void)
417{
418 if (! DidCGWarpMouseCursorPosition) {
419 if (HaveApplicationServicesBun()) {
420 MyCGWarpMouseCursorPosition =
421 (CGWarpMouseCursorPositionProcPtr)
422 CFBundleGetFunctionPointerForName(
423 AppServBunRef, CFSTR("CGWarpMouseCursorPosition"));
424 }
425 DidCGWarpMouseCursorPosition = trueblnr;
426 }
427 return (MyCGWarpMouseCursorPosition != NULL);
428}
429
430#else
431
432#define HaveMyCGWarpMouseCursorPosition() trueblnr
433#define MyCGWarpMouseCursorPosition CGWarpMouseCursorPosition
434
435#endif /* ! UsingCarbonLib */
436
437
438#if UsingCarbonLib
439
440typedef CGEventErr
441(*CGSetLocalEventsSuppressionIntervalProcPtr) (CFTimeInterval seconds);
442LOCALVAR CGSetLocalEventsSuppressionIntervalProcPtr
443 MyCGSetLocalEventsSuppressionInterval = NULL;
444LOCALVAR blnr DidCGSetLocalEventsSuppressionInterval = falseblnr;
445
446LOCALFUNC blnr HaveMyCGSetLocalEventsSuppressionInterval(void)
447{
448 if (! DidCGSetLocalEventsSuppressionInterval) {
449 if (HaveApplicationServicesBun()) {
450 MyCGSetLocalEventsSuppressionInterval =
451 (CGSetLocalEventsSuppressionIntervalProcPtr)
452 CFBundleGetFunctionPointerForName(
453 AppServBunRef,
454 CFSTR("CGSetLocalEventsSuppressionInterval"));
455 }
456 DidCGSetLocalEventsSuppressionInterval = trueblnr;
457 }
458 return (MyCGSetLocalEventsSuppressionInterval != NULL);
459}
460
461#else
462
463#define HaveMyCGSetLocalEventsSuppressionInterval() trueblnr
464#define MyCGSetLocalEventsSuppressionInterval \
465 CGSetLocalEventsSuppressionInterval
466
467#endif /* ! UsingCarbonLib */
468
469
470#if UsingCarbonLib
471
472typedef OSStatus (*CreateStandardAlertProcPtr) (
473 AlertType alertType,
474 CFStringRef error,
475 CFStringRef explanation,
476 const AlertStdCFStringAlertParamRec * param,
477 DialogRef * outAlert
478);
479LOCALVAR CreateStandardAlertProcPtr MyCreateStandardAlert = NULL;
480LOCALVAR blnr DidCreateStandardAlert = falseblnr;
481
482LOCALFUNC blnr HaveMyCreateStandardAlert(void)
483{
484 if (! DidCreateStandardAlert) {
485 if (HaveHIToolboxBunRef()) {
486 MyCreateStandardAlert =
487 (CreateStandardAlertProcPtr)
488 CFBundleGetFunctionPointerForName(
489 HIToolboxBunRef, CFSTR("CreateStandardAlert"));
490 }
491 DidCreateStandardAlert = trueblnr;
492 }
493 return (MyCreateStandardAlert != NULL);
494}
495
496#else
497
498#define HaveMyCreateStandardAlert() trueblnr
499#define MyCreateStandardAlert CreateStandardAlert
500
501#endif /* ! UsingCarbonLib */
502
503
504#if UsingCarbonLib
505
506typedef OSStatus (*RunStandardAlertProcPtr) (
507 DialogRef inAlert,
508 ModalFilterUPP filterProc,
509 DialogItemIndex * outItemHit
510);
511LOCALVAR RunStandardAlertProcPtr MyRunStandardAlert = NULL;
512LOCALVAR blnr DidRunStandardAlert = falseblnr;
513
514LOCALFUNC blnr HaveMyRunStandardAlert(void)
515{
516 if (! DidRunStandardAlert) {
517 if (HaveHIToolboxBunRef()) {
518 MyRunStandardAlert =
519 (RunStandardAlertProcPtr)
520 CFBundleGetFunctionPointerForName(
521 HIToolboxBunRef, CFSTR("RunStandardAlert"));
522 }
523 DidRunStandardAlert = trueblnr;
524 }
525 return (MyRunStandardAlert != NULL);
526}
527
528#else
529
530#define HaveMyRunStandardAlert() trueblnr
531#define MyRunStandardAlert RunStandardAlert
532
533#endif /* ! UsingCarbonLib */
534
535
536typedef CGDirectDisplayID (*CGMainDisplayIDProcPtr)(void);
537
538LOCALVAR CGMainDisplayIDProcPtr MyCGMainDisplayID = NULL;
539LOCALVAR blnr DidCGMainDisplayID = falseblnr;
540
541LOCALFUNC blnr HaveMyCGMainDisplayID(void)
542{
543 if (! DidCGMainDisplayID) {
544 if (HaveApplicationServicesBun()) {
545 MyCGMainDisplayID =
546 (CGMainDisplayIDProcPtr)
547 CFBundleGetFunctionPointerForName(
548 AppServBunRef, CFSTR("CGMainDisplayID"));
549 }
550 DidCGMainDisplayID = trueblnr;
551 }
552 return (MyCGMainDisplayID != NULL);
553}
554
555#ifndef kCGNullDirectDisplay /* not in MPW Headers */
556#define kCGNullDirectDisplay ((CGDirectDisplayID)0)
557#endif
558
559typedef CGError
560(*CGDisplayRegisterReconfigurationCallbackProcPtr) (
561 CGDisplayReconfigurationCallBack proc,
562 void *userInfo
563 );
564LOCALVAR CGDisplayRegisterReconfigurationCallbackProcPtr
565 MyCGDisplayRegisterReconfigurationCallback = NULL;
566LOCALVAR blnr DidCGDisplayRegisterReconfigurationCallback = falseblnr;
567
568LOCALFUNC blnr HaveMyCGDisplayRegisterReconfigurationCallback(void)
569{
570 if (! DidCGDisplayRegisterReconfigurationCallback) {
571 if (HaveApplicationServicesBun()) {
572 MyCGDisplayRegisterReconfigurationCallback =
573 (CGDisplayRegisterReconfigurationCallbackProcPtr)
574 CFBundleGetFunctionPointerForName(
575 AppServBunRef,
576 CFSTR("CGDisplayRegisterReconfigurationCallback"));
577 }
578 DidCGDisplayRegisterReconfigurationCallback = trueblnr;
579 }
580 return (MyCGDisplayRegisterReconfigurationCallback != NULL);
581}
582
583
584typedef CGError
585(*CGDisplayRemoveReconfigurationCallbackProcPtr) (
586 CGDisplayReconfigurationCallBack proc,
587 void *userInfo
588 );
589LOCALVAR CGDisplayRemoveReconfigurationCallbackProcPtr
590 MyCGDisplayRemoveReconfigurationCallback = NULL;
591LOCALVAR blnr DidCGDisplayRemoveReconfigurationCallback = falseblnr;
592
593LOCALFUNC blnr HaveMyCGDisplayRemoveReconfigurationCallback(void)
594{
595 if (! DidCGDisplayRemoveReconfigurationCallback) {
596 if (HaveApplicationServicesBun()) {
597 MyCGDisplayRemoveReconfigurationCallback =
598 (CGDisplayRemoveReconfigurationCallbackProcPtr)
599 CFBundleGetFunctionPointerForName(
600 AppServBunRef,
601 CFSTR("CGDisplayRemoveReconfigurationCallback"));
602 }
603 DidCGDisplayRemoveReconfigurationCallback = trueblnr;
604 }
605 return (MyCGDisplayRemoveReconfigurationCallback != NULL);
606}
607
608
609typedef boolean_t (*CGCursorIsVisibleProcPtr)(void);
610
611LOCALVAR CGCursorIsVisibleProcPtr MyCGCursorIsVisible = NULL;
612LOCALVAR blnr DidCGCursorIsVisible = falseblnr;
613
614LOCALFUNC blnr HaveMyCGCursorIsVisible(void)
615{
616 if (! DidCGCursorIsVisible) {
617 if (HaveApplicationServicesBun()) {
618 MyCGCursorIsVisible =
619 (CGCursorIsVisibleProcPtr)
620 CFBundleGetFunctionPointerForName(
621 AppServBunRef, CFSTR("CGCursorIsVisible"));
622 }
623 DidCGCursorIsVisible = trueblnr;
624 }
625 return (MyCGCursorIsVisible != NULL);
626}
627
628
629/* --- end of adapting to API/ABI version differences --- */
630
631/* --- some simple utilities --- */
632
633GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount)
634{
635 (void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
636}
637
638LOCALPROC PStrFromChar(ps3p r, char x)
639{
640 r[0] = 1;
641 r[1] = (char)x;
642}
643
644/* --- mac style errors --- */
645
646#define CheckSavetMacErr(result) (mnvm_noErr == (err = (result)))
647 /*
648 where 'err' is a variable of type tMacErr in the function
649 this is used in
650 */
651
652#define To_tMacErr(result) ((tMacErr)(ui4b)(result))
653
654#define CheckSaveMacErr(result) (CheckSavetMacErr(To_tMacErr(result)))
655
656
657#define NeedCell2UnicodeMap 1
658#define NeedRequestInsertDisk 1
659#define NeedDoMoreCommandsMsg 1
660#define NeedDoAboutMsg 1
661
662#include "INTLCHAR.h"
663
664LOCALPROC UniCharStrFromSubstCStr(int *L, UniChar *x, char *s)
665{
666 int i;
667 int L0;
668 ui3b ps[ClStrMaxLength];
669
670 ClStrFromSubstCStr(&L0, ps, s);
671
672 for (i = 0; i < L0; ++i) {
673 x[i] = Cell2UnicodeMap[ps[i]];
674 }
675
676 *L = L0;
677}
678
679#define NotAfileRef (-1)
680
681LOCALFUNC tMacErr MyMakeFSRefUniChar(FSRef *ParentRef,
682 UniCharCount fileNameLength, const UniChar *fileName,
683 blnr *isFolder, FSRef *ChildRef)
684{
685 tMacErr err;
686 Boolean isFolder0;
687 Boolean isAlias;
688
689 if (CheckSaveMacErr(FSMakeFSRefUnicode(ParentRef,
690 fileNameLength, fileName, kTextEncodingUnknown,
691 ChildRef)))
692 if (CheckSaveMacErr(FSResolveAliasFile(ChildRef,
693 TRUE, &isFolder0, &isAlias)))
694 {
695 *isFolder = isFolder0;
696 }
697
698 return err;
699}
700
701LOCALFUNC tMacErr MyMakeFSRefC(FSRef *ParentRef, char *fileName,
702 blnr *isFolder, FSRef *ChildRef)
703{
704 int L;
705 UniChar x[ClStrMaxLength];
706
707 UniCharStrFromSubstCStr(&L, x, fileName);
708 return MyMakeFSRefUniChar(ParentRef, L, x,
709 isFolder, ChildRef);
710}
711
712#if UseActvFile
713LOCALFUNC tMacErr OpenNamedFileInFolderRef(FSRef *ParentRef,
714 char *fileName, short *refnum)
715{
716 tMacErr err;
717 blnr isFolder;
718 FSRef ChildRef;
719 HFSUniStr255 forkName;
720
721 if (CheckSavetMacErr(MyMakeFSRefC(ParentRef, fileName,
722 &isFolder, &ChildRef)))
723 if (CheckSaveMacErr(FSGetDataForkName(&forkName)))
724 if (CheckSaveMacErr(FSOpenFork(&ChildRef, forkName.length,
725 forkName.unicode, fsRdPerm, refnum)))
726 {
727 /* ok */
728 }
729
730 return err;
731}
732#endif
733
734#if dbglog_HAVE || UseActvFile
735LOCALFUNC tMacErr OpenWriteNamedFileInFolderRef(FSRef *ParentRef,
736 char *fileName, short *refnum)
737{
738 tMacErr err;
739 blnr isFolder;
740 FSRef ChildRef;
741 HFSUniStr255 forkName;
742 int L;
743 UniChar x[ClStrMaxLength];
744
745 UniCharStrFromSubstCStr(&L, x, fileName);
746 err = MyMakeFSRefUniChar(ParentRef, L, x, &isFolder, &ChildRef);
747 if (mnvm_fnfErr == err) {
748 err = To_tMacErr(FSCreateFileUnicode(ParentRef, L, x, 0, NULL,
749 &ChildRef, NULL));
750 }
751 if (mnvm_noErr == err) {
752 if (CheckSaveMacErr(FSGetDataForkName(&forkName)))
753 if (CheckSaveMacErr(FSOpenFork(&ChildRef, forkName.length,
754 forkName.unicode, fsRdWrPerm, refnum)))
755 {
756 /* ok */
757 }
758 }
759
760 return err;
761}
762#endif
763
764LOCALFUNC tMacErr FindNamedChildRef(FSRef *ParentRef,
765 char *ChildName, FSRef *ChildRef)
766{
767 tMacErr err;
768 blnr isFolder;
769
770 if (CheckSavetMacErr(MyMakeFSRefC(ParentRef, ChildName,
771 &isFolder, ChildRef)))
772 {
773 if (! isFolder) {
774 err = mnvm_miscErr;
775 }
776 }
777
778 return err;
779}
780
781#if UseActvFile || (IncludeSonyNew && ! SaveDialogEnable)
782LOCALFUNC tMacErr FindOrMakeNamedChildRef(FSRef *ParentRef,
783 char *ChildName, FSRef *ChildRef)
784{
785 tMacErr err;
786 blnr isFolder;
787 int L;
788 UniChar x[ClStrMaxLength];
789
790 UniCharStrFromSubstCStr(&L, x, ChildName);
791 if (CheckSavetMacErr(MyMakeFSRefUniChar(ParentRef, L, x,
792 &isFolder, ChildRef)))
793 {
794 if (! isFolder) {
795 err = mnvm_miscErr;
796 }
797 }
798 if (mnvm_fnfErr == err) {
799 err = To_tMacErr(FSCreateDirectoryUnicode(
800 ParentRef, L, x, kFSCatInfoNone, NULL,
801 ChildRef, NULL, NULL));
802 }
803
804 return err;
805}
806#endif
807
808LOCALVAR FSRef MyDatDirRef;
809
810LOCALVAR CFStringRef MyAppName = NULL;
811
812LOCALPROC UnInitMyApplInfo(void)
813{
814 if (MyAppName != NULL) {
815 CFRelease(MyAppName);
816 }
817}
818
819LOCALFUNC blnr InitMyApplInfo(void)
820{
821 ProcessSerialNumber currentProcess = {0, kCurrentProcess};
822 FSRef fsRef;
823 FSRef parentRef;
824
825 if (noErr == GetProcessBundleLocation(¤tProcess,
826 &fsRef))
827 if (noErr == FSGetCatalogInfo(&fsRef, kFSCatInfoNone,
828 NULL, NULL, NULL, &parentRef))
829 {
830 FSRef ContentsRef;
831 FSRef DatRef;
832
833 MyDatDirRef = parentRef;
834 if (mnvm_noErr == FindNamedChildRef(&fsRef, "Contents",
835 &ContentsRef))
836 if (mnvm_noErr == FindNamedChildRef(&ContentsRef, "mnvm_dat",
837 &DatRef))
838 {
839 MyDatDirRef = DatRef;
840 }
841
842 if (HaveMyLSCopyDisplayNameForRef()) {
843 if (noErr == MyLSCopyDisplayNameForRef(&fsRef, &MyAppName))
844 {
845 return trueblnr;
846 }
847 }
848
849 if (noErr == CopyProcessName(¤tProcess, &MyAppName)) {
850 return trueblnr;
851 }
852 }
853 return falseblnr;
854}
855
856/* --- sending debugging info to file --- */
857
858#if dbglog_HAVE
859
860LOCALVAR SInt16 dbglog_File = NotAfileRef;
861
862LOCALFUNC blnr dbglog_open0(void)
863{
864 tMacErr err;
865
866 err = OpenWriteNamedFileInFolderRef(&MyDatDirRef,
867 "dbglog.txt", &dbglog_File);
868
869 return (mnvm_noErr == err);
870}
871
872LOCALPROC dbglog_write0(char *s, uimr L)
873{
874 ByteCount actualCount;
875
876 if (dbglog_File != NotAfileRef) {
877 (void) FSWriteFork(
878 dbglog_File,
879 fsFromMark,
880 0,
881 L,
882 s,
883 &actualCount);
884 }
885}
886
887LOCALPROC dbglog_close0(void)
888{
889 if (dbglog_File != NotAfileRef) {
890 (void) FSSetForkSize(dbglog_File, fsFromMark, 0);
891 (void) FSCloseFork(dbglog_File);
892 dbglog_File = NotAfileRef;
893 }
894}
895
896#endif
897
898#if 1 /* (0 != vMacScreenDepth) && (vMacScreenDepth < 4) */
899#define WantColorTransValid 1
900#endif
901
902#include "COMOSGLU.h"
903
904/* --- time, date --- */
905
906/*
907 be sure to avoid getting confused if TickCount
908 overflows and wraps.
909*/
910
911#define dbglog_TimeStuff (0 && dbglog_HAVE)
912
913LOCALVAR ui5b TrueEmulatedTime = 0;
914
915LOCALVAR EventTime NextTickChangeTime;
916
917#define MyTickDuration (kEventDurationSecond / 60.14742)
918
919LOCALPROC UpdateTrueEmulatedTime(void)
920{
921 EventTime LatestTime = GetCurrentEventTime();
922 EventTime TimeDiff = LatestTime - NextTickChangeTime;
923
924 if (TimeDiff >= 0.0) {
925 if (TimeDiff > 16 * MyTickDuration) {
926 /* emulation interrupted, forget it */
927 ++TrueEmulatedTime;
928 NextTickChangeTime = LatestTime + MyTickDuration;
929
930#if dbglog_TimeStuff
931 dbglog_writelnNum("emulation interrupted",
932 TrueEmulatedTime);
933#endif
934 } else {
935 do {
936 ++TrueEmulatedTime;
937 TimeDiff -= MyTickDuration;
938 NextTickChangeTime += MyTickDuration;
939 } while (TimeDiff >= 0.0);
940 }
941 }
942}
943
944GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void)
945{
946 UpdateTrueEmulatedTime();
947 return TrueEmulatedTime == OnTrueTime;
948}
949
950/* LOCALVAR EventTime ETimeBase; */
951LOCALVAR CFAbsoluteTime ATimeBase;
952LOCALVAR ui5b TimeSecBase;
953
954LOCALFUNC blnr CheckDateTime(void)
955{
956 ui5b NewMacDateInSecond = TimeSecBase
957 + (ui5b)(CFAbsoluteTimeGetCurrent() - ATimeBase);
958 /*
959 ui5b NewMacDateInSecond = TimeSecBase
960 + (ui5b)(GetCurrentEventTime() - ETimeBase);
961 */
962 /*
963 ui5b NewMacDateInSecond = ((ui5b)(CFAbsoluteTimeGetCurrent()))
964 + 3061137600UL;
965 */
966
967 if (CurMacDateInSeconds != NewMacDateInSecond) {
968 CurMacDateInSeconds = NewMacDateInSecond;
969 return trueblnr;
970 } else {
971 return falseblnr;
972 }
973}
974
975/* --- parameter buffers --- */
976
977#include "PBUFSTDC.h"
978
979/* --- drives --- */
980
981LOCALVAR SInt16 Drives[NumDrives]; /* open disk image files */
982
983GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer,
984 tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
985 ui5r *Sony_ActCount)
986{
987 ByteCount actualCount;
988 tMacErr result;
989
990 if (IsWrite) {
991 result = To_tMacErr(FSWriteFork(
992 Drives[Drive_No],
993 fsFromStart,
994 Sony_Start,
995 Sony_Count,
996 Buffer,
997 &actualCount));
998 } else {
999 result = To_tMacErr(FSReadFork(
1000 Drives[Drive_No],
1001 fsFromStart,
1002 Sony_Start,
1003 Sony_Count,
1004 Buffer,
1005 &actualCount));
1006 }
1007
1008 if (nullpr != Sony_ActCount) {
1009 *Sony_ActCount = actualCount;
1010 }
1011
1012 return result;
1013}
1014
1015GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count)
1016{
1017 SInt64 forkSize;
1018 tMacErr err = To_tMacErr(
1019 FSGetForkSize(Drives[Drive_No], &forkSize));
1020 *Sony_Count = forkSize;
1021 return err;
1022}
1023
1024GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
1025{
1026 SInt16 refnum = Drives[Drive_No];
1027 Drives[Drive_No] = NotAfileRef;
1028
1029 DiskEjectedNotify(Drive_No);
1030
1031 (void) FSCloseFork(refnum);
1032
1033 return mnvm_noErr;
1034}
1035
1036#if IncludeSonyNew
1037GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No)
1038{
1039 FSRef ref;
1040 tMacErr err0;
1041 tMacErr err;
1042
1043 err0 = To_tMacErr(FSGetForkCBInfo(Drives[Drive_No], 0,
1044 NULL /* iterator */,
1045 NULL /* actualRefNum */,
1046 NULL /* forkInfo */,
1047 &ref /* ref */,
1048 NULL /* outForkName */));
1049 err = vSonyEject(Drive_No);
1050
1051 if (mnvm_noErr != err0) {
1052 err = err0;
1053 } else {
1054 (void) FSDeleteObject(&ref);
1055 }
1056
1057 return err;
1058}
1059#endif
1060
1061#if IncludeSonyGetName
1062GLOBALOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r)
1063{
1064 FSRef ref;
1065 HFSUniStr255 outName;
1066 CFStringRef DiskName;
1067 tMacErr err;
1068
1069 if (CheckSaveMacErr(FSGetForkCBInfo(Drives[Drive_No], 0,
1070 NULL /* iterator */,
1071 NULL /* actualRefNum */,
1072 NULL /* forkInfo */,
1073 &ref /* ref */,
1074 NULL /* outForkName */)))
1075 if (CheckSaveMacErr(FSGetCatalogInfo(&ref,
1076 kFSCatInfoNone /* whichInfo */,
1077 NULL /* catalogInfo */,
1078 &outName /* outName */,
1079 NULL /* fsSpec */,
1080 NULL /* parentRef */)))
1081 {
1082 DiskName = CFStringCreateWithCharacters(
1083 kCFAllocatorDefault, outName.unicode,
1084 outName.length);
1085 if (NULL != DiskName) {
1086 tPbuf i;
1087
1088 if (CheckSavetMacErr(PbufNew(outName.length, &i))) {
1089 if (CFStringGetBytes(DiskName,
1090 CFRangeMake(0, outName.length),
1091 kCFStringEncodingMacRoman,
1092 '?', false,
1093 PbufDat[i],
1094 outName.length,
1095 NULL) != outName.length)
1096 {
1097 err = mnvm_miscErr;
1098 }
1099 if (mnvm_noErr != err) {
1100 PbufDispose(i);
1101 } else {
1102 *r = i;
1103 }
1104 }
1105 CFRelease(DiskName);
1106 }
1107 }
1108
1109 return err;
1110}
1111#endif
1112
1113#if IncludeHostTextClipExchange
1114GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i)
1115{
1116 tMacErr err;
1117 ScrapRef scrapRef;
1118
1119 if (CheckSaveMacErr(ClearCurrentScrap()))
1120 if (CheckSaveMacErr(GetCurrentScrap(&scrapRef)))
1121 if (CheckSaveMacErr(PutScrapFlavor(
1122 scrapRef,
1123 FOUR_CHAR_CODE('TEXT'),
1124 kScrapFlavorMaskNone,
1125 PbufSize[i],
1126 PbufDat[i])))
1127 {
1128 /* ok */
1129 }
1130
1131 PbufDispose(i);
1132
1133 return err;
1134}
1135#endif
1136
1137#if IncludeHostTextClipExchange
1138GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r)
1139{
1140 tMacErr err;
1141 ScrapRef scrap;
1142 ScrapFlavorFlags flavorFlags;
1143 Size byteCount;
1144 tPbuf i;
1145
1146 if (CheckSaveMacErr(GetCurrentScrap(&scrap)))
1147 if (CheckSaveMacErr(GetScrapFlavorFlags(scrap,
1148 'TEXT', &flavorFlags)))
1149 if (CheckSaveMacErr(GetScrapFlavorSize(scrap,
1150 'TEXT', &byteCount)))
1151 if (CheckSavetMacErr(PbufNew(byteCount, &i)))
1152 {
1153 Size byteCount2 = byteCount;
1154 if (CheckSaveMacErr(GetScrapFlavorData(scrap,
1155 'TEXT', &byteCount2,
1156 PbufDat[i])))
1157 {
1158 if (byteCount != byteCount2) {
1159 err = mnvm_miscErr;
1160 }
1161 }
1162 if (mnvm_noErr != err) {
1163 PbufDispose(i);
1164 } else {
1165 *r = i;
1166 }
1167 }
1168
1169 return err;
1170}
1171#endif
1172
1173
1174#if EmLocalTalk
1175LOCALFUNC blnr EntropyGather(void)
1176{
1177 /*
1178 gather some entropy from several places, just in case
1179 /dev/urandom is not available.
1180 */
1181
1182 {
1183 EventTime v = GetCurrentEventTime();
1184
1185 EntropyPoolAddPtr((ui3p)&v, sizeof(v) / sizeof(ui3b));
1186 }
1187
1188 {
1189 CFAbsoluteTime v = CFAbsoluteTimeGetCurrent();
1190
1191 EntropyPoolAddPtr((ui3p)&v, sizeof(v) / sizeof(ui3b));
1192 }
1193
1194 {
1195 Point v;
1196
1197 GetGlobalMouse(&v);
1198 EntropyPoolAddPtr((ui3p)&v, sizeof(v) / sizeof(ui3b));
1199 }
1200
1201 {
1202 ProcessSerialNumber v;
1203
1204 (void) GetFrontProcess(&v);
1205 EntropyPoolAddPtr((ui3p)&v, sizeof(v) / sizeof(ui3b));
1206 }
1207
1208 {
1209 ui5b dat[2];
1210 int fd;
1211
1212 if (-1 == (fd = open("/dev/urandom", O_RDONLY))) {
1213#if dbglog_HAVE
1214 dbglog_writeCStr("open /dev/urandom fails");
1215 dbglog_writeNum(errno);
1216 dbglog_writeCStr(" (");
1217 dbglog_writeCStr(strerror(errno));
1218 dbglog_writeCStr(")");
1219 dbglog_writeReturn();
1220#endif
1221 } else {
1222
1223 if (read(fd, &dat, sizeof(dat)) < 0) {
1224#if dbglog_HAVE
1225 dbglog_writeCStr("open /dev/urandom fails");
1226 dbglog_writeNum(errno);
1227 dbglog_writeCStr(" (");
1228 dbglog_writeCStr(strerror(errno));
1229 dbglog_writeCStr(")");
1230 dbglog_writeReturn();
1231#endif
1232 } else {
1233
1234#if dbglog_HAVE
1235 dbglog_writeCStr("dat: ");
1236 dbglog_writeHex(dat[0]);
1237 dbglog_writeCStr(" ");
1238 dbglog_writeHex(dat[1]);
1239 dbglog_writeReturn();
1240#endif
1241
1242 e_p[0] ^= dat[0];
1243 e_p[1] ^= dat[1];
1244 /*
1245 if "/dev/urandom" is working correctly,
1246 this should make the previous contents of e_p
1247 irrelevant. if it is completely broken, like
1248 returning 0, this will not make e_p any less
1249 random.
1250 */
1251
1252#if dbglog_HAVE
1253 dbglog_writeCStr("ep: ");
1254 dbglog_writeHex(e_p[0]);
1255 dbglog_writeCStr(" ");
1256 dbglog_writeHex(e_p[1]);
1257 dbglog_writeReturn();
1258#endif
1259 }
1260
1261 close(fd);
1262 }
1263 }
1264
1265 return trueblnr;
1266}
1267#endif
1268
1269
1270#if EmLocalTalk
1271
1272#include "LOCALTLK.h"
1273
1274#endif
1275
1276
1277/* --- control mode and internationalization --- */
1278
1279#define WantKeyboard_RemapMac 1
1280
1281#include "CONTROLM.h"
1282
1283
1284/* --- video out --- */
1285
1286LOCALVAR WindowPtr gMyMainWindow = NULL;
1287LOCALVAR WindowPtr gMyOldWindow = NULL;
1288
1289#if MayFullScreen
1290LOCALVAR short hOffset;
1291LOCALVAR short vOffset;
1292#endif
1293
1294#if MayFullScreen
1295LOCALVAR blnr GrabMachine = falseblnr;
1296#endif
1297
1298#if VarFullScreen
1299LOCALVAR blnr UseFullScreen = (WantInitFullScreen != 0);
1300#endif
1301
1302#if EnableMagnify
1303LOCALVAR blnr UseMagnify = (WantInitMagnify != 0);
1304#endif
1305
1306#if EnableMagnify
1307LOCALPROC MyScaleRect(Rect *r)
1308{
1309 r->left *= MyWindowScale;
1310 r->right *= MyWindowScale;
1311 r->top *= MyWindowScale;
1312 r->bottom *= MyWindowScale;
1313}
1314#endif
1315
1316LOCALPROC SetScrnRectFromCoords(Rect *r,
1317 si4b top, si4b left, si4b bottom, si4b right)
1318{
1319 r->left = left;
1320 r->right = right;
1321 r->top = top;
1322 r->bottom = bottom;
1323
1324#if VarFullScreen
1325 if (UseFullScreen)
1326#endif
1327#if MayFullScreen
1328 {
1329 OffsetRect(r, - ViewHStart, - ViewVStart);
1330 }
1331#endif
1332
1333#if EnableMagnify
1334 if (UseMagnify) {
1335 MyScaleRect(r);
1336 }
1337#endif
1338
1339#if VarFullScreen
1340 if (UseFullScreen)
1341#endif
1342#if MayFullScreen
1343 {
1344 OffsetRect(r, hOffset, vOffset);
1345 }
1346#endif
1347}
1348
1349LOCALVAR ui3p ScalingBuff = nullpr;
1350
1351LOCALVAR ui3p CLUT_final;
1352
1353#define CLUT_finalsz1 (256 * 8)
1354
1355#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
1356
1357#define CLUT_finalClrSz (256 << (5 - vMacScreenDepth))
1358
1359#define CLUT_finalsz ((CLUT_finalClrSz > CLUT_finalsz1) \
1360 ? CLUT_finalClrSz : CLUT_finalsz1)
1361
1362#else
1363#define CLUT_finalsz CLUT_finalsz1
1364#endif
1365
1366
1367#define ScrnMapr_DoMap UpdateBWLuminanceCopy
1368#define ScrnMapr_Src GetCurDrawBuff()
1369#define ScrnMapr_Dst ScalingBuff
1370#define ScrnMapr_SrcDepth 0
1371#define ScrnMapr_DstDepth 3
1372#define ScrnMapr_Map CLUT_final
1373
1374#include "SCRNMAPR.h"
1375
1376
1377#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
1378
1379#define ScrnMapr_DoMap UpdateMappedColorCopy
1380#define ScrnMapr_Src GetCurDrawBuff()
1381#define ScrnMapr_Dst ScalingBuff
1382#define ScrnMapr_SrcDepth vMacScreenDepth
1383#define ScrnMapr_DstDepth 5
1384#define ScrnMapr_Map CLUT_final
1385
1386#include "SCRNMAPR.h"
1387
1388#endif
1389
1390#if vMacScreenDepth >= 4
1391
1392#define ScrnTrns_DoTrans UpdateTransColorCopy
1393#define ScrnTrns_Src GetCurDrawBuff()
1394#define ScrnTrns_Dst ScalingBuff
1395#define ScrnTrns_SrcDepth vMacScreenDepth
1396#define ScrnTrns_DstDepth 5
1397#define ScrnTrns_DstZLo 1
1398
1399#include "SCRNTRNS.h"
1400
1401#endif
1402
1403LOCALPROC UpdateLuminanceCopy(si4b top, si4b left,
1404 si4b bottom, si4b right)
1405{
1406 int i;
1407
1408#if 0 != vMacScreenDepth
1409 if (UseColorMode) {
1410
1411#if vMacScreenDepth < 4
1412
1413 if (! ColorTransValid) {
1414 int j;
1415 int k;
1416 ui5p p4;
1417
1418 p4 = (ui5p)CLUT_final;
1419 for (i = 0; i < 256; ++i) {
1420 for (k = 1 << (3 - vMacScreenDepth); --k >= 0; ) {
1421 j = (i >> (k << vMacScreenDepth)) & (CLUT_size - 1);
1422 *p4++ = (((long)CLUT_reds[j] & 0xFF00) << 16)
1423 | (((long)CLUT_greens[j] & 0xFF00) << 8)
1424 | ((long)CLUT_blues[j] & 0xFF00);
1425 }
1426 }
1427 ColorTransValid = trueblnr;
1428 }
1429
1430 UpdateMappedColorCopy(top, left, bottom, right);
1431
1432#else
1433 UpdateTransColorCopy(top, left, bottom, right);
1434#endif
1435
1436 } else
1437#endif
1438 {
1439 if (! ColorTransValid) {
1440 int k;
1441 ui3p p4 = (ui3p)CLUT_final;
1442
1443 for (i = 0; i < 256; ++i) {
1444 for (k = 8; --k >= 0; ) {
1445 *p4++ = ((i >> k) & 0x01) - 1;
1446 }
1447 }
1448 ColorTransValid = trueblnr;
1449 }
1450
1451 UpdateBWLuminanceCopy(top, left, bottom, right);
1452 }
1453}
1454
1455LOCALVAR AGLContext ctx = NULL;
1456LOCALVAR short GLhOffset;
1457LOCALVAR short GLvOffset;
1458
1459#ifndef UseAGLdoublebuff
1460#define UseAGLdoublebuff 0
1461#endif
1462
1463LOCALPROC MyDrawWithOpenGL(ui4r top, ui4r left, ui4r bottom, ui4r right)
1464{
1465 if (NULL == ctx) {
1466 /* oops */
1467 } else if (GL_TRUE != aglSetCurrentContext(ctx)) {
1468 /* err = aglReportError() */
1469 } else {
1470 si4b top2;
1471 si4b left2;
1472
1473#if UseAGLdoublebuff
1474 /* redraw all */
1475 top = 0;
1476 left = 0;
1477 bottom = vMacScreenHeight;
1478 right = vMacScreenWidth;
1479#endif
1480
1481#if VarFullScreen
1482 if (UseFullScreen)
1483#endif
1484#if MayFullScreen
1485 {
1486 if (top < ViewVStart) {
1487 top = ViewVStart;
1488 }
1489 if (left < ViewHStart) {
1490 left = ViewHStart;
1491 }
1492 if (bottom > ViewVStart + ViewVSize) {
1493 bottom = ViewVStart + ViewVSize;
1494 }
1495 if (right > ViewHStart + ViewHSize) {
1496 right = ViewHStart + ViewHSize;
1497 }
1498
1499 if ((top >= bottom) || (left >= right)) {
1500 goto label_exit;
1501 }
1502 }
1503#endif
1504
1505 top2 = top;
1506 left2 = left;
1507
1508#if VarFullScreen
1509 if (UseFullScreen)
1510#endif
1511#if MayFullScreen
1512 {
1513 left2 -= ViewHStart;
1514 top2 -= ViewVStart;
1515 }
1516#endif
1517
1518#if EnableMagnify
1519 if (UseMagnify) {
1520 top2 *= MyWindowScale;
1521 left2 *= MyWindowScale;
1522 }
1523#endif
1524
1525#if 0
1526 glClear(GL_COLOR_BUFFER_BIT);
1527 glBitmap(vMacScreenWidth,
1528 vMacScreenHeight,
1529 0,
1530 0,
1531 0,
1532 0,
1533 (const GLubyte *)GetCurDrawBuff());
1534#endif
1535#if 1
1536 UpdateLuminanceCopy(top, left, bottom, right);
1537 glRasterPos2i(GLhOffset + left2, GLvOffset - top2);
1538#if 0 != vMacScreenDepth
1539 if (UseColorMode) {
1540 glDrawPixels(right - left,
1541 bottom - top,
1542 GL_RGBA,
1543 GL_UNSIGNED_INT_8_8_8_8,
1544 ScalingBuff + (left + top * vMacScreenWidth) * 4
1545 );
1546 } else
1547#endif
1548 {
1549 glDrawPixels(right - left,
1550 bottom - top,
1551 GL_LUMINANCE,
1552 GL_UNSIGNED_BYTE,
1553 ScalingBuff + (left + top * vMacScreenWidth)
1554 );
1555 }
1556#endif
1557
1558#if 0 /* a very quick and dirty check of where drawing */
1559 glDrawPixels(right - left,
1560 1,
1561 GL_RED,
1562 GL_UNSIGNED_BYTE,
1563 ScalingBuff + (left + top * vMacScreenWidth)
1564 );
1565
1566 glDrawPixels(1,
1567 bottom - top,
1568 GL_RED,
1569 GL_UNSIGNED_BYTE,
1570 ScalingBuff + (left + top * vMacScreenWidth)
1571 );
1572#endif
1573
1574#if UseAGLdoublebuff
1575 aglSwapBuffers(ctx);
1576#else
1577 glFlush();
1578#endif
1579 }
1580
1581#if MayFullScreen
1582label_exit:
1583 ;
1584#endif
1585}
1586
1587LOCALPROC Update_Screen(void)
1588{
1589 MyDrawWithOpenGL(0, 0, vMacScreenHeight, vMacScreenWidth);
1590}
1591
1592LOCALPROC MyDrawChangesAndClear(void)
1593{
1594 if (ScreenChangedBottom > ScreenChangedTop) {
1595 MyDrawWithOpenGL(ScreenChangedTop, ScreenChangedLeft,
1596 ScreenChangedBottom, ScreenChangedRight);
1597 ScreenClearChanges();
1598 }
1599}
1600
1601
1602LOCALVAR blnr MouseIsOutside = falseblnr;
1603 /*
1604 MouseIsOutside true if sure mouse outside our window. If in
1605 our window, or not sure, set false.
1606 */
1607
1608LOCALVAR blnr WantCursorHidden = falseblnr;
1609
1610LOCALPROC MousePositionNotify(Point NewMousePos)
1611{
1612 /*
1613 Not MouseIsOutside includes in the title bar, etc, so have
1614 to check if in content area.
1615 */
1616
1617 Rect r;
1618 blnr ShouldHaveCursorHidden = ! MouseIsOutside;
1619
1620 GetWindowBounds(gMyMainWindow, kWindowContentRgn, &r);
1621
1622 NewMousePos.h -= r.left;
1623 NewMousePos.v -= r.top;
1624
1625#if VarFullScreen
1626 if (UseFullScreen)
1627#endif
1628#if MayFullScreen
1629 {
1630 NewMousePos.h -= hOffset;
1631 NewMousePos.v -= vOffset;
1632 }
1633#endif
1634
1635#if EnableMagnify
1636 if (UseMagnify) {
1637 NewMousePos.h /= MyWindowScale;
1638 NewMousePos.v /= MyWindowScale;
1639 }
1640#endif
1641
1642#if VarFullScreen
1643 if (UseFullScreen)
1644#endif
1645#if MayFullScreen
1646 {
1647 NewMousePos.h += ViewHStart;
1648 NewMousePos.v += ViewVStart;
1649 }
1650#endif
1651
1652#if EnableFSMouseMotion
1653 if (HaveMouseMotion) {
1654 MyMousePositionSetDelta(NewMousePos.h - SavedMouseH,
1655 NewMousePos.v - SavedMouseV);
1656 SavedMouseH = NewMousePos.h;
1657 SavedMouseV = NewMousePos.v;
1658 } else
1659#endif
1660 {
1661 if (NewMousePos.h < 0) {
1662 NewMousePos.h = 0;
1663 ShouldHaveCursorHidden = falseblnr;
1664 } else if (NewMousePos.h >= vMacScreenWidth) {
1665 NewMousePos.h = vMacScreenWidth - 1;
1666 ShouldHaveCursorHidden = falseblnr;
1667 }
1668 if (NewMousePos.v < 0) {
1669 NewMousePos.v = 0;
1670 ShouldHaveCursorHidden = falseblnr;
1671 } else if (NewMousePos.v >= vMacScreenHeight) {
1672 NewMousePos.v = vMacScreenHeight - 1;
1673 ShouldHaveCursorHidden = falseblnr;
1674 }
1675
1676 /* if (ShouldHaveCursorHidden || CurMouseButton) */
1677 /*
1678 for a game like arkanoid, would like mouse to still
1679 move even when outside window in one direction
1680 */
1681 MyMousePositionSet(NewMousePos.h, NewMousePos.v);
1682 }
1683
1684 WantCursorHidden = ShouldHaveCursorHidden;
1685}
1686
1687LOCALPROC CheckMouseState(void)
1688{
1689 Point NewMousePos;
1690 GetGlobalMouse(&NewMousePos);
1691 /*
1692 Deprecated, but haven't found usable replacement.
1693 Between window deactivate and then reactivate,
1694 mouse can move without getting kEventMouseMoved.
1695 Also no way to get initial position.
1696 (Also don't get kEventMouseMoved after
1697 using menu bar. Or while using menubar, but
1698 that isn't too important.)
1699 */
1700 MousePositionNotify(NewMousePos);
1701}
1702
1703LOCALVAR blnr gLackFocusFlag = falseblnr;
1704LOCALVAR blnr gWeAreActive = falseblnr;
1705
1706GLOBALOSGLUPROC DoneWithDrawingForTick(void)
1707{
1708#if EnableFSMouseMotion
1709 if (HaveMouseMotion) {
1710 AutoScrollScreen();
1711 }
1712#endif
1713 MyDrawChangesAndClear();
1714}
1715
1716LOCALVAR blnr CurSpeedStopped = trueblnr;
1717
1718/* --- keyboard --- */
1719
1720LOCALVAR UInt32 SavedModifiers = 0;
1721
1722LOCALPROC MyUpdateKeyboardModifiers(UInt32 theModifiers)
1723{
1724 UInt32 ChangedModifiers = theModifiers ^ SavedModifiers;
1725
1726 if (0 != ChangedModifiers) {
1727 if (0 != (ChangedModifiers & shiftKey)) {
1728 Keyboard_UpdateKeyMap2(MKC_formac_Shift,
1729 (shiftKey & theModifiers) != 0);
1730 }
1731 if (0 != (ChangedModifiers & cmdKey)) {
1732 Keyboard_UpdateKeyMap2(MKC_formac_Command,
1733 (cmdKey & theModifiers) != 0);
1734 }
1735 if (0 != (ChangedModifiers & alphaLock)) {
1736 Keyboard_UpdateKeyMap2(MKC_formac_CapsLock,
1737 (alphaLock & theModifiers) != 0);
1738 }
1739 if (0 != (ChangedModifiers & optionKey)) {
1740 Keyboard_UpdateKeyMap2(MKC_formac_Option,
1741 (optionKey & theModifiers) != 0);
1742 }
1743 if (0 != (ChangedModifiers & controlKey)) {
1744 Keyboard_UpdateKeyMap2(MKC_formac_Control,
1745 (controlKey & theModifiers) != 0);
1746 }
1747
1748 SavedModifiers = theModifiers;
1749 }
1750}
1751
1752LOCALPROC ReconnectKeyCodes3(void)
1753{
1754 /*
1755 turn off any modifiers (other than alpha)
1756 that were turned on by drag and drop,
1757 unless still being held down.
1758 */
1759
1760 UInt32 theModifiers = GetCurrentKeyModifiers();
1761
1762 MyUpdateKeyboardModifiers(theModifiers
1763 & (SavedModifiers | alphaLock));
1764
1765 SavedModifiers = theModifiers;
1766}
1767
1768/* --- display utilities --- */
1769
1770/* DoForEachDisplay adapted from Apple Technical Q&A QA1168 */
1771
1772typedef void
1773(*ForEachDisplayProcPtr) (CGDirectDisplayID display);
1774
1775LOCALPROC DoForEachDisplay0(CGDisplayCount dspCount,
1776 CGDirectDisplayID *displays, ForEachDisplayProcPtr p)
1777{
1778 CGDisplayCount i;
1779
1780 if (noErr == MyCGGetActiveDisplayList(dspCount,
1781 displays, &dspCount))
1782 {
1783 for (i = 0; i < dspCount; ++i) {
1784 p(displays[i]);
1785 }
1786 }
1787}
1788
1789LOCALPROC DoForEachDisplay(ForEachDisplayProcPtr p)
1790{
1791 CGDisplayCount dspCount = 0;
1792
1793 if (HaveMyCGGetActiveDisplayList()
1794 && (noErr == MyCGGetActiveDisplayList(0, NULL, &dspCount)))
1795 {
1796 if (dspCount <= 2) {
1797 CGDirectDisplayID displays[2];
1798 DoForEachDisplay0(dspCount, displays, p);
1799 } else {
1800 CGDirectDisplayID *displays =
1801 calloc((size_t)dspCount, sizeof(CGDirectDisplayID));
1802 if (NULL != displays) {
1803 DoForEachDisplay0(dspCount, displays, p);
1804 free(displays);
1805 }
1806 }
1807 }
1808}
1809
1810LOCALVAR void *datp;
1811
1812LOCALPROC MyMainDisplayIDProc(CGDirectDisplayID display)
1813{
1814 CGDirectDisplayID *p = (CGDirectDisplayID *)datp;
1815
1816 if (kCGNullDirectDisplay == *p) {
1817 *p = display;
1818 }
1819}
1820
1821LOCALFUNC CGDirectDisplayID MyMainDisplayID(void)
1822{
1823 if (HaveMyCGMainDisplayID()) {
1824 return MyCGMainDisplayID();
1825 } else {
1826 /* for before OS X 10.2 */
1827 CGDirectDisplayID r = kCGNullDirectDisplay;
1828 void *savedatp = datp;
1829 datp = (void *)&r;
1830 DoForEachDisplay(MyMainDisplayIDProc);
1831 datp = savedatp;
1832 return r;
1833 }
1834}
1835
1836/* --- cursor hiding --- */
1837
1838#if 0
1839LOCALPROC MyShowCursorProc(CGDirectDisplayID display)
1840{
1841 (void) CGDisplayShowCursor(display);
1842}
1843#endif
1844
1845LOCALPROC MyShowCursor(void)
1846{
1847#if 0
1848 /* ShowCursor(); deprecated */
1849 DoForEachDisplay(MyShowCursorProc);
1850#endif
1851 if (HaveMyCGDisplayShowCursor()) {
1852 (void) MyCGDisplayShowCursor(MyMainDisplayID());
1853 /* documentation now claims argument ignored */
1854 }
1855}
1856
1857#if 0
1858LOCALPROC MyHideCursorProc(CGDirectDisplayID display)
1859{
1860 (void) CGDisplayHideCursor(display);
1861}
1862#endif
1863
1864LOCALPROC MyHideCursor(void)
1865{
1866#if 0
1867 /* HideCursor(); deprecated */
1868 DoForEachDisplay(MyHideCursorProc);
1869#endif
1870 if (HaveMyCGDisplayHideCursor()) {
1871 (void) MyCGDisplayHideCursor(MyMainDisplayID());
1872 /* documentation now claims argument ignored */
1873 }
1874}
1875
1876LOCALVAR blnr HaveCursorHidden = falseblnr;
1877
1878LOCALPROC ForceShowCursor(void)
1879{
1880 if (HaveCursorHidden) {
1881 HaveCursorHidden = falseblnr;
1882 MyShowCursor();
1883 }
1884}
1885
1886/* --- cursor moving --- */
1887
1888LOCALPROC SetCursorArrow(void)
1889{
1890 SetThemeCursor(kThemeArrowCursor);
1891}
1892
1893#if EnableMoveMouse
1894LOCALFUNC blnr MyMoveMouse(si4b h, si4b v)
1895{
1896 Point CurMousePos;
1897 Rect r;
1898
1899#if VarFullScreen
1900 if (UseFullScreen)
1901#endif
1902#if MayFullScreen
1903 {
1904 h -= ViewHStart;
1905 v -= ViewVStart;
1906 }
1907#endif
1908
1909#if EnableMagnify
1910 if (UseMagnify) {
1911 h *= MyWindowScale;
1912 v *= MyWindowScale;
1913 }
1914#endif
1915
1916#if VarFullScreen
1917 if (UseFullScreen)
1918#endif
1919#if MayFullScreen
1920 {
1921 h += hOffset;
1922 v += vOffset;
1923 }
1924#endif
1925
1926 GetWindowBounds(gMyMainWindow, kWindowContentRgn, &r);
1927 CurMousePos.h = r.left + h;
1928 CurMousePos.v = r.top + v;
1929
1930 /*
1931 This method from SDL_QuartzWM.m, "Simple DirectMedia Layer",
1932 Copyright (C) 1997-2003 Sam Lantinga
1933 */
1934 if (HaveMyCGSetLocalEventsSuppressionInterval()) {
1935 if (noErr != MyCGSetLocalEventsSuppressionInterval(0.0)) {
1936 /* don't use MacMsg which can call MyMoveMouse */
1937 }
1938 }
1939 if (HaveMyCGWarpMouseCursorPosition()) {
1940 CGPoint pt;
1941 pt.x = CurMousePos.h;
1942 pt.y = CurMousePos.v;
1943 if (noErr != MyCGWarpMouseCursorPosition(pt)) {
1944 /* don't use MacMsg which can call MyMoveMouse */
1945 }
1946 }
1947#if 0
1948 if (HaveMyCGDisplayMoveCursorToPoint()) {
1949 CGPoint pt;
1950 pt.x = CurMousePos.h;
1951 pt.y = CurMousePos.v;
1952 if (noErr != MyCGDisplayMoveCursorToPoint(
1953 MyMainDisplayID(), pt))
1954 {
1955 /* don't use MacMsg which can call MyMoveMouse */
1956 }
1957 }
1958#endif
1959
1960 return trueblnr;
1961}
1962#endif
1963
1964#if EnableFSMouseMotion
1965LOCALPROC AdjustMouseMotionGrab(void)
1966{
1967 if (gMyMainWindow != NULL) {
1968#if MayFullScreen
1969 if (GrabMachine) {
1970 /*
1971 if magnification changes, need to reset,
1972 even if HaveMouseMotion already true
1973 */
1974 if (MyMoveMouse(ViewHStart + (ViewHSize / 2),
1975 ViewVStart + (ViewVSize / 2)))
1976 {
1977 SavedMouseH = ViewHStart + (ViewHSize / 2);
1978 SavedMouseV = ViewVStart + (ViewVSize / 2);
1979 HaveMouseMotion = trueblnr;
1980 }
1981 } else
1982#endif
1983 {
1984 if (HaveMouseMotion) {
1985 (void) MyMoveMouse(CurMouseH, CurMouseV);
1986 HaveMouseMotion = falseblnr;
1987 }
1988 }
1989 }
1990}
1991#endif
1992
1993#if EnableFSMouseMotion
1994LOCALPROC MyMouseConstrain(void)
1995{
1996 si4b shiftdh;
1997 si4b shiftdv;
1998
1999 if (SavedMouseH < ViewHStart + (ViewHSize / 4)) {
2000 shiftdh = ViewHSize / 2;
2001 } else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4)) {
2002 shiftdh = - ViewHSize / 2;
2003 } else {
2004 shiftdh = 0;
2005 }
2006 if (SavedMouseV < ViewVStart + (ViewVSize / 4)) {
2007 shiftdv = ViewVSize / 2;
2008 } else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4)) {
2009 shiftdv = - ViewVSize / 2;
2010 } else {
2011 shiftdv = 0;
2012 }
2013 if ((shiftdh != 0) || (shiftdv != 0)) {
2014 SavedMouseH += shiftdh;
2015 SavedMouseV += shiftdv;
2016 if (! MyMoveMouse(SavedMouseH, SavedMouseV)) {
2017 HaveMouseMotion = falseblnr;
2018 }
2019 }
2020}
2021#endif
2022
2023#if 0
2024LOCALFUNC blnr InitMousePosition(void)
2025{
2026 /*
2027 Since there doesn't seem to be any nondeprecated
2028 way to get initial cursor position, instead
2029 start by moving cursor to known position.
2030 */
2031
2032#if VarFullScreen
2033 if (! UseFullScreen)
2034#endif
2035#if MayNotFullScreen
2036 {
2037 CurMouseH = 16;
2038 CurMouseV = 16;
2039 WantCursorHidden = trueblnr;
2040 (void) MyMoveMouse(CurMouseH, CurMouseV);
2041 }
2042#endif
2043
2044 return trueblnr;
2045}
2046#endif
2047
2048/* --- time, date, location, part 2 --- */
2049
2050#include "DATE2SEC.h"
2051
2052LOCALFUNC blnr InitLocationDat(void)
2053{
2054#if AutoLocation || AutoTimeZone
2055 MachineLocation loc;
2056
2057 ReadLocation(&loc);
2058#if AutoLocation
2059 CurMacLatitude = (ui5b)loc.latitude;
2060 CurMacLongitude = (ui5b)loc.longitude;
2061#endif
2062#if AutoTimeZone
2063 CurMacDelta = (ui5b)loc.u.gmtDelta;
2064#endif
2065#endif
2066
2067 {
2068 CFTimeZoneRef tz = CFTimeZoneCopySystem();
2069 if (tz) {
2070 /* CFAbsoluteTime */ ATimeBase = CFAbsoluteTimeGetCurrent();
2071 /* ETimeBase = GetCurrentEventTime(); */
2072 {
2073 CFGregorianDate d = CFAbsoluteTimeGetGregorianDate(
2074 ATimeBase, tz);
2075 double floorsec = floor(d.second);
2076 ATimeBase -= (d.second - floorsec);
2077 /* ETimeBase -= (d.second - floorsec); */
2078 TimeSecBase = Date2MacSeconds(floorsec,
2079 d.minute, d.hour,
2080 d.day, d.month, d.year);
2081
2082 (void) CheckDateTime();
2083 }
2084 CFRelease(tz);
2085 }
2086 }
2087
2088 OnTrueTime = TrueEmulatedTime;
2089
2090 return trueblnr;
2091}
2092
2093LOCALPROC StartUpTimeAdjust(void)
2094{
2095 NextTickChangeTime = GetCurrentEventTime() + MyTickDuration;
2096}
2097
2098/* --- sound --- */
2099
2100#if MySoundEnabled
2101
2102#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
2103#define kSoundBuffers (1 << kLn2SoundBuffers)
2104#define kSoundBuffMask (kSoundBuffers - 1)
2105
2106#define DesiredMinFilledSoundBuffs 3
2107 /*
2108 if too big then sound lags behind emulation.
2109 if too small then sound will have pauses.
2110 */
2111
2112#define kLnOneBuffLen 9
2113#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen)
2114#define kOneBuffLen (1UL << kLnOneBuffLen)
2115#define kAllBuffLen (1UL << kLnAllBuffLen)
2116#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3)
2117#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3)
2118#define kOneBuffSz (1UL << kLnOneBuffSz)
2119#define kAllBuffSz (1UL << kLnAllBuffSz)
2120#define kOneBuffMask (kOneBuffLen - 1)
2121#define kAllBuffMask (kAllBuffLen - 1)
2122#define dbhBufferSize (kAllBuffSz + kOneBuffSz)
2123
2124#define dbglog_SoundStuff (0 && dbglog_HAVE)
2125#define dbglog_SoundBuffStats (0 && dbglog_HAVE)
2126
2127LOCALVAR tpSoundSamp TheSoundBuffer = nullpr;
2128volatile static ui4b ThePlayOffset;
2129volatile static ui4b TheFillOffset;
2130volatile static ui4b MinFilledSoundBuffs;
2131#if dbglog_SoundBuffStats
2132LOCALVAR ui4b MaxFilledSoundBuffs;
2133#endif
2134LOCALVAR ui4b TheWriteOffset;
2135
2136LOCALPROC MySound_Start0(void)
2137{
2138 /* Reset variables */
2139 ThePlayOffset = 0;
2140 TheFillOffset = 0;
2141 TheWriteOffset = 0;
2142 MinFilledSoundBuffs = kSoundBuffers + 1;
2143#if dbglog_SoundBuffStats
2144 MaxFilledSoundBuffs = 0;
2145#endif
2146}
2147
2148GLOBALOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL)
2149{
2150 ui4b ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
2151 ui4b WriteBuffContig =
2152 kOneBuffLen - (TheWriteOffset & kOneBuffMask);
2153
2154 if (WriteBuffContig < n) {
2155 n = WriteBuffContig;
2156 }
2157 if (ToFillLen < n) {
2158 /* overwrite previous buffer */
2159#if dbglog_SoundStuff
2160 dbglog_writeln("sound buffer over flow");
2161#endif
2162 TheWriteOffset -= kOneBuffLen;
2163 }
2164
2165 *actL = n;
2166 return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
2167}
2168
2169#if 4 == kLn2SoundSampSz
2170LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p)
2171{
2172 int i;
2173
2174 for (i = kOneBuffLen; --i >= 0; ) {
2175 *p++ -= 0x8000;
2176 }
2177}
2178#else
2179#define ConvertSoundBlockToNative(p)
2180#endif
2181
2182LOCALPROC MySound_WroteABlock(void)
2183{
2184#if (4 == kLn2SoundSampSz)
2185 ui4b PrevWriteOffset = TheWriteOffset - kOneBuffLen;
2186 tpSoundSamp p = TheSoundBuffer + (PrevWriteOffset & kAllBuffMask);
2187#endif
2188
2189#if dbglog_SoundStuff
2190 dbglog_writeln("enter MySound_WroteABlock");
2191#endif
2192
2193 ConvertSoundBlockToNative(p);
2194
2195 TheFillOffset = TheWriteOffset;
2196
2197#if dbglog_SoundBuffStats
2198 {
2199 ui4b ToPlayLen = TheFillOffset
2200 - ThePlayOffset;
2201 ui4b ToPlayBuffs = ToPlayLen >> kLnOneBuffLen;
2202
2203 if (ToPlayBuffs > MaxFilledSoundBuffs) {
2204 MaxFilledSoundBuffs = ToPlayBuffs;
2205 }
2206 }
2207#endif
2208}
2209
2210LOCALFUNC blnr MySound_EndWrite0(ui4r actL)
2211{
2212 blnr v;
2213
2214 TheWriteOffset += actL;
2215
2216 if (0 != (TheWriteOffset & kOneBuffMask)) {
2217 v = falseblnr;
2218 } else {
2219 /* just finished a block */
2220
2221 MySound_WroteABlock();
2222
2223 v = trueblnr;
2224 }
2225
2226 return v;
2227}
2228
2229LOCALPROC MySound_SecondNotify0(void)
2230{
2231 if (MinFilledSoundBuffs <= kSoundBuffers) {
2232 if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
2233#if dbglog_SoundStuff
2234 dbglog_writeln("MinFilledSoundBuffs too high");
2235#endif
2236 NextTickChangeTime += MyTickDuration;
2237 } else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
2238#if dbglog_SoundStuff
2239 dbglog_writeln("MinFilledSoundBuffs too low");
2240#endif
2241 ++TrueEmulatedTime;
2242 }
2243#if dbglog_SoundBuffStats
2244 dbglog_writelnNum("MinFilledSoundBuffs",
2245 MinFilledSoundBuffs);
2246 dbglog_writelnNum("MaxFilledSoundBuffs",
2247 MaxFilledSoundBuffs);
2248 MaxFilledSoundBuffs = 0;
2249#endif
2250 MinFilledSoundBuffs = kSoundBuffers + 1;
2251 }
2252}
2253
2254LOCALPROC RampSound(tpSoundSamp p,
2255 trSoundSamp BeginVal, trSoundSamp EndVal)
2256{
2257 int i;
2258 ui5r v = (((ui5r)BeginVal) << kLnOneBuffLen) + (kLnOneBuffLen >> 1);
2259
2260 for (i = kOneBuffLen; --i >= 0; ) {
2261 *p++ = v >> kLnOneBuffLen;
2262 v = v + EndVal - BeginVal;
2263 }
2264}
2265
2266#if 4 == kLn2SoundSampSz
2267#define ConvertSoundSampleFromNative(v) ((v) + 0x8000)
2268#else
2269#define ConvertSoundSampleFromNative(v) (v)
2270#endif
2271
2272struct MySoundR {
2273 tpSoundSamp fTheSoundBuffer;
2274 volatile ui4b (*fPlayOffset);
2275 volatile ui4b (*fFillOffset);
2276 volatile ui4b (*fMinFilledSoundBuffs);
2277
2278 volatile blnr PlayingBuffBlock;
2279 volatile trSoundSamp lastv;
2280 volatile blnr wantplaying;
2281 volatile blnr StartingBlocks;
2282
2283 CmpSoundHeader /* ExtSoundHeader */ soundHeader;
2284};
2285typedef struct MySoundR MySoundR;
2286
2287
2288/*
2289 Some of this code descended from CarbonSndPlayDB, an
2290 example from Apple, as found being used in vMac for Mac OS.
2291*/
2292
2293LOCALPROC InsertSndDoCommand(SndChannelPtr chan, SndCommand * newCmd)
2294{
2295 if (-1 == chan->qHead) {
2296 chan->qHead = chan->qTail;
2297 }
2298
2299 if (1 <= chan->qHead) {
2300 chan->qHead--;
2301 } else {
2302 chan->qHead = chan->qTail;
2303 }
2304
2305 chan->queue[chan->qHead] = *newCmd;
2306}
2307
2308/* call back */ static pascal void
2309MySound_CallBack(SndChannelPtr theChannel, SndCommand * theCallBackCmd)
2310{
2311 MySoundR *datp =
2312 (MySoundR *)(theCallBackCmd->param2);
2313 blnr wantplaying0 = datp->wantplaying;
2314 trSoundSamp v0 = datp->lastv;
2315
2316#if dbglog_SoundStuff
2317 dbglog_writeln("Enter MySound_CallBack");
2318#endif
2319
2320 if (datp->PlayingBuffBlock) {
2321 /* finish with last sample */
2322#if dbglog_SoundStuff
2323 dbglog_writeln("done with sample");
2324#endif
2325
2326 *datp->fPlayOffset += kOneBuffLen;
2327 datp->PlayingBuffBlock = falseblnr;
2328 }
2329
2330 if ((! wantplaying0) && (kCenterSound == v0)) {
2331#if dbglog_SoundStuff
2332 dbglog_writeln("terminating");
2333#endif
2334 } else {
2335 SndCommand playCmd;
2336 tpSoundSamp p;
2337 trSoundSamp v1 = v0;
2338 blnr WantRamp = falseblnr;
2339 ui4b CurPlayOffset = *datp->fPlayOffset;
2340 ui4b ToPlayLen = *datp->fFillOffset - CurPlayOffset;
2341 ui4b FilledSoundBuffs = ToPlayLen >> kLnOneBuffLen;
2342
2343 if (FilledSoundBuffs < *datp->fMinFilledSoundBuffs) {
2344 *datp->fMinFilledSoundBuffs = FilledSoundBuffs;
2345 }
2346
2347 if (! wantplaying0) {
2348#if dbglog_SoundStuff
2349 dbglog_writeln("playing end transistion");
2350#endif
2351 v1 = kCenterSound;
2352
2353 WantRamp = trueblnr;
2354 } else
2355 if (datp->StartingBlocks) {
2356#if dbglog_SoundStuff
2357 dbglog_writeln("playing start block");
2358#endif
2359
2360 if ((ToPlayLen >> kLnOneBuffLen) < 12) {
2361 datp->StartingBlocks = falseblnr;
2362#if dbglog_SoundStuff
2363 dbglog_writeln("have enough samples to start");
2364#endif
2365
2366 p = datp->fTheSoundBuffer
2367 + (CurPlayOffset & kAllBuffMask);
2368 v1 = ConvertSoundSampleFromNative(*p);
2369 }
2370
2371 WantRamp = trueblnr;
2372 } else
2373 if (0 == FilledSoundBuffs) {
2374#if dbglog_SoundStuff
2375 dbglog_writeln("playing under run");
2376#endif
2377
2378 WantRamp = trueblnr;
2379 } else
2380 {
2381 /* play next sample */
2382 p = datp->fTheSoundBuffer
2383 + (CurPlayOffset & kAllBuffMask);
2384 datp->PlayingBuffBlock = trueblnr;
2385 v1 =
2386 ConvertSoundSampleFromNative(*(p + kOneBuffLen - 1));
2387#if dbglog_SoundStuff
2388 dbglog_writeln("playing sample");
2389#endif
2390 }
2391
2392 if (WantRamp) {
2393 p = datp->fTheSoundBuffer + kAllBuffLen;
2394
2395#if dbglog_SoundStuff
2396 dbglog_writelnNum("v0", v0);
2397 dbglog_writelnNum("v1", v1);
2398#endif
2399
2400 RampSound(p, v0, v1);
2401 ConvertSoundBlockToNative(p);
2402 }
2403
2404 datp->soundHeader.samplePtr = (Ptr)p;
2405 datp->soundHeader.numFrames =
2406 (unsigned long)kOneBuffLen;
2407
2408 /* Insert our callback command */
2409 InsertSndDoCommand (theChannel, theCallBackCmd);
2410
2411#if 0
2412 {
2413 int i;
2414 tpSoundSamp pS =
2415 (tpSoundSamp)datp->soundHeader.samplePtr;
2416
2417 for (i = datp->soundHeader.numFrames; --i >= 0; )
2418 {
2419 fprintf(stderr, "%d\n", *pS++);
2420 }
2421 }
2422#endif
2423
2424 /* Play the next buffer */
2425 playCmd.cmd = bufferCmd;
2426 playCmd.param1 = 0;
2427 playCmd.param2 = (long)&(datp->soundHeader);
2428 InsertSndDoCommand (theChannel, &playCmd);
2429
2430 datp->lastv = v1;
2431 }
2432}
2433
2434LOCALVAR MySoundR cur_audio;
2435
2436LOCALVAR SndCallBackUPP gCarbonSndPlayDoubleBufferCallBackUPP = NULL;
2437
2438LOCALVAR SndChannelPtr sndChannel = NULL; /* our sound channel */
2439
2440LOCALPROC MySound_Start(void)
2441{
2442#if dbglog_SoundStuff
2443 dbglog_writeln("MySound_Start");
2444#endif
2445
2446 if (NULL == sndChannel) {
2447 SndCommand callBack;
2448 SndChannelPtr chan = NULL;
2449
2450 cur_audio.wantplaying = falseblnr;
2451 cur_audio.StartingBlocks = falseblnr;
2452
2453 MySound_Start0();
2454
2455 SndNewChannel(&chan, sampledSynth, initMono, nil);
2456 if (NULL != chan) {
2457 sndChannel = chan;
2458
2459 cur_audio.PlayingBuffBlock = falseblnr;
2460 cur_audio.lastv = kCenterSound;
2461 cur_audio.StartingBlocks = trueblnr;
2462 cur_audio.wantplaying = trueblnr;
2463
2464 callBack.cmd = callBackCmd;
2465 callBack.param1 = 0; /* unused */
2466 callBack.param2 = (long)&cur_audio;
2467
2468 sndChannel->callBack =
2469 gCarbonSndPlayDoubleBufferCallBackUPP;
2470
2471 (void) SndDoCommand (sndChannel, &callBack, true);
2472 }
2473 }
2474}
2475
2476LOCALPROC MySound_Stop(void)
2477{
2478#if dbglog_SoundStuff
2479 dbglog_writeln("enter MySound_Stop");
2480#endif
2481
2482 if (NULL != sndChannel) {
2483 ui4r retry_limit = 50; /* half of a second */
2484 SCStatus r;
2485
2486 cur_audio.wantplaying = falseblnr;
2487#if dbglog_SoundStuff
2488 dbglog_writeln("cleared wantplaying");
2489#endif
2490
2491label_retry:
2492 r.scChannelBusy = falseblnr; /* what is this for? */
2493 if (noErr != SndChannelStatus(sndChannel,
2494 sizeof(SCStatus), &r))
2495 {
2496 /* fail */
2497 } else
2498 if ((! r.scChannelBusy) && (kCenterSound == cur_audio.lastv)) {
2499 /* done */
2500
2501 /*
2502 observed reporting not busy unexpectedly,
2503 so also check lastv.
2504 */
2505 } else
2506 if (0 == --retry_limit) {
2507#if dbglog_SoundStuff
2508 dbglog_writeln("retry limit reached");
2509#endif
2510 /*
2511 don't trust SndChannelStatus, make
2512 sure don't get in infinite loop.
2513 */
2514
2515 /* done */
2516 } else
2517 {
2518 /*
2519 give time back, particularly important
2520 if got here on a suspend event.
2521 */
2522 struct timespec rqt;
2523 struct timespec rmt;
2524
2525#if dbglog_SoundStuff
2526 dbglog_writeln("busy, so sleep");
2527#endif
2528
2529 rqt.tv_sec = 0;
2530 rqt.tv_nsec = 10000000;
2531 (void) nanosleep(&rqt, &rmt);
2532
2533 goto label_retry;
2534 }
2535
2536 SndDisposeChannel(sndChannel, true);
2537 sndChannel = NULL;
2538 }
2539
2540#if dbglog_SoundStuff
2541 dbglog_writeln("leave MySound_Stop");
2542#endif
2543}
2544
2545#define SOUND_SAMPLERATE rate22khz
2546 /* = 0x56EE8BA3 = (7833600 * 2 / 704) << 16 */
2547
2548LOCALFUNC blnr MySound_Init(void)
2549{
2550#if dbglog_SoundStuff
2551 dbglog_writeln("enter MySound_Init");
2552#endif
2553
2554 cur_audio.fTheSoundBuffer = TheSoundBuffer;
2555
2556 cur_audio.fPlayOffset = &ThePlayOffset;
2557 cur_audio.fFillOffset = &TheFillOffset;
2558 cur_audio.fMinFilledSoundBuffs = &MinFilledSoundBuffs;
2559 cur_audio.wantplaying = falseblnr;
2560
2561 /* Init basic per channel information */
2562 cur_audio.soundHeader.sampleRate = SOUND_SAMPLERATE;
2563 /* sample rate */
2564 cur_audio.soundHeader.numChannels = 1; /* one channel */
2565 cur_audio.soundHeader.loopStart = 0;
2566 cur_audio.soundHeader.loopEnd = 0;
2567 cur_audio.soundHeader.encode = cmpSH /* extSH */;
2568 cur_audio.soundHeader.baseFrequency = kMiddleC;
2569 cur_audio.soundHeader.numFrames =
2570 (unsigned long)kOneBuffLen;
2571 /* cur_audio.soundHeader.AIFFSampleRate = 0; */
2572 /* unused */
2573 cur_audio.soundHeader.markerChunk = nil;
2574 cur_audio.soundHeader.futureUse2 = 0;
2575 cur_audio.soundHeader.stateVars = nil;
2576 cur_audio.soundHeader.leftOverSamples = nil;
2577 cur_audio.soundHeader.compressionID = 0;
2578 /* no compression */
2579 cur_audio.soundHeader.packetSize = 0;
2580 /* no compression */
2581 cur_audio.soundHeader.snthID = 0;
2582 cur_audio.soundHeader.sampleSize = (1 << kLn2SoundSampSz);
2583 /* 8 or 16 bits per sample */
2584 cur_audio.soundHeader.sampleArea[0] = 0;
2585#if 3 == kLn2SoundSampSz
2586 cur_audio.soundHeader.format = kSoundNotCompressed;
2587#elif 4 == kLn2SoundSampSz
2588 cur_audio.soundHeader.format = k16BitNativeEndianFormat;
2589#else
2590#error "unsupported kLn2SoundSampSz"
2591#endif
2592 cur_audio.soundHeader.samplePtr = (Ptr)TheSoundBuffer;
2593
2594 gCarbonSndPlayDoubleBufferCallBackUPP =
2595 NewSndCallBackUPP(MySound_CallBack);
2596 if (gCarbonSndPlayDoubleBufferCallBackUPP != NULL) {
2597
2598 MySound_Start();
2599 /*
2600 This should be taken care of by LeaveSpeedStopped,
2601 but since takes a while to get going properly,
2602 start early.
2603 */
2604
2605 return trueblnr;
2606 }
2607 return falseblnr;
2608}
2609
2610GLOBALOSGLUPROC MySound_EndWrite(ui4r actL)
2611{
2612 if (MySound_EndWrite0(actL)) {
2613 }
2614}
2615
2616LOCALPROC MySound_SecondNotify(void)
2617{
2618 if (sndChannel != NULL) {
2619 MySound_SecondNotify0();
2620 }
2621}
2622
2623#endif
2624
2625
2626LOCALPROC MyAdjustGLforSize(int h, int v)
2627{
2628 if (GL_TRUE != aglSetCurrentContext(ctx)) {
2629 /* err = aglReportError() */
2630 } else {
2631
2632 glClearColor (0.0, 0.0, 0.0, 1.0);
2633
2634#if 1
2635 glViewport(0, 0, h, v);
2636 glMatrixMode(GL_PROJECTION);
2637 glLoadIdentity();
2638 glOrtho(0, h, 0, v, -1.0, 1.0);
2639 glMatrixMode(GL_MODELVIEW);
2640#endif
2641
2642 glColor3f(0.0, 0.0, 0.0);
2643#if EnableMagnify
2644 if (UseMagnify) {
2645 glPixelZoom(MyWindowScale, - MyWindowScale);
2646 } else
2647#endif
2648 {
2649 glPixelZoom(1, -1);
2650 }
2651 glPixelStorei(GL_UNPACK_ROW_LENGTH, vMacScreenWidth);
2652
2653 glClear(GL_COLOR_BUFFER_BIT);
2654
2655 if (GL_TRUE != aglSetCurrentContext(NULL)) {
2656 /* err = aglReportError() */
2657 }
2658
2659 ScreenChangedAll();
2660 }
2661}
2662
2663LOCALVAR blnr WantScreensChangedCheck = falseblnr;
2664
2665LOCALPROC MyUpdateOpenGLContext(void)
2666{
2667 if (NULL == ctx) {
2668 /* oops */
2669 } else if (GL_TRUE != aglSetCurrentContext(ctx)) {
2670 /* err = aglReportError() */
2671 } else {
2672 aglUpdateContext(ctx);
2673 }
2674}
2675
2676#if 0 /* some experiments */
2677LOCALVAR CGrafPtr GrabbedPort = NULL;
2678#endif
2679
2680#if 0
2681LOCALPROC AdjustMainScreenGrab(void)
2682{
2683 if (GrabMachine) {
2684 if (NULL == GrabbedPort) {
2685 /* CGDisplayCapture(MyMainDisplayID()); */
2686 CGCaptureAllDisplays();
2687 /* CGDisplayHideCursor( MyMainDisplayID() ); */
2688 GrabbedPort =
2689 CreateNewPortForCGDisplayID((UInt32)MyMainDisplayID());
2690 LockPortBits (GrabbedPort);
2691 }
2692 } else {
2693 if (GrabbedPort != NULL) {
2694 UnlockPortBits (GrabbedPort);
2695 /* CGDisplayShowCursor( MyMainDisplayID() ); */
2696 /* CGDisplayRelease(MyMainDisplayID()); */
2697 CGReleaseAllDisplays();
2698 GrabbedPort = NULL;
2699 }
2700 }
2701}
2702#endif
2703
2704#if 0
2705typedef CGDisplayErr (*CGReleaseAllDisplaysProcPtr)
2706 (void);
2707
2708LOCALPROC MyReleaseAllDisplays(void)
2709{
2710 if (HaveApplicationServicesBun()) {
2711 CGReleaseAllDisplaysProcPtr ReleaseAllDisplaysProc =
2712 (CGReleaseAllDisplaysProcPtr)
2713 CFBundleGetFunctionPointerForName(
2714 AppServBunRef, CFSTR("CGReleaseAllDisplays"));
2715 if (ReleaseAllDisplaysProc != NULL) {
2716 ReleaseAllDisplaysProc();
2717 }
2718 }
2719}
2720
2721typedef CGDisplayErr (*CGCaptureAllDisplaysProcPtr)
2722 (void);
2723
2724LOCALPROC MyCaptureAllDisplays(void)
2725{
2726 if (HaveApplicationServicesBun()) {
2727 CGCaptureAllDisplaysProcPtr CaptureAllDisplaysProc =
2728 (CGCaptureAllDisplaysProcPtr)
2729 CFBundleGetFunctionPointerForName(
2730 AppServBunRef, CFSTR("CGCaptureAllDisplays"));
2731 if (CaptureAllDisplaysProc != NULL) {
2732 CaptureAllDisplaysProc();
2733 }
2734 }
2735}
2736#endif
2737
2738LOCALVAR AGLPixelFormat window_fmt = NULL;
2739LOCALVAR AGLContext window_ctx = NULL;
2740
2741#ifndef UseAGLfullscreen
2742#define UseAGLfullscreen 0
2743#endif
2744
2745#if UseAGLfullscreen
2746LOCALVAR AGLPixelFormat fullscreen_fmt = NULL;
2747LOCALVAR AGLContext fullscreen_ctx = NULL;
2748#endif
2749
2750#if UseAGLfullscreen
2751LOCALPROC MaybeFullScreen(void)
2752{
2753 if (
2754#if VarFullScreen
2755 UseFullScreen &&
2756#endif
2757 (NULL == fullscreen_ctx)
2758 && HaveMyCGDisplayPixelsWide()
2759 && HaveMyCGDisplayPixelsHigh())
2760 {
2761 static const GLint fullscreen_attrib[] = {AGL_RGBA,
2762 AGL_NO_RECOVERY,
2763 AGL_FULLSCREEN,
2764 AGL_SINGLE_RENDERER, AGL_ACCELERATED,
2765#if UseAGLdoublebuff
2766 AGL_DOUBLEBUFFER,
2767#endif
2768 AGL_NONE};
2769 GDHandle theDevice;
2770 CGDirectDisplayID CurMainDisplayID = MyMainDisplayID();
2771
2772 DMGetGDeviceByDisplayID(
2773 (DisplayIDType)CurMainDisplayID, &theDevice, false);
2774 fullscreen_fmt = aglChoosePixelFormat(
2775 &theDevice, 1, fullscreen_attrib);
2776 if (NULL == fullscreen_fmt) {
2777 /* err = aglReportError() */
2778 } else {
2779 fullscreen_ctx = aglCreateContext(fullscreen_fmt, NULL);
2780 if (NULL == fullscreen_ctx) {
2781 /* err = aglReportError() */
2782 } else {
2783 /* MyCaptureAllDisplays(); */
2784 if (GL_TRUE != aglSetFullScreen(fullscreen_ctx,
2785 0, 0, 0, 0))
2786 {
2787 /* err = aglReportError() */
2788 } else {
2789 Rect r;
2790
2791 int h = MyCGDisplayPixelsWide(CurMainDisplayID);
2792 int v = MyCGDisplayPixelsHigh(CurMainDisplayID);
2793
2794 GetWindowBounds(gMyMainWindow, kWindowContentRgn,
2795 &r);
2796
2797 GLhOffset = r.left + hOffset;
2798 GLvOffset = v - (r.top + vOffset);
2799
2800 ctx = fullscreen_ctx;
2801 MyAdjustGLforSize(h, v);
2802 return;
2803 }
2804 /* MyReleaseAllDisplays(); */
2805
2806 if (GL_TRUE != aglDestroyContext(fullscreen_ctx)) {
2807 /* err = aglReportError() */
2808 }
2809 fullscreen_ctx = NULL;
2810 }
2811
2812 aglDestroyPixelFormat (fullscreen_fmt);
2813 fullscreen_fmt = NULL;
2814 }
2815 }
2816}
2817#endif
2818
2819#if UseAGLfullscreen
2820LOCALPROC NoFullScreen(void)
2821{
2822 if (fullscreen_ctx != NULL) {
2823 Rect r;
2824 int h;
2825 int v;
2826
2827 GetWindowBounds(gMyMainWindow, kWindowContentRgn, &r);
2828
2829 h = r.right - r.left;
2830 v = r.bottom - r.top;
2831
2832 GLhOffset = hOffset;
2833 GLvOffset = v - vOffset;
2834
2835 ctx = window_ctx;
2836
2837 MyAdjustGLforSize(h, v);
2838
2839 Update_Screen();
2840
2841 if (fullscreen_ctx != NULL) {
2842 if (GL_TRUE != aglDestroyContext(fullscreen_ctx)) {
2843 /* err = aglReportError() */
2844 }
2845 fullscreen_ctx = NULL;
2846 }
2847 if (fullscreen_fmt != NULL) {
2848 aglDestroyPixelFormat(fullscreen_fmt);
2849 fullscreen_fmt = NULL;
2850 }
2851 }
2852}
2853#endif
2854
2855#if UseAGLfullscreen
2856LOCALPROC AdjustOpenGLGrab(void)
2857{
2858 if (GrabMachine) {
2859 MaybeFullScreen();
2860 } else {
2861 NoFullScreen();
2862 }
2863}
2864#endif
2865
2866#if MayFullScreen
2867LOCALPROC AdjustMachineGrab(void)
2868{
2869#if EnableFSMouseMotion
2870 AdjustMouseMotionGrab();
2871#endif
2872#if UseAGLfullscreen
2873 AdjustOpenGLGrab();
2874#endif
2875#if 0
2876 AdjustMainScreenGrab();
2877#endif
2878}
2879#endif
2880
2881#if MayFullScreen
2882LOCALPROC UngrabMachine(void)
2883{
2884 GrabMachine = falseblnr;
2885 AdjustMachineGrab();
2886}
2887#endif
2888
2889LOCALPROC ClearWeAreActive(void)
2890{
2891 if (gWeAreActive) {
2892 gWeAreActive = falseblnr;
2893
2894 DisconnectKeyCodes2();
2895
2896 SavedModifiers &= alphaLock;
2897
2898 MyMouseButtonSet(falseblnr);
2899
2900#if MayFullScreen
2901 UngrabMachine();
2902#endif
2903
2904 ForceShowCursor();
2905 }
2906}
2907
2908/* --- basic dialogs --- */
2909
2910LOCALFUNC CFStringRef CFStringCreateFromSubstCStr(char *s)
2911{
2912 int L;
2913 UniChar x[ClStrMaxLength];
2914
2915 UniCharStrFromSubstCStr(&L, x, s);
2916
2917 return CFStringCreateWithCharacters(kCFAllocatorDefault, x, L);
2918}
2919
2920#define kMyStandardAlert 128
2921
2922LOCALPROC CheckSavedMacMsg(void)
2923{
2924 if (nullpr != SavedBriefMsg) {
2925 if (HaveMyCreateStandardAlert() && HaveMyRunStandardAlert()) {
2926 CFStringRef briefMsgu = CFStringCreateFromSubstCStr(
2927 SavedBriefMsg);
2928 if (NULL != briefMsgu) {
2929 CFStringRef longMsgu = CFStringCreateFromSubstCStr(
2930 SavedLongMsg);
2931 if (NULL != longMsgu) {
2932 DialogRef TheAlert;
2933 OSStatus err = MyCreateStandardAlert(
2934 (SavedFatalMsg) ? kAlertStopAlert
2935 : kAlertCautionAlert,
2936 briefMsgu, longMsgu, NULL,
2937 &TheAlert);
2938 if (noErr == err) {
2939 (void) MyRunStandardAlert(TheAlert, NULL, NULL);
2940 }
2941 CFRelease(longMsgu);
2942 }
2943 CFRelease(briefMsgu);
2944 }
2945 }
2946
2947 SavedBriefMsg = nullpr;
2948 }
2949}
2950
2951LOCALVAR blnr gTrueBackgroundFlag = falseblnr;
2952
2953LOCALPROC MyBeginDialog(void)
2954{
2955 ClearWeAreActive();
2956}
2957
2958LOCALPROC MyEndDialog(void)
2959{
2960}
2961
2962/* --- hide/show menubar --- */
2963
2964#if MayFullScreen
2965LOCALPROC My_HideMenuBar(void)
2966{
2967 if (HaveMySetSystemUIMode()) {
2968 (void) MySetSystemUIMode(MykUIModeAllHidden,
2969 MykUIOptionDisableAppleMenu
2970#if GrabKeysFullScreen
2971 | MykUIOptionDisableProcessSwitch
2972#if GrabKeysMaxFullScreen /* dangerous !! */
2973 | MykUIOptionDisableForceQuit
2974 | MykUIOptionDisableSessionTerminate
2975#endif
2976#endif
2977 );
2978 } else {
2979 if (IsMenuBarVisible()) {
2980 HideMenuBar();
2981 }
2982 }
2983}
2984#endif
2985
2986#if MayFullScreen
2987LOCALPROC My_ShowMenuBar(void)
2988{
2989 if (HaveMySetSystemUIMode()) {
2990 (void) MySetSystemUIMode(MykUIModeNormal,
2991 0);
2992 } else {
2993 if (! IsMenuBarVisible()) {
2994 ShowMenuBar();
2995 }
2996 }
2997}
2998#endif
2999
3000/* --- drives, part 2 --- */
3001
3002LOCALPROC InitDrives(void)
3003{
3004 /*
3005 This isn't really needed, Drives[i]
3006 need not have valid value when not vSonyIsInserted[i].
3007 */
3008 tDrive i;
3009
3010 for (i = 0; i < NumDrives; ++i) {
3011 Drives[i] = NotAfileRef;
3012 }
3013}
3014
3015LOCALPROC UnInitDrives(void)
3016{
3017 tDrive i;
3018
3019 for (i = 0; i < NumDrives; ++i) {
3020 if (vSonyIsInserted(i)) {
3021 (void) vSonyEject(i);
3022 }
3023 }
3024}
3025
3026LOCALFUNC tMacErr Sony_Insert0(SInt16 refnum, blnr locked)
3027{
3028 tDrive Drive_No;
3029
3030 if (! FirstFreeDisk(&Drive_No)) {
3031 (void) FSCloseFork(refnum);
3032 return mnvm_tmfoErr;
3033 } else {
3034 Drives[Drive_No] = refnum;
3035 DiskInsertNotify(Drive_No, locked);
3036 return mnvm_noErr;
3037 }
3038}
3039
3040LOCALPROC ReportStandardOpenDiskError(tMacErr err)
3041{
3042 if (mnvm_noErr != err) {
3043 if (mnvm_tmfoErr == err) {
3044 MacMsg(kStrTooManyImagesTitle,
3045 kStrTooManyImagesMessage, falseblnr);
3046 } else if (mnvm_opWrErr == err) {
3047 MacMsg(kStrImageInUseTitle,
3048 kStrImageInUseMessage, falseblnr);
3049 } else {
3050 MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
3051 }
3052 }
3053}
3054
3055LOCALFUNC tMacErr InsertADiskFromFSRef(FSRef *theRef)
3056{
3057 tMacErr err;
3058 HFSUniStr255 forkName;
3059 SInt16 refnum;
3060 blnr locked = falseblnr;
3061
3062 if (CheckSaveMacErr(FSGetDataForkName(&forkName))) {
3063 err = To_tMacErr(FSOpenFork(theRef, forkName.length,
3064 forkName.unicode, fsRdWrPerm, &refnum));
3065 switch (err) {
3066 case mnvm_permErr:
3067 case mnvm_wrPermErr:
3068 case mnvm_afpAccessDenied:
3069 locked = trueblnr;
3070 err = To_tMacErr(FSOpenFork(theRef, forkName.length,
3071 forkName.unicode, fsRdPerm, &refnum));
3072 break;
3073 default:
3074 break;
3075 }
3076 if (mnvm_noErr == err) {
3077 err = Sony_Insert0(refnum, locked);
3078 }
3079 }
3080
3081 return err;
3082}
3083
3084LOCALFUNC tMacErr LoadMacRomFromRefNum(SInt16 refnum)
3085{
3086 tMacErr err;
3087 ByteCount actualCount;
3088
3089 if (mnvm_noErr != (err = To_tMacErr(
3090 FSReadFork(refnum, fsFromStart, 0,
3091 kROM_Size, ROM, &actualCount))))
3092 {
3093 if (mnvm_eofErr == err) {
3094 MacMsgOverride(kStrShortROMTitle, kStrShortROMMessage);
3095 } else {
3096 MacMsgOverride(kStrNoReadROMTitle, kStrNoReadROMMessage);
3097 }
3098 } else
3099 {
3100 err = ROM_IsValid();
3101 }
3102
3103 return err;
3104}
3105
3106LOCALFUNC tMacErr LoadMacRomFromFSRef(FSRef *theRef)
3107{
3108 tMacErr err;
3109 HFSUniStr255 forkName;
3110 SInt16 refnum;
3111
3112 if (mnvm_noErr == (err =
3113 To_tMacErr(FSGetDataForkName(&forkName))))
3114 if (mnvm_noErr == (err = To_tMacErr(
3115 FSOpenFork(theRef, forkName.length,
3116 forkName.unicode, fsRdPerm, &refnum))))
3117 {
3118 err = LoadMacRomFromRefNum(refnum);
3119
3120 (void) FSCloseFork(refnum);
3121 }
3122
3123 return err;
3124}
3125
3126LOCALFUNC tMacErr InsertADiskFromFSRef1(FSRef *theRef)
3127{
3128 tMacErr err;
3129
3130 if (! ROM_loaded) {
3131 err = LoadMacRomFromFSRef(theRef);
3132 } else {
3133 err = InsertADiskFromFSRef(theRef);
3134 }
3135
3136 return err;
3137}
3138
3139LOCALFUNC tMacErr InsertDisksFromDocList(AEDescList *docList)
3140{
3141 tMacErr err = mnvm_noErr;
3142 long itemsInList;
3143 long index;
3144 AEKeyword keyword;
3145 DescType typeCode;
3146 FSRef theRef;
3147 Size actualSize;
3148
3149 if (CheckSaveMacErr(AECountItems(docList, &itemsInList))) {
3150 for (index = 1; index <= itemsInList; ++index) {
3151 if (CheckSaveMacErr(AEGetNthPtr(docList, index, typeFSRef,
3152 &keyword, &typeCode, (Ptr)&theRef,
3153 sizeof(FSRef), &actualSize)))
3154 if (CheckSavetMacErr(InsertADiskFromFSRef1(&theRef)))
3155 {
3156 }
3157 if (mnvm_noErr != err) {
3158 goto label_fail;
3159 }
3160 }
3161 }
3162
3163label_fail:
3164 return err;
3165}
3166
3167LOCALFUNC tMacErr InsertADiskFromNameEtc(FSRef *ParentRef,
3168 char *fileName)
3169{
3170 tMacErr err;
3171 blnr isFolder;
3172 FSRef ChildRef;
3173
3174 if (CheckSavetMacErr(MyMakeFSRefC(ParentRef, fileName,
3175 &isFolder, &ChildRef)))
3176 {
3177 if (isFolder) {
3178 err = mnvm_miscErr;
3179 } else {
3180 if (CheckSavetMacErr(InsertADiskFromFSRef(&ChildRef))) {
3181 /* ok */
3182 }
3183 }
3184 }
3185
3186 return err;
3187}
3188
3189#if IncludeSonyNew
3190LOCALFUNC tMacErr WriteZero(SInt16 refnum, ui5b L)
3191{
3192#define ZeroBufferSize 2048
3193 tMacErr err = mnvm_noErr;
3194 ui5b i;
3195 ui3b buffer[ZeroBufferSize];
3196 ByteCount actualCount;
3197 ui5b offset = 0;
3198
3199 memset(&buffer, 0, ZeroBufferSize);
3200
3201 while (L > 0) {
3202 i = (L > ZeroBufferSize) ? ZeroBufferSize : L;
3203 if (! CheckSaveMacErr(FSWriteFork(refnum,
3204 fsFromStart,
3205 offset,
3206 i,
3207 buffer,
3208 &actualCount)))
3209 {
3210 goto label_fail;
3211 }
3212 L -= i;
3213 offset += i;
3214 }
3215
3216label_fail:
3217 return err;
3218}
3219#endif
3220
3221#if IncludeSonyNew
3222LOCALFUNC tMacErr MyCreateFileCFStringRef(FSRef *saveFileParent,
3223 CFStringRef saveFileName, FSRef *NewRef)
3224{
3225 tMacErr err;
3226 UniChar buffer[255];
3227
3228 CFIndex len = CFStringGetLength(saveFileName);
3229
3230 if (len > 255) {
3231 len = 255;
3232 }
3233
3234 CFStringGetCharacters(saveFileName, CFRangeMake(0, len), buffer);
3235
3236 err = To_tMacErr(FSMakeFSRefUnicode(saveFileParent, len,
3237 buffer, kTextEncodingUnknown, NewRef));
3238 if (mnvm_fnfErr == err) { /* file is not there yet - create it */
3239 err = To_tMacErr(FSCreateFileUnicode(saveFileParent,
3240 len, buffer, 0, NULL, NewRef, NULL));
3241 }
3242
3243 return err;
3244}
3245#endif
3246
3247#if IncludeSonyNew
3248LOCALFUNC tMacErr MakeNewDisk0(FSRef *saveFileParent,
3249 CFStringRef saveFileName, ui5b L)
3250{
3251 tMacErr err;
3252 FSRef NewRef;
3253 HFSUniStr255 forkName;
3254 SInt16 refnum;
3255
3256 if (CheckSavetMacErr(
3257 MyCreateFileCFStringRef(saveFileParent, saveFileName, &NewRef)))
3258 {
3259 if (CheckSaveMacErr(FSGetDataForkName(&forkName)))
3260 if (CheckSaveMacErr(FSOpenFork(&NewRef, forkName.length,
3261 forkName.unicode, fsRdWrPerm, &refnum)))
3262 {
3263 SInt64 forkSize = L;
3264 if (CheckSaveMacErr(
3265 FSSetForkSize(refnum, fsFromStart, forkSize)))
3266 /*
3267 zero out fork. It looks like this is already done,
3268 but documentation says this isn't guaranteed.
3269 */
3270 if (CheckSavetMacErr(WriteZero(refnum, L)))
3271 {
3272 err = Sony_Insert0(refnum, falseblnr);
3273 refnum = NotAfileRef;
3274 }
3275 if (NotAfileRef != refnum) {
3276 (void) FSCloseFork(refnum);
3277 }
3278 }
3279 if (mnvm_noErr != err) {
3280 (void) FSDeleteObject(&NewRef);
3281 }
3282 }
3283
3284 return err;
3285}
3286#endif
3287
3288#if IncludeSonyNameNew
3289LOCALFUNC CFStringRef CFStringCreateWithPbuf(tPbuf i)
3290{
3291 return CFStringCreateWithBytes(NULL,
3292 (UInt8 *)PbufDat[i], PbufSize[i],
3293 kCFStringEncodingMacRoman, false);
3294}
3295#endif
3296
3297pascal Boolean NavigationFilterProc(
3298 AEDesc* theItem, void* info, void* NavCallBackUserData,
3299 NavFilterModes theNavFilterModes);
3300pascal Boolean NavigationFilterProc(
3301 AEDesc* theItem, void* info, void* NavCallBackUserData,
3302 NavFilterModes theNavFilterModes)
3303{
3304 /* NavFileOrFolderInfo* theInfo = (NavFileOrFolderInfo*)info; */
3305 UnusedParam(theItem);
3306 UnusedParam(info);
3307 UnusedParam(theNavFilterModes);
3308 UnusedParam(NavCallBackUserData);
3309
3310 return true; /* display all items */
3311}
3312
3313
3314pascal void NavigationEventProc(
3315 NavEventCallbackMessage callBackSelector,
3316 NavCBRecPtr callBackParms, void *NavCallBackUserData);
3317pascal void NavigationEventProc(
3318 NavEventCallbackMessage callBackSelector,
3319 NavCBRecPtr callBackParms, void *NavCallBackUserData)
3320{
3321 UnusedParam(NavCallBackUserData);
3322
3323 switch (callBackSelector) {
3324 case kNavCBEvent: /* probably not needed in os x */
3325 switch (callBackParms->eventData.eventDataParms.event->what)
3326 {
3327 case updateEvt:
3328 {
3329 WindowPtr which =
3330 (WindowPtr)callBackParms
3331 ->eventData.eventDataParms.event
3332 ->message;
3333
3334 BeginUpdate(which);
3335
3336 if (which == gMyMainWindow) {
3337 Update_Screen();
3338 }
3339
3340 EndUpdate(which);
3341 }
3342 break;
3343 }
3344 break;
3345#if 0
3346 case kNavCBUserAction:
3347 {
3348 NavUserAction userAction = NavDialogGetUserAction(
3349 callBackParms->context);
3350 switch (userAction) {
3351 case kNavUserActionOpen: {
3352 /* got something to open */
3353 break;
3354 }
3355 }
3356 }
3357 break;
3358 case kNavCBTerminate:
3359 break;
3360#endif
3361 }
3362}
3363
3364LOCALPROC InsertADisk0(void)
3365{
3366 NavDialogRef theOpenDialog;
3367 NavDialogCreationOptions dialogOptions;
3368 NavReplyRecord theReply;
3369 NavTypeListHandle openList = NULL;
3370 NavEventUPP gEventProc = NewNavEventUPP(NavigationEventProc);
3371 NavObjectFilterUPP filterUPP =
3372 NewNavObjectFilterUPP(NavigationFilterProc);
3373
3374 if (noErr == NavGetDefaultDialogCreationOptions(&dialogOptions)) {
3375 dialogOptions.modality = kWindowModalityAppModal;
3376 dialogOptions.optionFlags |= kNavDontAutoTranslate;
3377 dialogOptions.optionFlags &= ~ kNavAllowPreviews;
3378 if (noErr == NavCreateGetFileDialog(&dialogOptions,
3379 (NavTypeListHandle)openList,
3380 gEventProc, NULL,
3381 filterUPP, NULL, &theOpenDialog))
3382 {
3383 MyBeginDialog();
3384 (void) NavDialogRun(theOpenDialog);
3385 MyEndDialog();
3386 if (noErr == NavDialogGetReply(theOpenDialog,
3387 &theReply))
3388 {
3389 if (theReply.validRecord) {
3390 ReportStandardOpenDiskError(
3391 InsertDisksFromDocList(&theReply.selection));
3392 }
3393 (void) NavDisposeReply(&theReply);
3394 }
3395 NavDialogDispose(theOpenDialog);
3396 }
3397 }
3398
3399 DisposeNavEventUPP(gEventProc);
3400 DisposeNavObjectFilterUPP(filterUPP);
3401}
3402
3403#if IncludeSonyNew
3404LOCALPROC MakeNewDisk(ui5b L, CFStringRef NewDiskName)
3405{
3406#if SaveDialogEnable
3407 NavDialogRef theSaveDialog;
3408 NavDialogCreationOptions dialogOptions;
3409 NavReplyRecord theReply;
3410 NavEventUPP gEventProc = NewNavEventUPP(NavigationEventProc);
3411
3412 if (noErr == NavGetDefaultDialogCreationOptions(&dialogOptions)) {
3413 dialogOptions.modality = kWindowModalityAppModal;
3414 dialogOptions.saveFileName = NewDiskName;
3415 if (noErr == NavCreatePutFileDialog(&dialogOptions,
3416 'TEXT', 'MPS ',
3417 gEventProc, NULL,
3418 &theSaveDialog))
3419 {
3420 MyBeginDialog();
3421 (void) NavDialogRun(theSaveDialog);
3422 MyEndDialog();
3423 if (noErr == NavDialogGetReply(theSaveDialog,
3424 &theReply))
3425 {
3426 if (theReply.validRecord) {
3427 long itemsInList;
3428 AEKeyword keyword;
3429 DescType typeCode;
3430 FSRef theRef;
3431 Size actualSize;
3432
3433 if (noErr == AECountItems(
3434 &theReply.selection, &itemsInList))
3435 {
3436 if (itemsInList == 1) {
3437 if (noErr == AEGetNthPtr(
3438 &theReply.selection, 1, typeFSRef,
3439 &keyword, &typeCode, (Ptr)&theRef,
3440 sizeof(FSRef), &actualSize))
3441 {
3442 ReportStandardOpenDiskError(
3443 MakeNewDisk0(&theRef,
3444 theReply.saveFileName, L));
3445 }
3446 }
3447 }
3448 }
3449 (void) NavDisposeReply(&theReply);
3450 }
3451 NavDialogDispose(theSaveDialog);
3452 }
3453 }
3454
3455 DisposeNavEventUPP(gEventProc);
3456#else /* SaveDialogEnable */
3457 FSRef OutRef;
3458
3459 if (mnvm_noErr == FindOrMakeNamedChildRef(&MyDatDirRef,
3460 "out", &OutRef))
3461 {
3462 MakeNewDisk0(&OutRef, NewDiskName, L);
3463 }
3464#endif /* SaveDialogEnable */
3465}
3466#endif
3467
3468LOCALFUNC tMacErr LoadMacRomFromNameFolder(FSRef *ParentRef,
3469 char *fileName)
3470{
3471 tMacErr err;
3472 blnr isFolder;
3473 FSRef ChildRef;
3474
3475 if (mnvm_noErr == (err =
3476 MyMakeFSRefC(ParentRef, fileName, &isFolder, &ChildRef)))
3477 if (mnvm_noErr == (err =
3478 LoadMacRomFromFSRef(&ChildRef)))
3479 {
3480 }
3481
3482 return err;
3483}
3484
3485LOCALFUNC tMacErr LoadMacRomFromPrefDir(void)
3486{
3487 tMacErr err;
3488 FSRef PrefRef;
3489 FSRef GryphelRef;
3490 FSRef ROMsRef;
3491
3492 if (mnvm_noErr == (err = To_tMacErr(FSFindFolder(kUserDomain,
3493 kPreferencesFolderType, kDontCreateFolder, &PrefRef))))
3494 if (mnvm_noErr == (err = FindNamedChildRef(&PrefRef,
3495 "Gryphel", &GryphelRef)))
3496 if (mnvm_noErr == (err = FindNamedChildRef(&GryphelRef,
3497 "mnvm_rom", &ROMsRef)))
3498 if (mnvm_noErr == (err = LoadMacRomFromNameFolder(&ROMsRef,
3499 RomFileName)))
3500 {
3501 /* ok */
3502 }
3503
3504 return err;
3505}
3506
3507LOCALFUNC blnr LoadMacRom(void)
3508{
3509 tMacErr err;
3510
3511 if (mnvm_fnfErr == (err =
3512 LoadMacRomFromNameFolder(&MyDatDirRef, RomFileName)))
3513 if (mnvm_fnfErr == (err =
3514 LoadMacRomFromPrefDir()))
3515 {
3516 }
3517
3518 return trueblnr; /* keep launching Mini vMac, regardless */
3519}
3520
3521LOCALFUNC blnr Sony_InsertIth(int i)
3522{
3523 tMacErr err = mnvm_noErr;
3524
3525 if ((i > 9) || ! FirstFreeDisk(nullpr)) {
3526 return falseblnr;
3527 } else {
3528 char s[16] = "disk?.dsk";
3529
3530 s[4] = '0' + i;
3531
3532 if (! CheckSavetMacErr(InsertADiskFromNameEtc(&MyDatDirRef, s)))
3533 {
3534 if (mnvm_fnfErr != err) {
3535 ReportStandardOpenDiskError(err);
3536 }
3537 /* stop on first error (including file not found) */
3538 return falseblnr;
3539 }
3540 }
3541
3542 return trueblnr;
3543}
3544
3545LOCALFUNC blnr LoadInitialImages(void)
3546{
3547 int i;
3548
3549 for (i = 1; Sony_InsertIth(i); ++i) {
3550 /* stop on first error (including file not found) */
3551 }
3552
3553 return trueblnr;
3554}
3555
3556#if UseActvFile
3557
3558#define ActvCodeFileName "act_1"
3559
3560LOCALFUNC tMacErr OpenActvCodeFile(SInt16 *refnum)
3561{
3562 tMacErr err;
3563 FSRef PrefRef;
3564 FSRef GryphelRef;
3565 FSRef ActRef;
3566
3567 if (CheckSaveMacErr(FSFindFolder(kUserDomain,
3568 kPreferencesFolderType, kDontCreateFolder, &PrefRef)))
3569 if (CheckSavetMacErr(FindNamedChildRef(&PrefRef,
3570 "Gryphel", &GryphelRef)))
3571 if (CheckSavetMacErr(FindNamedChildRef(&GryphelRef,
3572 "mnvm_act", &ActRef)))
3573 if (CheckSavetMacErr(OpenNamedFileInFolderRef(&ActRef,
3574 ActvCodeFileName, refnum)))
3575 {
3576 /* ok */
3577 }
3578
3579 return err;
3580}
3581
3582LOCALFUNC tMacErr ActvCodeFileLoad(ui3p p)
3583{
3584 tMacErr err;
3585 SInt16 refnum;
3586
3587 if (CheckSavetMacErr(OpenActvCodeFile(&refnum))) {
3588 ByteCount actualCount;
3589 err = To_tMacErr(FSReadFork(refnum, fsFromStart, 0,
3590 ActvCodeFileLen, p, &actualCount));
3591 (void) FSCloseFork(refnum);
3592 }
3593
3594 return err;
3595}
3596
3597LOCALFUNC tMacErr ActvCodeFileSave(ui3p p)
3598{
3599 tMacErr err;
3600 SInt16 refnum;
3601 FSRef PrefRef;
3602 FSRef GryphelRef;
3603 FSRef ActRef;
3604 ByteCount count = ActvCodeFileLen;
3605
3606 if (CheckSaveMacErr(FSFindFolder(kUserDomain,
3607 kPreferencesFolderType, kDontCreateFolder, &PrefRef)))
3608 if (CheckSavetMacErr(FindOrMakeNamedChildRef(&PrefRef,
3609 "Gryphel", &GryphelRef)))
3610 if (CheckSavetMacErr(FindOrMakeNamedChildRef(&GryphelRef,
3611 "mnvm_act", &ActRef)))
3612 if (CheckSavetMacErr(OpenWriteNamedFileInFolderRef(&ActRef,
3613 ActvCodeFileName, &refnum)))
3614 {
3615 ByteCount actualCount;
3616 err = To_tMacErr(FSWriteFork(refnum, fsFromStart, 0,
3617 count, p, &actualCount));
3618 (void) FSCloseFork(refnum);
3619 }
3620
3621 return err;
3622}
3623
3624#endif /* UseActvFile */
3625
3626/* --- utilities for adapting to the environment --- */
3627
3628LOCALPROC MyGetScreenBitsBounds(Rect *r)
3629{
3630 if (HaveMyCGDisplayBounds()) {
3631 CGRect cgr = MyCGDisplayBounds(MyMainDisplayID());
3632
3633 r->left = cgr.origin.x;
3634 r->top = cgr.origin.y;
3635 r->right = cgr.origin.x + cgr.size.width;
3636 r->bottom = cgr.origin.y + cgr.size.height;
3637 }
3638}
3639
3640#if MayNotFullScreen
3641LOCALPROC InvalWholeWindow(WindowRef mw)
3642{
3643 Rect bounds;
3644
3645 GetWindowPortBounds(mw, &bounds);
3646 InvalWindowRect(mw, &bounds);
3647}
3648#endif
3649
3650#if MayNotFullScreen
3651LOCALPROC MySetMacWindContRect(WindowRef mw, Rect *r)
3652{
3653 (void) SetWindowBounds (mw, kWindowContentRgn, r);
3654 InvalWholeWindow(mw);
3655}
3656#endif
3657
3658#if MayNotFullScreen
3659LOCALFUNC blnr MyGetWindowTitleBounds(WindowRef mw, Rect *r)
3660{
3661 return (noErr == GetWindowBounds(mw, kWindowTitleBarRgn, r));
3662}
3663#endif
3664
3665#if EnableRecreateW && MayNotFullScreen
3666LOCALFUNC blnr MyGetWindowContBounds(WindowRef mw, Rect *r)
3667{
3668 return (noErr == GetWindowBounds(mw, kWindowContentRgn, r));
3669}
3670#endif
3671
3672LOCALPROC MyGetGrayRgnBounds(Rect *r)
3673{
3674 GetRegionBounds(GetGrayRgn(), (Rect *)r);
3675}
3676
3677#define openOnly 1
3678#define openPrint 2
3679
3680LOCALFUNC blnr GotRequiredParams(AppleEvent *theAppleEvent)
3681{
3682 DescType typeCode;
3683 Size actualSize;
3684 OSErr theErr;
3685
3686 theErr = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr,
3687 typeWildCard, &typeCode, NULL, 0, &actualSize);
3688 if (errAEDescNotFound == theErr) { /* No more required params. */
3689 return trueblnr;
3690 } else if (noErr == theErr) { /* More required params! */
3691 return /* CheckSysCode(errAEEventNotHandled) */ falseblnr;
3692 } else { /* Unexpected Error! */
3693 return /* CheckSysCode(theErr) */ falseblnr;
3694 }
3695}
3696
3697LOCALFUNC blnr GotRequiredParams0(AppleEvent *theAppleEvent)
3698{
3699 DescType typeCode;
3700 Size actualSize;
3701 OSErr theErr;
3702
3703 theErr = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr,
3704 typeWildCard, &typeCode, NULL, 0, &actualSize);
3705 if (errAEDescNotFound == theErr) { /* No more required params. */
3706 return trueblnr;
3707 } else if (noErr == theErr) { /* More required params! */
3708 return trueblnr; /* errAEEventNotHandled; */ /*^*/
3709 } else { /* Unexpected Error! */
3710 return /* CheckSysCode(theErr) */ falseblnr;
3711 }
3712}
3713
3714/* call back */ static pascal OSErr OpenOrPrintFiles(
3715 AppleEvent *theAppleEvent, AppleEvent *reply, long aRefCon)
3716{
3717 /*
3718 Adapted from IM VI: AppleEvent Manager:
3719 Handling Required AppleEvents
3720 */
3721 AEDescList docList;
3722
3723 UnusedParam(reply);
3724 UnusedParam(aRefCon);
3725 /* put the direct parameter (a list of descriptors) into docList */
3726 if (noErr == (AEGetParamDesc(theAppleEvent, keyDirectObject,
3727 typeAEList, &docList)))
3728 {
3729 if (GotRequiredParams0(theAppleEvent)) {
3730 /* Check for missing required parameters */
3731 /* printIt = (openPrint == aRefCon) */
3732 ReportStandardOpenDiskError(
3733 InsertDisksFromDocList(&docList));
3734 }
3735 /* vCheckSysCode */ (void) (AEDisposeDesc(&docList));
3736 }
3737
3738 return /* GetASysResultCode() */ 0;
3739}
3740
3741/* call back */ static pascal OSErr DoOpenEvent(
3742 AppleEvent *theAppleEvent, AppleEvent *reply, long aRefCon)
3743/*
3744 This is the alternative to getting an
3745 open document event on startup.
3746*/
3747{
3748 UnusedParam(reply);
3749 UnusedParam(aRefCon);
3750 if (GotRequiredParams0(theAppleEvent)) {
3751 }
3752 return /* GetASysResultCode() */ 0;
3753 /* Make sure there are no additional "required" parameters. */
3754}
3755
3756
3757/* call back */ static pascal OSErr DoQuitEvent(
3758 AppleEvent *theAppleEvent, AppleEvent *reply, long aRefCon)
3759{
3760 UnusedParam(reply);
3761 UnusedParam(aRefCon);
3762 if (GotRequiredParams(theAppleEvent)) {
3763 RequestMacOff = trueblnr;
3764 }
3765
3766 return /* GetASysResultCode() */ 0;
3767}
3768
3769LOCALFUNC blnr MyInstallEventHandler(AEEventClass theAEEventClass,
3770 AEEventID theAEEventID, ProcPtr p,
3771 long handlerRefcon, blnr isSysHandler)
3772{
3773 return noErr == (AEInstallEventHandler(theAEEventClass,
3774 theAEEventID, NewAEEventHandlerUPP((AEEventHandlerProcPtr)p),
3775 handlerRefcon, isSysHandler));
3776}
3777
3778LOCALPROC InstallAppleEventHandlers(void)
3779{
3780 if (noErr == AESetInteractionAllowed(kAEInteractWithLocal))
3781 if (MyInstallEventHandler(kCoreEventClass, kAEOpenApplication,
3782 (ProcPtr)DoOpenEvent, 0, falseblnr))
3783 if (MyInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
3784 (ProcPtr)OpenOrPrintFiles, openOnly, falseblnr))
3785 if (MyInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
3786 (ProcPtr)OpenOrPrintFiles, openPrint, falseblnr))
3787 if (MyInstallEventHandler(kCoreEventClass, kAEQuitApplication,
3788 (ProcPtr)DoQuitEvent, 0, falseblnr))
3789 {
3790 }
3791}
3792
3793static pascal OSErr GlobalTrackingHandler(DragTrackingMessage message,
3794 WindowRef theWindow, void *handlerRefCon, DragReference theDragRef)
3795{
3796 RgnHandle hilightRgn;
3797 Rect Bounds;
3798
3799 UnusedParam(theWindow);
3800 UnusedParam(handlerRefCon);
3801 switch(message) {
3802 case kDragTrackingEnterWindow:
3803 hilightRgn = NewRgn();
3804 if (hilightRgn != NULL) {
3805 SetScrnRectFromCoords(&Bounds,
3806 0, 0, vMacScreenHeight, vMacScreenWidth);
3807 RectRgn(hilightRgn, &Bounds);
3808 ShowDragHilite(theDragRef, hilightRgn, true);
3809 DisposeRgn(hilightRgn);
3810 }
3811 break;
3812 case kDragTrackingLeaveWindow:
3813 HideDragHilite(theDragRef);
3814 break;
3815 }
3816
3817 return noErr;
3818}
3819
3820LOCALFUNC tMacErr InsertADiskOrAliasFromFSRef(FSRef *theRef)
3821{
3822 tMacErr err;
3823 Boolean isFolder;
3824 Boolean isAlias;
3825
3826 if (CheckSaveMacErr(FSResolveAliasFile(theRef, true,
3827 &isFolder, &isAlias)))
3828 {
3829 err = InsertADiskFromFSRef1(theRef);
3830 }
3831
3832 return err;
3833}
3834
3835LOCALFUNC tMacErr InsertADiskOrAliasFromSpec(FSSpec *spec)
3836{
3837 tMacErr err;
3838 FSRef newRef;
3839
3840 if (CheckSaveMacErr(FSpMakeFSRef(spec, &newRef)))
3841 if (CheckSavetMacErr(InsertADiskOrAliasFromFSRef(&newRef)))
3842 {
3843 /* ok */
3844 }
3845
3846 return err;
3847}
3848
3849static pascal OSErr GlobalReceiveHandler(WindowRef pWindow,
3850 void *handlerRefCon, DragReference theDragRef)
3851{
3852 SInt16 mouseUpModifiers;
3853 unsigned short items;
3854 unsigned short index;
3855 ItemReference theItem;
3856 Size SentSize;
3857 HFSFlavor r;
3858
3859 UnusedParam(pWindow);
3860 UnusedParam(handlerRefCon);
3861
3862 if (noErr == GetDragModifiers(theDragRef,
3863 NULL, NULL, &mouseUpModifiers))
3864 {
3865 MyUpdateKeyboardModifiers(mouseUpModifiers);
3866 }
3867
3868 if (noErr == CountDragItems(theDragRef, &items)) {
3869 for (index = 1; index <= items; ++index) {
3870 if (noErr == GetDragItemReferenceNumber(theDragRef,
3871 index, &theItem))
3872 if (noErr == GetFlavorDataSize(theDragRef,
3873 theItem, flavorTypeHFS, &SentSize))
3874 /*
3875 On very old macs SentSize might only be big enough
3876 to hold the actual file name. Have not seen this
3877 in OS X, but still leave the check
3878 as '<=' instead of '=='.
3879 */
3880 if (SentSize <= sizeof(HFSFlavor))
3881 if (noErr == GetFlavorData(theDragRef, theItem,
3882 flavorTypeHFS, (Ptr)&r, &SentSize, 0))
3883 {
3884 ReportStandardOpenDiskError(
3885 InsertADiskOrAliasFromSpec(&r.fileSpec));
3886 }
3887 }
3888
3889#if 1
3890 if (gTrueBackgroundFlag) {
3891 ProcessSerialNumber currentProcess = {0, kCurrentProcess};
3892
3893 (void) SetFrontProcess(¤tProcess);
3894 }
3895#endif
3896 }
3897
3898 return noErr;
3899}
3900
3901LOCALVAR DragTrackingHandlerUPP gGlobalTrackingHandler = NULL;
3902LOCALVAR DragReceiveHandlerUPP gGlobalReceiveHandler = NULL;
3903
3904LOCALPROC UnPrepareForDragging(void)
3905{
3906 if (NULL != gGlobalReceiveHandler) {
3907 RemoveReceiveHandler(gGlobalReceiveHandler, gMyMainWindow);
3908 DisposeDragReceiveHandlerUPP(gGlobalReceiveHandler);
3909 gGlobalReceiveHandler = NULL;
3910 }
3911 if (NULL != gGlobalTrackingHandler) {
3912 RemoveTrackingHandler(gGlobalTrackingHandler, gMyMainWindow);
3913 DisposeDragTrackingHandlerUPP(gGlobalTrackingHandler);
3914 gGlobalTrackingHandler = NULL;
3915 }
3916}
3917
3918LOCALFUNC blnr PrepareForDragging(void)
3919{
3920 blnr IsOk = falseblnr;
3921
3922 gGlobalTrackingHandler = NewDragTrackingHandlerUPP(
3923 GlobalTrackingHandler);
3924 if (gGlobalTrackingHandler != NULL) {
3925 gGlobalReceiveHandler = NewDragReceiveHandlerUPP(
3926 GlobalReceiveHandler);
3927 if (gGlobalReceiveHandler != NULL) {
3928 if (noErr == InstallTrackingHandler(gGlobalTrackingHandler,
3929 gMyMainWindow, nil))
3930 {
3931 if (noErr == InstallReceiveHandler(
3932 gGlobalReceiveHandler, gMyMainWindow, nil))
3933 {
3934 IsOk = trueblnr;
3935 }
3936 }
3937 }
3938 }
3939
3940 return IsOk;
3941}
3942
3943LOCALPROC HandleEventLocation(EventRef theEvent)
3944{
3945 Point NewMousePos;
3946
3947 if (! gWeAreActive) {
3948 return;
3949 }
3950
3951 if (noErr == GetEventParameter(theEvent,
3952 kEventParamMouseLocation,
3953 typeQDPoint,
3954 NULL,
3955 sizeof(NewMousePos),
3956 NULL,
3957 &NewMousePos))
3958 {
3959 MousePositionNotify(NewMousePos);
3960 }
3961}
3962
3963LOCALPROC HandleEventModifiers(EventRef theEvent)
3964{
3965 UInt32 theModifiers;
3966
3967 if (gWeAreActive) {
3968 GetEventParameter(theEvent, kEventParamKeyModifiers,
3969 typeUInt32, NULL, sizeof(typeUInt32), NULL, &theModifiers);
3970
3971 MyUpdateKeyboardModifiers(theModifiers);
3972 }
3973}
3974
3975LOCALVAR blnr IsOurMouseMove;
3976
3977static pascal OSStatus windowEventHandler(
3978 EventHandlerCallRef nextHandler, EventRef theEvent,
3979 void* userData)
3980{
3981 OSStatus result = eventNotHandledErr;
3982 UInt32 eventClass = GetEventClass(theEvent);
3983 UInt32 eventKind = GetEventKind(theEvent);
3984
3985 UnusedParam(nextHandler);
3986 UnusedParam(userData);
3987 switch(eventClass) {
3988 case kEventClassWindow:
3989 switch(eventKind) {
3990 case kEventWindowClose:
3991 RequestMacOff = trueblnr;
3992 result = noErr;
3993 break;
3994 case kEventWindowDrawContent:
3995 Update_Screen();
3996 result = noErr;
3997 break;
3998 case kEventWindowClickContentRgn:
3999 MouseIsOutside = falseblnr;
4000 HandleEventLocation(theEvent);
4001 HandleEventModifiers(theEvent);
4002 MyMouseButtonSet(trueblnr);
4003 result = noErr;
4004 break;
4005 case kEventWindowFocusAcquired:
4006 gLackFocusFlag = falseblnr;
4007 result = noErr;
4008 break;
4009 case kEventWindowFocusRelinquish:
4010 {
4011 WindowRef window;
4012
4013 (void) GetEventParameter(theEvent,
4014 kEventParamDirectObject, typeWindowRef,
4015 NULL, sizeof(WindowRef), NULL, &window);
4016 if ((window == gMyMainWindow)
4017 && (window != gMyOldWindow))
4018 {
4019 ClearWeAreActive();
4020 gLackFocusFlag = trueblnr;
4021 }
4022 }
4023 result = noErr;
4024 break;
4025 }
4026 break;
4027 case kEventClassMouse:
4028 switch(eventKind) {
4029 case kEventMouseMoved:
4030 case kEventMouseDragged:
4031 MouseIsOutside = falseblnr;
4032#if 0 /* don't bother, CheckMouseState will take care of it, better */
4033 HandleEventLocation(theEvent);
4034 HandleEventModifiers(theEvent);
4035#endif
4036 IsOurMouseMove = trueblnr;
4037 result = noErr;
4038 break;
4039 }
4040 break;
4041 }
4042
4043 return result;
4044}
4045
4046LOCALFUNC blnr MyCreateNewWindow(Rect *Bounds, WindowPtr *theWindow)
4047{
4048 WindowPtr ResultWin;
4049 blnr IsOk = falseblnr;
4050
4051 if (noErr == CreateNewWindow(
4052
4053#if VarFullScreen
4054 UseFullScreen ?
4055#endif
4056#if MayFullScreen
4057 /*
4058 appears not to work properly with aglSetWindowRef
4059 at least in OS X 10.5.5
4060 also doesn't seem to be needed. maybe dates from when
4061 didn't cover all screens in full screen mode.
4062 */
4063 /*
4064 Oops, no, kDocumentWindowClass doesn't seem to
4065 work quite right if made immediately after
4066 launch, title bar gets moved onscreen. At least
4067 in Intel 10.5.6, doesn't happen in PowerPC 10.4.11.
4068 Oddly, this problem doesn't happen if icon
4069 already in dock before launch, but perhaps
4070 that is just a timing issue.
4071 So use kPlainWindowClass after all.
4072 */
4073 kPlainWindowClass
4074#endif
4075#if VarFullScreen
4076 :
4077#endif
4078#if MayNotFullScreen
4079 kDocumentWindowClass
4080#endif
4081 ,
4082
4083#if VarFullScreen
4084 UseFullScreen ?
4085#endif
4086#if MayFullScreen
4087 /* kWindowStandardHandlerAttribute */ 0
4088#endif
4089#if VarFullScreen
4090 :
4091#endif
4092#if MayNotFullScreen
4093 kWindowCloseBoxAttribute
4094 | kWindowCollapseBoxAttribute
4095#endif
4096 ,
4097
4098 Bounds, &ResultWin
4099 ))
4100 {
4101#if VarFullScreen
4102 if (! UseFullScreen)
4103#endif
4104#if MayNotFullScreen
4105 {
4106 SetWindowTitleWithCFString(ResultWin,
4107 MyAppName /* CFSTR("Mini vMac") */);
4108 }
4109#endif
4110 InstallStandardEventHandler(GetWindowEventTarget(ResultWin));
4111 {
4112 static const EventTypeSpec windowEvents[] =
4113 {
4114 {kEventClassWindow, kEventWindowClose},
4115 {kEventClassWindow, kEventWindowDrawContent},
4116 {kEventClassWindow, kEventWindowClickContentRgn},
4117 {kEventClassMouse, kEventMouseMoved},
4118 {kEventClassMouse, kEventMouseDragged},
4119 {kEventClassWindow, kEventWindowFocusAcquired},
4120 {kEventClassWindow, kEventWindowFocusRelinquish}
4121 };
4122 InstallWindowEventHandler(ResultWin,
4123 NewEventHandlerUPP(windowEventHandler),
4124 GetEventTypeCount(windowEvents),
4125 windowEvents, 0, NULL);
4126 }
4127
4128 *theWindow = ResultWin;
4129
4130 IsOk = trueblnr;
4131 }
4132
4133 return IsOk;
4134}
4135
4136LOCALPROC CloseAglCurrentContext(void)
4137{
4138 if (ctx != NULL) {
4139 /*
4140 Only because MyDrawWithOpenGL doesn't
4141 bother to do this. No one
4142 uses the CurrentContext
4143 without settting it first.
4144 */
4145 if (GL_TRUE != aglSetCurrentContext(NULL)) {
4146 /* err = aglReportError() */
4147 }
4148 ctx = NULL;
4149 }
4150}
4151
4152LOCALPROC CloseMainWindow(void)
4153{
4154 UnPrepareForDragging();
4155
4156 if (window_ctx != NULL) {
4157 if (GL_TRUE != aglDestroyContext(window_ctx)) {
4158 /* err = aglReportError() */
4159 }
4160 window_ctx = NULL;
4161 }
4162
4163 if (window_fmt != NULL) {
4164 aglDestroyPixelFormat(window_fmt);
4165 window_fmt = NULL;
4166 }
4167
4168 if (gMyMainWindow != NULL) {
4169 DisposeWindow(gMyMainWindow);
4170 gMyMainWindow = NULL;
4171 }
4172}
4173
4174enum {
4175 kMagStateNormal,
4176#if EnableMagnify
4177 kMagStateMagnifgy,
4178#endif
4179 kNumMagStates
4180};
4181
4182#define kMagStateAuto kNumMagStates
4183
4184#if MayNotFullScreen
4185LOCALVAR int CurWinIndx;
4186LOCALVAR blnr HavePositionWins[kNumMagStates];
4187LOCALVAR Point WinPositionWins[kNumMagStates];
4188#endif
4189
4190LOCALFUNC blnr CreateMainWindow(void)
4191{
4192#if MayNotFullScreen
4193 int WinIndx;
4194#endif
4195 Rect MainScrnBounds;
4196 Rect AllScrnBounds;
4197 Rect NewWinRect;
4198 short leftPos;
4199 short topPos;
4200 short NewWindowHeight = vMacScreenHeight;
4201 short NewWindowWidth = vMacScreenWidth;
4202 blnr IsOk = falseblnr;
4203
4204#if VarFullScreen
4205 if (UseFullScreen) {
4206 My_HideMenuBar();
4207 } else {
4208 My_ShowMenuBar();
4209 }
4210#else
4211#if MayFullScreen
4212 My_HideMenuBar();
4213#endif
4214#endif
4215
4216 MyGetGrayRgnBounds(&AllScrnBounds);
4217 MyGetScreenBitsBounds(&MainScrnBounds);
4218
4219#if EnableMagnify
4220 if (UseMagnify) {
4221 NewWindowHeight *= MyWindowScale;
4222 NewWindowWidth *= MyWindowScale;
4223 }
4224#endif
4225
4226 leftPos = MainScrnBounds.left
4227 + ((MainScrnBounds.right - MainScrnBounds.left)
4228 - NewWindowWidth) / 2;
4229 topPos = MainScrnBounds.top
4230 + ((MainScrnBounds.bottom - MainScrnBounds.top)
4231 - NewWindowHeight) / 2;
4232 if (leftPos < MainScrnBounds.left) {
4233 leftPos = MainScrnBounds.left;
4234 }
4235 if (topPos < MainScrnBounds.top) {
4236 topPos = MainScrnBounds.top;
4237 }
4238
4239#if VarFullScreen
4240 if (UseFullScreen)
4241#endif
4242#if MayFullScreen
4243 {
4244 ViewHSize = MainScrnBounds.right - MainScrnBounds.left;
4245 ViewVSize = MainScrnBounds.bottom - MainScrnBounds.top;
4246#if EnableMagnify
4247 if (UseMagnify) {
4248 ViewHSize /= MyWindowScale;
4249 ViewVSize /= MyWindowScale;
4250 }
4251#endif
4252 if (ViewHSize >= vMacScreenWidth) {
4253 ViewHStart = 0;
4254 ViewHSize = vMacScreenWidth;
4255 } else {
4256 ViewHSize &= ~ 1;
4257 }
4258 if (ViewVSize >= vMacScreenHeight) {
4259 ViewVStart = 0;
4260 ViewVSize = vMacScreenHeight;
4261 } else {
4262 ViewVSize &= ~ 1;
4263 }
4264 }
4265#endif
4266
4267 /* Create window rectangle and centre it on the screen */
4268 SetRect(&MainScrnBounds, 0, 0, NewWindowWidth, NewWindowHeight);
4269 OffsetRect(&MainScrnBounds, leftPos, topPos);
4270
4271#if VarFullScreen
4272 if (UseFullScreen)
4273#endif
4274#if MayFullScreen
4275 {
4276 NewWinRect = AllScrnBounds;
4277 }
4278#endif
4279#if VarFullScreen
4280 else
4281#endif
4282#if MayNotFullScreen
4283 {
4284#if EnableMagnify
4285 if (UseMagnify) {
4286 WinIndx = kMagStateMagnifgy;
4287 } else
4288#endif
4289 {
4290 WinIndx = kMagStateNormal;
4291 }
4292
4293 if (! HavePositionWins[WinIndx]) {
4294 WinPositionWins[WinIndx].h = leftPos;
4295 WinPositionWins[WinIndx].v = topPos;
4296 HavePositionWins[WinIndx] = trueblnr;
4297 NewWinRect = MainScrnBounds;
4298 } else {
4299 SetRect(&NewWinRect, 0, 0, NewWindowWidth, NewWindowHeight);
4300 OffsetRect(&NewWinRect,
4301 WinPositionWins[WinIndx].h, WinPositionWins[WinIndx].v);
4302 }
4303 }
4304#endif
4305
4306#if MayNotFullScreen
4307 CurWinIndx = WinIndx;
4308#endif
4309
4310#if VarFullScreen
4311 if (UseFullScreen)
4312#endif
4313#if MayFullScreen
4314 {
4315 hOffset = MainScrnBounds.left - AllScrnBounds.left;
4316 vOffset = MainScrnBounds.top - AllScrnBounds.top;
4317 }
4318#endif
4319
4320 if (MyCreateNewWindow(&NewWinRect, &gMyMainWindow)) {
4321 static const GLint window_attrib[] = {AGL_RGBA,
4322#if UseAGLdoublebuff
4323 AGL_DOUBLEBUFFER,
4324#endif
4325 /* AGL_DEPTH_SIZE, 16, */
4326 AGL_NONE};
4327
4328#if 0 != vMacScreenDepth
4329 ColorModeWorks = trueblnr;
4330#endif
4331
4332 window_fmt = aglChoosePixelFormat(NULL, 0, window_attrib);
4333 if (NULL == window_fmt) {
4334 /* err = aglReportError() */
4335 } else {
4336 window_ctx = aglCreateContext(window_fmt, NULL);
4337 if (NULL == window_ctx) {
4338 /* err = aglReportError() */
4339 } else {
4340
4341 ShowWindow(gMyMainWindow);
4342
4343 if (GL_TRUE != (
4344 /*
4345 aglSetDrawable is deprecated, but use it anyway
4346 if at all possible, because aglSetWindowRef
4347 doesn't seeem to work properly on a
4348 kPlainWindowClass window.
4349 Should move to Cocoa.
4350 */
4351 HaveMyaglSetDrawable()
4352 ? MyaglSetDrawable(window_ctx,
4353 GetWindowPort(gMyMainWindow))
4354 :
4355 HaveMyaglSetWindowRef()
4356 ? MyaglSetWindowRef(window_ctx, gMyMainWindow)
4357 :
4358 GL_FALSE))
4359 {
4360 /* err = aglReportError() */
4361 } else {
4362 ctx = window_ctx;
4363
4364#if VarFullScreen
4365 if (UseFullScreen)
4366#endif
4367#if MayFullScreen
4368 {
4369 int h = NewWinRect.right - NewWinRect.left;
4370 int v = NewWinRect.bottom - NewWinRect.top;
4371
4372 GLhOffset = hOffset;
4373 GLvOffset = v - vOffset;
4374 MyAdjustGLforSize(h, v);
4375 }
4376#endif
4377#if VarFullScreen
4378 else
4379#endif
4380#if MayNotFullScreen
4381 {
4382 GLhOffset = 0;
4383 GLvOffset = NewWindowHeight;
4384 MyAdjustGLforSize(NewWindowWidth,
4385 NewWindowHeight);
4386 }
4387#endif
4388
4389#if UseAGLdoublebuff && 1
4390 {
4391 GLint agSwapInterval = 1;
4392 if (GL_TRUE != aglSetInteger(
4393 window_ctx, AGL_SWAP_INTERVAL,
4394 &agSwapInterval))
4395 {
4396 MacMsg("oops", "aglSetInteger failed",
4397 falseblnr);
4398 } else {
4399 /*
4400 MacMsg("good", "aglSetInteger ok",
4401 falseblnr);
4402 */
4403 }
4404 }
4405#endif
4406
4407#if VarFullScreen
4408 if (! UseFullScreen)
4409#endif
4410#if MayNotFullScreen
4411 {
4412 /* check if window rect valid */
4413 Rect tr;
4414
4415 if (MyGetWindowTitleBounds(gMyMainWindow, &tr))
4416 {
4417 if (! RectInRgn(&tr, GetGrayRgn())) {
4418 MySetMacWindContRect(gMyMainWindow,
4419 &MainScrnBounds);
4420 if (MyGetWindowTitleBounds(
4421 gMyMainWindow, &tr))
4422 {
4423 if (! RectInRgn(&tr, GetGrayRgn()))
4424 {
4425 OffsetRect(&MainScrnBounds, 0,
4426 AllScrnBounds.top - tr.top);
4427 MySetMacWindContRect(
4428 gMyMainWindow,
4429 &MainScrnBounds);
4430 }
4431 }
4432 }
4433 }
4434 }
4435#endif
4436
4437 (void) PrepareForDragging();
4438
4439 IsOk = trueblnr;
4440 }
4441 }
4442 }
4443 }
4444
4445 return IsOk;
4446}
4447
4448#if EnableRecreateW
4449LOCALPROC ZapMyWState(void)
4450{
4451 gMyMainWindow = NULL;
4452 window_fmt = NULL;
4453 window_ctx = NULL;
4454 gGlobalReceiveHandler = NULL;
4455 gGlobalTrackingHandler = NULL;
4456}
4457#endif
4458
4459#if EnableRecreateW
4460struct MyWState {
4461 WindowPtr f_MainWindow;
4462 AGLPixelFormat f_fmt;
4463 AGLContext f_ctx;
4464#if MayFullScreen
4465 short f_hOffset;
4466 short f_vOffset;
4467 ui4r f_ViewHSize;
4468 ui4r f_ViewVSize;
4469 ui4r f_ViewHStart;
4470 ui4r f_ViewVStart;
4471#endif
4472#if VarFullScreen
4473 blnr f_UseFullScreen;
4474#endif
4475#if EnableMagnify
4476 blnr f_UseMagnify;
4477#endif
4478#if MayNotFullScreen
4479 int f_CurWinIndx;
4480#endif
4481 short f_GLhOffset;
4482 short f_GLvOffset;
4483 DragTrackingHandlerUPP f_gGlobalTrackingHandler;
4484 DragReceiveHandlerUPP f_gGlobalReceiveHandler;
4485};
4486typedef struct MyWState MyWState;
4487#endif
4488
4489#if EnableRecreateW
4490LOCALPROC GetMyWState(MyWState *r)
4491{
4492 r->f_MainWindow = gMyMainWindow;
4493 r->f_fmt = window_fmt;
4494 r->f_ctx = window_ctx;
4495#if MayFullScreen
4496 r->f_hOffset = hOffset;
4497 r->f_vOffset = vOffset;
4498 r->f_ViewHSize = ViewHSize;
4499 r->f_ViewVSize = ViewVSize;
4500 r->f_ViewHStart = ViewHStart;
4501 r->f_ViewVStart = ViewVStart;
4502#endif
4503#if VarFullScreen
4504 r->f_UseFullScreen = UseFullScreen;
4505#endif
4506#if EnableMagnify
4507 r->f_UseMagnify = UseMagnify;
4508#endif
4509#if MayNotFullScreen
4510 r->f_CurWinIndx = CurWinIndx;
4511#endif
4512 r->f_GLhOffset = GLhOffset;
4513 r->f_GLvOffset = GLvOffset;
4514 r->f_gGlobalTrackingHandler = gGlobalTrackingHandler;
4515 r->f_gGlobalReceiveHandler = gGlobalReceiveHandler;
4516}
4517#endif
4518
4519#if EnableRecreateW
4520LOCALPROC SetMyWState(MyWState *r)
4521{
4522 gMyMainWindow = r->f_MainWindow;
4523 window_fmt = r->f_fmt;
4524 window_ctx = r->f_ctx;
4525#if MayFullScreen
4526 hOffset = r->f_hOffset;
4527 vOffset = r->f_vOffset;
4528 ViewHSize = r->f_ViewHSize;
4529 ViewVSize = r->f_ViewVSize;
4530 ViewHStart = r->f_ViewHStart;
4531 ViewVStart = r->f_ViewVStart;
4532#endif
4533#if VarFullScreen
4534 UseFullScreen = r->f_UseFullScreen;
4535#endif
4536#if EnableMagnify
4537 UseMagnify = r->f_UseMagnify;
4538#endif
4539#if MayNotFullScreen
4540 CurWinIndx = r->f_CurWinIndx;
4541#endif
4542 GLhOffset = r->f_GLhOffset;
4543 GLvOffset = r->f_GLvOffset;
4544 gGlobalTrackingHandler = r->f_gGlobalTrackingHandler;
4545 gGlobalReceiveHandler = r->f_gGlobalReceiveHandler;
4546
4547 ctx = window_ctx;
4548}
4549#endif
4550
4551#if EnableRecreateW
4552LOCALFUNC blnr ReCreateMainWindow(void)
4553{
4554 MyWState old_state;
4555 MyWState new_state;
4556
4557#if VarFullScreen
4558 if (! UseFullScreen)
4559#endif
4560#if MayNotFullScreen
4561 {
4562 /* save old position */
4563 if (gMyMainWindow != NULL) {
4564 Rect r;
4565
4566 if (MyGetWindowContBounds(gMyMainWindow, &r)) {
4567 WinPositionWins[CurWinIndx].h = r.left;
4568 WinPositionWins[CurWinIndx].v = r.top;
4569 }
4570 }
4571 }
4572#endif
4573
4574#if MayFullScreen
4575 UngrabMachine();
4576#endif
4577
4578 CloseAglCurrentContext();
4579
4580 gMyOldWindow = gMyMainWindow;
4581
4582 GetMyWState(&old_state);
4583
4584 ZapMyWState();
4585
4586#if VarFullScreen
4587 UseFullScreen = WantFullScreen;
4588#endif
4589#if EnableMagnify
4590 UseMagnify = WantMagnify;
4591#endif
4592
4593 if (! CreateMainWindow()) {
4594 gMyOldWindow = NULL;
4595 CloseMainWindow();
4596 SetMyWState(&old_state);
4597
4598#if VarFullScreen
4599 if (UseFullScreen) {
4600 My_HideMenuBar();
4601 } else {
4602 My_ShowMenuBar();
4603 }
4604#endif
4605
4606 /* avoid retry */
4607#if VarFullScreen
4608 WantFullScreen = UseFullScreen;
4609#endif
4610#if EnableMagnify
4611 WantMagnify = UseMagnify;
4612#endif
4613
4614 return falseblnr;
4615 } else {
4616 GetMyWState(&new_state);
4617 SetMyWState(&old_state);
4618 CloseMainWindow();
4619 gMyOldWindow = NULL;
4620 SetMyWState(&new_state);
4621
4622 if (HaveCursorHidden) {
4623 (void) MyMoveMouse(CurMouseH, CurMouseV);
4624 WantCursorHidden = trueblnr;
4625 } else {
4626 MouseIsOutside = falseblnr; /* don't know */
4627 }
4628
4629 return trueblnr;
4630 }
4631}
4632#endif
4633
4634#if VarFullScreen && EnableMagnify
4635enum {
4636 kWinStateWindowed,
4637#if EnableMagnify
4638 kWinStateFullScreen,
4639#endif
4640 kNumWinStates
4641};
4642#endif
4643
4644#if VarFullScreen && EnableMagnify
4645LOCALVAR int WinMagStates[kNumWinStates];
4646#endif
4647
4648LOCALPROC ZapWinStateVars(void)
4649{
4650#if MayNotFullScreen
4651 {
4652 int i;
4653
4654 for (i = 0; i < kNumMagStates; ++i) {
4655 HavePositionWins[i] = falseblnr;
4656 }
4657 }
4658#endif
4659#if VarFullScreen && EnableMagnify
4660 {
4661 int i;
4662
4663 for (i = 0; i < kNumWinStates; ++i) {
4664 WinMagStates[i] = kMagStateAuto;
4665 }
4666 }
4667#endif
4668}
4669
4670#if VarFullScreen
4671LOCALPROC ToggleWantFullScreen(void)
4672{
4673 WantFullScreen = ! WantFullScreen;
4674
4675#if EnableMagnify
4676 {
4677 int OldWinState =
4678 UseFullScreen ? kWinStateFullScreen : kWinStateWindowed;
4679 int OldMagState =
4680 UseMagnify ? kMagStateMagnifgy : kMagStateNormal;
4681 int NewWinState =
4682 WantFullScreen ? kWinStateFullScreen : kWinStateWindowed;
4683 int NewMagState = WinMagStates[NewWinState];
4684
4685 WinMagStates[OldWinState] = OldMagState;
4686 if (kMagStateAuto != NewMagState) {
4687 WantMagnify = (kMagStateMagnifgy == NewMagState);
4688 } else {
4689 WantMagnify = falseblnr;
4690 if (WantFullScreen
4691 && HaveMyCGDisplayPixelsWide()
4692 && HaveMyCGDisplayPixelsHigh())
4693 {
4694 CGDirectDisplayID CurMainDisplayID = MyMainDisplayID();
4695
4696 if ((MyCGDisplayPixelsWide(CurMainDisplayID)
4697 >= vMacScreenWidth * MyWindowScale)
4698 && (MyCGDisplayPixelsHigh(CurMainDisplayID)
4699 >= vMacScreenHeight * MyWindowScale)
4700 )
4701 {
4702 WantMagnify = trueblnr;
4703 }
4704 }
4705 }
4706 }
4707#endif
4708}
4709#endif
4710
4711LOCALPROC LeaveSpeedStopped(void)
4712{
4713#if MySoundEnabled
4714 MySound_Start();
4715#endif
4716
4717 StartUpTimeAdjust();
4718}
4719
4720LOCALPROC EnterSpeedStopped(void)
4721{
4722#if MySoundEnabled
4723 MySound_Stop();
4724#endif
4725}
4726
4727LOCALPROC DoNotInBackgroundTasks(void)
4728{
4729#if 0
4730 if (HaveMyCGCursorIsVisible()) {
4731 HaveCursorHidden = ! MyCGCursorIsVisible();
4732
4733 /*
4734 This shouldn't be needed, but have seen
4735 cursor state get messed up in 10.4.
4736 If the os x hide count gets off, this
4737 should fix it within a few ticks.
4738
4739 oops, no, doesn't seem to be accurate,
4740 and makes things worse. particularly if
4741 cursor in obscured state after typing
4742 into dialog.
4743 */
4744 /* trying a different approach further below */
4745 }
4746#endif
4747
4748 if (HaveCursorHidden != (
4749#if MayNotFullScreen
4750 (WantCursorHidden
4751#if VarFullScreen
4752 || UseFullScreen
4753#endif
4754 ) &&
4755#endif
4756 gWeAreActive && ! CurSpeedStopped))
4757 {
4758 HaveCursorHidden = ! HaveCursorHidden;
4759 if (HaveCursorHidden) {
4760 MyHideCursor();
4761 } else {
4762 /*
4763 kludge for OS X, where mouse over Dock devider
4764 changes cursor, and never sets it back.
4765 */
4766 SetCursorArrow();
4767
4768 MyShowCursor();
4769 }
4770 }
4771
4772 /* check if actual cursor visibility is what it should be */
4773 if (HaveMyCGCursorIsVisible()) {
4774 /* but only in OS X 10.3 and later */
4775 if (MyCGCursorIsVisible()) {
4776 if (HaveCursorHidden) {
4777 MyHideCursor();
4778 if (MyCGCursorIsVisible()) {
4779 /*
4780 didn't work, attempt undo so that
4781 hide cursor count won't get large
4782 */
4783 MyShowCursor();
4784 }
4785 }
4786 } else {
4787 if (! HaveCursorHidden) {
4788 MyShowCursor();
4789 /*
4790 don't check if worked, assume can't decrement
4791 hide cursor count below 0
4792 */
4793 }
4794 }
4795 }
4796}
4797
4798LOCALPROC CheckForSavedTasks(void)
4799{
4800 if (MyEvtQNeedRecover) {
4801 MyEvtQNeedRecover = falseblnr;
4802
4803 /* attempt cleanup, MyEvtQNeedRecover may get set again */
4804 MyEvtQTryRecoverFromFull();
4805 }
4806
4807#if EnableFSMouseMotion
4808 if (HaveMouseMotion) {
4809 MyMouseConstrain();
4810 }
4811#endif
4812
4813 if (RequestMacOff) {
4814 RequestMacOff = falseblnr;
4815 if (AnyDiskInserted()) {
4816 MacMsgOverride(kStrQuitWarningTitle,
4817 kStrQuitWarningMessage);
4818 } else {
4819 ForceMacOff = trueblnr;
4820 }
4821 }
4822
4823 if (! gWeAreActive) {
4824 if (! (gTrueBackgroundFlag || gLackFocusFlag)) {
4825 gWeAreActive = trueblnr;
4826 ReconnectKeyCodes3();
4827 SetCursorArrow();
4828 }
4829 }
4830
4831#if VarFullScreen
4832 if (gTrueBackgroundFlag && WantFullScreen) {
4833 ToggleWantFullScreen();
4834 }
4835#endif
4836
4837 if (CurSpeedStopped != (SpeedStopped ||
4838 (gTrueBackgroundFlag && ! RunInBackground
4839#if EnableAutoSlow && 0
4840 && (QuietSubTicks >= 4092)
4841#endif
4842 )))
4843 {
4844 CurSpeedStopped = ! CurSpeedStopped;
4845 if (CurSpeedStopped) {
4846 EnterSpeedStopped();
4847 } else {
4848 LeaveSpeedStopped();
4849 }
4850 }
4851
4852#if EnableRecreateW
4853 if (gWeAreActive) {
4854 if (0
4855#if EnableMagnify
4856 || (UseMagnify != WantMagnify)
4857#endif
4858#if VarFullScreen
4859 || (UseFullScreen != WantFullScreen)
4860#endif
4861 )
4862 {
4863 (void) ReCreateMainWindow();
4864 }
4865 }
4866#endif
4867
4868#if MayFullScreen
4869 if (GrabMachine != (
4870#if VarFullScreen
4871 UseFullScreen &&
4872#endif
4873 gWeAreActive && ! CurSpeedStopped))
4874 {
4875 GrabMachine = ! GrabMachine;
4876 AdjustMachineGrab();
4877 }
4878#endif
4879
4880 if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
4881 MacMsgDisplayOn();
4882 }
4883
4884 if (WantScreensChangedCheck) {
4885 WantScreensChangedCheck = falseblnr;
4886 MyUpdateOpenGLContext();
4887 }
4888
4889 if (NeedWholeScreenDraw) {
4890 NeedWholeScreenDraw = falseblnr;
4891 ScreenChangedAll();
4892 }
4893
4894 if (! gWeAreActive) {
4895 /*
4896 dialog during drag and drop hangs if in background
4897 and don't want recursive dialogs
4898 so wait til later to display dialog
4899 */
4900 } else {
4901#if IncludeSonyNew
4902 if (vSonyNewDiskWanted) {
4903#if IncludeSonyNameNew
4904 if (vSonyNewDiskName != NotAPbuf) {
4905 CFStringRef NewDiskName =
4906 CFStringCreateWithPbuf(vSonyNewDiskName);
4907 MakeNewDisk(vSonyNewDiskSize, NewDiskName);
4908 if (NewDiskName != NULL) {
4909 CFRelease(NewDiskName);
4910 }
4911 PbufDispose(vSonyNewDiskName);
4912 vSonyNewDiskName = NotAPbuf;
4913 } else
4914#endif
4915 {
4916 MakeNewDisk(vSonyNewDiskSize, NULL);
4917 }
4918 vSonyNewDiskWanted = falseblnr;
4919 /* must be done after may have gotten disk */
4920 }
4921#endif
4922 if (RequestInsertDisk) {
4923 RequestInsertDisk = falseblnr;
4924 InsertADisk0();
4925 }
4926 }
4927
4928#if NeedRequestIthDisk
4929 if (0 != RequestIthDisk) {
4930 Sony_InsertIth(RequestIthDisk);
4931 RequestIthDisk = 0;
4932 }
4933#endif
4934
4935 if (gWeAreActive) {
4936 DoNotInBackgroundTasks();
4937 }
4938}
4939
4940#define CheckItem CheckMenuItem
4941
4942/* Menu Constants */
4943
4944#define kAppleMenu 128
4945#define kFileMenu 129
4946#define kSpecialMenu 130
4947
4948enum {
4949 kCmdIdNull,
4950 kCmdIdMoreCommands,
4951
4952 kNumCmdIds
4953};
4954
4955LOCALFUNC OSStatus MyProcessCommand(MenuCommand inCommandID)
4956{
4957 OSStatus result = noErr;
4958
4959 switch (inCommandID) {
4960 case kHICommandAbout:
4961 DoAboutMsg();
4962 break;
4963 case kHICommandQuit:
4964 RequestMacOff = trueblnr;
4965 break;
4966 case kHICommandOpen:
4967 RequestInsertDisk = trueblnr;
4968 break;
4969 case kCmdIdMoreCommands:
4970 DoMoreCommandsMsg();
4971 break;
4972 default:
4973 result = eventNotHandledErr;
4974 break;
4975 }
4976
4977 return result;
4978}
4979
4980LOCALFUNC OSStatus Keyboard_UpdateKeyMap3(EventRef theEvent, blnr down)
4981{
4982 UInt32 uiKeyCode;
4983
4984 HandleEventModifiers(theEvent);
4985 GetEventParameter(theEvent, kEventParamKeyCode, typeUInt32, NULL,
4986 sizeof(uiKeyCode), NULL, &uiKeyCode);
4987 Keyboard_UpdateKeyMap2(Keyboard_RemapMac(uiKeyCode & 0x000000FF),
4988 down);
4989 return noErr;
4990}
4991
4992static pascal OSStatus MyEventHandler(EventHandlerCallRef nextHandler,
4993 EventRef theEvent, void * userData)
4994{
4995 OSStatus result = eventNotHandledErr;
4996 UInt32 eventClass = GetEventClass(theEvent);
4997 UInt32 eventKind = GetEventKind(theEvent);
4998
4999 UnusedParam(userData);
5000
5001 switch (eventClass) {
5002 case kEventClassMouse:
5003 switch (eventKind) {
5004 case kEventMouseDown:
5005#if MayFullScreen
5006 if (GrabMachine) {
5007 HandleEventLocation(theEvent);
5008 HandleEventModifiers(theEvent);
5009 MyMouseButtonSet(trueblnr);
5010 result = noErr;
5011 } else
5012#endif
5013 {
5014 result = CallNextEventHandler(
5015 nextHandler, theEvent);
5016 }
5017 break;
5018 case kEventMouseUp:
5019 HandleEventLocation(theEvent);
5020 HandleEventModifiers(theEvent);
5021 MyMouseButtonSet(falseblnr);
5022#if MayFullScreen
5023 if (GrabMachine) {
5024 result = noErr;
5025 } else
5026#endif
5027 {
5028 result = CallNextEventHandler(
5029 nextHandler, theEvent);
5030 }
5031 break;
5032 case kEventMouseMoved:
5033 case kEventMouseDragged:
5034 IsOurMouseMove = falseblnr;
5035 result = CallNextEventHandler(
5036 nextHandler, theEvent);
5037 /*
5038 Actually, mousing over window does't seem
5039 to go through here, it goes directly to
5040 the window routine. But since not documented
5041 either way, leave the check in case this
5042 changes.
5043 */
5044 if (! IsOurMouseMove) {
5045 MouseIsOutside = trueblnr;
5046#if 0 /* don't bother, CheckMouseState will take care of it, better */
5047 HandleEventLocation(theEvent);
5048 HandleEventModifiers(theEvent);
5049#endif
5050 }
5051 break;
5052 }
5053 break;
5054 case kEventClassApplication:
5055 switch (eventKind) {
5056 case kEventAppActivated:
5057 gTrueBackgroundFlag = falseblnr;
5058 result = noErr;
5059 break;
5060 case kEventAppDeactivated:
5061 gTrueBackgroundFlag = trueblnr;
5062 result = noErr;
5063 ClearWeAreActive();
5064 break;
5065 }
5066 break;
5067 case kEventClassCommand:
5068 switch (eventKind) {
5069 case kEventProcessCommand:
5070 {
5071 HICommand hiCommand;
5072
5073 GetEventParameter(theEvent,
5074 kEventParamDirectObject, typeHICommand,
5075 NULL, sizeof(HICommand), NULL, &hiCommand);
5076 result = MyProcessCommand(hiCommand.commandID);
5077 }
5078 break;
5079 }
5080 break;
5081 case kEventClassKeyboard:
5082 if (! gWeAreActive) {
5083 return CallNextEventHandler(nextHandler, theEvent);
5084 } else {
5085 switch (eventKind) {
5086 case kEventRawKeyDown:
5087 result = Keyboard_UpdateKeyMap3(
5088 theEvent, trueblnr);
5089 break;
5090 case kEventRawKeyUp:
5091 result = Keyboard_UpdateKeyMap3(
5092 theEvent, falseblnr);
5093 break;
5094 case kEventRawKeyModifiersChanged:
5095 HandleEventModifiers(theEvent);
5096 result = noErr;
5097 break;
5098 default:
5099 break;
5100 }
5101 }
5102 break;
5103 default:
5104 break;
5105 }
5106 return result;
5107}
5108
5109LOCALPROC AppendMenuConvertCStr(
5110 MenuRef menu,
5111 MenuCommand inCommandID,
5112 char *s)
5113{
5114 CFStringRef cfStr = CFStringCreateFromSubstCStr(s);
5115 if (NULL != cfStr) {
5116 AppendMenuItemTextWithCFString(menu, cfStr,
5117 0, inCommandID, NULL);
5118 CFRelease(cfStr);
5119 }
5120}
5121
5122LOCALPROC AppendMenuSep(MenuRef menu)
5123{
5124 AppendMenuItemTextWithCFString(menu, NULL,
5125 kMenuItemAttrSeparator, 0, NULL);
5126}
5127
5128LOCALFUNC MenuRef NewMenuFromConvertCStr(short menuID, char *s)
5129{
5130 MenuRef menu = NULL;
5131
5132 CFStringRef cfStr = CFStringCreateFromSubstCStr(s);
5133 if (NULL != cfStr) {
5134 OSStatus err = CreateNewMenu(menuID, 0, &menu);
5135 if (err != noErr) {
5136 menu = NULL;
5137 } else {
5138 (void) SetMenuTitleWithCFString(menu, cfStr);
5139 }
5140 CFRelease(cfStr);
5141 }
5142
5143 return menu;
5144}
5145
5146LOCALPROC RemoveCommandKeysInMenu(MenuRef theMenu)
5147{
5148 MenuRef outHierMenu;
5149 int i;
5150 UInt16 n = CountMenuItems(theMenu);
5151
5152 for (i = 1; i <= n; ++i) {
5153 SetItemCmd(theMenu, i, 0);
5154 if (noErr == GetMenuItemHierarchicalMenu(
5155 theMenu, i, &outHierMenu)
5156 && (NULL != outHierMenu))
5157 {
5158 RemoveCommandKeysInMenu(outHierMenu);
5159 }
5160 }
5161}
5162
5163LOCALFUNC blnr InstallOurMenus(void)
5164{
5165 MenuRef menu;
5166 Str255 s;
5167
5168 PStrFromChar(s, (char)20);
5169 menu = NewMenu(kAppleMenu, s);
5170 if (menu != NULL) {
5171 AppendMenuConvertCStr(menu,
5172 kHICommandAbout,
5173 kStrMenuItemAbout);
5174 AppendMenuSep(menu);
5175 InsertMenu(menu, 0);
5176 }
5177
5178 menu = NewMenuFromConvertCStr(kFileMenu, kStrMenuFile);
5179 if (menu != NULL) {
5180 AppendMenuConvertCStr(menu,
5181 kHICommandOpen,
5182 kStrMenuItemOpen ";ll");
5183 InsertMenu(menu, 0);
5184 }
5185
5186 menu = NewMenuFromConvertCStr(kSpecialMenu, kStrMenuSpecial);
5187 if (menu != NULL) {
5188 AppendMenuConvertCStr(menu,
5189 kCmdIdMoreCommands,
5190 kStrMenuItemMore ";ll");
5191 InsertMenu(menu, 0);
5192 }
5193
5194 {
5195 MenuRef outMenu;
5196 MenuItemIndex outIndex;
5197
5198 if (noErr == GetIndMenuItemWithCommandID(
5199 NULL, kHICommandQuit, 1, &outMenu, &outIndex))
5200 {
5201 RemoveCommandKeysInMenu(outMenu);
5202 }
5203 }
5204
5205 DrawMenuBar();
5206
5207 return trueblnr;
5208}
5209
5210LOCALFUNC blnr InstallOurAppearanceClient(void)
5211{
5212 RegisterAppearanceClient(); /* maybe not needed ? */
5213 return trueblnr;
5214}
5215
5216LOCALVAR blnr DisplayRegistrationCallBackSuccessful = falseblnr;
5217
5218static void DisplayRegisterReconfigurationCallback(
5219 CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags,
5220 void *userInfo)
5221{
5222 UnusedParam(display);
5223 UnusedParam(userInfo);
5224
5225 if (0 != (flags & kCGDisplayBeginConfigurationFlag)) {
5226 /* fprintf(stderr, "kCGDisplayBeginConfigurationFlag\n"); */
5227 } else {
5228#if 0
5229 if (0 != (flags & kCGDisplayMovedFlag)) {
5230 fprintf(stderr, "kCGDisplayMovedFlag\n");
5231 }
5232 if (0 != (flags & kCGDisplaySetMainFlag)) {
5233 fprintf(stderr, "kCGDisplaySetMainFlag\n");
5234 }
5235 if (0 != (flags & kCGDisplaySetModeFlag)) {
5236 fprintf(stderr, "kCGDisplaySetModeFlag\n");
5237 }
5238
5239 if (0 != (flags & kCGDisplayAddFlag)) {
5240 fprintf(stderr, "kCGDisplayAddFlag\n");
5241 }
5242 if (0 != (flags & kCGDisplayRemoveFlag)) {
5243 fprintf(stderr, "kCGDisplayRemoveFlag\n");
5244 }
5245
5246 if (0 != (flags & kCGDisplayEnabledFlag)) {
5247 fprintf(stderr, "kCGDisplayEnabledFlag\n");
5248 }
5249 if (0 != (flags & kCGDisplayDisabledFlag)) {
5250 fprintf(stderr, "kCGDisplayDisabledFlag\n");
5251 }
5252
5253 if (0 != (flags & kCGDisplayMirrorFlag)) {
5254 fprintf(stderr, "kCGDisplayMirrorFlag\n");
5255 }
5256 if (0 != (flags & kCGDisplayUnMirrorFlag)) {
5257 fprintf(stderr, "kCGDisplayMirrorFlag\n");
5258 }
5259#endif
5260
5261 WantScreensChangedCheck = trueblnr;
5262
5263#if VarFullScreen
5264 if (WantFullScreen) {
5265 ToggleWantFullScreen();
5266 }
5267#endif
5268 }
5269}
5270
5271LOCALFUNC blnr InstallOurEventHandlers(void)
5272{
5273 EventTypeSpec eventTypes[] = {
5274 {kEventClassMouse, kEventMouseDown},
5275 {kEventClassMouse, kEventMouseUp},
5276 {kEventClassMouse, kEventMouseMoved},
5277 {kEventClassMouse, kEventMouseDragged},
5278 {kEventClassKeyboard, kEventRawKeyModifiersChanged},
5279 {kEventClassKeyboard, kEventRawKeyDown},
5280 {kEventClassKeyboard, kEventRawKeyUp},
5281 {kEventClassApplication, kEventAppActivated},
5282 {kEventClassApplication, kEventAppDeactivated},
5283 {kEventClassCommand, kEventProcessCommand}
5284 };
5285
5286 InstallApplicationEventHandler(
5287 NewEventHandlerUPP(MyEventHandler),
5288 GetEventTypeCount(eventTypes),
5289 eventTypes, NULL, NULL);
5290
5291 InitKeyCodes();
5292
5293 InstallAppleEventHandlers();
5294
5295 if (HaveMyCGDisplayRegisterReconfigurationCallback()) {
5296 if (kCGErrorSuccess ==
5297 MyCGDisplayRegisterReconfigurationCallback(
5298 DisplayRegisterReconfigurationCallback, NULL))
5299 {
5300 DisplayRegistrationCallBackSuccessful = trueblnr;
5301 }
5302 }
5303
5304 /* (void) SetMouseCoalescingEnabled(false, NULL); */
5305
5306 return trueblnr;
5307}
5308
5309LOCALPROC UnInstallOurEventHandlers(void)
5310{
5311 if (DisplayRegistrationCallBackSuccessful) {
5312 if (HaveMyCGDisplayRemoveReconfigurationCallback()) {
5313 MyCGDisplayRemoveReconfigurationCallback(
5314 DisplayRegisterReconfigurationCallback, NULL);
5315 }
5316 }
5317}
5318
5319GLOBALOSGLUPROC WaitForNextTick(void)
5320{
5321 OSStatus err;
5322 EventRef theEvent;
5323 ui3r NumChecks;
5324 EventTimeout inTimeout;
5325 EventTargetRef theTarget = GetEventDispatcherTarget();
5326
5327 inTimeout = kEventDurationNoWait;
5328
5329label_retry:
5330 NumChecks = 0;
5331 while ((NumChecks < 32) && (noErr == (err =
5332 ReceiveNextEvent(0, NULL, inTimeout,
5333 true, &theEvent))))
5334 {
5335 (void) SendEventToEventTarget(theEvent, theTarget);
5336 ReleaseEvent(theEvent);
5337 inTimeout = kEventDurationNoWait;
5338 ++NumChecks;
5339 }
5340
5341 CheckForSavedTasks();
5342
5343 if (ForceMacOff) {
5344 return;
5345 }
5346
5347 if (CurSpeedStopped) {
5348 DoneWithDrawingForTick();
5349 inTimeout = kEventDurationForever;
5350 goto label_retry;
5351 }
5352
5353 if (ExtraTimeNotOver()) {
5354 inTimeout =
5355 NextTickChangeTime - GetCurrentEventTime();
5356 if (inTimeout > 0.0) {
5357#if 1
5358 struct timespec rqt;
5359 struct timespec rmt;
5360
5361 rqt.tv_sec = 0;
5362 rqt.tv_nsec = inTimeout / kEventDurationNanosecond;
5363 (void) nanosleep(&rqt, &rmt);
5364 inTimeout = kEventDurationNoWait;
5365 goto label_retry;
5366#elif 1
5367 usleep(inTimeout / kEventDurationMicrosecond);
5368 inTimeout = kEventDurationNoWait;
5369 goto label_retry;
5370#else
5371 /*
5372 This has higher overhead.
5373 */
5374 goto label_retry;
5375#endif
5376 }
5377 }
5378
5379 if (CheckDateTime()) {
5380#if MySoundEnabled
5381 MySound_SecondNotify();
5382#endif
5383#if EnableDemoMsg
5384 DemoModeSecondNotify();
5385#endif
5386 }
5387
5388 if (gWeAreActive) {
5389 CheckMouseState();
5390 }
5391
5392 OnTrueTime = TrueEmulatedTime;
5393
5394#if dbglog_TimeStuff
5395 dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime);
5396#endif
5397}
5398
5399/* --- platform independent code can be thought of as going here --- */
5400
5401#include "PROGMAIN.h"
5402
5403LOCALPROC ReserveAllocAll(void)
5404{
5405#if dbglog_HAVE
5406 dbglog_ReserveAlloc();
5407#endif
5408 ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr);
5409 ReserveAllocOneBlock(&screencomparebuff,
5410 vMacScreenNumBytes, 5, trueblnr);
5411 ReserveAllocOneBlock(&CntrlDisplayBuff,
5412 vMacScreenNumBytes, 5, falseblnr);
5413 ReserveAllocOneBlock(&ScalingBuff, vMacScreenNumPixels
5414#if 0 != vMacScreenDepth
5415 * 4
5416#endif
5417 , 5, falseblnr);
5418 ReserveAllocOneBlock(&CLUT_final, CLUT_finalsz, 5, falseblnr);
5419#if MySoundEnabled
5420 ReserveAllocOneBlock((ui3p *)&TheSoundBuffer,
5421 dbhBufferSize, 5, falseblnr);
5422#endif
5423
5424 EmulationReserveAlloc();
5425}
5426
5427LOCALFUNC blnr AllocMyMemory(void)
5428{
5429 uimr n;
5430 blnr IsOk = falseblnr;
5431
5432 ReserveAllocOffset = 0;
5433 ReserveAllocBigBlock = nullpr;
5434 ReserveAllocAll();
5435 n = ReserveAllocOffset;
5436 ReserveAllocBigBlock = (ui3p)calloc(1, n);
5437 if (NULL == ReserveAllocBigBlock) {
5438 MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
5439 } else {
5440 ReserveAllocOffset = 0;
5441 ReserveAllocAll();
5442 if (n != ReserveAllocOffset) {
5443 /* oops, program error */
5444 } else {
5445 IsOk = trueblnr;
5446 }
5447 }
5448
5449 return IsOk;
5450}
5451
5452LOCALFUNC blnr InitOSGLU(void)
5453{
5454 if (AllocMyMemory())
5455 if (InitMyApplInfo())
5456#if dbglog_HAVE
5457 if (dbglog_open())
5458#endif
5459#if MySoundEnabled
5460 if (MySound_Init())
5461#endif
5462 if (InstallOurAppearanceClient())
5463 if (InstallOurEventHandlers())
5464 if (InstallOurMenus())
5465 if (CreateMainWindow())
5466 if (LoadMacRom())
5467 if (LoadInitialImages())
5468#if UseActvCode
5469 if (ActvCodeInit())
5470#endif
5471 if (InitLocationDat())
5472#if EmLocalTalk
5473 if (EntropyGather())
5474 if (InitLocalTalk())
5475#endif
5476 if (WaitForRom())
5477 {
5478 return trueblnr;
5479 }
5480 return falseblnr;
5481}
5482
5483#if dbglog_HAVE && 0
5484IMPORTPROC DoDumpTable(void);
5485#endif
5486#if dbglog_HAVE && 0
5487IMPORTPROC DumpRTC(void);
5488#endif
5489
5490LOCALPROC UnInitOSGLU(void)
5491{
5492#if dbglog_HAVE && 0
5493 DoDumpTable();
5494#endif
5495#if dbglog_HAVE && 0
5496 DumpRTC();
5497#endif
5498
5499 if (MacMsgDisplayed) {
5500 MacMsgDisplayOff();
5501 }
5502
5503#if EmLocalTalk
5504 UnInitLocalTalk();
5505#endif
5506
5507#if MayFullScreen
5508 UngrabMachine();
5509#endif
5510
5511#if MySoundEnabled
5512 MySound_Stop();
5513#endif
5514
5515 CloseAglCurrentContext();
5516 CloseMainWindow();
5517
5518#if MayFullScreen
5519 My_ShowMenuBar();
5520#endif
5521
5522#if IncludePbufs
5523 UnInitPbufs();
5524#endif
5525 UnInitDrives();
5526
5527 if (! gTrueBackgroundFlag) {
5528 CheckSavedMacMsg();
5529 }
5530
5531 UnInstallOurEventHandlers();
5532
5533#if dbglog_HAVE
5534 dbglog_close();
5535#endif
5536
5537 UnInitMyApplInfo();
5538
5539 ForceShowCursor();
5540}
5541
5542LOCALPROC ZapOSGLUVars(void)
5543{
5544 InitDrives();
5545 ZapWinStateVars();
5546}
5547
5548/* adapted from Apple "Technical Q&A QA1061" */
5549
5550static pascal OSStatus EventLoopEventHandler(
5551 EventHandlerCallRef inHandlerCallRef, EventRef inEvent,
5552 void *inUserData)
5553/*
5554 This code contains the standard Carbon event dispatch loop,
5555 as per "Inside Macintosh: Handling Carbon Events", Listing 3-10,
5556 except:
5557
5558 o this loop supports yielding to cooperative threads based on the
5559 application maintaining the gNumberOfRunningThreads global
5560 variable, and
5561
5562 o it also works around a problem with the Inside Macintosh code
5563 which unexpectedly quits when run on traditional Mac OS 9.
5564
5565 See RunApplicationEventLoopWithCooperativeThreadSupport for
5566 an explanation of why this is inside a Carbon event handler.
5567
5568 The code in Inside Mac has a problem in that it quits the
5569 event loop when ReceiveNextEvent returns an error. This is
5570 wrong because ReceiveNextEvent can return eventLoopQuitErr
5571 when you call WakeUpProcess on traditional Mac OS. So, rather
5572 than relying on an error from ReceiveNextEvent, this routine tracks
5573 whether the application is really quitting by installing a
5574 customer handler for the kEventClassApplication/kEventAppQuit
5575 Carbon event. All the custom handler does is call through
5576 to the previous handler and, if it returns noErr (which indicates
5577 the application is quitting, it sets quitNow so that our event
5578 loop quits.
5579
5580 Note that this approach continues to support
5581 QuitApplicationEventLoop, which is a simple wrapper that just posts
5582 a kEventClassApplication/kEventAppQuit event to the event loop.
5583*/
5584{
5585 UnusedParam(inHandlerCallRef);
5586 UnusedParam(inEvent);
5587 UnusedParam(inUserData);
5588
5589 ProgramMain();
5590 QuitApplicationEventLoop();
5591
5592 return noErr;
5593}
5594
5595LOCALPROC RunApplicationEventLoopWithCooperativeThreadSupport(void)
5596/*
5597 A reimplementation of RunApplicationEventLoop that supports
5598 yielding time to cooperative threads.
5599*/
5600{
5601 static const EventTypeSpec eventSpec = {'KWIN', 'KWIN'};
5602 EventHandlerUPP theEventLoopEventHandlerUPP = nil;
5603 EventHandlerRef installedHandler = NULL;
5604 EventRef dummyEvent = nil;
5605
5606/*
5607 Install EventLoopEventHandler, create a dummy event and post it,
5608 and then call RunApplicationEventLoop. The rationale for this
5609 is as follows: We want to unravel RunApplicationEventLoop so
5610 that we can can yield to cooperative threads. In fact, the
5611 core code for RunApplicationEventLoop is pretty easy (you
5612 can see it above in EventLoopEventHandler). However, if you
5613 just execute this code you miss out on all the standard event
5614 handlers. These are relatively easy to reproduce (handling
5615 the quit event and so on), but doing so is a pain because
5616 a) it requires a bunch boilerplate code, and b) if Apple
5617 extends the list of standard event handlers, your application
5618 wouldn't benefit. So, we execute our event loop from within
5619 a Carbon event handler that we cause to be executed by
5620 explicitly posting an event to our event loop. Thus, the
5621 standard event handlers are installed while our event loop runs.
5622*/
5623 if (nil == (theEventLoopEventHandlerUPP
5624 = NewEventHandlerUPP(EventLoopEventHandler)))
5625 {
5626 /* fail */
5627 } else
5628 if (noErr != InstallEventHandler(GetApplicationEventTarget(),
5629 theEventLoopEventHandlerUPP, 1, &eventSpec, nil,
5630 &installedHandler))
5631 {
5632 /* fail */
5633 } else
5634 if (noErr != MacCreateEvent(nil, 'KWIN', 'KWIN',
5635 GetCurrentEventTime(), kEventAttributeNone,
5636 &dummyEvent))
5637 {
5638 /* fail */
5639 } else
5640 if (noErr != PostEventToQueue(GetMainEventQueue(),
5641 dummyEvent, kEventPriorityHigh))
5642 {
5643 /* fail */
5644 } else
5645 {
5646 RunApplicationEventLoop();
5647 }
5648
5649 if (nil != dummyEvent) {
5650 ReleaseEvent(dummyEvent);
5651 }
5652
5653 if (NULL != installedHandler) {
5654 (void) RemoveEventHandler(installedHandler);
5655 }
5656}
5657
5658int main(void)
5659{
5660 ZapOSGLUVars();
5661 if (InitOSGLU()) {
5662 RunApplicationEventLoopWithCooperativeThreadSupport();
5663 }
5664 UnInitOSGLU();
5665
5666 return 0;
5667}
5668
5669#endif /* WantOSGLUOSX */