https://git.reactos.org/?p=reactos.git;a=commitdiff;h=17d4df8102562e22bd8f88...
commit 17d4df8102562e22bd8f88af689cf1cb4f986850 Author: Baruch Rutman peterooch@gmail.com AuthorDate: Fri Sep 28 18:02:38 2018 +0300 Commit: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org CommitDate: Mon Oct 8 16:16:52 2018 +0200
[USER32] Implement UserLpkPSMTextOut(). (#890)
This function is a condensed version of LpkPSMTextOut() (from lpk.dll), but not bug-for-bug equivalent. The main difference is that the underscore is drawn without taking into account any kind of script processing. --- win32ss/user/user32/misc/stubs.c | 8 --- win32ss/user/user32/user32.spec | 2 +- win32ss/user/user32/windows/font.c | 112 +++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 9 deletions(-)
diff --git a/win32ss/user/user32/misc/stubs.c b/win32ss/user/user32/misc/stubs.c index b73397d44b..a04ca5eddb 100644 --- a/win32ss/user/user32/misc/stubs.c +++ b/win32ss/user/user32/misc/stubs.c @@ -546,14 +546,6 @@ RecordShutdownReason(DWORD dw0) return FALSE; }
-BOOL -WINAPI -UserLpkPSMTextOut(DWORD dw1, DWORD dw2, DWORD dw3, DWORD dw4, DWORD dw5, DWORD dw6) -{ - UNIMPLEMENTED; - return FALSE; -} - BOOL WINAPI UserLpkTabbedTextOut( diff --git a/win32ss/user/user32/user32.spec b/win32ss/user/user32/user32.spec index 2f3ec10bac..dc54a3e22e 100644 --- a/win32ss/user/user32/user32.spec +++ b/win32ss/user/user32/user32.spec @@ -719,7 +719,7 @@ 710 stdcall User32InitializeImmEntryTable(ptr) 711 stdcall UserClientDllInitialize(long long ptr) DllMain 712 stdcall UserHandleGrantAccess(ptr ptr long) NtUserUserHandleGrantAccess -713 stdcall UserLpkPSMTextOut(long long long long long long) +713 stdcall UserLpkPSMTextOut(long long long wstr long long) 714 stdcall UserLpkTabbedTextOut(long long long long long long long long long long long long) 715 stdcall UserRealizePalette(long) 716 stdcall UserRegisterWowHandlers(ptr ptr) diff --git a/win32ss/user/user32/windows/font.c b/win32ss/user/user32/windows/font.c index 6031ae970d..3d16eddb9a 100644 --- a/win32ss/user/user32/windows/font.c +++ b/win32ss/user/user32/windows/font.c @@ -383,3 +383,115 @@ INT WINAPI DrawTextA( HDC hdc, LPCSTR str, INT count, LPRECT rect, UINT flags ) } return DrawTextExA( hdc, (LPSTR)str, count, rect, flags, &dtp ); } + +/*************************************************************************** + * UserLpkPSMTextOut + * + * Stripped down version of DrawText, can only draw single line text and + * Prefix underscore (only on the last found amperstand) + * only flags to be found to be of use in testing: + * + * DT_NOPREFIX - Draw the string as is it without any changes + * DT_HIDEPREFIX - Draw the string without underscore + * DT_PREFIXONLY - Draw only the underscore + * + * without any of these flags the behavior is the string being drawn without the amperstands and + * with the underscore. + * + * lpk has an equivalent function - LpkPSMTextOut + * Notes by testing: + * This function in windows doesn't check if lpString is NULL, which results a crash, + * returns seemingly random values without any logic, and ignores the DT_NOPREFIX value. + * All of these issues don't exist in the LPK version. + * + * Note: lpString does not need to be null terminated + */ +#define PREFIX 38 +#define ALPHA_PREFIX 30 /* Win16: Alphabet prefix */ +#define KANA_PREFIX 31 /* Win16: Katakana prefix */ + +INT WINAPI UserLpkPSMTextOut(HDC hdc, int x, int y, LPCWSTR lpString, int cString, DWORD dwFlags) +{ + SIZE size; + TEXTMETRICW tm; + int len, i = 0, j = 0;; + int prefix_count = 0, prefix_offset = -1; + LPWSTR display_str = NULL; + int prefix_x, prefix_end; + HPEN hpen; + HPEN oldPen; + + if (!lpString || cString <= 0) + return 0; + + if (dwFlags & DT_NOPREFIX) /* Windows ignores this */ + { + ExtTextOutW(hdc, x, y, (dwFlags & DT_RTLREADING) ? ETO_RTLREADING : 0, NULL, lpString, cString, NULL); + GetTextExtentPointW(hdc, lpString, cString, &size); + return size.cx; + } + + display_str = HeapAlloc(GetProcessHeap(), 0, (cString + 1) * sizeof(WCHAR)); + + if (!display_str) + return 0; + + while (i < cString) + { + if (lpString[i] == PREFIX || (iswspace(lpString[i]) && lpString[i] != L' ')) + { + if (i < cString - 1 && lpString[i + 1] == PREFIX) + display_str[j++] = lpString[i++]; + else + i++; + } + else + { + display_str[j++] = lpString[i++]; + } + } + + display_str[j] = L'\0'; + len = wcslen(display_str); + + if (!(dwFlags & DT_PREFIXONLY)) + ExtTextOutW(hdc, x, y, (dwFlags & DT_RTLREADING) ? ETO_RTLREADING : 0, NULL, display_str, len, NULL); + + if (!(dwFlags & DT_HIDEPREFIX)) + { + + for (i = 0; i < cString - 1; i++) + { + if (lpString[i] == PREFIX && lpString[i + 1] != PREFIX) + { + prefix_offset = i - prefix_count; + prefix_count++; + } + else if (lpString[i] == PREFIX && lpString[i + 1] == PREFIX) + { + i++; + } + } + + GetTextMetricsW(hdc, &tm); + + if (prefix_offset != -1) + { + GetTextExtentPointW(hdc, display_str, prefix_offset, &size); + prefix_x = x + size.cx; + GetTextExtentPointW(hdc, display_str, prefix_offset + 1, &size); + prefix_end = x + size.cx - 1; + hpen = CreatePen(PS_SOLID, 1, GetTextColor(hdc)); + oldPen = SelectObject(hdc, hpen); + MoveToEx(hdc, prefix_x, y + tm.tmAscent + 1, NULL); + LineTo(hdc, prefix_end, y + tm.tmAscent + 1); + SelectObject(hdc, oldPen); + DeleteObject(hpen); + } + } + + GetTextExtentPointW(hdc, display_str, len + 1, &size); + HeapFree(GetProcessHeap(), 0, display_str); + + return size.cx; +}