]> git.eshelyaron.com Git - emacs.git/commitdiff
* fileio.c (Fread_file_name): Pass Qt as fifth parameter to
authorJan Djärv <jan.h.d@swipnet.se>
Tue, 2 Nov 2004 08:21:16 +0000 (08:21 +0000)
committerJan Djärv <jan.h.d@swipnet.se>
Tue, 2 Nov 2004 08:21:16 +0000 (08:21 +0000)
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.

src/ChangeLog
src/fileio.c
src/gtkutil.c
src/gtkutil.h
src/lisp.h
src/macfns.c
src/w32fns.c
src/xfns.c

index 18704954db011307b37f6235aab0667c567ca76f..68794ed6cef7f3009a1965efa624328d7a1027a9 100644 (file)
@@ -1,5 +1,36 @@
 2004-11-02  Jan Dj\e,Ad\e(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>
index c10969378bcbd0e9e84aab8e9ca2e51d347142dc..68ca97cf57f2abeeaad3dfbb66db3ff4759e14ba 100644 (file)
@@ -6321,7 +6321,8 @@ and `read-file-name-function'.  */)
        }
       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
index dc091c1a09b9595221ede72bb39b673c77e003a6..ac4f1af56f9b8abf4230de94c19396f67b92435f 100644 (file)
@@ -1118,6 +1118,10 @@ create_dialog (wv, select_cb, deactivate_cb)
 }
 
 
+\f
+/***********************************************************************
+                      File dialog functions
+ ***********************************************************************/
 enum
 {
   XG_FILE_NOT_DONE,
@@ -1126,6 +1130,69 @@ enum
   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 @@ xg_file_sel_destroy (w, arg)
   *(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 @@ xg_file_sel_destroy (w, arg)
    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 @@ xg_get_file_name (f, prompt, default_filename, mustmatch_p)
   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 @@ xg_get_file_name (f, prompt, default_filename, mustmatch_p)
 
   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;
+}
 
 \f
 /***********************************************************************
@@ -3429,6 +3538,14 @@ xg_initialize ()
                                     "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 */
index c0055f361cc6b17ea633542e13f11630a9a2f638..b2e2c5f2fffc2c75805b6b41433b33b5b509d7a9 100644 (file)
@@ -132,7 +132,8 @@ extern void free_widget_value P_ ((widget_value *));
 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,
index 49d6fa9219d38f6554dcf3121d0ba4c4110204cd..daf23a05f545813c0eb3968831c04bc623f367d9 100644 (file)
@@ -3121,7 +3121,7 @@ extern void syms_of_xfns P_ ((void));
 #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 */
index 88f975a65c88f6cf9ab972a3302b3c34acd0edec..401c7011feac9f4955ea3669cd714ff33f6ab139 100644 (file)
@@ -4216,22 +4216,23 @@ Value is t if tooltip was open, nil otherwise.  */)
 
 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 @@ specified.  Ensure that file exists if MUSTMATCH is non-nil.  */)
     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 @@ specified.  Ensure that file exists if MUSTMATCH is non-nil.  */)
     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 @@ specified.  Ensure that file exists if MUSTMATCH is non-nil.  */)
            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 @@ specified.  Ensure that file exists if MUSTMATCH is non-nil.  */)
     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);
index 38faa7c3199b9537fc476fe1bd6c645993458138..41bd6a9b9f987a84f9720c8ef17195bb307080fe 100644 (file)
@@ -7742,23 +7742,24 @@ file_dialog_callback (hwnd, msg, wParam, lParam)
   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 @@ specified.  Ensure that file exists if MUSTMATCH is non-nil.  */)
     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;
index 01d528e27908572c20d5f8d01be621962946cb7d..2cf8a59ca5207910db4894f3911059218b9d588e 100644 (file)
@@ -5106,27 +5106,26 @@ file_dialog_unmap_cb (widget, client_data, call_data)
 }
 
 
-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;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
 
-  GCPRO5 (prompt, dir, default_filename, mustmatch, file);
+  GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
   CHECK_STRING (prompt);
   CHECK_STRING (dir);
 
@@ -5159,9 +5158,9 @@ selection dialog's entry field, if MUSTMATCH is non-nil.  */)
   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 @@ selection dialog's entry field, if MUSTMATCH is non-nil.  */)
   /* 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;
+      Widget wtext = XmFileSelectionBoxGetChild (dialog, XmDIALOG_TEXT);
+      Widget list = XmFileSelectionBoxGetChild (dialog, XmDIALOG_LIST);
 
-      default_xmstring
-       = XmStringCreateLocalized (SDATA (default_filename));
+      XmTextPosition last_pos = XmTextFieldGetLastPosition (wtext);
+      XmTextFieldReplace (wtext, 0, last_pos,
+                          (SDATA (Ffile_name_nondirectory (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);
-      XmStringFree (default_xmstring);
+      /* Select DEFAULT_FILENAME in the files list box.  DEFAULT_FILENAME
+         must include the path for this to work.  */
+
+      default_xmstring = XmStringCreateLocalized (SDATA (default_filename));
 
-      /* Select the item and scroll it into view.  */
-      XmListSelectPos (list, item_pos, True);
-      XmListSetPos (list, item_pos);
+      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);
     }
 
   /* Process events until the user presses Cancel or OK.  */
@@ -5250,23 +5249,23 @@ selection dialog's entry field, if MUSTMATCH is non-nil.  */)
 
 #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 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
   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)
     {