From e50e6057ea2b0e17e268d756cb781e12e9dd315f Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Wed, 4 Aug 2021 10:27:15 +0200 Subject: [PATCH] +add: File on disk changed notification in title bar --- src/Dialogs.c | 13 +++++++--- src/Dialogs.h | 4 ++-- src/Notepad3.c | 65 +++++++++++++++++++++++++++++++++----------------- 3 files changed, 55 insertions(+), 27 deletions(-) diff --git a/src/Dialogs.c b/src/Dialogs.c index 9e57e2265..1a3a18a1e 100644 --- a/src/Dialogs.c +++ b/src/Dialogs.c @@ -4829,8 +4829,9 @@ void AppendAdditionalTitleInfo(LPCWSTR lpszAddTitleInfo) { StringCchCat(s_wchAdditionalTitleInfo, COUNTOF(s_wchAdditionalTitleInfo), lpszAddTitleInfo); } -static const WCHAR *pszSep = L" - "; -static const WCHAR *pszMod = L"* "; +static const WCHAR *pszFChg = L"@ "; +static const WCHAR *pszMod = L"* "; +static const WCHAR *pszSep = L" - "; static WCHAR s_wchCachedFile[MAX_PATH] = { L'\0' }; static WCHAR s_wchCachedDisplayName[MAX_PATH] = { L'\0' }; @@ -4838,7 +4839,7 @@ static WCHAR s_wchCachedDisplayName[MAX_PATH] = { L'\0' }; void SetWindowTitle(HWND hwnd, LPCWSTR lpszFile, int iFormat, bool bPasteBoard, bool bIsElevated, bool bModified, - bool bFileLocked, bool bReadOnly, LPCWSTR lpszExcerpt) { + bool bFileLocked, bool bFileChanged, bool bReadOnly, LPCWSTR lpszExcerpt) { if (s_bFreezeAppTitle) { return; @@ -4861,16 +4862,22 @@ void SetWindowTitle(HWND hwnd, LPCWSTR lpszFile, int iFormat, WCHAR szTitle[MIDSZ_BUFFER] = { L'\0' }; + if (bFileChanged) { + StringCchCat(szTitle, COUNTOF(szTitle), pszFChg); + } if (bModified) { StringCchCat(szTitle, COUNTOF(szTitle), pszMod); } if (StrIsNotEmpty(lpszExcerpt)) { + WCHAR szExcrptFmt[32] = { L'\0' }; WCHAR szExcrptQuot[SMALL_BUFFER] = { L'\0' }; GetLngString(IDS_MUI_TITLEEXCERPT, szExcrptFmt, COUNTOF(szExcrptFmt)); StringCchPrintf(szExcrptQuot, COUNTOF(szExcrptQuot), szExcrptFmt, lpszExcerpt); StringCchCat(szTitle, COUNTOF(szTitle), szExcrptQuot); + } else if (StrIsNotEmpty(lpszFile)) { + if ((iFormat < 2) && !PathIsRoot(lpszFile)) { if (StringCchCompareN(s_wchCachedFile, COUNTOF(s_wchCachedFile), lpszFile, MAX_PATH) != 0) { StringCchCopy(s_wchCachedFile, COUNTOF(s_wchCachedFile), lpszFile); diff --git a/src/Dialogs.h b/src/Dialogs.h index 0015e8a8f..1ca98fffe 100644 --- a/src/Dialogs.h +++ b/src/Dialogs.h @@ -81,8 +81,8 @@ LONG InfoBoxLng(UINT uType, LPCWSTR lpstrSetting, UINT uidMsg, ...); #define INFOBOX_MODE(_R_) HIWORD(_R_) void SetWindowTitle(HWND hwnd, LPCWSTR lpszFile, int iFormat, - bool bPasteBoard, bool bIsElevated, bool bModified, - bool bFileLocked, bool bReadOnly, LPCWSTR lpszExcerpt); + bool bPasteBoard, bool bIsElevated, bool bModified, + bool bFileLocked, bool bFileChanged, bool bReadOnly, LPCWSTR lpszExcerpt); void SetAdditionalTitleInfo(LPCWSTR lpszAddTitleInfo); void AppendAdditionalTitleInfo(LPCWSTR lpszAddTitleInfo); void SetWindowTransparentMode(HWND hwnd, bool bTransparentMode, int iOpacityLevel); diff --git a/src/Notepad3.c b/src/Notepad3.c index 953ff5be1..988bea625 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -534,6 +534,34 @@ static void CALLBACK MQ_ExecuteNext(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWOR } +//============================================================================= +// +// HasCurrentFileChanged +// + +static WIN32_FIND_DATA s_fdCurFile = { 0 }; +static HANDLE s_hEventFileChangedExt = INVALID_HANDLE_VALUE; + +static inline bool HasCurrentFileChanged() { + if (StrIsEmpty(Paths.CurrentFile)) { + return false; + } + WIN32_FIND_DATA fdUpdated = { 0 }; + if (!GetFileAttributesEx(Paths.CurrentFile, GetFileExInfoStandard, &fdUpdated)) { + SetEvent(s_hEventFileChangedExt); + return true; // The current file has been removed + } + bool const changed = (s_fdCurFile.nFileSizeLow != fdUpdated.nFileSizeLow) || (s_fdCurFile.nFileSizeHigh != fdUpdated.nFileSizeHigh) + //~|| (CompareFileTime(&s_fdCurFile.ftLastWriteTime, &fdUpdated.ftLastWriteTime) != 0) + || (s_fdCurFile.ftLastWriteTime.dwLowDateTime != fdUpdated.ftLastWriteTime.dwLowDateTime) + || (s_fdCurFile.ftLastWriteTime.dwHighDateTime != fdUpdated.ftLastWriteTime.dwHighDateTime); + if (changed) { + SetEvent(s_hEventFileChangedExt); + } + return changed; +} + + //============================================================================= // // InvalidateStyleRedraw @@ -728,6 +756,11 @@ static void _CleanUpResources(const HWND hwnd, bool bIsInitialized) UndoRedoSelectionUTArray = NULL; } + if (IS_VALID_HANDLE(s_hEventFileChangedExt)) { + CloseHandle(s_hEventFileChangedExt); + s_hEventFileChangedExt = INVALID_HANDLE_VALUE; + } + // ------------------------------- // Save Settings is done elsewhere // ------------------------------- @@ -1369,8 +1402,8 @@ HWND InitInstance(const HINSTANCE hInstance, LPCWSTR pszCmdLine, int nCmdShow) SetDialogIconNP3(Globals.hwndMain); InitWindowCommon(Globals.hwndMain, true); - // manual reset und initially not signaled (TRUE , FALSE) - // s_hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + // manual (no automatic) reset & initial state: not signaled (TRUE, FALSE) + s_hEventFileChangedExt = CreateEvent(NULL, TRUE, FALSE, NULL); if (Settings.TransparentMode) { SetWindowTransparentMode(Globals.hwndMain, true, Settings2.OpacityLevel); @@ -9268,11 +9301,13 @@ void UpdateSaveSettingsCmds() void UpdateTitleBar(const HWND hwnd) { if (hwnd == Globals.hwndMain) { + bool const bFileLocked = (FileWatching.FileWatchingMode == FWM_EXCLUSIVELOCK); + bool const bFileChanged = (WaitForSingleObject(s_hEventFileChangedExt, 0) != WAIT_TIMEOUT); SetWindowTitle(Globals.hwndMain, Paths.CurrentFile, Settings.PathNameFormat, - s_flagPasteBoard, s_bIsProcessElevated, GetDocModified(), - bFileLocked, s_bFileReadOnly, s_wchTitleExcerpt); + s_flagPasteBoard, s_bIsProcessElevated, GetDocModified(), + bFileLocked, bFileChanged, s_bFileReadOnly, s_wchTitleExcerpt); } PostMessage(hwnd, WM_NCACTIVATE, FALSE, -1); // (!) PostMessage(hwnd, WM_NCACTIVATE, TRUE, 0); @@ -9746,6 +9781,10 @@ bool FileIO(bool fLoad, LPWSTR pszFileName, EditFileIOStatus *status, s_bFileReadOnly = IsReadOnly(GetFileAttributes(pszFileName)); + if (fSuccess) { + ResetEvent(s_hEventFileChangedExt); + } + EndWaitCursor(); return(fSuccess); @@ -11167,24 +11206,6 @@ void CALLBACK PasteBoardTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTi // //============================================================================= -static WIN32_FIND_DATA s_fdCurFile = { 0 }; - -static inline bool HasCurrentFileChanged() { - if (StrIsEmpty(Paths.CurrentFile)) { - return false; - } - WIN32_FIND_DATA fdUpdated = { 0 }; - if (!GetFileAttributesEx(Paths.CurrentFile, GetFileExInfoStandard, &fdUpdated)) { - return true; // The current file has been removed - } - bool const changed = (s_fdCurFile.nFileSizeLow != fdUpdated.nFileSizeLow) || (s_fdCurFile.nFileSizeHigh != fdUpdated.nFileSizeHigh) - //~|| (CompareFileTime(&s_fdCurFile.ftLastWriteTime, &fdUpdated.ftLastWriteTime) != 0) - || (s_fdCurFile.ftLastWriteTime.dwLowDateTime != fdUpdated.ftLastWriteTime.dwLowDateTime) - || (s_fdCurFile.ftLastWriteTime.dwHighDateTime != fdUpdated.ftLastWriteTime.dwHighDateTime); - return changed; -} -// ---------------------------------------------------------------------------- - static DWORD s_dwFileChangeNotifyTime = 0UL; static inline void NotifyIfFileHasChanged(const bool forcedNotify) {