diff --git a/res/Notepad3.exe.manifest b/res/Notepad3.exe.manifest
index c94716b38..0fb453c68 100644
--- a/res/Notepad3.exe.manifest
+++ b/res/Notepad3.exe.manifest
@@ -41,7 +41,7 @@
PerMonitorV2,PerMonitor
- false
+ true
false
diff --git a/src/.clang-format b/src/.clang-format
index 2d22a9b81..8cc8ef6d0 100644
--- a/src/.clang-format
+++ b/src/.clang-format
@@ -8,9 +8,26 @@ TabWidth: 4
Language: Cpp
AccessModifierOffset: -2
AlignAfterOpenBracket: DontAlign
+AlignConsecutiveDeclarations: true
+PointerAlignment: Left
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: true
ColumnLimit: 0
+#BraceWrapping:
+# AfterClass: true
+# AfterControlStatement: true
+# AfterEnum: false
+# AfterFunction: true
+# AfterNamespace: false
+# AfterObjCDeclaration: true
+# AfterStruct: true
+# AfterUnion: true
+# BeforeCatch: true
+# BeforeElse: false
+# IndentBraces: false
+#BreakBeforeBraces: Custom
+BreakBeforeBraces: Stroustrup
+#BreakBeforeBraces: Allman
Cpp11BracedListStyle: false
FixNamespaceComments: false
SortIncludes: false
diff --git a/src/Config/Config.cpp b/src/Config/Config.cpp
index 10329e0e7..e452ec70a 100644
--- a/src/Config/Config.cpp
+++ b/src/Config/Config.cpp
@@ -21,9 +21,10 @@
#if !defined(NTDDI_VERSION)
#define NTDDI_VERSION 0x06010000 /*NTDDI_WIN7*/
#endif
+
#define VC_EXTRALEAN 1
#define WIN32_LEAN_AND_MEAN 1
-#define NOMINMAX 1
+//#define NOMINMAX 1
#include
#include
@@ -44,6 +45,7 @@ extern "C" {
#include "Notepad3.h"
#include "MuiLanguage.h"
#include "DynStrg.h"
+#include "PathLib.h"
}
#include "DarkMode/DarkMode.h"
@@ -838,15 +840,17 @@ extern "C" void ClearDestinationsOnRecentDocs()
//
static bool _CheckIniFile(LPWSTR lpszFile, LPCWSTR lpszModule)
{
- WCHAR wchFileExpanded[MAX_PATH] = { L'\0' };
- ExpandEnvironmentStrings(lpszFile, wchFileExpanded, COUNTOF(wchFileExpanded));
+ HPATHL hPathExpanded = Path_Allocate(lpszFile);
+ Path_ExpandEnvStrings(hPathExpanded);
+
+ const bool bIsMaxPath = (Path_GetLength(hPathExpanded) <= MAX_PATH);
bool result = false;
- if (PathIsRelative(wchFileExpanded)) {
+ if (bIsMaxPath && PathIsRelative(Path_Get(hPathExpanded))) {
WCHAR tchBuild[MAX_PATH] = { L'\0' };
- // program directory
+ // program directory
StringCchCopy(tchBuild, COUNTOF(tchBuild), lpszModule);
- StringCchCopy(PathFindFileName(tchBuild), COUNTOF(tchBuild), wchFileExpanded);
+ StringCchCopy(PathFindFileName(tchBuild), COUNTOF(tchBuild), Path_Get(hPathExpanded));
if (PathIsExistingFile(tchBuild)) {
StringCchCopy(lpszFile, MAX_PATH, tchBuild);
result = true;
@@ -856,14 +860,14 @@ static bool _CheckIniFile(LPWSTR lpszFile, LPCWSTR lpszModule)
StringCchCopy(tchBuild, COUNTOF(tchBuild), lpszModule);
PathCchRemoveFileSpec(tchBuild, COUNTOF(tchBuild));
StringCchCat(tchBuild, COUNTOF(tchBuild), L"\\np3\\");
- StringCchCat(tchBuild, COUNTOF(tchBuild), wchFileExpanded);
+ StringCchCat(tchBuild, COUNTOF(tchBuild), Path_Get(hPathExpanded));
if (PathIsExistingFile(tchBuild)) {
StringCchCopy(lpszFile, MAX_PATH, tchBuild);
result = true;
}
// Application Data (%APPDATA%)
if (!result && GetKnownFolderPath(FOLDERID_RoamingAppData, tchBuild, COUNTOF(tchBuild))) {
- PathCchAppend(tchBuild, COUNTOF(tchBuild), wchFileExpanded);
+ PathCchAppend(tchBuild, COUNTOF(tchBuild), Path_Get(hPathExpanded));
if (PathIsExistingFile(tchBuild)) {
StringCchCopy(lpszFile, MAX_PATH, tchBuild);
result = true;
@@ -871,7 +875,7 @@ static bool _CheckIniFile(LPWSTR lpszFile, LPCWSTR lpszModule)
}
// Home (%HOMEPATH%) user's profile dir
if (!result && GetKnownFolderPath(FOLDERID_Profile, tchBuild, COUNTOF(tchBuild))) {
- PathCchAppend(tchBuild, COUNTOF(tchBuild), wchFileExpanded);
+ PathCchAppend(tchBuild, COUNTOF(tchBuild), Path_Get(hPathExpanded));
if (PathIsExistingFile(tchBuild)) {
StringCchCopy(lpszFile, MAX_PATH, tchBuild);
result = true;
@@ -883,10 +887,12 @@ static bool _CheckIniFile(LPWSTR lpszFile, LPCWSTR lpszModule)
//~ return true;
//~}
}
- } else if (PathIsExistingFile(wchFileExpanded)) {
- StringCchCopy(lpszFile, MAX_PATH, wchFileExpanded);
+ }
+ else if (Path_IsExistingFile(hPathExpanded)) {
+ StringCchCopy(lpszFile, MAX_PATH, Path_Get(hPathExpanded));
result = true;
}
+ Path_Release(hPathExpanded);
return result;
}
// ============================================================================
diff --git a/src/Dialogs.c b/src/Dialogs.c
index 7e9f78d40..6a5c66b2e 100644
--- a/src/Dialogs.c
+++ b/src/Dialogs.c
@@ -30,6 +30,7 @@
#include
#pragma warning( pop )
+#include "PathLib.h"
#include "Edit.h"
#include "Dlapi.h"
#include "Version.h"
diff --git a/src/DynStrg.c b/src/DynStrg.c
index f5944a512..391c3bc5e 100644
--- a/src/DynStrg.c
+++ b/src/DynStrg.c
@@ -7,7 +7,6 @@
#include
#include
#include
-//#include
#include
#include
#include
@@ -32,7 +31,6 @@ typedef struct tagSTRINGW
/* */
/**************************************************/
-
// direct heap allocation
#if (defined(_DEBUG) || defined(DEBUG)) && !defined(NDEBUG)
#define DEFAULT_ALLOC_FLAGS (HEAP_GENERATE_EXCEPTIONS)
@@ -65,39 +63,41 @@ __forceinline size_t SizeOfMemStrg(LPCVOID lpMemory) {
/* */
/**************************************************/
-__forceinline STRINGW* STRAPI ToWString(HSTRINGW hstr)
+__forceinline STRINGW* ToWStrg(HSTRINGW hstr)
{
if (!hstr)
return NULL;
return (STRINGW*)hstr;
}
-__forceinline size_t STRAPI StrlenW(const wchar_t *p) {
+__forceinline size_t StrlenW(const wchar_t *p) {
return (!p) ? 0 : wcslen(p);
}
-inline static void * STRAPI AllocBuffer(size_t len, size_t char_size, BOOL bZeroMem) {
+#define limit_len(len) (((len) < STRINGW_MAX_CCH) ? (len) : (STRINGW_MAX_CCH - 1))
+
+inline static void * AllocBuffer(size_t len, size_t char_size, BOOL bZeroMem) {
if (!s_hndlProcessHeap) {
s_hndlProcessHeap = GetProcessHeap();
}
- return AllocMemStrg(len * char_size, bZeroMem ? HEAP_ZERO_MEMORY : 0);
+ return AllocMemStrg(limit_len(len) * char_size, bZeroMem ? HEAP_ZERO_MEMORY : 0);
}
-inline static void * STRAPI ReAllocBuffer(void* pdata, size_t len, size_t char_size, BOOL bZeroMem) {
+inline static void * ReAllocBuffer(void* pdata, size_t len, size_t char_size, BOOL bZeroMem) {
if (!s_hndlProcessHeap) {
s_hndlProcessHeap = GetProcessHeap();
}
- return ReAllocMemStrg(pdata, len * char_size, bZeroMem ? HEAP_ZERO_MEMORY : 0);
+ return ReAllocMemStrg(pdata, limit_len(len) * char_size, bZeroMem ? HEAP_ZERO_MEMORY : 0);
}
-inline static void STRAPI FreeBuffer(wchar_t * pstr) {
+inline static void FreeBuffer(wchar_t * pstr) {
if (!s_hndlProcessHeap) {
s_hndlProcessHeap = GetProcessHeap();
}
FreeMemStrg(pstr);
}
-inline static void STRAPI FreeBufferW(STRINGW* pstr) {
+inline static void FreeBufferW(STRINGW* pstr) {
if (!pstr->data) {
return;
}
@@ -107,17 +107,18 @@ inline static void STRAPI FreeBufferW(STRINGW* pstr) {
pstr->data_length = 0;
}
-static void STRAPI AllocW(STRINGW* pstr, size_t len)
+static void AllocW(STRINGW* pstr, size_t len)
{
if (len == 0)
FreeBufferW(pstr);
else
{
+ len = limit_len(len);
size_t const alloc_len = len + 1;
if (!pstr->data) {
- pstr->data = AllocBuffer(alloc_len, sizeof(wchar_t), FALSE);
+ pstr->data = AllocBuffer(alloc_len, sizeof(wchar_t), TRUE);
} else if (len >= pstr->alloc_length) {
- pstr->data = ReAllocBuffer(pstr->data, alloc_len, sizeof(wchar_t), FALSE);
+ pstr->data = ReAllocBuffer(pstr->data, alloc_len, sizeof(wchar_t), TRUE);
}
if (pstr->data) // init
{
@@ -129,7 +130,7 @@ static void STRAPI AllocW(STRINGW* pstr, size_t len)
}
}
-static void STRAPI AllocCopyW(STRINGW* pstr, STRINGW* pDest, size_t copy_len, size_t copy_index, size_t extra_len)
+static void AllocCopyW(STRINGW* pstr, STRINGW* pDest, size_t copy_len, size_t copy_index, size_t extra_len)
{
size_t new_len = copy_len + extra_len;
if (new_len > 0)
@@ -141,7 +142,7 @@ static void STRAPI AllocCopyW(STRINGW* pstr, STRINGW* pDest, size_t copy_len, si
}
}
-static void STRAPI CopyW(STRINGW *pstr, size_t len, const wchar_t *p) {
+static void CopyW(STRINGW *pstr, size_t len, const wchar_t *p) {
if (pstr->data) {
wchar_t *endptr = NULL;
StringCchCopyNExW(pstr->data, pstr->alloc_length, p, len, &endptr, NULL, STR_CCH_FLAGS);
@@ -149,16 +150,16 @@ static void STRAPI CopyW(STRINGW *pstr, size_t len, const wchar_t *p) {
}
}
-static void STRAPI SetCopyW(STRINGW* pstr, size_t len, const wchar_t* p)
+static void SetCopyW(STRINGW* pstr, size_t len, const wchar_t* p)
{
AllocW(pstr, len);
CopyW(pstr, len, p);
}
-static wchar_t* STRAPI CopyOldDataW(STRINGW* pstr, size_t* outLen)
+static wchar_t* CopyOldDataW(STRINGW* pstr, size_t* outLen)
{
size_t old_len = StrlenW(pstr->data);
- wchar_t* ptr = AllocBuffer(old_len + 1, sizeof(wchar_t), FALSE);
+ wchar_t* ptr = AllocBuffer(old_len + 1, sizeof(wchar_t), TRUE);
if (ptr)
{
wchar_t *endptr = NULL;
@@ -168,7 +169,7 @@ static wchar_t* STRAPI CopyOldDataW(STRINGW* pstr, size_t* outLen)
return ptr;
}
-static void STRAPI FreeUnusedData(STRINGW *pstr)
+static void FreeUnusedData(STRINGW *pstr)
{
if ((pstr->data_length + 1) != pstr->alloc_length) {
size_t old_len = 0;
@@ -183,7 +184,7 @@ static void STRAPI FreeUnusedData(STRINGW *pstr)
}
}
-static void STRAPI CopyConcatW(STRINGW *pstr, size_t len1, const wchar_t *p1, size_t len2, const wchar_t *p2)
+static void CopyConcatW(STRINGW *pstr, size_t len1, const wchar_t *p1, size_t len2, const wchar_t *p2)
{
size_t const new_len = len1 + len2;
if (new_len != 0)
@@ -195,7 +196,7 @@ static void STRAPI CopyConcatW(STRINGW *pstr, size_t len1, const wchar_t *p1, si
}
}
-static void STRAPI ConcatW(STRINGW* pstr, size_t len, const wchar_t* p)
+static void ConcatW(STRINGW* pstr, size_t len, const wchar_t* p)
{
if (len == 0)
return;
@@ -222,13 +223,13 @@ static void STRAPI ConcatW(STRINGW* pstr, size_t len, const wchar_t* p)
}
-static void STRAPI FormatW(HSTRINGW hstr, const wchar_t* fmt, va_list args)
+static void FormatW(HSTRINGW hstr, const wchar_t* fmt, va_list args)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
- va_list prev_list = args;
+ va_list orig_list = args;
size_t max_len = 0;
const wchar_t * p;
@@ -367,6 +368,7 @@ static void STRAPI FormatW(HSTRINGW hstr, const wchar_t* fmt, va_list args)
default:
assert(0); /* unknown format */
+ break;
}
}
max_len += item_len;
@@ -375,9 +377,9 @@ static void STRAPI FormatW(HSTRINGW hstr, const wchar_t* fmt, va_list args)
AllocW(pstr, max_len);
wchar_t* endptr = NULL;
- StringCchVPrintfExW(pstr->data, pstr->alloc_length, &endptr, NULL, STR_CCH_FLAGS, fmt, prev_list);
+ StringCchVPrintfExW(pstr->data, pstr->alloc_length, &endptr, NULL, STR_CCH_FLAGS, fmt, orig_list);
pstr->data_length = (size_t)(endptr - pstr->data);
- va_end(prev_list);
+ va_end(orig_list);
}
@@ -396,18 +398,9 @@ HSTRINGW STRAPI StrgCreate()
}
-//~void STRAPI StrgReserveBuffer(HSTRINGW hstr, size_t len) {
-//~
-//~ STRINGW* ptr = ToWString(hstr);
-//~ if (!ptr)
-//~ return;
-//~ AllocW(ptr, len);
-//~}
-
-
void STRAPI StrgDestroy(HSTRINGW hstr)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
FreeBufferW(pstr);
@@ -417,7 +410,7 @@ void STRAPI StrgDestroy(HSTRINGW hstr)
int STRAPI StrgSet(HSTRINGW hstr, const wchar_t* str)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return -1;
SetCopyW(pstr, StrlenW(str), str);
@@ -427,7 +420,7 @@ int STRAPI StrgSet(HSTRINGW hstr, const wchar_t* str)
const wchar_t* STRAPI StrgGet(HSTRINGW hstr)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return NULL;
return pstr->data;
@@ -436,7 +429,7 @@ const wchar_t* STRAPI StrgGet(HSTRINGW hstr)
size_t STRAPI StrgGetLength(HSTRINGW hstr)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return 0;
return pstr->data_length;
@@ -445,7 +438,7 @@ size_t STRAPI StrgGetLength(HSTRINGW hstr)
size_t STRAPI StrgGetAllocLength(HSTRINGW hstr)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return 0;
return pstr->alloc_length;
@@ -460,7 +453,7 @@ int STRAPI StrgIsEmpty(HSTRINGW hstr)
void STRAPI StrgFreeExtra(HSTRINGW hstr)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
FreeUnusedData(pstr);
@@ -469,7 +462,7 @@ void STRAPI StrgFreeExtra(HSTRINGW hstr)
void STRAPI StrgEmpty(HSTRINGW hstr)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
FreeBufferW(pstr);
@@ -478,7 +471,7 @@ void STRAPI StrgEmpty(HSTRINGW hstr)
void STRAPI StrgSetAt(HSTRINGW hstr, size_t index, wchar_t ch)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
if (index >= pstr->data_length)
@@ -492,7 +485,7 @@ void STRAPI StrgSetAt(HSTRINGW hstr, size_t index, wchar_t ch)
wchar_t STRAPI StrgGetAt(HSTRINGW hstr, size_t index)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return L'\0';
if (index >= pstr->data_length)
@@ -506,7 +499,7 @@ wchar_t STRAPI StrgGetAt(HSTRINGW hstr, size_t index)
void STRAPI StrgCat(HSTRINGW hstr, const wchar_t* str)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
ConcatW(pstr, StrlenW(str), str);
@@ -515,7 +508,7 @@ void STRAPI StrgCat(HSTRINGW hstr, const wchar_t* str)
size_t STRAPI StrgInsert(HSTRINGW hstr, size_t index, const wchar_t* str)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return STRINGW_INVALID_SIZE;
@@ -548,7 +541,7 @@ size_t STRAPI StrgInsert(HSTRINGW hstr, size_t index, const wchar_t* str)
size_t STRAPI StrgInsertCh(HSTRINGW hstr, size_t index, wchar_t c)
{
- STRINGW *pstr = ToWString(hstr);
+ STRINGW *pstr = ToWStrg(hstr);
if (!pstr)
return 0;
@@ -573,7 +566,7 @@ size_t STRAPI StrgInsertCh(HSTRINGW hstr, size_t index, wchar_t c)
size_t STRAPI StrgReplace(HSTRINGW hstr, const wchar_t* pOld, const wchar_t* pNew)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return 0;
@@ -640,7 +633,7 @@ size_t STRAPI StrgRemove(HSTRINGW hstr, const wchar_t *str)
size_t STRAPI StrgReplaceCh(HSTRINGW hstr, wchar_t chOld, wchar_t chNew)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return 0;
@@ -665,7 +658,7 @@ size_t STRAPI StrgReplaceCh(HSTRINGW hstr, wchar_t chOld, wchar_t chNew)
size_t STRAPI StrgRemoveCh(HSTRINGW hstr, wchar_t chRemove)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return 0;
@@ -693,7 +686,7 @@ size_t STRAPI StrgRemoveCh(HSTRINGW hstr, wchar_t chRemove)
size_t STRAPI StrgDelete(HSTRINGW hstr, size_t index, size_t count)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return 0;
@@ -711,7 +704,7 @@ size_t STRAPI StrgDelete(HSTRINGW hstr, size_t index, size_t count)
void STRAPI StrgToUpper(HSTRINGW hstr)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
_wcsupr_s(pstr->data, pstr->data_length);
@@ -720,7 +713,7 @@ void STRAPI StrgToUpper(HSTRINGW hstr)
void STRAPI StrgToLower(HSTRINGW hstr)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
_wcslwr_s(pstr->data, pstr->data_length);
@@ -729,7 +722,7 @@ void STRAPI StrgToLower(HSTRINGW hstr)
void STRAPI StrgReverse(HSTRINGW hstr)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
_wcsrev(pstr->data);
@@ -738,7 +731,7 @@ void STRAPI StrgReverse(HSTRINGW hstr)
void STRAPI StrgTrimRight(HSTRINGW hstr)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
@@ -767,7 +760,7 @@ void STRAPI StrgTrimRight(HSTRINGW hstr)
void STRAPI StrgTrimLeft(HSTRINGW hstr)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return;
@@ -794,7 +787,7 @@ void STRAPI StrgTrim(HSTRINGW hstr)
size_t STRAPI StrgFind(HSTRINGW hstr, const wchar_t* sub, size_t start)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return STRINGW_INVALID_SIZE;
@@ -809,7 +802,7 @@ size_t STRAPI StrgFind(HSTRINGW hstr, const wchar_t* sub, size_t start)
size_t STRAPI StrgFindCh(HSTRINGW hstr, wchar_t ch, size_t start)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return STRINGW_INVALID_SIZE;
@@ -824,7 +817,7 @@ size_t STRAPI StrgFindCh(HSTRINGW hstr, wchar_t ch, size_t start)
size_t STRAPI StrgReverseFind(HSTRINGW hstr, wchar_t ch)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return STRINGW_INVALID_SIZE;
@@ -836,7 +829,7 @@ size_t STRAPI StrgReverseFind(HSTRINGW hstr, wchar_t ch)
size_t STRAPI StrgFindOneOf(HSTRINGW hstr, const wchar_t* char_set)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return STRINGW_INVALID_SIZE;
@@ -847,12 +840,12 @@ size_t STRAPI StrgFindOneOf(HSTRINGW hstr, const wchar_t* char_set)
HSTRINGW STRAPI StrgCopy(HSTRINGW hstr)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return NULL;
HSTRINGW hCopy = StrgCreate();
- STRINGW* pCopy = ToWString(hCopy);
+ STRINGW* pCopy = ToWStrg(hCopy);
SetCopyW(pCopy, pstr->data_length, pstr->data);
return hCopy;
@@ -861,7 +854,7 @@ HSTRINGW STRAPI StrgCopy(HSTRINGW hstr)
HSTRINGW STRAPI StrgMid(HSTRINGW hstr, size_t start, size_t count)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return NULL;
@@ -873,7 +866,7 @@ HSTRINGW STRAPI StrgMid(HSTRINGW hstr, size_t start, size_t count)
assert(start + count <= pstr->data_length);
HSTRINGW hCopy = StrgCreate();
- STRINGW* pCopy = ToWString(hCopy);
+ STRINGW* pCopy = ToWStrg(hCopy);
if (start == 0 && start + count == pstr->data_length) {
SetCopyW(pCopy, pstr->data_length, pstr->data);
@@ -887,12 +880,12 @@ HSTRINGW STRAPI StrgMid(HSTRINGW hstr, size_t start, size_t count)
HSTRINGW STRAPI StrgLeft(HSTRINGW hstr, size_t count)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return NULL;
HSTRINGW hCopy = StrgCreate();
- STRINGW* pCopy = ToWString(hCopy);
+ STRINGW* pCopy = ToWStrg(hCopy);
if (count >= pstr->data_length) {
SetCopyW(pCopy, pstr->data_length, pstr->data);
@@ -905,12 +898,12 @@ HSTRINGW STRAPI StrgLeft(HSTRINGW hstr, size_t count)
HSTRINGW STRAPI StrgRight(HSTRINGW hstr, size_t count)
{
- STRINGW* pstr = ToWString(hstr);
+ STRINGW* pstr = ToWStrg(hstr);
if (!pstr)
return NULL;
HSTRINGW hCopy = StrgCreate();
- STRINGW* pCopy = ToWString(hCopy);
+ STRINGW* pCopy = ToWStrg(hCopy);
if (count >= pstr->data_length) {
SetCopyW(pCopy, pstr->data_length, pstr->data);
@@ -923,7 +916,7 @@ HSTRINGW STRAPI StrgRight(HSTRINGW hstr, size_t count)
void STRAPI StrgFormat(HSTRINGW hstr, const wchar_t* fmt, ...)
{
- STRINGW *pstr = ToWString(hstr);
+ STRINGW* const pstr = ToWStrg(hstr);
if (!pstr)
return;
va_list args;
@@ -932,3 +925,38 @@ void STRAPI StrgFormat(HSTRINGW hstr, const wchar_t* fmt, ...)
va_end(args);
}
+// --------------------------------------------------------------------------
+
+// Only for PathLib: ensure buffer size is at least MAX_PATH
+// NP3_PATH_LIB_IMPLEMENTATION
+
+wchar_t* STRAPI StrgAccessMaxPathBuf(HSTRINGW hstr, size_t min_len)
+{
+ STRINGW* pstr = ToWStrg(hstr);
+ if (!pstr)
+ return NULL;
+
+ if (pstr->alloc_length <= min_len) {
+ size_t old_len = 0;
+ wchar_t* pOld = CopyOldDataW(pstr, &old_len);
+ FreeBufferW(pstr);
+ SetCopyW(pstr, min_len, pOld);
+ FreeBuffer(pOld);
+ }
+ return pstr->data;
+}
+
+void STRAPI StrgSanitize(HSTRINGW hstr)
+{
+ STRINGW* pstr = ToWStrg(hstr);
+ if (!pstr)
+ return;
+ // ensure buffer limit
+ ptrdiff_t const len = (ptrdiff_t)pstr->alloc_length - 1;
+ if (len > 0) {
+ pstr->data[len] = L'\0';
+ }
+ pstr->data_length = StrlenW(pstr->data);
+}
+
+// --------------------------------------------------------------------------
diff --git a/src/DynStrg.h b/src/DynStrg.h
index ecaf6eab3..2e5b422a4 100644
--- a/src/DynStrg.h
+++ b/src/DynStrg.h
@@ -8,7 +8,11 @@
/* calls instead of using void* pointer */
/**************************************************/
#ifndef DECLARE_HANDLE
-#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
+#define DECLARE_HANDLE(name) \
+ struct name##__ { \
+ int unused; \
+ }; \
+ typedef struct name##__ *name
#endif
#define STRAPI __stdcall
@@ -23,7 +27,6 @@ DECLARE_HANDLE(HSTRINGW);
#define STRINGW_INVALID_SIZE ((size_t)-1)
HSTRINGW STRAPI StrgCreate();
-//~void STRAPI StrgReserveBuffer(HSTRINGW hstr, size_t len);
void STRAPI StrgDestroy(HSTRINGW hstr);
size_t STRAPI StrgGetLength(HSTRINGW hstr);
@@ -67,3 +70,11 @@ HSTRINGW STRAPI StrgRight(HSTRINGW hstr, size_t count);
void STRAPI StrgFormat(HSTRINGW hstr, const wchar_t* fmt, ...);
+
+// use for PathLib Only !
+#ifdef NP3_PATH_LIB_IMPLEMENTATION
+
+wchar_t* STRAPI StrgAccessMaxPathBuf(HSTRINGW hstr, size_t min_len);
+void STRAPI StrgSanitize(HSTRINGW hstr); // correct strg length after buffer access
+
+#endif
diff --git a/src/Helpers.c b/src/Helpers.c
index 2a64b77b1..45c341ed8 100644
--- a/src/Helpers.c
+++ b/src/Helpers.c
@@ -23,8 +23,7 @@
#include
#include
-//#include
-
+#include "PathLib.h"
#include "Edit.h"
#include "Encoding.h"
#include "MuiLanguage.h"
@@ -1625,8 +1624,8 @@ DWORD NormalizePathEx(LPWSTR lpszPath, DWORD cchBuffer, bool bRealPath, bool bSe
StringCchCopy(lpszPath, cchBuffer, p);
}
}
+ CloseHandle(hFile);
}
- CloseHandle(hFile);
}
return (DWORD)StringCchLen(lpszPath, cchBuffer);
diff --git a/src/Helpers.h b/src/Helpers.h
index 26e8cf7d9..49361f8de 100644
--- a/src/Helpers.h
+++ b/src/Helpers.h
@@ -807,42 +807,7 @@ void CloseApplication();
// ----------------------------------------------------------------------------
-inline bool PathIsExistingFile(LPCWSTR pszPath)
-{
- return (PathFileExists(pszPath) && !PathIsDirectory(pszPath));
-}
-
-// including and linking against pathcch.lib
-// api-ms-win-core-path-l1-1-0.dll library : Minimum supported client is Windows 8 :-/
-// so switch back to previous (deprecated) methods:
-inline HRESULT PathCchAppend(PWSTR p,size_t l,PCWSTR a)
-{
- UNREFERENCED_PARAMETER(l);
- return (PathAppend(p,a) ? S_OK : E_FAIL);
-}
-inline HRESULT PathCchCanonicalize(PWSTR p,size_t l,PCWSTR a)
-{
- UNREFERENCED_PARAMETER(l);
- return (PathCanonicalize(p,a) ? S_OK : E_FAIL);
-}
-inline HRESULT PathCchRenameExtension(PWSTR p,size_t l,PCWSTR a)
-{
- UNREFERENCED_PARAMETER(l);
- return (PathRenameExtension(p,a) ? S_OK : E_FAIL);
-}
-inline HRESULT PathCchRemoveFileSpec(PWSTR p,size_t l)
-{
- UNREFERENCED_PARAMETER(l);
- return (PathRemoveFileSpec(p) ? S_OK : E_FAIL);
-}
-
-inline bool IsReadOnly(const DWORD dwFileAttr)
-{
- return ((dwFileAttr != INVALID_FILE_ATTRIBUTES) && (dwFileAttr & FILE_ATTRIBUTE_READONLY));
-}
-
-inline int PointSizeToFontHeight(const float fPtHeight, const HDC hdc)
-{
+inline int PointSizeToFontHeight(const float fPtHeight, const HDC hdc) {
return -MulDiv(float2int(fPtHeight * 100.0f), GetDeviceCaps(hdc, LOGPIXELSY), 72 * SC_FONT_SIZE_MULTIPLIER);
}
diff --git a/src/MuiLanguage.c b/src/MuiLanguage.c
index 8bdf10815..6d14ed2df 100644
--- a/src/MuiLanguage.c
+++ b/src/MuiLanguage.c
@@ -20,6 +20,7 @@
#include
#include
+#include "PathLib.h"
#include "Dialogs.h"
#include "Encoding.h"
#include "Config/Config.h"
diff --git a/src/Notepad3.c b/src/Notepad3.c
index 3d12bb605..453dae7a8 100644
--- a/src/Notepad3.c
+++ b/src/Notepad3.c
@@ -28,6 +28,7 @@
#include
//#include
+#include "PathLib.h"
#include "Edit.h"
#include "Styles.h"
#include "Dialogs.h"
diff --git a/src/Notepad3.vcxproj b/src/Notepad3.vcxproj
index ff57934c3..9a2644c1f 100644
--- a/src/Notepad3.vcxproj
+++ b/src/Notepad3.vcxproj
@@ -623,6 +623,7 @@
+
@@ -780,6 +781,7 @@
+
diff --git a/src/Notepad3.vcxproj.filters b/src/Notepad3.vcxproj.filters
index e779b1604..57d92bd8b 100644
--- a/src/Notepad3.vcxproj.filters
+++ b/src/Notepad3.vcxproj.filters
@@ -423,6 +423,9 @@
Source Files
+
+ Source Files
+
@@ -605,6 +608,9 @@
Header Files
+
+ Header Files
+
diff --git a/src/PathLib.c b/src/PathLib.c
new file mode 100644
index 000000000..13c82028e
--- /dev/null
+++ b/src/PathLib.c
@@ -0,0 +1,319 @@
+
+// ============================================================================
+//
+// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
+//
+// https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation
+//
+// In the Windows API (with some exceptions discussed in the following paragraphs),
+// the maximum length for a path is MAX_PATH, which is defined as 260 characters.
+// A local path is structured in the following order: drive letter, colon, backslash,
+// name components separated by backslashes, and a terminating null character.
+// For example, the maximum path on drive D is "D:\some 256-character path string"
+// where "" represents the invisible terminating null character for the current
+// system codepage.
+// (The characters < > are used here for visual clarity and cannot be part of a valid path string.)
+//
+// The Windows API has many functions that also have Unicode versions to permit an
+// extended-length path for a maximum total path length of 32767 characters.
+// This type of path is composed of components separated by backslashes,
+// each up to the value returned in the lpMaximumComponentLength parameter of the
+// GetVolumeInformation function (this value is commonly 255 characters).
+// To specify an extended-length path, use the "\\?\" prefix. For example,
+// "\\?\D:\very long path".
+//
+// The "\\?\" prefix can also be used with paths constructed according to the universal
+// naming convention (UNC). To specify such a path using UNC, use the "\\?\UNC\" prefix.
+// For example, "\\?\UNC\server\share", where "server" is the name of the computer and
+// "share" is the name of the shared folder.
+// These prefixes are not used as part of the path itself.
+// They indicate that the path should be passed to the system with minimal modification,
+// which means that you cannot use forward slashes to represent path separators,
+// or a period to represent the current directory, or double dots to represent the
+// parent directory. Because you cannot use the "\\?\" prefix with a relative path,
+// relative paths are always limited to a total of MAX_PATH characters.
+//
+// There is no need to perform any Unicode normalization on path and file name strings
+// for use by the Windows file I/O API functions because the file system treats path and
+// file names as an opaque sequence of WCHARs. Any normalization that your application
+// requires should be performed with this in mind, external of any calls to related
+// Windows file I/O API functions.
+//
+// When using an API to create a directory, the specified path cannot be so long that you
+// cannot append an 8.3 file name (that is, the directory name cannot exceed MAX_PATH minus 12).
+//
+// The shell and the file system have different requirements.
+// It is possible to create a path with the Windows API that the shell user interface
+// is not able to interpret properly.
+//
+// ============================================================================
+
+// ============================================================================
+// TODO: if (IsWindows10OrGreater() && OptInRemovedMaxPathLimit()) {}
+// https://docs.microsoft.com/de-de/windows/win32/api/fileapi/nf-fileapi-getfileattributesa
+//
+// These are the directory management functions that no longer have MAX_PATH restrictions
+// if you opt - in to long path behavior :
+// - CreateDirectoryW
+// - CreateDirectoryExW
+// - GetCurrentDirectoryW
+// - RemoveDirectoryW
+// - SetCurrentDirectoryW
+//
+// These are the file management functions that no longer have MAX_PATH restrictions
+// if you opt - in to long path behavior :
+// - CopyFileW
+// - CopyFile2
+// - CopyFileExW
+// - CreateFileW
+// - CreateFile2
+// - CreateHardLinkW
+// - CreateSymbolicLinkW
+// - DeleteFileW
+// - FindFirstFileW
+// - FindFirstFileExW
+// - FindNextFileW
+// - GetFileAttributesW
+// - GetFileAttributesExW
+// - SetFileAttributesW
+// - GetFullPathNameW
+// - GetLongPathNameW
+// - MoveFileW
+// - MoveFileExW
+// - MoveFileWithProgressW
+// - ReplaceFileW
+// - SearchPathW
+// - FindFirstFileNameW
+// - FindNextFileNameW
+// - FindFirstStreamW
+// - FindNextStreamW
+// - GetCompressedFileSizeW
+// - GetFinalPathNameByHandleW
+//
+// ============================================================================
+
+#if !defined(WINVER)
+#define WINVER 0x602 /*_WIN32_WINNT_WIN8*/
+#endif
+#if !defined(_WIN32_WINNT)
+#define _WIN32_WINNT 0x602 /*_WIN32_WINNT_WIN8*/
+#endif
+#if !defined(NTDDI_VERSION)
+#define NTDDI_VERSION 0x06020000 /*NTDDI_WIN7*/
+#endif
+
+#define VC_EXTRALEAN 1
+#define WIN32_LEAN_AND_MEAN 1
+#include
+
+// get rid of this:
+#include
+
+#include
+#include
+#include
+#include
+
+#define NP3_PATH_LIB_IMPLEMENTATION 1
+
+#include "DynStrg.h"
+#include "PathLib.h"
+
+
+/**************************************************/
+/* */
+/* PRIVATE API */
+/* */
+/**************************************************/
+
+const wchar_t* const LONG_PATH_PREFIX = L"\\\\?\\";
+
+static bool OptInRemoveMaxPathLimit()
+{
+ static int s_MaxPathLimitRemoved = -1;
+
+ switch (s_MaxPathLimitRemoved) {
+
+ case -1: {
+ // Function pointer to driver function
+ BOOLEAN(WINAPI * pRtlAreLongPathsEnabled)(void) = NULL;
+ s_MaxPathLimitRemoved = 0; // at least called once
+ HINSTANCE const hNTdllDll = LoadLibrary(L"ntdll.dll");
+ if (hNTdllDll) {
+ // get the function pointer to RtlAreLongPathsEnabled
+ pRtlAreLongPathsEnabled = (BOOLEAN(WINAPI*)(void))GetProcAddress(hNTdllDll, "RtlAreLongPathsEnabled");
+ if (pRtlAreLongPathsEnabled != NULL) {
+ s_MaxPathLimitRemoved = pRtlAreLongPathsEnabled() ? 1 : 0;
+ }
+ FreeLibrary(hNTdllDll);
+ }
+ return (s_MaxPathLimitRemoved == 1);
+ }
+
+ case 1:
+ return true;
+
+ default:
+ break;
+ }
+ return false;
+}
+// ----------------------------------------------------------------------------
+
+
+__forceinline HSTRINGW ToHStrgW(HPATHL hpth)
+{
+ if (!hpth)
+ return NULL;
+ return (HSTRINGW)hpth;
+}
+// ----------------------------------------------------------------------------
+
+
+/**************************************************/
+/* */
+/* PUBLIC API */
+/* */
+/**************************************************/
+
+HPATHL PTHAPI Path_Allocate(const wchar_t* path)
+{
+ HSTRINGW hstr = StrgCreate();
+ if (path) {
+ StrgSet(hstr, path);
+ }
+ return (HPATHL)hstr;
+}
+// ----------------------------------------------------------------------------
+
+
+void PTHAPI Path_Release(HPATHL hpth)
+{
+ HSTRINGW hstr = ToHStrgW(hpth);
+ StrgDestroy(hstr);
+}
+// ----------------------------------------------------------------------------
+
+
+int PTHAPI Path_Reset(HPATHL hpth, const wchar_t* path)
+{
+ HSTRINGW hstr = ToHStrgW(hpth);
+ return StrgSet(hstr, path);
+}
+// ----------------------------------------------------------------------------
+
+
+size_t PTHAPI Path_GetLength(HPATHL hpth)
+{
+ HSTRINGW hstr = ToHStrgW(hpth);
+ return StrgGetLength(hstr);
+}
+// ----------------------------------------------------------------------------
+
+
+bool PTHAPI Path_RemoveFileSpec(HPATHL hpth)
+{
+ HSTRINGW hstr = ToHStrgW(hpth);
+ if (!hpth)
+ return false;
+
+ LPWSTR wbuf = StrgAccessMaxPathBuf(hstr, MAX_PATH);
+ size_t cch = StrgGetAllocLength(hstr);
+
+ bool const bOK = SUCCEEDED(PathCchRemoveFileSpec(wbuf, cch));
+ StrgSanitize(hstr);
+
+ return bOK;
+}
+// ----------------------------------------------------------------------------
+
+
+void PTHAPI Path_ExpandEnvStrings(HPATHL hpth)
+{
+ HSTRINGW hstr = ToHStrgW(hpth);
+ if (!hpth)
+ return;
+
+ LPCWSTR const path_buf = StrgGet(hstr);
+
+ HSTRINGW hExPath = StrgCreate();
+
+ size_t const min_len = max(ExpandEnvironmentStrings(path_buf, NULL, 0), MAX_PATH);
+ LPWSTR expth_buf = StrgAccessMaxPathBuf(hExPath, min_len);
+
+ DWORD const nSize = (DWORD)StrgGetAllocLength(hExPath);
+ ExpandEnvironmentStrings(path_buf, expth_buf, nSize);
+ StrgSanitize(hExPath);
+
+ StrgSet(hstr, expth_buf);
+
+ StrgDestroy(hExPath);
+}
+// ----------------------------------------------------------------------------
+
+
+bool PTHAPI Path_IsExistingFile(HPATHL hpth)
+{
+ HSTRINGW hstr = ToHStrgW(hpth);
+ if (!hpth)
+ return false;
+
+ HSTRINGW hxpth = StrgCopy(hstr);
+ if (!OptInRemoveMaxPathLimit()) {
+ StrgInsert(hxpth, 0, L"\\\\?\\");
+ }
+ LPCWSTR expth_buf = StrgAccessMaxPathBuf(hxpth, 1);
+
+ DWORD const dwFileAttrib = GetFileAttributesW(expth_buf);
+
+ bool const bAccessOK = (dwFileAttrib != INVALID_FILE_ATTRIBUTES);
+
+ //if (!bAccessOK) {
+ // DWORD const dwError = GetLastError();
+ // switch (dwError) {
+ // case ERROR_FILE_NOT_FOUND:
+ // break;
+ // case ERROR_PATH_NOT_FOUND:
+ // break;
+ // case ERROR_ACCESS_DENIED:
+ // break;
+ // default:
+ // break;
+ // }
+ //}
+
+ bool const bIsDirectory = (dwFileAttrib & FILE_ATTRIBUTE_DIRECTORY);
+
+ return (bAccessOK && !bIsDirectory);
+}
+// ----------------------------------------------------------------------------
+
+
+// ============================================================================
+// ============================================================================
+
+
+const wchar_t* PTHAPI Path_Get(HPATHL hpth)
+{
+ HSTRINGW hstr = ToHStrgW(hpth);
+ return StrgGet(hstr);
+}
+// ----------------------------------------------------------------------------
+
+size_t PTHAPI Path_GetBufCount(HPATHL hpth)
+{
+ HSTRINGW hstr = ToHStrgW(hpth);
+ return StrgGetAllocLength(hstr);
+}
+// ----------------------------------------------------------------------------
+
+
+// get wchar buffer with at least MAX_PATH size
+// TODO: get rid of this intermediate state handler
+wchar_t *PTHAPI Path_AccessBuf(HPATHL hpth, size_t len)
+{
+ HSTRINGW hstr = ToHStrgW(hpth);
+ return StrgAccessMaxPathBuf(hstr, max(len, MAX_PATH));
+}
+// ----------------------------------------------------------------------------
+
diff --git a/src/PathLib.h b/src/PathLib.h
new file mode 100644
index 000000000..0e58b34e3
--- /dev/null
+++ b/src/PathLib.h
@@ -0,0 +1,89 @@
+/****************************************************************/
+#pragma once
+
+/**************************************************/
+/* Declared in WINNT.H */
+/* */
+/* Provides bottom line type safety in function */
+/* calls instead of using void* pointer */
+/**************************************************/
+#ifndef DECLARE_HANDLE
+#define DECLARE_HANDLE(name) \
+ struct name##__ { \
+ int unused; \
+ }; \
+ typedef struct name##__ *name
+#endif
+
+#define PTHAPI __stdcall
+
+DECLARE_HANDLE(HPATHL);
+
+
+/**************************************************/
+/* */
+/* DYNAMIC WIDCHAR LONG PATH */
+/* */
+/**************************************************/
+
+HPATHL PTHAPI Path_Allocate(const wchar_t* path);
+void PTHAPI Path_Release(HPATHL hstr);
+int PTHAPI Path_Reset(HPATHL hpth, const wchar_t* path);
+size_t PTHAPI Path_GetLength(HPATHL hpth);
+bool PTHAPI Path_RemoveFileSpec(HPATHL hpth);
+void PTHAPI Path_ExpandEnvStrings(HPATHL hpth);
+bool PTHAPI Path_IsExistingFile(HPATHL hpth);
+
+// -------------------------------------------------------
+
+const wchar_t* PTHAPI Path_Get(HPATHL hpth);
+size_t PTHAPI Path_GetBufCount(HPATHL hpth);
+
+// get wchar buffer with at least MAX_PATH size
+// TODO: get rid of this intermediate state handler
+wchar_t* PTHAPI Path_AccessBuf(HPATHL hpth, size_t len);
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+
+inline bool PathIsExistingFile(LPCWSTR pszPath)
+{
+ return (PathFileExists(pszPath) && !PathIsDirectory(pszPath));
+}
+
+inline bool IsReadOnly(const DWORD dwFileAttr)
+{
+ return ((dwFileAttr != INVALID_FILE_ATTRIBUTES) && (dwFileAttr & FILE_ATTRIBUTE_READONLY));
+}
+
+#ifndef NP3_PATH_LIB_IMPLEMENTATION
+
+// including and linking against pathcch.lib
+// api-ms-win-core-path-l1-1-0.dll library : Minimum supported client is Windows 8 :-/
+// so switch back to previous (deprecated) methods:
+
+inline HRESULT PathCchAppend(PWSTR p, size_t l, PCWSTR a)
+{
+ UNREFERENCED_PARAMETER(l);
+ return (PathAppend(p, a) ? S_OK : S_FALSE);
+}
+inline HRESULT PathCchCanonicalize(PWSTR p, size_t l, PCWSTR a)
+{
+ UNREFERENCED_PARAMETER(l);
+ return (PathCanonicalize(p, a) ? S_OK : S_FALSE);
+}
+inline HRESULT PathCchRenameExtension(PWSTR p, size_t l, PCWSTR a)
+{
+ UNREFERENCED_PARAMETER(l);
+ return (PathRenameExtension(p, a) ? S_OK : S_FALSE);
+}
+inline HRESULT PathCchRemoveFileSpec(PWSTR p, size_t l)
+{
+ UNREFERENCED_PARAMETER(l);
+ return (PathRemoveFileSpec(p) ? S_OK : S_FALSE);
+}
+
+#endif
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
diff --git a/src/Styles.c b/src/Styles.c
index 6d89ce6fa..f8e112b6d 100644
--- a/src/Styles.c
+++ b/src/Styles.c
@@ -29,6 +29,7 @@
#include "uthash/utarray.h"
+#include "PathLib.h"
#include "Edit.h"
#include "Dialogs.h"
#include "Encoding.h"