Make Unix style path (slashes) work in open file dialog (optional)

Close #3948, fix #2438, fix #3840
This commit is contained in:
Isaiah Norton 2018-02-14 00:45:08 -05:00 committed by Don HO
parent 721f7f0608
commit 556901b83b

View File

@ -31,6 +31,7 @@
#include "FileDialog.h" #include "FileDialog.h"
#include "Parameters.h" #include "Parameters.h"
#include <algorithm>
FileDialog *FileDialog::staticThis = NULL; FileDialog *FileDialog::staticThis = NULL;
//int FileDialog::_dialogFileBoxId = (NppParameters::getInstance())->getWinVersion() < WV_W2K?edt1:cmb13; //int FileDialog::_dialogFileBoxId = (NppParameters::getInstance())->getWinVersion() < WV_W2K?edt1:cmb13;
@ -171,6 +172,12 @@ TCHAR* FileDialog::doOpenSingleFileDlg()
_ofn.Flags |= OFN_FILEMUSTEXIST; _ofn.Flags |= OFN_FILEMUSTEXIST;
if (!params->useNewStyleSaveDlg())
{
_ofn.Flags |= OFN_ENABLEHOOK | OFN_NOVALIDATE;
_ofn.lpfnHook = OFNHookProc;
}
TCHAR *fn = NULL; TCHAR *fn = NULL;
try { try {
fn = ::GetOpenFileName(&_ofn)?_fileName:NULL; fn = ::GetOpenFileName(&_ofn)?_fileName:NULL;
@ -200,7 +207,13 @@ stringVector * FileDialog::doOpenMultiFilesDlg()
NppParameters * params = NppParameters::getInstance(); NppParameters * params = NppParameters::getInstance();
_ofn.lpstrInitialDir = params->getWorkingDir(); _ofn.lpstrInitialDir = params->getWorkingDir();
_ofn.Flags |= OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT; _ofn.Flags |= OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_ENABLESIZING;
if (!params->useNewStyleSaveDlg())
{
_ofn.Flags |= OFN_ENABLEHOOK | OFN_NOVALIDATE;
_ofn.lpfnHook = OFNHookProc;
}
BOOL res = ::GetOpenFileName(&_ofn); BOOL res = ::GetOpenFileName(&_ofn);
if (params->getNppGUI()._openSaveDir == dir_last) if (params->getNppGUI()._openSaveDir == dir_last)
@ -256,7 +269,7 @@ TCHAR * FileDialog::doSaveDlg()
if (!params->useNewStyleSaveDlg()) if (!params->useNewStyleSaveDlg())
{ {
_ofn.Flags |= OFN_ENABLEHOOK; _ofn.Flags |= OFN_ENABLEHOOK | OFN_NOVALIDATE;
_ofn.lpfnHook = OFNHookProc; _ofn.lpfnHook = OFNHookProc;
} }
@ -355,7 +368,6 @@ static generic_string addExt(HWND textCtrl, HWND typeCtrl) {
return returnExt; return returnExt;
}; };
UINT_PTR CALLBACK FileDialog::OFNHookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) UINT_PTR CALLBACK FileDialog::OFNHookProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
switch(uMsg) switch(uMsg)
@ -374,7 +386,6 @@ UINT_PTR CALLBACK FileDialog::OFNHookProc(HWND hWnd, UINT uMsg, WPARAM wParam, L
HWND typeControl = ::GetDlgItem(hFileDlg, cmb1); HWND typeControl = ::GetDlgItem(hFileDlg, cmb1);
::SendMessage(typeControl, CB_SETCURSEL, index, 0); ::SendMessage(typeControl, CB_SETCURSEL, index, 0);
} }
// Don't touch the following 3 lines, they are cursed !!! // Don't touch the following 3 lines, they are cursed !!!
oldProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hFileDlg, GWLP_WNDPROC)); oldProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hFileDlg, GWLP_WNDPROC));
if (oldProc) if (oldProc)
@ -431,6 +442,34 @@ BOOL APIENTRY FileDialog::run(HWND hWnd, UINT uMsg, WPARAM, LPARAM lParam)
int index = static_cast<int32_t>(::SendMessage(typeControl, CB_GETCURSEL, 0, 0)); int index = static_cast<int32_t>(::SendMessage(typeControl, CB_GETCURSEL, 0, 0));
NppParameters *pNppParam = NppParameters::getInstance(); NppParameters *pNppParam = NppParameters::getInstance();
pNppParam->setFileSaveDlgFilterIndex(index); pNppParam->setFileSaveDlgFilterIndex(index);
// change forward-slash to back-slash directory paths so dialog can interpret
OPENFILENAME* ofn = reinterpret_cast<LPOFNOTIFY>(lParam)->lpOFN;
TCHAR* fileName = ofn->lpstrFile;
// note: this check is essential, because otherwise we could return True
// with a OFN_NOVALIDATE dialog, which leads to opening every file
// in the specified directory. Multi-select terminator is \0\0.
if ((ofn->Flags & OFN_ALLOWMULTISELECT) &&
(*(fileName + lstrlen(fileName) + 1) != '\0'))
return FALSE;
if (::PathIsDirectory(fileName))
{
// change to backslash, and insert trailing '\' to indicate directory
hFileDlg = ::GetParent(hWnd);
std::wstring _fnStr(fileName);
std::replace(_fnStr.begin(), _fnStr.end(), '/', '\\');
if (_fnStr.back() != '\\')
_fnStr.insert(_fnStr.end(), '\\');
// change the dialog directory selection
::SendMessage(hFileDlg, CDM_SETCONTROLTEXT, edt1,
reinterpret_cast<LPARAM>(_fnStr.c_str()));
::PostMessage(hFileDlg, WM_COMMAND, IDOK, 0);
::SetWindowLongPtr(hWnd, 0 /*DWL_MSGRESULT*/, 1);
}
return TRUE; return TRUE;
} }