From 1030b26bcc03cc968021979b9754a93f91921e8d Mon Sep 17 00:00:00 2001 From: Jason Rumney Date: Sat, 22 Jun 2002 19:52:29 +0000 Subject: [PATCH] (file_dialog_callback): New function. (Fx_file_dialog): Allow selecting directories as well as files. --- src/ChangeLog | 5 ++ src/w32fns.c | 132 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 92 insertions(+), 45 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 222f06329cc..7651e9701f0 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2002-06-22 Jason Rumney + + * w32fns.c (file_dialog_callback): New function. + (Fx_file_dialog): Allow selecting directories as well as files. + 2002-06-21 Pavel Jan,Bm(Bk * m/pmax.h (START_FILES): Define START_FILES for NetBSD and diff --git a/src/w32fns.c b/src/w32fns.c index 95ecc1b401c..09824ccbd6f 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -52,6 +52,9 @@ Boston, MA 02111-1307, USA. */ #include #include +#include +#define FILE_NAME_TEXT_FIELD edt1 + extern void free_frame_menubar (); extern void x_compute_fringe_widths P_ ((struct frame *, int)); extern double atof (); @@ -14244,9 +14247,47 @@ Value is t if tooltip was open, nil otherwise. */) /*********************************************************************** File selection dialog ***********************************************************************/ - extern Lisp_Object Qfile_name_history; +/* Callback for altering the behaviour of the Open File dialog. + Makes the Filename text field contain "Current Directory" and be + read-only when "Directories" is selected in the filter. This + allows us to work around the fact that the standard Open File + dialog does not support directories. */ +UINT CALLBACK +file_dialog_callback (hwnd, msg, wParam, lParam) + HWND hwnd; + UINT msg; + WPARAM wParam; + LPARAM lParam; +{ + if (msg == WM_NOTIFY) + { + OFNOTIFY * notify = (OFNOTIFY *)lParam; + /* Detect when the Filter dropdown is changed. */ + if (notify->hdr.code == CDN_TYPECHANGE) + { + HWND dialog = GetParent (hwnd); + HWND edit_control = GetDlgItem (dialog, FILE_NAME_TEXT_FIELD); + + /* Directories is in index 2. */ + if (notify->lpOFN->nFilterIndex == 2) + { + CommDlg_OpenSave_SetControlText (dialog, FILE_NAME_TEXT_FIELD, + "Current Directory"); + EnableWindow (edit_control, FALSE); + } + else + { + CommDlg_OpenSave_SetControlText (dialog, FILE_NAME_TEXT_FIELD, + ""); + EnableWindow (edit_control, TRUE); + } + } + } + return 0; +} + 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. @@ -14261,7 +14302,6 @@ specified. Ensure that file exists if MUSTMATCH is non-nil. */) struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; char filename[MAX_PATH + 1]; char init_dir[MAX_PATH + 1]; - int use_dialog_p = 1; GCPRO5 (prompt, dir, default_filename, mustmatch, file); CHECK_STRING (prompt); @@ -14287,12 +14327,6 @@ specified. Ensure that file exists if MUSTMATCH is non-nil. */) 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); @@ -14301,46 +14335,54 @@ specified. Ensure that file exists if MUSTMATCH is non-nil. */) else filename[0] = '\0'; - if (use_dialog_p) - { - OPENFILENAME file_details; + { + OPENFILENAME file_details; - /* Prevent redisplay. */ - specbind (Qinhibit_redisplay, Qt); - BLOCK_INPUT; + /* 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); - /* Undocumented Bug in Common File Dialog: - If a filter is not specified, shell links are not resolved. */ - file_details.lpstrFilter = "ALL Files (*.*)\0*.*\0\0"; - file_details.lpstrFile = filename; - file_details.nMaxFile = sizeof (filename); - file_details.lpstrInitialDir = init_dir; - file_details.lpstrTitle = XSTRING (prompt)->data; - 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 = DECODE_FILE(build_string (filename)); - } - else - file = Qnil; + bzero (&file_details, sizeof (file_details)); + file_details.lStructSize = sizeof (file_details); + file_details.hwndOwner = FRAME_W32_WINDOW (f); + /* Undocumented Bug in Common File Dialog: + If a filter is not specified, shell links are not resolved. */ + file_details.lpstrFilter = "All Files (*.*)\0*.*\0Directories\0*|*\0\0"; + file_details.lpstrFile = filename; + file_details.nMaxFile = sizeof (filename); + file_details.lpstrInitialDir = init_dir; + file_details.lpstrTitle = XSTRING (prompt)->data; + file_details.Flags = (OFN_HIDEREADONLY | OFN_NOCHANGEDIR + | OFN_EXPLORER | OFN_ENABLEHOOK); + if (!NILP (mustmatch)) + file_details.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; + + file_details.lpfnHook = (LPOFNHOOKPROC) file_dialog_callback; + + if (GetOpenFileName (&file_details)) + { + dostounix_filename (filename); + if (file_details.nFilterIndex == 2) + { + /* "Folder Only" selected - strip dummy file name. */ + char * last = strrchr (filename, '/'); + *last = '\0'; + } - UNBLOCK_INPUT; - file = unbind_to (count, file); - } - /* 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); + file = DECODE_FILE(build_string (filename)); + } + /* User cancelled the dialog without making a selection. */ + else if (!CommDlgExtendedError ()) + file = Qnil; + /* An error occurred, fallback on reading from the mini-buffer. */ + else + file = Fcompleting_read (prompt, intern ("read-file-name-internal"), + dir, mustmatch, dir, Qfile_name_history, + default_filename, Qnil); + + UNBLOCK_INPUT; + file = unbind_to (count, file); + } UNGCPRO; -- 2.39.2