changeset 57868:c955f6add62a

* fileio.c (Fread_file_name): Pass Qt as fifth parameter to Fx_file_dialog if only directories should be read. * lisp.h: Fx_file_dialog takes 5 parameters. * xfns.c (Fx_file_dialog): Both Motif and GTK version: Add parameter only_dir_p. In Motif version, don't put DEFAULT_FILENAME in filter part of the dialog, just text field part. Do not add DEFAULT_FILENAME to list of files if it isn't there. In GTK version, pass only_dir_p parameter to xg_get_file_name. * macfns.c (Fx_file_dialog): Add parameter only_dir_p. Check only_dir_p instead of comparing prompt to "Dired". When using a save dialog, add option kNavDontConfirmReplacement, change title to "Enter name", change text for save button to "Ok". * w32fns.c (Fx_file_dialog): Add parameter only_dir_p. Check only_dir_p instead of comparing prompt to "Dired". * gtkutil.c (xg_get_file_with_chooser) (xg_get_file_with_selection): New functions, only defined ifdef HAVE_GTK_FILE_CHOOSER_DIALOG_NEW and HAVE_GTK_FILE_SELECTION_NEW respectively. (xg_get_file_name): Add parameter only_dir_p. Call xg_get_file_with_chooser or xg_get_file_with_selection depending on HAVE_GTK_FILE* and the value of use_old_gtk_file_dialog. (xg_initialize): New DEFVAR_BOOL use_old_gtk_file_dialog. * gtkutil.h (xg_get_file_name): Add parameter only_dir_p.
author Jan Djärv <jan.h.d@swipnet.se>
date Tue, 02 Nov 2004 08:21:16 +0000
parents 5a547995da89
children 646473e416c8
files src/ChangeLog src/fileio.c src/gtkutil.c src/gtkutil.h src/lisp.h src/macfns.c src/w32fns.c src/xfns.c
diffstat 8 files changed, 231 insertions(+), 82 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Tue Nov 02 07:57:53 2004 +0000
+++ b/src/ChangeLog	Tue Nov 02 08:21:16 2004 +0000
@@ -1,5 +1,36 @@
 2004-11-02  Jan Dj,Ad(Brv  <jan.h.d@swipnet.se>
 
+	* fileio.c (Fread_file_name): Pass Qt as fifth parameter to
+	Fx_file_dialog if only directories should be read.
+
+	* lisp.h: Fx_file_dialog takes 5 parameters.
+
+	* xfns.c (Fx_file_dialog): Both Motif and GTK version:  Add
+	parameter only_dir_p.
+	In Motif version, don't put DEFAULT_FILENAME in filter part of the
+	dialog, just text field part.  Do not add DEFAULT_FILENAME
+	to list of files if it isn't there.
+	In GTK version, pass only_dir_p parameter to xg_get_file_name.
+
+	* macfns.c (Fx_file_dialog): Add parameter only_dir_p.  Check
+	only_dir_p instead of comparing prompt to "Dired".  When using
+	a save dialog, add option kNavDontConfirmReplacement, change title
+	to "Enter name", change text for save button to "Ok".
+
+	* w32fns.c (Fx_file_dialog): Add parameter only_dir_p.  Check
+	only_dir_p instead of comparing prompt to "Dired".
+
+	* gtkutil.c (xg_get_file_with_chooser)
+	(xg_get_file_with_selection): New functions, only defined ifdef
+	HAVE_GTK_FILE_CHOOSER_DIALOG_NEW and HAVE_GTK_FILE_SELECTION_NEW
+	respectively.
+	(xg_get_file_name): Add parameter only_dir_p.
+	Call xg_get_file_with_chooser or xg_get_file_with_selection
+	depending on HAVE_GTK_FILE* and the value of use_old_gtk_file_dialog.
+	(xg_initialize): New DEFVAR_BOOL use_old_gtk_file_dialog.
+
+	* gtkutil.h (xg_get_file_name): Add parameter only_dir_p.
+
 	* config.in: Rebuild (added HAVE_GTK_FILE_*).
 
 2004-11-01  Kim F. Storm  <storm@cua.dk>
--- a/src/fileio.c	Tue Nov 02 07:57:53 2004 +0000
+++ b/src/fileio.c	Tue Nov 02 08:21:16 2004 +0000
@@ -6321,7 +6321,8 @@
 	}
       if (!NILP(default_filename))
         default_filename = Fexpand_file_name (default_filename, dir);
-      val = Fx_file_dialog (prompt, dir, default_filename, mustmatch);
+      val = Fx_file_dialog (prompt, dir, default_filename, mustmatch,
+                            EQ (predicate, Qfile_directory_p) ? Qt : Qnil);
       add_to_history = 1;
     }
   else
--- a/src/gtkutil.c	Tue Nov 02 07:57:53 2004 +0000
+++ b/src/gtkutil.c	Tue Nov 02 08:21:16 2004 +0000
@@ -1118,6 +1118,10 @@
 }
 
 
+
+/***********************************************************************
+                      File dialog functions
+ ***********************************************************************/
 enum
 {
   XG_FILE_NOT_DONE,
@@ -1126,6 +1130,69 @@
   XG_FILE_DESTROYED,
 };
 
+#ifdef HAVE_GTK_FILE_BOTH
+static int use_old_gtk_file_dialog;
+#endif
+
+
+#ifdef HAVE_GTK_FILE_CHOOSER_DIALOG_NEW
+/* Read a file name from the user using a file chooser dialog.
+   F is the current frame.
+   PROMPT is a prompt to show to the user.  May not be NULL.
+   DEFAULT_FILENAME is a default selection to be displayed.  May be NULL.
+   If MUSTMATCH_P is non-zero, the returned file name must be an existing
+   file.
+
+   Returns a file name or NULL if no file was selected.
+   The returned string must be freed by the caller.  */
+
+static char *
+xg_get_file_with_chooser (f, prompt, default_filename, mustmatch_p, only_dir_p)
+     FRAME_PTR f;
+     char *prompt;
+     char *default_filename;
+     int mustmatch_p, only_dir_p;
+{
+  GtkWidget *filewin;
+  GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
+
+  char *fn = 0;
+  GtkFileChooserAction action = (mustmatch_p ?
+                                 GTK_FILE_CHOOSER_ACTION_OPEN :
+                                 GTK_FILE_CHOOSER_ACTION_SAVE);
+
+  if (only_dir_p)
+    action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
+
+  filewin = gtk_file_chooser_dialog_new (prompt, gwin, action,
+                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                         (mustmatch_p || only_dir_p ?
+                                          GTK_STOCK_OPEN : GTK_STOCK_SAVE),
+                                         GTK_RESPONSE_OK,
+                                         NULL);
+
+  xg_set_screen (filewin, f);
+  gtk_widget_set_name (filewin, "emacs-filedialog");
+  gtk_window_set_transient_for (GTK_WINDOW (filewin), gwin);
+  gtk_window_set_destroy_with_parent (GTK_WINDOW (filewin), TRUE);
+
+
+  if (default_filename)
+    gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (filewin),
+                                   default_filename);
+
+  gtk_widget_show (filewin);
+
+  if (gtk_dialog_run (GTK_DIALOG (filewin)) == GTK_RESPONSE_OK)
+    fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filewin));
+
+  gtk_widget_destroy (filewin);
+
+  return fn;
+}
+#endif /* HAVE_GTK_FILE_CHOOSER_DIALOG_NEW */
+
+#ifdef HAVE_GTK_FILE_SELECTION_NEW
 /* Callback function invoked when the Ok button is pressed in
    a file dialog.
    W is the file dialog widget,
@@ -1167,7 +1234,7 @@
   *(int*)arg = XG_FILE_DESTROYED;
 }
 
-/* Read a file name from the user using a file dialog.
+/* Read a file name from the user using a file selection dialog.
    F is the current frame.
    PROMPT is a prompt to show to the user.  May not be NULL.
    DEFAULT_FILENAME is a default selection to be displayed.  May be NULL.
@@ -1177,12 +1244,13 @@
    Returns a file name or NULL if no file was selected.
    The returned string must be freed by the caller.  */
 
-char *
-xg_get_file_name (f, prompt, default_filename, mustmatch_p)
+static char *
+xg_get_file_with_selection (f, prompt, default_filename,
+                            mustmatch_p, only_dir_p)
      FRAME_PTR f;
      char *prompt;
      char *default_filename;
-     int mustmatch_p;
+     int mustmatch_p, only_dir_p;
 {
   GtkWidget *filewin;
   GtkFileSelection *filesel;
@@ -1193,9 +1261,7 @@
   filesel = GTK_FILE_SELECTION (filewin);
 
   xg_set_screen (filewin, f);
-
   gtk_widget_set_name (filewin, "emacs-filedialog");
-
   gtk_window_set_transient_for (GTK_WINDOW (filewin),
                                 GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
   gtk_window_set_destroy_with_parent (GTK_WINDOW (filewin), TRUE);
@@ -1237,6 +1303,49 @@
 
   return fn;
 }
+#endif /* HAVE_GTK_FILE_SELECTION_NEW */
+
+/* Read a file name from the user using a file dialog, either the old
+   file selection dialog, or the new file chooser dialog.  Which to use
+   depends on what the GTK version used has, and what the value of
+   gtk-use-old-file-dialog.
+   F is the current frame.
+   PROMPT is a prompt to show to the user.  May not be NULL.
+   DEFAULT_FILENAME is a default selection to be displayed.  May be NULL.
+   If MUSTMATCH_P is non-zero, the returned file name must be an existing
+   file.
+
+   Returns a file name or NULL if no file was selected.
+   The returned string must be freed by the caller.  */
+
+char *
+xg_get_file_name (f, prompt, default_filename, mustmatch_p, only_dir_p)
+     FRAME_PTR f;
+     char *prompt;
+     char *default_filename;
+     int mustmatch_p, only_dir_p;
+{
+#ifdef HAVE_GTK_FILE_BOTH
+  if (use_old_gtk_file_dialog)
+    return xg_get_file_with_selection (f, prompt, default_filename,
+                                       mustmatch_p, only_dir_p);
+  return xg_get_file_with_chooser (f, prompt, default_filename,
+                                   mustmatch_p, only_dir_p);
+
+#else /* not HAVE_GTK_FILE_BOTH */
+
+#ifdef HAVE_GTK_FILE_SELECTION_DIALOG_NEW
+  return xg_get_file_with_selection (f, prompt, default_filename,
+                                     mustmatch_p, only_dir_p);
+#endif
+#ifdef HAVE_GTK_FILE_CHOOSER_DIALOG_NEW
+  return xg_get_file_with_chooser (f, prompt, default_filename,
+                                   mustmatch_p, only_dir_p);
+#endif
+
+#endif /* HAVE_GTK_FILE_BOTH */
+  return 0;
+}
 
 
 /***********************************************************************
@@ -3429,6 +3538,14 @@
                                     "gtk-key-theme-name",
                                     "Emacs",
                                     EMACS_CLASS);
+
+#ifdef HAVE_GTK_FILE_BOTH
+  DEFVAR_BOOL ("use-old-gtk-file-dialog", &use_old_gtk_file_dialog,
+    doc: /* *Non-nil means that the old GTK file selection dialog is used.
+            If nil the new GTK file chooser is used instead.  To turn off
+            all file dialogs set the variable `use-file-dialog'.  */);
+  use_old_gtk_file_dialog = 0;
+#endif
 }
 
 #endif /* USE_GTK */
--- a/src/gtkutil.h	Tue Nov 02 07:57:53 2004 +0000
+++ b/src/gtkutil.h	Tue Nov 02 08:21:16 2004 +0000
@@ -132,7 +132,8 @@
 extern char *xg_get_file_name P_ ((FRAME_PTR f,
                                    char *prompt,
                                    char *default_filename,
-                                   int mustmatch_p));
+                                   int mustmatch_p,
+                                   int only_dir_p));
 
 extern GtkWidget *xg_create_widget P_ ((char *type,
                                         char *name,
--- a/src/lisp.h	Tue Nov 02 07:57:53 2004 +0000
+++ b/src/lisp.h	Tue Nov 02 08:21:16 2004 +0000
@@ -3121,7 +3121,7 @@
 #ifdef HAVE_WINDOW_SYSTEM
 /* Defined in xfns.c, w32fns.c, or macfns.c */
 EXFUN (Fxw_display_color_p, 1);
-EXFUN (Fx_file_dialog, 4);
+EXFUN (Fx_file_dialog, 5);
 #endif /* HAVE_WINDOW_SYSTEM */
 
 /* Defined in xsmfns.c */
--- a/src/macfns.c	Tue Nov 02 07:57:53 2004 +0000
+++ b/src/macfns.c	Tue Nov 02 08:21:16 2004 +0000
@@ -4216,22 +4216,23 @@
 
 extern Lisp_Object Qfile_name_history;
 
-DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
+DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 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.  Ensure that file exists if MUSTMATCH is non-nil.  */)
-  (prompt, dir, default_filename, mustmatch)
-     Lisp_Object prompt, dir, default_filename, mustmatch;
+specified.  Ensure that file exists if MUSTMATCH is non-nil.
+If ONLY-DIR-P is non-nil, the user can only select directories.  */)
+  (prompt, dir, default_filename, mustmatch, only_dir_p)
+     Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
 {
   struct frame *f = SELECTED_FRAME ();
   Lisp_Object file = Qnil;
   int count = SPECPDL_INDEX ();
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
   char filename[1001];
   int default_filter_index = 1; /* 1: All Files, 2: Directories only  */
 
-  GCPRO5 (prompt, dir, default_filename, mustmatch, file);
+  GCPRO6 (prompt, dir, default_filename, mustmatch, file, only_dir_p);
   CHECK_STRING (prompt);
   CHECK_STRING (dir);
 
@@ -4245,7 +4246,8 @@
     NavDialogRef dialogRef;
     NavTypeListHandle fileTypes = NULL;
     NavUserAction userAction;
-    CFStringRef message=NULL, client=NULL, saveName = NULL;
+    CFStringRef message=NULL, client=NULL, saveName = NULL, ok = NULL;
+    CFStringRef title = NULL;
     
     BLOCK_INPUT;
     /* No need for a callback function because we are modal */
@@ -4268,13 +4270,19 @@
     options.clientName = client;
     */
 
-    /* Do Dired hack copied from w32fns.c */ 
-    if (!NILP(prompt) && strncmp (SDATA(prompt), "Dired", 5) == 0)
+    if (!NILP (only_dir_p))
       status = NavCreateChooseFolderDialog(&options, NULL, NULL, NULL,
 					   &dialogRef);
     else if (NILP (mustmatch)) 
       { 
 	/* This is a save dialog */
+	ok = CFStringCreateWithCString (NULL, "Ok", kCFStringEncodingUTF8);
+	title = CFStringCreateWithCString (NULL, "Enter name",
+	                                   kCFStringEncodingUTF8);
+	options.optionFlags |= kNavDontConfirmReplacement;
+	options.actionButtonLabel = ok;
+	options.windowTitle = title;
+
 	if (!NILP(default_filename))
 	  {
 	    saveName = CFStringCreateWithCString(NULL, SDATA(default_filename),
@@ -4282,20 +4290,10 @@
 	    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*/
@@ -4324,6 +4322,8 @@
     if (saveName) CFRelease(saveName);
     if (client) CFRelease(client);
     if (message) CFRelease(message);
+    if (ok) CFRelease(ok);
+    if (title) CFRelease(title);
 
     if (status == noErr) {
       userAction = NavDialogGetUserAction(dialogRef);
--- a/src/w32fns.c	Tue Nov 02 07:57:53 2004 +0000
+++ b/src/w32fns.c	Tue Nov 02 08:21:16 2004 +0000
@@ -7742,23 +7742,24 @@
   return 0;
 }
 
-DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
+DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 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.  Ensure that file exists if MUSTMATCH is non-nil.  */)
-  (prompt, dir, default_filename, mustmatch)
-     Lisp_Object prompt, dir, default_filename, mustmatch;
+specified.  Ensure that file exists if MUSTMATCH is non-nil.
+If ONLY-DIR-P is non-nil, the user can only select directories.  */)
+  (prompt, dir, default_filename, mustmatch, only_dir_p)
+     Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
 {
   struct frame *f = SELECTED_FRAME ();
   Lisp_Object file = Qnil;
   int count = SPECPDL_INDEX ();
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
   char filename[MAX_PATH + 1];
   char init_dir[MAX_PATH + 1];
   int default_filter_index = 1; /* 1: All Files, 2: Directories only  */
 
-  GCPRO5 (prompt, dir, default_filename, mustmatch, file);
+  GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
   CHECK_STRING (prompt);
   CHECK_STRING (dir);
 
@@ -7806,10 +7807,7 @@
     file_details.lpstrInitialDir = init_dir;
     file_details.lpstrTitle = SDATA (prompt);
 
-    /* If prompt starts with Dired, default to directories only.  */
-    /* A bit hacky, but there doesn't seem to be a better way to
-       DTRT for dired.  */
-    if (strncmp (file_details.lpstrTitle, "Dired", 5) == 0)
+    if (! NILP (only_dir_p))
       default_filter_index = 2;
 
     file_details.nFilterIndex = default_filter_index;
--- a/src/xfns.c	Tue Nov 02 07:57:53 2004 +0000
+++ b/src/xfns.c	Tue Nov 02 08:21:16 2004 +0000
@@ -5106,27 +5106,26 @@
 }
 
 
-DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
+DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 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.  */)
-     (prompt, dir, default_filename, mustmatch)
-     Lisp_Object prompt, dir, default_filename, mustmatch;
+Use a file selection dialog.  Select DEFAULT-FILENAME in the dialog's file
+selection box, if specified.  If MUSTMATCH is non-nil, the returned file
+or directory must exist.  ONLY-DIR-P is ignored."  */)
+  (prompt, dir, default_filename, mustmatch, only_dir_p)
+     Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
 {
   int result;
   struct frame *f = SELECTED_FRAME ();
   Lisp_Object file = Qnil;
-  Widget dialog, text, list, help;
+  Widget dialog, text, help;
   Arg al[10];
   int ac = 0;
   extern XtAppContext Xt_app_con;
   XmString dir_xmstring, pattern_xmstring;
   int count = SPECPDL_INDEX ();
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
-
-  GCPRO5 (prompt, dir, default_filename, mustmatch, file);
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
+
+  GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
   CHECK_STRING (prompt);
   CHECK_STRING (dir);
 
@@ -5159,9 +5158,9 @@
   XtAddCallback (dialog, XmNunmapCallback, file_dialog_unmap_cb,
 		 (XtPointer) &result);
 
-  /* Disable the help button since we can't display help.  */
+  /* Remove the help button since we can't display help.  */
   help = XmFileSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON);
-  XtSetSensitive (help, False);
+  XtUnmanageChild (help);
 
   /* Mark OK button as default.  */
   XtVaSetValues (XmFileSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON),
@@ -5183,30 +5182,30 @@
   /* Manage the dialog, so that list boxes get filled.  */
   XtManageChild (dialog);
 
-  /* Select DEFAULT_FILENAME in the files list box.  DEFAULT_FILENAME
-     must include the path for this to work.  */
-  list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
   if (STRINGP (default_filename))
     {
       XmString default_xmstring;
-      int item_pos;
-
-      default_xmstring
-	= XmStringCreateLocalized (SDATA (default_filename));
-
-      if (!XmListItemExists (list, default_xmstring))
-	{
-	  /* Add a new item if DEFAULT_FILENAME is not in the list.  */
-	  XmListAddItem (list, default_xmstring, 0);
-	  item_pos = 0;
-	}
-      else
-	item_pos = XmListItemPos (list, default_xmstring);
+      Widget wtext = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
+      Widget list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
+
+      XmTextPosition last_pos = XmTextFieldGetLastPosition (wtext);
+      XmTextFieldReplace (wtext, 0, last_pos,
+                          (SDATA (Ffile_name_nondirectory (default_filename))));
+
+      /* Select DEFAULT_FILENAME in the files list box.  DEFAULT_FILENAME
+         must include the path for this to work.  */
+
+      default_xmstring = XmStringCreateLocalized (SDATA (default_filename));
+
+      if (XmListItemExists (list, default_xmstring))
+        {
+          int item_pos = XmListItemPos (list, default_xmstring);
+          /* Select the item and scroll it into view.  */
+          XmListSelectPos (list, item_pos, True);
+          XmListSetPos (list, item_pos);
+        }
+
       XmStringFree (default_xmstring);
-
-      /* Select the item and scroll it into view.  */
-      XmListSelectPos (list, item_pos, True);
-      XmListSetPos (list, item_pos);
     }
 
   /* Process events until the user presses Cancel or OK.  */
@@ -5250,23 +5249,23 @@
 
 #ifdef USE_GTK
 
-DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
-  "Read file name, prompting with PROMPT in directory DIR.\n\
-Use a file selection dialog.\n\
-Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
-specified.  Don't let the user enter a file name in the file\n\
-selection dialog's entry field, if MUSTMATCH is non-nil.")
-  (prompt, dir, default_filename, mustmatch)
-     Lisp_Object prompt, dir, default_filename, mustmatch;
+DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 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.  If MUSTMATCH is non-nil, the returned file
+or directory must exist.  If ONLY-DIR-P is non-nil, the user can only select
+directories.  */)
+  (prompt, dir, default_filename, mustmatch, only_dir_p)
+     Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
 {
   FRAME_PTR f = SELECTED_FRAME ();
   char *fn;
   Lisp_Object file = Qnil;
   int count = specpdl_ptr - specpdl;
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
   char *cdef_file;
 
-  GCPRO5 (prompt, dir, default_filename, mustmatch, file);
+  GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
   CHECK_STRING (prompt);
   CHECK_STRING (dir);
 
@@ -5280,7 +5279,9 @@
   else
     cdef_file = SDATA (dir);
 
-  fn = xg_get_file_name (f, SDATA (prompt), cdef_file, ! NILP (mustmatch));
+  fn = xg_get_file_name (f, SDATA (prompt), cdef_file,
+                         ! NILP (mustmatch),
+                         ! NILP (only_dir_p));
 
   if (fn)
     {