From 23ef2df24b12496ec4ffd0c2f08ed610a48cf40f Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Fri, 24 May 2019 22:53:30 +0200 Subject: [PATCH] + 1st draft version of editable "Multi-Selection" --- src/Edit.c | 841 ++++++++++++++++++++------------------- src/Notepad3.c | 1034 +++++++++++++++++++++++++++++++----------------- src/Notepad3.h | 23 +- src/SciCall.h | 2 + 4 files changed, 1105 insertions(+), 795 deletions(-) diff --git a/src/Edit.c b/src/Edit.c index 137f7ceb2..01c6e8f7f 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -650,7 +650,7 @@ bool EditSwapClipboard(HWND hwnd, bool bSkipUnicodeCheck) DocPos const iCurPos = SciCall_GetCurrentPos(); DocPos const iAnchorPos = SciCall_GetAnchor(); - bool const bIsRectSel = SciCall_IsSelectionRectangle(); + bool const bIsMultiSel = Sci_IsMultiOrRectangleSelection(); char* pszText = NULL; size_t const size = SciCall_GetSelText(NULL); @@ -666,7 +666,7 @@ bool EditSwapClipboard(HWND hwnd, bool bSkipUnicodeCheck) } if (pszText) { FreeMem(pszText); } - if (!bIsRectSel) { + if (!bIsMultiSel) { // TODO(rkotten): check for Rectangular Clipboard and skip selection restore if (iCurPos < iAnchorPos) EditSetSelectionEx(hwnd, iCurPos + clipLen, iCurPos, -1, -1); @@ -697,7 +697,7 @@ bool EditCopyAppend(HWND hwnd, bool bAppend) DocPos length = 0; if (iSelStart != iSelEnd) { - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return res; } @@ -1456,54 +1456,54 @@ bool EditSaveFile( void EditInvertCase(HWND hwnd) { UNUSED(hwnd); - const DocPos iCurPos = SciCall_GetCurrentPos(); + const DocPos iCurPos = SciCall_GetCurrentPos(); const DocPos iAnchorPos = SciCall_GetAnchor(); if (iCurPos != iAnchorPos) { - if (!SciCall_IsSelectionRectangle()) + if (!Sci_IsMultiOrRectangleSelection()) { - const DocPos iSelStart = SciCall_GetSelectionStart(); - const DocPos iSelEnd = SciCall_GetSelectionEnd(); - const DocPos iSelSize = SciCall_GetSelText(NULL); - - LPSTR pszText = AllocMem(iSelSize, HEAP_ZERO_MEMORY); - LPWSTR pszTextW = AllocMem(iSelSize * sizeof(WCHAR), HEAP_ZERO_MEMORY); - if (!pszText || !pszTextW) { - FreeMem(pszText); - FreeMem(pszTextW); - return; - } + InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); + return; + } + const DocPos iSelStart = SciCall_GetSelectionStart(); + const DocPos iSelEnd = SciCall_GetSelectionEnd(); + const DocPos iSelSize = SciCall_GetSelText(NULL); - SciCall_GetSelText(pszText); - - int const cchTextW = MultiByteToWideChar(Encoding_SciCP,0,pszText,(MBWC_DocPos_Cast)(iSelSize-1), - pszTextW,(MBWC_DocPos_Cast)iSelSize); - - bool bChanged = false; - for (int i = 0; i < cchTextW; i++) { - if (IsCharUpperW(pszTextW[i])) { - pszTextW[i] = LOWORD(CharLowerW((LPWSTR)(LONG_PTR)MAKELONG(pszTextW[i],0))); - bChanged = true; - } - else if (IsCharLowerW(pszTextW[i])) { - pszTextW[i] = LOWORD(CharUpperW((LPWSTR)(LONG_PTR)MAKELONG(pszTextW[i],0))); - bChanged = true; - } - } - - if (bChanged) { - WideCharToMultiByte(Encoding_SciCP,0,pszTextW,cchTextW, - pszText,(MBWC_DocPos_Cast)SizeOfMem(pszText),NULL,NULL); - SciCall_Clear(); - SciCall_AddText((iSelEnd - iSelStart), pszText); - SciCall_SetSel(iAnchorPos, iCurPos); - } + LPSTR pszText = AllocMem(iSelSize, HEAP_ZERO_MEMORY); + LPWSTR pszTextW = AllocMem(iSelSize * sizeof(WCHAR), HEAP_ZERO_MEMORY); + if (!pszText || !pszTextW) { FreeMem(pszText); FreeMem(pszTextW); + return; } - else - InfoBoxLng(MB_ICONWARNING, NULL,IDS_MUI_SELRECT); + + SciCall_GetSelText(pszText); + + int const cchTextW = MultiByteToWideChar(Encoding_SciCP, 0, pszText, (MBWC_DocPos_Cast)(iSelSize - 1), + pszTextW, (MBWC_DocPos_Cast)iSelSize); + + bool bChanged = false; + for (int i = 0; i < cchTextW; i++) { + if (IsCharUpperW(pszTextW[i])) { + pszTextW[i] = LOWORD(CharLowerW((LPWSTR)(LONG_PTR)MAKELONG(pszTextW[i], 0))); + bChanged = true; + } + else if (IsCharLowerW(pszTextW[i])) { + pszTextW[i] = LOWORD(CharUpperW((LPWSTR)(LONG_PTR)MAKELONG(pszTextW[i], 0))); + bChanged = true; + } + } + + if (bChanged) { + WideCharToMultiByte(Encoding_SciCP, 0, pszTextW, cchTextW, + pszText, (MBWC_DocPos_Cast)SizeOfMem(pszText), NULL, NULL); + SciCall_Clear(); + SciCall_AddText((iSelEnd - iSelStart), pszText); + SciCall_SetSel(iAnchorPos, iCurPos); + } + FreeMem(pszText); + FreeMem(pszTextW); } } @@ -1520,56 +1520,55 @@ void EditTitleCase(HWND hwnd) if (iCurPos != iAnchorPos) { - if (!SciCall_IsSelectionRectangle()) + if (!Sci_IsMultiOrRectangleSelection()) { - const DocPos iSelStart = SciCall_GetSelectionStart(); - const DocPos iSelEnd = SciCall_GetSelectionEnd(); - const DocPos iSelSize = SciCall_GetSelText(NULL); + InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); + return; + } + const DocPos iSelStart = SciCall_GetSelectionStart(); + const DocPos iSelEnd = SciCall_GetSelectionEnd(); + const DocPos iSelSize = SciCall_GetSelText(NULL); - char* pszText = AllocMem(iSelSize, HEAP_ZERO_MEMORY); - LPWSTR pszTextW = AllocMem((iSelSize*sizeof(WCHAR)), HEAP_ZERO_MEMORY); - - if (pszText == NULL || pszTextW == NULL) { - FreeMem(pszText); - FreeMem(pszTextW); - return; - } - SciCall_GetSelText(pszText); - - int const cchTextW = MultiByteToWideChar(Encoding_SciCP,0,pszText,(MBWC_DocPos_Cast)(iSelSize-1), - pszTextW,(MBWC_DocPos_Cast)iSelSize); - - bool bChanged = false; - LPWSTR pszMappedW = AllocMem(SizeOfMem(pszTextW),HEAP_ZERO_MEMORY); - if (pszMappedW) { - // first make lower case, before applying TitleCase - if (LCMapString(LOCALE_SYSTEM_DEFAULT, (LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE), pszTextW, cchTextW, pszMappedW, (MBWC_DocPos_Cast)iSelSize)) { - if (LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_TITLECASE, pszMappedW, cchTextW, pszTextW, (MBWC_DocPos_Cast)iSelSize)) { - bChanged = true; - } - } - FreeMem(pszMappedW); - } - - if (bChanged) { - - WideCharToMultiByte(Encoding_SciCP,0,pszTextW,cchTextW, - pszText,(MBWC_DocPos_Cast)SizeOfMem(pszText),NULL,NULL); - - SciCall_Clear(); - SciCall_AddText((iSelEnd - iSelStart), pszText); - SciCall_SetSel(iAnchorPos, iCurPos); - } + char* pszText = AllocMem(iSelSize, HEAP_ZERO_MEMORY); + LPWSTR pszTextW = AllocMem((iSelSize * sizeof(WCHAR)), HEAP_ZERO_MEMORY); + if (pszText == NULL || pszTextW == NULL) { FreeMem(pszText); FreeMem(pszTextW); + return; } - else - InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); + SciCall_GetSelText(pszText); + + int const cchTextW = MultiByteToWideChar(Encoding_SciCP, 0, pszText, (MBWC_DocPos_Cast)(iSelSize - 1), + pszTextW, (MBWC_DocPos_Cast)iSelSize); + + bool bChanged = false; + LPWSTR pszMappedW = AllocMem(SizeOfMem(pszTextW), HEAP_ZERO_MEMORY); + if (pszMappedW) { + // first make lower case, before applying TitleCase + if (LCMapString(LOCALE_SYSTEM_DEFAULT, (LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE), pszTextW, cchTextW, pszMappedW, (MBWC_DocPos_Cast)iSelSize)) { + if (LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_TITLECASE, pszMappedW, cchTextW, pszTextW, (MBWC_DocPos_Cast)iSelSize)) { + bChanged = true; + } + } + FreeMem(pszMappedW); + } + + if (bChanged) { + + WideCharToMultiByte(Encoding_SciCP, 0, pszTextW, cchTextW, + pszText, (MBWC_DocPos_Cast)SizeOfMem(pszText), NULL, NULL); + + SciCall_Clear(); + SciCall_AddText((iSelEnd - iSelStart), pszText); + SciCall_SetSel(iAnchorPos, iCurPos); + } + + FreeMem(pszText); + FreeMem(pszTextW); } } - //============================================================================= // // EditSentenceCase() @@ -1582,69 +1581,69 @@ void EditSentenceCase(HWND hwnd) if (iCurPos != iAnchorPos) { - if (!SciCall_IsSelectionRectangle()) + if (!Sci_IsMultiOrRectangleSelection()) { - const DocPos iSelStart = SciCall_GetSelectionStart(); - const DocPos iSelEnd = SciCall_GetSelectionEnd(); - const DocPos iSelSize = SciCall_GetSelText(NULL); + InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); + return; + } + const DocPos iSelStart = SciCall_GetSelectionStart(); + const DocPos iSelEnd = SciCall_GetSelectionEnd(); + const DocPos iSelSize = SciCall_GetSelText(NULL); - char* pszText = AllocMem(iSelSize, HEAP_ZERO_MEMORY); - LPWSTR pszTextW = AllocMem((iSelSize*sizeof(WCHAR)), HEAP_ZERO_MEMORY); + char* pszText = AllocMem(iSelSize, HEAP_ZERO_MEMORY); + LPWSTR pszTextW = AllocMem((iSelSize * sizeof(WCHAR)), HEAP_ZERO_MEMORY); - if (pszText == NULL || pszTextW == NULL) { - FreeMem(pszText); - FreeMem(pszTextW); - return; + if (pszText == NULL || pszTextW == NULL) { + FreeMem(pszText); + FreeMem(pszTextW); + return; + } + SciCall_GetSelText(pszText); + + int cchTextW = MultiByteToWideChar(Encoding_SciCP, 0, pszText, (MBWC_DocPos_Cast)(iSelSize - 1), pszTextW, (MBWC_DocPos_Cast)iSelSize); + + bool bChanged = false; + bool bNewSentence = true; + for (int i = 0; i < cchTextW; i++) { + if (StrChr(L".;!?\r\n", pszTextW[i])) { + bNewSentence = true; } - SciCall_GetSelText(pszText); - - int cchTextW = MultiByteToWideChar(Encoding_SciCP,0,pszText,(MBWC_DocPos_Cast)(iSelSize-1),pszTextW,(MBWC_DocPos_Cast)iSelSize); - - bool bChanged = false; - bool bNewSentence = true; - for (int i = 0; i < cchTextW; i++) { - if (StrChr(L".;!?\r\n",pszTextW[i])) { - bNewSentence = true; - } - else { - if (IsCharAlphaNumericW(pszTextW[i])) { - if (bNewSentence) { - if (IsCharLowerW(pszTextW[i])) { - pszTextW[i] = LOWORD(CharUpperW((LPWSTR)(LONG_PTR)MAKELONG(pszTextW[i],0))); - bChanged = true; - } - bNewSentence = false; + else { + if (IsCharAlphaNumericW(pszTextW[i])) { + if (bNewSentence) { + if (IsCharLowerW(pszTextW[i])) { + pszTextW[i] = LOWORD(CharUpperW((LPWSTR)(LONG_PTR)MAKELONG(pszTextW[i], 0))); + bChanged = true; } - else { - if (IsCharUpperW(pszTextW[i])) { - pszTextW[i] = LOWORD(CharLowerW((LPWSTR)(LONG_PTR)MAKELONG(pszTextW[i],0))); - bChanged = true; - } + bNewSentence = false; + } + else { + if (IsCharUpperW(pszTextW[i])) { + pszTextW[i] = LOWORD(CharLowerW((LPWSTR)(LONG_PTR)MAKELONG(pszTextW[i], 0))); + bChanged = true; } } } } - - if (bChanged) { - - WideCharToMultiByte(Encoding_SciCP,0,pszTextW,cchTextW, - pszText,(MBWC_DocPos_Cast)SizeOfMem(pszText),NULL,NULL); - - SciCall_Clear(); - SciCall_AddText((iSelEnd - iSelStart), pszText); - SciCall_SetSel(iAnchorPos, iCurPos); - } - - FreeMem(pszText); - FreeMem(pszTextW); } - else { - InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); + + if (bChanged) { + + WideCharToMultiByte(Encoding_SciCP, 0, pszTextW, cchTextW, + pszText, (MBWC_DocPos_Cast)SizeOfMem(pszText), NULL, NULL); + + SciCall_Clear(); + SciCall_AddText((iSelEnd - iSelStart), pszText); + SciCall_SetSel(iAnchorPos, iCurPos); } + + FreeMem(pszText); + FreeMem(pszTextW); } } + //============================================================================= // // EditURLEncode() @@ -1653,7 +1652,7 @@ void EditURLEncode(HWND hwnd) { if (SciCall_IsSelectionEmpty()) { return; } - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; } @@ -1724,7 +1723,7 @@ void EditURLDecode(HWND hwnd) { if (SciCall_IsSelectionEmpty()) { return; } - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; } @@ -1795,7 +1794,7 @@ void EditEscapeCChars(HWND hwnd) { if (!SciCall_IsSelectionEmpty()) { - if (SciCall_IsSelectionRectangle()) + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; @@ -1827,7 +1826,7 @@ void EditUnescapeCChars(HWND hwnd) { if (!SciCall_IsSelectionEmpty()) { - if (SciCall_IsSelectionRectangle()) + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; @@ -1857,7 +1856,7 @@ void EditUnescapeCChars(HWND hwnd) { // void EditChar2Hex(HWND hwnd) { - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; } @@ -1915,7 +1914,7 @@ void EditHex2Char(HWND hwnd) { if (SciCall_IsSelectionEmpty()) { return; } - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; } @@ -2040,7 +2039,7 @@ void EditSelectToMatchingBrace(HWND hwnd) // void EditModifyNumber(HWND hwnd,bool bIncrease) { - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; } @@ -2112,7 +2111,7 @@ void EditTabsToSpaces(HWND hwnd,int nTabWidth,bool bOnlyIndentingWS) { if (SciCall_IsSelectionEmpty()) { return; } // no selection - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; } @@ -2208,7 +2207,7 @@ void EditSpacesToTabs(HWND hwnd,int nTabWidth,bool bOnlyIndentingWS) { if (SciCall_IsSelectionEmpty()) { return; } // no selection - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; } @@ -2322,7 +2321,7 @@ void EditSpacesToTabs(HWND hwnd,int nTabWidth,bool bOnlyIndentingWS) // static void _EditMoveLines(bool bMoveUp) { - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); } else { @@ -2391,7 +2390,7 @@ void EditMoveDown(HWND hwnd) void EditJumpToSelectionStart(HWND hwnd) { UNUSED(hwnd); - if (!SciCall_IsSelectionRectangle()) { + if (!Sci_IsMultiSelection()) { if (SciCall_GetCurrentPos() != SciCall_GetSelectionStart()) { SciCall_SwapMainAnchorCaret(); } @@ -2405,7 +2404,7 @@ void EditJumpToSelectionStart(HWND hwnd) void EditJumpToSelectionEnd(HWND hwnd) { UNUSED(hwnd); - if (!SciCall_IsSelectionRectangle()) { + if (!Sci_IsMultiSelection()) { if (SciCall_GetCurrentPos() != SciCall_GetSelectionEnd()) { SciCall_SwapMainAnchorCaret(); } @@ -2417,10 +2416,16 @@ void EditJumpToSelectionEnd(HWND hwnd) // // EditModifyLines() // -void EditModifyLines(HWND hwnd,LPCWSTR pwszPrefix,LPCWSTR pwszAppend) +void EditModifyLines(HWND hwnd, LPCWSTR pwszPrefix, LPCWSTR pwszAppend) { - char mszPrefix1[256*3] = { '\0' }; - char mszAppend1[256*3] = { '\0' }; + if (!Sci_IsMultiOrRectangleSelection()) + { + InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); + return; + } + + char mszPrefix1[256 * 3] = { '\0' }; + char mszAppend1[256 * 3] = { '\0' }; DocPos iSelStart = SciCall_GetSelectionStart(); DocPos iSelEnd = SciCall_GetSelectionEnd(); @@ -2428,243 +2433,238 @@ void EditModifyLines(HWND hwnd,LPCWSTR pwszPrefix,LPCWSTR pwszAppend) if (StrIsNotEmpty(pwszPrefix)) { WideCharToMultiByte(Encoding_SciCP, 0, pwszPrefix, -1, mszPrefix1, COUNTOF(mszPrefix1), NULL, NULL); } if (StrIsNotEmpty(pwszAppend)) { WideCharToMultiByte(Encoding_SciCP, 0, pwszAppend, -1, mszAppend1, COUNTOF(mszAppend1), NULL, NULL); } - if (!SciCall_IsSelectionRectangle()) + DocLn iLine; + + DocLn iLineStart = SciCall_LineFromPosition(iSelStart); + DocLn iLineEnd = SciCall_LineFromPosition(iSelEnd); + + //if (iSelStart > SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLineStart,0)) + // iLineStart++; + + if (iSelEnd <= SciCall_PositionFromLine(iLineEnd)) { - DocLn iLine; + if ((iLineEnd - iLineStart) >= 1) + --iLineEnd; + } - DocLn iLineStart = SciCall_LineFromPosition(iSelStart); - DocLn iLineEnd = SciCall_LineFromPosition(iSelEnd); + bool bPrefixNum = false; + DocLn iPrefixNum = 0; + int iPrefixNumWidth = 1; + DocLn iAppendNum = 0; + int iAppendNumWidth = 1; + char* pszPrefixNumPad = ""; + char* pszAppendNumPad = ""; + char mszPrefix2[256 * 3] = { '\0' }; + char mszAppend2[256 * 3] = { '\0' }; - //if (iSelStart > SendMessage(hwnd,SCI_POSITIONFROMLINE,(WPARAM)iLineStart,0)) - // iLineStart++; - - if (iSelEnd <= SciCall_PositionFromLine(iLineEnd)) - { - if ((iLineEnd - iLineStart) >= 1) - --iLineEnd; - } + if (!StrIsEmptyA(mszPrefix1)) + { + char* p = StrStrA(mszPrefix1, "$("); + while (!bPrefixNum && p) { - bool bPrefixNum = false; - DocLn iPrefixNum = 0; - int iPrefixNumWidth = 1; - DocLn iAppendNum = 0; - int iAppendNumWidth = 1; - char* pszPrefixNumPad = ""; - char* pszAppendNumPad = ""; - char mszPrefix2[256*3] = { '\0' }; - char mszAppend2[256*3] = { '\0' }; - - if (!StrIsEmptyA(mszPrefix1)) - { - char* p = StrStrA(mszPrefix1, "$("); - while (!bPrefixNum && p) { - - if (StrCmpNA(p,"$(I)",CSTRLEN("$(I)")) == 0) { - *p = 0; - StringCchCopyA(mszPrefix2,COUNTOF(mszPrefix2),p + CSTRLEN("$(I)")); - bPrefixNum = true; - iPrefixNum = 0; - for (DocLn i = iLineEnd - iLineStart; i >= 10; i = i / 10) - iPrefixNumWidth++; - pszPrefixNumPad = ""; - } - - else if (StrCmpNA(p,"$(0I)",CSTRLEN("$(0I)")) == 0) { - *p = 0; - StringCchCopyA(mszPrefix2,COUNTOF(mszPrefix2),p + CSTRLEN("$(0I)")); - bPrefixNum = true; - iPrefixNum = 0; - for (DocLn i = iLineEnd - iLineStart; i >= 10; i = i / 10) - iPrefixNumWidth++; - pszPrefixNumPad = "0"; - } - - else if (StrCmpNA(p,"$(N)",CSTRLEN("$(N)")) == 0) { - *p = 0; - StringCchCopyA(mszPrefix2,COUNTOF(mszPrefix2),p + CSTRLEN("$(N)")); - bPrefixNum = true; - iPrefixNum = 1; - for (DocLn i = iLineEnd - iLineStart + 1; i >= 10; i = i / 10) - iPrefixNumWidth++; - pszPrefixNumPad = ""; - } - - else if (StrCmpNA(p,"$(0N)",CSTRLEN("$(0N)")) == 0) { - *p = 0; - StringCchCopyA(mszPrefix2,COUNTOF(mszPrefix2),p + CSTRLEN("$(0N)")); - bPrefixNum = true; - iPrefixNum = 1; - for (DocLn i = iLineEnd - iLineStart + 1; i >= 10; i = i / 10) - iPrefixNumWidth++; - pszPrefixNumPad = "0"; - } - - else if (StrCmpNA(p,"$(L)",CSTRLEN("$(L)")) == 0) { - *p = 0; - StringCchCopyA(mszPrefix2,COUNTOF(mszPrefix2),p + CSTRLEN("$(L)")); - bPrefixNum = true; - iPrefixNum = iLineStart+1; - for (DocLn i = iLineEnd + 1; i >= 10; i = i / 10) - iPrefixNumWidth++; - pszPrefixNumPad = ""; - } - - else if (StrCmpNA(p,"$(0L)",CSTRLEN("$(0L)")) == 0) { - *p = 0; - StringCchCopyA(mszPrefix2,COUNTOF(mszPrefix2),p + CSTRLEN("$(0L)")); - bPrefixNum = true; - iPrefixNum = iLineStart+1; - for (DocLn i = iLineEnd + 1; i >= 10; i = i / 10) - iPrefixNumWidth++; - pszPrefixNumPad = "0"; - } - p += CSTRLEN("$("); - p = StrStrA(p, "$("); // next - } - } - - bool bAppendNum = false; - - if (!StrIsEmptyA(mszAppend1)) - { - char* p = StrStrA(mszAppend1, "$("); - while (!bAppendNum && p) { - - if (StrCmpNA(p,"$(I)",CSTRLEN("$(I)")) == 0) { - *p = 0; - StringCchCopyA(mszAppend2,COUNTOF(mszAppend2),p + CSTRLEN("$(I)")); - bAppendNum = true; - iAppendNum = 0; - for (DocLn i = iLineEnd - iLineStart; i >= 10; i = i / 10) - iAppendNumWidth++; - pszAppendNumPad = ""; - } - - else if (StrCmpNA(p,"$(0I)",CSTRLEN("$(0I)")) == 0) { - *p = 0; - StringCchCopyA(mszAppend2,COUNTOF(mszAppend2),p + CSTRLEN("$(0I)")); - bAppendNum = true; - iAppendNum = 0; - for (DocLn i = iLineEnd - iLineStart; i >= 10; i = i / 10) - iAppendNumWidth++; - pszAppendNumPad = "0"; - } - - else if (StrCmpNA(p,"$(N)",CSTRLEN("$(N)")) == 0) { - *p = 0; - StringCchCopyA(mszAppend2,COUNTOF(mszAppend2),p + CSTRLEN("$(N)")); - bAppendNum = true; - iAppendNum = 1; - for (DocLn i = iLineEnd - iLineStart + 1; i >= 10; i = i / 10) - iAppendNumWidth++; - pszAppendNumPad = ""; - } - - else if (StrCmpNA(p,"$(0N)",CSTRLEN("$(0N)")) == 0) { - *p = 0; - StringCchCopyA(mszAppend2,COUNTOF(mszAppend2),p + CSTRLEN("$(0N)")); - bAppendNum = true; - iAppendNum = 1; - for (DocLn i = iLineEnd - iLineStart + 1; i >= 10; i = i / 10) - iAppendNumWidth++; - pszAppendNumPad = "0"; - } - - else if (StrCmpNA(p,"$(L)",CSTRLEN("$(L)")) == 0) { - *p = 0; - StringCchCopyA(mszAppend2,COUNTOF(mszAppend2),p + CSTRLEN("$(L)")); - bAppendNum = true; - iAppendNum = iLineStart+1; - for (DocLn i = iLineEnd + 1; i >= 10; i = i / 10) - iAppendNumWidth++; - pszAppendNumPad = ""; - } - - else if (StrCmpNA(p,"$(0L)",CSTRLEN("$(0L)")) == 0) { - *p = 0; - StringCchCopyA(mszAppend2,COUNTOF(mszAppend2),p + CSTRLEN("$(0L)")); - bAppendNum = true; - iAppendNum = iLineStart+1; - for (DocLn i = iLineEnd + 1; i >= 10; i = i / 10) - iAppendNumWidth++; - pszAppendNumPad = "0"; - } - p += CSTRLEN("$("); - p = StrStrA(p, "$("); // next - } - } - - _IGNORE_NOTIFY_CHANGE_; - - DocPos const saveTargetBeg = SciCall_GetTargetStart(); - DocPos const saveTargetEnd = SciCall_GetTargetEnd(); - - for (iLine = iLineStart; iLine <= iLineEnd; iLine++) - { - DocPos iPos; - - if (StrIsNotEmpty(pwszPrefix)) { - - char mszInsert[512*3] = { '\0' }; - StringCchCopyA(mszInsert,COUNTOF(mszInsert),mszPrefix1); - - if (bPrefixNum) { - char tchFmt[64] = { '\0' }; - char tchNum[64] = { '\0' }; - StringCchPrintfA(tchFmt,COUNTOF(tchFmt),"%%%s%ii",pszPrefixNumPad,iPrefixNumWidth); - StringCchPrintfA(tchNum,COUNTOF(tchNum),tchFmt,iPrefixNum); - StringCchCatA(mszInsert,COUNTOF(mszInsert),tchNum); - StringCchCatA(mszInsert,COUNTOF(mszInsert),mszPrefix2); - iPrefixNum++; - } - iPos = SciCall_PositionFromLine(iLine); - SciCall_SetTargetRange(iPos, iPos); - SciCall_ReplaceTarget(-1, mszInsert); + if (StrCmpNA(p, "$(I)", CSTRLEN("$(I)")) == 0) { + *p = 0; + StringCchCopyA(mszPrefix2, COUNTOF(mszPrefix2), p + CSTRLEN("$(I)")); + bPrefixNum = true; + iPrefixNum = 0; + for (DocLn i = iLineEnd - iLineStart; i >= 10; i = i / 10) + iPrefixNumWidth++; + pszPrefixNumPad = ""; } - if (StrIsNotEmpty(pwszAppend)) { - - char mszInsert[512*3] = { '\0' }; - StringCchCopyA(mszInsert,COUNTOF(mszInsert),mszAppend1); - - if (bAppendNum) { - char tchFmt[64] = { '\0' }; - char tchNum[64] = { '\0' }; - StringCchPrintfA(tchFmt,COUNTOF(tchFmt),"%%%s%ii",pszAppendNumPad,iAppendNumWidth); - StringCchPrintfA(tchNum,COUNTOF(tchNum),tchFmt,iAppendNum); - StringCchCatA(mszInsert,COUNTOF(mszInsert),tchNum); - StringCchCatA(mszInsert,COUNTOF(mszInsert),mszAppend2); - iAppendNum++; - } - iPos = SciCall_GetLineEndPosition(iLine); - SciCall_SetTargetRange(iPos, iPos); - SciCall_ReplaceTarget(-1, mszInsert); + else if (StrCmpNA(p, "$(0I)", CSTRLEN("$(0I)")) == 0) { + *p = 0; + StringCchCopyA(mszPrefix2, COUNTOF(mszPrefix2), p + CSTRLEN("$(0I)")); + bPrefixNum = true; + iPrefixNum = 0; + for (DocLn i = iLineEnd - iLineStart; i >= 10; i = i / 10) + iPrefixNumWidth++; + pszPrefixNumPad = "0"; } - } - SciCall_SetTargetRange(saveTargetBeg, saveTargetEnd); //restore - _OBSERVE_NOTIFY_CHANGE_; + else if (StrCmpNA(p, "$(N)", CSTRLEN("$(N)")) == 0) { + *p = 0; + StringCchCopyA(mszPrefix2, COUNTOF(mszPrefix2), p + CSTRLEN("$(N)")); + bPrefixNum = true; + iPrefixNum = 1; + for (DocLn i = iLineEnd - iLineStart + 1; i >= 10; i = i / 10) + iPrefixNumWidth++; + pszPrefixNumPad = ""; + } - // extend selection to start of first line - // the above code is not required when last line has been excluded - if (iSelStart != iSelEnd) - { - DocPos iCurPos = SciCall_GetCurrentPos(); - DocPos iAnchorPos = SciCall_GetAnchor(); - if (iCurPos < iAnchorPos) { - iCurPos = SciCall_PositionFromLine(iLineStart); - iAnchorPos = SciCall_PositionFromLine(iLineEnd + 1); + else if (StrCmpNA(p, "$(0N)", CSTRLEN("$(0N)")) == 0) { + *p = 0; + StringCchCopyA(mszPrefix2, COUNTOF(mszPrefix2), p + CSTRLEN("$(0N)")); + bPrefixNum = true; + iPrefixNum = 1; + for (DocLn i = iLineEnd - iLineStart + 1; i >= 10; i = i / 10) + iPrefixNumWidth++; + pszPrefixNumPad = "0"; } - else { - iAnchorPos = SciCall_PositionFromLine(iLineStart); - iCurPos = SciCall_PositionFromLine(iLineEnd + 1); + + else if (StrCmpNA(p, "$(L)", CSTRLEN("$(L)")) == 0) { + *p = 0; + StringCchCopyA(mszPrefix2, COUNTOF(mszPrefix2), p + CSTRLEN("$(L)")); + bPrefixNum = true; + iPrefixNum = iLineStart + 1; + for (DocLn i = iLineEnd + 1; i >= 10; i = i / 10) + iPrefixNumWidth++; + pszPrefixNumPad = ""; } - EditSetSelectionEx(hwnd, iAnchorPos, iCurPos, -1, -1); + + else if (StrCmpNA(p, "$(0L)", CSTRLEN("$(0L)")) == 0) { + *p = 0; + StringCchCopyA(mszPrefix2, COUNTOF(mszPrefix2), p + CSTRLEN("$(0L)")); + bPrefixNum = true; + iPrefixNum = iLineStart + 1; + for (DocLn i = iLineEnd + 1; i >= 10; i = i / 10) + iPrefixNumWidth++; + pszPrefixNumPad = "0"; + } + p += CSTRLEN("$("); + p = StrStrA(p, "$("); // next } } - else { - InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); + + bool bAppendNum = false; + + if (!StrIsEmptyA(mszAppend1)) + { + char* p = StrStrA(mszAppend1, "$("); + while (!bAppendNum && p) { + + if (StrCmpNA(p, "$(I)", CSTRLEN("$(I)")) == 0) { + *p = 0; + StringCchCopyA(mszAppend2, COUNTOF(mszAppend2), p + CSTRLEN("$(I)")); + bAppendNum = true; + iAppendNum = 0; + for (DocLn i = iLineEnd - iLineStart; i >= 10; i = i / 10) + iAppendNumWidth++; + pszAppendNumPad = ""; + } + + else if (StrCmpNA(p, "$(0I)", CSTRLEN("$(0I)")) == 0) { + *p = 0; + StringCchCopyA(mszAppend2, COUNTOF(mszAppend2), p + CSTRLEN("$(0I)")); + bAppendNum = true; + iAppendNum = 0; + for (DocLn i = iLineEnd - iLineStart; i >= 10; i = i / 10) + iAppendNumWidth++; + pszAppendNumPad = "0"; + } + + else if (StrCmpNA(p, "$(N)", CSTRLEN("$(N)")) == 0) { + *p = 0; + StringCchCopyA(mszAppend2, COUNTOF(mszAppend2), p + CSTRLEN("$(N)")); + bAppendNum = true; + iAppendNum = 1; + for (DocLn i = iLineEnd - iLineStart + 1; i >= 10; i = i / 10) + iAppendNumWidth++; + pszAppendNumPad = ""; + } + + else if (StrCmpNA(p, "$(0N)", CSTRLEN("$(0N)")) == 0) { + *p = 0; + StringCchCopyA(mszAppend2, COUNTOF(mszAppend2), p + CSTRLEN("$(0N)")); + bAppendNum = true; + iAppendNum = 1; + for (DocLn i = iLineEnd - iLineStart + 1; i >= 10; i = i / 10) + iAppendNumWidth++; + pszAppendNumPad = "0"; + } + + else if (StrCmpNA(p, "$(L)", CSTRLEN("$(L)")) == 0) { + *p = 0; + StringCchCopyA(mszAppend2, COUNTOF(mszAppend2), p + CSTRLEN("$(L)")); + bAppendNum = true; + iAppendNum = iLineStart + 1; + for (DocLn i = iLineEnd + 1; i >= 10; i = i / 10) + iAppendNumWidth++; + pszAppendNumPad = ""; + } + + else if (StrCmpNA(p, "$(0L)", CSTRLEN("$(0L)")) == 0) { + *p = 0; + StringCchCopyA(mszAppend2, COUNTOF(mszAppend2), p + CSTRLEN("$(0L)")); + bAppendNum = true; + iAppendNum = iLineStart + 1; + for (DocLn i = iLineEnd + 1; i >= 10; i = i / 10) + iAppendNumWidth++; + pszAppendNumPad = "0"; + } + p += CSTRLEN("$("); + p = StrStrA(p, "$("); // next + } } + + _IGNORE_NOTIFY_CHANGE_; + + DocPos const saveTargetBeg = SciCall_GetTargetStart(); + DocPos const saveTargetEnd = SciCall_GetTargetEnd(); + + for (iLine = iLineStart; iLine <= iLineEnd; iLine++) + { + DocPos iPos; + + if (StrIsNotEmpty(pwszPrefix)) { + + char mszInsert[512 * 3] = { '\0' }; + StringCchCopyA(mszInsert, COUNTOF(mszInsert), mszPrefix1); + + if (bPrefixNum) { + char tchFmt[64] = { '\0' }; + char tchNum[64] = { '\0' }; + StringCchPrintfA(tchFmt, COUNTOF(tchFmt), "%%%s%ii", pszPrefixNumPad, iPrefixNumWidth); + StringCchPrintfA(tchNum, COUNTOF(tchNum), tchFmt, iPrefixNum); + StringCchCatA(mszInsert, COUNTOF(mszInsert), tchNum); + StringCchCatA(mszInsert, COUNTOF(mszInsert), mszPrefix2); + iPrefixNum++; + } + iPos = SciCall_PositionFromLine(iLine); + SciCall_SetTargetRange(iPos, iPos); + SciCall_ReplaceTarget(-1, mszInsert); + } + + if (StrIsNotEmpty(pwszAppend)) { + + char mszInsert[512 * 3] = { '\0' }; + StringCchCopyA(mszInsert, COUNTOF(mszInsert), mszAppend1); + + if (bAppendNum) { + char tchFmt[64] = { '\0' }; + char tchNum[64] = { '\0' }; + StringCchPrintfA(tchFmt, COUNTOF(tchFmt), "%%%s%ii", pszAppendNumPad, iAppendNumWidth); + StringCchPrintfA(tchNum, COUNTOF(tchNum), tchFmt, iAppendNum); + StringCchCatA(mszInsert, COUNTOF(mszInsert), tchNum); + StringCchCatA(mszInsert, COUNTOF(mszInsert), mszAppend2); + iAppendNum++; + } + iPos = SciCall_GetLineEndPosition(iLine); + SciCall_SetTargetRange(iPos, iPos); + SciCall_ReplaceTarget(-1, mszInsert); + } + } + + SciCall_SetTargetRange(saveTargetBeg, saveTargetEnd); //restore + _OBSERVE_NOTIFY_CHANGE_; + + // extend selection to start of first line + // the above code is not required when last line has been excluded + if (iSelStart != iSelEnd) + { + DocPos iCurPos = SciCall_GetCurrentPos(); + DocPos iAnchorPos = SciCall_GetAnchor(); + if (iCurPos < iAnchorPos) { + iCurPos = SciCall_PositionFromLine(iLineStart); + iAnchorPos = SciCall_PositionFromLine(iLineEnd + 1); + } + else { + iAnchorPos = SciCall_PositionFromLine(iLineStart); + iCurPos = SciCall_PositionFromLine(iLineEnd + 1); + } + EditSetSelectionEx(hwnd, iAnchorPos, iCurPos, -1, -1); + } + } @@ -2678,7 +2678,7 @@ void EditIndentBlock(HWND hwnd, int cmd, bool bFormatIndentation, bool bForceAll SendMessage(hwnd, cmd, 0, 0); return; } - if (!bForceAll && SciCall_IsSelectionRectangle()) + if (!bForceAll && Sci_IsMultiOrRectangleSelection()) { SendMessage(hwnd, cmd, 0, 0); return; @@ -2777,7 +2777,7 @@ void EditAlignText(HWND hwnd, int nMode) DocPos const iCurCol = SciCall_GetColumn(iCurPos); DocPos const iAnchorCol = SciCall_GetColumn(iAnchorPos); - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; } @@ -2997,7 +2997,7 @@ void EditAlignText(HWND hwnd, int nMode) // void EditEncloseSelection(HWND hwnd, LPCWSTR pwszOpen, LPCWSTR pwszClose) { - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; } @@ -3058,7 +3058,7 @@ void EditToggleLineComments(HWND hwnd, LPCWSTR pwszComment, bool bInsertAtStart) if (cchComment == 0) { return; } - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; } @@ -3175,8 +3175,6 @@ static DocPos _AppendSpaces(HWND hwnd, DocLn iLineStart, DocLn iLineEnd, DocPos DocPos const saveTargetBeg = SciCall_GetTargetStart(); DocPos const saveTargetEnd = SciCall_GetTargetEnd(); - //const bool bIsSelectionRectangle = SciCall_IsSelectionRectangle(); - for (DocLn iLine = iLineStart; iLine <= iLineEnd; ++iLine) { // insertion position is at end of line @@ -3215,7 +3213,7 @@ void EditPadWithSpaces(HWND hwnd, bool bSkipEmpty, bool bNoUndoGroup) int const token = (!bNoUndoGroup ? BeginUndoAction() : -1); - if (SciCall_IsSelectionRectangle() && !SciCall_IsSelectionEmpty()) + if (Sci_IsMultiOrRectangleSelection() && !SciCall_IsSelectionEmpty()) { DocPos const selAnchorMainPos = SciCall_GetRectangularSelectionAnchor(); DocPos const selCaretMainPos = SciCall_GetRectangularSelectionCaret(); @@ -3371,7 +3369,10 @@ void EditStripFirstCharacter(HWND hwnd) SciCall_SetRectangularSelectionCaretVirtualSpace(vSpcCaretMainPos); } } - else // SC_SEL_LINES | SC_SEL_STREAM + else if (Sci_IsMultiSelection()) { + // not implemented + } + else // SC_SEL_LINES | SC_SEL_STREAM { for (DocLn iLine = iLineStart; iLine <= iLineEnd; ++iLine) { const DocPos iPos = SciCall_PositionFromLine(iLine); @@ -3403,7 +3404,7 @@ void EditStripLastCharacter(HWND hwnd, bool bIgnoreSelection, bool bTrailingBlan DocPos const saveTargetBeg = SciCall_GetTargetStart(); DocPos const saveTargetEnd = SciCall_GetTargetEnd(); - if (SciCall_IsSelectionRectangle() && !bIgnoreSelection) + if (Sci_IsMultiOrRectangleSelection() && !bIgnoreSelection) { if (SciCall_IsSelectionEmpty()) { SciCall_Clear(); @@ -3518,10 +3519,9 @@ void EditCompressBlanks(HWND hwnd) const DocLn iLineStart = SciCall_LineFromPosition(iSelStartPos); const DocLn iLineEnd = SciCall_LineFromPosition(iSelEndPos); - if (SciCall_IsSelectionRectangle()) { - if (bIsSelEmpty) { - return; - } + if (SciCall_IsSelectionRectangle()) + { + if (bIsSelEmpty) { return; } const DocPos selAnchorMainPos = SciCall_GetRectangularSelectionAnchor(); const DocPos selCaretMainPos = SciCall_GetRectangularSelectionCaret(); @@ -3568,13 +3568,17 @@ void EditCompressBlanks(HWND hwnd) } SciCall_SetRectangularSelectionAnchor(selAnchorMainPos); - if (vSpcAnchorMainPos > 0) + if (vSpcAnchorMainPos > 0) { SciCall_SetRectangularSelectionAnchorVirtualSpace(vSpcAnchorMainPos); - + } SciCall_SetRectangularSelectionCaret(selCaretMainPos - remCount); - if (vSpcCaretMainPos > 0) + if (vSpcCaretMainPos > 0) { SciCall_SetRectangularSelectionCaretVirtualSpace(vSpcCaretMainPos); - + } + } + else if (Sci_IsMultiSelection()) { + // @@@ not implemented + InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); } else // SC_SEL_LINES | SC_SEL_STREAM { @@ -3677,7 +3681,7 @@ void EditRemoveBlankLines(HWND hwnd, bool bMerge, bool bRemoveWhiteSpace) { UNUSED(hwnd); - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; } @@ -3750,7 +3754,7 @@ void EditRemoveDuplicateLines(HWND hwnd, bool bRemoveEmptyLines) { UNUSED(hwnd); - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; } @@ -3821,7 +3825,7 @@ void EditRemoveDuplicateLines(HWND hwnd, bool bRemoveEmptyLines) // void EditWrapToColumn(HWND hwnd,DocPos nColumn/*,int nTabWidth*/) { - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; } @@ -3997,10 +4001,9 @@ void EditJoinLinesEx(HWND hwnd, bool bPreserveParagraphs, bool bCRLF2Space) { bool bModified = false; - if (SciCall_IsSelectionEmpty()) - return; + if (SciCall_IsSelectionEmpty()) { return; } - if (SciCall_IsSelectionRectangle()) { + if (Sci_IsMultiOrRectangleSelection()) { InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SELRECT); return; } @@ -4138,26 +4141,26 @@ void EditSortLines(HWND hwnd, int iSortFlags) FNSTRCMP pfnStrCmp = (iSortFlags & SORT_NOCASE) ? StrCmpIW : StrCmpW; - bool const bIsRectSel = SciCall_IsSelectionRectangle(); + bool const bIsMultiSel = Sci_IsMultiOrRectangleSelection(); DocPos const iSelStart = SciCall_GetSelectionStart(); //iSelStart = SciCall_PositionFromLine(iLine); DocPos const iSelEnd = SciCall_GetSelectionEnd(); //DocLn const iLine = SciCall_LineFromPosition(iSelStart); - DocPos iCurPos = bIsRectSel ? SciCall_GetRectangularSelectionCaret() : SciCall_GetCurrentPos(); - DocPos iAnchorPos = bIsRectSel ? SciCall_GetRectangularSelectionAnchor() : SciCall_GetAnchor(); - DocPos iCurPosVS = bIsRectSel ? SciCall_GetRectangularSelectionCaretVirtualSpace() : 0; - DocPos iAnchorPosVS = bIsRectSel ? SciCall_GetRectangularSelectionAnchorVirtualSpace() : 0; + DocPos iCurPos = bIsMultiSel ? SciCall_GetRectangularSelectionCaret() : SciCall_GetCurrentPos(); + DocPos iAnchorPos = bIsMultiSel ? SciCall_GetRectangularSelectionAnchor() : SciCall_GetAnchor(); + DocPos iCurPosVS = bIsMultiSel ? SciCall_GetRectangularSelectionCaretVirtualSpace() : 0; + DocPos iAnchorPosVS = bIsMultiSel ? SciCall_GetRectangularSelectionAnchorVirtualSpace() : 0; - DocLn const iRcCurLine = bIsRectSel ? SciCall_LineFromPosition(iCurPos) : 0; - DocLn const iRcAnchorLine = bIsRectSel ? SciCall_LineFromPosition(iAnchorPos) : 0; + DocLn const iRcCurLine = bIsMultiSel ? SciCall_LineFromPosition(iCurPos) : 0; + DocLn const iRcAnchorLine = bIsMultiSel ? SciCall_LineFromPosition(iAnchorPos) : 0; DocPos const iCurCol = SciCall_GetColumn(iCurPos); DocPos const iAnchorCol = SciCall_GetColumn(iAnchorPos); - DocLn const iSortColumn = bIsRectSel ? min_p(iCurCol, iAnchorCol) : (UINT)SciCall_GetColumn(iCurPos); + DocLn const iSortColumn = bIsMultiSel ? min_p(iCurCol, iAnchorCol) : (UINT)SciCall_GetColumn(iCurPos); - DocLn const iLineStart = bIsRectSel ? min_ln(iRcCurLine, iRcAnchorLine) : SciCall_LineFromPosition(iSelStart); - DocLn const _lnend = bIsRectSel ? max_ln(iRcCurLine, iRcAnchorLine) : SciCall_LineFromPosition(iSelEnd); + DocLn const iLineStart = bIsMultiSel ? min_ln(iRcCurLine, iRcAnchorLine) : SciCall_LineFromPosition(iSelStart); + DocLn const _lnend = bIsMultiSel ? max_ln(iRcCurLine, iRcAnchorLine) : SciCall_LineFromPosition(iSelEnd); DocLn const iLineEnd = (iSelEnd <= SciCall_PositionFromLine(_lnend)) ? (_lnend - 1) : _lnend; if (iLineEnd <= iLineStart) { return; } @@ -4175,7 +4178,7 @@ void EditSortLines(HWND hwnd, int iSortFlags) int const _iTabWidth = SciCall_GetTabWidth(); - if (bIsRectSel) + if (bIsMultiSel) { EditPadWithSpaces(hwnd, !(iSortFlags & SORT_SHUFFLE), true); // changed rectangular selection @@ -4328,7 +4331,7 @@ void EditSortLines(HWND hwnd, int iSortFlags) FreeMem(pLines); //DocPos const iResultLength = (DocPos)StringCchLenA(pmszResult, lenRes) + ((cEOLMode == SC_EOL_CRLF) ? 2 : 1); - if (!bIsRectSel) { + if (!bIsMultiSel) { if (iAnchorPos > iCurPos) { iCurPos = SciCall_FindColumn(iLineStart, iCurCol); iAnchorPos = SciCall_FindColumn(_lnend, iAnchorCol); @@ -4347,7 +4350,7 @@ void EditSortLines(HWND hwnd, int iSortFlags) SciCall_SetTargetRange(saveTargetBeg, saveTargetEnd); //restore FreeMem(pmszResult); - if (bIsRectSel) { + if (bIsMultiSel) { EditSetSelectionEx(hwnd, iAnchorPos, iCurPos, iAnchorPosVS, iCurPosVS); } else { @@ -4423,6 +4426,12 @@ void EditEnsureSelectionVisible(HWND hwnd) iAnchorPosVS = SciCall_GetRectangularSelectionAnchorVirtualSpace(); iCurPosVS = SciCall_GetRectangularSelectionCaretVirtualSpace(); } + else if (Sci_IsMultiSelection()) { + iAnchorPos = SciCall_GetSelectionNAnchor(0); + iCurrentPos = SciCall_GetSelectionNCaret(0); + iAnchorPosVS = SciCall_GetSelectionNAnchorVirtualSpace(0); + iCurPosVS = SciCall_GetSelectionNCaretVirtualSpace(0); + } else { iAnchorPos = SciCall_GetAnchor(); iCurrentPos = SciCall_GetCurrentPos(); @@ -4499,8 +4508,8 @@ const DOCVIEWPOS_T EditGetCurrentDocView(HWND hwnd) { UNUSED(hwnd); DOCVIEWPOS_T docView = INIT_DOCVIEWPOS; - docView.iCurPos = SciCall_IsSelectionRectangle() ? SciCall_GetRectangularSelectionCaret() : SciCall_GetCurrentPos(); - docView.iAnchorPos = SciCall_IsSelectionRectangle() ? SciCall_GetRectangularSelectionAnchor() : SciCall_GetAnchor(); + docView.iCurPos = Sci_IsMultiOrRectangleSelection() ? SciCall_GetSelectionNCaret(0) : SciCall_GetCurrentPos(); + docView.iAnchorPos = Sci_IsMultiOrRectangleSelection() ? SciCall_GetSelectionNAnchor(SciCall_GetSelections() - 1) : SciCall_GetAnchor(); //docView.vSpcCaretPos = SciCall_IsSelectionRectangle() ? SciCall_GetRectangularSelectionCaretVirtualSpace() : -1; //docView.vSpcAnchorPos = SciCall_IsSelectionRectangle() ? SciCall_GetRectangularSelectionAnchorVirtualSpace() : -1; docView.iCurrLine = SciCall_LineFromPosition(docView.iCurPos); @@ -4515,13 +4524,13 @@ const DOCVIEWPOS_T EditGetCurrentDocView(HWND hwnd) //============================================================================= // -// EditGetCurrentDocView() +// EditSetDocView() // void EditSetDocView(HWND hwnd, const DOCVIEWPOS_T docView) { EditJumpTo(hwnd, docView.iCurrLine + 1, docView.iCurColumn + 1); - SciCall_EnsureVisible(docView.iDocTopLine); DocLn const iNewTopLine = SciCall_GetFirstVisibleLine(); + SciCall_EnsureVisible(iNewTopLine); SciCall_LineScroll(0, docView.iVisTopLine - iNewTopLine); SciCall_SetXOffset(docView.iXOffset); } @@ -4571,14 +4580,14 @@ void EditGetExcerpt(HWND hwnd,LPWSTR lpszExcerpt,DWORD cchExcerpt) const DocPos iCurPos = SciCall_GetCurrentPos(); const DocPos iAnchorPos = SciCall_GetAnchor(); - if (iCurPos == iAnchorPos || SciCall_IsSelectionRectangle()) { + if ((iCurPos == iAnchorPos) || Sci_IsMultiOrRectangleSelection()) { StringCchCopy(lpszExcerpt,cchExcerpt,L""); return; } WCHAR tch[256] = { L'\0' }; struct Sci_TextRange tr = { { 0, 0 }, NULL }; - /*if (iCurPos != iAnchorPos && !SciCall_IsSelectionRectangle()) {*/ + /*if (iCurPos != iAnchorPos && !Sci_IsMultiOrRectangleSelection()) {*/ tr.chrg.cpMin = (DocPosCR)SciCall_GetSelectionStart(); tr.chrg.cpMax = min_cr((tr.chrg.cpMin + (DocPosCR)COUNTOF(tch)), (DocPosCR)SciCall_GetSelectionEnd()); /*} @@ -5210,7 +5219,7 @@ static INT_PTR CALLBACK EditFindReplaceDlgProcW(HWND hwnd,UINT umsg,WPARAM wPara } _SetSearchFlags(hwnd, sg_pefrData); // sync s_fwrdMatch = NO_MATCH; - s_anyMatch = (SciCall_IsSelectionRectangle() || SciCall_IsSelectionEmpty() ? NO_MATCH : MATCH); + s_anyMatch = (Sci_IsMultiOrRectangleSelection() || SciCall_IsSelectionEmpty() ? NO_MATCH : MATCH); HMENU hmenu = GetSystemMenu(hwnd, false); GetLngString(IDS_MUI_SAVEPOS, s_tchBuf, COUNTOF(s_tchBuf)); @@ -5228,7 +5237,7 @@ static INT_PTR CALLBACK EditFindReplaceDlgProcW(HWND hwnd,UINT umsg,WPARAM wPara s_InitialTopLine = SciCall_GetFirstVisibleLine(); // find first occurrence of clip-board text - //if (!SciCall_IsSelectionRectangle() && SciCall_IsSelectionEmpty()) { + //if (!Sci_IsMultiOrRectangleSelection() && SciCall_IsSelectionEmpty()) { // PostWMCommand(hwnd, IDOK); //} @@ -5362,7 +5371,7 @@ static INT_PTR CALLBACK EditFindReplaceDlgProcW(HWND hwnd,UINT umsg,WPARAM wPara EditEnsureSelectionVisible(Globals.hwndEdit); } - bool const bEnableReplInSel = !(SciCall_IsSelectionEmpty() || SciCall_IsSelectionRectangle()); + bool const bEnableReplInSel = !(SciCall_IsSelectionEmpty() || Sci_IsMultiOrRectangleSelection()); DialogEnableWindow(hwnd, IDC_REPLACEINSEL, bEnableReplInSel); _DelayMarkAll(hwnd, 50, s_InitialSearchStart); @@ -5467,7 +5476,7 @@ static INT_PTR CALLBACK EditFindReplaceDlgProcW(HWND hwnd,UINT umsg,WPARAM wPara bool const bEnableR = (GetWindowTextLengthW(GetDlgItem(hwnd, IDC_REPLACETEXT)) || CB_ERR != SendDlgItemMessage(hwnd, IDC_REPLACETEXT, CB_GETCURSEL, 0, 0)); - bool const bEnableIS = !(SciCall_IsSelectionEmpty() || SciCall_IsSelectionRectangle()); + bool const bEnableIS = !(SciCall_IsSelectionEmpty() || Sci_IsMultiOrRectangleSelection()); DialogEnableWindow(hwnd, IDOK, bEnableF); DialogEnableWindow(hwnd, IDC_FINDPREV, bEnableF); @@ -7699,7 +7708,7 @@ static INT_PTR CALLBACK EditSortDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM if (*piSortFlags & SORT_LOGICAL) { CheckDlgButton(hwnd, 109, BST_CHECKED); } - if (!SciCall_IsSelectionRectangle()) { + if (!Sci_IsMultiOrRectangleSelection()) { *piSortFlags &= ~SORT_COLUMN; DialogEnableWindow(hwnd,110,false); } diff --git a/src/Notepad3.c b/src/Notepad3.c index aa12c38f6..116e072ee 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -226,16 +226,159 @@ int const g_FontQuality[4] = { // static method declarations // undo / redo selections -static UT_icd UndoRedoSelection_icd = { sizeof(UndoRedoSelection_t), NULL, NULL, NULL }; + +static UT_icd UndoRedoSelElement_icd = { sizeof(DocPos), NULL, NULL, NULL }; + +static void InitUndoRedoSelection(void* elt) +{ + UndoRedoSelection_t* selection = (UndoRedoSelection_t*)elt; + + if (selection != NULL) { + selection->selMode_undo = 0; + selection->anchorPos_undo = NULL; + selection->curPos_undo = NULL; + selection->anchorVS_undo = NULL; + selection->curVS_undo = NULL; + + selection->selMode_redo = 0; + selection->anchorPos_redo = NULL; + selection->curPos_redo = NULL; + selection->anchorVS_redo = NULL; + selection->curVS_redo = NULL; + } +} + + +static void DelUndoRedoSelection(void* elt) +{ + UndoRedoSelection_t* selection = (UndoRedoSelection_t*)elt; + + if (selection != NULL) { + if (selection->anchorPos_undo != NULL) { + utarray_clear(selection->anchorPos_undo); + utarray_free(selection->anchorPos_undo); + selection->anchorPos_undo = NULL; + } + if (selection->curPos_undo != NULL) { + utarray_clear(selection->curPos_undo); + utarray_free(selection->curPos_undo); + selection->curPos_undo = NULL; + } + if (selection->anchorVS_undo != NULL) { + utarray_clear(selection->anchorVS_undo); + utarray_free(selection->anchorVS_undo); + selection->anchorVS_undo = NULL; + } + if (selection->curVS_undo != NULL) { + utarray_clear(selection->curVS_undo); + utarray_free(selection->curVS_undo); + selection->curVS_undo = NULL; + } + + if (selection->anchorPos_redo != NULL) { + utarray_clear(selection->anchorPos_redo); + utarray_free(selection->anchorPos_redo); + selection->anchorPos_redo = NULL; + } + if (selection->curPos_redo != NULL) { + utarray_clear(selection->curPos_redo); + utarray_free(selection->curPos_redo); + selection->curPos_redo = NULL; + } + if (selection->anchorVS_redo != NULL) { + utarray_clear(selection->anchorVS_redo); + utarray_free(selection->anchorVS_redo); + selection->anchorVS_redo = NULL; + } + if (selection->curVS_redo != NULL) { + utarray_clear(selection->curVS_redo); + utarray_free(selection->curVS_redo); + selection->curVS_redo = NULL; + } + } +} + +static void CopyUndoRedoSelection(void* dst, const void* src) +{ + UndoRedoSelection_t* dst_sel = (UndoRedoSelection_t*)dst; + const UndoRedoSelection_t* src_sel = (UndoRedoSelection_t*)src; + + DocPos* pPos = NULL; + InitUndoRedoSelection(dst); + + dst_sel->selMode_undo = (src_sel) ? src_sel->selMode_undo : 0; + + utarray_new(dst_sel->anchorPos_undo, &UndoRedoSelElement_icd); + if (src_sel) { + while ((pPos = (DocPos*)utarray_next(src_sel->anchorPos_undo, pPos)) != NULL) { + utarray_push_back(dst_sel->anchorPos_undo, pPos); + } + } + + utarray_new(dst_sel->curPos_undo, &UndoRedoSelElement_icd); + if (src_sel) { + while ((pPos = (DocPos*)utarray_next(src_sel->curPos_undo, pPos)) != NULL) { + utarray_push_back(dst_sel->curPos_undo, pPos); + } + } + + utarray_new(dst_sel->anchorVS_undo, &UndoRedoSelElement_icd); + if (src_sel) { + while ((pPos = (DocPos*)utarray_next(src_sel->anchorVS_undo, pPos)) != NULL) { + utarray_push_back(dst_sel->anchorVS_undo, pPos); + } + } + + utarray_new(dst_sel->curVS_undo, &UndoRedoSelElement_icd); + if (src_sel) { + while ((pPos = (DocPos*)utarray_next(src_sel->curVS_undo, pPos)) != NULL) { + utarray_push_back(dst_sel->curVS_undo, pPos); + } + } + + + dst_sel->selMode_redo = (src_sel) ? src_sel->selMode_redo : 0; + + utarray_new(dst_sel->anchorPos_redo, &UndoRedoSelElement_icd); + if (src_sel) { + while ((pPos = (DocPos*)utarray_next(src_sel->anchorPos_redo, pPos)) != NULL) { + utarray_push_back(dst_sel->anchorPos_redo, pPos); + } + } + + utarray_new(dst_sel->curPos_redo, &UndoRedoSelElement_icd); + if (src_sel) { + while ((pPos = (DocPos*)utarray_next(src_sel->curPos_redo, pPos)) != NULL) { + utarray_push_back(dst_sel->curPos_redo, pPos); + } + } + + utarray_new(dst_sel->anchorVS_redo, &UndoRedoSelElement_icd); + if (src_sel) { + while ((pPos = (DocPos*)utarray_next(src_sel->anchorVS_redo, pPos)) != NULL) { + utarray_push_back(dst_sel->anchorVS_redo, pPos); + } + } + + utarray_new(dst_sel->curVS_redo, &UndoRedoSelElement_icd); + if (src_sel) { + while ((pPos = (DocPos*)utarray_next(src_sel->curVS_redo, pPos)) != NULL) { + utarray_push_back(dst_sel->curVS_redo, pPos); + } + } +} + + +static UT_icd UndoRedoSelection_icd = { sizeof(UndoRedoSelection_t), InitUndoRedoSelection, CopyUndoRedoSelection, DelUndoRedoSelection }; static UT_array* UndoRedoSelectionUTArray = NULL; static bool _InUndoRedoTransaction(); static void _SaveRedoSelection(int token); static int _SaveUndoSelection(); -static int _UndoRedoActionMap(int token, UndoRedoSelection_t* selection); +static int _UndoRedoActionMap(int token, UndoRedoSelection_t** selection); + static void _DelayClearZoomCallTip(int delay); - #ifdef _EXTRA_DRAG_N_DROP_HANDLER_ static CLIPFORMAT cfDrpF = CF_HDROP; static POINTL ptDummy = { 0, 0 }; @@ -1529,6 +1672,7 @@ static void _InitializeSciEditCtrl(HWND hwndEditCtrl) int const evtMask2 = SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT | SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE; SendMessage(hwndEditCtrl, SCI_SETMODEVENTMASK, (WPARAM)(evtMask1 | evtMask2), 0); + SendMessage(hwndEditCtrl, SCI_SETCOMMANDEVENTS, false, 0); // speedup folding SendMessage(hwndEditCtrl, SCI_SETCODEPAGE, (WPARAM)SC_CP_UTF8, 0); // fixed internal UTF-8 (Sci:default) SendMessage(hwndEditCtrl, SCI_SETLAYOUTCACHE, SC_CACHE_PAGE, 0); //SendMessage(hwndEditCtrl, SCI_SETLAYOUTCACHE, SC_CACHE_DOCUMENT, 0); @@ -1540,20 +1684,22 @@ static void _InitializeSciEditCtrl(HWND hwndEditCtrl) SendMessage(hwndEditCtrl, SCI_SETSCROLLWIDTH, 1, 0); SendMessage(hwndEditCtrl, SCI_SETSCROLLWIDTHTRACKING, true, 0); SendMessage(hwndEditCtrl, SCI_SETENDATLASTLINE, true, 0); + + SendMessage(hwndEditCtrl, SCI_SETMULTIPLESELECTION, true, 0); + SendMessage(hwndEditCtrl, SCI_SETADDITIONALSELECTIONTYPING, true, 0); + SendMessage(hwndEditCtrl, SCI_SETMULTIPASTE, SC_MULTIPASTE_EACH, 0); SendMessage(hwndEditCtrl, SCI_SETMOUSESELECTIONRECTANGULARSWITCH, true, 0); - SendMessage(hwndEditCtrl, SCI_SETMULTIPLESELECTION, false, 0); - SendMessage(hwndEditCtrl, SCI_SETADDITIONALSELECTIONTYPING, false, 0); - SendMessage(hwndEditCtrl, SCI_SETADDITIONALCARETSBLINK, true, 0); - SendMessage(hwndEditCtrl, SCI_SETADDITIONALCARETSVISIBLE, true, 0); int const vspaceOpt = Settings2.DenyVirtualSpaceAccess ? SCVS_NONE : NP3_VIRTUAL_SPACE_ACCESS_OPTIONS; SendMessage(hwndEditCtrl, SCI_SETVIRTUALSPACEOPTIONS, vspaceOpt, 0); + SendMessage(hwndEditCtrl, SCI_SETADDITIONALCARETSBLINK, true, 0); + SendMessage(hwndEditCtrl, SCI_SETADDITIONALCARETSVISIBLE, true, 0); + SendMessage(hwndEditCtrl, SCI_SETIDLESTYLING, SC_IDLESTYLING_NONE, 0); // needed for focused view // Idle Styling (very large text) //~~~SendMessage(hwndEditCtrl, SCI_SETIDLESTYLING, SC_IDLESTYLING_AFTERVISIBLE, 0); //~~~SendMessage(hwndEditCtrl, SCI_SETIDLESTYLING, SC_IDLESTYLING_ALL, 0); - SendMessage(hwndEditCtrl, SCI_SETCOMMANDEVENTS, false, 0); // speedup folding // assign command keys SendMessage(hwndEditCtrl, SCI_ASSIGNCMDKEY, (SCK_NEXT + (SCMOD_CTRL << 16)), SCI_PARADOWN); @@ -6499,6 +6645,290 @@ static bool _IsIMEOpenInNoNativeMode() } #endif + +//============================================================================= +// +// MsgNotifyLean() - Handles WM_NOTIFY (only absolute neccessary events) +// +// !!! Set correct SCI_SETMODEVENTMASK in _InitializeSciEditCtrl() +// +inline static LRESULT _MsgNotifyLean(const LPNMHDR pnmh, const SCNotification* const scn) +{ + // --- check only mandatory events (must be fast !!!) --- + if (pnmh->idFrom == IDC_EDIT) { + if (pnmh->code == 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 (!SciCall_IsSelectionEmpty() && !_InUndoRedoTransaction()) + _SaveRedoSelection(_SaveUndoSelection()); + } + bModified = false; // not yet + } + // check for ADDUNDOACTION step + if (iModType & SC_MOD_CONTAINER) + { + if (iModType & SC_PERFORMED_UNDO) { + RestoreAction(scn->token, UNDO); + } + else if (iModType & SC_PERFORMED_REDO) { + RestoreAction(scn->token, REDO); + } + } + if (bModified) { _SetSaveNeededFlag(true); } + } + else if (pnmh->code == SCN_SAVEPOINTREACHED) { + _SetSaveNeededFlag(false); + } + else if (pnmh->code == SCN_SAVEPOINTLEFT) { + _SetSaveNeededFlag(true); + } + else if (pnmh->code == SCN_MODIFYATTEMPTRO) { + if (FocusedView.HideNonMatchedLines) { EditToggleView(Globals.hwndEdit); } + } + } + return TRUE; +} + + +//============================================================================= +// +// _MsgNotifyFromEdit() - Handles WM_NOTIFY (only absolute neccessary events) +// +// !!! Set correct SCI_SETMODEVENTMASK in _InitializeSciEditCtrl() +// +static LRESULT _MsgNotifyFromEdit(HWND hwnd, const LPNMHDR pnmh, const SCNotification* const scn) +{ + static int _s_indic_click_modifiers = 0; + + switch (pnmh->code) + { + case SCN_HOTSPOTCLICK: + case SCN_HOTSPOTDOUBLECLICK: + case SCN_HOTSPOTRELEASECLICK: + case SCN_CALLTIPCLICK: + return 0; + + case SCN_MODIFIED: + { + int const iModType = scn->modificationType; + bool bModified = true; + if ((iModType & SC_MOD_BEFOREINSERT) || ((iModType & SC_MOD_BEFOREDELETE))) { + if (!((iModType & SC_PERFORMED_UNDO) || (iModType & SC_PERFORMED_REDO))) { + if (!SciCall_IsSelectionEmpty() && !_InUndoRedoTransaction()) + _SaveRedoSelection(_SaveUndoSelection()); + } + bModified = false; // not yet + } + if (iModType & SC_MOD_CONTAINER) { + if (iModType & SC_PERFORMED_UNDO) { + RestoreAction(scn->token, UNDO); + } + else if (iModType & SC_PERFORMED_REDO) { + RestoreAction(scn->token, REDO); + } + } + if (bModified) { + if (IsMarkOccurrencesEnabled()) { + MarkAllOccurrences(Settings2.UpdateDelayMarkAllOccurrences, true); + } + if (Settings.HyperlinkHotspot) { + UpdateVisibleUrlIndics(); + } + if (scn->linesAdded != 0) { + UpdateMarginWidth(); + } + _SetSaveNeededFlag(true); + } + } + break; + + case SCN_STYLENEEDED: // this event needs SCI_SETLEXER(SCLEX_CONTAINER) + { + EditFinalizeStyling(Globals.hwndEdit, scn->position); + } + break; + + case SCN_UPDATEUI: + { + int const iUpd = scn->updated; + //if (scn->updated & SC_UPDATE_NP3_INTERNAL_NOTIFY) { + // // special case + //} + //else + + if (iUpd & (SC_UPDATE_SELECTION | SC_UPDATE_CONTENT)) + { + // Brace Match + if (Settings.MatchBraces) { + EditMatchBrace(Globals.hwndEdit); + } + if (IsMarkOccurrencesEnabled()) { + // clear marks only, if selection changed + if (iUpd & SC_UPDATE_SELECTION) + { + if (!SciCall_IsSelectionEmpty() || Settings.MarkOccurrencesCurrentWord) { + MarkAllOccurrences(Settings2.UpdateDelayMarkAllOccurrences, true); + } + else { + EditClearAllOccurrenceMarkers(Globals.hwndEdit); + } + } + 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(Settings2.UpdateDelayMarkAllCoccurrences, false); + //~~~UpdateVisibleUrlIndics(); + } + } + UpdateToolbar(); + UpdateStatusbar(false); + } + else if (iUpd & SC_UPDATE_V_SCROLL) + { + if (IsMarkOccurrencesEnabled() && Settings.MarkOccurrencesMatchVisible) { + MarkAllOccurrences(Settings2.UpdateDelayMarkAllOccurrences, false); + } + } + if (Settings.HyperlinkHotspot) { + UpdateVisibleUrlIndics(); + } + } + break; + + case SCN_DWELLSTART: + case SCN_DWELLEND: + { + HandleDWellStartEnd(scn->position, pnmh->code); + } + break; + + case SCN_INDICATORCLICK: + { + _s_indic_click_modifiers = scn->modifiers; + } + break; + + case SCN_INDICATORRELEASE: + { + if (_s_indic_click_modifiers & SCMOD_CTRL) { + // open in browser + HandleHotSpotURL(scn->position, OPEN_WITH_BROWSER); + } + else if (_s_indic_click_modifiers & SCMOD_ALT) { + // open in application, if applicable (file://) + HandleHotSpotURL(scn->position, OPEN_WITH_NOTEPAD3); + } + _s_indic_click_modifiers = 0; + } + break; + + case SCN_CHARADDED: + { + int const ich = scn->ch; + + if (Globals.CallTipType != CT_NONE) { + CancelCallTip(); + } + + switch (ich) { + case '\r': + case '\n': + if (Settings.AutoIndent) { _HandleAutoIndent(ich); } + break; + case '>': + if (Settings.AutoCloseTags) { _HandleAutoCloseTags(); } + break; + case '?': + _HandleTinyExpr(); + break; + default: + break; + } + + if ((Settings.AutoCompleteWords || Settings.AutoCLexerKeyWords)) + { + if (!EditAutoCompleteWord(Globals.hwndEdit, false)) { return 0; } + } + } + break; + + case SCN_AUTOCCHARDELETED: + if ((Settings.AutoCompleteWords || Settings.AutoCLexerKeyWords)) + { + if (!EditAutoCompleteWord(Globals.hwndEdit, false)) { return 0; } + } + break; + + case SCN_NEEDSHOWN: + { + DocLn const iFirstLine = SciCall_LineFromPosition((DocPos)scn->position); + DocLn const iLastLine = SciCall_LineFromPosition((DocPos)(scn->position + scn->length - 1)); + for (DocLn i = iFirstLine; i <= iLastLine; ++i) { SciCall_EnsureVisible(i); } + } + break; + + case SCN_MARGINCLICK: + if (scn->margin == MARGIN_SCI_FOLDING) { + EditFoldClick(SciCall_LineFromPosition((DocPos)scn->position), scn->modifiers); + } + break; + + // ~~~ Not used in Windows ~~~ + // see: CMD_ALTUP / CMD_ALTDOWN + //case SCN_KEY: + // // Also see the corresponding patch in scintilla\src\Editor.cxx + // FoldAltArrow(scn->ch, scn->modifiers); + // break; + + + case SCN_SAVEPOINTREACHED: + _SetSaveNeededFlag(false); + break; + + + case SCN_SAVEPOINTLEFT: + _SetSaveNeededFlag(true); + break; + + + case SCN_ZOOM: + UpdateMarginWidth(); + break; + + case SCN_URIDROPPED: + { + // see WM_DROPFILES + WCHAR szBuf[MAX_PATH + 40]; + if (MultiByteToWideChar(CP_UTF8, 0, scn->text, -1, szBuf, COUNTOF(szBuf)) > 0) + { + if (IsIconic(hwnd)) { + ShowWindow(hwnd, SW_RESTORE); + } + //SetForegroundWindow(hwnd); + if (PathIsDirectory(szBuf)) { + WCHAR tchFile[MAX_PATH]; + if (OpenFileDlg(Globals.hwndMain, tchFile, COUNTOF(tchFile), szBuf)) { + FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchFile); + } + } + else if (PathFileExists(szBuf)) { + FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, szBuf); + } + } + } + break; + + default: + return 0; + } + return -1LL; +} + + + + //============================================================================= // // MsgNotify() - Handles WM_NOTIFY @@ -6512,279 +6942,18 @@ LRESULT MsgNotify(HWND hwnd, WPARAM wParam, LPARAM lParam) { UNUSED(wParam); - LPNMHDR pnmh = (LPNMHDR)lParam; - struct SCNotification* scn = (struct SCNotification*)lParam; + LPNMHDR const pnmh = (LPNMHDR)lParam; + const SCNotification* const scn = (SCNotification*)lParam; if (!CheckNotifyChangeEvent()) { - // --- check only mandatory events (must be fast !!!) --- - if (pnmh->idFrom == IDC_EDIT) { - if (pnmh->code == 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 (!SciCall_IsSelectionEmpty() && !_InUndoRedoTransaction()) - _SaveRedoSelection(_SaveUndoSelection()); - } - bModified = false; // not yet - } - // check for ADDUNDOACTION step - if (iModType & SC_MOD_CONTAINER) - { - if (iModType & SC_PERFORMED_UNDO) { - RestoreAction(scn->token, UNDO); - } - else if (iModType & SC_PERFORMED_REDO) { - RestoreAction(scn->token, REDO); - } - } - if (bModified) { _SetSaveNeededFlag(true); } - } - else if (pnmh->code == SCN_SAVEPOINTREACHED) { - _SetSaveNeededFlag(false); - } - else if (pnmh->code == SCN_SAVEPOINTLEFT) { - _SetSaveNeededFlag(true); - } - else if (pnmh->code == SCN_MODIFYATTEMPTRO) { - if (FocusedView.HideNonMatchedLines) { EditToggleView(Globals.hwndEdit); } - } - } - return TRUE; + return _MsgNotifyLean(pnmh, scn); } - // --- check ALL events --- - switch(pnmh->idFrom) { - static int _s_indic_click_modifiers = 0; - case IDC_EDIT: - switch (pnmh->code) - { - case SCN_HOTSPOTCLICK: - case SCN_HOTSPOTDOUBLECLICK: - case SCN_HOTSPOTRELEASECLICK: - case SCN_CALLTIPCLICK: - return FALSE; - - case SCN_MODIFIED: - { - int const iModType = scn->modificationType; - bool bModified = true; - if ((iModType & SC_MOD_BEFOREINSERT) || ((iModType & SC_MOD_BEFOREDELETE))) { - if (!((iModType & SC_PERFORMED_UNDO) || (iModType & SC_PERFORMED_REDO))) { - if (!SciCall_IsSelectionEmpty() && !_InUndoRedoTransaction()) - _SaveRedoSelection(_SaveUndoSelection()); - } - bModified = false; // not yet - } - if (iModType & SC_MOD_CONTAINER) { - if (iModType & SC_PERFORMED_UNDO) { - RestoreAction(scn->token, UNDO); - } - else if (iModType & SC_PERFORMED_REDO) { - RestoreAction(scn->token, REDO); - } - } - if (bModified) { - if (IsMarkOccurrencesEnabled()) { - MarkAllOccurrences(Settings2.UpdateDelayMarkAllOccurrences, true); - } - if (Settings.HyperlinkHotspot) { - UpdateVisibleUrlIndics(); - } - if (scn->linesAdded != 0) { - UpdateMarginWidth(); - } - _SetSaveNeededFlag(true); - } - } - break; - - case SCN_STYLENEEDED: // this event needs SCI_SETLEXER(SCLEX_CONTAINER) - { - EditFinalizeStyling(Globals.hwndEdit, scn->position); - } - break; - - case SCN_UPDATEUI: - { - int const iUpd = scn->updated; - //if (scn->updated & SC_UPDATE_NP3_INTERNAL_NOTIFY) { - // // special case - //} - //else - - if (iUpd & (SC_UPDATE_SELECTION | SC_UPDATE_CONTENT)) - { - // Brace Match - if (Settings.MatchBraces) { - EditMatchBrace(Globals.hwndEdit); - } - if (IsMarkOccurrencesEnabled()) { - // clear marks only, if selection changed - if (iUpd & SC_UPDATE_SELECTION) - { - if (!SciCall_IsSelectionEmpty() || Settings.MarkOccurrencesCurrentWord) { - MarkAllOccurrences(Settings2.UpdateDelayMarkAllOccurrences, true); - } - else { - EditClearAllOccurrenceMarkers(Globals.hwndEdit); - } - } - 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(Settings2.UpdateDelayMarkAllCoccurrences, false); - //~~~UpdateVisibleUrlIndics(); - } - } - UpdateToolbar(); - UpdateStatusbar(false); - } - else if (iUpd & SC_UPDATE_V_SCROLL) - { - if (IsMarkOccurrencesEnabled() && Settings.MarkOccurrencesMatchVisible) { - MarkAllOccurrences(Settings2.UpdateDelayMarkAllOccurrences, false); - } - } - if (Settings.HyperlinkHotspot) { - UpdateVisibleUrlIndics(); - } - } - break; - - case SCN_DWELLSTART: - case SCN_DWELLEND: - { - HandleDWellStartEnd(scn->position, pnmh->code); - } - break; - - case SCN_INDICATORCLICK: - { - _s_indic_click_modifiers = scn->modifiers; - } - break; - - case SCN_INDICATORRELEASE: - { - if (_s_indic_click_modifiers & SCMOD_CTRL) { - // open in browser - HandleHotSpotURL(scn->position, OPEN_WITH_BROWSER); - } - else if (_s_indic_click_modifiers & SCMOD_ALT) { - // open in application, if applicable (file://) - HandleHotSpotURL(scn->position, OPEN_WITH_NOTEPAD3); - } - _s_indic_click_modifiers = 0; - } - break; - - case SCN_CHARADDED: - { - int const ich = scn->ch; - - if (Globals.CallTipType != CT_NONE) { - CancelCallTip(); - } - - switch (ich) { - case '\r': - case '\n': - if (Settings.AutoIndent) { _HandleAutoIndent(ich); } - break; - case '>': - if (Settings.AutoCloseTags) { _HandleAutoCloseTags(); } - break; - case '?': - _HandleTinyExpr(); - break; - default: - break; - } - - if ((Settings.AutoCompleteWords || Settings.AutoCLexerKeyWords)) - { - if (!EditAutoCompleteWord(Globals.hwndEdit, false)) { return 0; } - } - } - break; - - case SCN_AUTOCCHARDELETED: - if ((Settings.AutoCompleteWords || Settings.AutoCLexerKeyWords)) - { - if (!EditAutoCompleteWord(Globals.hwndEdit, false)) { return 0; } - } - break; - - case SCN_NEEDSHOWN: - { - DocLn iFirstLine = SciCall_LineFromPosition((DocPos)scn->position); - DocLn iLastLine = SciCall_LineFromPosition((DocPos)(scn->position + scn->length - 1)); - for (DocLn i = iFirstLine; i <= iLastLine; ++i) { SciCall_EnsureVisible(i); } - } - break; - - - case SCN_MARGINCLICK: - if (scn->margin == MARGIN_SCI_FOLDING) { - EditFoldClick(SciCall_LineFromPosition((DocPos)scn->position), scn->modifiers); - } - break; - - - // ~~~ Not used in Windows ~~~ - // see: CMD_ALTUP / CMD_ALTDOWN - //case SCN_KEY: - // // Also see the corresponding patch in scintilla\src\Editor.cxx - // FoldAltArrow(scn->ch, scn->modifiers); - // break; - - - case SCN_SAVEPOINTREACHED: - _SetSaveNeededFlag(false); - break; - - - case SCN_SAVEPOINTLEFT: - _SetSaveNeededFlag(true); - break; - - - case SCN_ZOOM: - UpdateMarginWidth(); - break; - - case SCN_URIDROPPED: - { - // see WM_DROPFILES - WCHAR szBuf[MAX_PATH + 40]; - if (MultiByteToWideChar(CP_UTF8, 0, scn->text, -1, szBuf, COUNTOF(szBuf)) > 0) - { - if (IsIconic(hwnd)) { - ShowWindow(hwnd, SW_RESTORE); - } - //SetForegroundWindow(hwnd); - if (PathIsDirectory(szBuf)) { - WCHAR tchFile[MAX_PATH]; - if (OpenFileDlg(Globals.hwndMain, tchFile, COUNTOF(tchFile), szBuf)) { - FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchFile); - } - } - else if (PathFileExists(szBuf)) { - FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, szBuf); - } - } - } - break; - - default: - return FALSE; - } - return -1LL; + return _MsgNotifyFromEdit(hwnd, pnmh, scn); // ------------------------------------------------------------------------ @@ -6926,13 +7095,16 @@ LRESULT MsgNotify(HWND hwnd, WPARAM wParam, LPARAM lParam) default: switch(pnmh->code) { + // ToolTip case TTN_NEEDTEXT: { if (!(((LPTOOLTIPTEXT)lParam)->uFlags & TTF_IDISHWND)) { - WCHAR tch[MIDSZ_BUFFER] = { L'\0' }; + WCHAR tch[SMALL_BUFFER] = { L'\0' }; GetLngString((UINT)pnmh->idFrom,tch,COUNTOF(tch)); - StringCchCopyN(((LPTOOLTIPTEXT)lParam)->szText,COUNTOF(((LPTOOLTIPTEXT)lParam)->szText),tch,COUNTOF(((LPTOOLTIPTEXT)lParam)->szText)); + WCHAR* pttText = ((LPTOOLTIPTEXT)lParam)->szText; + size_t const ttLen = COUNTOF(((LPTOOLTIPTEXT)lParam)->szText); + StringCchCopyN(pttText, ttLen, tch,COUNTOF(tch)); } } break; @@ -8716,10 +8888,10 @@ static void _CalculateStatusbarSections(int vSectionWidth[], sectionTxt_t tchSt //============================================================================= // -// _InterpRectSelTinyExpr() +// _InterpMultiSelectionTinyExpr() // // -static double _InterpRectSelTinyExpr(int* piExprError) +static double _InterpMultiSelectionTinyExpr(int* piExprError) { #define _tmpBufCnt 128 char tmpRectSelN[_tmpBufCnt] = { '\0' }; @@ -8781,7 +8953,7 @@ static void _UpdateStatusbarDelayed(bool bForceRedraw) DocPos const iSelEnd = SciCall_GetSelectionEnd(); bool const bIsSelectionEmpty = SciCall_IsSelectionEmpty(); - bool const bIsSelCountable = !(bIsSelectionEmpty || SciCall_IsSelectionRectangle()); + bool const bIsSelCharCountable = !(bIsSelectionEmpty || Sci_IsMultiOrRectangleSelection()); bool bIsUpdateNeeded = bForceRedraw; @@ -8889,10 +9061,10 @@ static void _UpdateStatusbarDelayed(bool bForceRedraw) static DocPos s_iSelStart = -1; static DocPos s_iSelEnd = -1; - if (bForceRedraw || ((s_bIsSelCountable != bIsSelCountable) || (s_iSelStart != iSelStart) || (s_iSelEnd != iSelEnd))) + if (bForceRedraw || ((s_bIsSelCountable != bIsSelCharCountable) || (s_iSelStart != iSelStart) || (s_iSelEnd != iSelEnd))) { static WCHAR tchSelB[64] = { L'\0' }; - if (bIsSelCountable) + if (bIsSelCharCountable) { const DocPos iSel = (DocPos)SendMessage(Globals.hwndEdit, SCI_COUNTCHARACTERS, iSelStart, iSelEnd); StringCchPrintf(tchSel, COUNTOF(tchSel), DOCPOSFMTW, iSel); @@ -8909,7 +9081,7 @@ static void _UpdateStatusbarDelayed(bool bForceRedraw) StringCchPrintf(tchStatusBar[STATUS_SELCTBYTES], txtWidth, L"%s%s%s", s_mxSBPrefix[STATUS_SELCTBYTES], tchSelB, s_mxSBPostfix[STATUS_SELCTBYTES]); - s_bIsSelCountable = bIsSelCountable; + s_bIsSelCountable = bIsSelCharCountable; s_iSelStart = iSelStart; s_iSelEnd = iSelEnd; bIsUpdateNeeded = true; @@ -8961,7 +9133,7 @@ static void _UpdateStatusbarDelayed(bool bForceRedraw) tchExpression[1] = L'-'; tchExpression[2] = L'\0'; - if (bIsSelCountable) + if (bIsSelCharCountable) { DocPos const iSelSize = SciCall_GetSelText(NULL); if (iSelSize < 2048) // should be fast ! @@ -8979,9 +9151,9 @@ static void _UpdateStatusbarDelayed(bool bForceRedraw) s_iExprError = -1; } } - else if (SciCall_IsSelectionRectangle() && !bIsSelectionEmpty) + else if (Sci_IsMultiOrRectangleSelection() && !bIsSelectionEmpty) { - s_dExpression = _InterpRectSelTinyExpr(&s_iExprError); + s_dExpression = _InterpMultiSelectionTinyExpr(&s_iExprError); } else s_iExprError = -2; @@ -9372,35 +9544,85 @@ void UndoRedoRecordingStop() static int _SaveUndoSelection() { UndoRedoSelection_t sel = INIT_UNDOREDOSEL; - sel.selMode_undo = (int)SendMessage(Globals.hwndEdit, SCI_GETSELECTIONMODE, 0, 0); + CopyUndoRedoSelection(&sel, NULL); // init + UndoRedoSelection_t* pSel = &sel; - switch (sel.selMode_undo) - { - case SC_SEL_RECTANGLE: - case SC_SEL_THIN: - sel.anchorPos_undo = (DocPos)SendMessage(Globals.hwndEdit, SCI_GETRECTANGULARSELECTIONANCHOR, 0, 0); - sel.curPos_undo = (DocPos)SendMessage(Globals.hwndEdit, SCI_GETRECTANGULARSELECTIONCARET, 0, 0); - if (!Settings2.DenyVirtualSpaceAccess) { - sel.anchorVS_undo = (DocPos)SendMessage(Globals.hwndEdit, SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE, 0, 0); - sel.curVS_undo = (DocPos)SendMessage(Globals.hwndEdit, SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE, 0, 0); + if (pSel) { + pSel->selMode_undo = (Sci_IsMultiSelection() && !SciCall_IsSelectionRectangle()) ? + NP3_SEL_MULTI : + (int)SendMessage(Globals.hwndEdit, SCI_GETSELECTIONMODE, 0, 0); + + switch (pSel->selMode_undo) + { + case NP3_SEL_MULTI: + { + DocPosU const selCount = SciCall_GetSelections(); + for (DocPosU i = 0; i < selCount; ++i) { + DocPos const anchorPos = SciCall_GetSelectionNAnchor(i); + utarray_push_back(pSel->anchorPos_undo, &anchorPos); + DocPos const curPos = SciCall_GetSelectionNCaret(i); + utarray_push_back(pSel->curPos_undo, &curPos); + if (!Settings2.DenyVirtualSpaceAccess) { + DocPos const anchorVS = SciCall_GetSelectionNAnchorVirtualSpace(i); + utarray_push_back(pSel->anchorVS_undo, &anchorVS); + DocPos const curVS = SciCall_GetSelectionNCaretVirtualSpace(i); + utarray_push_back(pSel->curVS_undo, &curVS); + } + else { + DocPos const anchorVS = (DocPos)-1; + utarray_push_back(pSel->anchorVS_redo, &anchorVS); + DocPos const curVS = (DocPos)-1; + utarray_push_back(pSel->curVS_redo, &curVS); + } + } + } + break; + + case SC_SEL_RECTANGLE: + case SC_SEL_THIN: + { + DocPos const anchorPos = SciCall_GetRectangularSelectionAnchor(); + utarray_push_back(pSel->anchorPos_undo, &anchorPos); + DocPos const curPos = SciCall_GetRectangularSelectionCaret(); + utarray_push_back(pSel->curPos_undo, &curPos); + if (!Settings2.DenyVirtualSpaceAccess) { + DocPos const anchorVS = SciCall_GetRectangularSelectionAnchorVirtualSpace(); + utarray_push_back(pSel->anchorVS_undo, &anchorVS); + DocPos const curVS = SciCall_GetRectangularSelectionCaretVirtualSpace(); + utarray_push_back(pSel->curVS_undo, &curVS); + } + else { + DocPos const anchorVS = (DocPos)-1; + utarray_push_back(pSel->anchorVS_redo, &anchorVS); + DocPos const curVS = (DocPos)-1; + utarray_push_back(pSel->curVS_redo, &curVS); + } + } + break; + + case SC_SEL_LINES: + case SC_SEL_STREAM: + default: + { + DocPos const anchorPos = SciCall_GetAnchor(); + utarray_push_back(pSel->anchorPos_undo, &anchorPos); + DocPos const curPos = SciCall_GetCurrentPos(); + utarray_push_back(pSel->curPos_undo, &curPos); + DocPos const dummy = (DocPos)-1; + utarray_push_back(pSel->anchorVS_undo, &dummy); + utarray_push_back(pSel->curVS_undo, &dummy); + } + break; } - break; - case SC_SEL_LINES: - case SC_SEL_STREAM: - default: - sel.anchorPos_undo = (DocPos)SendMessage(Globals.hwndEdit, SCI_GETANCHOR, 0, 0); - sel.curPos_undo = (DocPos)SendMessage(Globals.hwndEdit, SCI_GETCURRENTPOS, 0, 0); - break; + int const token = _UndoRedoActionMap(-1, &pSel); + + if (token >= 0) { + SciCall_AddUndoAction(token, 0); + } + return token; } - - int const token = _UndoRedoActionMap(-1, &sel); - - if (token >= 0) { - SciCall_AddUndoAction(token, 0); - } - - return token; + return -1; } @@ -9412,32 +9634,74 @@ static int _SaveUndoSelection() static void _SaveRedoSelection(int token) { if (token >= 0) { - UndoRedoSelection_t sel = INIT_UNDOREDOSEL; + UndoRedoSelection_t* pSel = NULL; - if (_UndoRedoActionMap(token, &sel) >= 0) + if ((_UndoRedoActionMap(token, &pSel) >= 0) && (pSel != NULL)) { - sel.selMode_redo = (int)SendMessage(Globals.hwndEdit, SCI_GETSELECTIONMODE, 0, 0); + pSel->selMode_redo = (Sci_IsMultiSelection() && !SciCall_IsSelectionRectangle())? NP3_SEL_MULTI : SciCall_GetSelectionMode(); - switch (sel.selMode_redo) + switch (pSel->selMode_redo) { - case SC_SEL_RECTANGLE: - case SC_SEL_THIN: - sel.anchorPos_redo = (DocPos)SendMessage(Globals.hwndEdit, SCI_GETRECTANGULARSELECTIONANCHOR, 0, 0); - sel.curPos_redo = (DocPos)SendMessage(Globals.hwndEdit, SCI_GETRECTANGULARSELECTIONCARET, 0, 0); - if (!Settings2.DenyVirtualSpaceAccess) { - sel.anchorVS_redo = (DocPos)SendMessage(Globals.hwndEdit, SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE, 0, 0); + case NP3_SEL_MULTI: + { + DocPosU const selCount = SciCall_GetSelections(); + for (DocPosU i = 0; i < selCount; ++i) { + DocPos const anchorPos = SciCall_GetSelectionNAnchor(i); + utarray_push_back(pSel->anchorPos_redo, &anchorPos); + DocPos const curPos = SciCall_GetSelectionNCaret(i); + utarray_push_back(pSel->curPos_redo, &curPos); + if (!Settings2.DenyVirtualSpaceAccess) { + DocPos const anchorVS = SciCall_GetSelectionNAnchorVirtualSpace(i); + utarray_push_back(pSel->anchorVS_redo, &anchorVS); + DocPos const curVS = SciCall_GetSelectionNCaretVirtualSpace(i); + utarray_push_back(pSel->curVS_redo, &curVS); + } + else { + DocPos const anchorVS = (DocPos)-1; + utarray_push_back(pSel->anchorVS_redo, &anchorVS); + DocPos const curVS = (DocPos)-1; + utarray_push_back(pSel->curVS_redo, &curVS); + } + } } break; - case SC_SEL_LINES: - case SC_SEL_STREAM: - default: - sel.anchorPos_redo = (DocPos)SendMessage(Globals.hwndEdit, SCI_GETANCHOR, 0, 0); - sel.curPos_redo = (DocPos)SendMessage(Globals.hwndEdit, SCI_GETCURRENTPOS, 0, 0); + case SC_SEL_RECTANGLE: + case SC_SEL_THIN: + { + DocPos const anchorPos = SciCall_GetRectangularSelectionAnchor(); + utarray_push_back(pSel->anchorPos_redo, &anchorPos); + DocPos const curPos = SciCall_GetRectangularSelectionCaret(); + utarray_push_back(pSel->curPos_redo, &curPos); + if (!Settings2.DenyVirtualSpaceAccess) { + DocPos const anchorVS = SciCall_GetRectangularSelectionAnchorVirtualSpace(); + utarray_push_back(pSel->anchorVS_redo, &anchorVS); + DocPos const curVS = SciCall_GetRectangularSelectionCaretVirtualSpace(); + utarray_push_back(pSel->curVS_redo, &curVS); + } + else { + DocPos const anchorVS = (DocPos)-1; + utarray_push_back(pSel->anchorVS_redo, &anchorVS); + DocPos const curVS = (DocPos)-1; + utarray_push_back(pSel->curVS_redo, &curVS); + } + } + break; + + case SC_SEL_LINES: + case SC_SEL_STREAM: + default: + { + DocPos const anchorPos = SciCall_GetAnchor(); + utarray_push_back(pSel->anchorPos_redo, &anchorPos); + DocPos const curPos = SciCall_GetCurrentPos(); + utarray_push_back(pSel->curPos_redo, &curPos); + DocPos const dummy = (DocPos)-1; + utarray_push_back(pSel->anchorVS_redo, &dummy); + utarray_push_back(pSel->curVS_redo, &dummy); + } break; } - - _UndoRedoActionMap(token, &sel); // set with redo action filled } } } @@ -9485,69 +9749,98 @@ void RestoreAction(int token, DoAction doAct) { if (_InUndoRedoTransaction()) { return; } - UndoRedoSelection_t sel = INIT_UNDOREDOSEL; + UndoRedoSelection_t* pSel = NULL; - if (_UndoRedoActionMap(token, &sel) >= 0) + if ((_UndoRedoActionMap(token, &pSel) >= 0) && (pSel != NULL)) { // we are inside undo/redo transaction, so do delayed PostMessage() instead of SendMessage() HWND const hwndedit = Globals.hwndEdit; - DocPos const _anchorPos = (doAct == UNDO ? sel.anchorPos_undo : sel.anchorPos_redo); - DocPos const _curPos = (doAct == UNDO ? sel.curPos_undo : sel.curPos_redo); + PostMessage(hwndedit, SCI_SETEMPTYSELECTION, 0, 0); - // Ensure that the first and last lines of a selection are always unfolded - // This needs to be done _before_ the SCI_SETSEL message - DocLn const anchorPosLine = SciCall_LineFromPosition(_anchorPos); - DocLn const currPosLine = SciCall_LineFromPosition(_curPos); - PostMessage(hwndedit, SCI_ENSUREVISIBLE, anchorPosLine, 0); - if (anchorPosLine != currPosLine) { PostMessage(hwndedit, SCI_ENSUREVISIBLE, currPosLine, 0); } + DocPos* pPosAnchor = NULL; + DocPos* pPosCur = NULL; + DocPos* pPosAnchorVS = NULL; + DocPos* pPosCurVS = NULL; + pPosAnchor = (DocPos*)((UNDO == doAct) ? utarray_next(pSel->anchorPos_undo, pPosAnchor) : utarray_next(pSel->anchorPos_redo, pPosAnchor)); + pPosCur = (DocPos*)((UNDO == doAct) ? utarray_next(pSel->curPos_undo, pPosCur) : utarray_next(pSel->curPos_redo, pPosCur)); + pPosAnchorVS = (DocPos*)((UNDO == doAct) ? utarray_next(pSel->anchorVS_undo, pPosAnchorVS) : utarray_next(pSel->anchorVS_redo, pPosAnchorVS)); + pPosCurVS = (DocPos*)((UNDO == doAct) ? utarray_next(pSel->curVS_undo, pPosCurVS) : utarray_next(pSel->curVS_redo, pPosCurVS)); + if (pPosAnchor && pPosCur) { + // Ensure that the first and last lines of a selection are always unfolded + // This needs to be done _before_ the SCI_SETSEL message + DocLn const anchorPosLine = SciCall_LineFromPosition((*pPosAnchor)); + DocLn const currPosLine = SciCall_LineFromPosition((*pPosCur)); + PostMessage(hwndedit, SCI_ENSUREVISIBLE, anchorPosLine, 0); + if (anchorPosLine != currPosLine) { PostMessage(hwndedit, SCI_ENSUREVISIBLE, currPosLine, 0); } - int const selectionMode = (doAct == UNDO ? sel.selMode_undo : sel.selMode_redo); - PostMessage(hwndedit, SCI_SETSELECTIONMODE, (WPARAM)selectionMode, 0); + int const selectionMode = (UNDO == doAct) ? pSel->selMode_undo : pSel->selMode_redo; - // independent from selection mode - PostMessage(hwndedit, SCI_SETANCHOR, (WPARAM)_anchorPos, 0); - PostMessage(hwndedit, SCI_SETCURRENTPOS, (WPARAM)_curPos, 0); - - switch (selectionMode) - { - case SC_SEL_RECTANGLE: - PostMessage(hwndedit, SCI_SETRECTANGULARSELECTIONANCHOR, (WPARAM)_anchorPos, 0); - PostMessage(hwndedit, SCI_SETRECTANGULARSELECTIONCARET, (WPARAM)_curPos, 0); - // fall-through - - case SC_SEL_THIN: + if (selectionMode != NP3_SEL_MULTI) { - 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)) { - PostMessage(hwndedit, SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE, (WPARAM)anchorVS, 0); - PostMessage(hwndedit, SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE, (WPARAM)currVS, 0); - } + PostMessage(hwndedit, SCI_SETSELECTIONMODE, (WPARAM)selectionMode, 0); + } + else { + PostMessage(hwndedit, SCI_CANCEL, 0, 0); } - break; - case SC_SEL_LINES: - case SC_SEL_STREAM: - default: - // nothing to do here - break; + switch (selectionMode) + { + case NP3_SEL_MULTI: + { +#if 0 // §§§ @@@ + int const selCount = utarray_len(pSel->anchorPos_undo); + int i = 0; + while (i < selCount) + { + PostMessage(hwndedit, SCI_SETSELECTIONNANCHOR, (WPARAM)i, (LPARAM)(*pPosAnchor)); + PostMessage(hwndedit, SCI_SETSELECTIONNCARET, (WPARAM)i, (LPARAM)(*pPosCur)); + if (((*pPosAnchorVS) >= 0) && ((*pPosCurVS) >= 0)) { + PostMessage(hwndedit, SCI_SETSELECTIONNANCHORVIRTUALSPACE, (WPARAM)i, (LPARAM)(*pPosAnchorVS)); + PostMessage(hwndedit, SCI_SETSELECTIONNCARETVIRTUALSPACE, (WPARAM)i, (LPARAM)(*pPosCurVS)); + } + ++i; + } +#endif + } + break; + + case SC_SEL_RECTANGLE: + PostMessage(Globals.hwndEdit, SCI_SETRECTANGULARSELECTIONANCHOR, (WPARAM)(*pPosAnchor), 0); + PostMessage(Globals.hwndEdit, SCI_SETRECTANGULARSELECTIONCARET, (WPARAM)(*pPosCur), 0); + // fall-through + case SC_SEL_THIN: + { + if (((*pPosAnchorVS) >= 0) && ((*pPosCurVS) >= 0)) { + PostMessage(hwndedit, SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE, (WPARAM)(*pPosAnchorVS), 0); + PostMessage(hwndedit, SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE, (WPARAM)(*pPosCurVS), 0); + } + } + break; + + case SC_SEL_LINES: + case SC_SEL_STREAM: + default: + PostMessage(hwndedit, SCI_SETANCHOR, (WPARAM)* pPosAnchor, 0); + PostMessage(hwndedit, SCI_SETCURRENTPOS, (WPARAM)* pPosCur, 0); + break; + } } + PostMessage(hwndedit, SCI_SCROLLCARET, 0, 0); PostMessage(hwndedit, SCI_CHOOSECARETX, 0, 0); PostMessage(hwndedit, SCI_CANCEL, 0, 0); - } } //============================================================================= // -// _UndoSelectionMap() +// _UndoRedoActionMap() // // -static int _UndoRedoActionMap(int token, UndoRedoSelection_t* selection) +static int _UndoRedoActionMap(int token, UndoRedoSelection_t** selection) { if (UndoRedoSelectionUTArray == NULL) { return -1; } @@ -9572,20 +9865,21 @@ static int _UndoRedoActionMap(int token, UndoRedoSelection_t* selection) // get or set map item request ? if ((token >= 0) && (utoken < uiTokenCnt)) { - if (selection->anchorPos_undo < 0) { + if ((*selection) == NULL) { // this is a get request - *selection = *(UndoRedoSelection_t*)utarray_eltptr(UndoRedoSelectionUTArray, utoken); + (*selection) = (UndoRedoSelection_t*)utarray_eltptr(UndoRedoSelectionUTArray, utoken); } else { - // this is a set request (fill redo pos) - utarray_insert(UndoRedoSelectionUTArray, (void*)selection, utoken); + // this is a set request (filled redo pos) + // is done in place, so: + assert(false); //§§§ should not occur } // don't clear map item here (token used in redo/undo again) } else if (token < 0) { // set map new item request token = (int)uiTokenCnt; - utarray_insert(UndoRedoSelectionUTArray, (void*)selection, uiTokenCnt); + utarray_insert(UndoRedoSelectionUTArray, (void*)(*selection), uiTokenCnt); uiTokenCnt = (uiTokenCnt < (unsigned int)INT_MAX) ? (uiTokenCnt + 1U) : 0U; // round robin next } return token; diff --git a/src/Notepad3.h b/src/Notepad3.h index c331079ee..d48657104 100644 --- a/src/Notepad3.h +++ b/src/Notepad3.h @@ -18,6 +18,7 @@ #include "TypeDefs.h" #include "SciCall.h" +#include "../uthash/utarray.h" //==== Main Window ============================================================ @@ -44,24 +45,28 @@ typedef struct np3params { np3params, *LPnp3params; +#pragma pack(push, 1) typedef struct _undoSel { int selMode_undo; - DocPos anchorPos_undo; - DocPos curPos_undo; - DocPos anchorVS_undo; - DocPos curVS_undo; + UT_array* anchorPos_undo; + UT_array* curPos_undo; + UT_array* anchorVS_undo; + UT_array* curVS_undo; int selMode_redo; - DocPos anchorPos_redo; - DocPos curPos_redo; - DocPos anchorVS_redo; - DocPos curVS_redo; + UT_array* anchorPos_redo; + UT_array* curPos_redo; + UT_array* anchorVS_redo; + UT_array* curVS_redo; } UndoRedoSelection_t; +#pragma pack(pop) -#define INIT_UNDOREDOSEL { SC_SEL_STREAM, (DocPos)-1, (DocPos)-1, 0, 0, SC_SEL_STREAM, (DocPos)-1, (DocPos)-1, 0, 0 } +//#define INIT_UNDOREDOSEL { SC_SEL_STREAM, (DocPos)-1, (DocPos)-1, 0, 0, SC_SEL_STREAM, (DocPos)-1, (DocPos)-1, 0, 0 } +#define INIT_UNDOREDOSEL { SC_SEL_STREAM, NULL, NULL, NULL, NULL, SC_SEL_STREAM, NULL, NULL, NULL, NULL } +#define NP3_SEL_MULTI (SC_SEL_RECTANGLE + SC_SEL_LINES + SC_SEL_THIN) typedef enum { UNDO = true, diff --git a/src/SciCall.h b/src/SciCall.h index 51e269a61..3c2b4a8ca 100644 --- a/src/SciCall.h +++ b/src/SciCall.h @@ -518,6 +518,8 @@ DeclareSciCallR0(IsIMEModeCJK, ISIMEMODECJK, bool) // DeclareSciCallR0(IsSelectionEmpty, GETSELECTIONEMPTY, bool) DeclareSciCallR0(IsSelectionRectangle, SELECTIONISRECTANGLE, bool) +#define Sci_IsMultiSelection() (SciCall_GetSelections() > 1) +#define Sci_IsMultiOrRectangleSelection() (SciCall_IsSelectionRectangle() || Sci_IsMultiSelection()) #define Sci_IsSingleLineSelection() (SciCall_LineFromPosition(SciCall_GetSelectionEnd()) == SciCall_LineFromPosition(SciCall_GetSelectionStart())) #define Sci_IsMultiLineSelection() ((SciCall_LineFromPosition(SciCall_GetSelectionEnd()) - SciCall_LineFromPosition(SciCall_GetSelectionStart())) > 1)