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/*---------------------------------------------------------------------------*/