From a2e1e1d96342feb6d66f616bff66cb7b88914b8c Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Sat, 9 May 2026 20:24:51 +0900 Subject: [PATCH] [NOTEPAD] Make loading file faster (#8938) Performance improvement. This PR will improve the speed of loading a large file. JIRA issue: CORE-19898 - Change 2 passes to 1 pass on ANSI/UTF-8, omitting precise buffer size calculation. - Change LocalReAlloc calls to LocalAlloc. - ReadText function now returns HLOCAL and no longer takes phLocal. --- base/applications/notepad/dialog.c | 10 ++- base/applications/notepad/notepad.h | 2 +- base/applications/notepad/text.c | 129 ++++++++++++++++++---------- 3 files changed, 92 insertions(+), 49 deletions(-) diff --git a/base/applications/notepad/dialog.c b/base/applications/notepad/dialog.c index 7185e4a0148..2a69fcae37d 100644 --- a/base/applications/notepad/dialog.c +++ b/base/applications/notepad/dialog.c @@ -342,7 +342,7 @@ VOID DoOpenFile(LPCTSTR szFileName) { HANDLE hFile; TCHAR log[5]; - HLOCAL hLocal; + HLOCAL hOldLocal, hNewLocal; /* Close any files and prompt to save changes */ if (!DoCloseFile()) @@ -360,13 +360,15 @@ VOID DoOpenFile(LPCTSTR szFileName) } /* To make loading file quicker, we use the internal handle of EDIT control */ - hLocal = (HLOCAL)SendMessageW(Globals.hEdit, EM_GETHANDLE, 0, 0); - if (!ReadText(hFile, &hLocal, &Globals.encFile, &Globals.iEoln)) + hOldLocal = (HLOCAL)SendMessageW(Globals.hEdit, EM_GETHANDLE, 0, 0); + hNewLocal = ReadText(hFile, &Globals.encFile, &Globals.iEoln); + if (!hNewLocal) { ShowLastError(); goto done; } - SendMessageW(Globals.hEdit, EM_SETHANDLE, (WPARAM)hLocal, 0); + SendMessageW(Globals.hEdit, EM_SETHANDLE, (WPARAM)hNewLocal, 0); + LocalFree(hOldLocal); /* No need of EM_SETMODIFY and EM_EMPTYUNDOBUFFER here. EM_SETHANDLE does instead. */ SetFocus(Globals.hEdit); diff --git a/base/applications/notepad/notepad.h b/base/applications/notepad/notepad.h index 1e65ea10de8..a7ad2f0a6f7 100644 --- a/base/applications/notepad/notepad.h +++ b/base/applications/notepad/notepad.h @@ -89,7 +89,7 @@ typedef struct extern NOTEPAD_GLOBALS Globals; -BOOL ReadText(HANDLE hFile, HLOCAL *phLocal, ENCODING *pencFile, EOLN *piEoln); +HLOCAL ReadText(HANDLE hFile, ENCODING *pencFile, EOLN *piEoln); BOOL WriteText(HANDLE hFile, LPCWSTR pszText, DWORD dwTextLen, ENCODING encFile, EOLN iEoln); void NOTEPAD_LoadSettingsFromRegistry(PWINDOWPLACEMENT pWP); diff --git a/base/applications/notepad/text.c b/base/applications/notepad/text.c index a0ad8640eb0..e9f4e08c5de 100644 --- a/base/applications/notepad/text.c +++ b/base/applications/notepad/text.c @@ -82,10 +82,11 @@ ReplaceNewLines(LPWSTR pszNew, SIZE_T cchNew, LPCWSTR pszOld, SIZE_T cchOld) static BOOL ProcessNewLinesAndNulls(HLOCAL *phLocal, LPWSTR *ppszText, SIZE_T *pcchText, EOLN *piEoln) { - SIZE_T ich, cchText = *pcchText, adwEolnCount[3] = { 0, 0, 0 }, cNonCRLFs; - LPWSTR pszText = *ppszText; + SIZE_T ich, cchText = *pcchText, adwEolnCount[3] = { 0, 0, 0 }, cNonCRLFs, cchNew; + LPWSTR pszText = *ppszText, pszNew; EOLN iEoln; BOOL bPrevCR = FALSE; + HLOCAL hLocal; /* Replace '\0' with SPACE. Count newlines. */ for (ich = 0; ich < cchText; ++ich) @@ -126,12 +127,19 @@ ProcessNewLinesAndNulls(HLOCAL *phLocal, LPWSTR *ppszText, SIZE_T *pcchText, EOL if (cNonCRLFs != 0) { /* Allocate a buffer for EM_SETHANDLE */ - SIZE_T cchNew = cchText + cNonCRLFs; - HLOCAL hLocal = LocalAlloc(LMEM_MOVEABLE, (cchNew + 1) * sizeof(WCHAR)); - LPWSTR pszNew = LocalLock(hLocal); + cchNew = cchText + cNonCRLFs; + hLocal = LocalAlloc(LMEM_MOVEABLE, (cchNew + 1) * sizeof(WCHAR)); + if (!hLocal) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; /* Failure */ + } + + pszNew = LocalLock(hLocal); if (!pszNew) { LocalFree(hLocal); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; /* Failure */ } @@ -149,8 +157,8 @@ ProcessNewLinesAndNulls(HLOCAL *phLocal, LPWSTR *ppszText, SIZE_T *pcchText, EOL return TRUE; } -BOOL -ReadText(HANDLE hFile, HLOCAL *phLocal, ENCODING *pencFile, EOLN *piEoln) +HLOCAL +ReadText(HANDLE hFile, ENCODING *pencFile, EOLN *piEoln) { LPBYTE pBytes = NULL; LPWSTR pszText, pszNewText = NULL; @@ -160,7 +168,7 @@ ReadText(HANDLE hFile, HLOCAL *phLocal, ENCODING *pencFile, EOLN *piEoln) ENCODING encFile; UINT iCodePage; HANDLE hMapping = INVALID_HANDLE_VALUE; - HLOCAL hNewLocal; + HLOCAL hNewLocal = NULL; dwSize = GetFileSize(hFile, NULL); if (dwSize == INVALID_FILE_SIZE) @@ -168,18 +176,26 @@ ReadText(HANDLE hFile, HLOCAL *phLocal, ENCODING *pencFile, EOLN *piEoln) if (dwSize == 0) // If file is empty { - hNewLocal = LocalReAlloc(*phLocal, sizeof(UNICODE_NULL), LMEM_MOVEABLE); - pszNewText = LocalLock(hNewLocal); - if (hNewLocal == NULL || pszNewText == NULL) + hNewLocal = LocalAlloc(LMEM_MOVEABLE, sizeof(UNICODE_NULL)); + if (!hNewLocal) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto done; + } + + pszNewText = LocalLock(hNewLocal); + if (!pszNewText) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } *pszNewText = UNICODE_NULL; LocalUnlock(hNewLocal); - *phLocal = hNewLocal; *piEoln = EOLN_CRLF; *pencFile = ENCODING_DEFAULT; - return TRUE; + return hNewLocal; } hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); @@ -217,15 +233,29 @@ ReadText(HANDLE hFile, HLOCAL *phLocal, ENCODING *pencFile, EOLN *piEoln) case ENCODING_UTF16BE: case ENCODING_UTF16LE: { - /* Re-allocate the buffer for EM_SETHANDLE */ - pszText = (LPWSTR) &pBytes[dwPos]; + /* Allocate the buffer for EM_SETHANDLE */ + pszText = (LPWSTR)&pBytes[dwPos]; cchText = (dwSize - dwPos) / sizeof(WCHAR); - hNewLocal = LocalReAlloc(*phLocal, (cchText + 1) * sizeof(WCHAR), LMEM_MOVEABLE); - pszNewText = LocalLock(hNewLocal); - if (pszNewText == NULL) + if (cchText >= MAXLONG / sizeof(WCHAR)) + { + SetLastError(ERROR_FILE_TOO_LARGE); goto done; + } + + hNewLocal = LocalAlloc(LMEM_MOVEABLE, (cchText + 1) * sizeof(WCHAR)); + if (!hNewLocal) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + + pszNewText = LocalLock(hNewLocal); + if (!pszNewText) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } - *phLocal = hNewLocal; CopyMemory(pszNewText, pszText, cchText * sizeof(WCHAR)); if (encFile == ENCODING_UTF16BE) /* big endian; Swap bytes */ @@ -245,34 +275,40 @@ ReadText(HANDLE hFile, HLOCAL *phLocal, ENCODING *pencFile, EOLN *piEoln) case ENCODING_UTF8: case ENCODING_UTF8BOM: { - iCodePage = ((encFile == ENCODING_UTF8 || encFile == ENCODING_UTF8BOM) ? CP_UTF8 : CP_ACP); - - /* Get ready for ANSI-to-Wide conversion */ + iCodePage = ((encFile == ENCODING_UTF8 || encFile == ENCODING_UTF8BOM) + ? CP_UTF8 : CP_ACP); cbContent = dwSize - dwPos; + if (cbContent >= MAXLONG / sizeof(WCHAR)) + { + SetLastError(ERROR_FILE_TOO_LARGE); + goto done; + } + + /* Allocate the buffer for EM_SETHANDLE */ + hNewLocal = LocalAlloc(LMEM_MOVEABLE, (cbContent + 1) * sizeof(WCHAR)); + if (!hNewLocal) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + + pszNewText = LocalLock(hNewLocal); + if (!pszNewText) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto done; + } + + /* Do conversion */ cchText = 0; if (cbContent > 0) { - cchText = MultiByteToWideChar(iCodePage, 0, (LPCSTR)&pBytes[dwPos], (INT)cbContent, NULL, 0); - if (cchText == 0) + cchText = MultiByteToWideChar(iCodePage, 0, + (LPCSTR)&pBytes[dwPos], (INT)cbContent, + pszNewText, (INT)cbContent); + if (!cchText) goto done; } - - /* Re-allocate the buffer for EM_SETHANDLE */ - hNewLocal = LocalReAlloc(*phLocal, (cchText + 1) * sizeof(WCHAR), LMEM_MOVEABLE); - pszNewText = LocalLock(hNewLocal); - if (!pszNewText) - goto done; - *phLocal = hNewLocal; - - /* Do ANSI-to-Wide conversion */ - if (cbContent > 0) - { - if (!MultiByteToWideChar(iCodePage, 0, (LPCSTR)&pBytes[dwPos], (INT)cbContent, - pszNewText, (INT)cchText)) - { - goto done; - } - } break; } @@ -281,7 +317,7 @@ ReadText(HANDLE hFile, HLOCAL *phLocal, ENCODING *pencFile, EOLN *piEoln) pszNewText[cchText] = UNICODE_NULL; - if (!ProcessNewLinesAndNulls(phLocal, &pszNewText, &cchText, piEoln)) + if (!ProcessNewLinesAndNulls(&hNewLocal, &pszNewText, &cchText, piEoln)) goto done; *pencFile = encFile; @@ -293,8 +329,13 @@ done: if (hMapping != INVALID_HANDLE_VALUE) CloseHandle(hMapping); if (pszNewText) - LocalUnlock(*phLocal); - return bSuccess; + LocalUnlock(hNewLocal); + if (!bSuccess && hNewLocal) + { + LocalFree(hNewLocal); + hNewLocal = NULL; + } + return hNewLocal; } static BOOL WriteEncodedText(HANDLE hFile, LPCWSTR pszText, DWORD dwTextLen, ENCODING encFile)