From d1d9f2c8d58c80d63a4268a3ccc3693021bb3b89 Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Thu, 7 Sep 2017 11:06:14 +0200 Subject: [PATCH 1/7] + fixed: RegExpr "Find previous" corrected (find mode "left to right" has been used, which has not the intended behavior) --- scintilla/deelx/DeelxRegexSearch.cxx | 375 ++++++++++++++------------- 1 file changed, 192 insertions(+), 183 deletions(-) diff --git a/scintilla/deelx/DeelxRegexSearch.cxx b/scintilla/deelx/DeelxRegexSearch.cxx index 175e834ad..2a208f5cb 100644 --- a/scintilla/deelx/DeelxRegexSearch.cxx +++ b/scintilla/deelx/DeelxRegexSearch.cxx @@ -29,7 +29,7 @@ #pragma warning( push ) #pragma warning( disable : 4996 ) // Scintilla's "unsafe" use of std::copy() (SplitVector.h) -// // or use -D_SCL_SECURE_NO_WARNINGS preprocessor define + // // or use -D_SCL_SECURE_NO_WARNINGS preprocessor define #include "Platform.h" #include "Scintilla.h" @@ -54,52 +54,52 @@ class DeelxRegexSearch : public RegexSearchBase { public: - explicit DeelxRegexSearch(CharClassify* charClassTable) - : m_RegExpr() - , m_Match() - , m_MatchPos(-1) - , m_MatchLength(0) - , m_pContext(nullptr) - , m_SubstitutionBuffer(nullptr) - {} + explicit DeelxRegexSearch(CharClassify* charClassTable) + : m_RegExpr() + ,m_Match() + ,m_MatchPos(-1) + ,m_MatchLength(0) + ,m_pContext(nullptr) + ,m_SubstitutionBuffer(nullptr) + {} - virtual ~DeelxRegexSearch() - { - ReleaseSubstitutionBuffer(); - ReleaseContext(); - } + virtual ~DeelxRegexSearch() + { + ReleaseSubstitutionBuffer(); + ReleaseContext(); + } - virtual long FindText(Document* doc, int minPos, int maxPos, const char* pattern, - bool caseSensitive, bool word, bool wordStart, int flags, int* length) override; + virtual long FindText(Document* doc,int minPos,int maxPos,const char* pattern, + bool caseSensitive,bool word,bool wordStart,int flags,int* length) override; - virtual const char* SubstituteByPosition(Document* doc, const char* text, int* length) override; + virtual const char* SubstituteByPosition(Document* doc,const char* text,int* length) override; private: - inline void ReleaseContext() - { - if (m_pContext != nullptr) { - m_RegExpr.ReleaseContext(m_pContext); - m_pContext = nullptr; - } + inline void ReleaseContext() + { + if (m_pContext != nullptr) { + m_RegExpr.ReleaseContext(m_pContext); + m_pContext = nullptr; } + } - inline void ReleaseSubstitutionBuffer() - { - if (m_SubstitutionBuffer) { - m_RegExpr.ReleaseString(m_SubstitutionBuffer); - m_SubstitutionBuffer = nullptr; - } + inline void ReleaseSubstitutionBuffer() + { + if (m_SubstitutionBuffer) { + m_RegExpr.ReleaseString(m_SubstitutionBuffer); + m_SubstitutionBuffer = nullptr; } + } private: - deelx::CRegexpT m_RegExpr; - deelx::MatchResult m_Match; - deelx::index_t m_MatchPos; - deelx::index_t m_MatchLength; - deelx::CContext* m_pContext; - char* m_SubstitutionBuffer; + deelx::CRegexpT m_RegExpr; + deelx::MatchResult m_Match; + deelx::index_t m_MatchPos; + deelx::index_t m_MatchLength; + deelx::CContext* m_pContext; + char* m_SubstitutionBuffer; }; // ============================================================================ @@ -107,12 +107,12 @@ private: #ifdef SCI_NAMESPACE RegexSearchBase *Scintilla::CreateRegexSearch(CharClassify *charClassTable) { - return new DeelxRegexSearch(charClassTable); + return new DeelxRegexSearch(charClassTable); } #else RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable) { - return new DeelxRegexSearch(charClassTable); + return new DeelxRegexSearch(charClassTable); } #endif @@ -121,7 +121,7 @@ RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable) /** * forward declaration of utility functions */ -std::string& translateRegExpr(std::string& regExprStr, bool wholeWord, bool wordStart); +std::string& translateRegExpr(std::string& regExprStr,bool wholeWord,bool wordStart); std::string& convertReplExpr(std::string& replStr); @@ -133,83 +133,92 @@ std::string& convertReplExpr(std::string& replStr); * searches (just pass minPos > maxPos to do a backward search) * Has not been tested with backwards DBCS searches yet. */ -long DeelxRegexSearch::FindText(Document* doc, int minPos, int maxPos, const char *pattern, - bool caseSensitive, bool word, bool wordStart, int searchFlags, int *length) +long DeelxRegexSearch::FindText(Document* doc,int minPos,int maxPos,const char *pattern, + bool caseSensitive,bool word,bool wordStart,int searchFlags,int *length) { - int startPos, endPos; - bool left2right; + const bool right2left = false; // always left-to-right match mode + const bool extended = false; // ignore spaces and use '#' as line-comment) - if (minPos <= maxPos) { - left2right = true; - startPos = minPos; - endPos = maxPos; + // Range endpoints should not be inside DBCS characters, but just in case, move them. + minPos = doc->MovePositionOutsideChar(minPos,1,false); + maxPos = doc->MovePositionOutsideChar(maxPos,1,false); + const bool findprevious = (minPos > maxPos); + + + int compileFlags = deelx::NO_FLAG; + compileFlags |= (deelx::MULTILINE | deelx::GLOBAL); // the .(dot) does not match line-breaks + //compileFlags |= (deelx::SINGLELINE | deelx::MULTILINE | deelx::GLOBAL); // the .(dot) also matches line-breaks + compileFlags |= (extended) ? deelx::EXTENDED : deelx::NO_FLAG; + compileFlags |= (!caseSensitive) ? deelx::IGNORECASE : deelx::NO_FLAG; + compileFlags |= (right2left) ? deelx::RIGHTTOLEFT : deelx::NO_FLAG; + + std::string sRegExprStrg = translateRegExpr(std::string(pattern,*length),word,wordStart); + + try { + m_RegExpr.Compile(sRegExprStrg.c_str(),compileFlags); + } + catch (...) { + return -2; // -1 is normally used for not found, -2 is used here for invalid regex + } + + int rangeBegin = (findprevious) ? maxPos : minPos; + int rangeLength = abs(maxPos - minPos); + + ReleaseContext(); + m_pContext = m_RegExpr.PrepareMatch(doc->RangePointer(rangeBegin,rangeLength)); + + m_MatchPos = -1; // not found + m_MatchLength = 0; + + m_Match = m_RegExpr.Match(m_pContext); + + if (findprevious) // search previous + { + // search for last occurrence in range + while (m_Match.IsMatched() && (m_Match.GetStart() < rangeLength)) + { + m_MatchPos = rangeBegin + m_Match.GetStart(); + m_MatchLength = (m_Match.GetEnd() - m_Match.GetStart()); + + m_Match = m_RegExpr.Match(m_pContext); //next } - else { // backward search - left2right = false; - startPos = maxPos; - endPos = minPos; + } + else + { + if (m_Match.IsMatched() && (m_Match.GetStart() < rangeLength)) + { + m_MatchPos = rangeBegin + m_Match.GetStart(); + m_MatchLength = (m_Match.GetEnd() - m_Match.GetStart()); } + } - // Range endpoints should not be inside DBCS characters, but just in case, move them. - startPos = doc->MovePositionOutsideChar(startPos, 1, false); - endPos = doc->MovePositionOutsideChar(endPos, 1, false); - - //int compileFlags(deelx::SINGLELINE | deelx::MULTILINE | deelx::GLOBAL); // the .(dot) also matches line-breaks - int compileFlags(deelx::MULTILINE | deelx::GLOBAL); // the .(dot) does not match line-breaks - //compileFlags |= deelx::EXTENDED; // ignore spaces and use '#' as line-comment) - compileFlags |= (caseSensitive) ? deelx::NO_FLAG : deelx::IGNORECASE; - compileFlags |= (left2right) ? deelx::NO_FLAG : deelx::RIGHTTOLEFT; - - std::string sRegExprStrg = translateRegExpr(std::string(pattern, *length), word, wordStart); - - try { - m_RegExpr.Compile(sRegExprStrg.c_str(), compileFlags); - } - catch (...) { - return -2; // -1 is normally used for not found, -2 is used here for invalid regex - } - - int rangeLen = endPos - startPos; - int searchStartPos = left2right ? 0 : rangeLen; - ReleaseContext(); - m_pContext = m_RegExpr.PrepareMatch(doc->RangePointer(startPos, rangeLen), searchStartPos); - - m_Match = m_RegExpr.Match(m_pContext); - - m_MatchPos = -1; // not found - m_MatchLength = 0; - if (m_Match.IsMatched()) { - m_MatchPos = startPos + m_Match.GetStart(); - m_MatchLength = (m_Match.GetEnd() - m_Match.GetStart()); - } - - //NOTE: potential 64-bit-size issue at interface here: - *length = static_cast(m_MatchLength); - return static_cast(m_MatchPos); + //NOTE: potential 64-bit-size issue at interface here: + *length = static_cast(m_MatchLength); + return static_cast(m_MatchPos); } // ============================================================================ -const char* DeelxRegexSearch::SubstituteByPosition(Document* doc, const char* text, int* length) +const char* DeelxRegexSearch::SubstituteByPosition(Document* doc,const char* text,int* length) { - if (!m_Match.IsMatched() || (m_MatchPos < 0)) { - *length = 0; - return nullptr; - } - std::string sReplStrg = convertReplExpr(std::string(text, *length)); + if (!m_Match.IsMatched() || (m_MatchPos < 0)) { + *length = 0; + return nullptr; + } + std::string sReplStrg = convertReplExpr(std::string(text,*length)); - //NOTE: potential 64-bit-size issue at interface here: - const char* pString = doc->RangePointer(static_cast(m_MatchPos), static_cast(m_MatchLength)); + //NOTE: potential 64-bit-size issue at interface here: + const char* pString = doc->RangePointer(static_cast(m_MatchPos),static_cast(m_MatchLength)); - deelx::index_t resLength; - ReleaseSubstitutionBuffer(); - m_SubstitutionBuffer = m_RegExpr.Replace(pString, m_MatchLength, sReplStrg.c_str(), - static_cast(sReplStrg.length()), resLength); + deelx::index_t resLength; + ReleaseSubstitutionBuffer(); + m_SubstitutionBuffer = m_RegExpr.Replace(pString,m_MatchLength,sReplStrg.c_str(), + static_cast(sReplStrg.length()),resLength); - //NOTE: potential 64-bit-size issue at interface here: - *length = static_cast(resLength); + //NOTE: potential 64-bit-size issue at interface here: + *length = static_cast(resLength); - return m_SubstitutionBuffer; + return m_SubstitutionBuffer; } // ============================================================================ @@ -221,47 +230,47 @@ const char* DeelxRegexSearch::SubstituteByPosition(Document* doc, const char* te // ============================================================================ -void replaceAll(std::string& source, const std::string& from, const std::string& to) +void replaceAll(std::string& source,const std::string& from,const std::string& to) { - std::string newString; - newString.reserve(source.length() * 2); // avoids a few memory allocations + std::string newString; + newString.reserve(source.length() * 2); // avoids a few memory allocations - std::string::size_type lastPos = 0; - std::string::size_type findPos; + std::string::size_type lastPos = 0; + std::string::size_type findPos; - while (std::string::npos != (findPos = source.find(from, lastPos))) { - newString.append(source, lastPos, findPos - lastPos); - newString += to; - lastPos = findPos + from.length(); - } - // Care for the rest after last occurrence - newString += source.substr(lastPos); + while (std::string::npos != (findPos = source.find(from,lastPos))) { + newString.append(source,lastPos,findPos - lastPos); + newString += to; + lastPos = findPos + from.length(); + } + // Care for the rest after last occurrence + newString += source.substr(lastPos); - source.swap(newString); + source.swap(newString); } // ---------------------------------------------------------------------------- -std::string& translateRegExpr(std::string& regExprStr, bool wholeWord, bool wordStart) +std::string& translateRegExpr(std::string& regExprStr,bool wholeWord,bool wordStart) { - std::string tmpStr; + std::string tmpStr; - if (wholeWord || wordStart) { // push '\b' at the begin of regexpr - tmpStr.push_back('\\'); - tmpStr.push_back('b'); - tmpStr.append(regExprStr); - if (wholeWord) { // push '\b' at the end of regexpr - tmpStr.push_back('\\'); - tmpStr.push_back('b'); - } - replaceAll(tmpStr, ".", "\\w"); + if (wholeWord || wordStart) { // push '\b' at the begin of regexpr + tmpStr.push_back('\\'); + tmpStr.push_back('b'); + tmpStr.append(regExprStr); + if (wholeWord) { // push '\b' at the end of regexpr + tmpStr.push_back('\\'); + tmpStr.push_back('b'); } - else { - tmpStr.append(regExprStr); - } - std::swap(regExprStr, tmpStr); - return regExprStr; + replaceAll(tmpStr,".","\\w"); + } + else { + tmpStr.append(regExprStr); + } + std::swap(regExprStr,tmpStr); + return regExprStr; } // ---------------------------------------------------------------------------- @@ -269,60 +278,60 @@ std::string& translateRegExpr(std::string& regExprStr, bool wholeWord, bool word std::string& convertReplExpr(std::string& replStr) { - std::string tmpStr; - for (size_t i = 0; i < replStr.length(); ++i) { - char ch = replStr[i]; - if (ch == '\\') { - ch = replStr[++i]; // next char - if (ch == '\\') { - // skip 2nd backslash ("\\") - if (i < replStr.length()) { ch = replStr[++i]; } - else { break; } - } - if (ch >= '1' && ch <= '9') { - // former behavior convenience: - // change "\\" to deelx's group reference ($) - tmpStr.push_back('$'); - } - switch (ch) { - // check for escape seq: - case 'a': - tmpStr.push_back('\a'); - break; - case 'b': - tmpStr.push_back('\b'); - break; - case 'f': - tmpStr.push_back('\f'); - break; - case 'n': - tmpStr.push_back('\n'); - break; - case 'r': - tmpStr.push_back('\r'); - break; - case 't': - tmpStr.push_back('\t'); - break; - case 'v': - tmpStr.push_back('\v'); - break; - case '\\': - tmpStr.push_back('\\'); - break; - default: - // unknown ctrl seq - tmpStr.push_back(ch); - break; - } - } - else { - tmpStr.push_back(ch); - } - } //for + std::string tmpStr; + for (size_t i = 0; i < replStr.length(); ++i) { + char ch = replStr[i]; + if (ch == '\\') { + ch = replStr[++i]; // next char + if (ch == '\\') { + // skip 2nd backslash ("\\") + if (i < replStr.length()) { ch = replStr[++i]; } + else { break; } + } + if (ch >= '1' && ch <= '9') { + // former behavior convenience: + // change "\\" to deelx's group reference ($) + tmpStr.push_back('$'); + } + switch (ch) { + // check for escape seq: + case 'a': + tmpStr.push_back('\a'); + break; + case 'b': + tmpStr.push_back('\b'); + break; + case 'f': + tmpStr.push_back('\f'); + break; + case 'n': + tmpStr.push_back('\n'); + break; + case 'r': + tmpStr.push_back('\r'); + break; + case 't': + tmpStr.push_back('\t'); + break; + case 'v': + tmpStr.push_back('\v'); + break; + case '\\': + tmpStr.push_back('\\'); + break; + default: + // unknown ctrl seq + tmpStr.push_back(ch); + break; + } + } + else { + tmpStr.push_back(ch); + } + } //for - std::swap(replStr, tmpStr); - return replStr; + std::swap(replStr,tmpStr); + return replStr; } // ============================================================================ From d3bd71e3f2694cfefea1e0cddff0386cad95a5ca Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Thu, 7 Sep 2017 14:04:25 +0200 Subject: [PATCH 2/7] + updated Compiler Info --- src/Version.h | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/src/Version.h b/src/Version.h index 37d72407f..e1f8f8d8e 100644 --- a/src/Version.h +++ b/src/Version.h @@ -55,39 +55,31 @@ #endif // Compiler specific -#if defined(WDK_BUILD) - #if _MSC_VER == 1600 - #if (_MSC_FULL_VER >= 160040219) - #define VER_CPL "WDK (MSVC 2010 SP1)" +#if defined(_MSC_VER) + #if _MSC_VER >= 1911 + #if (_MSC_FULL_VER >= 191125506) + #define VER_CPL "Microsoft Visual C++ 2017 Version 15.3" #else - #define VER_CPL "WDK (MSVC 2010)" - #endif - #elif _MSC_VER == 1500 - #if (_MSC_FULL_VER == 150030729) - #define VER_CPL "WDK" - #else - #define VER_CPL "WDK (version unknown)" - #endif - #endif -#elif defined(_MSC_VER) - #if _MSC_VER >= 1910 - #if (_MSC_FULL_VER >= 191025017) #define VER_CPL "Microsoft Visual C++ 2017" #endif + #elif _MSC_VER >= 1910 + #if (_MSC_FULL_VER >= 191025017) + #define VER_CPL "Microsoft Visual C++ 2017" + #else + #define VER_CPL "Microsoft Visual C++ 2017 RC" + #endif #elif _MSC_VER == 1900 - #if (_MSC_FULL_VER == 190024213) - #define VER_CPL "Microsoft Visual C++ 2015 Update 3" - #elif (_MSC_FULL_VER == 190023918) - #define VER_CPL "Microsoft Visual C++ 2015 Update 2" - #elif (_MSC_FULL_VER == 190023506) - #define VER_CPL "Microsoft Visual C++ 2015 Update 1" - #elif (_MSC_FULL_VER == 190023026) - #define VER_CPL "Microsoft Visual C++ 2015" + #if (_MSC_FULL_VER >= 190024213) + #define VER_CPL "Microsoft Visual C++ 2015 Update 3" + #elif (_MSC_FULL_VER >= 190023918) + #define VER_CPL "Microsoft Visual C++ 2015 Update 2" + #elif (_MSC_FULL_VER >= 190023506) + #define VER_CPL "Microsoft Visual C++ 2015 Update 1" #else #define VER_CPL "Microsoft Visual C++ 2015" #endif #else - #define VER_CPL "Microsoft Visual C++ (version unknown)" + #define VER_CPL "Microsoft Visual C++ (version unknown)" #endif #else #define VER_CPL "(Unknown compiler)" From 61b692891832f9b06a00ab239863995e660003aa Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Fri, 8 Sep 2017 08:39:59 +0200 Subject: [PATCH 3/7] + add build.txt (and .ps1 changes) for Local Build Version patching (common AppVeyor/Local script) --- Version.ps1 | 22 +++++++++++++++------- Versions/build.txt | 1 + 2 files changed, 16 insertions(+), 7 deletions(-) create mode 100644 Versions/build.txt diff --git a/Version.ps1 b/Version.ps1 index 436ef009d..6f00b162f 100644 --- a/Version.ps1 +++ b/Version.ps1 @@ -32,14 +32,19 @@ function DebugOutput($msg) try { $Major = 2 - $Minor = $(Get-Date -format yy) - $Revis = $(Get-Date -format Mdd) - $Build = $env:appveyor_build_number + $Minor = [int]$(Get-Date -format yy) + $Revis = [int]$(Get-Date -format Mdd) + if ($AppVeyorEnv) { + $Build = [int]($env:appveyor_build_number) + } + else { + $Build = [int](Get-Content "Versions\build.txt") + } if (!$Build) { $Build = 0 } - $SciVer = Get-Content "scintilla\version.txt" + $SciVer = [int](Get-Content "scintilla\version.txt") if (!$SciVer) { $SciVer = 0 } - $CompleteVer = "$Major.$Minor.$Revis.$Build" - + + $CompleteVer = "$Major.$Minor.$Revis.$Build" DebugOutput("Version number: '$CompleteVer'") Copy-Item -LiteralPath "Versions\VersionEx.h.tpl" -Destination "src\VersionEx.h" -Force @@ -51,7 +56,7 @@ try Copy-Item -LiteralPath "Versions\Notepad3.exe.manifest.tpl" -Destination "res\Notepad3.exe.manifest.conf" -Force (Get-Content "res\Notepad3.exe.manifest.conf") | ForEach-Object { $_ -replace '\$VERSION\$', $CompleteVer } | Set-Content "res\Notepad3.exe.manifest.conf" if ($AppVeyorEnv) { - Update-AppveyorBuild -Version $CompleteVer + Update-AppveyorBuild -Version $CompleteVer } } catch @@ -63,6 +68,9 @@ catch } finally { + if (-not $AppVeyorEnv) { + $Build + 1 | Set-Content "Versions\build.txt" + } [Environment]::SetEnvironmentVariable("LASTEXITCODE", $LastExitCode, "User") $host.SetShouldExit($LastExitCode) Write-Host "VersionPatching: Done! Elapsed time: $($stopwatch.Elapsed)." diff --git a/Versions/build.txt b/Versions/build.txt new file mode 100644 index 000000000..a786da04d --- /dev/null +++ b/Versions/build.txt @@ -0,0 +1 @@ +492 From 604383ca6393fa54b68ea117e169639079db3e58 Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Fri, 8 Sep 2017 11:58:26 +0200 Subject: [PATCH 4/7] + fixing issue "Convert to Title Case" while selected text is all upper case --- src/Edit.c | 64 +++++++++--------------------------------------------- 1 file changed, 10 insertions(+), 54 deletions(-) diff --git a/src/Edit.c b/src/Edit.c index 4363126d1..21f220fd7 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -562,8 +562,6 @@ char* EditGetClipboardText(HWND hwnd,BOOL bCheckEncoding) { char *pmch; char *ptmp; int wlen,mlen,mlen2; - UINT codepage; - int eolmode; if (!IsClipboardFormatAvailable(CF_UNICODETEXT) || !OpenClipboard(GetParent(hwnd))) { char* pEmpty = StrDupA(""); @@ -598,8 +596,7 @@ char* EditGetClipboardText(HWND hwnd,BOOL bCheckEncoding) { } // get clipboard - codepage = Encoding_SciGetCodePage(hwnd); - eolmode = (int)SendMessage(hwnd,SCI_GETEOLMODE,0,0); + UINT codepage = Encoding_SciGetCodePage(hwnd); mlen = WideCharToMultiByte(codepage,0,pwch,wlen + 2,NULL,0,NULL,NULL); pmch = LocalAlloc(LPTR,mlen + 2); @@ -616,6 +613,7 @@ char* EditGetClipboardText(HWND hwnd,BOOL bCheckEncoding) { if (ptmp) { char *s = pmch; char *d = ptmp; + int eolmode = (int)SendMessage(hwnd,SCI_GETEOLMODE,0,0); for (int i = 0; (i <= mlen) && (*s != '\0'); i++) { if (*s == '\n' || *s == '\r') { if (eolmode == SC_EOL_CR) { @@ -2046,10 +2044,6 @@ void EditTitleCase(HWND hwnd) int iCurPos; int iAnchorPos; UINT cpEdit; - int i; - BOOL bNewWord = TRUE; - BOOL bChanged = FALSE; - BOOL bPrevWasSpace = FALSE; iCurPos = (int)SendMessage(hwnd,SCI_GETCURRENTPOS,0,0); iAnchorPos = (int)SendMessage(hwnd,SCI_GETANCHOR,0,0); @@ -2076,56 +2070,18 @@ void EditTitleCase(HWND hwnd) cpEdit = Encoding_SciGetCodePage(hwnd); cchTextW = MultiByteToWideChar(cpEdit,0,pszText,iSelLength,pszTextW,iSelLength); - if (IsWin7()) { + BOOL bChanged = FALSE; - LPWSTR pszMappedW = LocalAlloc(LPTR,GlobalSize(pszTextW)); - - if (LCMapString(LOCALE_SYSTEM_DEFAULT,LCMAP_LINGUISTIC_CASING|LCMAP_TITLECASE, - pszTextW,cchTextW,pszMappedW,iSelLength)) { - StringCchCopyN(pszTextW,iSelLength,pszMappedW,iSelLength); + LPWSTR pszMappedW = LocalAlloc(LPTR,GlobalSize(pszTextW)); + // first make lower case, before applying TitleCase + if (LCMapString(LOCALE_SYSTEM_DEFAULT,LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE, + pszTextW,cchTextW,pszMappedW,iSelLength)) { + if (LCMapString(LOCALE_SYSTEM_DEFAULT,LCMAP_TITLECASE, + pszMappedW,cchTextW,pszTextW,iSelLength)) { bChanged = TRUE; } - else - bChanged = FALSE; - - LocalFree(pszMappedW); - } - - else { - - // Slightly enhanced function to make Title Case: - // Added some '-characters and bPrevWasSpace makes it better (for example "'Don't'" will now work) - bPrevWasSpace = TRUE; - for (i = 0; i < cchTextW; i++) - { - if (!IsCharAlphaNumericW(pszTextW[i]) && (!StrChr(L"'`΄’",pszTextW[i]) || bPrevWasSpace ) ) - { - bNewWord = TRUE; - } - else - { - if (bNewWord) - { - if (IsCharLowerW(pszTextW[i])) - { - pszTextW[i] = LOWORD(CharUpperW((LPWSTR)(SIZE_T)MAKELONG(pszTextW[i],0))); - bChanged = TRUE; - } - } - else - { - if (IsCharUpperW(pszTextW[i])) - { - pszTextW[i] = LOWORD(CharLowerW((LPWSTR)(SIZE_T)MAKELONG(pszTextW[i],0))); - bChanged = TRUE; - } - } - bNewWord = FALSE; - } - if( StrChr(L" \r\n\t[](){}",pszTextW[i]) ) bPrevWasSpace = TRUE; else bPrevWasSpace = FALSE; - } - } + LocalFree(pszMappedW); if (bChanged) { From 1736875cad9b3870e8fc6985ffa31926c48c6919 Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Fri, 8 Sep 2017 12:52:39 +0200 Subject: [PATCH 5/7] + fix broken "Complete Word" feature (Ctrl+Enter/Return) --- src/Edit.c | 24 +++++++++++++----------- src/Notepad3.c | 2 +- src/Notepad3.rc | Bin 181048 -> 181048 bytes src/resource.h | 2 +- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/Edit.c b/src/Edit.c index 21f220fd7..c31f1a6f2 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -5893,8 +5893,10 @@ struct WLIST { struct WLIST* next; }; -void CompleteWord(HWND hwnd, BOOL autoInsert) { - const char* NON_WORD = " \t\r\n@#$%^&*~-=+()[]{}\\/.,:;'\"!?<>`|"; +void CompleteWord(HWND hwnd, BOOL autoInsert) +{ + const char* NON_WORD = DelimChars; + int iCurrentPos = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, iCurrentPos, 0); int iCurrentLinePos = iCurrentPos - (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (WPARAM)iLine, 0); @@ -5927,11 +5929,11 @@ void CompleteWord(HWND hwnd, BOOL autoInsert) { return; } - int cnt = iCurrentLinePos - iStartWordPos + 2; - pRoot = LocalAlloc(LPTR,cnt); - StringCchCopyNA(pRoot,cnt,pLine + iStartWordPos,cnt-1); + int cnt = iCurrentLinePos - iStartWordPos; + pRoot = LocalAlloc(LPTR,cnt+1); + StringCchCopyNA(pRoot,cnt+1,pLine + iStartWordPos,cnt); LocalFree(pLine); - iRootLen = _StringCchLenNA(pRoot,cnt); + iRootLen = _StringCchLenNA(pRoot,cnt+1); iDocLen = (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0); @@ -5955,7 +5957,7 @@ void CompleteWord(HWND hwnd, BOOL autoInsert) { //int lastCmp = 0; BOOL found = FALSE; - pWord = LocalAlloc(LPTR,wordLength + 2); + pWord = LocalAlloc(LPTR,wordLength + 1); tr.lpstrText = pWord; tr.chrg.cpMin = iPosFind; @@ -5963,7 +5965,7 @@ void CompleteWord(HWND hwnd, BOOL autoInsert) { SendMessage(hwnd, SCI_GETTEXTRANGE, 0, (LPARAM)&tr); while(p) { - int cmp = StringCchCompareNA(pWord,wordLength + 2, p->word,-1); + int cmp = StringCchCompareNA(pWord,wordLength + 1, p->word,-1); if (cmp == 0) { found = TRUE; break; @@ -5975,8 +5977,8 @@ void CompleteWord(HWND hwnd, BOOL autoInsert) { } if (!found) { struct WLIST* el = (struct WLIST*)LocalAlloc(LPTR, sizeof(struct WLIST)); - el->word = LocalAlloc(LPTR,wordLength + 2); - StringCchCopyA(el->word,wordLength + 2,pWord); + el->word = LocalAlloc(LPTR,wordLength + 1); + StringCchCopyA(el->word,wordLength + 1,pWord); el->next = p; if (t) { t->next = el; @@ -5985,7 +5987,7 @@ void CompleteWord(HWND hwnd, BOOL autoInsert) { } iNumWords++; - iWListSize += _StringCchLenNA(pWord,wordLength + 2) + 1; + iWListSize += _StringCchLenNA(pWord,wordLength + 1) + 1; } LocalFree(pWord); } diff --git a/src/Notepad3.c b/src/Notepad3.c index 7b14ca90a..53ef17a70 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -4585,7 +4585,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) // Newline with toggled auto indent setting - case CMD_CTRLENTER: + case CMD_SHIFTCTRLENTER: bAutoIndent = (bAutoIndent) ? 0 : 1; SendMessage(hwndEdit,SCI_NEWLINE,0,0); bAutoIndent = (bAutoIndent) ? 0 : 1; diff --git a/src/Notepad3.rc b/src/Notepad3.rc index 5aa742bdb41791631e804ed1713cf58a2bf1e65e..5b8bb89f5c77ef2c1a6ae7c9663bcf65b5a6746a 100644 GIT binary patch delta 34 scmV+-0Nww%h6}ic3$SeWlkC_ElWg}Mla9eolMwj`gX;IU>h}Ro%R(s=1poj5 delta 34 scmV+-0Nww%h6}ic3$SeWlYle`lYaLWla87klQ7jngXs6S==T9o%O@5Q*Z=?k diff --git a/src/resource.h b/src/resource.h index 5c33cbdf6..a295ccb5a 100644 --- a/src/resource.h +++ b/src/resource.h @@ -170,7 +170,7 @@ #define IDS_WILDCARDHELP 10021 #define CMD_ESCAPE 20000 #define CMD_SHIFTESC 20001 -#define CMD_CTRLENTER 20002 +#define CMD_SHIFTCTRLENTER 20002 #define CMD_CTRLLEFT 20003 #define CMD_CTRLRIGHT 20004 #define CMD_BACK 20005 From 34ce1288d0c7dc1ea31423ef6d05f9938e3ebaa7 Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Fri, 8 Sep 2017 13:57:51 +0200 Subject: [PATCH 6/7] + change accelerator key for feature "Complete Word" from Ctrl+Enter to Ctrl+Alt+Enter + add feature "Insert New (empty) Line above current line Ctrl+Enter (as in VisualStudio) --- src/Notepad3.c | 22 ++++++++++++++++++++++ src/Notepad3.rc | Bin 181048 -> 181404 bytes src/resource.h | 1 + 3 files changed, 23 insertions(+) diff --git a/src/Notepad3.c b/src/Notepad3.c index 53ef17a70..b3de39d92 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -4584,6 +4584,26 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) break; + case CMD_CTRLENTER: + { + int token = BeginSelUndoAction(); + int iPos = (int)SendMessage(hwndEdit,SCI_GETCURRENTPOS,0,0); + int iLine = (int)SendMessage(hwndEdit,SCI_LINEFROMPOSITION,(WPARAM)iPos,0); + if (iLine <= 0) { + SendMessage(hwndEdit,SCI_GOTOLINE,0,0); + SendMessage(hwndEdit,SCI_NEWLINE,0,0); + SendMessage(hwndEdit,SCI_GOTOLINE,0,0); + } + else { + SendMessage(hwndEdit,SCI_GOTOPOS, + (WPARAM)SendMessage(hwndEdit,SCI_GETLINEENDPOSITION,(WPARAM)(iLine - 1),0),0); + SendMessage(hwndEdit,SCI_NEWLINE,0,0); + } + EndSelUndoAction(token); + } + break; + + // Newline with toggled auto indent setting case CMD_SHIFTCTRLENTER: bAutoIndent = (bAutoIndent) ? 0 : 1; @@ -4591,6 +4611,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) bAutoIndent = (bAutoIndent) ? 0 : 1; break; + case CMD_DEL: { int token = BeginSelUndoAction(); @@ -4599,6 +4620,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) } break; + case CMD_BACK: { int token = BeginSelUndoAction(); diff --git a/src/Notepad3.rc b/src/Notepad3.rc index 5b8bb89f5c77ef2c1a6ae7c9663bcf65b5a6746a..faf54982c8f5a97044685512d4de5da0848bf3a8 100644 GIT binary patch delta 159 zcmV;Q0AT;Ph6|jD3$Q3NlW<1{lQ2>sl3@r5MF4I9bO2=la+9Gt8Im{zlfXv=lLp@q zlje04lORJ#laLY=lddxuvpzHG9vvnCP5@;9cK{#&OaN&BZUAKfAOJxCVgPRdb^v9Q zK~f`=cr*|PMF36!Q~*Vjp Date: Fri, 8 Sep 2017 14:00:09 +0200 Subject: [PATCH 7/7] + code cleanup --- src/Notepad3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Notepad3.c b/src/Notepad3.c index b3de39d92..48b01acd1 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -4596,7 +4596,7 @@ LRESULT MsgCommand(HWND hwnd,WPARAM wParam,LPARAM lParam) } else { SendMessage(hwndEdit,SCI_GOTOPOS, - (WPARAM)SendMessage(hwndEdit,SCI_GETLINEENDPOSITION,(WPARAM)(iLine - 1),0),0); + SendMessage(hwndEdit,SCI_GETLINEENDPOSITION,(WPARAM)(iLine - 1),0),0); SendMessage(hwndEdit,SCI_NEWLINE,0,0); } EndSelUndoAction(token);