https://git.reactos.org/?p=reactos.git;a=commitdiff;h=17d4df8102562e22bd8f88af689cf1cb4f986850

commit 17d4df8102562e22bd8f88af689cf1cb4f986850
Author:     Baruch Rutman <[email protected]>
AuthorDate: Fri Sep 28 18:02:38 2018 +0300
Commit:     Hermès Bélusca-Maïto <[email protected]>
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;
+}

Reply via email to