From 6f987a6c0e78f61f4725eaea8d5af917ae0e512f Mon Sep 17 00:00:00 2001 From: jingham Date: Mon, 17 Apr 2000 02:16:50 +0000 Subject: Add Navigation Services support. --- mac/tkMacDialog.c | 851 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 716 insertions(+), 135 deletions(-) diff --git a/mac/tkMacDialog.c b/mac/tkMacDialog.c index cfd1863..51c250c 100644 --- a/mac/tkMacDialog.c +++ b/mac/tkMacDialog.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacDialog.c,v 1.4 1999/05/22 06:32:42 jingham Exp $ + * RCS: @(#) $Id: tkMacDialog.c,v 1.5 2000/04/17 02:16:50 jingham Exp $ */ #include @@ -20,6 +20,7 @@ #include #include #include +#include #include "tkPort.h" #include "tkInt.h" #include "tclMacInt.h" @@ -43,6 +44,7 @@ #define SAVE_FILE 0 #define OPEN_FILE 1 +#define CHOOSE_FOLDER 2 #define MATCHED 0 #define UNMATCHED 1 @@ -62,24 +64,46 @@ typedef struct _OpenFileData { * -filetypes option is set). */ } OpenFileData; + static pascal Boolean FileFilterProc _ANSI_ARGS_((CInfoPBPtr pb, void *myData)); static int GetFileName _ANSI_ARGS_ ((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int isOpen)); -static Boolean MatchOneType _ANSI_ARGS_((CInfoPBPtr pb, +static int NavGetFileName _ANSI_ARGS_ ((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[], int isOpen)); +static Boolean MatchOneType _ANSI_ARGS_((StringPtr fileNamePtr, OSType fileType, OpenFileData *myofdPtr, FileFilter *filterPtr)); static pascal short OpenHookProc _ANSI_ARGS_((short item, DialogPtr theDialog, OpenFileData * myofdPtr)); static int ParseFileDlgArgs _ANSI_ARGS_ ((Tcl_Interp * interp, OpenFileData * myofdPtr, int argc, char ** argv, int isOpen)); - +static pascal Boolean OpenFileFilterProc(AEDesc* theItem, void* info, + NavCallBackUserData callBackUD, + NavFilterModes filterMode ); +pascal void OpenEventProc(NavEventCallbackMessage callBackSelector, + NavCBRecPtr callBackParms, + NavCallBackUserData callBackUD ); +static void InitFileDialogs(); +static int StdGetFile(Tcl_Interp *interp, OpenFileData *ofd, + unsigned char *initialFile, int isOpen); +static int NavServicesGetFile(Tcl_Interp *interp, OpenFileData *ofd, + AEDesc *initialDesc, unsigned char *initialFile, + StringPtr title, StringPtr message, int multiple, int isOpen); +static int HandleInitialDirectory (Tcl_Interp *interp, char *initialDir, FSSpec *dirSpec, + AEDesc *dirDescPtr); /* * Filter and hook functions used by the tk_getOpenFile and tk_getSaveFile * commands. */ +int fileDlgInited = 0; +int useNavServices = 0; +NavObjectFilterUPP openFileFilterUPP; +NavEventUPP openFileEventUPP; + static FileFilterYDUPP openFilter = NULL; static DlgHookYDUPP openHook = NULL; static DlgHookYDUPP saveHook = NULL; @@ -274,7 +298,121 @@ Tk_GetOpenFileObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[]) /* Argument objects. */ { - return GetFileName(clientData, interp, objc, objv, OPEN_FILE); + int i, result, multiple; + OpenFileData ofd; + Tk_Window parent; + Str255 message, title; + AEDesc initialDesc = {typeNull, NULL}; + FSSpec dirSpec; + static char *openOptionStrings[] = { + "-filetypes", "-initialdir", "-message", "-multiple", + "-parent", "-title", NULL + }; + enum openOptions { + OPEN_TYPES, OPEN_INITDIR, OPEN_MESSAGE, OPEN_MULTIPLE, + OPEN_PARENT, OPEN_TITLE + }; + + if (!fileDlgInited) { + InitFileDialogs(); + } + + result = TCL_ERROR; + parent = (Tk_Window) clientData; + multiple = false; + title[0] = 0; + message[0] = 0; + + TkInitFileFilters(&ofd.fl); + + ofd.curType = 0; + ofd.popupItem = OPEN_POPUP_ITEM; + ofd.usePopup = 1; + + for (i = 1; i < objc; i += 2) { + char *choice; + int index, choiceLen; + char *string; + int srcRead, dstWrote; + + if (Tcl_GetIndexFromObj(interp, objv[i], openOptionStrings, "option", + TCL_EXACT, &index) != TCL_OK) { + result = TCL_ERROR; + goto end; + } + if (i + 1 == objc) { + string = Tcl_GetStringFromObj(objv[i], NULL); + Tcl_AppendResult(interp, "value for \"", string, "\" missing", + (char *) NULL); + result = TCL_ERROR; + goto end; + } + + switch (index) { + case OPEN_TYPES: + choice = Tcl_GetStringFromObj(objv[i + 1], NULL); + if (TkGetFileFilters(interp, &ofd.fl, choice, 0) + != TCL_OK) { + result = TCL_ERROR; + goto end; + } + break; + case OPEN_INITDIR: + choice = Tcl_GetStringFromObj(objv[i + 1], NULL); + if (HandleInitialDirectory(interp, choice, &dirSpec, + &initialDesc) != TCL_OK) { + result = TCL_ERROR; + goto end; + } + break; + case OPEN_MESSAGE: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + Tcl_UtfToExternal(NULL, NULL, choice, choiceLen, + 0, NULL, StrBody(message), 255, + &srcRead, &dstWrote, NULL); + message[0] = dstWrote; + break; + case OPEN_MULTIPLE: + if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &multiple) != TCL_OK) { + result = TCL_ERROR; + goto end; + } + break; + case OPEN_PARENT: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + parent = Tk_NameToWindow(interp, choice, parent); + if (parent == NULL) { + result = TCL_ERROR; + goto end; + } + break; + case OPEN_TITLE: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + Tcl_UtfToExternal(NULL, NULL, choice, choiceLen, + 0, NULL, StrBody(title), 255, + &srcRead, &dstWrote, NULL); + title[0] = dstWrote; + break; + } + } + + if (useNavServices) { + AEDesc *initialPtr = NULL; + + if (initialDesc.descriptorType == typeFSS) { + initialPtr = &initialDesc; + } + result = NavServicesGetFile(interp, &ofd, initialPtr, NULL, + title, message, multiple, OPEN_FILE); + } else { + result = StdGetFile(interp, &ofd, NULL, OPEN_FILE); + } + + end: + TkFreeFileFilters(&ofd.fl); + AEDisposeDesc(&initialDesc); + + return result; } /* @@ -300,69 +438,180 @@ Tk_GetSaveFileObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[]) /* Argument objects. */ { - return GetFileName(clientData, interp, objc, objv, SAVE_FILE); + int i, result; + Str255 initialFile; + Tk_Window parent; + AEDesc initialDesc = {typeNull, NULL}; + FSSpec dirSpec; + Str255 title, message; + OpenFileData ofd; + static char *saveOptionStrings[] = { + "-defaultextension", "-initialdir", "-initialfile", + "-message", "-parent", "-title", NULL + }; + enum saveOptions { + SAVE_DEFAULT, SAVE_INITDIR, SAVE_INITFILE, + SAVE_MESSAGE, SAVE_PARENT, SAVE_TITLE + }; + + if (!fileDlgInited) { + InitFileDialogs(); + } + + result = TCL_ERROR; + parent = (Tk_Window) clientData; + StrLength(initialFile) = 0; + title[0] = 0; + message[0] = 0; + + + for (i = 1; i < objc; i += 2) { + char *choice; + int index, choiceLen; + char *string; + Tcl_DString ds; + int srcRead, dstWrote; + + if (Tcl_GetIndexFromObj(interp, objv[i], saveOptionStrings, "option", + TCL_EXACT, &index) != TCL_OK) { + return TCL_ERROR; + } + if (i + 1 == objc) { + string = Tcl_GetStringFromObj(objv[i], NULL); + Tcl_AppendResult(interp, "value for \"", string, "\" missing", + (char *) NULL); + return TCL_ERROR; + } + switch (index) { + case SAVE_DEFAULT: + break; + case SAVE_INITDIR: + choice = Tcl_GetStringFromObj(objv[i + 1], NULL); + if (HandleInitialDirectory(interp, choice, &dirSpec, + &initialDesc) != TCL_OK) { + result = TCL_ERROR; + goto end; + } + break; + case SAVE_INITFILE: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + if (Tcl_TranslateFileName(interp, choice, &ds) == NULL) { + result = TCL_ERROR; + goto end; + } + Tcl_UtfToExternal(NULL, NULL, Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds), 0, NULL, + StrBody(initialFile), 255, &srcRead, &dstWrote, NULL); + StrLength(initialFile) = (unsigned char) dstWrote; + Tcl_DStringFree(&ds); + break; + case SAVE_MESSAGE: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + Tcl_UtfToExternal(NULL, NULL, choice, choiceLen, + 0, NULL, StrBody(message), 255, + &srcRead, &dstWrote, NULL); + StrLength(message) = (unsigned char) dstWrote; + break; + case SAVE_PARENT: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + parent = Tk_NameToWindow(interp, choice, parent); + if (parent == NULL) { + result = TCL_ERROR; + goto end; + } + break; + case SAVE_TITLE: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + Tcl_UtfToExternal(NULL, NULL, choice, choiceLen, + 0, NULL, StrBody(title), 255, + &srcRead, &dstWrote, NULL); + StrLength(title) = (unsigned char) dstWrote; + break; + } + } + + TkInitFileFilters(&ofd.fl); + ofd.usePopup = 0; + + if (useNavServices) { + AEDesc *initialPtr = NULL; + + if (initialDesc.descriptorType == typeFSS) { + initialPtr = &initialDesc; + } + result = NavServicesGetFile(interp, &ofd, initialPtr, initialFile, + title, message, false, SAVE_FILE); + } else { + result = StdGetFile(interp, NULL, initialFile, SAVE_FILE); + } + + end: + + AEDisposeDesc(&initialDesc); + + return result; } /* *---------------------------------------------------------------------- * - * GetFileName -- + * Tk_ChooseDirectoryObjCmd -- * - * Calls the Mac file dialog functions for the user to choose a - * file to or save. + * This procedure implements the "tk_chooseDirectory" dialog box + * for the Windows platform. See the user documentation for details + * on what it does. * * Results: - * A standard Tcl result. + * See user documentation. * * Side effects: - * If the user selects a file, the native pathname of the file - * is returned in the interp's result. Otherwise an empty string - * is returned in the interp's result. + * A modal dialog window is created. Tcl_SetServiceMode() is + * called to allow background events to be processed * *---------------------------------------------------------------------- */ -static int -GetFileName( - ClientData clientData, /* Main window associated with interpreter. */ - Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ - Tcl_Obj *CONST objv[], /* Argument objects. */ - int isOpen) /* true if we should call GetOpenFileName(), - * false if we should call GetSaveFileName() */ +int +Tk_ChooseDirectoryObjCmd(clientData, interp, objc, objv) + ClientData clientData; /* Main window associated with interpreter. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { int i, result; - OpenFileData ofd; - StandardFileReply reply; - Point mypoint; - MenuHandle menu; - Str255 initialFile; - char *choice[6]; Tk_Window parent; - static char *optionStrings[] = { - "-defaultextension", "-filetypes", "-initialdir", "-initialfile", - "-parent", "-title", NULL + AEDesc initialDesc = {typeNull, NULL}; + FSSpec dirSpec; + Str255 message, title; + int srcRead, dstWrote; + OpenFileData ofd; + static char *chooseOptionStrings[] = { + "-initialdir", "-message", "-mustexist", "-parent", "-title", NULL }; - enum options { - FILE_DEFAULT, FILE_TYPES, FILE_INITDIR, FILE_INITFILE, - FILE_PARENT, FILE_TITLE + enum chooseOptions { + CHOOSE_INITDIR, CHOOSE_MESSAGE, CHOOSE_MUSTEXIST, + CHOOSE_PARENT, CHOOSE_TITLE }; + + + if (!NavServicesAvailable()) { + return TCL_ERROR; + } - if (openFilter == NULL) { - openFilter = NewFileFilterYDProc(FileFilterProc); - openHook = NewDlgHookYDProc(OpenHookProc); - saveHook = NewDlgHookYDProc(OpenHookProc); + if (!fileDlgInited) { + InitFileDialogs(); } - result = TCL_ERROR; parent = (Tk_Window) clientData; - memset(choice, 0, sizeof(choice)); + title[0] = 0; + message[0] = 0; for (i = 1; i < objc; i += 2) { - int index; + char *choice; + int index, choiceLen; char *string; - if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", + if (Tcl_GetIndexFromObj(interp, objv[i], chooseOptionStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } @@ -372,35 +621,77 @@ GetFileName( (char *) NULL); return TCL_ERROR; } - choice[index] = Tcl_GetStringFromObj(objv[i + 1], NULL); + switch (index) { + case CHOOSE_INITDIR: + choice = Tcl_GetStringFromObj(objv[i + 1], NULL); + if (HandleInitialDirectory(interp, choice, &dirSpec, + &initialDesc) != TCL_OK) { + result = TCL_ERROR; + goto end; + } + break; + case CHOOSE_MESSAGE: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + Tcl_UtfToExternal(NULL, NULL, choice, choiceLen, + 0, NULL, StrBody(message), 255, + &srcRead, &dstWrote, NULL); + StrLength(message) = (unsigned char) dstWrote; + break; + case CHOOSE_PARENT: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + parent = Tk_NameToWindow(interp, choice, parent); + if (parent == NULL) { + result = TCL_ERROR; + goto end; + } + break; + case CHOOSE_TITLE: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + Tcl_UtfToExternal(NULL, NULL, choice, choiceLen, + 0, NULL, StrBody(title), 255, + &srcRead, &dstWrote, NULL); + StrLength(title) = (unsigned char) dstWrote; + break; + } } - - StrLength(initialFile) = 0; - menu = NULL; - + TkInitFileFilters(&ofd.fl); - ofd.curType = 0; - ofd.popupItem = OPEN_POPUP_ITEM; - ofd.usePopup = isOpen; - - if (choice[FILE_TYPES] != NULL) { - if (TkGetFileFilters(interp, &ofd.fl, choice[FILE_TYPES], 0) != TCL_OK) { - goto end; + ofd.usePopup = 0; + + if (useNavServices) { + AEDesc *initialPtr = NULL; + + if (initialDesc.descriptorType == typeFSS) { + initialPtr = &initialDesc; } + result = NavServicesGetFile(interp, &ofd, initialPtr, NULL, + title, message, false, CHOOSE_FOLDER); + } else { + result = TCL_ERROR; } - if (choice[FILE_INITDIR] != NULL) { - FSSpec dirSpec; + + end: + AEDisposeDesc(&initialDesc); + + return result; +} + +int +HandleInitialDirectory ( + Tcl_Interp *interp, + char *initialDir, + FSSpec *dirSpec, + AEDesc *dirDescPtr) +{ Tcl_DString ds; long dirID; OSErr err; Boolean isDirectory; - char *string; Str255 dir; int srcRead, dstWrote; - string = choice[FILE_INITDIR]; - if (Tcl_TranslateFileName(interp, string, &ds) == NULL) { - goto end; + if (Tcl_TranslateFileName(interp, initialDir, &ds) == NULL) { + return TCL_ERROR; } Tcl_UtfToExternal(NULL, NULL, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds), 0, NULL, StrBody(dir), 255, @@ -408,46 +699,360 @@ GetFileName( StrLength(dir) = (unsigned char) dstWrote; Tcl_DStringFree(&ds); - err = FSpLocationFromPath(StrLength(dir), StrBody(dir), &dirSpec); + err = FSpLocationFromPath(StrLength(dir), StrBody(dir), dirSpec); if (err != noErr) { - Tcl_AppendResult(interp, "bad directory \"", string, "\"", NULL); - goto end; + Tcl_AppendResult(interp, "bad directory \"", initialDir, "\"", NULL); + return TCL_ERROR; } - err = FSpGetDirectoryID(&dirSpec, &dirID, &isDirectory); + err = FSpGetDirectoryID(dirSpec, &dirID, &isDirectory); if ((err != noErr) || !isDirectory) { - Tcl_AppendResult(interp, "bad directory \"", string, "\"", NULL); - goto end; + Tcl_AppendResult(interp, "bad directory \"", initialDir, "\"", NULL); + return TCL_ERROR; } - /* - * Make sure you negate -dirSpec.vRefNum because the - * standard file package wants it that way ! - */ + + if (useNavServices) { + AECreateDesc( typeFSS, dirSpec, sizeof(*dirSpec), dirDescPtr); + } else { + /* + * Make sure you negate -dirSpec.vRefNum because the + * standard file package wants it that way ! + */ - LMSetSFSaveDisk(-dirSpec.vRefNum); - LMSetCurDirStore(dirID); + LMSetSFSaveDisk(-dirSpec->vRefNum); + LMSetCurDirStore(dirID); + } + return TCL_OK; +} + +static void +InitFileDialogs() +{ + fileDlgInited = 1; + + if (NavServicesAvailable()) { + openFileFilterUPP = NewNavObjectFilterProc(OpenFileFilterProc); + openFileEventUPP = NewNavEventProc(OpenEventProc); + useNavServices = 1; + } else { + openFilter = NewFileFilterYDProc(FileFilterProc); + openHook = NewDlgHookYDProc(OpenHookProc); + saveHook = NewDlgHookYDProc(OpenHookProc); + useNavServices = 0; } - if (choice[FILE_INITFILE] != NULL) { - Tcl_DString ds; - int srcRead, dstWrote; + - if (Tcl_TranslateFileName(interp, choice[FILE_INITFILE], &ds) == NULL) { - goto end; - } - Tcl_UtfToExternal(NULL, NULL, Tcl_DStringValue(&ds), - Tcl_DStringLength(&ds), 0, NULL, - StrBody(initialFile), 255, &srcRead, &dstWrote, NULL); - StrLength(initialFile) = (unsigned char) dstWrote; - Tcl_DStringFree(&ds); - } - if (choice[FILE_PARENT] != NULL) { - parent = Tk_NameToWindow(interp, choice[FILE_PARENT], parent); - if (parent == NULL) { - return TCL_ERROR; +} + + +/* + *---------------------------------------------------------------------- + * + * GetFileName -- + * + * Calls the Mac file dialog functions for the user to choose a + * file to or save. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * If the user selects a file, the native pathname of the file + * is returned in the interp's result. Otherwise an empty string + * is returned in the interp's result. + * + *---------------------------------------------------------------------- + */ + +static int +GetFileName( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[], /* Argument objects. */ + int isOpen) /* true if we should call GetOpenFileName(), + * false if we should call GetSaveFileName() */ +{ + return TCL_OK; +} + +static int +NavServicesGetFile( + Tcl_Interp *interp, + OpenFileData *ofdPtr, + AEDesc *initialDesc, + unsigned char *initialFile, + StringPtr title, + StringPtr message, + int multiple, + int isOpen) +{ + NavReplyRecord theReply; + NavDialogOptions diagOptions; + OSErr err; + Tcl_Obj *theResult; + int result; + + + diagOptions.location.h = -1; + diagOptions.location.v = -1; + diagOptions.dialogOptionFlags = kNavDontAutoTranslate + + kNavDontAddTranslateItems; + + if (multiple) { + diagOptions.dialogOptionFlags += kNavAllowMultipleFiles; + } + + if (ofdPtr != NULL && ofdPtr->usePopup) { + FileFilter *filterPtr; + + filterPtr = ofdPtr->fl.filters; + if (filterPtr == NULL) { + ofdPtr->usePopup = 0; } } + + if (ofdPtr != NULL && ofdPtr->usePopup) { + NavMenuItemSpecHandle popupExtensionHandle = NULL; + NavMenuItemSpec *popupItems; + FileFilter *filterPtr; + short index = 0; + + ofdPtr->curType = 0; + + popupExtensionHandle = (NavMenuItemSpecHandle) NewHandle(ofdPtr->fl.numFilters + * sizeof(NavMenuItemSpec)); + HLock((Handle) popupExtensionHandle); + popupItems = *popupExtensionHandle; + + for (filterPtr = ofdPtr->fl.filters; filterPtr != NULL; + filterPtr = filterPtr->next, popupItems++, index++) { + int len; + + len = strlen(filterPtr->name); + BlockMove(filterPtr->name, popupItems->menuItemName + 1, len); + popupItems->menuItemName[0] = len; + popupItems->menuCreator = 'WIsH'; + popupItems->menuType = index; + } + HUnlock((Handle) popupExtensionHandle); + diagOptions.popupExtension = popupExtensionHandle; + } else { + diagOptions.dialogOptionFlags += kNavNoTypePopup; + diagOptions.popupExtension = NULL; + } + + if ((initialFile != NULL) && (initialFile[0] != 0)) { + char *lastColon; + int len; + + len = initialFile[0]; + + p2cstr(initialFile); + lastColon = strrchr((char *)initialFile, ':'); + if (lastColon != NULL) { + len -= lastColon - ((char *) (initialFile + 1)); + BlockMove(lastColon + 1, diagOptions.savedFileName + 1, len); + diagOptions.savedFileName[0] = len; + } else { + BlockMove(initialFile, diagOptions.savedFileName + 1, len); + diagOptions.savedFileName[0] = len; + } + } else { + diagOptions.savedFileName[0] = 0; + } + + strcpy((char *) (diagOptions.clientName + 1),"Wish"); + diagOptions.clientName[0] = strlen("Wish"); + + if (title == NULL) { + diagOptions.windowTitle[0] = 0; + } else { + BlockMove(title, diagOptions.windowTitle, title[0] + 1); + diagOptions.windowTitle[0] = title[0]; + } + + if (message == NULL) { + diagOptions.message[0] = 0; + } else { + BlockMove(message, diagOptions.message, message[0] + 1); + diagOptions.message[0] = message[0]; + } + + diagOptions.actionButtonLabel[0] = 0; + diagOptions.cancelButtonLabel[0] = 0; + diagOptions.preferenceKey = 0; + + /* Now process the selection list. We have to use the popupExtension + * to fill the menu. + */ + + + if (isOpen == OPEN_FILE) { + err = NavGetFile(initialDesc, &theReply, &diagOptions, openFileEventUPP, + NULL, openFileFilterUPP, NULL, ofdPtr); + } else if (isOpen == SAVE_FILE) { + err = NavPutFile (initialDesc, &theReply, &diagOptions, openFileEventUPP, + 'TEXT', 'WIsH', NULL); + } else if (isOpen == CHOOSE_FOLDER) { + err = NavChooseFolder (initialDesc, &theReply, &diagOptions, + openFileEventUPP, NULL, NULL); + } + + theResult = Tcl_NewListObj(0, NULL); + + if ( theReply.validRecord && err == noErr ) { + AEDesc resultDesc; + long count; + Tcl_DString fileName; + Handle pathHandle; + int length; + + if ( err == noErr ) { + err = AECountItems(&(theReply.selection), &count); + if (err == noErr) { + long i; + for (i = 1; i <= count; i++ ) { + err = AEGetNthDesc(&(theReply.selection), + i, typeFSS, NULL, &resultDesc); + if (err == noErr) { + HLock(resultDesc.dataHandle); + pathHandle = NULL; + FSpPathFromLocation((FSSpec *) *resultDesc.dataHandle, + &length, &pathHandle); + HLock(pathHandle); + Tcl_ExternalToUtfDString(NULL, (char *) *pathHandle, -1, &fileName); + Tcl_ListObjAppendElement(interp, theResult, + Tcl_NewStringObj(Tcl_DStringValue(&fileName), + Tcl_DStringLength(&fileName))); + Tcl_DStringFree(&fileName); + HUnlock(pathHandle); + DisposeHandle(pathHandle); + HUnlock(resultDesc.dataHandle); + AEDisposeDesc( &resultDesc ); + } + } + } + } + err = NavDisposeReply( &theReply ); + Tcl_SetObjResult(interp, theResult); + result = TCL_OK; + } else if (err == userCanceledErr) { + result = TCL_OK; + } else { + result = TCL_ERROR; + } + + if (diagOptions.popupExtension != NULL) { + DisposeHandle((Handle) diagOptions.popupExtension); + } + + return result; +} + +static pascal Boolean +OpenFileFilterProc( + AEDesc* theItem, void* info, + NavCallBackUserData callBackUD, + NavFilterModes filterMode ) +{ + OpenFileData *ofdPtr = (OpenFileData *) callBackUD; + if (!ofdPtr->usePopup) { + return true; + } else { + if (ofdPtr->fl.numFilters == 0) { + return true; + } else { + + if ( theItem->descriptorType == typeFSS ) { + NavFileOrFolderInfo* theInfo = (NavFileOrFolderInfo*)info; + int result; + + if ( !theInfo->isFolder ) { + OSType fileType; + StringPtr fileNamePtr; + int i; + FileFilter *filterPtr; + + fileType = theInfo->fileAndFolder.fileInfo.finderInfo.fdType; + HLock(theItem->dataHandle); + fileNamePtr = (((FSSpec *) *theItem->dataHandle)->name); + + if (ofdPtr->usePopup) { + i = ofdPtr->curType; + for (filterPtr=ofdPtr->fl.filters; filterPtr && i>0; i--) { + filterPtr = filterPtr->next; + } + if (filterPtr) { + result = MatchOneType(fileNamePtr, fileType, + ofdPtr, filterPtr); + } else { + result = false; + } + } else { + /* + * We are not using the popup menu. In this case, the file is + * considered matched if it matches any of the file filters. + */ + result = UNMATCHED; + for (filterPtr=ofdPtr->fl.filters; filterPtr; + filterPtr=filterPtr->next) { + if (MatchOneType(fileNamePtr, fileType, + ofdPtr, filterPtr) == MATCHED) { + result = MATCHED; + break; + } + } + } + + HUnlock(theItem->dataHandle); + return (result == MATCHED); + } else { + return true; + } + } + } + + return true; + } +} + +pascal void +OpenEventProc( + NavEventCallbackMessage callBackSelector, + NavCBRecPtr callBackParams, + NavCallBackUserData callBackUD ) +{ + NavMenuItemSpec *chosenItem; + OpenFileData *ofd = (OpenFileData *) callBackUD; + static SInt32 otherEvent = ~(kNavCBCustomize|kNavCBStart|kNavCBTerminate + |kNavCBNewLocation|kNavCBShowDesktop|kNavCBSelectEntry|kNavCBAccept + |kNavCBCancel|kNavCBAdjustPreview); + + if (callBackSelector == kNavCBPopupMenuSelect) { + chosenItem = (NavMenuItemSpec *) callBackParams->eventData.eventDataParms.param; + ofd->curType = chosenItem->menuType; + } else if (callBackSelector == kNavCBAdjustRect || callBackSelector & otherEvent != 0) { + while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT|TCL_WINDOW_EVENTS)) { + /* Empty Body */ + } + } +} + +static int +StdGetFile( + Tcl_Interp *interp, + OpenFileData *ofd, + unsigned char *initialFile, + int isOpen) +{ + int i; + StandardFileReply reply; + Point mypoint; + MenuHandle menu = NULL; + /* - * 2. Set the items in the file types popup. + * Set the items in the file types popup. */ /* @@ -455,7 +1060,7 @@ GetFileName( * left overs from previous invocation of this command */ - if (ofd.usePopup) { + if (ofd != NULL && ofd->usePopup) { FileFilter *filterPtr; menu = GetMenu(OPEN_MENU); @@ -469,9 +1074,9 @@ GetFileName( DeleteMenuItem(menu, i); } - filterPtr = ofd.fl.filters; + filterPtr = ofd->fl.filters; if (filterPtr == NULL) { - ofd.usePopup = 0; + ofd->usePopup = 0; } else { for ( ; filterPtr != NULL; filterPtr = filterPtr->next) { Str255 str; @@ -484,33 +1089,37 @@ GetFileName( } /* - * 3. Call the toolbox file dialog function. + * Call the toolbox file dialog function. */ SetPt(&mypoint, -1, -1); TkpSetCursor(NULL); - if (isOpen) { - if (ofd.usePopup) { + if (isOpen == OPEN_FILE) { + if (ofd != NULL && ofd->usePopup) { CustomGetFile(openFilter, (short) -1, NULL, &reply, OPEN_BOX, mypoint, openHook, NULL, NULL, NULL, (void*) &ofd); } else { StandardGetFile(NULL, -1, NULL, &reply); } - } else { + } else if (isOpen == SAVE_FILE) { static Str255 prompt = "\pSave as"; - if (ofd.usePopup) { + if (ofd != NULL && ofd->usePopup) { /* * Currently this never gets called because we don't use * popup for the save dialog. */ CustomPutFile(prompt, initialFile, &reply, OPEN_BOX, - mypoint, saveHook, NULL, NULL, NULL, (void *) &ofd); + mypoint, saveHook, NULL, NULL, NULL, (void *) ofd); } else { StandardPutFile(prompt, initialFile, &reply); } } + /* + * Now parse the reply, and populate the Tcl result. + */ + if (reply.sfGood) { int length; Handle pathHandle; @@ -529,14 +1138,11 @@ GetFileName( } } - result = TCL_OK; - - end: - TkFreeFileFilters(&ofd.fl); if (menu != NULL) { DisposeMenu(menu); } - return result; + + return TCL_OK; } /* *---------------------------------------------------------------------- @@ -649,7 +1255,8 @@ FileFilterProc( filterPtr = filterPtr->next; } if (filterPtr) { - return MatchOneType(pb, ofdPtr, filterPtr); + return MatchOneType(pb->hFileInfo.ioNamePtr, pb->hFileInfo.ioFlFndrInfo.fdType, + ofdPtr, filterPtr); } else { return UNMATCHED; } @@ -661,7 +1268,8 @@ FileFilterProc( for (filterPtr=ofdPtr->fl.filters; filterPtr; filterPtr=filterPtr->next) { - if (MatchOneType(pb, ofdPtr, filterPtr) == MATCHED) { + if (MatchOneType(pb->hFileInfo.ioNamePtr, pb->hFileInfo.ioFlFndrInfo.fdType, + ofdPtr, filterPtr) == MATCHED) { return MATCHED; } } @@ -688,7 +1296,8 @@ FileFilterProc( static Boolean MatchOneType( - CInfoPBPtr pb, /* Information about the file */ + StringPtr fileNamePtr, /* Name of the file */ + OSType fileType, /* Type of the file */ OpenFileData * ofdPtr, /* Information about this file dialog */ FileFilter * filterPtr) /* Match the file described by pb against * this filter */ @@ -730,10 +1339,10 @@ MatchOneType( int len; char * p, *q, *ext; - if (pb->hFileInfo.ioNamePtr == NULL) { + if (fileNamePtr == NULL) { continue; } - p = (char*)(pb->hFileInfo.ioNamePtr); + p = (char*)(fileNamePtr); len = p[0]; strncpy(filename, p+1, len); filename[len] = '\0'; @@ -767,7 +1376,7 @@ MatchOneType( } for (mfPtr=clausePtr->macTypes; mfPtr; mfPtr=mfPtr->next) { - if (pb->hFileInfo.ioFlFndrInfo.fdType == mfPtr->type) { + if (fileType == mfPtr->type) { macMatched = 1; break; } @@ -780,33 +1389,5 @@ MatchOneType( return UNMATCHED; } -/* - *---------------------------------------------------------------------- - * - * Tk_ChooseDirectoryObjCmd -- - * - * This procedure implements the "tk_chooseDirectory" dialog box - * for the Windows platform. See the user documentation for details - * on what it does. - * - * Results: - * See user documentation. - * - * Side effects: - * A modal dialog window is created. Tcl_SetServiceMode() is - * called to allow background events to be processed - * - *---------------------------------------------------------------------- - */ - -int -Tk_ChooseDirectoryObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ -{ - return TCL_ERROR; -} -- cgit v0.12