From 999292b85f8af618427789997f6dcf39249ba6dc Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Sat, 5 May 2018 09:47:56 +0200 Subject: [PATCH 1/3] - fix: broken Undo/Redo stack (in case of selection) --- src/Edit.c | 59 ++++---- src/Notepad3.c | 394 +++++++++++++++++++++++++++---------------------- src/Notepad3.h | 12 +- 3 files changed, 248 insertions(+), 217 deletions(-) diff --git a/src/Edit.c b/src/Edit.c index b081acfce..efdce6d8c 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -364,15 +364,14 @@ void EditInitWordDelimiter(HWND hwnd) // void __fastcall _ClearTextBuffer(HWND hwnd) { + UndoRedoStop(); + SendMessage(hwnd, SCI_CANCEL, 0, 0); _IGNORE_NOTIFY_CHANGE_; if (SciCall_GetReadOnly()) { SciCall_SetReadOnly(false); } - UndoRedoActionMap(-1, NULL); - SciCall_SetUndoCollection(false); - EditClearAllOccurrenceMarkers(hwnd, 0, -1); if (EditToggleView(g_hwndEdit, false)) { EditToggleView(g_hwndEdit, true); @@ -381,8 +380,6 @@ void __fastcall _ClearTextBuffer(HWND hwnd) SendMessage(hwnd, SCI_CLEARALL, 0, 0); SendMessage(hwnd, SCI_MARKERDELETEALL, (WPARAM)MARKER_NP3_BOOKMARK, 0); - SciCall_SetUndoCollection(true); - SendMessage(hwnd, SCI_SETSCROLLWIDTH, 1, 0); SendMessage(hwnd, SCI_SETXOFFSET, 0, 0); @@ -396,21 +393,20 @@ void __fastcall _ClearTextBuffer(HWND hwnd) // void __fastcall _InitTextBuffer(HWND hwnd, const char* lpstrText, DocPos textLen, bool bSetSavePoint) { - SciCall_SetUndoCollection(false); - if (textLen > 0) { SciCall_AddText(textLen, lpstrText); } SciCall_GotoPos(0); SciCall_ChooseCaretX(); - SciCall_SetUndoCollection(true); + UndoRedoStart(); - if (bSetSavePoint) { SendMessage(hwnd, SCI_SETSAVEPOINT, 0, 0); } + if (bSetSavePoint) { + SendMessage(hwnd, SCI_SETSAVEPOINT, 0, 0); + } } - //============================================================================= // // EditSetNewText() @@ -508,14 +504,14 @@ bool EditSetNewEncoding(HWND hwnd,int iNewEncoding,bool bNoUI,bool bSetSavePoint if (SciCall_GetTextLength() == 0) { - bool bIsEmptyUndoHistory = (SendMessage(hwnd, SCI_CANUNDO, 0, 0) == 0 && SendMessage(hwnd, SCI_CANREDO, 0, 0) == 0); + bool bIsEmptyUndoHistory = !(SciCall_CanUndo() || SciCall_CanRedo()); + bool doNewEncoding = (!bIsEmptyUndoHistory && !bNoUI) ? (InfoBox(MBYESNO, L"MsgConv2", IDS_ASK_ENCODING2) == IDYES) : true; if (doNewEncoding) { return EditConvertText(hwnd,iCurrentEncoding,iNewEncoding,bSetSavePoint); - } } else { @@ -5470,9 +5466,9 @@ INT_PTR CALLBACK EditFindReplaceDlgProcW(HWND hwnd,UINT umsg,WPARAM wParam,LPARA case IDC_REPLACE: { bReplaceInitialized = true; - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditReplace(sg_pefrData->hwnd, sg_pefrData); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; @@ -6095,11 +6091,11 @@ bool EditReplaceAll(HWND hwnd, LPCEDITFINDREPLACE lpefr, bool bShowInfo) BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; iReplacedOccurrences = EditReplaceAllInRange(hwnd, lpefr, start, end, &enlargement); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); @@ -6131,7 +6127,7 @@ bool EditReplaceAllInSelection(HWND hwnd, LPCEDITFINDREPLACE lpefr, bool bShowIn const DocPos anchorPos = SciCall_GetAnchor(); DocPos enlargement = 0; - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; bool const bWaitCursor = ((end - start) > (512 * 512)) ? true : false; if (bWaitCursor) { BeginWaitCursor(NULL); } @@ -6140,24 +6136,21 @@ bool EditReplaceAllInSelection(HWND hwnd, LPCEDITFINDREPLACE lpefr, bool bShowIn _OBSERVE_NOTIFY_CHANGE_; if (bWaitCursor) { EndWaitCursor(); } - if (iReplacedOccurrences <= 0) { - EndUndoAction(token); - return false; - } - - if (currPos < anchorPos) - SciCall_SetSel(anchorPos + enlargement, currPos); - else - SciCall_SetSel(anchorPos, currPos + enlargement); - - EndUndoAction(token); - - if (bShowInfo) { - if (iReplacedOccurrences > 0) - InfoBox(0, L"MsgReplaceCount", IDS_REPLCOUNT, iReplacedOccurrences); + if (iReplacedOccurrences > 0) + { + if (currPos < anchorPos) + SciCall_SetSel(anchorPos + enlargement, currPos); else - InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); + SciCall_SetSel(anchorPos, currPos + enlargement); + + if (bShowInfo) { + if (iReplacedOccurrences > 0) + InfoBox(0, L"MsgReplaceCount", IDS_REPLCOUNT, iReplacedOccurrences); + else + InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); + } } + _END_UNDO_ACTION_; return (iReplacedOccurrences > 0) ? true : false; } diff --git a/src/Notepad3.c b/src/Notepad3.c index dbceb5a79..a752f63ea 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -361,12 +361,15 @@ static char g_pTempLineBufferMain[TEMPLINE_BUFFER]; // undo / redo selections static UT_icd UndoRedoSelection_icd = { sizeof(UndoRedoSelection_t), NULL, NULL, NULL }; static UT_array* UndoRedoSelectionUTArray = NULL; +static int __fastcall _UndoRedoActionMap(int token, UndoRedoSelection_t* selection); static CLIPFORMAT cfDrpF = CF_HDROP; static POINTL ptDummy = { 0, 0 }; static PDROPTARGET pDropTarget = NULL; static DWORD DropFilesProc(CLIPFORMAT cf, HGLOBAL hData, HWND hWnd, DWORD dwKeyState, POINTL pt, void *pUserData); +// declarations + //============================================================================= // // IgnoreNotifyChangeEvent(), ObserveNotifyChangeEvent(), CheckNotifyChangeEvent() @@ -1063,13 +1066,13 @@ HWND InitInstance(HINSTANCE hInstance,LPSTR pszCmdLine,int nCmdShow) bool bAutoIndent2 = bAutoIndent; bAutoIndent = 0; EditJumpTo(g_hwndEdit, -1, 0); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; if (SendMessage(g_hwndEdit, SCI_GETLENGTH, 0, 0) > 0) { SendMessage(g_hwndEdit, SCI_NEWLINE, 0, 0); } SendMessage(g_hwndEdit, SCI_PASTE, 0, 0); SendMessage(g_hwndEdit, SCI_NEWLINE, 0, 0); - EndUndoAction(token); + _END_UNDO_ACTION_; bAutoIndent = bAutoIndent2; if (g_flagJumpTo) EditJumpTo(g_hwndEdit, iInitialLine, iInitialColumn); @@ -3151,7 +3154,7 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) if (g_flagPasteBoard) bLastCopyFromMe = true; - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; if (!SciCall_IsSelectionEmpty()) { SciCall_Cut(); @@ -3160,7 +3163,7 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) SciCall_CopyAllowLine(); SciCall_LineDelete(); } - EndUndoAction(token); + _END_UNDO_ACTION_; UpdateToolbar(); } break; @@ -3198,11 +3201,11 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) { if (g_flagPasteBoard) bLastCopyFromMe = true; - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; _IGNORE_NOTIFY_CHANGE_; SciCall_Paste(); _OBSERVE_NOTIFY_CHANGE_; - EndUndoAction(token); + _END_UNDO_ACTION_; UpdateToolbar(); UpdateStatusbar(false); UpdateLineNumberWidth(); @@ -3213,11 +3216,11 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) { if (g_flagPasteBoard) bLastCopyFromMe = true; - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; _IGNORE_NOTIFY_CHANGE_; EditSwapClipboard(g_hwndEdit, bSkipUnicodeDetection); _OBSERVE_NOTIFY_CHANGE_; - EndUndoAction(token); + _END_UNDO_ACTION_; UpdateToolbar(); UpdateStatusbar(false); UpdateLineNumberWidth(); @@ -3291,18 +3294,18 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_MOVELINEUP: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditMoveUp(g_hwndEdit); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; case IDM_EDIT_MOVELINEDOWN: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditMoveDown(g_hwndEdit); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; @@ -3316,90 +3319,90 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) { if (g_flagPasteBoard) bLastCopyFromMe = true; - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SendMessage(g_hwndEdit,SCI_LINECUT,0,0); + _END_UNDO_ACTION_; UpdateToolbar(); - EndUndoAction(token); } break; case IDM_EDIT_DELETELINE: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SendMessage(g_hwndEdit, SCI_LINEDELETE, 0, 0); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; case IDM_EDIT_DELETELINELEFT: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SendMessage(g_hwndEdit, SCI_DELLINELEFT, 0, 0); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; case IDM_EDIT_DELETELINERIGHT: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SendMessage(g_hwndEdit, SCI_DELLINERIGHT, 0, 0); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; case IDM_EDIT_INDENT: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditIndentBlock(g_hwndEdit, SCI_TAB, true); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; case IDM_EDIT_UNINDENT: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditIndentBlock(g_hwndEdit, SCI_BACKTAB, true); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; case CMD_TAB: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditIndentBlock(g_hwndEdit, SCI_TAB, false); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; case CMD_BACKTAB: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditIndentBlock(g_hwndEdit, SCI_BACKTAB, false); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; case CMD_CTRLTAB: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SendMessage(g_hwndEdit, SCI_SETUSETABS, true, 0); SendMessage(g_hwndEdit, SCI_SETTABINDENTS, false, 0); EditIndentBlock(g_hwndEdit, SCI_TAB, false); SendMessage(g_hwndEdit, SCI_SETTABINDENTS, g_bTabIndents, 0); SendMessage(g_hwndEdit, SCI_SETUSETABS, !g_bTabsAsSpaces, 0); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; case CMD_DELETEBACK: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SendMessage(g_hwndEdit, SCI_DELETEBACK, 0, 0); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; @@ -3411,9 +3414,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_ENCLOSESELECTION: if (EditEncloseSelectionDlg(hwnd,wchPrefixSelection,wchAppendSelection)) { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditEncloseSelection(g_hwndEdit,wchPrefixSelection,wchAppendSelection); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3422,9 +3425,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_SELECTIONDUPLICATE: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SendMessage(g_hwndEdit,SCI_SELECTIONDUPLICATE,0,0); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3442,9 +3445,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_STRIP1STCHAR: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditStripFirstCharacter(g_hwndEdit); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3453,9 +3456,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_STRIPLASTCHAR: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditStripLastCharacter(g_hwndEdit, false, false); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3464,9 +3467,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_TRIMLINES: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditStripLastCharacter(g_hwndEdit, false, true); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3475,9 +3478,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_COMPRESSWS: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditCompressSpaces(g_hwndEdit); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3486,9 +3489,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_MERGEBLANKLINES: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditRemoveBlankLines(g_hwndEdit, true, true); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3496,9 +3499,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_MERGEEMPTYLINES: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditRemoveBlankLines(g_hwndEdit, true, false); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3507,9 +3510,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_REMOVEBLANKLINES: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditRemoveBlankLines(g_hwndEdit, false, true); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3518,9 +3521,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_REMOVEEMPTYLINES: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditRemoveBlankLines(g_hwndEdit, false, false); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3529,9 +3532,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_REMOVEDUPLICATELINES: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditRemoveDuplicateLines(g_hwndEdit, false); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3541,9 +3544,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) { if (EditModifyLinesDlg(hwnd,wchPrefixLines,wchAppendLines)) { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditModifyLines(g_hwndEdit,wchPrefixLines,wchAppendLines); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } } @@ -3554,9 +3557,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) { if (EditAlignDlg(hwnd,&iAlignMode)) { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditAlignText(g_hwndEdit,iAlignMode); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } } @@ -3567,9 +3570,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) { if (EditSortDlg(hwnd,&iSortOptions)) { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditSortLines(g_hwndEdit,iSortOptions); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } } @@ -3587,9 +3590,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) { iWrapCol = (DocPos)max(min(uWrpCol,(UINT)g_iLongLinesLimit),1); BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditWrapToColumn(g_hwndEdit,iWrapCol); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } } @@ -3599,9 +3602,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_SPLITLINES: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditSplitLines(g_hwndEdit); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3610,9 +3613,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_JOINLINES: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditJoinLinesEx(g_hwndEdit, false, true); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3620,9 +3623,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_JOINLN_NOSP: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditJoinLinesEx(g_hwndEdit, false, false); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3630,9 +3633,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_JOINLINES_PARA: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditJoinLinesEx(g_hwndEdit, true, true); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3641,9 +3644,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_CONVERTUPPERCASE: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SendMessage(g_hwndEdit,SCI_UPPERCASE,0,0); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3652,9 +3655,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_CONVERTLOWERCASE: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SendMessage(g_hwndEdit,SCI_LOWERCASE,0,0); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3663,9 +3666,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_INVERTCASE: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditInvertCase(g_hwndEdit); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3674,9 +3677,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_TITLECASE: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditTitleCase(g_hwndEdit); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3685,9 +3688,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_SENTENCECASE: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditSentenceCase(g_hwndEdit); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3696,9 +3699,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_CONVERTTABS: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditTabsToSpaces(g_hwndEdit, g_iTabWidth, false); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3707,9 +3710,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_CONVERTSPACES: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditSpacesToTabs(g_hwndEdit, g_iTabWidth, false); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3718,9 +3721,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_CONVERTTABS2: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditTabsToSpaces(g_hwndEdit, g_iTabWidth, true); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3729,9 +3732,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_CONVERTSPACES2: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditSpacesToTabs(g_hwndEdit, g_iTabWidth, true); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3742,9 +3745,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) WCHAR wszOpen[256] = { L'\0' }; WCHAR wszClose[256] = { L'\0' }; if (EditInsertTagDlg(hwnd, wszOpen, wszClose)) { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditEncloseSelection(g_hwndEdit, wszOpen, wszClose); - EndUndoAction(token); + _END_UNDO_ACTION_; } } break; @@ -3759,9 +3762,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) char *p = StrChrA(msz, ','); if (p) *p = 0; - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SendMessage(g_hwndEdit,SCI_REPLACESEL,0,(LPARAM)msz); - EndUndoAction(token); + _END_UNDO_ACTION_; } } break; @@ -3805,9 +3808,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) } WideCharToMultiByteStrg(Encoding_SciCP,tchDateTime,mszBuf); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SendMessage(g_hwndEdit,SCI_REPLACESEL,0,(LPARAM)mszBuf); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; @@ -3836,9 +3839,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) } WideCharToMultiByteStrg(Encoding_SciCP,pszInsert,mszBuf); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SendMessage(g_hwndEdit,SCI_REPLACESEL,0,(LPARAM)mszBuf); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; @@ -3853,9 +3856,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) wszGuid[wcslen(wszGuid) - 1] = L'\0'; // trim last brace char char mszGuid[40 * 4]; // UTF-8 max of 4 bytes per char if (WideCharToMultiByteStrg(Encoding_SciCP,pwszGuid,mszGuid)) { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SendMessage(g_hwndEdit,SCI_REPLACESEL,0,(LPARAM)mszGuid); - EndUndoAction(token); + _END_UNDO_ACTION_; } } } @@ -3866,7 +3869,7 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_LINECOMMENT: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; switch (SendMessage(g_hwndEdit, SCI_GETLEXER, 0, 0)) { default: @@ -3924,7 +3927,7 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) break; } - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3933,7 +3936,7 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_STREAMCOMMENT: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; switch (SendMessage(g_hwndEdit, SCI_GETLEXER, 0, 0)) { default: @@ -3985,7 +3988,7 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case SCLEX_MATLAB: EditEncloseSelection(g_hwndEdit, L"%{", L"%}"); } - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -3994,9 +3997,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_URLENCODE: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditURLEncode(g_hwndEdit); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -4005,9 +4008,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_URLDECODE: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditURLDecode(g_hwndEdit); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -4016,9 +4019,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_ESCAPECCHARS: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditEscapeCChars(g_hwndEdit); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -4027,9 +4030,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_UNESCAPECCHARS: { BeginWaitCursor(NULL); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditUnescapeCChars(g_hwndEdit); - EndUndoAction(token); + _END_UNDO_ACTION_; EndWaitCursor(); } break; @@ -4037,9 +4040,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_CHAR2HEX: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditChar2Hex(g_hwndEdit); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; @@ -4056,9 +4059,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_SELTOMATCHINGBRACE: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditSelectToMatchingBrace(g_hwndEdit); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; @@ -4895,7 +4898,7 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case CMD_CTRLENTER: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; const DocPos iPos = SciCall_GetCurrentPos(); const DocLn iLine = SciCall_LineFromPosition(iPos); if (iLine <= 0) { @@ -4907,7 +4910,7 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) SciCall_GotoPos(SciCall_GetLineEndPosition(iLine - 1)); SciCall_NewLine(); } - EndUndoAction(token); + _END_UNDO_ACTION_; } break; @@ -4923,9 +4926,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_CLEAR: case CMD_DEL: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SciCall_Clear(); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; @@ -4949,9 +4952,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) const DocPos iIndentPos = SciCall_GetLineIndentPosition(iLine); if (iPos != iAnchor) { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SciCall_SetSel(iPos, iPos); - EndUndoAction(token); + _END_UNDO_ACTION_; } else { if (iPos == iStartPos) @@ -4974,9 +4977,9 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) const DocPos iEndPos = SciCall_GetLineEndPosition(iLine); if (iPos != iAnchor) { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SciCall_SetSel(iPos, iPos); - EndUndoAction(token); + _END_UNDO_ACTION_; } else { if (iStartPos != iEndPos) @@ -5220,54 +5223,54 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case CMD_STRINGIFY: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditEncloseSelection(g_hwndEdit, L"'", L"'"); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; case CMD_STRINGIFY2: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditEncloseSelection(g_hwndEdit, L"\"", L"\""); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; case CMD_EMBRACE: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditEncloseSelection(g_hwndEdit, L"(", L")"); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; case CMD_EMBRACE2: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditEncloseSelection(g_hwndEdit, L"[", L"]"); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; case CMD_EMBRACE3: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditEncloseSelection(g_hwndEdit, L"{", L"}"); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; case CMD_EMBRACE4: { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; EditEncloseSelection(g_hwndEdit, L"`", L"`"); - EndUndoAction(token); + _END_UNDO_ACTION_; } break; @@ -5690,23 +5693,23 @@ LRESULT MsgNotify(HWND hwnd,WPARAM wParam,LPARAM lParam) if (pnmh->code == SCN_MODIFIED) { bool bModified = true; // check for ADDUNDOACTION step - if (scn->modificationType & SC_MOD_CONTAINER) + int const iModType = scn->modificationType; + if (iModType & SC_MOD_CONTAINER) { - if (scn->modificationType & SC_PERFORMED_UNDO) { + if (iModType & SC_PERFORMED_UNDO) { RestoreAction(scn->token, UNDO); } - else if (scn->modificationType & SC_PERFORMED_REDO) { + else if (iModType & SC_PERFORMED_REDO) { RestoreAction(scn->token, REDO); } } - else if ((scn->modificationType & SC_MOD_BEFOREINSERT) || - (scn->modificationType & SC_MOD_BEFOREDELETE)) { - if (!(scn->modificationType & SC_STARTACTION) && !SciCall_IsSelectionEmpty()) { - int const token = BeginUndoAction(); - if (token >= 0) { EndUndoAction(token); } - } - bModified = false; // not yet - } + //else if ((iModType & SC_MOD_BEFOREINSERT) || (iModType & SC_MOD_BEFOREDELETE)) { + // if ((iModType & SC_STARTACTION) && !SciCall_IsSelectionEmpty()) { + // _BEGIN_UNDO_ACTION_; + // _END_UNDO_ACTION_; + // } + // bModified = false; // not yet + //} if (bModified) { _SetDocumentModified(true); } } else if (pnmh->code == SCN_SAVEPOINTREACHED) { @@ -5806,23 +5809,24 @@ LRESULT MsgNotify(HWND hwnd,WPARAM wParam,LPARAM lParam) case SCN_MODIFIED: { bool bModified = true; - if (scn->modificationType & SC_MOD_CONTAINER) { - if (scn->modificationType & SC_PERFORMED_UNDO) { + int const iModType = scn->modificationType; + if (iModType & SC_MOD_CONTAINER) { + if (iModType & SC_PERFORMED_UNDO) { RestoreAction(scn->token, UNDO); } - else if (scn->modificationType & SC_PERFORMED_REDO) { + else if (iModType & SC_PERFORMED_REDO) { RestoreAction(scn->token, REDO); } } - else if ((scn->modificationType & SC_MOD_BEFOREINSERT) || - (scn->modificationType & SC_MOD_BEFOREDELETE)) { - if (!(scn->modificationType & SC_STARTACTION) && !SciCall_IsSelectionEmpty()) { - int const token = BeginUndoAction(); - if (token >= 0) { EndUndoAction(token); } - } - bModified = false; // not yet - } - else if (scn->modificationType & SC_MOD_CHANGESTYLE) { + //else if ((iModType & SC_MOD_BEFOREINSERT) || (iModType & SC_MOD_BEFOREDELETE)) + //{ + // if ((iModType & SC_STARTACTION) && !SciCall_IsSelectionEmpty()) { + // _BEGIN_UNDO_ACTION_; + // _END_UNDO_ACTION_; + // } + // bModified = false; // not yet + //} + else if (iModType & SC_MOD_CHANGESTYLE) { const DocPos iStartPos = (DocPos)scn->position; const DocPos iEndPos = (DocPos)(scn->position + scn->length); EditUpdateUrlHotspots(g_hwndEdit, iStartPos, iEndPos, g_bHyperlinkHotspot); @@ -5892,9 +5896,9 @@ LRESULT MsgNotify(HWND hwnd,WPARAM wParam,LPARAM lParam) *pPos = '\0'; } if (*pLineBuf) { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SciCall_AddText(lstrlenA(pLineBuf), pLineBuf); - EndUndoAction(token); + _END_UNDO_ACTION_; } if (bAllocLnBuf) { FreeMem(pLineBuf); } } @@ -5946,10 +5950,10 @@ LRESULT MsgNotify(HWND hwnd,WPARAM wParam,LPARAM lParam) StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "", -1) && StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "", -1)) { - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SciCall_ReplaceSel(g_pTempLineBufferMain); SciCall_SetSel(iCurPos, iCurPos); - EndUndoAction(token); + _END_UNDO_ACTION_; } } } @@ -8022,17 +8026,50 @@ void UpdateUI() } + +//============================================================================= + +#define UNDOREDO_FREE (-1L) +#define UNDOREDO_BLOCKED (-2L) +static volatile LONG UndoActionToken = UNDOREDO_BLOCKED; // block + +//============================================================================= +// +// UndoRedoStart() +// +void UndoRedoStart() +{ + InterlockedExchange(&UndoActionToken, UNDOREDO_FREE); // free + _UndoRedoActionMap(-1, NULL); + SciCall_SetUndoCollection(true); +} + + +//============================================================================= +// +// UndoRedoStop() +// +void UndoRedoStop() +{ + int const curToken = InterlockedExchange(&UndoActionToken, UndoActionToken); + if (curToken >= 0) { EndUndoAction(curToken); } + + _UndoRedoActionMap(-1, NULL); + + SciCall_SetUndoCollection(false); + SciCall_EmptyUndoBuffer(); +} + + //============================================================================= // // BeginUndoAction() // // -static volatile LONG UndoActionToken = -1L; - int BeginUndoAction() { - if (InterlockedExchange(&UndoActionToken, UndoActionToken) >= 0L) { return -1; } // already active + if (InterlockedExchange(&UndoActionToken, UndoActionToken) != UNDOREDO_FREE) { return -1; } // already active UndoRedoSelection_t sel = INIT_UNDOREDOSEL; sel.selMode_undo = (int)SendMessage(g_hwndEdit,SCI_GETSELECTIONMODE,0,0); @@ -8057,7 +8094,7 @@ int BeginUndoAction() break; } - int const token = UndoRedoActionMap(-1, &sel); + int const token = _UndoRedoActionMap(-1, &sel); if (token >= 0) { SciCall_BeginUndoAction(); @@ -8080,7 +8117,7 @@ void EndUndoAction(int token) { UndoRedoSelection_t sel = INIT_UNDOREDOSEL; - if (UndoRedoActionMap(token, &sel) >= 0) + if (_UndoRedoActionMap(token, &sel) >= 0) { sel.selMode_redo = (int)SendMessage(g_hwndEdit, SCI_GETSELECTIONMODE, 0, 0); @@ -8104,11 +8141,11 @@ void EndUndoAction(int token) } } - UndoRedoActionMap(token,&sel); // set with redo action filled + _UndoRedoActionMap(token, &sel); // set with redo action filled SciCall_EndUndoAction(); - InterlockedExchange(&UndoActionToken, -1L); + InterlockedExchange(&UndoActionToken, UNDOREDO_FREE); } } @@ -8120,9 +8157,11 @@ void EndUndoAction(int token) // void RestoreAction(int token, DoAction doAct) { + if (InterlockedExchange(&UndoActionToken, UndoActionToken) != UNDOREDO_FREE) { return; } // in action recording + UndoRedoSelection_t sel = INIT_UNDOREDOSEL; - if (UndoRedoActionMap(token, &sel) >= 0) + if (_UndoRedoActionMap(token, &sel) >= 0) { // we are inside undo/redo transaction, so do delayed PostMessage() instead of SendMessage() #define ISSUE_MESSAGE PostMessage @@ -8183,9 +8222,9 @@ void RestoreAction(int token, DoAction doAct) // UndoSelectionMap() // // -int UndoRedoActionMap(int token, UndoRedoSelection_t* selection) +static int __fastcall _UndoRedoActionMap(int token, UndoRedoSelection_t* selection) { - if (UndoRedoSelectionUTArray == NULL) { return -1L; } + if (UndoRedoSelectionUTArray == NULL) { return -1; } static unsigned int uiTokenCnt = 0U; @@ -8196,13 +8235,10 @@ int UndoRedoActionMap(int token, UndoRedoSelection_t* selection) // reset / clear int const curToken = InterlockedExchange(&UndoActionToken, UndoActionToken); if (curToken >= 0) { EndUndoAction(curToken); } - SciCall_SetUndoCollection(false); - SciCall_EmptyUndoBuffer(); utarray_clear(UndoRedoSelectionUTArray); utarray_init(UndoRedoSelectionUTArray, &UndoRedoSelection_icd); uiTokenCnt = 0U; - SciCall_SetUndoCollection(true); - InterlockedExchange(&UndoActionToken, -1L); + InterlockedExchange(&UndoActionToken, UNDOREDO_FREE); return -1; } @@ -8467,12 +8503,12 @@ bool FileLoad(bool bDontSave, bool bNew, bool bReload, bool bSkipUnicodeDetect, SendMessage(g_hwndEdit,SCI_GETTEXT,5,(LPARAM)tchLog); if (StringCchCompareXA(tchLog,".LOG") == 0) { EditJumpTo(g_hwndEdit,-1,0); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; SendMessage(g_hwndEdit,SCI_NEWLINE,0,0); SendMessage(g_hwndMain,WM_COMMAND,MAKELONG(IDM_EDIT_INSERT_SHORTDATE,1),0); EditJumpTo(g_hwndEdit,-1,0); SendMessage(g_hwndEdit,SCI_NEWLINE,0,0); - EndUndoAction(token); + _END_UNDO_ACTION_; SendMessage(g_hwndEdit, SCI_DOCUMENTEND, 0, 0); EditEnsureSelectionVisible(g_hwndEdit); } @@ -9517,13 +9553,13 @@ void CALLBACK PasteBoardTimer(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime) bool bAutoIndent2 = bAutoIndent; bAutoIndent = 0; EditJumpTo(g_hwndEdit,-1,0); - int const token = BeginUndoAction(); + _BEGIN_UNDO_ACTION_; if (SendMessage(g_hwndEdit, SCI_GETLENGTH, 0, 0) > 0) { SendMessage(g_hwndEdit, SCI_NEWLINE, 0, 0); } SendMessage(g_hwndEdit,SCI_PASTE,0,0); SendMessage(g_hwndEdit,SCI_NEWLINE,0,0); - EndUndoAction(token); + _END_UNDO_ACTION_; EditEnsureSelectionVisible(g_hwndEdit); bAutoIndent = bAutoIndent2; } diff --git a/src/Notepad3.h b/src/Notepad3.h index ca22a59b5..ae8396346 100644 --- a/src/Notepad3.h +++ b/src/Notepad3.h @@ -146,13 +146,15 @@ void UpdateSettingsCmds(); void UpdateVisibleUrlHotspot(int); void UpdateUI(); - -void InvalidateSelections(); - -int BeginUndoAction(); +void UndoRedoStart(); +void UndoRedoStop(); +int BeginUndoAction(); void EndUndoAction(int); void RestoreAction(int,DoAction); -int UndoRedoActionMap(int,UndoRedoSelection_t*); + +#define _BEGIN_UNDO_ACTION_ { int const _token_ = BeginUndoAction(); __try { +#define _END_UNDO_ACTION_ } __finally { EndUndoAction(_token_); } } + void OpenHotSpotURL(DocPos, bool); From 5fe964a51f71c1744766316f98aa4d0259582236 Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Sat, 5 May 2018 13:37:44 +0200 Subject: [PATCH 2/3] + fix issue on recording initial selection Undo/Redo --- src/Edit.c | 4 +- src/Notepad3.c | 222 +++++++++++++++++++++++++++++-------------------- src/Notepad3.h | 4 +- src/SciCall.h | 2 + 4 files changed, 137 insertions(+), 95 deletions(-) diff --git a/src/Edit.c b/src/Edit.c index efdce6d8c..480ef169a 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -364,7 +364,7 @@ void EditInitWordDelimiter(HWND hwnd) // void __fastcall _ClearTextBuffer(HWND hwnd) { - UndoRedoStop(); + UndoRedoRecordingStop(); SendMessage(hwnd, SCI_CANCEL, 0, 0); @@ -399,7 +399,7 @@ void __fastcall _InitTextBuffer(HWND hwnd, const char* lpstrText, DocPos textLen SciCall_GotoPos(0); SciCall_ChooseCaretX(); - UndoRedoStart(); + UndoRedoRecordingStart(); if (bSetSavePoint) { SendMessage(hwnd, SCI_SETSAVEPOINT, 0, 0); diff --git a/src/Notepad3.c b/src/Notepad3.c index a752f63ea..eba2758ff 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -361,7 +361,10 @@ static char g_pTempLineBufferMain[TEMPLINE_BUFFER]; // undo / redo selections static UT_icd UndoRedoSelection_icd = { sizeof(UndoRedoSelection_t), NULL, NULL, NULL }; static UT_array* UndoRedoSelectionUTArray = NULL; -static int __fastcall _UndoRedoActionMap(int token, UndoRedoSelection_t* selection); +static bool __fastcall _InUndoRedoTransaction(); +static void __fastcall _SaveRedoSelection(int token); +static int __fastcall _SaveUndoSelection(); +static int __fastcall _UndoRedoActionMap(int token, UndoRedoSelection_t* const selection); static CLIPFORMAT cfDrpF = CF_HDROP; static POINTL ptDummy = { 0, 0 }; @@ -3136,16 +3139,21 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) case IDM_EDIT_UNDO: - _IGNORE_NOTIFY_CHANGE_; - SendMessage(g_hwndEdit, SCI_UNDO, 0, 0); - _OBSERVE_NOTIFY_CHANGE_; + if (SciCall_CanUndo()) { + _IGNORE_NOTIFY_CHANGE_; + SciCall_Undo(); + _OBSERVE_NOTIFY_CHANGE_; + UpdateToolbar(); + } break; - case IDM_EDIT_REDO: - _IGNORE_NOTIFY_CHANGE_; - SendMessage(g_hwndEdit, SCI_REDO, 0, 0); - _OBSERVE_NOTIFY_CHANGE_; + if (SciCall_CanRedo()) { + _IGNORE_NOTIFY_CHANGE_; + SciCall_Redo(); + _OBSERVE_NOTIFY_CHANGE_; + UpdateToolbar(); + } break; @@ -5691,9 +5699,14 @@ LRESULT MsgNotify(HWND hwnd,WPARAM wParam,LPARAM lParam) // --- check only mandatory events (must be fast !!!) --- if (pnmh->idFrom == IDC_EDIT) { if (pnmh->code == SCN_MODIFIED) { - bool bModified = true; - // check for ADDUNDOACTION step int const iModType = scn->modificationType; + if ((iModType & SC_MOD_BEFOREINSERT) || ((iModType & SC_MOD_BEFOREDELETE))) { + if (!((iModType & SC_PERFORMED_UNDO) || (iModType & SC_PERFORMED_REDO))) { + if (!_InUndoRedoTransaction()) + _SaveRedoSelection(_SaveUndoSelection()); + } + } + // check for ADDUNDOACTION step if (iModType & SC_MOD_CONTAINER) { if (iModType & SC_PERFORMED_UNDO) { @@ -5703,14 +5716,7 @@ LRESULT MsgNotify(HWND hwnd,WPARAM wParam,LPARAM lParam) RestoreAction(scn->token, REDO); } } - //else if ((iModType & SC_MOD_BEFOREINSERT) || (iModType & SC_MOD_BEFOREDELETE)) { - // if ((iModType & SC_STARTACTION) && !SciCall_IsSelectionEmpty()) { - // _BEGIN_UNDO_ACTION_; - // _END_UNDO_ACTION_; - // } - // bModified = false; // not yet - //} - if (bModified) { _SetDocumentModified(true); } + _SetDocumentModified(true); } else if (pnmh->code == SCN_SAVEPOINTREACHED) { _SetDocumentModified(false); @@ -5758,58 +5764,66 @@ LRESULT MsgNotify(HWND hwnd,WPARAM wParam,LPARAM lParam) // break; case SCN_UPDATEUI: - - //if (scn->updated & SC_UPDATE_NP3_INTERNAL_NOTIFY) { - // // special case - //} - //else - - if (scn->updated & (SC_UPDATE_SELECTION | SC_UPDATE_CONTENT)) { - //~InvalidateSelections(); // fixed in SCI ? + int const iUpd = scn->updated; + //if (scn->updated & SC_UPDATE_NP3_INTERNAL_NOTIFY) { + // // special case + //} + //else - // Brace Match - if (bMatchBraces) { - EditMatchBrace(g_hwndEdit); - } + if (iUpd & (SC_UPDATE_SELECTION | SC_UPDATE_CONTENT)) + { + //~InvalidateSelections(); // fixed in SCI ? - if (g_iMarkOccurrences > 0) { - // clear marks only, if selection changed - if (scn->updated & SC_UPDATE_SELECTION) { - EditClearAllOccurrenceMarkers(g_hwndEdit, 0, -1); - if (!SciCall_IsSelectionEmpty()) { - MarkAllOccurrences(iUpdateDelayMarkAllCoccurrences); + // Brace Match + if (bMatchBraces) { + EditMatchBrace(g_hwndEdit); + } + + if (g_iMarkOccurrences > 0) { + // clear marks only, if selection changed + if (iUpd & SC_UPDATE_SELECTION) { + + EditClearAllOccurrenceMarkers(g_hwndEdit, 0, -1); + if (!SciCall_IsSelectionEmpty()) { + MarkAllOccurrences(iUpdateDelayMarkAllCoccurrences); + } + } + else if (iUpd & SC_UPDATE_CONTENT) { + // ignoring SC_UPDATE_CONTENT cause Style and Marker are out of scope here + // using WM_COMMAND -> SCEN_CHANGE instead! + //~MarkAllOccurrences(iUpdateDelayMarkAllCoccurrences); } } - else if (scn->updated & SC_UPDATE_CONTENT) { - // ignoring SC_UPDATE_CONTENT cause Style and Marker are out of scope here - // using WM_COMMAND -> SCEN_CHANGE instead! - //~MarkAllOccurrences(iUpdateDelayMarkAllCoccurrences); + + if (g_bHyperlinkHotspot) { + UpdateVisibleUrlHotspot(iUpdateDelayHyperlinkStyling); + } + UpdateToolbar(); + UpdateStatusbar(false); + } + else if (iUpd & SC_UPDATE_V_SCROLL) + { + if ((g_iMarkOccurrences > 0) && g_bMarkOccurrencesMatchVisible) { + MarkAllOccurrences(iUpdateDelayMarkAllCoccurrences); + } + if (g_bHyperlinkHotspot) { + UpdateVisibleUrlHotspot(iUpdateDelayHyperlinkStyling); } } - - if (g_bHyperlinkHotspot) { - UpdateVisibleUrlHotspot(iUpdateDelayHyperlinkStyling); - } - UpdateToolbar(); - UpdateStatusbar(false); - } - else if (scn->updated & SC_UPDATE_V_SCROLL) - { - if ((g_iMarkOccurrences > 0) && g_bMarkOccurrencesMatchVisible) { - MarkAllOccurrences(iUpdateDelayMarkAllCoccurrences); - } - if (g_bHyperlinkHotspot) { - UpdateVisibleUrlHotspot(iUpdateDelayHyperlinkStyling); - } - } + } break; case SCN_MODIFIED: { - bool bModified = true; int const iModType = scn->modificationType; + if ((iModType & SC_MOD_BEFOREINSERT) || ((iModType & SC_MOD_BEFOREDELETE))) { + if (!((iModType & SC_PERFORMED_UNDO) || (iModType & SC_PERFORMED_REDO))) { + if (!_InUndoRedoTransaction()) + _SaveRedoSelection(_SaveUndoSelection()); + } + } if (iModType & SC_MOD_CONTAINER) { if (iModType & SC_PERFORMED_UNDO) { RestoreAction(scn->token, UNDO); @@ -5818,14 +5832,6 @@ LRESULT MsgNotify(HWND hwnd,WPARAM wParam,LPARAM lParam) RestoreAction(scn->token, REDO); } } - //else if ((iModType & SC_MOD_BEFOREINSERT) || (iModType & SC_MOD_BEFOREDELETE)) - //{ - // if ((iModType & SC_STARTACTION) && !SciCall_IsSelectionEmpty()) { - // _BEGIN_UNDO_ACTION_; - // _END_UNDO_ACTION_; - // } - // bModified = false; // not yet - //} else if (iModType & SC_MOD_CHANGESTYLE) { const DocPos iStartPos = (DocPos)scn->position; const DocPos iEndPos = (DocPos)(scn->position + scn->length); @@ -5841,7 +5847,7 @@ LRESULT MsgNotify(HWND hwnd,WPARAM wParam,LPARAM lParam) UpdateLineNumberWidth(); } - if (bModified) { _SetDocumentModified(true); } + _SetDocumentModified(true); UpdateToolbar(); UpdateStatusbar(false); @@ -8033,13 +8039,19 @@ void UpdateUI() #define UNDOREDO_BLOCKED (-2L) static volatile LONG UndoActionToken = UNDOREDO_BLOCKED; // block +//============================================================================= + +static bool __fastcall _InUndoRedoTransaction() { + return (InterlockedExchange(&UndoActionToken, UndoActionToken) != UNDOREDO_FREE); +} + //============================================================================= // -// UndoRedoStart() +// UndoRedoRecordingStart() // -void UndoRedoStart() +void UndoRedoRecordingStart() { - InterlockedExchange(&UndoActionToken, UNDOREDO_FREE); // free + InterlockedExchange(&UndoActionToken, UNDOREDO_FREE); // clear _UndoRedoActionMap(-1, NULL); SciCall_SetUndoCollection(true); } @@ -8047,9 +8059,9 @@ void UndoRedoStart() //============================================================================= // -// UndoRedoStop() +// UndoRedoRecordingStop() // -void UndoRedoStop() +void UndoRedoRecordingStop() { int const curToken = InterlockedExchange(&UndoActionToken, UndoActionToken); if (curToken >= 0) { EndUndoAction(curToken); } @@ -8063,16 +8075,13 @@ void UndoRedoStop() //============================================================================= // -// BeginUndoAction() +// _SaveUndoSelection() // // - -int BeginUndoAction() +static int __fastcall _SaveUndoSelection() { - if (InterlockedExchange(&UndoActionToken, UndoActionToken) != UNDOREDO_FREE) { return -1; } // already active - UndoRedoSelection_t sel = INIT_UNDOREDOSEL; - sel.selMode_undo = (int)SendMessage(g_hwndEdit,SCI_GETSELECTIONMODE,0,0); + sel.selMode_undo = (int)SendMessage(g_hwndEdit, SCI_GETSELECTIONMODE, 0, 0); switch (sel.selMode_undo) { @@ -8095,29 +8104,26 @@ int BeginUndoAction() } int const token = _UndoRedoActionMap(-1, &sel); - + if (token >= 0) { - SciCall_BeginUndoAction(); SciCall_AddUndoAction(token, 0); } - - InterlockedExchange(&UndoActionToken, (LONG)token); + return token; } //============================================================================= // -// EndUndoAction() +// _SaveRedoSelection() // // -void EndUndoAction(int token) +static void __fastcall _SaveRedoSelection(int token) { - if ((token >= 0) && (token == (int)InterlockedExchange(&UndoActionToken, UndoActionToken))) - { + if (token >= 0) { UndoRedoSelection_t sel = INIT_UNDOREDOSEL; - if (_UndoRedoActionMap(token, &sel) >= 0) + if (_UndoRedoActionMap(token, &sel) >= 0) { sel.selMode_redo = (int)SendMessage(g_hwndEdit, SCI_GETSELECTIONMODE, 0, 0); @@ -8139,9 +8145,43 @@ void EndUndoAction(int token) sel.curPos_redo = (DocPos)SendMessage(g_hwndEdit, SCI_GETCURRENTPOS, 0, 0); break; } + + _UndoRedoActionMap(token, &sel); // set with redo action filled } - - _UndoRedoActionMap(token, &sel); // set with redo action filled + } +} + + +//============================================================================= +// +// BeginUndoAction() +// +// +int BeginUndoAction() +{ + if (_InUndoRedoTransaction()) { return -1; } + + SciCall_BeginUndoAction(); + + int const token = _SaveUndoSelection(); + + InterlockedExchange(&UndoActionToken, (LONG)token); + + return token; +} + + + +//============================================================================= +// +// EndUndoAction() +// +// +void EndUndoAction(int token) +{ + if ((token >= 0) && (token == (int)InterlockedExchange(&UndoActionToken, UndoActionToken))) + { + _SaveRedoSelection(token); SciCall_EndUndoAction(); @@ -8157,7 +8197,7 @@ void EndUndoAction(int token) // void RestoreAction(int token, DoAction doAct) { - if (InterlockedExchange(&UndoActionToken, UndoActionToken) != UNDOREDO_FREE) { return; } // in action recording + if (_InUndoRedoTransaction()) { return; } UndoRedoSelection_t sel = INIT_UNDOREDOSEL; @@ -8219,10 +8259,10 @@ void RestoreAction(int token, DoAction doAct) //============================================================================= // -// UndoSelectionMap() +// _UndoSelectionMap() // // -static int __fastcall _UndoRedoActionMap(int token, UndoRedoSelection_t* selection) +static int __fastcall _UndoRedoActionMap(int token, UndoRedoSelection_t* const selection) { if (UndoRedoSelectionUTArray == NULL) { return -1; } diff --git a/src/Notepad3.h b/src/Notepad3.h index ae8396346..8d61d1fce 100644 --- a/src/Notepad3.h +++ b/src/Notepad3.h @@ -146,8 +146,8 @@ void UpdateSettingsCmds(); void UpdateVisibleUrlHotspot(int); void UpdateUI(); -void UndoRedoStart(); -void UndoRedoStop(); +void UndoRedoRecordingStart(); +void UndoRedoRecordingStop(); int BeginUndoAction(); void EndUndoAction(int); void RestoreAction(int,DoAction); diff --git a/src/SciCall.h b/src/SciCall.h index 64b87ce6e..1c1b02ea1 100644 --- a/src/SciCall.h +++ b/src/SciCall.h @@ -136,6 +136,8 @@ __forceinline LRESULT SciCall_##fn(type1 var1, type2 var2) { \ DeclareSciCallR0(GetReadOnly, GETREADONLY, bool) DeclareSciCallV1(SetReadOnly, SETREADONLY, bool, flag) +DeclareSciCallV0(Undo, UNDO) +DeclareSciCallV0(Redo, REDO) DeclareSciCallR0(CanUndo, CANUNDO, bool) DeclareSciCallR0(CanRedo, CANREDO, bool) DeclareSciCallR0(IsDocModified, GETMODIFY, bool) From 20aec881b7c5e3273ab0721ee940f8a5417a2f09 Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Sat, 5 May 2018 13:47:18 +0200 Subject: [PATCH 3/3] + fix: recording selection Redo/Undo action only for non empty selection --- src/Notepad3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Notepad3.c b/src/Notepad3.c index eba2758ff..6ca7c2fc2 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -5702,7 +5702,7 @@ LRESULT MsgNotify(HWND hwnd,WPARAM wParam,LPARAM lParam) int const iModType = scn->modificationType; if ((iModType & SC_MOD_BEFOREINSERT) || ((iModType & SC_MOD_BEFOREDELETE))) { if (!((iModType & SC_PERFORMED_UNDO) || (iModType & SC_PERFORMED_REDO))) { - if (!_InUndoRedoTransaction()) + if (!SciCall_IsSelectionEmpty() && !_InUndoRedoTransaction()) _SaveRedoSelection(_SaveUndoSelection()); } } @@ -5820,7 +5820,7 @@ LRESULT MsgNotify(HWND hwnd,WPARAM wParam,LPARAM lParam) int const iModType = scn->modificationType; if ((iModType & SC_MOD_BEFOREINSERT) || ((iModType & SC_MOD_BEFOREDELETE))) { if (!((iModType & SC_PERFORMED_UNDO) || (iModType & SC_PERFORMED_REDO))) { - if (!_InUndoRedoTransaction()) + if (!SciCall_IsSelectionEmpty() && !_InUndoRedoTransaction()) _SaveRedoSelection(_SaveUndoSelection()); } }