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