\f
+#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;
{
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);
/* 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';
- }
- else
- filename[0] = '\0';
- if (use_dialog_p)
- {
- OPENFILENAME file_details;
- char *filename_file;
+ {
+ 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);
+ }
- /* Prevent redisplay. */
- specbind (Qinhibit_redisplay, Qt);
BLOCK_INPUT;
+ status = NavDialogRun(dialogRef);
+ UNBLOCK_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 (saveName) CFRelease(saveName);
+ if (client) CFRelease(client);
+ if (message) CFRelease(message);
- if (GetOpenFileName (&file_details))
- {
- dostounix_filename (filename);
- file = build_string (filename);
- }
- else
- file = Qnil;
-
- UNBLOCK_INPUT;
- file = unbind_to (count, file);
+ 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
\f
/***********************************************************************
Initialization
last_show_tip_args = Qnil;
staticpro (&last_show_tip_args);
-#if 0 /* MAC_TODO */
+#if TARGET_API_MAC_CARBON
defsubr (&Sx_file_dialog);
#endif
}