# HG changeset patch # User Steven Tamm # Date 1093544924 0 # Node ID df3c9bb112b359fcd377b638e555c431408fd907 # Parent 2383026ff0d98d4039bf26c2f822dc2aa2dfb092 fileio.c (Fread_file_name): Call x_file_dialog on carbon on tool-bar/menu click macfns.c (Fx_file_dialog): Implemented using NavServices diff -r 2383026ff0d9 -r df3c9bb112b3 src/ChangeLog --- a/src/ChangeLog Thu Aug 26 18:20:52 2004 +0000 +++ b/src/ChangeLog Thu Aug 26 18:28:44 2004 +0000 @@ -1,3 +1,9 @@ +2004-08-26 Steven Tamm + + * fileio.c (Fread_file_name): Call x_file_dialog on carbon on + tool-bar/menu click + * macfns.c (Fx_file_dialog): Implemented using NavServices + 2004-08-24 Jan Dj,Ad(Brv * xterm.c (x_catch_errors_unwind): Do not XSync if display has closed. diff -r 2383026ff0d9 -r df3c9bb112b3 src/fileio.c --- a/src/fileio.c Thu Aug 26 18:20:52 2004 +0000 +++ b/src/fileio.c Thu Aug 26 18:28:44 2004 +0000 @@ -6304,7 +6304,7 @@ GCPRO2 (insdef, default_filename); -#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) +#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) || defined(TARGET_API_MAC_CARBON) if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event)) && use_dialog_box && use_file_dialog diff -r 2383026ff0d9 -r df3c9bb112b3 src/macfns.c --- a/src/macfns.c Thu Aug 26 18:20:52 2004 +0000 +++ b/src/macfns.c Thu Aug 26 18:28:44 2004 +0000 @@ -4192,19 +4192,27 @@ +#ifdef TARGET_API_MAC_CARBON /*********************************************************************** File selection dialog ***********************************************************************/ -#if 0 /* MAC_TODO: can standard file dialog */ +/** + There is a relatively standard way to do this using applescript to run + a (choose file) method. However, this doesn't do "the right thing" + by working only if the find-file occurred during a menu or toolbar + click. So we must do the file dialog by hand, using the navigation + manager. This also has more flexibility in determining the default + directory and whether or not we are going to choose a file. + **/ + extern Lisp_Object Qfile_name_history; DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0, doc: /* Read file name, prompting with PROMPT in directory DIR. Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file selection box, if -specified. Don't let the user enter a file name in the file -selection dialog's entry field, if MUSTMATCH is non-nil. */) +specified. Ensure that file exists if MUSTMATCH is non-nil. */) (prompt, dir, default_filename, mustmatch) Lisp_Object prompt, dir, default_filename, mustmatch; { @@ -4212,9 +4220,8 @@ Lisp_Object file = Qnil; int count = SPECPDL_INDEX (); struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; - char filename[MAX_PATH + 1]; - char init_dir[MAX_PATH + 1]; - int use_dialog_p = 1; + char filename[1001]; + int default_filter_index = 1; /* 1: All Files, 2: Directories only */ GCPRO5 (prompt, dir, default_filename, mustmatch, file); CHECK_STRING (prompt); @@ -4223,87 +4230,150 @@ /* Create the dialog with PROMPT as title, using DIR as initial directory and using "*" as pattern. */ dir = Fexpand_file_name (dir, Qnil); - strncpy (init_dir, SDATA (dir), MAX_PATH); - init_dir[MAX_PATH] = '\0'; - unixtodos_filename (init_dir); - - if (STRINGP (default_filename)) - { - char *file_name_only; - char *full_path_name = SDATA (default_filename); - - unixtodos_filename (full_path_name); - - file_name_only = strrchr (full_path_name, '\\'); - if (!file_name_only) - file_name_only = full_path_name; - else - { - file_name_only++; - - /* If default_file_name is a directory, don't use the open - file dialog, as it does not support selecting - directories. */ - if (!(*file_name_only)) - use_dialog_p = 0; - } - - strncpy (filename, file_name_only, MAX_PATH); - filename[MAX_PATH] = '\0'; + + { + OSStatus status; + NavDialogCreationOptions options; + NavDialogRef dialogRef; + NavTypeListHandle fileTypes = NULL; + NavUserAction userAction; + CFStringRef message=NULL, client=NULL, saveName = NULL; + + /* No need for a callback function because we are modal */ + NavGetDefaultDialogCreationOptions(&options); + options.modality = kWindowModalityAppModal; + options.location.h = options.location.v = -1; + options.optionFlags = kNavDefaultNavDlogOptions; + options.optionFlags |= kNavAllFilesInPopup; /* All files allowed */ + options.optionFlags |= kNavSelectAllReadableItem; + if (!NILP(prompt)) + { + message = CFStringCreateWithCStringNoCopy(NULL, SDATA(prompt), + kCFStringEncodingUTF8, + kCFAllocatorNull); + options.message = message; + } + /* Don't set the application, let it use default. + client = CFStringCreateWithCStringNoCopy(NULL, "Emacs", + kCFStringEncodingMacRoman, NULL); + options.clientName = client; + */ + + /* Do Dired hack copied from w32fns.c */ + if (!NILP(prompt) && strncmp (SDATA(prompt), "Dired", 5) == 0) + status = NavCreateChooseFolderDialog(&options, NULL, NULL, NULL, + &dialogRef); + else if (NILP (mustmatch)) + { + /* This is a save dialog */ + if (!NILP(default_filename)) + { + saveName = CFStringCreateWithCString(NULL, SDATA(default_filename), + kCFStringEncodingUTF8); + options.saveFileName = saveName; + options.optionFlags |= kNavSelectDefaultLocation; + } + /* MAC_TODO: Find a better way to determine if this is a save + or load dialog than comparing dir with default_filename */ + if (EQ(dir, default_filename)) + { + status = NavCreateChooseFileDialog(&options, fileTypes, + NULL, NULL, NULL, NULL, + &dialogRef); + } + else { + status = NavCreatePutFileDialog(&options, + 'TEXT', kNavGenericSignature, + NULL, NULL, &dialogRef); + } + } + else + { + /* This is an open dialog*/ + status = NavCreateChooseFileDialog(&options, fileTypes, + NULL, NULL, NULL, NULL, + &dialogRef); + } + + /* Set the default location and continue*/ + if (status == noErr) { + if (!NILP(dir)) { + FSRef defLoc; + AEDesc defLocAed; + status = FSPathMakeRef(SDATA(dir), &defLoc, NULL); + if (status == noErr) + { + AECreateDesc(typeFSRef, &defLoc, sizeof(FSRef), &defLocAed); + NavCustomControl(dialogRef, kNavCtlSetLocation, (void*) &defLocAed); + } + AEDisposeDesc(&defLocAed); + } + + BLOCK_INPUT; + status = NavDialogRun(dialogRef); + UNBLOCK_INPUT; } - else - filename[0] = '\0'; - - if (use_dialog_p) - { - OPENFILENAME file_details; - char *filename_file; - - /* Prevent redisplay. */ - specbind (Qinhibit_redisplay, Qt); - BLOCK_INPUT; - - bzero (&file_details, sizeof (file_details)); - file_details.lStructSize = sizeof (file_details); - file_details.hwndOwner = FRAME_W32_WINDOW (f); - file_details.lpstrFile = filename; - file_details.nMaxFile = sizeof (filename); - file_details.lpstrInitialDir = init_dir; - file_details.lpstrTitle = SDATA (prompt); - file_details.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; - - if (!NILP (mustmatch)) - file_details.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; - - if (GetOpenFileName (&file_details)) - { - dostounix_filename (filename); - file = build_string (filename); - } - else - file = Qnil; - - UNBLOCK_INPUT; - file = unbind_to (count, file); + + if (saveName) CFRelease(saveName); + if (client) CFRelease(client); + if (message) CFRelease(message); + + if (status == noErr) { + userAction = NavDialogGetUserAction(dialogRef); + switch (userAction) + { + case kNavUserActionNone: + case kNavUserActionCancel: + NavDialogDispose(dialogRef); + Fsignal (Qquit, Qnil); /* Treat cancel like C-g */ + return; + case kNavUserActionOpen: + case kNavUserActionChoose: + case kNavUserActionSaveAs: + { + NavReplyRecord reply; + AEDesc aed; + FSRef fsRef; + status = NavDialogGetReply(dialogRef, &reply); + AECoerceDesc(&reply.selection, typeFSRef, &aed); + AEGetDescData(&aed, (void *) &fsRef, sizeof (FSRef)); + FSRefMakePath(&fsRef, (UInt8 *) filename, 1000); + AEDisposeDesc(&aed); + if (reply.saveFileName) + { + /* If it was a saved file, we need to add the file name */ + int len = strlen(filename); + if (len && filename[len-1] != '/') + filename[len++] = '/'; + CFStringGetCString(reply.saveFileName, filename+len, + 1000-len, kCFStringEncodingUTF8); + } + file = DECODE_FILE(build_string (filename)); + NavDisposeReply(&reply); + } + break; + } + NavDialogDispose(dialogRef); } - /* Open File dialog will not allow folders to be selected, so resort - to minibuffer completing reads for directories. */ - else - file = Fcompleting_read (prompt, intern ("read-file-name-internal"), - dir, mustmatch, dir, Qfile_name_history, - default_filename, Qnil); + else { + /* Fall back on minibuffer if there was a problem */ + file = Fcompleting_read (prompt, intern ("read-file-name-internal"), + dir, mustmatch, dir, Qfile_name_history, + default_filename, Qnil); + } + } UNGCPRO; - + /* Make "Cancel" equivalent to C-g. */ if (NILP (file)) Fsignal (Qquit, Qnil); - + return unbind_to (count, file); } -#endif /* MAC_TODO */ - - + + +#endif /*********************************************************************** Initialization @@ -4507,7 +4577,7 @@ last_show_tip_args = Qnil; staticpro (&last_show_tip_args); -#if 0 /* MAC_TODO */ +#if TARGET_API_MAC_CARBON defsubr (&Sx_file_dialog); #endif }