diff --git a/Build/Notepad3.ini b/Build/Notepad3.ini index f8190d6a9..4299efef4 100644 Binary files a/Build/Notepad3.ini and b/Build/Notepad3.ini differ diff --git a/src/Edit.c b/src/Edit.c index 101174964..2b939318b 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -339,6 +339,55 @@ void EditInitWordDelimiter(HWND hwnd) } +//============================================================================= +// +// _ClearTextBuffer() +// +void __fastcall _ClearTextBuffer(HWND hwnd) +{ + SendMessage(hwnd, SCI_CANCEL, 0, 0); + + if (SendMessage(hwnd, SCI_GETREADONLY, 0, 0)) { SendMessage(hwnd, SCI_SETREADONLY, false, 0); } + + UndoRedoActionMap(-1, NULL); + + SciCall_SetUndoCollection(false); + + SendMessage(hwnd, SCI_CLEARALL, 0, 0); + SendMessage(hwnd, SCI_MARKERDELETEALL, (WPARAM)MARKER_NP3_BOOKMARK, 0); + + EditClearAllOccurrenceMarkers(hwnd, 0, -1); + if (EditToggleView(g_hwndEdit, false)) { + EditToggleView(g_hwndEdit, true); + } + + SciCall_SetUndoCollection(true); + + SendMessage(hwnd, SCI_SETSCROLLWIDTH, 1, 0); + SendMessage(hwnd, SCI_SETXOFFSET, 0, 0); +} + + +//============================================================================= +// +// _InitTextBuffer() +// +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(0); + + SciCall_SetUndoCollection(true); + + if (bSetSavePoint) { SendMessage(hwnd, SCI_SETSAVEPOINT, 0, 0); } +} + + //============================================================================= // @@ -347,38 +396,15 @@ void EditInitWordDelimiter(HWND hwnd) extern bool bFreezeAppTitle; extern FILEVARS fvCurFile; - void EditSetNewText(HWND hwnd,char* lpstrText,DWORD cbText) { bFreezeAppTitle = true; - if (SendMessage(hwnd, SCI_GETREADONLY, 0, 0)) { - SendMessage(hwnd, SCI_SETREADONLY, false, 0); - } - - SendMessage(hwnd,SCI_CANCEL,0,0); - SendMessage(hwnd,SCI_SETUNDOCOLLECTION,0,0); - UndoRedoActionMap(-1,NULL); - SendMessage(hwnd,SCI_CLEARALL,0,0); - SendMessage(hwnd,SCI_MARKERDELETEALL,(WPARAM)MARKER_NP3_BOOKMARK,0); - SendMessage(hwnd,SCI_MARKERDELETEALL,(WPARAM)MARKER_NP3_OCCUR_LINE,0); - SendMessage(hwnd,SCI_SETSCROLLWIDTH,GetSystemMetrics(SM_CXSCREEN),0); - SendMessage(hwnd,SCI_SETXOFFSET,0,0); - if (EditToggleView(g_hwndEdit, false)) { - EditToggleView(g_hwndEdit, true); - } + _ClearTextBuffer(hwnd); FileVars_Apply(hwnd,&fvCurFile); - if (cbText > 0) { - SendMessage(hwnd, SCI_ADDTEXT, cbText, (LPARAM)lpstrText); - } - SendMessage(hwnd,SCI_SETUNDOCOLLECTION,1,0); - //SendMessage(hwnd,EM_EMPTYUNDOBUFFER,0,0); // deprecated - SendMessage(hwnd,SCI_SETSAVEPOINT,0,0); - SendMessage(hwnd, SCI_SETSCROLLWIDTH, 1, 0); - SendMessage(hwnd,SCI_GOTOPOS,0,0); - SendMessage(hwnd,SCI_CHOOSECARETX,0,0); + _InitTextBuffer(hwnd, lpstrText, cbText, true); bFreezeAppTitle = false; } @@ -396,22 +422,12 @@ bool EditConvertText(HWND hwnd, int encSource, int encDest, bool bSetSavePoint) if (!(Encoding_IsValid(encSource) && Encoding_IsValid(encDest))) return(false); - DocPos length = SciCall_GetTextLength(); + DocPos const length = SciCall_GetTextLength(); if (length == 0) { - SendMessage(hwnd,SCI_CANCEL,0,0); - SendMessage(hwnd,SCI_SETUNDOCOLLECTION,0,0); - UndoRedoActionMap(-1,NULL); - SendMessage(hwnd,SCI_CLEARALL,0,0); - SendMessage(hwnd,SCI_MARKERDELETEALL,(WPARAM)MARKER_NP3_BOOKMARK,0); - SendMessage(hwnd, SCI_MARKERDELETEALL, (WPARAM)MARKER_NP3_OCCUR_LINE, 0); - SendMessage(hwnd,SCI_SETUNDOCOLLECTION,(WPARAM)1,0); - SendMessage(hwnd,SCI_GOTOPOS,0,0); - SendMessage(hwnd,SCI_CHOOSECARETX,0,0); - - if (bSetSavePoint) - SendMessage(hwnd,SCI_SETSAVEPOINT,0,0); + _ClearTextBuffer(hwnd); + _InitTextBuffer(hwnd, NULL, length, bSetSavePoint); } else { @@ -439,20 +455,12 @@ bool EditConvertText(HWND hwnd, int encSource, int encDest, bool bSetSavePoint) pchText[cbText] = '\0'; pchText[cbText+1] = '\0'; - SendMessage(hwnd,SCI_CANCEL,0,0); - SendMessage(hwnd,SCI_SETUNDOCOLLECTION,0,0); - UndoRedoActionMap(-1,NULL); - SendMessage(hwnd,SCI_CLEARALL,0,0); - SendMessage(hwnd,SCI_MARKERDELETEALL,(WPARAM)MARKER_NP3_BOOKMARK,0); - SendMessage(hwnd, SCI_MARKERDELETEALL, (WPARAM)MARKER_NP3_OCCUR_LINE, 0); - SendMessage(hwnd,SCI_ADDTEXT,cbText,(LPARAM)pchText); - SendMessage(hwnd,SCI_SETUNDOCOLLECTION,(WPARAM)1,0); - SendMessage(hwnd,SCI_GOTOPOS,0,0); - SendMessage(hwnd,SCI_CHOOSECARETX,0,0); - - FreeMem(pchText); FreeMem(pwchText); + _ClearTextBuffer(hwnd); + _InitTextBuffer(hwnd, pchText, cbText, bSetSavePoint); + + FreeMem(pchText); } return(true); } @@ -485,6 +493,7 @@ bool EditSetNewEncoding(HWND hwnd,int iNewEncoding,bool bNoUI,bool bSetSavePoint if (doNewEncoding) { return EditConvertText(hwnd,iCurrentEncoding,iNewEncoding,bSetSavePoint); + } } else { @@ -499,6 +508,7 @@ bool EditSetNewEncoding(HWND hwnd,int iNewEncoding,bool bNoUI,bool bSetSavePoint return false; } + //============================================================================= // // EditIsRecodingNeeded() @@ -2747,9 +2757,7 @@ void EditIndentBlock(HWND hwnd, int cmd, bool bFormatIndentation) // void EditAlignText(HWND hwnd,int nMode) { - #define BUFSIZE_ALIGN 1024 - - bool bModified = false; + #define BUFSIZE_ALIGN 2048 const DocPos iSelStart = SciCall_GetSelectionStart(); const DocPos iSelEnd = SciCall_GetSelectionEnd(); @@ -2807,15 +2815,9 @@ void EditAlignText(HWND hwnd,int nMode) DocPos iIndentPos = SciCall_GetLineIndentPosition(iLine); if ((iIndentPos == iEndPos) && (iEndPos > 0)) { - - if (!bModified) { - SendMessage(hwnd, SCI_BEGINUNDOACTION, 0, 0); - bModified = true; - } SendMessage(hwnd, SCI_SETTARGETRANGE, SciCall_PositionFromLine(iLine), iEndPos); SendMessage(hwnd, SCI_REPLACETARGET, 0, (LPARAM)""); } - else { char tchLineBuf[BUFSIZE_ALIGN*3] = { '\0' }; @@ -2827,11 +2829,6 @@ void EditAlignText(HWND hwnd,int nMode) int iWordsLength = 0; DocPos cchLine = SciCall_GetLine(iLine, tchLineBuf); - if (!bModified) { - SendMessage(hwnd, SCI_BEGINUNDOACTION, 0, 0); - bModified = true; - } - MultiByteToWideChar(Encoding_SciCP,0,tchLineBuf,(int)cchLine,wchLineBuf,COUNTOF(wchLineBuf)); StrTrim(wchLineBuf,L"\r\n\t "); @@ -2979,10 +2976,6 @@ void EditAlignText(HWND hwnd,int nMode) else MsgBox(MBINFO, IDS_BUFFERTOOSMALL); - if (bModified) { - SendMessage(hwnd, SCI_ENDUNDOACTION, 0, 0); - } - if (iCurPos < iAnchorPos) { iCurPos = SciCall_PositionFromLine(iLineStart); iAnchorPos = SciCall_PositionFromLine(iLineEnd + 1); diff --git a/src/Notepad3.c b/src/Notepad3.c index d8ecebbf1..0adb27a27 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -960,13 +960,13 @@ HWND InitInstance(HINSTANCE hInstance,LPSTR pszCmdLine,int nCmdShow) bool bAutoIndent2 = bAutoIndent; bAutoIndent = 0; EditJumpTo(g_hwndEdit, -1, 0); - SendMessage(g_hwndEdit, SCI_BEGINUNDOACTION, 0, 0); + int token = BeginUndoAction(); 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); - SendMessage(g_hwndEdit, SCI_ENDUNDOACTION, 0, 0); + EndUndoAction(token); bAutoIndent = bAutoIndent2; if (flagJumpTo) EditJumpTo(g_hwndEdit, iInitialLine, iInitialColumn); @@ -5676,16 +5676,16 @@ LRESULT MsgNotify(HWND hwnd,WPARAM wParam,LPARAM lParam) } if (pLineBuf) { - SendMessage(g_hwndEdit, SCI_GETLINE, iCurLine - 1, (LPARAM)pLineBuf); + SciCall_GetLine(iCurLine - 1, pLineBuf); *(pLineBuf + iPrevLineLength) = '\0'; for (char* pPos = pLineBuf; *pPos; pPos++) { if (*pPos != ' ' && *pPos != '\t') *pPos = '\0'; } if (*pLineBuf) { - SendMessage(g_hwndEdit, SCI_BEGINUNDOACTION, 0, 0); - SendMessage(g_hwndEdit, SCI_ADDTEXT, lstrlenA(pLineBuf), (LPARAM)pLineBuf); - SendMessage(g_hwndEdit, SCI_ENDUNDOACTION, 0, 0); + int token = BeginUndoAction(); + SciCall_AddText(lstrlenA(pLineBuf), pLineBuf); + EndUndoAction(token); } if (bAllocLnBuf) { FreeMem(pLineBuf); } } @@ -7480,9 +7480,13 @@ void UpdateUI() // BeginUndoAction() // // + +static volatile LONG UndoActionToken = -1L; + int BeginUndoAction() { - int token = -1; + if (InterlockedExchange(&UndoActionToken, UndoActionToken) >= 0L) { return -1; } // already active + UndoRedoSelection_t sel = INIT_UNDOREDOSEL; sel.selMode_undo = (int)SendMessage(g_hwndEdit,SCI_GETSELECTIONMODE,0,0); @@ -7505,16 +7509,19 @@ int BeginUndoAction() sel.curPos_undo = (DocPos)SendMessage(g_hwndEdit, SCI_GETCURRENTPOS, 0, 0); break; } - token = UndoRedoActionMap(-1, &sel); + + int token = UndoRedoActionMap(-1, &sel); + if (token >= 0) { - SendMessage(g_hwndEdit, SCI_BEGINUNDOACTION, 0, 0); - SendMessage(g_hwndEdit, SCI_ADDUNDOACTION, (WPARAM)token, 0); + SciCall_BeginUndoAction(); + SciCall_AddUndoAction(token, 0); } + + InterlockedExchange(&UndoActionToken, (LONG)token); return token; } - //============================================================================= // // EndUndoAction() @@ -7522,10 +7529,12 @@ int BeginUndoAction() // void EndUndoAction(int token) { - if (token >= 0) { + if ((token >= 0) && (token == (int)InterlockedExchange(&UndoActionToken, UndoActionToken))) + { 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); switch (sel.selMode_redo) @@ -7547,8 +7556,12 @@ void EndUndoAction(int token) break; } } + UndoRedoActionMap(token,&sel); // set with redo action filled - SendMessage(g_hwndEdit, SCI_ENDUNDOACTION, 0, 0); + + SciCall_EndUndoAction(); + + InterlockedExchange(&UndoActionToken, -1L); } } @@ -7567,18 +7580,18 @@ void RestoreAction(int token, DoAction doAct) // we are inside undo/redo transaction, so do delayed PostMessage() instead of SendMessage() #define ISSUE_MESSAGE PostMessage - const DocPos _anchorPos = (doAct == UNDO ? sel.anchorPos_undo : sel.anchorPos_redo); - const DocPos _curPos = (doAct == UNDO ? sel.curPos_undo : sel.curPos_redo); + DocPos const _anchorPos = (doAct == UNDO ? sel.anchorPos_undo : sel.anchorPos_redo); + DocPos const _curPos = (doAct == UNDO ? sel.curPos_undo : sel.curPos_redo); // Ensure that the first and last lines of a selection are always unfolded // This needs to be done _before_ the SCI_SETSEL message - const DocLn anchorPosLine = SciCall_LineFromPosition(_anchorPos); - const DocLn currPosLine = SciCall_LineFromPosition(_curPos); + DocLn const anchorPosLine = SciCall_LineFromPosition(_anchorPos); + DocLn const currPosLine = SciCall_LineFromPosition(_curPos); ISSUE_MESSAGE(g_hwndEdit, SCI_ENSUREVISIBLE, anchorPosLine, 0); if (anchorPosLine != currPosLine) { ISSUE_MESSAGE(g_hwndEdit, SCI_ENSUREVISIBLE, currPosLine, 0); } - const int selectionMode = (doAct == UNDO ? sel.selMode_undo : sel.selMode_redo); + int const selectionMode = (doAct == UNDO ? sel.selMode_undo : sel.selMode_redo); ISSUE_MESSAGE(g_hwndEdit, SCI_SETSELECTIONMODE, (WPARAM)selectionMode, 0); // independent from selection mode @@ -7594,8 +7607,8 @@ void RestoreAction(int token, DoAction doAct) case SC_SEL_THIN: { - const DocPos anchorVS = (doAct == UNDO ? sel.anchorVS_undo : sel.anchorVS_redo); - const DocPos currVS = (doAct == UNDO ? sel.curVS_undo : sel.curVS_redo); + DocPos const anchorVS = (doAct == UNDO ? sel.anchorVS_undo : sel.anchorVS_redo); + DocPos const currVS = (doAct == UNDO ? sel.curVS_undo : sel.curVS_redo); if ((anchorVS != 0) || (currVS != 0)) { ISSUE_MESSAGE(g_hwndEdit, SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE, (WPARAM)anchorVS, 0); ISSUE_MESSAGE(g_hwndEdit, SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE, (WPARAM)currVS, 0); @@ -7625,26 +7638,31 @@ void RestoreAction(int token, DoAction doAct) // int UndoRedoActionMap(int token, UndoRedoSelection_t* selection) { - if (UndoRedoSelectionUTArray == NULL) { return -1; } + if (UndoRedoSelectionUTArray == NULL) { return -1L; } - static unsigned int iTokenCnt = 0; + static unsigned int uiTokenCnt = 0U; // indexing is unsigned unsigned int utoken = (token >= 0) ? (unsigned int)token : 0U; if (selection == NULL) { // reset / clear - SendMessage(g_hwndEdit, SCI_EMPTYUNDOBUFFER, 0, 0); + int const curToken = InterlockedExchange(&UndoActionToken, UndoActionToken); + if (curToken >= 0) { EndUndoAction(curToken); } + SciCall_SetUndoCollection(false); + SciCall_EmptyUndoBuffer(); utarray_clear(UndoRedoSelectionUTArray); utarray_init(UndoRedoSelectionUTArray, &UndoRedoSelection_icd); - iTokenCnt = 0U; + uiTokenCnt = 0U; + SciCall_SetUndoCollection(true); + InterlockedExchange(&UndoActionToken, -1L); return -1; } if (!SciCall_GetUndoCollection()) { return -1; } // get or set map item request ? - if ((token >= 0) && (utoken < iTokenCnt)) + if ((token >= 0) && (utoken < uiTokenCnt)) { if (selection->anchorPos_undo < 0) { // this is a get request @@ -7658,9 +7676,9 @@ int UndoRedoActionMap(int token, UndoRedoSelection_t* selection) } else if (token < 0) { // set map new item request - utarray_insert(UndoRedoSelectionUTArray, (void*)selection, iTokenCnt); - token = (int)iTokenCnt; - iTokenCnt = (iTokenCnt < INT_MAX) ? (iTokenCnt + 1) : 0U; // round robin next + token = (int)uiTokenCnt; + utarray_insert(UndoRedoSelectionUTArray, (void*)selection, uiTokenCnt); + uiTokenCnt = (uiTokenCnt < (unsigned int)INT_MAX) ? (uiTokenCnt + 1U) : 0U; // round robin next } return token; } @@ -7894,12 +7912,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); - SendMessage(g_hwndEdit,SCI_BEGINUNDOACTION,0,0); + int token = BeginUndoAction(); 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); - SendMessage(g_hwndEdit,SCI_ENDUNDOACTION,0,0); + EndUndoAction(token); SendMessage(g_hwndEdit, SCI_DOCUMENTEND, 0, 0); EditEnsureSelectionVisible(g_hwndEdit); } @@ -8937,13 +8955,13 @@ void CALLBACK PasteBoardTimer(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime) bool bAutoIndent2 = bAutoIndent; bAutoIndent = 0; EditJumpTo(g_hwndEdit,-1,0); - SendMessage(g_hwndEdit,SCI_BEGINUNDOACTION,0,0); + int token = BeginUndoAction(); 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); - SendMessage(g_hwndEdit,SCI_ENDUNDOACTION,0,0); + EndUndoAction(token); EditEnsureSelectionVisible(g_hwndEdit); bAutoIndent = bAutoIndent2; } diff --git a/src/Notepad3.h b/src/Notepad3.h index 667203132..87d220028 100644 --- a/src/Notepad3.h +++ b/src/Notepad3.h @@ -156,10 +156,12 @@ void UpdateUI(); void InvalidateSelections(); -int BeginUndoAction(); + +int BeginUndoAction(); void EndUndoAction(int); void RestoreAction(int,DoAction); -int UndoRedoActionMap(int,UndoRedoSelection_t*); +int UndoRedoActionMap(int,UndoRedoSelection_t*); + void OpenHotSpotURL(DocPos, bool); bool IsFindPatternEmpty(); diff --git a/src/SciCall.h b/src/SciCall.h index 8cdd679e6..399b52840 100644 --- a/src/SciCall.h +++ b/src/SciCall.h @@ -192,7 +192,6 @@ DeclareSciCallV2(SetSel, SETSEL, DocPos, anchorPos, DocPos, currentPos) DeclareSciCallV0(SelectAll, SELECTALL) DeclareSciCallR01(GetSelText, GETSELTEXT, DocPos, const char*, text) DeclareSciCallV01(ReplaceSel, REPLACESEL, const char*, text) -DeclareSciCallR2(GetLine, GETLINE, DocPos, DocLn, line, const char*, text) DeclareSciCallV2(InsertText, INSERTTEXT, DocPos, position, const char*, text) @@ -226,7 +225,8 @@ DeclareSciCallR2(FindColumn, FINDCOLUMN, DocPos, DocLn, line, DocPos, column) DeclareSciCallR1(GetLineIndentPosition, GETLINEINDENTPOSITION, DocPos, DocLn, line) DeclareSciCallR2(GetRangePointer, GETRANGEPOINTER, char* const, DocPos, start, DocPos, length) -DeclareSciCallR0(GetCharacterPointer, GETCHARACTERPOINTER, const char*) +DeclareSciCallR0(GetCharacterPointer, GETCHARACTERPOINTER, char* const) +DeclareSciCallR2(GetLine, GETLINE, DocPos, DocLn, line, const char*, text) DeclareSciCallV1(SetVirtualSpaceOptions, SETVIRTUALSPACEOPTIONS, int, options) @@ -340,7 +340,12 @@ DeclareSciCallV1(SetCursor, SETCURSOR, int, flags) // // Undo/Redo Stack // +DeclareSciCallV0(EmptyUndoBuffer, EMPTYUNDOBUFFER) +DeclareSciCallV0(BeginUndoAction, BEGINUNDOACTION) +DeclareSciCallV2(AddUndoAction, ADDUNDOACTION, int, token, int, flags) +DeclareSciCallV0(EndUndoAction, ENDUNDOACTION) DeclareSciCallR0(GetUndoCollection, GETUNDOCOLLECTION, bool) +DeclareSciCallV1(SetUndoCollection, SETUNDOCOLLECTION, bool, bCollectUndo) //=============================================================================