xref: /reactos/dll/win32/lpk/lpk.c (revision e08ae510)
1 /*
2  * PROJECT:     ReactOS LPK
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Language Pack DLL.
5  * PROGRAMMERS: Magnus Olsen  (greatlrd)
6  *              Baruch Rutman (peterooch at gmail dot com)
7  */
8 
9 #include "ros_lpk.h"
10 #include <debug.h>
11 
12 LPK_LPEDITCONTROL_LIST LpkEditControl = {EditCreate,       EditIchToXY,  EditMouseToIch, EditCchInWidth,
13                                          EditGetLineWidth, EditDrawText, EditHScroll,    EditMoveSelection,
14                                          EditVerifyText,   EditNextWord, EditSetMenu,    EditProcessMenu,
15                                          EditCreateCaret, EditAdjustCaret};
16 
17 BOOL
18 WINAPI
19 DllMain(
20     HANDLE  hDll,
21     DWORD   dwReason,
22     LPVOID  lpReserved)
23 {
24 
25     return LpkDllInitialize(hDll,dwReason,lpReserved);
26 }
27 
28 BOOL
29 WINAPI
30 LpkDllInitialize(
31     HANDLE  hDll,
32     DWORD   dwReason,
33     LPVOID  lpReserved)
34 {
35     switch(dwReason)
36     {
37         case DLL_PROCESS_ATTACH:
38             DisableThreadLibraryCalls(hDll);
39             /* Tell usp10 it is activated usp10 */
40             //LpkPresent();
41             break;
42 
43         default:
44             break;
45     }
46 
47     return TRUE;
48 }
49 
50 
51 /*
52  * @implemented
53  */
54 BOOL
55 WINAPI
56 LpkExtTextOut(
57     HDC hdc,
58     int x,
59     int y,
60     UINT fuOptions,
61     const RECT *lprc,
62     LPCWSTR lpString,
63     UINT uCount,
64     const INT *lpDx,
65     INT unknown)
66 {
67     LPWORD glyphs = NULL;
68     LPWSTR reordered_str = NULL;
69     INT cGlyphs;
70     DWORD dwSICFlags = SIC_COMPLEX;
71     BOOL bResult, bReorder;
72 
73     UNREFERENCED_PARAMETER(unknown);
74 
75     fuOptions |= ETO_IGNORELANGUAGE;
76 
77     /* Check text direction */
78     if ((GetLayout(hdc) & LAYOUT_RTL) || (GetTextAlign(hdc) & TA_RTLREADING))
79         fuOptions |= ETO_RTLREADING;
80 
81     /* If text direction is RTL change flag to account neutral characters */
82     if (fuOptions & ETO_RTLREADING)
83         dwSICFlags |= SIC_NEUTRAL;
84 
85     /* Check if the string requires complex script processing and not a "glyph indices" array */
86     if (ScriptIsComplex(lpString, uCount, dwSICFlags) == S_OK && !(fuOptions & ETO_GLYPH_INDEX))
87     {
88         /* reordered_str is used as fallback in case the glyphs array fails to generate,
89            BIDI_Reorder doesn't attempt to write into reordered_str if memory allocation fails */
90         reordered_str = HeapAlloc(GetProcessHeap(), 0, uCount * sizeof(WCHAR));
91 
92         bReorder = BIDI_Reorder(hdc, lpString, uCount, GCP_REORDER,
93                                 (fuOptions & ETO_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
94                                 reordered_str, uCount, NULL, &glyphs, &cGlyphs);
95 
96         if (glyphs)
97         {
98             fuOptions |= ETO_GLYPH_INDEX;
99             uCount = cGlyphs;
100         }
101 
102         /* Now display the reordered text if any of the arrays is valid and if BIDI_Reorder succeeded */
103         if ((glyphs || reordered_str) && bReorder)
104         {
105             bResult = ExtTextOutW(hdc, x, y, fuOptions, lprc,
106                                   glyphs ? (LPWSTR)glyphs : reordered_str, uCount, lpDx);
107         }
108         else
109         {
110             DPRINT1("BIDI_Reorder failed, falling back to original string.\n");
111             bResult = ExtTextOutW(hdc, x, y, fuOptions, lprc, lpString, uCount, lpDx);
112         }
113 
114         HeapFree(GetProcessHeap(), 0, glyphs);
115         HeapFree(GetProcessHeap(), 0, reordered_str);
116 
117         return bResult;
118     }
119 
120     return ExtTextOutW(hdc, x, y, fuOptions, lprc, lpString, uCount, lpDx);
121 }
122 
123 /*
124  * @implemented
125  */
126 DWORD
127 WINAPI
128 LpkGetCharacterPlacement(
129     HDC hdc,
130     LPCWSTR lpString,
131     INT uCount,
132     INT nMaxExtent,
133     LPGCP_RESULTSW lpResults,
134     DWORD dwFlags,
135     DWORD dwUnused)
136 {
137     DWORD ret = 0;
138     HRESULT hr;
139     SCRIPT_STRING_ANALYSIS ssa;
140     LPWORD lpGlyphs = NULL;
141     SIZE size;
142     UINT nSet, i;
143     INT cGlyphs;
144 
145     UNREFERENCED_PARAMETER(dwUnused);
146 
147     /* Sanity check (most likely a direct call) */
148     if (!(dwFlags & GCP_REORDER))
149        return GetCharacterPlacementW(hdc, lpString, uCount, nMaxExtent, lpResults, dwFlags);
150 
151     nSet = (UINT)uCount;
152     if (nSet > lpResults->nGlyphs)
153         nSet = lpResults->nGlyphs;
154 
155     BIDI_Reorder(hdc, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
156                  nSet, lpResults->lpOrder, &lpGlyphs, &cGlyphs);
157 
158     lpResults->nGlyphs = (UINT)cGlyphs;
159 
160     if (lpResults->lpGlyphs)
161     {
162         if (lpGlyphs)
163             StringCchCopyW(lpResults->lpGlyphs, cGlyphs, lpGlyphs);
164         else if (lpResults->lpOutString)
165             GetGlyphIndicesW(hdc, lpResults->lpOutString, nSet, lpResults->lpGlyphs, 0);
166     }
167 
168     if (lpResults->lpDx)
169     {
170         int c;
171 
172         /* If glyph shaping was requested */
173         if (dwFlags & GCP_GLYPHSHAPE)
174         {
175             if (lpResults->lpGlyphs)
176             {
177                 for (i = 0; i < lpResults->nGlyphs; i++)
178                 {
179                     if (GetCharWidthI(hdc, 0, 1, (WORD *)&lpResults->lpGlyphs[i], &c))
180                         lpResults->lpDx[i] = c;
181                 }
182             }
183         }
184 
185         else
186         {
187             for (i = 0; i < nSet; i++)
188             {
189                 if (GetCharWidth32W(hdc, lpResults->lpOutString[i], lpResults->lpOutString[i], &c))
190                     lpResults->lpDx[i] = c;
191             }
192         }
193     }
194 
195     if (lpResults->lpCaretPos)
196     {
197         int pos = 0;
198 
199         hr = ScriptStringAnalyse(hdc, lpString, nSet,
200 #ifdef __REACTOS__
201                                  /* ReactOS r57677 and r57679 */
202                                  (3 * nSet / 2 + 16),
203 #else
204                                  (1.5 * nSet + 16),
205 #endif
206                                  -1, SSA_GLYPHS, -1,
207                                  NULL, NULL, NULL, NULL, NULL, &ssa);
208         if (hr == S_OK)
209         {
210             for (i = 0; i < nSet; i++)
211             {
212                 if (ScriptStringCPtoX(ssa, i, FALSE, &pos) == S_OK)
213                     lpResults->lpCaretPos[i] = pos;
214             }
215             ScriptStringFree(&ssa);
216         }
217         else
218         {
219             lpResults->lpCaretPos[0] = 0;
220             for (i = 1; i < nSet; i++)
221             {
222                 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
223                     lpResults->lpCaretPos[i] = (pos += size.cx);
224             }
225         }
226     }
227 
228     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
229         ret = MAKELONG(size.cx, size.cy);
230 
231     HeapFree(GetProcessHeap(), 0, lpGlyphs);
232 
233     return ret;
234 }
235