1/*****************************************************************************\
2     Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3                This file is licensed under the Snes9x License.
4   For further information, consult the LICENSE file in the root directory.
5\*****************************************************************************/
6
7/***********************************************************************************
8  SNES9X for Mac OS (c) Copyright John Stiles
9
10  Snes9x for Mac OS X
11
12  (c) Copyright 2001 - 2011  zones
13  (c) Copyright 2002 - 2005  107
14  (c) Copyright 2002         PB1400c
15  (c) Copyright 2004         Alexander and Sander
16  (c) Copyright 2004 - 2005  Steven Seeger
17  (c) Copyright 2005         Ryan Vogt
18 ***********************************************************************************/
19
20
21#import "snes9x.h"
22#import "memmap.h"
23#import "snapshot.h"
24#import "movie.h"
25
26#import <wchar.h>
27#import <Cocoa/Cocoa.h>
28#import <objc/objc-runtime.h>
29
30#import "mac-cocoatools.h"
31#import "mac-prefix.h"
32#import "mac-dialog.h"
33#import "mac-os.h"
34#import "mac-quicktime.h"
35#import "mac-screenshot.h"
36#import "mac-snes9x.h"
37#import "mac-stringtools.h"
38#import "mac-cart.h"
39
40typedef struct
41{
42	NavDialogRef	nref;
43	WindowRef		parent;
44	FSRef			ref;
45	Boolean			reply;
46	char			name[PATH_MAX + 1];
47#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
48	IBNibRef		customNib;
49	WindowRef		customWindow;
50	HIViewRef		customPane;
51	short			customWidth, customHeight;
52#endif
53}	NavState;
54
55extern wchar_t	macRecordWChar[MOVIE_MAX_METADATA];
56
57static NavEventUPP			gSheetEventUPP;
58static NavObjectFilterUPP	gSheetFilterUPP;
59static NavState				gSheetNav;
60static NSAutoreleasePool	*gPool;
61static NSPopUpButton		*gPopM, *gPopI, *gPopV, *gPopH;
62
63static pascal void NavGenericOpenEventHandler (const NavEventCallbackMessage, NavCBRecPtr, NavCallBackUserData);
64static pascal void NavGenericSaveEventHandler (const NavEventCallbackMessage, NavCBRecPtr, NavCallBackUserData);
65static pascal Boolean NavOpenCartFilter (AEDesc *, void *, NavCallBackUserData, NavFilterModes);
66static pascal Boolean NavDefrostFromFilter (AEDesc *, void *, NavCallBackUserData, NavFilterModes);
67static pascal Boolean NavPlayMovieFromFilter (AEDesc *, void *, NavCallBackUserData, NavFilterModes);
68#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
69static void GlobalPointToWindowLocalPoint (Point *, WindowRef);
70static pascal void NavOpenCartEventHandler (const NavEventCallbackMessage, NavCBRecPtr, NavCallBackUserData);
71static pascal void NavRecordMovieToEventHandler (const NavEventCallbackMessage, NavCBRecPtr, NavCallBackUserData);
72static pascal void NavPlayMovieFromEventHandler (const NavEventCallbackMessage, NavCBRecPtr, NavCallBackUserData);
73static pascal void NavQTMovieRecordToEventHandler (const NavEventCallbackMessage, NavCBRecPtr, NavCallBackUserData);
74#endif
75#ifdef MAC_TIGER_PANTHER_SUPPORT
76static pascal Boolean NavDefrostFromPreview (NavCBRecPtr, NavCallBackUserData);
77static pascal Boolean NavPlayMovieFromPreview (NavCBRecPtr, NavCallBackUserData);
78#endif
79
80
81@interface NavController : NSObject
82
83- (id) init;
84- (void) dealloc;
85- (IBAction) handleCompressButton: (id) sender;
86
87@end
88
89@implementation NavController
90
91- (id) init
92{
93	self = [super init];
94	return (self);
95}
96
97- (void) dealloc
98{
99	[super dealloc];
100}
101
102- (IBAction) handleCompressButton: (id) sender
103{
104	MacQTVideoConfig();
105}
106
107@end
108
109@interface NSView (HICocoaViewDummy)
110- (void) setNeedsDisplayOnHICocoaViewDummy;
111@end
112
113@implementation NSView (HICocoaViewDummy)
114+ (void) initialize
115{
116	/* Add a dummy instance method to make compatible with 10.10 or later */
117	if (self == [NSView self]) {
118		SEL sel = @selector(setNeedsDisplayOnHICocoaView);
119		if (![NSView instancesRespondToSelector:sel]) {
120			Method m = class_getInstanceMethod([NSView class], @selector(setNeedsDisplayOnHICocoaViewDummy));
121			IMP imp = method_getImplementation(m);
122			class_addMethod([NSView class], sel, imp, "v@");
123		}
124	}
125}
126- (void) setNeedsDisplayOnHICocoaViewDummy{}
127@end
128
129
130bool8 NavOpenROMImage (FSRef *ref)
131{
132	OSStatus					err;
133	NavDialogCreationOptions	dialogOptions;
134	NavEventUPP					eventUPP;
135	NavObjectFilterUPP			filterUPP;
136	NavState					nav;
137
138#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
139	if (systemVersion < 0x1060)
140	{
141		HIViewID	cid = { 'PANE', 1000 };
142		Rect		rct;
143
144		err = CreateNibReference(kMacS9XCFString, &(nav.customNib));
145		if (err)
146			return (false);
147
148		err = CreateWindowFromNib(nav.customNib, CFSTR("OpenROM"), &(nav.customWindow));
149		if (err)
150		{
151			DisposeNibReference(nav.customNib);
152			return (false);
153		}
154
155		GetWindowBounds(nav.customWindow, kWindowContentRgn, &rct);
156		nav.customWidth  = rct.right  - rct.left;
157		nav.customHeight = rct.bottom - rct.top;
158
159		HIViewFindByID(HIViewGetRoot(nav.customWindow), cid, &(nav.customPane));
160	}
161#endif
162
163	err = NavGetDefaultDialogCreationOptions(&dialogOptions);
164	dialogOptions.optionFlags &= ~kNavAllowMultipleFiles;
165	dialogOptions.preferenceKey = 3;
166	dialogOptions.clientName = kMacS9XCFString;
167	dialogOptions.windowTitle = CFCopyLocalizedString(CFSTR("OpenROMMes"), "Open");
168	dialogOptions.modality = kWindowModalityAppModal;
169	dialogOptions.parentWindow = NULL;
170	nav.parent = NULL;
171
172#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
173	eventUPP = NewNavEventUPP((systemVersion < 0x1060) ? NavOpenCartEventHandler : NavGenericOpenEventHandler);
174#else
175	eventUPP = NewNavEventUPP(NavGenericOpenEventHandler);
176#endif
177	filterUPP = NewNavObjectFilterUPP(NavOpenCartFilter);
178
179	err = NavCreateChooseFileDialog(&dialogOptions, NULL, eventUPP, NULL, filterUPP, &nav, &(nav.nref));
180	if (err == noErr)
181	{
182		if (systemVersion >= 0x1060)
183		{
184			NSAutoreleasePool	*pool;
185			NSView				*view;
186			NSTextField			*txtM, *txtI, *txtV, *txtH;
187			NSPopUpButton		*popM, *popI, *popV, *popH;
188			NSArray				*aryM, *aryI, *aryV, *aryH;
189
190			pool = [[NSAutoreleasePool alloc] init];
191
192			view = [[[NSView alloc] initWithFrame: NSMakeRect(0, 0, 433, 52)] autorelease];
193
194			aryM = [NSArray arrayWithObjects: NSLocalizedString(@"OpenROM5", @""), @"---", NSLocalizedString(@"OpenROM6", @""), NSLocalizedString(@"OpenROM7", @""), nil];
195			aryI = [NSArray arrayWithObjects: NSLocalizedString(@"OpenROM5", @""), @"---", NSLocalizedString(@"OpenROMa", @""), NSLocalizedString(@"OpenROMb", @""), NSLocalizedString(@"OpenROMc", @""), NSLocalizedString(@"OpenROMd", @""), nil];
196			aryV = [NSArray arrayWithObjects: NSLocalizedString(@"OpenROM5", @""), @"---", NSLocalizedString(@"OpenROM8", @""), NSLocalizedString(@"OpenROM9", @""), nil];
197			aryH = [NSArray arrayWithObjects: NSLocalizedString(@"OpenROM5", @""), @"---", NSLocalizedString(@"OpenROMe", @""), NSLocalizedString(@"OpenROMf", @""), nil];
198
199			CocoaAddStatTextToView(view, @"OpenROM1",   5, 32,  84, 14, &txtM);
200			CocoaAddStatTextToView(view, @"OpenROM3", 214, 32,  96, 14, &txtI);
201			CocoaAddStatTextToView(view, @"OpenROM2",   5,  7,  84, 14, &txtV);
202			CocoaAddStatTextToView(view, @"OpenROM4", 214,  7,  96, 14, &txtH);
203			CocoaAddPopUpBtnToView(view, aryM,         91, 27, 116, 22, &popM);
204			CocoaAddPopUpBtnToView(view, aryI,        312, 27, 116, 22, &popI);
205			CocoaAddPopUpBtnToView(view, aryV,         91,  2, 116, 22, &popV);
206			CocoaAddPopUpBtnToView(view, aryH,        312,  2, 116, 22, &popH);
207
208			[txtM setAlignment: NSRightTextAlignment];
209			[txtI setAlignment: NSRightTextAlignment];
210			[txtV setAlignment: NSRightTextAlignment];
211			[txtH setAlignment: NSRightTextAlignment];
212
213			[popM selectItemAtIndex: romDetect       ];
214			[popI selectItemAtIndex: interleaveDetect];
215			[popV selectItemAtIndex: videoDetect     ];
216			[popH selectItemAtIndex: headerDetect    ];
217
218			[(NSOpenPanel *) nav.nref setAccessoryView: view];
219
220			err = NavDialogRun(nav.nref);
221			if (err)
222				NavDialogDispose(nav.nref);
223
224			romDetect        = [popM indexOfSelectedItem];
225			interleaveDetect = [popI indexOfSelectedItem];
226			videoDetect      = [popV indexOfSelectedItem];
227			headerDetect     = [popH indexOfSelectedItem];
228
229			[pool release];
230		}
231	#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
232		else
233		{
234			err = NavDialogRun(nav.nref);
235			if (err)
236				NavDialogDispose(nav.nref);
237		}
238	#endif
239	}
240
241	DisposeNavObjectFilterUPP(filterUPP);
242	DisposeNavEventUPP(eventUPP);
243
244	CFRelease(dialogOptions.windowTitle);
245
246#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
247	if (systemVersion < 0x1060)
248	{
249		CFRelease(nav.customWindow);
250		DisposeNibReference(nav.customNib);
251	}
252#endif
253
254	if (err)
255		return (false);
256	else
257	{
258		if (nav.reply)
259		{
260			*ref = nav.ref;
261			return (true);
262		}
263		else
264			return (false);
265	}
266}
267
268bool8 NavBeginOpenROMImageSheet (WindowRef parent, CFStringRef mes)
269{
270	OSStatus					err;
271	NavDialogCreationOptions	dialogOptions;
272
273#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
274	if (systemVersion < 0x1060)
275	{
276		HIViewID	cid = { 'PANE', 1000 };
277		Rect		rct;
278
279		err = CreateNibReference(kMacS9XCFString, &(gSheetNav.customNib));
280		if (err)
281			return (false);
282
283		err = CreateWindowFromNib(gSheetNav.customNib, CFSTR("OpenROM"), &(gSheetNav.customWindow));
284		if (err)
285		{
286			DisposeNibReference(gSheetNav.customNib);
287			return (false);
288		}
289
290		GetWindowBounds(gSheetNav.customWindow, kWindowContentRgn, &rct);
291		gSheetNav.customWidth  = rct.right  - rct.left;
292		gSheetNav.customHeight = rct.bottom - rct.top;
293
294		HIViewFindByID(HIViewGetRoot(gSheetNav.customWindow), cid, &(gSheetNav.customPane));
295	}
296#endif
297
298	err = NavGetDefaultDialogCreationOptions(&dialogOptions);
299	dialogOptions.optionFlags &= ~kNavAllowMultipleFiles;
300	dialogOptions.preferenceKey = 3;
301	dialogOptions.clientName = kMacS9XCFString;
302	dialogOptions.windowTitle = CFCopyLocalizedString(CFSTR("OpenROMMes"), "Open");
303	dialogOptions.message = mes;
304	dialogOptions.modality = kWindowModalityWindowModal;
305	dialogOptions.parentWindow = parent;
306	gSheetNav.parent = parent;
307
308#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
309	gSheetEventUPP = NewNavEventUPP((systemVersion < 0x1060) ? NavOpenCartEventHandler : NavGenericOpenEventHandler);
310#else
311	gSheetEventUPP = NewNavEventUPP(NavGenericOpenEventHandler);
312#endif
313	gSheetFilterUPP = NewNavObjectFilterUPP(NavOpenCartFilter);
314
315	err = NavCreateChooseFileDialog(&dialogOptions, NULL, gSheetEventUPP, NULL, gSheetFilterUPP, &gSheetNav, &(gSheetNav.nref));
316	if (err == noErr)
317	{
318		if (systemVersion >= 0x1060)
319		{
320			NSView		*view;
321			NSTextField	*txtM, *txtI, *txtV, *txtH;
322			NSArray		*aryM, *aryI, *aryV, *aryH;
323
324			gPool = [[NSAutoreleasePool alloc] init];
325
326			view = [[[NSView alloc] initWithFrame: NSMakeRect(0, 0, 433, 52)] autorelease];
327
328			aryM = [NSArray arrayWithObjects: NSLocalizedString(@"OpenROM5", @""), @"---", NSLocalizedString(@"OpenROM6", @""), NSLocalizedString(@"OpenROM7", @""), nil];
329			aryI = [NSArray arrayWithObjects: NSLocalizedString(@"OpenROM5", @""), @"---", NSLocalizedString(@"OpenROMa", @""), NSLocalizedString(@"OpenROMb", @""), NSLocalizedString(@"OpenROMc", @""), NSLocalizedString(@"OpenROMd", @""), nil];
330			aryV = [NSArray arrayWithObjects: NSLocalizedString(@"OpenROM5", @""), @"---", NSLocalizedString(@"OpenROM8", @""), NSLocalizedString(@"OpenROM9", @""), nil];
331			aryH = [NSArray arrayWithObjects: NSLocalizedString(@"OpenROM5", @""), @"---", NSLocalizedString(@"OpenROMe", @""), NSLocalizedString(@"OpenROMf", @""), nil];
332
333			CocoaAddStatTextToView(view, @"OpenROM1",   5, 32,  84, 14, &txtM);
334			CocoaAddStatTextToView(view, @"OpenROM3", 214, 32,  96, 14, &txtI);
335			CocoaAddStatTextToView(view, @"OpenROM2",   5,  7,  84, 14, &txtV);
336			CocoaAddStatTextToView(view, @"OpenROM4", 214,  7,  96, 14, &txtH);
337			CocoaAddPopUpBtnToView(view, aryM,         91, 27, 116, 22, &gPopM);
338			CocoaAddPopUpBtnToView(view, aryI,        312, 27, 116, 22, &gPopI);
339			CocoaAddPopUpBtnToView(view, aryV,         91,  2, 116, 22, &gPopV);
340			CocoaAddPopUpBtnToView(view, aryH,        312,  2, 116, 22, &gPopH);
341
342			[txtM setAlignment: NSRightTextAlignment];
343			[txtI setAlignment: NSRightTextAlignment];
344			[txtV setAlignment: NSRightTextAlignment];
345			[txtH setAlignment: NSRightTextAlignment];
346
347			[gPopM selectItemAtIndex: romDetect       ];
348			[gPopI selectItemAtIndex: interleaveDetect];
349			[gPopV selectItemAtIndex: videoDetect     ];
350			[gPopH selectItemAtIndex: headerDetect    ];
351
352			[(NSOpenPanel *) gSheetNav.nref setAccessoryView: view];
353
354			err = NavDialogRun(gSheetNav.nref);
355			if (err)
356			{
357				[gPool release];
358				NavDialogDispose(gSheetNav.nref);
359				DisposeNavObjectFilterUPP(gSheetFilterUPP);
360				DisposeNavEventUPP(gSheetEventUPP);
361				CFRelease(dialogOptions.windowTitle);
362				return (false);
363			}
364		}
365	#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
366		else
367		{
368			err = NavDialogRun(gSheetNav.nref);
369			if (err)
370			{
371				NavDialogDispose(gSheetNav.nref);
372				DisposeNavObjectFilterUPP(gSheetFilterUPP);
373				DisposeNavEventUPP(gSheetEventUPP);
374				CFRelease(dialogOptions.windowTitle);
375				CFRelease(gSheetNav.customWindow);
376				DisposeNibReference(gSheetNav.customNib);
377				return (false);
378			}
379		}
380	#endif
381	}
382	else
383	{
384		DisposeNavObjectFilterUPP(gSheetFilterUPP);
385		DisposeNavEventUPP(gSheetEventUPP);
386		CFRelease(dialogOptions.windowTitle);
387	#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
388		if (systemVersion < 0x1060)
389		{
390			CFRelease(gSheetNav.customWindow);
391			DisposeNibReference(gSheetNav.customNib);
392		}
393	#endif
394		return (false);
395	}
396
397	CFRelease(dialogOptions.windowTitle);
398	return (true);
399}
400
401bool8 NavEndOpenROMImageSheet (FSRef *ref)
402{
403	if (systemVersion >= 0x1060)
404	{
405		romDetect        = [gPopM indexOfSelectedItem];
406		interleaveDetect = [gPopI indexOfSelectedItem];
407		videoDetect      = [gPopV indexOfSelectedItem];
408		headerDetect     = [gPopH indexOfSelectedItem];
409
410		[gPool release];
411	}
412
413	DisposeNavObjectFilterUPP(gSheetFilterUPP);
414	DisposeNavEventUPP(gSheetEventUPP);
415
416#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
417	if (systemVersion < 0x1060)
418	{
419		CFRelease(gSheetNav.customWindow);
420		DisposeNibReference(gSheetNav.customNib);
421	}
422#endif
423
424	if (gSheetNav.reply)
425	{
426		*ref = gSheetNav.ref;
427		return (true);
428	}
429	else
430		return (false);
431}
432
433bool8 NavFreezeTo (char *path)
434{
435	OSStatus					err;
436	NavDialogCreationOptions	dialogOptions;
437	NavEventUPP					eventUPP;
438	NavState					nav;
439	CFStringRef					numRef, romRef, baseRef;
440	CFMutableStringRef			mesRef, saveRef;
441	SInt32						replaceAt;
442	char						drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
443
444	_splitpath(Memory.ROMFilename, drive, dir, fname, ext);
445	romRef  = CFStringCreateWithCString(kCFAllocatorDefault, fname, kCFStringEncodingUTF8);
446	numRef  = CFCopyLocalizedString(CFSTR("FreezeToPos"), "1");
447	baseRef = CFCopyLocalizedString(CFSTR("FreezeToMes"), "Freeze");
448	mesRef  = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, baseRef);
449	saveRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, romRef);
450	replaceAt = CFStringGetIntValue(numRef);
451	CFStringReplace(mesRef, CFRangeMake(replaceAt - 1, 1), romRef);
452	CFStringAppendCString(saveRef, ".frz", CFStringGetSystemEncoding());
453
454	err = NavGetDefaultDialogCreationOptions(&dialogOptions);
455	dialogOptions.preferenceKey = 4;
456	dialogOptions.clientName = kMacS9XCFString;
457	dialogOptions.windowTitle = mesRef;
458	dialogOptions.saveFileName = saveRef;
459	dialogOptions.modality = kWindowModalityAppModal;
460	dialogOptions.parentWindow = NULL;
461	nav.parent = NULL;
462
463	eventUPP = NewNavEventUPP(NavGenericSaveEventHandler);
464
465	err = NavCreatePutFileDialog(&dialogOptions, 'SAVE', '~9X~', eventUPP, &nav, &(nav.nref));
466	if (err == noErr)
467	{
468		err = NavDialogRun(nav.nref);
469		if (err)
470			NavDialogDispose(nav.nref);
471	}
472
473	DisposeNavEventUPP(eventUPP);
474
475	CFRelease(saveRef);
476	CFRelease(mesRef);
477	CFRelease(baseRef);
478	CFRelease(numRef);
479	CFRelease(romRef);
480
481	if (err)
482		return (false);
483	else
484	{
485		if (nav.reply)
486		{
487			char	s[PATH_MAX + 1];
488
489			err = FSRefMakePath(&(nav.ref), (unsigned char *) s, PATH_MAX);
490			snprintf(path, PATH_MAX + 1, "%s%s%s", s, MAC_PATH_SEPARATOR, nav.name);
491
492			return (true);
493		}
494		else
495			return (false);
496	}
497}
498
499bool8 NavDefrostFrom (char *path)
500{
501	OSStatus					err;
502	NavDialogCreationOptions	dialogOptions;
503	NavEventUPP					eventUPP;
504	NavObjectFilterUPP			filterUPP;
505	NavState					nav;
506	CFStringRef					numRef, romRef, baseRef;
507	CFMutableStringRef			mesRef;
508	SInt32						replaceAt;
509	char						drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
510#ifdef MAC_TIGER_PANTHER_SUPPORT
511	NavPreviewUPP				previewUPP;
512#endif
513
514	_splitpath(Memory.ROMFilename, drive, dir, fname, ext);
515	romRef  = CFStringCreateWithCString(kCFAllocatorDefault, fname, kCFStringEncodingUTF8);
516	numRef  = CFCopyLocalizedString(CFSTR("DefrostFromPos"), "1");
517	baseRef = CFCopyLocalizedString(CFSTR("DefrostFromMes"), "Defrost");
518	mesRef  = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, baseRef);
519	replaceAt = CFStringGetIntValue(numRef);
520	CFStringReplace(mesRef, CFRangeMake(replaceAt - 1, 1), romRef);
521
522	err = NavGetDefaultDialogCreationOptions(&dialogOptions);
523	dialogOptions.optionFlags &= ~kNavAllowMultipleFiles;
524	dialogOptions.preferenceKey = 5;
525	dialogOptions.clientName = kMacS9XCFString;
526	dialogOptions.windowTitle = mesRef;
527	dialogOptions.modality = kWindowModalityAppModal;
528	dialogOptions.parentWindow = NULL;
529	nav.parent = NULL;
530
531	eventUPP = NewNavEventUPP(NavGenericOpenEventHandler);
532	filterUPP = NewNavObjectFilterUPP(NavDefrostFromFilter);
533#ifdef MAC_TIGER_PANTHER_SUPPORT
534	previewUPP = NewNavPreviewUPP(NavDefrostFromPreview);
535#endif
536
537#ifdef MAC_TIGER_PANTHER_SUPPORT
538	err = NavCreateChooseFileDialog(&dialogOptions, NULL, eventUPP, previewUPP, filterUPP, &nav, &(nav.nref));
539#else
540	err = NavCreateChooseFileDialog(&dialogOptions, NULL, eventUPP, NULL, filterUPP, &nav, &(nav.nref));
541#endif
542	if (err == noErr)
543	{
544		err = NavDialogRun(nav.nref);
545		if (err)
546			NavDialogDispose(nav.nref);
547	}
548
549#ifdef MAC_TIGER_PANTHER_SUPPORT
550	DisposeNavPreviewUPP(previewUPP);
551#endif
552	DisposeNavObjectFilterUPP(filterUPP);
553	DisposeNavEventUPP(eventUPP);
554
555	CFRelease(mesRef);
556	CFRelease(baseRef);
557	CFRelease(numRef);
558	CFRelease(romRef);
559
560	if (err)
561		return (false);
562	else
563	{
564		if (nav.reply)
565		{
566			err = FSRefMakePath(&(nav.ref), (unsigned char *) path, PATH_MAX);
567			return (true);
568		}
569		else
570			return (false);
571	}
572}
573
574bool8 NavRecordMovieTo (char *path)
575{
576	OSStatus					err;
577	NavDialogCreationOptions	dialogOptions;
578	NavEventUPP					eventUPP;
579	NavState					nav;
580	CFStringRef					numRef, romRef, baseRef;
581	CFMutableStringRef			mesRef, saveRef;
582	SInt32						replaceAt;
583	char						drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
584
585#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
586	if (systemVersion < 0x1060)
587	{
588		HIViewID	cid = { 'PANE', 1000 };
589		Rect		rct;
590
591		err = CreateNibReference(kMacS9XCFString, &(nav.customNib));
592		if (err)
593			return (false);
594
595		err = CreateWindowFromNib(nav.customNib, CFSTR("RecordSMV"), &(nav.customWindow));
596		if (err)
597		{
598			DisposeNibReference(nav.customNib);
599			return (false);
600		}
601
602		GetWindowBounds(nav.customWindow, kWindowContentRgn, &rct);
603		nav.customWidth  = rct.right  - rct.left;
604		nav.customHeight = rct.bottom - rct.top;
605
606		HIViewFindByID(HIViewGetRoot(nav.customWindow), cid, &(nav.customPane));
607	}
608#endif
609
610	_splitpath(Memory.ROMFilename, drive, dir, fname, ext);
611	romRef  = CFStringCreateWithCString(kCFAllocatorDefault, fname, kCFStringEncodingUTF8);
612	numRef  = CFCopyLocalizedString(CFSTR("RecordToPos"), "1");
613	baseRef = CFCopyLocalizedString(CFSTR("RecordToMes"), "Record");
614	mesRef  = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, baseRef);
615	saveRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, romRef);
616	replaceAt = CFStringGetIntValue(numRef);
617	CFStringReplace(mesRef, CFRangeMake(replaceAt - 1, 1), romRef);
618	CFStringAppendCString(saveRef, ".smv", CFStringGetSystemEncoding());
619
620	err = NavGetDefaultDialogCreationOptions(&dialogOptions);
621	dialogOptions.preferenceKey = 6;
622	dialogOptions.clientName = kMacS9XCFString;
623	dialogOptions.windowTitle = mesRef;
624	dialogOptions.saveFileName = saveRef;
625	dialogOptions.modality = kWindowModalityAppModal;
626	dialogOptions.parentWindow = NULL;
627	nav.parent = NULL;
628
629#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
630	eventUPP = NewNavEventUPP((systemVersion < 0x1060) ? NavRecordMovieToEventHandler : NavGenericSaveEventHandler);
631#else
632	eventUPP = NewNavEventUPP(NavGenericSaveEventHandler);
633#endif
634
635	err = NavCreatePutFileDialog(&dialogOptions, 'SMOV', '~9X~', eventUPP, &nav, &(nav.nref));
636	if (err == noErr)
637	{
638		if (systemVersion >= 0x1060)
639		{
640			NSAutoreleasePool	*pool;
641			NSView				*view;
642			NSTextField			*text;
643			NSButton			*cb1p, *cb2p, *cb3p, *cb4p, *cb5p, *cbre;
644			NSString			*comment;
645
646			pool = [[NSAutoreleasePool alloc] init];
647
648			view = [[[NSView alloc] initWithFrame: NSMakeRect(0, 0, 433, 54)] autorelease];
649
650			CocoaAddStatTextToView(view, @"RecordSMV6",   5, 33, 104, 14, NULL);
651			CocoaAddStatTextToView(view, @"RecordSMV7",   5,  8,  63, 14, NULL);
652			CocoaAddEditTextToView(view, @"",            74,  6, 351, 19, &text);
653			CocoaAddCheckBoxToView(view, @"RecordSMV1", 112, 31,  29, 18, &cb1p);
654			CocoaAddCheckBoxToView(view, @"RecordSMV2", 150, 31,  29, 18, &cb2p);
655			CocoaAddCheckBoxToView(view, @"RecordSMV3", 188, 31,  29, 18, &cb3p);
656			CocoaAddCheckBoxToView(view, @"RecordSMV4", 226, 31,  29, 18, &cb4p);
657			CocoaAddCheckBoxToView(view, @"RecordSMV5", 264, 31,  29, 18, &cb5p);
658			CocoaAddCheckBoxToView(view, @"RecordSMV8", 356, 31,  51, 18, &cbre);
659
660			[cb1p setState: (macRecordFlag & (1 << 0) ? NSOnState : NSOffState)];
661			[cb2p setState: (macRecordFlag & (1 << 1) ? NSOnState : NSOffState)];
662			[cb3p setState: (macRecordFlag & (1 << 2) ? NSOnState : NSOffState)];
663			[cb4p setState: (macRecordFlag & (1 << 3) ? NSOnState : NSOffState)];
664			[cb5p setState: (macRecordFlag & (1 << 4) ? NSOnState : NSOffState)];
665			[cbre setState: (macRecordFlag & (1 << 5) ? NSOnState : NSOffState)];
666
667			[(NSOpenPanel *) nav.nref setAccessoryView: view];
668
669			err = NavDialogRun(nav.nref);
670			if (err)
671				NavDialogDispose(nav.nref);
672
673			macRecordFlag  = 0;
674			macRecordFlag |= ((([cb1p state] == NSOnState) ? 1 : 0) << 0);
675			macRecordFlag |= ((([cb2p state] == NSOnState) ? 1 : 0) << 1);
676			macRecordFlag |= ((([cb3p state] == NSOnState) ? 1 : 0) << 2);
677			macRecordFlag |= ((([cb4p state] == NSOnState) ? 1 : 0) << 3);
678			macRecordFlag |= ((([cb5p state] == NSOnState) ? 1 : 0) << 4);
679			macRecordFlag |= ((([cbre state] == NSOnState) ? 1 : 0) << 5);
680
681			comment = [text stringValue];
682			if (comment)
683			{
684				NSUInteger	cflen;
685				unichar		unistr[MOVIE_MAX_METADATA];
686
687				cflen = [comment length];
688				if (cflen > MOVIE_MAX_METADATA - 1)
689					cflen = MOVIE_MAX_METADATA - 1;
690
691				[comment getCharacters: unistr range: NSMakeRange(0, cflen)];
692
693				for (unsigned i = 0; i < cflen; i++)
694					macRecordWChar[i] = (wchar_t) unistr[i];
695				macRecordWChar[cflen] = 0;
696			}
697			else
698				macRecordWChar[0] = 0;
699
700			[pool release];
701		}
702	#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
703		else
704		{
705			err = NavDialogRun(nav.nref);
706			if (err)
707				NavDialogDispose(nav.nref);
708		}
709	#endif
710	}
711
712	DisposeNavEventUPP(eventUPP);
713
714	CFRelease(saveRef);
715	CFRelease(mesRef);
716	CFRelease(baseRef);
717	CFRelease(numRef);
718	CFRelease(romRef);
719
720#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
721	if (systemVersion < 0x1060)
722	{
723		CFRelease(nav.customWindow);
724		DisposeNibReference(nav.customNib);
725	}
726#endif
727
728	if (err)
729		return (false);
730	else
731	{
732		if (nav.reply)
733		{
734			char	s[PATH_MAX + 1];
735
736			err = FSRefMakePath(&(nav.ref), (unsigned char *) s, PATH_MAX);
737			snprintf(path, PATH_MAX + 1, "%s%s%s", s, MAC_PATH_SEPARATOR, nav.name);
738
739			return (true);
740		}
741		else
742			return (false);
743	}
744}
745
746bool8 NavPlayMovieFrom (char *path)
747{
748	OSStatus					err;
749	NavDialogCreationOptions	dialogOptions;
750	NavEventUPP					eventUPP;
751	NavObjectFilterUPP			filterUPP;
752	NavState					nav;
753	CFStringRef					numRef, romRef, baseRef;
754	CFMutableStringRef			mesRef;
755	SInt32						replaceAt;
756	char						drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
757#ifdef MAC_TIGER_PANTHER_SUPPORT
758	NavPreviewUPP				previewUPP;
759#endif
760
761#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
762	if (systemVersion < 0x1060)
763	{
764		HIViewID	cid = { 'PANE', 1000 };
765		Rect		rct;
766
767		err = CreateNibReference(kMacS9XCFString, &(nav.customNib));
768		if (err)
769			return (false);
770
771		err = CreateWindowFromNib(nav.customNib, CFSTR("PlaySMV"), &(nav.customWindow));
772		if (err)
773		{
774			DisposeNibReference(nav.customNib);
775			return (false);
776		}
777
778		GetWindowBounds(nav.customWindow, kWindowContentRgn, &rct);
779		nav.customWidth  = rct.right  - rct.left;
780		nav.customHeight = rct.bottom - rct.top;
781
782		HIViewFindByID(HIViewGetRoot(nav.customWindow), cid, &(nav.customPane));
783	}
784#endif
785
786	_splitpath(Memory.ROMFilename, drive, dir, fname, ext);
787	romRef  = CFStringCreateWithCString(kCFAllocatorDefault, fname, kCFStringEncodingUTF8);
788	numRef  = CFCopyLocalizedString(CFSTR("PlayFromPos"), "1");
789	baseRef = CFCopyLocalizedString(CFSTR("PlayFromMes"), "Play");
790	mesRef  = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, baseRef);
791	replaceAt = CFStringGetIntValue(numRef);
792	CFStringReplace(mesRef, CFRangeMake(replaceAt - 1, 1), romRef);
793
794	err = NavGetDefaultDialogCreationOptions(&dialogOptions);
795	dialogOptions.optionFlags &= ~kNavAllowMultipleFiles;
796	dialogOptions.preferenceKey = 6;
797	dialogOptions.clientName = kMacS9XCFString;
798	dialogOptions.windowTitle = mesRef;
799	dialogOptions.modality = kWindowModalityAppModal;
800	dialogOptions.parentWindow = NULL;
801	nav.parent = NULL;
802
803#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
804	eventUPP = NewNavEventUPP((systemVersion < 0x1060) ? NavPlayMovieFromEventHandler : NavGenericOpenEventHandler);
805#else
806	eventUPP = NewNavEventUPP(NavGenericOpenEventHandler);
807#endif
808	filterUPP = NewNavObjectFilterUPP(NavPlayMovieFromFilter);
809#ifdef MAC_TIGER_PANTHER_SUPPORT
810	previewUPP = NewNavPreviewUPP(NavPlayMovieFromPreview);
811#endif
812
813#ifdef MAC_TIGER_PANTHER_SUPPORT
814	err = NavCreateChooseFileDialog(&dialogOptions, NULL, eventUPP, previewUPP, filterUPP, &nav, &(nav.nref));
815#else
816	err = NavCreateChooseFileDialog(&dialogOptions, NULL, eventUPP, NULL, filterUPP, &nav, &(nav.nref));
817#endif
818	if (err == noErr)
819	{
820		if (systemVersion >= 0x1060)
821		{
822			NSAutoreleasePool	*pool;
823			NSView				*view;
824			NSButton			*cbro, *cbqt;
825
826			pool = [[NSAutoreleasePool alloc] init];
827
828			view = [[[NSView alloc] initWithFrame: NSMakeRect(0, 0, 326, 29)] autorelease];
829
830			CocoaAddCheckBoxToView(view, @"PlaySMV1",   5, 6,  76, 18, &cbro);
831			CocoaAddCheckBoxToView(view, @"PlaySMV2", 100, 6, 220, 18, &cbqt);
832
833			[cbro setState: (macPlayFlag & (1 << 0) ? NSOnState : NSOffState)];
834			[cbqt setState: (macPlayFlag & (1 << 1) ? NSOnState : NSOffState)];
835
836			[(NSOpenPanel *) nav.nref setAccessoryView: view];
837
838			err = NavDialogRun(nav.nref);
839			if (err)
840				NavDialogDispose(nav.nref);
841
842			macPlayFlag  = 0;
843			macPlayFlag |= ((([cbro state] == NSOnState) ? 1 : 0) << 0);
844			macPlayFlag |= ((([cbqt state] == NSOnState) ? 1 : 0) << 1);
845
846			[pool release];
847		}
848	#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
849		else
850		{
851			err = NavDialogRun(nav.nref);
852			if (err)
853				NavDialogDispose(nav.nref);
854		}
855	#endif
856	}
857
858#ifdef MAC_TIGER_PANTHER_SUPPORT
859	DisposeNavPreviewUPP(previewUPP);
860#endif
861	DisposeNavObjectFilterUPP(filterUPP);
862	DisposeNavEventUPP(eventUPP);
863
864	CFRelease(mesRef);
865	CFRelease(baseRef);
866	CFRelease(numRef);
867	CFRelease(romRef);
868
869#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
870	if (systemVersion < 0x1060)
871	{
872		CFRelease(nav.customWindow);
873		DisposeNibReference(nav.customNib);
874	}
875#endif
876
877	if (err)
878		return (false);
879	else
880	{
881		if (nav.reply)
882		{
883			err = FSRefMakePath(&(nav.ref), (unsigned char *) path, PATH_MAX);
884			return (true);
885		}
886		else
887			return (false);
888	}
889}
890
891bool8 NavQTMovieRecordTo (char *path)
892{
893	OSStatus					err;
894	NavDialogCreationOptions	dialogOptions;
895	NavEventUPP					eventUPP;
896	NavState					nav;
897	CFStringRef					numRef, romRef, baseRef;
898	CFMutableStringRef			mesRef, saveRef;
899	SInt32						replaceAt;
900	char						drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
901
902#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
903	if (systemVersion < 0x1060)
904	{
905		HIViewID	cid = { 'PANE', 1000 };
906		Rect		rct;
907
908		err = CreateNibReference(kMacS9XCFString, &(nav.customNib));
909		if (err)
910			return (false);
911
912		err = CreateWindowFromNib(nav.customNib, CFSTR("QTMovie"), &(nav.customWindow));
913		if (err)
914		{
915			DisposeNibReference(nav.customNib);
916			return (false);
917		}
918
919		GetWindowBounds(nav.customWindow, kWindowContentRgn, &rct);
920		nav.customWidth  = rct.right  - rct.left;
921		nav.customHeight = rct.bottom - rct.top;
922
923		HIViewFindByID(HIViewGetRoot(nav.customWindow), cid, &(nav.customPane));
924	}
925#endif
926
927	_splitpath(Memory.ROMFilename, drive, dir, fname, ext);
928	romRef  = CFStringCreateWithCString(kCFAllocatorDefault, fname, kCFStringEncodingUTF8);
929	numRef  = CFCopyLocalizedString(CFSTR("QTRecordPos"), "1");
930	baseRef = CFCopyLocalizedString(CFSTR("QTRecordMes"), "QT");
931	mesRef  = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, baseRef);
932	saveRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, romRef);
933	replaceAt = CFStringGetIntValue(numRef);
934	CFStringReplace(mesRef, CFRangeMake(replaceAt - 1, 1), romRef);
935	CFStringAppendCString(saveRef, ".mov", CFStringGetSystemEncoding());
936
937	err = NavGetDefaultDialogCreationOptions(&dialogOptions);
938	dialogOptions.preferenceKey = 7;
939	dialogOptions.clientName = kMacS9XCFString;
940	dialogOptions.windowTitle = mesRef;
941	dialogOptions.saveFileName = saveRef;
942	dialogOptions.modality = kWindowModalityAppModal;
943	dialogOptions.parentWindow = NULL;
944	nav.parent = NULL;
945
946#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
947	eventUPP = NewNavEventUPP((systemVersion < 0x1060) ? NavQTMovieRecordToEventHandler : NavGenericSaveEventHandler);
948#else
949	eventUPP = NewNavEventUPP(NavGenericSaveEventHandler);
950#endif
951
952	err = NavCreatePutFileDialog(&dialogOptions, 'MooV', 'TVOD', eventUPP, &nav, &(nav.nref));
953	if (err == noErr)
954	{
955		if (systemVersion >= 0x1060)
956		{
957			NSAutoreleasePool	*pool;
958			NSView				*view;
959			NSPopUpButton		*fpop;
960			NSButton			*cbds, *cbov, *comp;
961			NSArray				*array;
962			NavController		*controller;
963
964			pool = [[NSAutoreleasePool alloc] init];
965
966			controller = [[[NavController alloc] init] autorelease];
967			view = [[[NSView alloc] initWithFrame: NSMakeRect(0, 0, 433, 31)] autorelease];
968
969			array = [NSArray arrayWithObjects: @"0", @"1", @"2", @"3", @"4", @"5", nil];
970			CocoaAddStatTextToView(view, @"QTRecord3", 185, 9,  70, 14, NULL);
971			CocoaAddCheckBoxToView(view, @"QTRecord1",   5, 7,  85, 18, &cbds);
972			CocoaAddCheckBoxToView(view, @"QTRecord2",  97, 7,  71, 18, &cbov);
973			CocoaAddMPushBtnToView(view, @"QTRecord4", 313, 1, 117, 28, &comp);
974			CocoaAddPopUpBtnToView(view, array,        255, 4,  50, 22, &fpop);
975
976			[cbds setState: (macQTMovFlag & (1 << 0) ? NSOnState : NSOffState)];
977			[cbov setState: (macQTMovFlag & (1 << 1) ? NSOnState : NSOffState)];
978			[fpop selectItemAtIndex: (macQTMovFlag >> 8)];
979
980			[comp setTarget: controller];
981			[comp setAction: @selector(handleCompressButton:)];
982
983			[(NSOpenPanel *) nav.nref setAccessoryView: view];
984
985			err = NavDialogRun(nav.nref);
986			if (err)
987				NavDialogDispose(nav.nref);
988
989			macQTMovFlag  = 0;
990			macQTMovFlag |= ((([cbds state] == NSOnState) ? 1 : 0) << 0);
991			macQTMovFlag |= ((([cbov state] == NSOnState) ? 1 : 0) << 1);
992			macQTMovFlag |= ([fpop indexOfSelectedItem] << 8);
993
994			[pool release];
995		}
996	#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
997		else
998		{
999			err = NavDialogRun(nav.nref);
1000			if (err)
1001				NavDialogDispose(nav.nref);
1002		}
1003	#endif
1004	}
1005
1006	DisposeNavEventUPP(eventUPP);
1007
1008	CFRelease(saveRef);
1009	CFRelease(mesRef);
1010	CFRelease(baseRef);
1011	CFRelease(numRef);
1012	CFRelease(romRef);
1013
1014#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
1015	if (systemVersion < 0x1060)
1016	{
1017		CFRelease(nav.customWindow);
1018		DisposeNibReference(nav.customNib);
1019	}
1020#endif
1021
1022	if (err)
1023		return (false);
1024	else
1025	{
1026		if (nav.reply)
1027		{
1028			char	s[PATH_MAX + 1];
1029
1030			err = FSRefMakePath(&(nav.ref), (unsigned char *) s, PATH_MAX);
1031			snprintf(path, PATH_MAX + 1, "%s%s%s", s, MAC_PATH_SEPARATOR, nav.name);
1032
1033			return (true);
1034		}
1035		else
1036			return (false);
1037	}
1038}
1039
1040bool8 NavBeginChooseFolderSheet (WindowRef parent)
1041{
1042	OSStatus					err;
1043	NavDialogCreationOptions	dialogOptions;
1044
1045	err = NavGetDefaultDialogCreationOptions(&dialogOptions);
1046	dialogOptions.optionFlags &= ~kNavAllowMultipleFiles;
1047	dialogOptions.preferenceKey = 8;
1048	dialogOptions.clientName = kMacS9XCFString;
1049	dialogOptions.modality = kWindowModalityWindowModal;
1050	dialogOptions.parentWindow = parent;
1051	gSheetNav.parent = parent;
1052
1053	gSheetEventUPP = NewNavEventUPP(NavGenericOpenEventHandler);
1054
1055	err = NavCreateChooseFolderDialog(&dialogOptions, gSheetEventUPP, NULL, &gSheetNav, &(gSheetNav.nref));
1056	if (err == noErr)
1057	{
1058		err = NavDialogRun(gSheetNav.nref);
1059		if (err)
1060		{
1061			NavDialogDispose(gSheetNav.nref);
1062			DisposeNavEventUPP(gSheetEventUPP);
1063			return (false);
1064		}
1065	}
1066	else
1067	{
1068		DisposeNavEventUPP(gSheetEventUPP);
1069		return (false);
1070	}
1071
1072	return (true);
1073}
1074
1075bool8 NavEndChooseFolderSheet (FSRef *ref)
1076{
1077	DisposeNavEventUPP(gSheetEventUPP);
1078
1079	if (gSheetNav.reply)
1080	{
1081		*ref = gSheetNav.ref;
1082		return (true);
1083	}
1084	else
1085		return (false);
1086}
1087
1088static pascal void NavGenericOpenEventHandler (const NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD)
1089{
1090	OSStatus		err;
1091	NavReplyRecord	reply;
1092	NavUserAction	userAction;
1093	NavState		*nav;
1094	AEDesc			resultDesc;
1095	SInt32 			count;
1096
1097	nav = (NavState *) callBackUD;
1098
1099	switch (callBackSelector)
1100	{
1101		case kNavCBEvent:
1102			break;
1103
1104		case kNavCBStart:
1105			nav->reply = false;
1106			break;
1107
1108		case kNavCBUserAction:
1109			userAction = NavDialogGetUserAction(callBackParms->context);
1110			switch (userAction)
1111			{
1112				case kNavUserActionChoose:
1113					err = NavDialogGetReply(callBackParms->context, &reply);
1114					if (err == noErr)
1115					{
1116						err = AECountItems(&(reply.selection), &count);
1117						if ((err == noErr) && (count == 1))
1118						{
1119							err = AEGetNthDesc(&(reply.selection), 1, typeFSRef, NULL, &resultDesc);
1120							if (err == noErr)
1121							{
1122								err = AEGetDescData(&resultDesc, &(nav->ref), sizeof(FSRef));
1123								if (err == noErr)
1124									nav->reply = true;
1125
1126								err = AEDisposeDesc(&resultDesc);
1127							}
1128						}
1129
1130						err = NavDisposeReply(&reply);
1131					}
1132
1133					break;
1134			}
1135
1136			break;
1137
1138		case kNavCBTerminate:
1139			NavDialogDispose(nav->nref);
1140
1141			if (nav->parent)
1142			{
1143				EventRef	event;
1144				HICommand	cmd;
1145
1146				cmd.commandID          = 'NvDn';
1147				cmd.attributes         = kEventAttributeUserEvent;
1148				cmd.menu.menuRef       = NULL;
1149				cmd.menu.menuItemIndex = 0;
1150
1151				err = CreateEvent(kCFAllocatorDefault, kEventClassCommand, kEventCommandProcess, GetCurrentEventTime(), kEventAttributeUserEvent, &event);
1152				if (err == noErr)
1153				{
1154					err = SetEventParameter(event, kEventParamDirectObject, typeHICommand, sizeof(HICommand), &cmd);
1155					if (err == noErr)
1156						err = SendEventToWindow(event, nav->parent);
1157
1158					ReleaseEvent(event);
1159				}
1160			}
1161
1162			break;
1163	}
1164}
1165
1166static pascal void NavGenericSaveEventHandler (const NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD)
1167{
1168	OSStatus		err;
1169	NavReplyRecord	reply;
1170	NavUserAction	userAction;
1171	NavState		*nav;
1172	AEDesc			resultDesc;
1173
1174	nav = (NavState *) callBackUD;
1175
1176	switch (callBackSelector)
1177	{
1178		case kNavCBEvent:
1179			break;
1180
1181		case kNavCBStart:
1182			nav->reply = false;
1183			break;
1184
1185		case kNavCBUserAction:
1186			userAction = NavDialogGetUserAction(callBackParms->context);
1187			switch (userAction)
1188			{
1189				case kNavUserActionSaveAs:
1190					err = NavDialogGetReply(callBackParms->context, &reply);
1191					if (err == noErr)
1192					{
1193						err = AEGetNthDesc(&(reply.selection), 1, typeFSRef, NULL, &resultDesc);
1194						if (err == noErr)
1195						{
1196							err = AEGetDescData(&resultDesc, &(nav->ref), sizeof(FSRef));
1197							if (err == noErr)
1198							{
1199								Boolean	r;
1200
1201								r = CFStringGetCString(reply.saveFileName, nav->name, PATH_MAX, kCFStringEncodingUTF8);
1202								if (r)
1203									nav->reply = true;
1204							}
1205
1206							err = AEDisposeDesc(&resultDesc);
1207				        }
1208
1209						err = NavDisposeReply(&reply);
1210					}
1211
1212					break;
1213            }
1214
1215            break;
1216
1217		case kNavCBTerminate:
1218			NavDialogDispose(nav->nref);
1219			break;
1220	}
1221}
1222
1223#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
1224static pascal void NavOpenCartEventHandler (const NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD)
1225{
1226	static Boolean	embedded = false;
1227
1228	OSStatus		err;
1229	NavReplyRecord	reply;
1230	NavUserAction	userAction;
1231	NavState		*nav;
1232	HIViewRef		ctl;
1233	HIViewID		cid;
1234	HIViewPartCode	part;
1235	AEDesc			resultDesc;
1236	Point			pt;
1237	SInt32 			count;
1238
1239	nav = (NavState *) callBackUD;
1240
1241	switch (callBackSelector)
1242	{
1243		case kNavCBEvent:
1244			switch (callBackParms->eventData.eventDataParms.event->what)
1245			{
1246				case mouseDown:
1247					pt = callBackParms->eventData.eventDataParms.event->where;
1248					GlobalPointToWindowLocalPoint(&pt, callBackParms->window);
1249
1250					ctl = FindControlUnderMouse(pt, callBackParms->window, &part);
1251					if (ctl)
1252					{
1253						GetControlID(ctl, &cid);
1254						if (cid.signature == 'CCTL')
1255							part = HandleControlClick(ctl, pt, callBackParms->eventData.eventDataParms.event->modifiers, (ControlActionUPP) -1L);
1256					}
1257
1258					break;
1259			}
1260
1261			break;
1262
1263		case kNavCBStart:
1264			nav->reply = false;
1265			cid.signature = 'CCTL';
1266			err = NavCustomControl(callBackParms->context, kNavCtlAddControl, nav->customPane);
1267
1268			cid.id = 101;
1269			HIViewFindByID(nav->customPane, cid, &ctl);
1270			SetControl32BitValue(ctl, romDetect        + 1);
1271
1272			cid.id = 102;
1273			HIViewFindByID(nav->customPane, cid, &ctl);
1274			SetControl32BitValue(ctl, interleaveDetect + 1);
1275
1276			cid.id = 103;
1277			HIViewFindByID(nav->customPane, cid, &ctl);
1278			SetControl32BitValue(ctl, videoDetect      + 1);
1279
1280			cid.id = 104;
1281			HIViewFindByID(nav->customPane, cid, &ctl);
1282			SetControl32BitValue(ctl, headerDetect     + 1);
1283
1284			MoveControl(nav->customPane, ((callBackParms->customRect.right  - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left,
1285										 ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top);
1286
1287			embedded = true;
1288
1289			break;
1290
1291		case kNavCBAccept:
1292			cid.signature = 'CCTL';
1293
1294			cid.id = 101;
1295			HIViewFindByID(nav->customPane, cid, &ctl);
1296			romDetect        = GetControl32BitValue(ctl) - 1;
1297
1298			cid.id = 102;
1299			HIViewFindByID(nav->customPane, cid, &ctl);
1300			interleaveDetect = GetControl32BitValue(ctl) - 1;
1301
1302			cid.id = 103;
1303			HIViewFindByID(nav->customPane, cid, &ctl);
1304			videoDetect      = GetControl32BitValue(ctl) - 1;
1305
1306			cid.id = 104;
1307			HIViewFindByID(nav->customPane, cid, &ctl);
1308			headerDetect     = GetControl32BitValue(ctl) - 1;
1309
1310			break;
1311
1312		case kNavCBCustomize:
1313			if ((callBackParms->customRect.right == 0) && (callBackParms->customRect.bottom == 0))	// First call
1314			{
1315				embedded = false;
1316
1317				callBackParms->customRect.right  = callBackParms->customRect.left + nav->customWidth;
1318				callBackParms->customRect.bottom = callBackParms->customRect.top  + nav->customHeight;
1319			}
1320
1321			break;
1322
1323		case kNavCBAdjustRect:
1324			if (embedded)
1325				MoveControl(nav->customPane, ((callBackParms->customRect.right  - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left,
1326											 ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top);
1327
1328			break;
1329
1330		case kNavCBUserAction:
1331			userAction = NavDialogGetUserAction(callBackParms->context);
1332			switch (userAction)
1333			{
1334				case kNavUserActionChoose:
1335					err = NavDialogGetReply(callBackParms->context, &reply);
1336					if (err == noErr)
1337					{
1338						err = AECountItems(&(reply.selection), &count);
1339						if ((err == noErr) && (count == 1))
1340						{
1341							err = AEGetNthDesc(&(reply.selection), 1, typeFSRef, NULL, &resultDesc);
1342							if (err == noErr)
1343							{
1344								err = AEGetDescData(&resultDesc, &(nav->ref), sizeof(FSRef));
1345								if (err == noErr)
1346									nav->reply = true;
1347
1348								err = AEDisposeDesc(&resultDesc);
1349							}
1350				        }
1351
1352						err = NavDisposeReply(&reply);
1353					}
1354
1355					break;
1356            }
1357
1358            break;
1359
1360		case kNavCBTerminate:
1361			NavDialogDispose(nav->nref);
1362
1363			if (nav->parent)
1364			{
1365				EventRef	event;
1366				HICommand	cmd;
1367
1368				cmd.commandID          = 'NvDn';
1369				cmd.attributes         = kEventAttributeUserEvent;
1370				cmd.menu.menuRef       = NULL;
1371				cmd.menu.menuItemIndex = 0;
1372
1373				err = CreateEvent(kCFAllocatorDefault, kEventClassCommand, kEventCommandProcess, GetCurrentEventTime(), kEventAttributeUserEvent, &event);
1374				if (err == noErr)
1375				{
1376					err = SetEventParameter(event, kEventParamDirectObject, typeHICommand, sizeof(HICommand), &cmd);
1377					if (err == noErr)
1378						err = SendEventToWindow(event, nav->parent);
1379
1380					ReleaseEvent(event);
1381				}
1382			}
1383
1384			break;
1385	}
1386}
1387
1388static pascal void NavPlayMovieFromEventHandler (const NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD)
1389{
1390	static Boolean	embedded = false;
1391
1392	OSStatus		err;
1393	NavReplyRecord	reply;
1394	NavUserAction	userAction;
1395	NavState		*nav;
1396	HIViewRef 		ctl;
1397	HIViewID		cid;
1398	HIViewPartCode	part;
1399	AEDesc			resultDesc;
1400	Point			pt;
1401	SInt32 			count;
1402
1403	nav = (NavState *) callBackUD;
1404
1405	switch (callBackSelector)
1406	{
1407		case kNavCBEvent:
1408			switch (callBackParms->eventData.eventDataParms.event->what)
1409			{
1410				case mouseDown:
1411					pt = callBackParms->eventData.eventDataParms.event->where;
1412					GlobalPointToWindowLocalPoint(&pt, callBackParms->window);
1413
1414					ctl = FindControlUnderMouse(pt, callBackParms->window, &part);
1415					if (ctl)
1416					{
1417						GetControlID(ctl, &cid);
1418						if (cid.signature == 'PCTL')
1419							part = HandleControlClick(ctl, pt, callBackParms->eventData.eventDataParms.event->modifiers, (ControlActionUPP) -1L);
1420					}
1421
1422					break;
1423			}
1424
1425			break;
1426
1427		case kNavCBStart:
1428			nav->reply = false;
1429			cid.signature = 'PCTL';
1430			err = NavCustomControl(callBackParms->context, kNavCtlAddControl, nav->customPane);
1431
1432			for (cid.id = 101; cid.id <= 102; cid.id++)
1433			{
1434				HIViewFindByID(nav->customPane, cid, &ctl);
1435				SetControl32BitValue(ctl, (macPlayFlag & (1 << (cid.id - 101))) ? true : false);
1436			}
1437
1438			MoveControl(nav->customPane, ((callBackParms->customRect.right  - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left,
1439										 ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top);
1440
1441			embedded = true;
1442
1443			break;
1444
1445		case kNavCBAccept:
1446			macPlayFlag = 0;
1447			cid.signature = 'PCTL';
1448
1449			for (cid.id = 101; cid.id <= 102; cid.id++)
1450			{
1451				HIViewFindByID(nav->customPane, cid, &ctl);
1452				if (GetControl32BitValue(ctl))
1453					macPlayFlag |= (1 << (cid.id - 101));
1454			}
1455
1456			break;
1457
1458		case kNavCBCustomize:
1459			if ((callBackParms->customRect.right == 0) && (callBackParms->customRect.bottom == 0))	// First call
1460			{
1461				embedded = false;
1462
1463				callBackParms->customRect.right  = callBackParms->customRect.left + nav->customWidth;
1464				callBackParms->customRect.bottom = callBackParms->customRect.top  + nav->customHeight;
1465			}
1466
1467			break;
1468
1469		case kNavCBAdjustRect:
1470			if (embedded)
1471				MoveControl(nav->customPane, ((callBackParms->customRect.right  - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left,
1472											 ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top);
1473
1474			break;
1475
1476		case kNavCBUserAction:
1477			userAction = NavDialogGetUserAction(callBackParms->context);
1478			switch (userAction)
1479			{
1480				case kNavUserActionChoose:
1481					err = NavDialogGetReply(callBackParms->context, &reply);
1482					if (err == noErr)
1483					{
1484						err = AECountItems(&(reply.selection), &count);
1485						if ((err == noErr) && (count == 1))
1486						{
1487							err = AEGetNthDesc(&(reply.selection), 1, typeFSRef, NULL, &resultDesc);
1488							if (err == noErr)
1489							{
1490								err = AEGetDescData(&resultDesc, &(nav->ref), sizeof(FSRef));
1491								if (err == noErr)
1492									nav->reply = true;
1493
1494								err = AEDisposeDesc(&resultDesc);
1495							}
1496				        }
1497
1498						err = NavDisposeReply(&reply);
1499					}
1500
1501					break;
1502            }
1503
1504            break;
1505
1506		case kNavCBTerminate:
1507			NavDialogDispose(nav->nref);
1508			break;
1509	}
1510}
1511
1512static pascal void NavRecordMovieToEventHandler (const NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD)
1513{
1514	static Boolean	embedded = false;
1515
1516	OSStatus		err;
1517	NavReplyRecord	reply;
1518	NavUserAction	userAction;
1519	NavState		*nav;
1520	HIViewRef 		ctl;
1521	HIViewID		cid;
1522	HIViewPartCode	part;
1523	CFStringRef		sref;
1524	CFIndex			cflen;
1525	AEDesc			resultDesc;
1526	Point			pt;
1527	UniChar			unistr[MOVIE_MAX_METADATA];
1528
1529	nav = (NavState *) callBackUD;
1530
1531	switch (callBackSelector)
1532	{
1533		case kNavCBEvent:
1534			switch (callBackParms->eventData.eventDataParms.event->what)
1535			{
1536				case mouseDown:
1537					pt = callBackParms->eventData.eventDataParms.event->where;
1538					GlobalPointToWindowLocalPoint(&pt, callBackParms->window);
1539
1540					ctl = FindControlUnderMouse(pt, callBackParms->window, &part);
1541					if (ctl)
1542					{
1543						GetControlID(ctl, &cid);
1544						if (cid.signature == 'RCTL')
1545						{
1546							if (cid.id == 107)
1547							{
1548								HIViewRef	tmp;
1549
1550								err = GetKeyboardFocus(callBackParms->window, &tmp);
1551								if ((err == noErr) && (tmp != ctl))
1552									err = SetKeyboardFocus(callBackParms->window, ctl, kControlFocusNextPart);
1553							}
1554
1555							part = HandleControlClick(ctl, pt, callBackParms->eventData.eventDataParms.event->modifiers, (ControlActionUPP) -1L);
1556						}
1557					}
1558
1559					break;
1560			}
1561
1562			break;
1563
1564		case kNavCBStart:
1565			nav->reply = false;
1566			cid.signature = 'RCTL';
1567			err = NavCustomControl(callBackParms->context, kNavCtlAddControl, nav->customPane);
1568
1569			for (cid.id = 101; cid.id <= 106; cid.id++)
1570			{
1571				HIViewFindByID(nav->customPane, cid, &ctl);
1572				SetControl32BitValue(ctl, (macRecordFlag & (1 << (cid.id - 101))) ? true : false);
1573			}
1574
1575			MoveControl(nav->customPane, ((callBackParms->customRect.right  - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left,
1576										 ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top);
1577
1578			embedded = true;
1579			break;
1580
1581		case kNavCBAccept:
1582			macRecordFlag = 0;
1583			cid.signature = 'RCTL';
1584
1585			for (cid.id = 101; cid.id <= 106; cid.id++)
1586			{
1587				HIViewFindByID(nav->customPane, cid, &ctl);
1588				if (GetControl32BitValue(ctl))
1589					macRecordFlag |= (1 << (cid.id - 101));
1590			}
1591
1592			cid.id = 107;
1593			HIViewFindByID(nav->customPane, cid, &ctl);
1594			CopyEditTextCFString(ctl, &sref);
1595			if (sref)
1596			{
1597				cflen = CFStringGetLength(sref);
1598				if (cflen > MOVIE_MAX_METADATA - 1)
1599					cflen = MOVIE_MAX_METADATA - 1;
1600
1601				CFStringGetCharacters(sref, CFRangeMake(0, cflen), unistr);
1602
1603				for (int i = 0; i < cflen; i++)
1604					macRecordWChar[i] = (wchar_t) unistr[i];
1605				macRecordWChar[cflen] = 0;
1606
1607				CFRelease(sref);
1608			}
1609			else
1610				macRecordWChar[0] = 0;
1611
1612			break;
1613
1614		case kNavCBCustomize:
1615			if ((callBackParms->customRect.right == 0) && (callBackParms->customRect.bottom == 0))	// First call
1616			{
1617				embedded = false;
1618
1619				callBackParms->customRect.right  = callBackParms->customRect.left + nav->customWidth;
1620				callBackParms->customRect.bottom = callBackParms->customRect.top  + nav->customHeight;
1621			}
1622
1623			break;
1624
1625		case kNavCBAdjustRect:
1626			if (embedded)
1627				MoveControl(nav->customPane, ((callBackParms->customRect.right  - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left,
1628											 ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top);
1629
1630			break;
1631
1632		case kNavCBUserAction:
1633			userAction = NavDialogGetUserAction(callBackParms->context);
1634			switch (userAction)
1635			{
1636				case kNavUserActionSaveAs:
1637					err = NavDialogGetReply(callBackParms->context, &reply);
1638					if (err == noErr)
1639					{
1640						err = AEGetNthDesc(&(reply.selection), 1, typeFSRef, NULL, &resultDesc);
1641						if (err == noErr)
1642						{
1643							err = AEGetDescData(&resultDesc, &(nav->ref), sizeof(FSRef));
1644							if (err == noErr)
1645							{
1646								Boolean	r;
1647
1648								r = CFStringGetCString(reply.saveFileName, nav->name, PATH_MAX, kCFStringEncodingUTF8);
1649								if (r)
1650									nav->reply = true;
1651							}
1652
1653							err = AEDisposeDesc(&resultDesc);
1654						}
1655
1656						err = NavDisposeReply(&reply);
1657					}
1658
1659					break;
1660			}
1661
1662			break;
1663
1664		case kNavCBTerminate:
1665			NavDialogDispose(nav->nref);
1666			break;
1667	}
1668}
1669
1670static pascal void NavQTMovieRecordToEventHandler (const NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD)
1671{
1672	static Boolean	embedded = false;
1673
1674	OSStatus		err;
1675	NavReplyRecord	reply;
1676	NavUserAction	userAction;
1677	NavState		*nav;
1678	HIViewRef 		ctl;
1679	HIViewID		cid;
1680	HIViewPartCode	part;
1681	AEDesc			resultDesc;
1682	Point			pt;
1683
1684	nav = (NavState *) callBackUD;
1685
1686	switch (callBackSelector)
1687	{
1688		case kNavCBEvent:
1689			switch (callBackParms->eventData.eventDataParms.event->what)
1690			{
1691				case mouseDown:
1692					pt = callBackParms->eventData.eventDataParms.event->where;
1693					GlobalPointToWindowLocalPoint(&pt, callBackParms->window);
1694
1695					ctl = FindControlUnderMouse(pt, callBackParms->window, &part);
1696					if (ctl)
1697					{
1698						GetControlID(ctl, &cid);
1699						if (cid.signature == 'QCTL')
1700							part = HandleControlClick(ctl, pt, callBackParms->eventData.eventDataParms.event->modifiers, (ControlActionUPP) -1L);
1701
1702						if (cid.id == 103)
1703							MacQTVideoConfig();
1704					}
1705
1706					break;
1707			}
1708
1709			break;
1710
1711		case kNavCBStart:
1712			nav->reply = false;
1713			cid.signature = 'QCTL';
1714			err = NavCustomControl(callBackParms->context, kNavCtlAddControl, nav->customPane);
1715
1716			for (cid.id = 101; cid.id <= 102; cid.id++)
1717			{
1718				HIViewFindByID(nav->customPane, cid, &ctl);
1719				SetControl32BitValue(ctl, (macQTMovFlag & (1 << (cid.id - 101))) ? true : false);
1720			}
1721
1722			cid.id = 104;
1723			HIViewFindByID(nav->customPane, cid, &ctl);
1724			SetControl32BitValue(ctl, ((macQTMovFlag & 0xFF00) >> 8) + 1);
1725
1726			MoveControl(nav->customPane, ((callBackParms->customRect.right  - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left,
1727										 ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top);
1728
1729			embedded = true;
1730
1731			break;
1732
1733		case kNavCBAccept:
1734			macQTMovFlag = 0;
1735			cid.signature = 'QCTL';
1736
1737			for (cid.id = 101; cid.id <= 102; cid.id++)
1738			{
1739				HIViewFindByID(nav->customPane, cid, &ctl);
1740				if (GetControl32BitValue(ctl))
1741					macQTMovFlag |= (1 << (cid.id - 101));
1742			}
1743
1744			cid.id = 104;
1745			HIViewFindByID(nav->customPane, cid, &ctl);
1746			macQTMovFlag |= ((GetControl32BitValue(ctl) - 1) << 8);
1747
1748			break;
1749
1750		case kNavCBCustomize:
1751			if ((callBackParms->customRect.right == 0) && (callBackParms->customRect.bottom == 0))	// First call
1752			{
1753				embedded = false;
1754
1755				callBackParms->customRect.right  = callBackParms->customRect.left + nav->customWidth;
1756				callBackParms->customRect.bottom = callBackParms->customRect.top  + nav->customHeight;
1757			}
1758
1759			break;
1760
1761		case kNavCBAdjustRect:
1762			if (embedded)
1763				MoveControl(nav->customPane, ((callBackParms->customRect.right  - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left,
1764											 ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top);
1765
1766			break;
1767
1768		case kNavCBUserAction:
1769			userAction = NavDialogGetUserAction(callBackParms->context);
1770			switch (userAction)
1771			{
1772				case kNavUserActionSaveAs:
1773					err = NavDialogGetReply(callBackParms->context, &reply);
1774					if (err == noErr)
1775					{
1776						err = AEGetNthDesc(&(reply.selection), 1, typeFSRef, NULL, &resultDesc);
1777						if (err == noErr)
1778						{
1779							err = AEGetDescData(&resultDesc, &(nav->ref), sizeof(FSRef));
1780							if (err == noErr)
1781							{
1782								Boolean	r;
1783
1784								r = CFStringGetCString(reply.saveFileName, nav->name, PATH_MAX, kCFStringEncodingUTF8);
1785								if (r)
1786									nav->reply = true;
1787							}
1788
1789							err = AEDisposeDesc(&resultDesc);
1790				        }
1791
1792						err = NavDisposeReply(&reply);
1793					}
1794
1795					break;
1796            }
1797
1798            break;
1799
1800		case kNavCBTerminate:
1801			NavDialogDispose(nav->nref);
1802			break;
1803	}
1804}
1805#endif
1806
1807static pascal Boolean NavOpenCartFilter (AEDesc *theItem, void *ninfo, NavCallBackUserData callbackUD, NavFilterModes filterMode)
1808{
1809	OSStatus	err;
1810	AEDesc 		resultDesc;
1811	Boolean		result = true;
1812
1813	err = AECoerceDesc(theItem, typeFSRef, &resultDesc);
1814	if (err == noErr)
1815	{
1816		FSRef	ref;
1817
1818		err = AEGetDescData(&resultDesc, &ref, sizeof(FSRef));
1819		if (err == noErr)
1820		{
1821			FSCatalogInfo	catinfo;
1822			HFSUniStr255	unistr;
1823
1824			err = FSGetCatalogInfo(&ref, kFSCatInfoNodeFlags, &catinfo, &unistr, NULL, NULL);
1825			if ((err == noErr) && !(catinfo.nodeFlags & kFSNodeIsDirectoryMask) && (unistr.length > 4))
1826			{
1827				UInt16	i = unistr.length;
1828
1829				if  ((unistr.unicode[i - 4] == '.') &&
1830				   (((unistr.unicode[i - 3] == 's') && (unistr.unicode[i - 2] == 'r') && (unistr.unicode[i - 1] == 'm')) ||
1831					((unistr.unicode[i - 3] == 'f') && (unistr.unicode[i - 2] == 'r') && (unistr.unicode[i - 1] == 'z')) ||
1832					((unistr.unicode[i - 3] == 's') && (unistr.unicode[i - 2] == 'm') && (unistr.unicode[i - 1] == 'v')) ||
1833					((unistr.unicode[i - 3] == 'm') && (unistr.unicode[i - 2] == 'o') && (unistr.unicode[i - 1] == 'v')) ||
1834					((unistr.unicode[i - 3] == 's') && (unistr.unicode[i - 2] == 'p') && (unistr.unicode[i - 1] == 'c')) ||
1835					((unistr.unicode[i - 3] == 'r') && (unistr.unicode[i - 2] == 't') && (unistr.unicode[i - 1] == 'c')) ||
1836					((unistr.unicode[i - 3] == 'd') && (unistr.unicode[i - 2] == 'a') && (unistr.unicode[i - 1] == 't')) ||
1837					((unistr.unicode[i - 3] == 'o') && (unistr.unicode[i - 2] == 'u') && (unistr.unicode[i - 1] == 't')) ||
1838					((unistr.unicode[i - 3] == 'c') && (unistr.unicode[i - 2] == 'h') && (unistr.unicode[i - 1] == 't')) ||
1839					((unistr.unicode[i - 3] == 'i') && (unistr.unicode[i - 2] == 'p') && (unistr.unicode[i - 1] == 's')) ||
1840					((unistr.unicode[i - 3] == 'u') && (unistr.unicode[i - 2] == 'p') && (unistr.unicode[i - 1] == 's')) ||
1841					((unistr.unicode[i - 3] == 'p') && (unistr.unicode[i - 2] == 'n') && (unistr.unicode[i - 1] == 'g'))))
1842					result = false;
1843			}
1844		}
1845
1846		AEDisposeDesc(&resultDesc);
1847	}
1848
1849	return (result);
1850}
1851
1852static pascal Boolean NavDefrostFromFilter (AEDesc *theItem, void *ninfo, NavCallBackUserData callbackUD, NavFilterModes filterMode)
1853{
1854	OSStatus	err;
1855	AEDesc 		resultDesc;
1856	Boolean		result = true;
1857
1858	err = AECoerceDesc(theItem, typeFSRef, &resultDesc);
1859	if (err == noErr)
1860	{
1861		FSRef	ref;
1862
1863		err = AEGetDescData(&resultDesc, &ref, sizeof(FSRef));
1864		if (err == noErr)
1865		{
1866			FSCatalogInfo	catinfo;
1867			HFSUniStr255	unistr;
1868
1869			err = FSGetCatalogInfo(&ref, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo, &catinfo, &unistr, NULL, NULL);
1870			if ((err == noErr) && !(catinfo.nodeFlags & kFSNodeIsDirectoryMask))
1871			{
1872				if (((FileInfo *) &catinfo.finderInfo)->fileType != 'SAVE')
1873				{
1874					UInt16	i = unistr.length;
1875
1876					if (i < 4)
1877						result = false;
1878					else
1879					if ((unistr.unicode[i - 4] == '.') && (unistr.unicode[i - 3] == 'f') && (unistr.unicode[i - 2] == 'r'))
1880						result = true;
1881					else
1882						result = false;
1883				}
1884			}
1885		}
1886
1887		AEDisposeDesc(&resultDesc);
1888	}
1889
1890	return (result);
1891}
1892
1893static pascal Boolean NavPlayMovieFromFilter (AEDesc *theItem, void *ninfo, NavCallBackUserData callbackUD, NavFilterModes filterMode)
1894{
1895	OSStatus	err;
1896	AEDesc 		resultDesc;
1897	Boolean		result = true;
1898
1899	err = AECoerceDesc(theItem, typeFSRef, &resultDesc);
1900	if (err == noErr)
1901	{
1902		FSRef	ref;
1903
1904		err = AEGetDescData(&resultDesc, &ref, sizeof(FSRef));
1905		if (err == noErr)
1906		{
1907			FSCatalogInfo	catinfo;
1908			HFSUniStr255	unistr;
1909
1910			err = FSGetCatalogInfo(&ref, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo, &catinfo, &unistr, NULL, NULL);
1911			if ((err == noErr) && !(catinfo.nodeFlags & kFSNodeIsDirectoryMask))
1912			{
1913				if (((FileInfo *) &catinfo.finderInfo)->fileType != 'SMOV')
1914				{
1915					UInt16	i = unistr.length;
1916
1917					if (i < 4)
1918						result = false;
1919					else
1920					if  ((unistr.unicode[i - 4] == '.') && (unistr.unicode[i - 3] == 's') && (unistr.unicode[i - 2] == 'm') && (unistr.unicode[i - 1] == 'v'))
1921						result = true;
1922					else
1923						result = false;
1924				}
1925			}
1926		}
1927
1928		AEDisposeDesc(&resultDesc);
1929	}
1930
1931	return (result);
1932}
1933
1934#ifdef MAC_TIGER_PANTHER_SUPPORT
1935static pascal Boolean NavDefrostFromPreview (NavCBRecPtr callBackParms, NavCallBackUserData callBackUD)
1936{
1937	if (systemVersion >= 0x1050)
1938		return (true);
1939
1940	OSStatus	err;
1941	Boolean		previewShowing, result = false;
1942
1943	err = NavCustomControl(callBackParms->context, kNavCtlIsPreviewShowing, &previewShowing);
1944	if ((err == noErr) && previewShowing)
1945	{
1946		AEDesc	resultDesc;
1947
1948		err = AECoerceDesc((AEDesc *) callBackParms->eventData.eventDataParms.param, typeFSRef, &resultDesc);
1949		if (err == noErr)
1950		{
1951			FSRef	ref;
1952
1953			err = AEGetDescData(&resultDesc, &ref, sizeof(FSRef));
1954			if (err == noErr)
1955			{
1956				FSCatalogInfo	catinfo;
1957
1958				err = FSGetCatalogInfo(&ref, kFSCatInfoNodeFlags | kFSCatInfoContentMod, &catinfo, NULL, NULL, NULL);
1959				if ((err == noErr) && !(catinfo.nodeFlags & kFSNodeIsDirectoryMask))
1960				{
1961					CFMutableStringRef	sref;
1962
1963					sref = CFStringCreateMutable(kCFAllocatorDefault, 0);
1964					if (sref)
1965					{
1966						CFAbsoluteTime		at;
1967						CFDateFormatterRef	format;
1968						CFLocaleRef			locale;
1969						CFStringRef			datstr;
1970
1971						err = UCConvertUTCDateTimeToCFAbsoluteTime(&(catinfo.contentModDate), &at);
1972						locale = CFLocaleCopyCurrent();
1973						format = CFDateFormatterCreate(kCFAllocatorDefault, locale, kCFDateFormatterShortStyle, kCFDateFormatterMediumStyle);
1974						datstr = CFDateFormatterCreateStringWithAbsoluteTime(kCFAllocatorDefault, format, at);
1975						CFStringAppend(sref, datstr);
1976						CFRelease(datstr);
1977						CFRelease(format);
1978						CFRelease(locale);
1979
1980						CGContextRef	ctx;
1981						CGRect			bounds;
1982						CGrafPtr		port;
1983						Rect			rct;
1984						int				rightedge;
1985
1986						port = GetWindowPort(callBackParms->window);
1987						GetWindowBounds(callBackParms->window, kWindowContentRgn, &rct);
1988
1989						err = QDBeginCGContext(port, &ctx);
1990
1991						rightedge = (callBackParms->previewRect.right < (rct.right - rct.left - 11)) ? callBackParms->previewRect.right : (rct.right - rct.left - 11);
1992
1993						bounds.origin.x = (float) callBackParms->previewRect.left;
1994						bounds.origin.y = (float) (rct.bottom - rct.top - callBackParms->previewRect.bottom);
1995						bounds.size.width  = (float) (rightedge - callBackParms->previewRect.left);
1996						bounds.size.height = (float) (callBackParms->previewRect.bottom - callBackParms->previewRect.top);
1997
1998						CGContextClipToRect(ctx, bounds);
1999
2000						CGContextSetRGBFillColor(ctx, 1.0f, 1.0f, 1.0f, 1.0f);
2001						CGContextFillRect(ctx, bounds);
2002						CGContextSetRGBFillColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f);
2003
2004						bounds.origin.x = (float) (callBackParms->previewRect.left + ((callBackParms->previewRect.right - callBackParms->previewRect.left - 128) >> 1));
2005						bounds.origin.y = (float) (rct.bottom - rct.top - callBackParms->previewRect.top - 120 - 25);
2006						bounds.size.width  = 128.0f;
2007						bounds.size.height = 120.0f;
2008
2009						DrawThumbnailResource(&ref, ctx, bounds);
2010
2011						HIThemeTextInfo	textinfo;
2012
2013						textinfo.version             = 0;
2014						textinfo.state               = kThemeStateActive;
2015						textinfo.fontID              = kThemeSmallSystemFont;
2016						textinfo.verticalFlushness   = kHIThemeTextVerticalFlushTop;
2017						textinfo.horizontalFlushness = kHIThemeTextHorizontalFlushCenter;
2018						textinfo.options             = 0;
2019						textinfo.truncationPosition  = kHIThemeTextTruncationMiddle;
2020						textinfo.truncationMaxLines  = 0;
2021						textinfo.truncationHappened  = false;
2022
2023						bounds.origin.x = (float) (callBackParms->previewRect.left + 10);
2024						bounds.origin.y = (float) (rct.bottom - rct.top - callBackParms->previewRect.top - 153 - 20);
2025						bounds.size.width  = (float) (callBackParms->previewRect.right - callBackParms->previewRect.left - 20);
2026						bounds.size.height = 20.0f;
2027
2028						err = HIThemeDrawTextBox(sref, &bounds, &textinfo, ctx, kHIThemeOrientationInverted);
2029
2030						CGContextSynchronize(ctx);
2031
2032						err = QDEndCGContext(port, &ctx);
2033
2034						CFRelease(sref);
2035
2036						result = true;
2037					}
2038				}
2039			}
2040
2041			AEDisposeDesc(&resultDesc);
2042		}
2043	}
2044
2045	return (result);
2046}
2047
2048static pascal Boolean NavPlayMovieFromPreview (NavCBRecPtr callBackParms, NavCallBackUserData callBackUD)
2049{
2050	if (systemVersion >= 0x1050)
2051		return (true);
2052
2053	OSStatus	err;
2054	Boolean		previewShowing, result = false;
2055
2056	err = NavCustomControl(callBackParms->context, kNavCtlIsPreviewShowing, &previewShowing);
2057	if ((err == noErr) && previewShowing)
2058	{
2059		AEDesc	resultDesc;
2060
2061		err = AECoerceDesc((AEDesc *) callBackParms->eventData.eventDataParms.param, typeFSRef, &resultDesc);
2062		if (err == noErr)
2063		{
2064			FSRef	ref;
2065
2066			err = AEGetDescData(&resultDesc, &ref, sizeof(FSRef));
2067			if (err == noErr)
2068			{
2069				char	path[PATH_MAX + 1];
2070
2071				err = FSRefMakePath(&ref, (unsigned char *) path, PATH_MAX);
2072				if (err == noErr)
2073				{
2074					MovieInfo	movinfo;
2075					int			r;
2076
2077					r = S9xMovieGetInfo(path, &movinfo);
2078					if (r == SUCCESS)
2079					{
2080						UTCDateTime		utctime;
2081						CGContextRef	ctx;
2082						CGRect			bounds;
2083						CGrafPtr		port;
2084						Rect			rct;
2085						CFStringRef		sref;
2086						UInt64			t;
2087						int				rightedge, border, width, l, sec, min, hr, n;
2088						char			cstr[256], cbuf[512];
2089						UniChar			unistr[MOVIE_MAX_METADATA];
2090
2091						sref = CFCopyLocalizedString(CFSTR("MoviePrevBorder"), "1");
2092						if (sref)
2093						{
2094							border = CFStringGetIntValue(sref);
2095							CFRelease(sref);
2096						}
2097						else
2098							border = 1;
2099
2100						sref = CFCopyLocalizedString(CFSTR("MoviePrevWidth"), "1");
2101						if (sref)
2102						{
2103							width = CFStringGetIntValue(sref);
2104							CFRelease(sref);
2105						}
2106						else
2107							width = 1;
2108
2109						// Date
2110
2111						t = (UInt64) movinfo.TimeCreated + ((365 * 66 + 17) * 24 * 60 * 60);
2112						utctime.highSeconds = (UInt16) (t >> 32);
2113						utctime.lowSeconds  = (UInt32) (t & 0xFFFFFFFF);
2114						utctime.fraction    = 0;
2115
2116						CFAbsoluteTime		at;
2117						CFDateFormatterRef	format;
2118						CFLocaleRef			locale;
2119						CFStringRef			datstr;
2120						Boolean				e;
2121
2122						err = UCConvertUTCDateTimeToCFAbsoluteTime(&utctime, &at);
2123						locale = CFLocaleCopyCurrent();
2124						format = CFDateFormatterCreate(kCFAllocatorDefault, locale, kCFDateFormatterShortStyle, kCFDateFormatterNoStyle);
2125						datstr = CFDateFormatterCreateStringWithAbsoluteTime(kCFAllocatorDefault, format, at);
2126						e = CFStringGetCString(datstr, cbuf, sizeof(cbuf), CFStringGetSystemEncoding());
2127						CFRelease(datstr);
2128						CFRelease(format);
2129						strcat(cbuf, "\n");
2130						format = CFDateFormatterCreate(kCFAllocatorDefault, locale, kCFDateFormatterNoStyle, kCFDateFormatterMediumStyle);
2131						datstr = CFDateFormatterCreateStringWithAbsoluteTime(kCFAllocatorDefault, format, at);
2132						e = CFStringGetCString(datstr, cstr, sizeof(cstr), CFStringGetSystemEncoding());
2133						CFRelease(datstr);
2134						CFRelease(format);
2135						strcat(cbuf, cstr);
2136						strcat(cbuf, "\n");
2137						CFRelease(locale);
2138
2139						// Length
2140
2141						l = (movinfo.LengthFrames + 30) / ((movinfo.Opts & MOVIE_OPT_PAL) ? 50 : 60);
2142						sec = l % 60;	l /= 60;
2143						min = l % 60;	l /= 60;
2144						hr  = l % 60;
2145
2146						sprintf(cstr, "%02d:%02d:%02d\n", hr, min, sec);
2147						strcat(cbuf, cstr);
2148
2149						// Frames
2150
2151						sprintf(cstr, "%d\n", movinfo.LengthFrames);
2152						strcat(cbuf, cstr);
2153
2154						//
2155
2156						port = GetWindowPort(callBackParms->window);
2157						GetWindowBounds(callBackParms->window, kWindowContentRgn, &rct);
2158
2159						err = QDBeginCGContext(port, &ctx);
2160
2161						rightedge = (callBackParms->previewRect.right < (rct.right - rct.left - 11)) ? callBackParms->previewRect.right : (rct.right - rct.left - 11);
2162
2163						bounds.origin.x = (float) callBackParms->previewRect.left;
2164						bounds.origin.y = (float) (rct.bottom - rct.top - callBackParms->previewRect.bottom);
2165						bounds.size.width  = (float) (rightedge - callBackParms->previewRect.left);
2166						bounds.size.height = (float) (callBackParms->previewRect.bottom - callBackParms->previewRect.top);
2167
2168						CGContextClipToRect(ctx, bounds);
2169
2170						CGContextSetRGBFillColor(ctx, 1.0f, 1.0f, 1.0f, 1.0f);
2171						CGContextFillRect(ctx, bounds);
2172						CGContextSetRGBFillColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f);
2173
2174						// Thumbnail
2175
2176						bounds.origin.x  = (float) (callBackParms->previewRect.left + ((callBackParms->previewRect.right - callBackParms->previewRect.left - 128) >> 1));
2177						bounds.origin.y  = (float) (rct.bottom - rct.top - callBackParms->previewRect.top - 120 - 25);
2178						bounds.size.width  = 128.0f;
2179						bounds.size.height = 120.0f;
2180
2181						DrawThumbnailResource(&ref, ctx, bounds);
2182
2183						// Text
2184
2185						HIThemeTextInfo	textinfo;
2186
2187						textinfo.version            = 0;
2188						textinfo.state              = kThemeStateActive;
2189						textinfo.fontID             = kThemeSmallSystemFont;
2190						textinfo.verticalFlushness  = kHIThemeTextVerticalFlushTop;
2191						textinfo.options            = 0;
2192						textinfo.truncationPosition = kHIThemeTextTruncationMiddle;
2193						textinfo.truncationMaxLines = 0;
2194						textinfo.truncationHappened = false;
2195
2196						bounds.origin.x = (float) (((callBackParms->previewRect.right - callBackParms->previewRect.left - width) >> 1) + callBackParms->previewRect.left + border + 7);
2197						bounds.origin.y = (float) (rct.bottom - rct.top - callBackParms->previewRect.top - 153 - 60);
2198						bounds.size.width  = (float) callBackParms->previewRect.right - bounds.origin.x;
2199						bounds.size.height = 60.0f;
2200
2201						sref = CFStringCreateWithCString(kCFAllocatorDefault, cbuf, CFStringGetSystemEncoding());
2202						if (sref)
2203						{
2204							textinfo.horizontalFlushness = kHIThemeTextHorizontalFlushLeft;
2205							err = HIThemeDrawTextBox(sref, &bounds, &textinfo, ctx, kHIThemeOrientationInverted);
2206							CFRelease(sref);
2207						}
2208
2209						bounds.origin.x = (float) callBackParms->previewRect.left;
2210						bounds.origin.y = (float) (rct.bottom - rct.top - callBackParms->previewRect.top - 153 - 60);
2211						bounds.size.width  = (float) (((callBackParms->previewRect.right - callBackParms->previewRect.left - width) >> 1) + border);
2212						bounds.size.height = 60.0f;
2213
2214						sref = CFCopyLocalizedString(CFSTR("MoviePrevMes"), "MovieInfo");
2215						if (sref)
2216						{
2217							textinfo.horizontalFlushness = kHIThemeTextHorizontalFlushRight;
2218							err = HIThemeDrawTextBox(sref, &bounds, &textinfo, ctx, kHIThemeOrientationInverted);
2219							CFRelease(sref);
2220						}
2221
2222						bounds.origin.x = (float) (((callBackParms->previewRect.right - callBackParms->previewRect.left - 132) >> 1) + callBackParms->previewRect.left);
2223						bounds.origin.y = (float) (rct.bottom - rct.top - callBackParms->previewRect.bottom + 10);
2224						bounds.size.width  = 132.0f;
2225						bounds.size.height = (float) (callBackParms->previewRect.bottom - callBackParms->previewRect.top - 223 - 10);
2226
2227						n = wcslen(movinfo.Metadata);
2228
2229						for (int i = 0; i < n; i++)
2230							unistr[i] = (UniChar) movinfo.Metadata[i];
2231						unistr[n] = 0;
2232
2233						sref = CFStringCreateWithCharacters(kCFAllocatorDefault, unistr, n);
2234						if (sref)
2235						{
2236							textinfo.horizontalFlushness = kHIThemeTextHorizontalFlushLeft;
2237							err = HIThemeDrawTextBox(sref, &bounds, &textinfo, ctx, kHIThemeOrientationInverted);
2238							CFRelease(sref);
2239						}
2240
2241						CGContextSynchronize(ctx);
2242
2243						err = QDEndCGContext(port, &ctx);
2244
2245						result = true;
2246					}
2247				}
2248			}
2249
2250			AEDisposeDesc(&resultDesc);
2251		}
2252	}
2253
2254	return (result);
2255}
2256#endif
2257
2258#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT
2259static void GlobalPointToWindowLocalPoint (Point *pt, WindowRef window)
2260{
2261	if (systemVersion >= 0x1040)
2262	{
2263		HIViewRef	view;
2264		HIPoint		cpt = CGPointMake((float) pt->h, (float) pt->v);
2265
2266		HIViewFindByID(HIViewGetRoot(window), kHIViewWindowContentID, &view);
2267		HIPointConvert(&cpt, kHICoordSpace72DPIGlobal, NULL, kHICoordSpaceView, view);
2268		pt->h = (short) cpt.x;
2269		pt->v = (short) cpt.y;
2270	}
2271#ifdef MAC_PANTHER_SUPPORT
2272	else
2273		QDGlobalToLocalPoint(GetWindowPort(window), pt);
2274#endif
2275}
2276#endif
2277