diff --git a/Versions/build.txt b/Versions/build.txt index 0cfbf0888..d00491fd7 100644 --- a/Versions/build.txt +++ b/Versions/build.txt @@ -1 +1 @@ -2 +1 diff --git a/Versions/day.txt b/Versions/day.txt index a817176f4..0ddd619ce 100644 --- a/Versions/day.txt +++ b/Versions/day.txt @@ -1 +1 @@ -216 +217 diff --git a/res/Notepad3.exe.manifest.conf b/res/Notepad3.exe.manifest.conf index 6e1459e78..9f1f274ec 100644 --- a/res/Notepad3.exe.manifest.conf +++ b/res/Notepad3.exe.manifest.conf @@ -3,7 +3,7 @@ Notepad3 RC1 diff --git a/scioniguruma/OnigurumaRegExEngine.cxx b/scioniguruma/OnigurumaRegExEngine.cxx index 8c4390e55..511ee148a 100644 --- a/scioniguruma/OnigurumaRegExEngine.cxx +++ b/scioniguruma/OnigurumaRegExEngine.cxx @@ -400,8 +400,6 @@ const char* OnigurumaRegExEngine::SubstituteByPosition(Document* doc, const char m_SubstBuffer.clear(); - //TODO: allow for arbitrary number of groups/regions - for (size_t j = 0; j < rawReplStrg.length(); j++) { bool bReplaced = false; @@ -409,7 +407,9 @@ const char* OnigurumaRegExEngine::SubstituteByPosition(Document* doc, const char { if ((rawReplStrg[j + 1] >= '0') && (rawReplStrg[j + 1] <= '9')) { - int const grpNum = rawReplStrg[j + 1] - '0'; + // group # limit = 99 / TODO: allow for arbitrary number of groups/regions + bool const num2nd = ((rawReplStrg[j + 2] >= '0') && (rawReplStrg[j + 2] <= '9')); + int const grpNum = num2nd ? (rawReplStrg[j + 1] - '0') * 10 + (rawReplStrg[j + 2] - '0') : (rawReplStrg[j + 1] - '0'); if (grpNum < m_Region.num_regs) { auto const rBeg = SciPos(m_Region.beg[grpNum]); @@ -418,13 +418,13 @@ const char* OnigurumaRegExEngine::SubstituteByPosition(Document* doc, const char m_SubstBuffer.append(doc->RangePointer(rBeg, len), static_cast(len)); } bReplaced = true; - ++j; + j += num2nd ? 2 : 1; } else if (rawReplStrg[j] == '$') { size_t k = ((rawReplStrg[j + 1] == '+') && (rawReplStrg[j + 2] == '{')) ? (j + 3) : ((rawReplStrg[j + 1] == '{') ? (j + 2) : 0); if (k > 0) { - // named group replacemment + // named group replacement auto const name_beg = UCharCPtr(&(rawReplStrg[k])); while (rawReplStrg[k] && IsCharAlphaNumericA(rawReplStrg[k])) { ++k; } if (rawReplStrg[k] == '}') @@ -567,6 +567,8 @@ std::string& OnigurumaRegExEngine::convertReplExpr(std::string& replStr) // former behavior convenience: // change "\\" to deelx's group reference ($) tmpStr.push_back('$'); + tmpStr.push_back(ch); + continue; } switch (ch) { // check for escape seq: @@ -574,10 +576,7 @@ std::string& OnigurumaRegExEngine::convertReplExpr(std::string& replStr) tmpStr.push_back('\a'); break; case 'b': - tmpStr.push_back('\b'); - break; - case '\x1B': - tmpStr.push_back('\e'); + tmpStr.push_back('\x1B'); break; case 'f': tmpStr.push_back('\f'); diff --git a/src/Config/SimpleIni.h b/src/Config/SimpleIni.h index cbad4d4f9..915f0acc3 100644 --- a/src/Config/SimpleIni.h +++ b/src/Config/SimpleIni.h @@ -294,6 +294,7 @@ enum class SI_Error : int { #if defined(_WIN32) # define SI_HAS_WIDE_FILE +//# define SI_USE_LOCKING_WIDE_FILE # define SI_WCHAR_T wchar_t #elif defined(SI_CONVERT_ICU) # define SI_HAS_WIDE_FILE @@ -412,10 +413,34 @@ public: fputs(a_pBuf, m_file); } private: + FileWriter() = delete; FileWriter(const FileWriter &); // disable FileWriter & operator=(const FileWriter &); // disable }; +#ifdef SI_USE_LOCKING_WIDE_FILE + class FileWriterLocking : public OutputWriter { + HANDLE m_file; + LPOVERLAPPED m_pOvrLpd; + public: + FileWriterLocking(HANDLE a_file, LPOVERLAPPED a_pOvrLpd) + : m_file(a_file) + , m_pOvrLpd(a_pOvrLpd) { } + ~FileWriterLocking() { + FlushFileBuffers(m_file); + } + void Write(const char* a_pBuf) override { + DWORD nBytesWritten = 0UL; + DWORD const nBytesToWrite = static_cast(strlen(a_pBuf)); + WriteFile(m_file, a_pBuf, nBytesToWrite, &nBytesWritten, m_pOvrLpd); + } + private: + FileWriterLocking() = delete; + FileWriterLocking(const FileWriterLocking&) = delete; // disable + FileWriterLocking& operator=(const FileWriterLocking&) = delete; // disable + }; +#endif + /** OutputWriter class to write the INI data to a string */ class StringWriter : public OutputWriter { std::string & m_string; @@ -610,9 +635,11 @@ public: @return SI_Error See error definitions */ - SI_Error LoadFile( - FILE * a_fpFile - ); +#ifdef SI_USE_LOCKING_WIDE_FILE + SI_Error LoadFile( HANDLE a_hFile, DWORD dwFileSize, LPOVERLAPPED pOvrLpd); +#else + SI_Error LoadFile( FILE * a_fpFile ); +#endif #ifdef SI_SUPPORT_IOSTREAMS /** Load INI file data from an istream. @@ -698,11 +725,18 @@ public: @return SI_Error See error definitions */ +#ifdef SI_USE_LOCKING_WIDE_FILE + SI_Error SaveFile( + HANDLE a_hFile, + LPOVERLAPPED a_pOvrLpd, + bool a_bAddSignature = false + ) const; +#else SI_Error SaveFile( FILE * a_pFile, bool a_bAddSignature = false ) const; - +#endif /** Save the INI data. The data will be written to the output device in a format appropriate to the current data, selected by: @@ -1392,6 +1426,44 @@ CSimpleIniTempl::LoadFile( } #ifdef SI_HAS_WIDE_FILE + +#ifdef SI_USE_LOCKING_WIDE_FILE + +template +SI_Error +CSimpleIniTempl::LoadFile( + const SI_WCHAR_T* a_pwszFile +) +{ + HANDLE hFile = CreateFile(a_pwszFile, + GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hFile == INVALID_HANDLE_VALUE) { + return SI_Error::SI_FILE; + } + + DWORD dwFileSizeHigh = 0UL; + DWORD const dwFileSize = GetFileSize(hFile, &dwFileSizeHigh); + if ((dwFileSize == INVALID_FILE_SIZE) || (dwFileSizeHigh != 0UL)) { + return SI_Error::SI_FILE; + } + + OVERLAPPED OvrLpd; ZeroMemory(&OvrLpd, sizeof(OVERLAPPED)); + + DWORD const flags = 0UL; // SHARED READ(!) ~ LOCKFILE_FAIL_IMMEDIATELY | LOCKFILE_EXCLUSIVE_LOCK + LockFileEx(hFile, flags, 0, dwFileSize, dwFileSizeHigh, &OvrLpd); + + SI_Error const rc = LoadFile(hFile, dwFileSize, &OvrLpd); + + UnlockFileEx(hFile, 0, dwFileSize, dwFileSizeHigh, &OvrLpd); + + CloseHandle(hFile); + return rc; +} + +#else + template SI_Error CSimpleIniTempl::LoadFile( @@ -1415,8 +1487,43 @@ CSimpleIniTempl::LoadFile( return LoadFile(szFile); #endif // _WIN32 } + +#endif // SI_USE_LOCKING_WIDE_FILE + #endif // SI_HAS_WIDE_FILE + +#ifdef SI_USE_LOCKING_WIDE_FILE + +template +SI_Error +CSimpleIniTempl::LoadFile( + HANDLE a_hFile, DWORD dwFileSize, LPOVERLAPPED pOvrLpd +) +{ + // allocate and ensure NULL terminated + auto* pData = new(std::nothrow) char[dwFileSize + 1]; + if (!pData) { + return SI_Error::SI_NOMEM; + } + pData[dwFileSize] = '\0'; + + // load the raw file data + DWORD nBytesRead = 0UL; + BOOL const result = ReadFile(a_hFile, pData, dwFileSize, &nBytesRead, pOvrLpd); + if ((result == FALSE) || (nBytesRead != dwFileSize)) { + delete[] pData; + return SI_Error::SI_FILE; + } + + // convert the raw data to unicode + SI_Error const rc = LoadData(pData, (size_t)nBytesRead); + delete[] pData; + return rc; +} + +#else + template SI_Error CSimpleIniTempl::LoadFile( @@ -1457,6 +1564,8 @@ CSimpleIniTempl::LoadFile( return rc; } +#endif + template SI_Error CSimpleIniTempl::LoadData( @@ -2521,6 +2630,45 @@ CSimpleIniTempl::SaveFile( } #ifdef SI_HAS_WIDE_FILE + +#ifdef SI_USE_LOCKING_WIDE_FILE + +template +SI_Error +CSimpleIniTempl::SaveFile( + const SI_WCHAR_T* a_pwszFile, + bool a_bAddSignature +) const +{ + HANDLE hFile = CreateFile(a_pwszFile, + GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hFile == INVALID_HANDLE_VALUE) { + return SI_Error::SI_FILE; + } + + DWORD dwFileSizeHigh = 0UL; + DWORD const dwFileSize = GetFileSize(hFile, &dwFileSizeHigh); + if ((dwFileSize == INVALID_FILE_SIZE) || (dwFileSizeHigh != 0UL)) { + return SI_Error::SI_FILE; + } + + OVERLAPPED OvrLpd; ZeroMemory(&OvrLpd, sizeof(OVERLAPPED)); + + DWORD const flags = 0UL; // SHARED READ(!) ~ LOCKFILE_FAIL_IMMEDIATELY | LOCKFILE_EXCLUSIVE_LOCK + LockFileEx(hFile, flags, 0, dwFileSize, dwFileSizeHigh, &OvrLpd); + + SI_Error const rc = SaveFile(hFile, &OvrLpd, a_bAddSignature); + + UnlockFileEx(hFile, 0, dwFileSize, dwFileSizeHigh, &OvrLpd); + + CloseHandle(hFile); + return rc; +} + +#else + template SI_Error CSimpleIniTempl::SaveFile( @@ -2546,8 +2694,25 @@ CSimpleIniTempl::SaveFile( return SaveFile(szFile, a_bAddSignature); #endif // _WIN32 } + +#endif // SI_USE_LOCKING_WIDE_FILE + #endif // SI_HAS_WIDE_FILE + +#ifdef SI_USE_LOCKING_WIDE_FILE +template +SI_Error +CSimpleIniTempl::SaveFile( + HANDLE a_hFile, + LPOVERLAPPED a_pOvrLpd, + bool a_bAddSignature +) const +{ + FileWriterLocking writer(a_hFile, a_pOvrLpd); + return Save(writer, a_bAddSignature); +} +#else template SI_Error CSimpleIniTempl::SaveFile( @@ -2558,6 +2723,7 @@ CSimpleIniTempl::SaveFile( FileWriter writer(a_pFile); return Save(writer, a_bAddSignature); } +#endif template SI_Error diff --git a/src/VersionEx.h b/src/VersionEx.h index 0510c0026..e28d7bd83 100644 --- a/src/VersionEx.h +++ b/src/VersionEx.h @@ -8,12 +8,12 @@ #define SAPPNAME "Notepad3" #define VERSION_MAJOR 5 #define VERSION_MINOR 20 -#define VERSION_REV 216 -#define VERSION_BUILD 2 +#define VERSION_REV 217 +#define VERSION_BUILD 1 #define SCINTILLA_VER 430 #define ONIGURUMA_REGEX_VER 6.9.4 #define UCHARDET_VER 2018.09.27 #define TINYEXPR_VER 2018.05.11 #define UTHASH_VER 2.1.0 #define VERSION_PATCH RC1 -#define VERSION_COMMIT_ID nebukadn +#define VERSION_COMMIT_ID t7820-rk