diff --git a/language/common_res.h b/language/common_res.h index d87dc3b46..3ecd1f856 100644 --- a/language/common_res.h +++ b/language/common_res.h @@ -453,8 +453,9 @@ #define IDC_AUTOSAVE_SUSPEND 18127 #define IDC_AUTOSAVE_SHUTDOWN 18128 #define IDC_AS_BACKUP_ENABLE 18129 -#define IDC_AS_BACKUP_OPENFOLDER 18130 +#define IDC_AS_BACKUP_AUTOSAVE 18130 #define IDC_AS_BACKUP_SIDEBYSIDE 18131 +#define IDC_AS_BACKUP_OPENFOLDER 18132 #define IDC_RADIO_BTN_A 18200 #define IDC_RADIO_BTN_B 18201 diff --git a/language/np3_de_de/dialogs_de_de.rc b/language/np3_de_de/dialogs_de_de.rc index 83cd54b9d..24951cfbf 100644 --- a/language/np3_de_de/dialogs_de_de.rc +++ b/language/np3_de_de/dialogs_de_de.rc @@ -811,23 +811,24 @@ END // // AutoSave and Backup Dialog // -IDD_MUI_AUTOSAVE_BACKUP DIALOGEX 0, 0, 184, 154 +IDD_MUI_AUTOSAVE_BACKUP DIALOGEX 0, 0, 184, 166 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Auto-Speichern Einstellungen" +CAPTION "Auto-Speichern & Backup Einstellungen" FONT 9, "Segoe UI", 0, 0, 0x0 BEGIN -GROUPBOX "Auto-Save: ", IDC_STATIC2, 7, 7, 170, 62, 0, WS_EX_TRANSPARENT +GROUPBOX "Auto-Speichern: ", IDC_STATIC, 7, 7, 170, 62, 0, WS_EX_TRANSPARENT AUTOCHECKBOX "Aktiviere Auto-Speichern.", IDC_AUTOSAVE_ENABLE, 14, 18, 155, 10, WS_GROUP | WS_TABSTOP -LTEXT "Auto-Speichern-Intervall [sec]:", IDC_STATIC, 14, 30, 108, 10, SS_RIGHT +LTEXT "Auto-Speichern-Intervall [sec]:", IDC_STATIC2, 14, 30, 108, 10, SS_RIGHT EDITTEXT IDC_AUTOSAVE_INTERVAL, 130, 28, 40, 12, ES_AUTOHSCROLL -AUTOCHECKBOX "Auto-Speichern bei Ruhezustand.", IDC_AUTOSAVE_SUSPEND, 14, 40, 155, 10, WS_GROUP | WS_TABSTOP -AUTOCHECKBOX "Auto-Speichern bei Runterfahren.", IDC_AUTOSAVE_SHUTDOWN, 14, 52, 155, 10, WS_TABSTOP -GROUPBOX "Backup: ", IDC_STATIC3, 7, 74, 170, 54, 0, WS_EX_TRANSPARENT +AUTOCHECKBOX "Auto-Speichern vor Ruhezustand.", IDC_AUTOSAVE_SUSPEND, 14, 40, 155, 10, WS_GROUP | WS_TABSTOP +AUTOCHECKBOX "Auto-Speichern vor Runterfahren.", IDC_AUTOSAVE_SHUTDOWN, 14, 52, 155, 10, WS_TABSTOP +GROUPBOX "Backup: ", IDC_STATIC3, 7, 74, 170, 66, 0, WS_EX_TRANSPARENT AUTOCHECKBOX "Aktiviere Backup.", IDC_AS_BACKUP_ENABLE, 14, 85, 155, 10, WS_GROUP | WS_TABSTOP -AUTOCHECKBOX "Seite-an-Seite Backup.", IDC_AS_BACKUP_SIDEBYSIDE, 14, 97, 155, 10, WS_GROUP | WS_TABSTOP -PUSHBUTTON "Öffne Ordner", IDC_AS_BACKUP_OPENFOLDER, 110, 110, 60, 14 -DEFPUSHBUTTON "OK", IDOK, 71, 134, 50, 14 -PUSHBUTTON "Abbrechen", IDCANCEL, 127, 134, 50, 14 +AUTOCHECKBOX "Backup bei Auto-Speichern.", IDC_AS_BACKUP_AUTOSAVE, 14, 97, 155, 10, WS_GROUP | WS_TABSTOP +AUTOCHECKBOX "Seite-an-Seite Backup.", IDC_AS_BACKUP_SIDEBYSIDE, 14, 109, 155, 10, WS_GROUP | WS_TABSTOP +PUSHBUTTON "Öffne Ordner", IDC_AS_BACKUP_OPENFOLDER, 110, 122, 60, 14 +DEFPUSHBUTTON "OK", IDOK, 71, 146, 50, 14 +PUSHBUTTON "Abbrechen", IDCANCEL, 127, 146, 50, 14 END diff --git a/language/np3_de_de/menu_de_de.rc b/language/np3_de_de/menu_de_de.rc index 70f0e9bcf..ceaa95e05 100644 --- a/language/np3_de_de/menu_de_de.rc +++ b/language/np3_de_de/menu_de_de.rc @@ -465,7 +465,7 @@ BEGIN MENUITEM SEPARATOR MENUITEM "Nur eine &Instanz pro Datei", IDM_SET_SINGLEFILEINSTANCE MENUITEM "Nachricht bei &Dateiänderung...\tAlt+F5", IDM_SET_CHANGENOTIFY - MENUITEM "Auto-Speichern / Backup Einstellungen...", IDM_SET_AUTOSAVE_BACKUP + ///MENUITEM "Auto-Speichern / Backup Einstellungen...", IDM_SET_AUTOSAVE_BACKUP MENUITEM "Keine Nachrichten &Beeps", IDM_SET_MUTE_MESSAGEBEEP POPUP "Esc-&Key Funktion" BEGIN diff --git a/language/np3_en_us/dialogs_en_us.rc b/language/np3_en_us/dialogs_en_us.rc index 37cee96c3..3f24a4544 100644 --- a/language/np3_en_us/dialogs_en_us.rc +++ b/language/np3_en_us/dialogs_en_us.rc @@ -811,23 +811,24 @@ END // // AutoSave and Backup Dialog // -IDD_MUI_AUTOSAVE_BACKUP DIALOGEX 0, 0, 184, 154 +IDD_MUI_AUTOSAVE_BACKUP DIALOGEX 0, 0, 184, 166 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Auto-Save & Backup Settings" FONT 9, "Segoe UI", 0, 0, 0x0 BEGIN -GROUPBOX "Auto-Save: ", IDC_STATIC2, 7, 7, 170, 62, 0, WS_EX_TRANSPARENT +GROUPBOX "Auto-Save: ", IDC_STATIC, 7, 7, 170, 62, 0, WS_EX_TRANSPARENT AUTOCHECKBOX "Enable Auto-Save.", IDC_AUTOSAVE_ENABLE, 14, 18, 155, 10, WS_GROUP | WS_TABSTOP -LTEXT "Auto-Save interval [sec]:", IDC_STATIC, 14, 30, 108, 10, SS_RIGHT +LTEXT "Auto-Save interval [sec]:", IDC_STATIC2, 14, 30, 108, 10, SS_RIGHT EDITTEXT IDC_AUTOSAVE_INTERVAL, 130, 28, 40, 12, ES_AUTOHSCROLL AUTOCHECKBOX "Auto-Save on system suspend.", IDC_AUTOSAVE_SUSPEND, 14, 40, 155, 10, WS_GROUP | WS_TABSTOP AUTOCHECKBOX "Auto-Save on system shutdown.", IDC_AUTOSAVE_SHUTDOWN, 14, 52, 155, 10, WS_TABSTOP -GROUPBOX "Backup: ", IDC_STATIC3, 7, 74, 170, 54, 0, WS_EX_TRANSPARENT +GROUPBOX "Backup: ", IDC_STATIC3, 7, 74, 170, 66, 0, WS_EX_TRANSPARENT AUTOCHECKBOX "Enable Backup.", IDC_AS_BACKUP_ENABLE, 14, 85, 155, 10, WS_GROUP | WS_TABSTOP -AUTOCHECKBOX "Side-by-Side Backup.", IDC_AS_BACKUP_SIDEBYSIDE, 14, 97, 155, 10, WS_GROUP | WS_TABSTOP -PUSHBUTTON "Open Folder", IDC_AS_BACKUP_OPENFOLDER, 110, 110, 60, 14 -DEFPUSHBUTTON "OK", IDOK, 71, 134, 50, 14 -PUSHBUTTON "Cancel", IDCANCEL, 127, 134, 50, 14 +AUTOCHECKBOX "Backup on Auto-Save.", IDC_AS_BACKUP_AUTOSAVE, 14, 97, 155, 10, WS_GROUP | WS_TABSTOP +AUTOCHECKBOX "Side-by-Side Backup.", IDC_AS_BACKUP_SIDEBYSIDE, 14, 109, 155, 10, WS_GROUP | WS_TABSTOP +PUSHBUTTON "Open Folder", IDC_AS_BACKUP_OPENFOLDER, 110, 122, 60, 14 +DEFPUSHBUTTON "OK", IDOK, 71, 146, 50, 14 +PUSHBUTTON "Cancel", IDCANCEL, 127, 146, 50, 14 END diff --git a/language/np3_en_us/menu_en_us.rc b/language/np3_en_us/menu_en_us.rc index b481e35db..e6f12967a 100644 --- a/language/np3_en_us/menu_en_us.rc +++ b/language/np3_en_us/menu_en_us.rc @@ -465,7 +465,7 @@ BEGIN MENUITEM SEPARATOR MENUITEM "Only One Instance per &File", IDM_SET_SINGLEFILEINSTANCE MENUITEM "File &Change Notification...\tAlt+F5", IDM_SET_CHANGENOTIFY - MENUITEM "AutoSave / Backup Settings...", IDM_SET_AUTOSAVE_BACKUP + ///MENUITEM "AutoSave / Backup Settings...", IDM_SET_AUTOSAVE_BACKUP MENUITEM "&Mute Message Beeps", IDM_SET_MUTE_MESSAGEBEEP POPUP "&Esc Key Function" BEGIN diff --git a/src/Dialogs.c b/src/Dialogs.c index f0b68b76d..731e3af5f 100644 --- a/src/Dialogs.c +++ b/src/Dialogs.c @@ -4230,7 +4230,7 @@ static INT_PTR CALLBACK AutoSaveBackupSettingsDlgProc(HWND hwnd, UINT umsg, WPAR SetExplorerTheme(GetDlgItem(hwnd, IDC_AS_BACKUP_OPENFOLDER)); //SetExplorerTheme(GetDlgItem(hwnd, IDC_RESIZEGRIP)); int const ctl[] = { IDC_AUTOSAVE_ENABLE, IDC_AUTOSAVE_INTERVAL, IDC_AUTOSAVE_SUSPEND, IDC_AUTOSAVE_SHUTDOWN, - IDC_AS_BACKUP_ENABLE, IDC_AS_BACKUP_SIDEBYSIDE, IDC_STATIC, IDC_STATIC2, IDC_STATIC3 }; + IDC_AS_BACKUP_ENABLE, IDC_AS_BACKUP_AUTOSAVE, IDC_AS_BACKUP_SIDEBYSIDE, IDC_STATIC, IDC_STATIC2, IDC_STATIC3 }; for (int i = 0; i < COUNTOF(ctl); ++i) { SetWindowTheme(GetDlgItem(hwnd, ctl[i]), L"", L""); // remove theme for BS_AUTORADIOBUTTON } @@ -4241,9 +4241,17 @@ static INT_PTR CALLBACK AutoSaveBackupSettingsDlgProc(HWND hwnd, UINT umsg, WPAR CheckDlgButton(hwnd, IDC_AUTOSAVE_SUSPEND, SetBtn(Settings.AutoSaveOptions & ASB_Suspend)); CheckDlgButton(hwnd, IDC_AUTOSAVE_SHUTDOWN, SetBtn(Settings.AutoSaveOptions & ASB_Shutdown)); + DialogEnableControl(hwnd, IDC_STATIC2, IsButtonChecked(hwnd, IDC_AUTOSAVE_ENABLE)); + DialogEnableControl(hwnd, IDC_AUTOSAVE_INTERVAL, IsButtonChecked(hwnd, IDC_AUTOSAVE_ENABLE)); + CheckDlgButton(hwnd, IDC_AS_BACKUP_ENABLE, SetBtn(Settings.AutoSaveOptions & ASB_Backup)); + CheckDlgButton(hwnd, IDC_AS_BACKUP_AUTOSAVE, SetBtn(Settings.AutoSaveOptions & ASB_OnAutoSave)); CheckDlgButton(hwnd, IDC_AS_BACKUP_SIDEBYSIDE, SetBtn(Settings.AutoSaveOptions & ASB_SideBySide)); + DialogEnableControl(hwnd, IDC_AS_BACKUP_AUTOSAVE, IsButtonChecked(hwnd, IDC_AS_BACKUP_ENABLE)); + DialogEnableControl(hwnd, IDC_AS_BACKUP_SIDEBYSIDE, IsButtonChecked(hwnd, IDC_AS_BACKUP_ENABLE)); + DialogEnableControl(hwnd, IDC_AS_BACKUP_OPENFOLDER, IsButtonChecked(hwnd, IDC_AS_BACKUP_ENABLE)); + WCHAR wch[32]; const UINT seconds = Settings.AutoSaveInterval / 1000; const UINT milliseconds = Settings.AutoSaveInterval % 1000; @@ -4300,6 +4308,7 @@ static INT_PTR CALLBACK AutoSaveBackupSettingsDlgProc(HWND hwnd, UINT umsg, WPAR options |= IsButtonChecked(hwnd, IDC_AUTOSAVE_SHUTDOWN) ? ASB_Shutdown : ASB_None; options |= IsButtonChecked(hwnd, IDC_AS_BACKUP_ENABLE) ? ASB_Backup : ASB_None; + options |= IsButtonChecked(hwnd, IDC_AS_BACKUP_SIDEBYSIDE) ? ASB_OnAutoSave : ASB_None; options |= IsButtonChecked(hwnd, IDC_AS_BACKUP_SIDEBYSIDE) ? ASB_SideBySide : ASB_None; Settings.AutoSaveOptions = options; @@ -4320,15 +4329,32 @@ static INT_PTR CALLBACK AutoSaveBackupSettingsDlgProc(HWND hwnd, UINT umsg, WPAR case IDC_AS_BACKUP_OPENFOLDER: { WCHAR szTitle[SMALL_BUFFER] = { L'\0' }; GetLngString(IDS_MUI_FAVORITES, szTitle, COUNTOF(szTitle)); - if (Path_BrowseDirectory(hwnd, szTitle, Settings.FavoritesDir, Settings.FavoritesDir, true)) { + HPATHL hdir_pth = Path_Allocate(NULL); + if (Path_BrowseDirectory(hwnd, szTitle, hdir_pth, Paths.WorkingDirectory, true)) { + InfoBoxLng(MB_ICONINFORMATION, NULL, IDS_MUI_LOADFILE, Path_Get(hdir_pth)); // change dir } + //if (GetFolderDlg(Globals.hwndMain, hdir_pth, Paths.WorkingDirectory, true)) { + // InfoBoxLng(MB_ICONINFORMATION, NULL, IDS_MUI_LOADFILE, Path_Get(hdir_pth)); + //} + Path_Release(hdir_pth); } break; case IDCANCEL: EndDialog(hwnd, IDCANCEL); break; + case IDC_AUTOSAVE_ENABLE: + DialogEnableControl(hwnd, IDC_STATIC2, IsButtonChecked(hwnd, IDC_AUTOSAVE_ENABLE)); + DialogEnableControl(hwnd, IDC_AUTOSAVE_INTERVAL, IsButtonChecked(hwnd, IDC_AUTOSAVE_ENABLE)); + break; + + case IDC_AS_BACKUP_ENABLE: + DialogEnableControl(hwnd, IDC_AS_BACKUP_AUTOSAVE, IsButtonChecked(hwnd, IDC_AS_BACKUP_ENABLE)); + DialogEnableControl(hwnd, IDC_AS_BACKUP_SIDEBYSIDE, IsButtonChecked(hwnd, IDC_AS_BACKUP_ENABLE)); + DialogEnableControl(hwnd, IDC_AS_BACKUP_OPENFOLDER, IsButtonChecked(hwnd, IDC_AS_BACKUP_ENABLE)); + break; + default: return FALSE; } @@ -6527,7 +6553,6 @@ INT_PTR CALLBACK ColorDialogHookProc( } - //============================================================================= // // CleanupDlgResources() @@ -6543,6 +6568,233 @@ void CleanupDlgResources() } +//============================================================================= +// +// _CanonicalizeInitialDir() TODO: use Path_NormalizeEx() here ? +// +static void _CanonicalizeInitialDir(HPATHL hpth_in_out) +{ + if (Path_IsEmpty(hpth_in_out)) { + + if (Path_IsNotEmpty(Paths.CurrentFile)) { + Path_Reset(hpth_in_out, Path_Get(Paths.CurrentFile)); + Path_RemoveFileSpec(hpth_in_out); + } + else if (Path_IsNotEmpty(Settings2.DefaultDirectory)) { + Path_Reset(hpth_in_out, Path_Get(Settings2.DefaultDirectory)); + } + else { + Path_Reset(hpth_in_out, Path_Get(Paths.WorkingDirectory)); + } + Path_CanonicalizeEx(hpth_in_out); + } + else { // Path_IsNotEmpty(hpth_in_out) + + if (Path_IsRelative(hpth_in_out)) { + Path_AbsoluteFromApp(hpth_in_out, true); + //~ already Path_CanonicalizeEx(hpth_in_out); + } + else { + Path_CanonicalizeEx(hpth_in_out); + } + if (!Path_IsExistingDirectory(hpth_in_out)) { + Path_RemoveFileSpec(hpth_in_out); + } + } + // finally: directory exists ? + if (!Path_IsExistingDirectory(hpth_in_out)) { + Path_Empty(hpth_in_out, false); + } +} + + +#if 0 +// ============================================================================ +// +// GetFolderDlg() +// lpstrInitialDir == NULL : leave initial dir to Open File Explorer +// lpstrInitialDir == ""[empty] : use a reasonable initial directory path +// +bool GetFolderDlg(HWND hwnd, HPATHL hdir_pth_io, const HPATHL hinidir_pth, bool bSelect) +{ + if (!hdir_pth_io) { + return false; + } + + HPATHL hpth_dir = Path_Allocate(Path_Get(hinidir_pth)); + _CanonicalizeInitialDir(hpth_dir); + + LPCWSTR inidirBuf = NULL; + DWORD dwAttributes = Path_GetFileAttributes(hpth_dir); + if (bSelect || (dwAttributes == INVALID_FILE_ATTRIBUTES) || !(dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + Path_RemoveFileSpec(hpth_dir); + } + if (bSelect && (dwAttributes != INVALID_FILE_ATTRIBUTES)) { + // if File is root, open the volume instead of open My Computer and select the volume + if ((dwAttributes & FILE_ATTRIBUTE_DIRECTORY) && Path_IsRoot(hpth_dir)) { + bSelect = false; + } + else { + inidirBuf = Path_Get(hinidir_pth); + } + } + dwAttributes = Path_GetFileAttributes(hpth_dir); + if ((dwAttributes == INVALID_FILE_ATTRIBUTES) || !(dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + return false; + } + + Path_Swap(hdir_pth_io, hpth_dir); + Path_Release(hpth_dir); + + HRESULT hr = S_FALSE; + PIDLIST_ABSOLUTE pidl = ILCreateFromPath(Path_WriteAccessBuf(hdir_pth_io, PATHLONG_MAX_CCH)); + if (pidl) { + PIDLIST_ABSOLUTE pidlEntry = inidirBuf ? ILCreateFromPath(inidirBuf) : NULL; + if (pidlEntry) { + hr = SHOpenFolderAndSelectItems(pidl, 1, (PCUITEMID_CHILD_ARRAY)(&pidlEntry), 0); + CoTaskMemFree((LPVOID)pidlEntry); + } + else if (!bSelect) { +#if 0 + // Use an invalid item to open the folder? + hr = SHOpenFolderAndSelectItems(pidl, 1, (LPCITEMIDLIST *)(&pidl), 0); +#else + SHELLEXECUTEINFO sei = { sizeof(SHELLEXECUTEINFO) }; + sei.fMask = SEE_MASK_IDLIST; + sei.hwnd = hwnd; + //~sei.lpVerb = L"explore"; + sei.lpVerb = L"open"; + sei.lpIDList = (void*)pidl; + sei.nShow = SW_SHOW; + + const BOOL result = ShellExecuteEx(&sei); + hr = result ? S_OK : S_FALSE; +#endif + } + else { + // open parent folder and select the folder + hr = SHOpenFolderAndSelectItems(pidl, 0, NULL, 0); + } + CoTaskMemFree((LPVOID)pidl); + } + + Path_Sanitize(hdir_pth_io); + Path_FreeExtra(hdir_pth_io, MAX_PATH_EXPLICIT); + + if (hr == S_OK) { + return true; + } + +#if 0 + if (path == NULL) { + path = wchDirectory; + } + + // open a new explorer window every time + LPWSTR szParameters = (LPWSTR)NP2HeapAlloc((lstrlen(path) + 64) * sizeof(WCHAR)); + lstrcpy(szParameters, bSelect ? L"/select," : L""); + lstrcat(szParameters, L"\""); + lstrcat(szParameters, path); + lstrcat(szParameters, L"\""); + ShellExecute(hwnd, L"open", L"explorer", szParameters, NULL, SW_SHOW); + NP2HeapFree(szParameters); +#endif + return false; +} +#endif + + +// ============================================================================ +// +// OpenFileDlg() +// lpstrInitialDir == NULL : leave initial dir to Open File Explorer +// lpstrInitialDir == ""[empty] : use a reasonable initial directory path +// +// TODO: Replace GetOpenFileNameW() by Common Item Dialog: IFileOpenDialog() +// https://docs.microsoft.com/en-us/windows/win32/shell/common-file-dialog +// +bool OpenFileDlg(HWND hwnd, HPATHL hfile_pth_io, const HPATHL hinidir_pth) +{ + if (!hfile_pth_io) { + return false; + } + + WCHAR szDefExt[64] = { L'\0' }; + WCHAR szFilter[EXTENTIONS_FILTER_BUFFER]; + Style_GetFileFilterStr(szFilter, COUNTOF(szFilter), szDefExt, COUNTOF(szDefExt), false); + + HPATHL hpth_dir = Path_Allocate(Path_Get(hinidir_pth)); + _CanonicalizeInitialDir(hpth_dir); + + OPENFILENAME ofn = { sizeof(OPENFILENAME) }; + ofn.hwndOwner = hwnd; + ofn.hInstance = Globals.hInstance; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; // no preserved (static member) user-defined patten + ofn.lpstrInitialDir = Path_IsNotEmpty(hpth_dir) ? Path_Get(hpth_dir) : NULL; + ofn.lpstrFile = Path_WriteAccessBuf(hfile_pth_io, PATHLONG_MAX_CCH); + ofn.nMaxFile = (DWORD)Path_GetBufCount(hfile_pth_io); + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | /* OFN_NOCHANGEDIR |*/ + OFN_DONTADDTORECENT | OFN_PATHMUSTEXIST | + OFN_SHAREAWARE /*| OFN_NODEREFERENCELINKS*/; + ofn.lpstrDefExt = StrIsNotEmpty(szDefExt) ? szDefExt : Settings2.DefaultExtension; + + bool const res = GetOpenFileNameW(&ofn); + + Path_Sanitize(hfile_pth_io); + + Path_Release(hpth_dir); + Path_FreeExtra(hfile_pth_io, MAX_PATH_EXPLICIT); + + return res; +} + +// ============================================================================ +// +// SaveFileDlg() +// lpstrInitialDir == NULL : leave initial dir to Save File Explorer +// lpstrInitialDir == ""[empty] : use a reasonable initial directory path +// +bool SaveFileDlg(HWND hwnd, HPATHL hfile_pth_io, const HPATHL hinidir_pth) +{ + if (!hfile_pth_io) { + return false; + } + + WCHAR szDefExt[64] = { L'\0' }; + WCHAR szFilter[EXTENTIONS_FILTER_BUFFER]; + Style_GetFileFilterStr(szFilter, COUNTOF(szFilter), szDefExt, COUNTOF(szDefExt), true); + + HPATHL hpth_dir = Path_Copy(hinidir_pth); + _CanonicalizeInitialDir(hpth_dir); + + OPENFILENAME ofn = { sizeof(OPENFILENAME) }; + ofn.hwndOwner = hwnd; + ofn.hInstance = Globals.hInstance; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; // no preserved (static member) user-defined patten + ofn.lpstrInitialDir = Path_IsNotEmpty(hpth_dir) ? Path_Get(hpth_dir) : NULL; + ofn.lpstrFile = Path_WriteAccessBuf(hfile_pth_io, PATHLONG_MAX_CCH); + ofn.nMaxFile = (DWORD)Path_GetBufCount(hfile_pth_io); + ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | /*| OFN_NOCHANGEDIR*/ + /*OFN_NODEREFERENCELINKS |*/ OFN_OVERWRITEPROMPT | + OFN_DONTADDTORECENT | OFN_PATHMUSTEXIST; + ofn.lpstrDefExt = StrIsNotEmpty(szDefExt) ? szDefExt : Settings2.DefaultExtension; + + bool const res = GetSaveFileNameW(&ofn); + + Path_Sanitize(hfile_pth_io); + + Path_Release(hpth_dir); + Path_FreeExtra(hfile_pth_io, MAX_PATH_EXPLICIT); + + return res; +} + + + + + #if FALSE //============================================================================= // diff --git a/src/Dialogs.h b/src/Dialogs.h index fec9c02cc..4d2cb03b3 100644 --- a/src/Dialogs.h +++ b/src/Dialogs.h @@ -279,6 +279,10 @@ INT_PTR ThemedDialogBoxParam(HINSTANCE hInstance, LPCTSTR lpTemplate, HWND hWndP HWND CreateThemedDialogParam(HINSTANCE hInstance, LPCTSTR lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam); void CleanupDlgResources(); +//bool GetFolderDlg(HWND hwnd, HPATHL hdir_pth_io, const HPATHL hinidir_pth, bool bSelect); +bool OpenFileDlg(HWND hwnd, HPATHL hfile_pth_io, const HPATHL hinidir_pth); +bool SaveFileDlg(HWND hwnd, HPATHL hfile_pth_io, const HPATHL hinidir_pth); + // --- Hook Procedures for Std-System Dialogs --------------------------------- diff --git a/src/Notepad3.c b/src/Notepad3.c index 70e9c5879..fc1e87099 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -11198,133 +11198,6 @@ bool FileSave(FileSaveFlags fSaveFlags) } -//============================================================================= -// -// _CanonicalizeInitialDir() TODO: use Path_NormalizeEx() here ? -// -static void _CanonicalizeInitialDir(HPATHL hpth_in_out) -{ - if (Path_IsEmpty(hpth_in_out)) { - - if (Path_IsNotEmpty(Paths.CurrentFile)) { - Path_Reset(hpth_in_out, Path_Get(Paths.CurrentFile)); - Path_RemoveFileSpec(hpth_in_out); - } else if (Path_IsNotEmpty(Settings2.DefaultDirectory)) { - Path_Reset(hpth_in_out, Path_Get(Settings2.DefaultDirectory)); - } else { - Path_Reset(hpth_in_out, Path_Get(Paths.WorkingDirectory)); - } - Path_CanonicalizeEx(hpth_in_out); - } - else { // Path_IsNotEmpty(hpth_in_out) - - if (Path_IsRelative(hpth_in_out)) { - Path_AbsoluteFromApp(hpth_in_out, true); - //~ already Path_CanonicalizeEx(hpth_in_out); - } - else { - Path_CanonicalizeEx(hpth_in_out); - } - if (!Path_IsExistingDirectory(hpth_in_out)) { - Path_RemoveFileSpec(hpth_in_out); - } - } - // finally: directory exists ? - if (!Path_IsExistingDirectory(hpth_in_out)) { - Path_Empty(hpth_in_out, false); - } -} - - -// ============================================================================ -// -// OpenFileDlg() -// lpstrInitialDir == NULL : leave initial dir to Open File Explorer -// lpstrInitialDir == ""[empty] : use a reasonable initial directory path -// -// TODO: Replace GetOpenFileNameW() by Common Item Dialog: IFileOpenDialog() -// https://docs.microsoft.com/en-us/windows/win32/shell/common-file-dialog -// -bool OpenFileDlg(HWND hwnd, HPATHL hfile_pth_io, const HPATHL hinidir_pth) -{ - if (!hfile_pth_io) { - return false; - } - - WCHAR szDefExt[64] = { L'\0' }; - WCHAR szFilter[EXTENTIONS_FILTER_BUFFER]; - Style_GetFileFilterStr(szFilter, COUNTOF(szFilter), szDefExt, COUNTOF(szDefExt), false); - - HPATHL hpth_dir = Path_Allocate(Path_Get(hinidir_pth)); - _CanonicalizeInitialDir(hpth_dir); - - OPENFILENAME ofn = { sizeof(OPENFILENAME) }; - ofn.hwndOwner = hwnd; - ofn.hInstance = Globals.hInstance; - ofn.lpstrFilter = szFilter; - ofn.lpstrCustomFilter = NULL; // no preserved (static member) user-defined patten - ofn.lpstrInitialDir = Path_IsNotEmpty(hpth_dir) ? Path_Get(hpth_dir) : NULL; - ofn.lpstrFile = Path_WriteAccessBuf(hfile_pth_io, PATHLONG_MAX_CCH); - ofn.nMaxFile = (DWORD)Path_GetBufCount(hfile_pth_io); - ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | /* OFN_NOCHANGEDIR |*/ - OFN_DONTADDTORECENT | OFN_PATHMUSTEXIST | - OFN_SHAREAWARE /*| OFN_NODEREFERENCELINKS*/; - ofn.lpstrDefExt = StrIsNotEmpty(szDefExt) ? szDefExt : Settings2.DefaultExtension; - - bool const res = GetOpenFileNameW(&ofn); - - Path_Sanitize(hfile_pth_io); - - Path_Release(hpth_dir); - Path_FreeExtra(hfile_pth_io, MAX_PATH_EXPLICIT); - - return res; -} - - -// ============================================================================ -// -// SaveFileDlg() -// lpstrInitialDir == NULL : leave initial dir to Save File Explorer -// lpstrInitialDir == ""[empty] : use a reasonable initial directory path -// -bool SaveFileDlg(HWND hwnd, HPATHL hfile_pth_io, const HPATHL hinidir_pth) -{ - if (!hfile_pth_io) { - return false; - } - - WCHAR szDefExt[64] = { L'\0' }; - WCHAR szFilter[EXTENTIONS_FILTER_BUFFER]; - Style_GetFileFilterStr(szFilter, COUNTOF(szFilter), szDefExt, COUNTOF(szDefExt), true); - - HPATHL hpth_dir = Path_Copy(hinidir_pth); - _CanonicalizeInitialDir(hpth_dir); - - OPENFILENAME ofn = { sizeof(OPENFILENAME) }; - ofn.hwndOwner = hwnd; - ofn.hInstance = Globals.hInstance; - ofn.lpstrFilter = szFilter; - ofn.lpstrCustomFilter = NULL; // no preserved (static member) user-defined patten - ofn.lpstrInitialDir = Path_IsNotEmpty(hpth_dir) ? Path_Get(hpth_dir) : NULL; - ofn.lpstrFile = Path_WriteAccessBuf(hfile_pth_io, PATHLONG_MAX_CCH); - ofn.nMaxFile = (DWORD)Path_GetBufCount(hfile_pth_io); - ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | /*| OFN_NOCHANGEDIR*/ - /*OFN_NODEREFERENCELINKS |*/ OFN_OVERWRITEPROMPT | - OFN_DONTADDTORECENT | OFN_PATHMUSTEXIST; - ofn.lpstrDefExt = StrIsNotEmpty(szDefExt) ? szDefExt : Settings2.DefaultExtension; - - bool const res = GetSaveFileNameW(&ofn); - - Path_Sanitize(hfile_pth_io); - - Path_Release(hpth_dir); - Path_FreeExtra(hfile_pth_io, MAX_PATH_EXPLICIT); - - return res; -} - - // ============================================================================ // // CountRunningInstances() diff --git a/src/Notepad3.h b/src/Notepad3.h index f239321e5..aaf5018bc 100644 --- a/src/Notepad3.h +++ b/src/Notepad3.h @@ -161,8 +161,6 @@ bool FileSave(FileSaveFlags fSaveFlags); bool FileRevert(const HPATHL hfile_pth, bool bIgnoreCmdLnEnc); bool FileIO(bool fLoad, const HPATHL hfile_pth, EditFileIOStatus* status, FileLoadFlags fLoadFlags, FileSaveFlags fSaveFlags, bool bSetSavePoint); -bool OpenFileDlg(HWND hwnd, HPATHL hfile_pth_io, const HPATHL hinidir_pth); -bool SaveFileDlg(HWND hwnd, HPATHL hfile_pth_io, const HPATHL hinidir_pth); void CALLBACK PasteBoardTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime); void InstallFileWatching(const bool bInstall); diff --git a/src/PathLib.c b/src/PathLib.c index 3d91cbc9c..c9a198502 100644 --- a/src/PathLib.c +++ b/src/PathLib.c @@ -852,6 +852,22 @@ bool PTHAPI Path_IsEmpty(const HPATHL hpth) // ---------------------------------------------------------------------------- +bool PTHAPI Path_IsRoot(const HPATHL hpth) +{ + HSTRINGW hstr = ToHStrgW(hpth); + if (!hstr) + return false; + + //PrependLongPathPrefix(hpth, false); + + WCHAR wchPathBegin[MAX_PATH_EXPLICIT] = { L'\0' }; + StringCchCopy(wchPathBegin, COUNTOF(wchPathBegin), StrgGet(hstr)); + + return PathIsRootW(wchPathBegin); +} +// ---------------------------------------------------------------------------- + + bool PTHAPI Path_IsValidUNC(const HPATHL hpth) { HSTRINGW hstr = ToHStrgW(hpth); diff --git a/src/PathLib.h b/src/PathLib.h index cdd936f2c..7d3135258 100644 --- a/src/PathLib.h +++ b/src/PathLib.h @@ -94,6 +94,7 @@ void PTHAPI Path_FreeExtra(HPATHL hpth_in_out, size_t keep_length); bool PTHAPI Path_Canonicalize(HPATHL hpth_in_out); bool PTHAPI Path_IsEmpty(const HPATHL hpth); inline bool PTHAPI Path_IsNotEmpty(const HPATHL hpth) { return !Path_IsEmpty(hpth); }; +bool PTHAPI Path_IsRoot(const HPATHL hpth); bool PTHAPI Path_IsValidUNC(const HPATHL hpth); bool PTHAPI Path_IsExistingDirectory(const HPATHL hpth); diff --git a/src/TypeDefs.h b/src/TypeDefs.h index 649109cce..7ca44f2fb 100644 --- a/src/TypeDefs.h +++ b/src/TypeDefs.h @@ -391,10 +391,10 @@ typedef enum AutoSaveBackupOptions { ASB_Shutdown = 1 << 2, ASB_Backup = 1 << 3, - ASB_SideBySide = 1 << 4, + ASB_OnAutoSave = 1 << 4, + ASB_SideBySide = 1 << 5, - - ASB_Default = ASB_Suspend | ASB_Shutdown, + ASB_Default = ASB_Suspend | ASB_Shutdown | ASB_SideBySide, } AutoSaveBackupOptions;