[USER32] Implement UserLpkPSMTextOut(). (#890)
authorBaruch Rutman <peterooch@gmail.com>
Fri, 28 Sep 2018 15:02:38 +0000 (18:02 +0300)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 8 Oct 2018 14:16:52 +0000 (16:16 +0200)
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
win32ss/user/user32/user32.spec
win32ss/user/user32/windows/font.c

index b73397d..a04ca5e 100644 (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(
index 2f3ec10..dc54a3e 100644 (file)
 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)
index 6031ae9..3d16edd 100644 (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;
+}