https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a494d0583fe3805f1b33e…
commit a494d0583fe3805f1b33ed0d65e6a6f7ed8f8e0b
Author: Baruch Rutman <peterooch(a)gmail.com>
AuthorDate: Fri Sep 28 01:00:31 2018 +0300
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Mon Oct 8 16:16:40 2018 +0200
[LPK] Implement LpkPSMTextOut(). (#890)
- The function is almost fully implemented, but some return values change wildly.
The results are mostly compatible to the Windows results.
- Remove #ifdef (this is primary ReactOS code).
---
dll/win32/lpk/lpk.c | 152 +++++++++++++++++++++++++++++++++++++++++++++---
dll/win32/lpk/lpk.spec | 2 +-
dll/win32/lpk/ros_lpk.h | 3 +-
dll/win32/lpk/stub.c | 9 ---
4 files changed, 147 insertions(+), 19 deletions(-)
diff --git a/dll/win32/lpk/lpk.c b/dll/win32/lpk/lpk.c
index b567d744ca..b99e8a3c65 100644
--- a/dll/win32/lpk/lpk.c
+++ b/dll/win32/lpk/lpk.c
@@ -14,6 +14,97 @@ LPK_LPEDITCONTROL_LIST LpkEditControl = {EditCreate, EditIchToXY,
EditMou
EditVerifyText, EditNextWord, EditSetMenu,
EditProcessMenu,
EditCreateCaret, EditAdjustCaret};
+#define PREFIX 38
+#define ALPHA_PREFIX 30 /* Win16: Alphabet prefix */
+#define KANA_PREFIX 31 /* Win16: Katakana prefix */
+
+static int PSM_FindLastPrefix(LPCWSTR str, int count)
+{
+ int i, prefix_count = 0, index = -1;
+
+ for (i = 0; i < count - 1; i++)
+ {
+ if (str[i] == PREFIX && str[i + 1] != PREFIX)
+ {
+ index = i - prefix_count;
+ prefix_count++;
+ }
+ else if (str[i] == PREFIX && str[i + 1] == PREFIX)
+ {
+ i++;
+ }
+ }
+ return index;
+}
+
+static void PSM_PrepareToDraw(LPCWSTR str, INT count, LPWSTR new_str, LPINT new_count)
+{
+ int len, i = 0, j = 0;
+
+ while (i < count)
+ {
+ if (str[i] == PREFIX || (iswspace(str[i]) && str[i] != L' '))
+ {
+ if(i < count - 1 && str[i + 1] == PREFIX)
+ new_str[j++] = str[i++];
+ else
+ i++;
+ }
+ else
+ {
+ new_str[j++] = str[i++];
+ }
+ }
+
+ new_str[j] = L'\0';
+ len = wcslen(new_str);
+ *new_count = len;
+}
+
+/* Can be used with also LpkDrawTextEx if it will be implemented */
+static void LPK_DrawUnderscore(HDC hdc, int x, int y, LPCWSTR str, int count, int
offset)
+{
+ SCRIPT_STRING_ANALYSIS ssa;
+ int prefix_x;
+ int prefix_end;
+ int pos;
+ SIZE size;
+ HPEN hpen;
+ HPEN oldPen;
+ HRESULT hr = S_FALSE;
+
+ if (offset == -1)
+ return;
+
+ if (ScriptIsComplex(str, count, SIC_COMPLEX) == S_OK)
+ {
+ hr = ScriptStringAnalyse(hdc, str, count, (3 * count / 2 + 16),
+ -1, SSA_GLYPHS, -1, NULL, NULL, NULL, NULL, NULL,
&ssa);
+ }
+
+ if (hr == S_OK)
+ {
+ ScriptStringCPtoX(ssa, offset, FALSE, &pos);
+ prefix_x = x + pos;
+ ScriptStringCPtoX(ssa, offset, TRUE, &pos);
+ prefix_end = x + pos;
+ ScriptStringFree(&ssa);
+ }
+ else
+ {
+ GetTextExtentPointW(hdc, str, offset, &size);
+ prefix_x = x + size.cx;
+ GetTextExtentPointW(hdc, str, 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, NULL);
+ LineTo(hdc, prefix_end, y);
+ SelectObject(hdc, oldPen);
+ DeleteObject(hpen);
+}
+
BOOL
WINAPI
DllMain(
@@ -196,14 +287,7 @@ LpkGetCharacterPlacement(
{
int pos = 0;
- hr = ScriptStringAnalyse(hdc, lpString, nSet,
-#ifdef __REACTOS__
- /* ReactOS r57677 and r57679 */
- (3 * nSet / 2 + 16),
-#else
- (1.5 * nSet + 16),
-#endif
- -1, SSA_GLYPHS, -1,
+ hr = ScriptStringAnalyse(hdc, lpString, nSet, (3 * nSet / 2 + 16), -1,
SSA_GLYPHS, -1,
NULL, NULL, NULL, NULL, NULL, &ssa);
if (hr == S_OK)
{
@@ -232,3 +316,55 @@ LpkGetCharacterPlacement(
return ret;
}
+
+/* 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 without removal of the amperstands and without
underscore
+ * 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.
+ * user32 has an equivalent function - UserLpkPSMTextOut
+ */
+INT WINAPI LpkPSMTextOut(HDC hdc, int x, int y, LPCWSTR lpString, int cString, DWORD
dwFlags)
+{
+ SIZE size;
+ TEXTMETRICW tm;
+ int prefix_offset, len;
+ LPWSTR display_str = NULL;
+
+ if (!lpString || cString <= 0)
+ return 0;
+
+ if (dwFlags & DT_NOPREFIX)
+ {
+ LpkExtTextOut(hdc, x, y, (dwFlags & DT_RTLREADING) ? ETO_RTLREADING : 0,
NULL, lpString, cString - 1, NULL, 0);
+ GetTextExtentPointW(hdc, lpString, cString, &size);
+ return size.cx;
+ }
+
+ display_str = HeapAlloc(GetProcessHeap(), 0, (cString + 1) * sizeof(WCHAR));
+
+ if (!display_str)
+ return 0;
+
+ PSM_PrepareToDraw(lpString, cString, display_str, &len);
+
+ if (!(dwFlags & DT_PREFIXONLY))
+ LpkExtTextOut(hdc, x, y, (dwFlags & DT_RTLREADING) ? ETO_RTLREADING : 0,
NULL, display_str, len, NULL, 0);
+
+ if (!(dwFlags & DT_HIDEPREFIX))
+ {
+ prefix_offset = PSM_FindLastPrefix(lpString, cString);
+ GetTextMetricsW(hdc, &tm);
+ LPK_DrawUnderscore(hdc, x, y + tm.tmAscent + 1, display_str, len,
prefix_offset);
+ }
+
+ GetTextExtentPointW(hdc, display_str, len + 1, &size);
+ HeapFree(GetProcessHeap(), 0, display_str);
+
+ return size.cx;
+}
diff --git a/dll/win32/lpk/lpk.spec b/dll/win32/lpk/lpk.spec
index 910d3dc65d..1ef05e1a74 100644
--- a/dll/win32/lpk/lpk.spec
+++ b/dll/win32/lpk/lpk.spec
@@ -6,6 +6,6 @@
@ stdcall LpkExtTextOut(long long long long ptr wstr long ptr long)
@ stdcall LpkGetCharacterPlacement(long wstr long long ptr long long)
@ stdcall LpkGetTextExtentExPoint(long long long long long long long long long)
-@ stdcall LpkPSMTextOut(long long long long long long)
+@ stdcall LpkPSMTextOut(long long long wstr long long)
@ stdcall LpkUseGDIWidthCache(long long long long long)
@ stdcall ftsWordBreak(long long long long long)
diff --git a/dll/win32/lpk/ros_lpk.h b/dll/win32/lpk/ros_lpk.h
index 0fb1fe341d..ecb3ef91fc 100644
--- a/dll/win32/lpk/ros_lpk.h
+++ b/dll/win32/lpk/ros_lpk.h
@@ -66,7 +66,6 @@ DWORD WINAPI LpkTabbedTextOut(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD
x5,DWORD
BOOL WINAPI LpkDllInitialize (HANDLE hDll, DWORD dwReason, LPVOID lpReserved);
DWORD WINAPI LpkDrawTextEx(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6,DWORD
x7,DWORD x8,DWORD x9, DWORD x10);
DWORD WINAPI LpkGetTextExtentExPoint(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD
x6,DWORD x7,DWORD x8,DWORD x9);
-DWORD WINAPI LpkPSMTextOut(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6);
DWORD WINAPI LpkUseGDIWidthCache(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5);
DWORD WINAPI ftsWordBreak(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5);
@@ -77,6 +76,8 @@ BOOL WINAPI LpkExtTextOut(HDC hdc, int x, int y, UINT fuOptions, const
RECT *lpr
DWORD WINAPI LpkGetCharacterPlacement(HDC hdc, LPCWSTR lpString, INT uCount, INT
nMaxExtent,
GCP_RESULTSW *lpResults, DWORD dwFlags, DWORD
dwUnused);
+
+INT WINAPI LpkPSMTextOut(HDC hdc, int x, int y, LPCWSTR lpString, int cString, DWORD
dwFlags);
/* bidi.c */
#define WINE_GCPW_FORCE_LTR 0
diff --git a/dll/win32/lpk/stub.c b/dll/win32/lpk/stub.c
index 51d8eda0e4..b601a35868 100644
--- a/dll/win32/lpk/stub.c
+++ b/dll/win32/lpk/stub.c
@@ -48,15 +48,6 @@ DWORD WINAPI LpkGetTextExtentExPoint(DWORD x1,DWORD x2,DWORD x3,DWORD
x4,DWORD x
return 0;
}
-/*
- * @unimplemented
- */
-DWORD WINAPI LpkPSMTextOut(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6)
-{
- UNIMPLEMENTED
- return 0;
-}
-
/*
* @unimplemented
*/