[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.
This commit is contained in:
Baruch Rutman 2018-09-28 18:02:38 +03:00 committed by Hermès Bélusca-Maïto
parent a494d0583f
commit 17d4df8102
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
3 changed files with 113 additions and 9 deletions

View file

@ -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(

View file

@ -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)

View file

@ -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;
}