diff --git a/src/Edit.c b/src/Edit.c index 381384916..0b5dd2f61 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -5162,6 +5162,7 @@ void EditSortLines(HWND hwnd, int iSortFlags) } BeginWaitCursor(iLineCount > 10000, L" Sorting Lines..."); + UndoTransActionBegin(); DocPos iMaxLineLen = Sci_GetRangeMaxLineLength(iLineStart, iLineEnd); char* const pmsz = AllocMem(iMaxLineLen + 1, HEAP_ZERO_MEMORY); @@ -5331,6 +5332,7 @@ void EditSortLines(HWND hwnd, int iSortFlags) EditSetSelectionEx(iAnchorPos, iCurPos, -1, -1); } + EndUndoTransAction(); EndWaitCursor(); } @@ -7276,8 +7278,6 @@ void EditMarkAllOccurrences(HWND hwnd, bool bForceClear) int const searchFlags = GetMarkAllOccSearchFlags(); - DocChangeTransactionBegin(); - if (Settings.MarkOccurrencesMatchVisible) { // get visible lines for update @@ -7292,8 +7292,6 @@ void EditMarkAllOccurrences(HWND hwnd, bool bForceClear) } else { EditMarkAll(NULL, searchFlags, 0, Sci_GetDocEndPosition(), false); } - - EndDocChangeTransaction(); } @@ -7488,7 +7486,9 @@ bool EditReplaceAll(HWND hwnd, LPEDITFINDREPLACE lpefr, bool bShowInfo) DocPos enlargement = 0; BeginWaitCursorUID(true, IDS_MUI_SB_REPLACE_ALL); + UndoTransActionBegin(); Globals.iReplacedOccurrences = EditReplaceAllInRange(hwnd, lpefr, start, end, &enlargement); + EndUndoTransAction(); EndWaitCursor(); WCHAR wchOcc[64] = { L'\0' }; diff --git a/src/Notepad3.c b/src/Notepad3.c index a0b43f607..38876398a 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -232,13 +232,19 @@ const WCHAR* const TBBUTTON_DEFAULT_IDS_V2 = L"1 2 4 3 28 0 5 6 0 7 8 9 0 10 11 // // Save Needed Flag // -static bool s_DocNeedSaving = false; // dirty-flag +static bool s_NeedSavingForced = false; // dirty-flag -static inline void SetSaveNeeded() +inline static bool IsSaveNeeded() { - AutoSaveStart(!s_DocNeedSaving); - s_DocNeedSaving = true; + return SciCall_GetModify() || s_NeedSavingForced; +} +static inline void SetSaveNeeded(const bool bSetFlag) +{ + AutoSaveStart(!s_NeedSavingForced); + if (bSetFlag) { + s_NeedSavingForced = true; + } if (IsWindow(Globals.hwndDlgFindReplace)) { PostWMCommand(Globals.hwndDlgFindReplace, IDC_DOC_MODIFIED); } @@ -251,14 +257,9 @@ static inline void SetSavePoint() UpdateToolbar(); } -inline static bool IsSaveNeeded() -{ - return SciCall_GetModify() || s_DocNeedSaving; -} - void SetSaveDone() { - s_DocNeedSaving = false; + s_NeedSavingForced = false; SetSavePoint(); } @@ -408,14 +409,22 @@ static void CopyUndoRedoSelection(void* dst, const void* src) static UT_icd UndoRedoSelection_icd = { sizeof(UndoRedoSelection_t), InitUndoRedoSelection, CopyUndoRedoSelection, DelUndoRedoSelection }; static UT_array* UndoRedoSelectionUTArray = NULL; -static inline bool _InUndoRedoTransaction(); static void _SaveRedoSelection(const LONG token); static LONG _SaveUndoSelection(); static LONG _UndoRedoActionMap(const LONG token, const UndoRedoSelection_t** selection); // => UndoTransActionBegin(); // => EndUndoTransAction(); -static inline void _SplitUndoTransaction() { + +static volatile LONG UndoActionToken = URTok_NoRecording; // needs UndoRedoRecordingStart() + +static inline bool _InUndoRedoTransaction() +{ + return (InterlockedOr(&UndoActionToken, 0L) >= URTok_TokenStart); +} + +static inline void _SplitUndoTransaction() +{ if (!_InUndoRedoTransaction()) { SciCall_BeginUndoAction(); /* noop */ @@ -448,10 +457,12 @@ static __forceinline bool NotifyDocChanged() return (InterlockedOr(&iNotifyChangeStackCounter, 0L) == 0L); } -void SetNotifyDocChangedEvent(const SciEventMask evm) +void SetNotifyDocChangedEvent() { + if (NotifyDocChanged()) { + SciCall_SetModEventMask(EVM_None); + } InterlockedIncrement(&iNotifyChangeStackCounter); - SciCall_SetModEventMask(evm); } void ResetNotifyDocChangedEvent() @@ -1768,7 +1779,7 @@ HWND InitInstance(const HINSTANCE hInstance, LPCWSTR pszCmdLine, int nCmdShow) if (Path_IsExistingFile(s_hpthRelaunchElevatedFile)) { DeleteFileW(Path_Get(s_hpthRelaunchElevatedFile)); } - SetSaveNeeded(); + SetSaveNeeded(true); } if (Path_IsNotEmpty(Paths.CurrentFile)) { @@ -3836,11 +3847,11 @@ LRESULT MsgFileChangeNotify(HWND hwnd, WPARAM wParam, LPARAM lParam) if (IsYesOkay(InfoBoxLng(MB_YESNO | MB_ICONWARNING, NULL, IDS_MUI_FILECHANGENOTIFY2))) { FileSave(FSF_SaveAlways); } else { - SetSaveNeeded(); + SetSaveNeeded(true); } } else { // FWM_INDICATORSILENT: nothing todo here - SetSaveNeeded(); + SetSaveNeeded(true); } } @@ -4817,7 +4828,7 @@ LRESULT MsgCommand(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) BeginWaitCursorUID(true, IDS_MUI_SB_RECODING_DOC); if (EditSetNewEncoding(Globals.hwndEdit, iNewEncoding, (s_flagSetEncoding != CPI_NONE))) { UpdateMargins(true); - SetSaveNeeded(); + SetSaveNeeded(true); } EndWaitCursor(); UpdateToolbar(); @@ -6437,7 +6448,7 @@ LRESULT MsgCommand(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) case IDM_SETPASS: if (GetFileKey(Globals.hwndEdit)) { - SetSaveNeeded(); + SetSaveNeeded(true); } break; @@ -8226,11 +8237,11 @@ inline static LRESULT _MsgNotifyLean(const SCNotification *const scn, bool* bMod } break; case SCN_SAVEPOINTREACHED: { - SetSavePoint(); + SetSaveDone(); } break; case SCN_SAVEPOINTLEFT: { - SetSaveNeeded(); + SetSaveNeeded(false); } break; case SCN_MODIFYATTEMPTRO: { @@ -10195,13 +10206,6 @@ void UpdateUI() { //============================================================================= -static volatile LONG UndoActionToken = URTok_NoRecording; // needs UndoRedoRecordingStart() - -static inline bool _InUndoRedoTransaction() -{ - return (InterlockedOr(&UndoActionToken, 0L) >= URTok_TokenStart); -} - LONG BeginUndoActionEx() { if (!_InUndoRedoTransaction()) { @@ -10209,22 +10213,22 @@ LONG BeginUndoActionEx() SciCall_BeginUndoAction(); return URTok_NoTokenFlag; } - return URTok_InTransaction; + return InterlockedOr(&UndoActionToken, 0L); // current token } void EndLockUndoActionEx(const LONG token) { if (_InUndoRedoTransaction()) { - if (InterlockedOr(&UndoActionToken, 0L) == token) { - SciCall_EndUndoAction(); - InterlockedExchange(&UndoActionToken, URTok_NoTransaction); + if (token == InterlockedOr(&UndoActionToken, 0L)) { + if (token == URTok_NoTokenFlag) { + SciCall_EndUndoAction(); + InterlockedExchange(&UndoActionToken, URTok_NoTransaction); + } + //else foreign token - okay, child transaction } else { assert("Wrong Transaction" && 0); } } - else if (URTok_InTransaction == token) { - // okay, was child transaction - } else { assert("No Transaction" && 0); } @@ -10239,7 +10243,6 @@ void UndoRedoRecordingStart() _UndoRedoActionMap(URTok_NoTransaction, NULL); // clear SciCall_SetUndoCollection(true); SciCall_EmptyUndoBuffer(); - SetSavePoint(); SciCall_SetChangeHistory(SC_CHANGE_HISTORY_ENABLED | Settings.ChangeHistoryMode); UpdateMargins(true); } @@ -10347,8 +10350,8 @@ static LONG _SaveUndoSelection() LONG const token = _UndoRedoActionMap(URTok_NoTransaction, &pSel); if (token >= 0) { - //~SciCall_AddUndoAction(token, UNDO_MAY_COALESCE); - SciCall_AddUndoAction((int)token, UNDO_NONE); + SciCall_AddUndoAction(token, UNDO_MAY_COALESCE); + //SciCall_AddUndoAction((int)token, UNDO_NONE); } DelUndoRedoSelection(&sel); // utarray_free() @@ -10465,15 +10468,17 @@ const char* const _assert_msg = "Broken UndoRedo-Transaction!"; void EndUndoActionSelection(const LONG token) { switch (token) { - case URTok_NoTransaction: case URTok_InTransaction: // nothing to do (child transaction) break; + case URTok_NoTransaction: + assert(_assert_msg && InterlockedOr(&UndoActionToken, 0L) == URTok_NoTransaction); + break; case URTok_NoRecording: assert(_assert_msg && InterlockedOr(&UndoActionToken, 0L) == URTok_NoRecording); break; default: - if (InterlockedOr(&UndoActionToken, 0L) == token) { + if (token == InterlockedOr(&UndoActionToken, 0L)) { _SaveRedoSelection(token); SciCall_EndUndoAction(); InterlockedExchange(&UndoActionToken, URTok_NoTransaction); @@ -10597,7 +10602,7 @@ void RestoreActionSelection(const LONG token, DoAction doAct) // static LONG _UndoRedoActionMap(const LONG token, const UndoRedoSelection_t** selection) { - static ULONG uiTokenCnt = URTok_TokenStart; + static ULONG uiTokenCnt = URTok_TokenStart; if (UndoRedoSelectionUTArray == NULL) { return URTok_NoRecording; @@ -10637,7 +10642,7 @@ static LONG _UndoRedoActionMap(const LONG token, const UndoRedoSelection_t** sel (*selection) = (UndoRedoSelection_t*)utarray_eltptr(UndoRedoSelectionUTArray, utoken); } else { // this is a set request (fill redo pos) - assert(false); // not used yet + assert("Invalid set request (fill redo pos)!" && 0); // not used yet //~utarray_insert(UndoRedoSelectionUTArray, (void*)(*selection), utoken); } // don't clear map item here (token used in redo/undo again) @@ -10788,7 +10793,7 @@ bool FileLoad(const HPATHL hfile_pth, FileLoadFlags fLoadFlags) Style_SetDefaultLexer(Globals.hwndEdit); - SetSavePoint(); + SetSaveDone(); UpdateToolbar(); UpdateMargins(true); diff --git a/src/Notepad3.h b/src/Notepad3.h index 37679bddb..f0552e25f 100644 --- a/src/Notepad3.h +++ b/src/Notepad3.h @@ -193,30 +193,36 @@ LRESULT MsgCommand(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam); LRESULT MsgSysCommand(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam); LRESULT MsgUahMenuBar(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam); -LRESULT MsgNonClientAreaPaint(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam); +//LRESULT MsgNonClientAreaPaint(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam); // ---------------------------------------------------------------------------- -void SetNotifyDocChangedEvent(const SciEventMask evm); -void ResetNotifyDocChangedEvent(); - #define DisableNotifyEvents() { int _evm_ = 0; __try { _evm_ = SciCall_GetModEventMask(); SciCall_SetModEventMask(EVM_None); #define EnableNotifyEvents() ;} __finally { SciCall_SetModEventMask(_evm_); } } // ---------------------------------------------------------------------------- +void SetNotifyDocChangedEvent(); +void ResetNotifyDocChangedEvent(); + +// none msg change notify, preserve redo-undo selection stack (only in simple, non complex operations) +#define UndoTransActionBegin() { LONG _token_ = 0L; __try { _token_ = BeginUndoActionSelection(); SetNotifyDocChangedEvent(); +#define EndUndoTransAction() ;} __finally { ResetNotifyDocChangedEvent(); EndUndoActionSelection(_token_); } } + +// ---------------------------------------------------------------------------- + LONG BeginUndoActionEx(); void EndLockUndoActionEx(const LONG token); // lean msg change notify (preferred) - does not preserve redo-undo selection stack -#define DocChangeTransactionBegin() { LONG _tok_ = 0L; __try { _tok_ = BeginUndoActionEx(); SetNotifyDocChangedEvent(EVM_None); +#define DocChangeTransactionBegin() { LONG _tok_ = 0L; __try { _tok_ = BeginUndoActionEx(); SetNotifyDocChangedEvent(); #define EndDocChangeTransaction() ;} __finally { ResetNotifyDocChangedEvent(); EndLockUndoActionEx(_tok_); } } -// ---------------------------------------------------------------------------- - -// none msg change notify, preserve redo-undo selection stack (only in simple, non complex operations) -#define UndoTransActionBegin() { LONG _token_ = 0L; __try { _token_ = BeginUndoActionSelection(); SetNotifyDocChangedEvent(EVM_None); -#define EndUndoTransAction() ;} __finally { ResetNotifyDocChangedEvent(); EndUndoActionSelection(_token_); } } +// DEBUG: +//#define DocChangeTransactionBegin() UndoTransActionBegin() +//#define EndDocChangeTransaction() EndUndoTransAction() +//#define UndoTransActionBegin() DocChangeTransactionBegin() +//#define EndUndoTransAction() EndDocChangeTransaction() // ---------------------------------------------------------------------------- diff --git a/src/SciCall.h b/src/SciCall.h index ff2060728..7534aa917 100644 --- a/src/SciCall.h +++ b/src/SciCall.h @@ -700,13 +700,22 @@ DeclareSciCallV1(SetAdditionalCaretsVisible, SETADDITIONALCARETSVISIBLE, bool, f // Undo/Redo Stack // DeclareSciCallV0(EmptyUndoBuffer, EMPTYUNDOBUFFER); -DeclareSciCallV0(BeginUndoAction, BEGINUNDOACTION); +//DeclareSciCallV0(BeginUndoAction, BEGINUNDOACTION); DeclareSciCallV2(AddUndoAction, ADDUNDOACTION, int, token, int, flags); -DeclareSciCallV0(EndUndoAction, ENDUNDOACTION); +//DeclareSciCallV0(EndUndoAction, ENDUNDOACTION); DeclareSciCallR0(GetUndoCollection, GETUNDOCOLLECTION, bool); DeclareSciCallV1(SetUndoCollection, SETUNDOCOLLECTION, bool, bCollectUndo); +inline void SciCall_BeginUndoAction() +{ + SciCall(SCI_BEGINUNDOACTION, 0, 0); +} +inline void SciCall_EndUndoAction() +{ + SciCall(SCI_ENDUNDOACTION, 0, 0); +} + //============================================================================= // // IME