https://git.reactos.org/?p=reactos.git;a=commitdiff;h=17d4df8102562e22bd8f8…
commit 17d4df8102562e22bd8f88af689cf1cb4f986850
Author: Baruch Rutman <peterooch(a)gmail.com>
AuthorDate: Fri Sep 28 18:02:38 2018 +0300
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)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;
+}