Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Build/rNotepad3.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[Notepad3]
Notepad3.ini=%USERPROFILE%\Notepad3\Notepad3.ini
[Settings2]
DefaultDirectory=%CSIDL:MYDOCUMENTS%
472 changes: 472 additions & 0 deletions minipath/plans/minipath-longpath-migration.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion minipath/res/MiniPath.exe.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<asmv3:windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
<ws2:longPathAware xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</ws2:longPathAware>
<!-- longPathAware removed: MiniPath still uses fixed MAX_PATH buffers -->
<gdiScaling xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">false</gdiScaling> <!-- if set true, no WM_DPICHANGED message is send -->
<heapType xmlns="http://schemas.microsoft.com/SMI/2020/WindowsSettings">SegmentHeap</heapType>
</asmv3:windowsSettings>
Expand Down
26 changes: 16 additions & 10 deletions src/DynStrg.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,18 @@ static void ReAllocW(STRINGW* pstr, size_t len)
}
}
else if (pstr->alloc_length < alloc_len) {
pstr->data = ReAllocBuffer(pstr->data, alloc_len, false);
pstr->alloc_length = LengthOfBuffer(pstr->data);
assert("inconsistent data 1" && (alloc_len == pstr->alloc_length));
/// original memory block is moved, so data_length is not touched
assert("inconsistent data 2" && (alloc_len > pstr->data_length));
pstr->data[pstr->data_length] = WCHR_NULL; // ensure terminating zero
// apply 1.5x growth factor to amortize repeated reallocations
size_t const grow_len = pstr->alloc_length + (pstr->alloc_length >> 1);
size_t const new_alloc = min_s(max_s(alloc_len, grow_len), STRINGW_MAX_CCH);
LPWSTR new_data = ReAllocBuffer(pstr->data, new_alloc, false);
if (new_data) {
pstr->data = new_data;
pstr->alloc_length = LengthOfBuffer(pstr->data);
assert("inconsistent data 1" && (pstr->alloc_length >= alloc_len));
/// original memory block is moved, so data_length is not touched
assert("inconsistent data 2" && (pstr->alloc_length > pstr->data_length));
pstr->data[pstr->data_length] = WCHR_NULL; // ensure terminating zero
}
}
else {
ZeroMemory(&(pstr->data[pstr->data_length]), (pstr->alloc_length - pstr->data_length) * sizeof(wchar_t));
Expand All @@ -185,7 +191,7 @@ static void AllocCopyW(STRINGW* pstr, STRINGW* pDest, size_t copy_len, size_t co
{
ReAllocW(pDest, new_len);
StringCchCopyNW(pDest->data, pDest->alloc_length, (pstr->data + copy_index), copy_len);
pDest->data_length = StrlenW(pstr->data);
pDest->data_length = StrlenW(pDest->data);
}
}
// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -801,7 +807,7 @@ size_t STRAPI StrgRemoveCh(HSTRINGW hstr, const wchar_t chRemove)
}
if (dest)
*dest = WCHR_NULL;
count = (int)(ptrdiff_t)(source - dest);
count = (size_t)(source - dest);
pstr->data_length -= count;

return count;
Expand Down Expand Up @@ -862,7 +868,7 @@ void STRAPI StrgToUpper(HSTRINGW hstr)
ReAllocW(pstr, 0);
}
if (pstr->data)
_wcsupr_s(pstr->data, pstr->data_length);
_wcsupr_s(pstr->data, pstr->data_length + 1);
}
// ----------------------------------------------------------------------------

Expand All @@ -876,7 +882,7 @@ void STRAPI StrgToLower(HSTRINGW hstr)
ReAllocW(pstr, 0);
}
if (pstr->data)
_wcslwr_s(pstr->data, pstr->data_length);
_wcslwr_s(pstr->data, pstr->data_length + 1);
}
// ----------------------------------------------------------------------------

Expand Down
80 changes: 49 additions & 31 deletions src/MuiLanguage.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,34 +266,41 @@ unsigned GetMUILanguageIndexByLocaleName(LPCWSTR pLocaleName) {
//
// CheckAvailableLanguages
//
static bool s_bFullLngScanDone = false;

static bool _CheckLanguageDLL(unsigned lng)
{
if (lng == 0 || lng >= MuiLanguages_CountOf()) {
return (lng == 0); // internal (index 0) is always available
}
if (!IsValidLocaleName(MUI_LanguageDLLs[lng].LocaleName)) {
return false;
}
#if (defined(_DEBUG) || defined(DEBUG)) && !defined(NDEBUG)
WCHAR wchLngLocalName[LOCALE_NAME_MAX_LENGTH + 1];
if (ResolveLocaleName(MUI_LanguageDLLs[lng].LocaleName, wchLngLocalName, COUNTOF(wchLngLocalName))) {
assert(IsSameLocale(MUI_LanguageDLLs[lng].LocaleName, wchLngLocalName) && "Problem with Locale Name of Language!");
}
#endif
WCHAR wchRelPath[SMALL_BUFFER] = { L'\0' };
StringCchPrintf(wchRelPath, COUNTOF(wchRelPath), L"lng/%s/np3lng.dll.mui", MUI_LanguageDLLs[lng].LocaleName);
HPATHL hpth = Path_Allocate(wchRelPath);
Path_AbsoluteFromApp(hpth, false);
bool const bAvail = Path_IsExistingFile(hpth);
Path_Release(hpth);
MUI_LanguageDLLs[lng].bHasDLL = bAvail;
return bAvail;
}

static unsigned _CheckAvailableLanguageDLLs()
{
unsigned count = 1; // internal instance always available

HPATHL hpth = Path_Allocate(NULL);

for (unsigned lng = 1; lng < MuiLanguages_CountOf(); ++lng) {

if (IsValidLocaleName(MUI_LanguageDLLs[lng].LocaleName)) {

#if (defined(_DEBUG) || defined(DEBUG)) && !defined(NDEBUG)
WCHAR wchLngLocalName[LOCALE_NAME_MAX_LENGTH + 1];
if (ResolveLocaleName(MUI_LanguageDLLs[lng].LocaleName, wchLngLocalName, COUNTOF(wchLngLocalName))) {
//~StringCchCopy(MUI_LanguageDLLs[lng].LocaleName, COUNTOF(MUI_LanguageDLLs[lng].LocaleName), wchLngLocalName); // put back resolved name
assert(IsSameLocale(MUI_LanguageDLLs[lng].LocaleName, wchLngLocalName) && "Problem with Locale Name of Language!");
}
#endif
// check for DLL
WCHAR wchRelPath[SMALL_BUFFER] = { L'\0' };
StringCchPrintf(wchRelPath, COUNTOF(wchRelPath), L"lng/%s/np3lng.dll.mui", MUI_LanguageDLLs[lng].LocaleName);
Path_Reset(hpth, wchRelPath);
Path_AbsoluteFromApp(hpth, false);
bool const bAvail = Path_IsExistingFile(hpth);
MUI_LanguageDLLs[lng].bHasDLL = bAvail;
count += bAvail ? 1 : 0;
if (_CheckLanguageDLL(lng)) {
++count;
}
}
Path_Release(hpth);
s_bFullLngScanDone = true;
return count;
}

Expand Down Expand Up @@ -344,22 +351,28 @@ unsigned LoadLanguageResources(LPCWSTR pLocaleName) {

unsigned const iInternalLngIndex = max_u(0, GetMUILanguageIndexByLocaleName(MUI_BASE_LNG_ID));

// 1st check language resources
Globals.uAvailLngCount = _CheckAvailableLanguageDLLs();

// set the appropriate fallback list
// Check only the preferred locale's DLL on startup (defer full scan to menu population)
unsigned iLngIndex = MuiLanguages_CountOf();
WCHAR tchAvailLngs[2 * (LOCALE_NAME_MAX_LENGTH + 1)] = { L'\0' };
for (unsigned lng = 0; lng < MuiLanguages_CountOf(); ++lng) {
if (StrCmpIW(MUI_LanguageDLLs[lng].LocaleName, pLocaleName) == 0) {
if (MUI_LanguageDLLs[lng].bHasDLL && (lng > 0)) {
StringCchCatW(tchAvailLngs, COUNTOF(tchAvailLngs), MUI_LanguageDLLs[lng].LocaleName);
StringCchCatW(tchAvailLngs, COUNTOF(tchAvailLngs), L";");
}
iLngIndex = lng;
if (lng > 0 && !s_bFullLngScanDone) {
_CheckLanguageDLL(lng); // check only the preferred locale
}
break;
}
}
if (!s_bFullLngScanDone) {
// Set count > 1 so language menu creation is not skipped prematurely
Globals.uAvailLngCount = MuiLanguages_CountOf();
}

// set the appropriate fallback list
WCHAR tchAvailLngs[2 * (LOCALE_NAME_MAX_LENGTH + 1)] = { L'\0' };
if (iLngIndex < MuiLanguages_CountOf() && MUI_LanguageDLLs[iLngIndex].bHasDLL && (iLngIndex > 0)) {
StringCchCatW(tchAvailLngs, COUNTOF(tchAvailLngs), MUI_LanguageDLLs[iLngIndex].LocaleName);
StringCchCatW(tchAvailLngs, COUNTOF(tchAvailLngs), L";");
}
StringCchCatW(tchAvailLngs, COUNTOF(tchAvailLngs), MUI_LanguageDLLs[iInternalLngIndex].LocaleName); // en-US fallback

// NOTES:
Expand Down Expand Up @@ -473,6 +486,11 @@ static HMENU s_hmenuLanguage = NULL;

bool InsertLanguageMenu(HMENU hMenuBar) {

// Perform full language DLL scan if deferred from startup
if (!s_bFullLngScanDone) {
Globals.uAvailLngCount = _CheckAvailableLanguageDLLs();
}

// check, if we need a language switching menu
if (Globals.uAvailLngCount < 2) {
Settings.PreferredLocale4DateFmt = false;
Expand Down
67 changes: 53 additions & 14 deletions src/Notepad3.c
Original file line number Diff line number Diff line change
Expand Up @@ -968,7 +968,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
#endif

_InitGlobals();
InitDarkMode();
// Dark mode init deferred to after LoadSettings() — see below

// Windows Class name
StringCchCopy(s_wchWndClass, COUNTOF(s_wchWndClass), _W(SAPPNAME));
Expand Down Expand Up @@ -1046,7 +1046,13 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
Scintilla_RegisterClasses(hInstance);

#ifdef D_NP3_WIN10_DARK_MODE
SetDarkMode(IsDarkModeSupported() && IsSettingDarkMode()); // settings
// Init dark mode after settings are loaded — skip UxTheme loading for explicit light mode
if (Settings.WinThemeDarkMode != WINDSPMOD_LIGHT) {
SetDarkMode(true); // probe: load UxTheme.dll, detect OS dark mode support
if (!IsSettingDarkMode()) {
SetDarkMode(false); // OS or user says light mode
}
}
#endif

HRSRC const hRes = FindResourceEx(hInstance, RT_RCDATA, MAKEINTRESOURCE(IDR_STD_DARKMODE_THEME),
Expand Down Expand Up @@ -1451,7 +1457,14 @@ static BOOL CALLBACK _EnumWndProc(HWND hwnd, LPARAM lParam)

if (StrCmpW(szClassName, s_wchWndClass) == 0) {

UINT const iReuseLock = GetDlgItemInt(hwnd, IDC_REUSELOCK, NULL, FALSE);
WCHAR wchReuseLock[32] = { L'\0' };
DWORD_PTR dwResult = 0;
HWND const hCtl = GetDlgItem(hwnd, IDC_REUSELOCK);
if (!hCtl || SendMessageTimeout(hCtl, WM_GETTEXT, COUNTOF(wchReuseLock),
(LPARAM)wchReuseLock, SMTO_ABORTIFHUNG | SMTO_BLOCK, 500, &dwResult) == 0) {
return TRUE; // skip unresponsive instance
}
UINT const iReuseLock = (UINT)wcstoul(wchReuseLock, NULL, 10);
if ((GetTicks_ms() - iReuseLock) >= REUSEWINDOWLOCKTIMEOUT) {

*(HWND*)lParam = hwnd;
Expand Down Expand Up @@ -1480,7 +1493,12 @@ static BOOL CALLBACK _EnumWndProc2(HWND hwnd, LPARAM lParam)
if (StrCmpW(szClassName, s_wchWndClass) == 0) {

WCHAR wchFileName[INTERNET_MAX_URL_LENGTH] = { L'\0' };
GetDlgItemText(hwnd, IDC_FILENAME, wchFileName, COUNTOF(wchFileName));
DWORD_PTR dwResult = 0;
HWND const hCtl = GetDlgItem(hwnd, IDC_FILENAME);
if (!hCtl || SendMessageTimeout(hCtl, WM_GETTEXT, COUNTOF(wchFileName),
(LPARAM)wchFileName, SMTO_ABORTIFHUNG | SMTO_BLOCK, 500, &dwResult) == 0) {
return TRUE; // skip unresponsive instance
}

HPATHL hpthFileName = Path_Allocate(wchFileName);
if (Path_StrgComparePath(hpthFileName, s_pthCheckFilePath, Paths.WorkingDirectory, true) == 0) {
Expand Down Expand Up @@ -1771,17 +1789,39 @@ HWND InitInstance(const HINSTANCE hInstance, int nCmdShow)
SetWindowTransparentMode(hwndMain, true, Settings2.OpacityLevel);
}

// Determine if starting minimized/tray (don't show window early in that case)
bool const bStartMinimized = s_flagStartAsTrayIcon || (nCmdShow == SW_MINIMIZE) || (nCmdShow == SW_SHOWMINIMIZED);

// Show window frame early for faster perceived startup — the user sees
// the window (with initial toolbar from WM_CREATE) while we re-create bars
if (!bStartMinimized) {
if (!Settings.ShowTitlebar) {
SetWindowLong(hwndMain, GWL_STYLE, GetWindowLong(hwndMain, GWL_STYLE) & ~WS_CAPTION);
}
SetWindowPos(hwndMain, Settings.AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
}

CreateBars(hwndMain, hInstance);

SetMenu(hwndMain, (Settings.ShowMenubar ? Globals.hMainMenu : NULL));
DrawMenuBar(hwndMain);

// Force layout recalculation after toolbar/statusbar re-creation
// (early ShowWindow already triggered WM_SIZE with old child windows)
if (!bStartMinimized) {
RECT rc;
GetClientRect(hwndMain, &rc);
SendMessage(hwndMain, WM_SIZE, SIZE_RESTORED, MAKELPARAM(rc.right, rc.bottom));
}

Globals.hwndMain = hwndMain; // make main window globaly available
SetWindowAppUserModelID(hwndMain, Settings2.AppUserModelID);

HPATHL hfile_pth = Path_Copy(s_pthArgFilePath);
FileLoadFlags fLoadFlags = FLF_None;

// Source Encoding
Encoding_Forced(s_flagSetEncoding);

Expand All @@ -1807,15 +1847,13 @@ HWND InitInstance(const HINSTANCE hInstance, int nCmdShow)

ShowWindowAsync(s_hwndEditFrame, SW_SHOWDEFAULT);
ShowWindowAsync(Globals.hwndEdit, SW_SHOWDEFAULT);
//~SnapToWinInfoPos(hwndMain, g_IniWinInfo, SCR_NORMAL, SW_HIDE); ~ instead set all needed properties here:
SetWindowPos(hwndMain, Settings.AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

UpdateWindow(hwndMain);
if (!Settings.ShowTitlebar) {
SetWindowLong(hwndMain, GWL_STYLE, GetWindowLong(hwndMain, GWL_STYLE) & ~WS_CAPTION);
}

if (s_flagStartAsTrayIcon || (nCmdShow == SW_MINIMIZE) || (nCmdShow == SW_SHOWMINIMIZED)) {
if (bStartMinimized) {
//~SnapToWinInfoPos(hwndMain, g_IniWinInfo, SCR_NORMAL, SW_HIDE);
SetWindowPos(hwndMain, Settings.AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
if (!Settings.ShowTitlebar) {
SetWindowLong(hwndMain, GWL_STYLE, GetWindowLong(hwndMain, GWL_STYLE) & ~WS_CAPTION);
}
if (Settings.MinimizeToTray) {
MinimizeWndToTray(hwndMain);
}
Expand All @@ -1824,7 +1862,8 @@ HWND InitInstance(const HINSTANCE hInstance, int nCmdShow)
}
}
else {
ShowWindow(hwndMain, nCmdShow);
// Window was already shown above; ensure children are painted
UpdateWindow(hwndMain);
}

bool bOpened = false;
Expand Down
Loading