1/*
2 * NavigationGetFile.c --
3 *
4 *		This file implements the Navigation dialog for opening movies with
5 *		preview. It is part of the QuickTimeTcl package which provides
6 *		Tcl/Tk bindings for QuickTime.
7 *
8 * Copyright (c) 2000-2003  Mats Bengtsson
9 *
10 * $Id: NavigationGetFile.c,v 1.2 2004/05/28 14:47:46 matben Exp $
11 */
12
13#include "QuickTimeTcl.h"
14
15#if !TARGET_API_MAC_CARBON
16    #include <Navigation.h>
17#endif
18
19typedef const OSTypePtr TypeListPtr;
20
21OSErr               GetOneFileWithPreview( AEDesc *defaultLocation, short numTypes, TypeListPtr typeListPtr,
22                            StringPtr title, FSSpecPtr theFSSpecPtr, void *filterProc );
23static Handle       CreateOpenHandle( OSType theApplicationSignature, short numTypes,
24                            TypeListPtr typeListPtr );
25static pascal void  HandleNavEvent( NavEventCallbackMessage callbackSelector,
26                            NavCBRecPtr theCallBackParms, void *callbackUD );
27static pascal void  OpenEventProc( NavEventCallbackMessage callBackSelector,
28                            NavCBRecPtr callBackParams, NavCallBackUserData callBackUD );
29
30
31/*
32 *-----------------------------------------------------------------------------
33 *
34 * GetOneFileWithPreview --
35 *
36 * Display the appropriate file-opening dialog box, with an optional QuickTime
37 * preview pane. If the user selects a file, return information about it using
38 * the theFSSpecPtr parameter.
39 *
40 * Note that both StandardGetFilePreview and NavGetFile use the function
41 * specified by filterProc as a file filter. This framework always passes NULL
42 * in the filterProc parameter. If you use this function in your own code,
43 * keep in mind that on Windows the function specifier must be of type FileFilterUPP
44 * and on Macintosh it must be of type NavObjectFilterUPP.
45 * (You can use the QTFrame_GetFileFilterUPP to create a function specifier of
46 * the appropriate type.)
47 * Also keep in mind that Navigation Services expects a file filter function to
48 * return true if a file is to be displayed, while the Standard File Package
49 * expects the filter to return false if a file is to be displayed.
50 *
51 * Results:
52 *	OSErr
53 *
54 * Side effects:
55 *	Dialog displayed
56 *
57 *-----------------------------------------------------------------------------
58 */
59
60OSErr
61GetOneFileWithPreview(
62        AEDesc          *defaultLocation,
63        short           numTypes,
64        TypeListPtr     typeListPtr,
65        StringPtr 		title,
66        FSSpecPtr       theFSSpecPtr,
67        void            *filterProc )
68{
69	NavReplyRecord		    reply;
70	NavDialogOptions	    dialogOptions;
71	NavTypeListHandle	    openList = NULL;
72	NavEventUPP			    eventUPP = NewNavEventUPP( HandleNavEvent );
73    TextEncoding 			encoding;
74	OSErr				    err = noErr;
75
76	if (theFSSpecPtr == NULL) {
77		return( paramErr );
78    }
79    encoding = GetApplicationTextEncoding();
80
81	/* Specify the options for the dialog box. */
82
83	NavGetDefaultDialogOptions( &dialogOptions );
84	dialogOptions.dialogOptionFlags -= kNavNoTypePopup;
85	dialogOptions.dialogOptionFlags -= kNavAllowMultipleFiles;
86	dialogOptions.dialogOptionFlags |= kNavDontAddTranslateItems;
87    if (title != NULL) {
88        BlockMoveData( title, dialogOptions.clientName, title[0] + 1 );
89    }
90
91	openList = (NavTypeListHandle) CreateOpenHandle( kNavGenericSignature,
92	        numTypes, typeListPtr );
93	if (openList != NULL) {
94		HLock( (Handle) openList );
95	}
96
97	/* Prompt the user for a file. */
98
99	err = NavGetFile( defaultLocation, &reply, &dialogOptions, eventUPP, NULL,
100	        (NavObjectFilterUPP) filterProc, openList, NULL );
101	if ((err == noErr) && reply.validRecord) {
102		AEKeyword		keyword;
103		DescType		actualType;
104		Size			actualSize = 0;
105
106		/* Get the FSSpec for the selected file. */
107
108		if (theFSSpecPtr != NULL) {
109			err = AEGetNthPtr( &(reply.selection), 1, typeFSS, &keyword, &actualType,
110			        theFSSpecPtr, sizeof(FSSpec), &actualSize );
111        }
112		NavDisposeReply( &reply );
113	} else if (err == noErr) {
114	    err = userCanceledErr;
115	}
116	if (openList != NULL) {
117		HUnlock( (Handle) openList );
118		DisposeHandle( (Handle) openList );
119	}
120
121	DisposeNavEventUPP( eventUPP );
122
123	return( err );
124}
125
126/*
127 *-----------------------------------------------------------------------------
128 *
129 * CreateOpenHandle --
130 *
131 *	Get the 'open' resource or dynamically create a NavTypeListHandle.
132 *
133 * Results:
134 *	Handle
135 *
136 * Side effects:
137 *	Memory allocated
138 *
139 *-----------------------------------------------------------------------------
140 */
141
142Handle
143CreateOpenHandle( OSType theApplicationSignature, short numTypes, TypeListPtr typeListPtr )
144{
145	Handle			handle = NULL;
146
147	if (typeListPtr == NULL) {
148		return handle;
149	}
150	if (numTypes > 0) {
151		handle = NewHandle( sizeof(NavTypeList) + (numTypes * sizeof(OSType)) );
152		if (handle != NULL) {
153			NavTypeListHandle 	typeListHand = (NavTypeListHandle) handle;
154
155			(*typeListHand)->componentSignature = theApplicationSignature;
156			(*typeListHand)->osTypeCount = numTypes;
157			BlockMoveData( typeListPtr, (*typeListHand)->osType, numTypes * sizeof(OSType) );
158		}
159	}
160
161	return handle;
162}
163
164/*
165 *-----------------------------------------------------------------------------
166 *
167 * HandleNavEvent --
168 *
169 *
170 * Results:
171 *		None.
172 *
173 * Side effects:
174 *		Events processed.
175 *
176 *-----------------------------------------------------------------------------
177 */
178
179pascal void
180HandleNavEvent( NavEventCallbackMessage callbackSelector, NavCBRecPtr callbackParams, void *callbackUD )
181{
182#pragma unused(callbackUD)
183
184    static SInt32 otherEvent = ~(kNavCBCustomize|kNavCBStart|kNavCBTerminate
185	    |kNavCBNewLocation|kNavCBShowDesktop|kNavCBSelectEntry|kNavCBAccept
186	    |kNavCBCancel|kNavCBAdjustPreview);
187
188	if (callbackSelector == kNavCBEvent) {
189
190#if !TARGET_API_MAC_CARBON
191		switch (callbackParams->eventData.eventDataParms.event->what) {
192
193			case updateEvt:
194        		if (TkMacConvertEvent( callbackParams->eventData.eventDataParms.event)) {
195            		while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT|TCL_WINDOW_EVENTS)) {
196               			/* Empty Body */
197            		}
198            	}
199				break;
200
201			case nullEvent:
202				// Handle Null Event
203				break;
204		}
205#endif
206
207    } else if ( callbackSelector & otherEvent != 0) {
208        while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT|TCL_WINDOW_EVENTS)) {
209            /* Empty Body */
210        }
211	}
212}
213
214/*---------------------------------------------------------------------------*/