Help CharNext handle surrogate pairs

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@7122 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2019-09-15 17:10:26 +00:00
parent 24d4c2678a
commit 27c8277a82

View file

@ -42,7 +42,6 @@ HWND g_hwndList;
HINSTANCE g_hInst;
void ExecScript(BOOL log);
void LogMessage(const TCHAR *pStr, BOOL bOEM);
TCHAR *my_strstr(TCHAR *a, TCHAR *b);
unsigned int my_atoi(TCHAR *s);
int WINAPI AsExeWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow);
@ -70,9 +69,19 @@ BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ul_reason_for_call, LPVOID lpReserved
return TRUE;
}
static BOOL IsLeadSurrogateUTF16(unsigned short c) {
return c >= 0xd800 && c <= 0xdbff;
static BOOL IsLeadSurrogateUTF16(unsigned short c) { return c >= 0xd800 && c <= 0xdbff; }
static BOOL IsTrailSurrogateUTF16(unsigned short c) { return c >= 0xdc00 && c <= 0xdfff; }
static PWSTR MyCharNext(PCWSTR p)
{
// Note: This is wrong for surrogate pair combining characters but CharNextW
// does not properly surrogate pairs so we have to manually handle the pairs.
if (!p[0]) return (PWSTR) p;
if (IsLeadSurrogateUTF16(p[0]) && IsTrailSurrogateUTF16(p[1])) return (PWSTR) p + 2; // Current is a surrogate pair, we incorrectly assume that it is not followed by combining characters.
if (IsLeadSurrogateUTF16(p[1]) && IsTrailSurrogateUTF16(p[2])) return (PWSTR) p + 1; // Next is a surrogate pair, we incorrectly assume that it is not a combining character for the current character.
return (CharNextW)(p);
}
#define CharNextW MyCharNext
static void TruncateStringUTF16LE(LPWSTR Buffer, SIZE_T Length, LPCWSTR Overflow, SIZE_T lenOver) {
if (Length) {
@ -141,6 +150,28 @@ static BOOL IsWOW64() {
#endif
}
// Tim Kosse's LogMessage
#ifdef UNICODE
static void LogMessage(const TCHAR *pStr, BOOL bOEM) {
#else
static void LogMessage(TCHAR *pStr, BOOL bOEM) {
#endif
LVITEM item;
int nItemCount;
if (!g_hwndList) return;
//if (!*pStr) return;
#ifndef UNICODE
if (bOEM == TRUE) OemToCharBuff(pStr, pStr, lstrlen(pStr));
#endif
nItemCount=(int) SendMessage(g_hwndList, LVM_GETITEMCOUNT, 0, 0);
item.mask=LVIF_TEXT;
item.pszText=(TCHAR *)pStr;
item.cchTextMax=0;
item.iItem=nItemCount, item.iSubItem=0;
ListView_InsertItem(g_hwndList, &item);
ListView_EnsureVisible(g_hwndList, item.iItem, 0);
}
void ExecScript(int mode) {
TCHAR szRet[128];
@ -277,6 +308,8 @@ params:
SIZE_T cbSrcTot = sizeof(bufSrc), cbSrc = 0, cbSrcFree;
TCHAR *bufOutput = 0, *pNewAlloc, *pD;
SIZE_T cchAlloc, cbAlloc, cchFree;
pi.hProcess = pi.hThread = NULL;
codepage = bOEM ? CP_OEMCP : CP_ACP;
if (!ignoreData) {
@ -313,7 +346,6 @@ params:
si.hStdOutput = newstdout;
si.hStdError = newstdout;
if (!CreateProcess(NULL, g_exec, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
pi.hProcess = pi.hThread = NULL;
lstrcpy(szRet, _T("error"));
goto done;
}
@ -388,11 +420,11 @@ parseLines:
}
else { // DBCS --> ?:
if (utfOutput) { // DBCS --> UTF-16LE:
BOOL isMb = IsDBCSLeadByteEx(codepage,((CHAR*)pSrc)[0]);
BOOL isMb = IsDBCSLeadByteEx(codepage, ((CHAR*)pSrc)[0]);
if (isMb && cbSrc < ++cbSrcChar) {
goto readMore;
}
cchDstChar = MultiByteToWideChar(codepage,0,pSrc,cbSrcChar,(WCHAR*) bufCh,2);
cchDstChar = MultiByteToWideChar(codepage, 0, pSrc, cbSrcChar, (WCHAR*) bufCh, 2);
}
else { // DBCS --> DBCS:
bufCh[0] = ((CHAR*)pSrc)[0], cchDstChar = 1; // Note: OEM codepage will be converted by LogMessage
@ -426,7 +458,7 @@ resizeOutputBuffer:
goto waitForProcess;
}
cchAlloc += 1024, cbAlloc = cchAlloc / sizeof(TCHAR);
pNewAlloc = GlobalReAlloc(bufOutput,cbAlloc + sizeof(TCHAR),GPTR|GMEM_MOVEABLE); // Include "hidden" space for a \0
pNewAlloc = GlobalReAlloc(bufOutput, cbAlloc + sizeof(TCHAR),GPTR|GMEM_MOVEABLE); // Include "hidden" space for a \0
if (!pNewAlloc) {
lstrcpy(szRet, _T("error"));
ignoreData = TRUE;
@ -467,24 +499,6 @@ done:
}
}
// Tim Kosse's LogMessage
void LogMessage(const TCHAR *pStr, BOOL bOEM) {
LVITEM item={0};
int nItemCount;
if (!g_hwndList) return;
//if (!lstrlen(pStr)) return;
#ifndef _UNICODE
if (bOEM == TRUE) OemToCharBuff(pStr, (char*)pStr, lstrlen(pStr));
#endif
nItemCount=(int) SendMessage(g_hwndList, LVM_GETITEMCOUNT, 0, 0);
item.mask=LVIF_TEXT;
item.pszText=(TCHAR *)pStr;
item.cchTextMax=0;
item.iItem=nItemCount;
ListView_InsertItem(g_hwndList, &item);
ListView_EnsureVisible(g_hwndList, item.iItem, 0);
}
TCHAR *my_strstr(TCHAR *a, TCHAR *b)
{
int l = lstrlen(b);