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