1 /*
2 * PROJECT: ReactOS win32 kernel mode subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: win32ss/gdi/ntgdi/text.c
5 * PURPOSE: Text/Font
6 * PROGRAMMER:
7 */
8
9 /** Includes ******************************************************************/
10
11 #include <win32k.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16
17 /*
18 This is a hack. See CORE-1091.
19
20 It is needed because ReactOS does not support raster fonts now.
21 After Raster Font support is added, then it can be removed.
22 Find the current font's logfont for testing its lf.lfFaceName.
23
24 The ftGdiGetTextMetricsW function currently in ReactOS will always return a Truetype font
25 because we cannot yet handle raster fonts. So it will return flags
26 TMPF_VECTOR and TMPF_TRUETYPE, which can cause problems in edit boxes.
27 */
28
29 VOID FASTCALL
IntTMWFixUp(HDC hDC,TMW_INTERNAL * ptm)30 IntTMWFixUp(
31 HDC hDC,
32 TMW_INTERNAL *ptm)
33 {
34 LOGFONTW lf;
35 HFONT hCurrentFont;
36
37 hCurrentFont = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_FONT);
38 GreGetObject(hCurrentFont, sizeof(LOGFONTW), &lf);
39
40 /* To compensate for the GetTextMetricsW call changing the PitchAndFamily
41 * to a TrueType one when we have a 'Raster' font as our input we filter
42 * out the problematic TrueType and Vector bits.
43 * Our list below checks for Raster Font Facenames. */
44 DPRINT("Font Facename is '%S'.\n", lf.lfFaceName);
45 if ((_wcsicmp(lf.lfFaceName, L"Courier") == 0) ||
46 (_wcsicmp(lf.lfFaceName, L"FixedSys") == 0) ||
47 (_wcsicmp(lf.lfFaceName, L"Helv") == 0) ||
48 (_wcsicmp(lf.lfFaceName, L"MS Sans Serif") == 0) ||
49 (_wcsicmp(lf.lfFaceName, L"MS Serif") == 0) ||
50 (_wcsicmp(lf.lfFaceName, L"System") == 0) ||
51 (_wcsicmp(lf.lfFaceName, L"Terminal") == 0) ||
52 (_wcsicmp(lf.lfFaceName, L"Tms Rmn") == 0))
53 {
54 ptm->TextMetric.tmPitchAndFamily &= ~(TMPF_TRUETYPE | TMPF_VECTOR);
55 }
56 }
57
58 /** Functions *****************************************************************/
59
60 BOOL FASTCALL
GreTextOutW(HDC hdc,int nXStart,int nYStart,LPCWSTR lpString,int cchString)61 GreTextOutW(
62 HDC hdc,
63 int nXStart,
64 int nYStart,
65 LPCWSTR lpString,
66 int cchString)
67 {
68 return GreExtTextOutW(hdc, nXStart, nYStart, 0, NULL, lpString, cchString, NULL, 0);
69 }
70
71 /*
72 flOpts :
73 GetTextExtentPoint32W = 0
74 GetTextExtentPointW = 1
75 */
76 BOOL
77 FASTCALL
GreGetTextExtentW(HDC hDC,LPCWSTR lpwsz,INT cwc,LPSIZE psize,UINT flOpts)78 GreGetTextExtentW(
79 HDC hDC,
80 LPCWSTR lpwsz,
81 INT cwc,
82 LPSIZE psize,
83 UINT flOpts)
84 {
85 PDC pdc;
86 PDC_ATTR pdcattr;
87 BOOL Result;
88 PTEXTOBJ TextObj;
89
90 if (!cwc)
91 {
92 psize->cx = 0;
93 psize->cy = 0;
94 return TRUE;
95 }
96
97 pdc = DC_LockDc(hDC);
98 if (!pdc)
99 {
100 EngSetLastError(ERROR_INVALID_HANDLE);
101 return FALSE;
102 }
103
104 pdcattr = pdc->pdcattr;
105
106 TextObj = RealizeFontInit(pdcattr->hlfntNew);
107 if ( TextObj )
108 {
109 Result = TextIntGetTextExtentPoint( pdc,
110 TextObj,
111 lpwsz,
112 cwc,
113 0,
114 NULL,
115 0,
116 psize,
117 flOpts);
118 TEXTOBJ_UnlockText(TextObj);
119 }
120 else
121 Result = FALSE;
122
123 DC_UnlockDc(pdc);
124 return Result;
125 }
126
127
128 /*
129 fl :
130 GetTextExtentExPointW = 0 and everything else that uses this.
131 GetTextExtentExPointI = 1
132 */
133 BOOL
134 FASTCALL
GreGetTextExtentExW(HDC hDC,LPCWSTR String,ULONG Count,ULONG MaxExtent,PULONG Fit,PULONG Dx,LPSIZE pSize,FLONG fl)135 GreGetTextExtentExW(
136 HDC hDC,
137 LPCWSTR String,
138 ULONG Count,
139 ULONG MaxExtent,
140 PULONG Fit,
141 PULONG Dx,
142 LPSIZE pSize,
143 FLONG fl)
144 {
145 PDC pdc;
146 PDC_ATTR pdcattr;
147 BOOL Result;
148 PTEXTOBJ TextObj;
149
150 if ( (!String && Count ) || !pSize )
151 {
152 EngSetLastError(ERROR_INVALID_PARAMETER);
153 return FALSE;
154 }
155
156 if ( !Count )
157 {
158 if ( Fit ) Fit = 0;
159 return TRUE;
160 }
161
162 pdc = DC_LockDc(hDC);
163 if (NULL == pdc)
164 {
165 EngSetLastError(ERROR_INVALID_HANDLE);
166 return FALSE;
167 }
168 pdcattr = pdc->pdcattr;
169
170 TextObj = RealizeFontInit(pdcattr->hlfntNew);
171 if ( TextObj )
172 {
173 Result = TextIntGetTextExtentPoint( pdc,
174 TextObj,
175 String,
176 Count,
177 MaxExtent,
178 (LPINT)Fit,
179 (LPINT)Dx,
180 pSize,
181 fl);
182 TEXTOBJ_UnlockText(TextObj);
183 }
184 else
185 Result = FALSE;
186
187 DC_UnlockDc(pdc);
188 return Result;
189 }
190
191 BOOL
192 WINAPI
GreGetTextMetricsW(_In_ HDC hdc,_Out_ LPTEXTMETRICW lptm)193 GreGetTextMetricsW(
194 _In_ HDC hdc,
195 _Out_ LPTEXTMETRICW lptm)
196 {
197 TMW_INTERNAL tmwi;
198 if (!ftGdiGetTextMetricsW(hdc, &tmwi)) return FALSE;
199 IntTMWFixUp(hdc, &tmwi);
200 *lptm = tmwi.TextMetric;
201 return TRUE;
202 }
203
204 DWORD
205 APIENTRY
NtGdiGetCharSet(HDC hDC)206 NtGdiGetCharSet(HDC hDC)
207 {
208 PDC Dc;
209 PDC_ATTR pdcattr;
210 DWORD cscp;
211 // If here, update everything!
212 Dc = DC_LockDc(hDC);
213 if (!Dc)
214 {
215 EngSetLastError(ERROR_INVALID_HANDLE);
216 return 0;
217 }
218 cscp = ftGdiGetTextCharsetInfo(Dc, NULL, 0);
219 pdcattr = Dc->pdcattr;
220 pdcattr->iCS_CP = cscp;
221 pdcattr->ulDirty_ &= ~DIRTY_CHARSET;
222 DC_UnlockDc( Dc );
223 return cscp;
224 }
225
226 BOOL
227 APIENTRY
NtGdiGetRasterizerCaps(OUT LPRASTERIZER_STATUS praststat,IN ULONG cjBytes)228 NtGdiGetRasterizerCaps(
229 OUT LPRASTERIZER_STATUS praststat,
230 IN ULONG cjBytes)
231 {
232 NTSTATUS Status = STATUS_SUCCESS;
233 RASTERIZER_STATUS rsSafe;
234
235 if (praststat && cjBytes)
236 {
237 if ( cjBytes >= sizeof(RASTERIZER_STATUS) ) cjBytes = sizeof(RASTERIZER_STATUS);
238 if ( ftGdiGetRasterizerCaps(&rsSafe))
239 {
240 _SEH2_TRY
241 {
242 ProbeForWrite( praststat,
243 sizeof(RASTERIZER_STATUS),
244 1);
245 RtlCopyMemory(praststat, &rsSafe, cjBytes );
246 }
247 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
248 {
249 Status = _SEH2_GetExceptionCode();
250 }
251 _SEH2_END;
252
253 if (!NT_SUCCESS(Status))
254 {
255 SetLastNtError(Status);
256 return FALSE;
257 }
258
259 return TRUE;
260 }
261 }
262 return FALSE;
263 }
264
265 INT
266 APIENTRY
NtGdiGetTextCharsetInfo(IN HDC hdc,OUT OPTIONAL LPFONTSIGNATURE lpSig,IN DWORD dwFlags)267 NtGdiGetTextCharsetInfo(
268 IN HDC hdc,
269 OUT OPTIONAL LPFONTSIGNATURE lpSig,
270 IN DWORD dwFlags)
271 {
272 PDC Dc;
273 INT Ret;
274 FONTSIGNATURE fsSafe;
275 PFONTSIGNATURE pfsSafe = &fsSafe;
276 NTSTATUS Status = STATUS_SUCCESS;
277
278 Dc = DC_LockDc(hdc);
279 if (!Dc)
280 {
281 EngSetLastError(ERROR_INVALID_HANDLE);
282 return DEFAULT_CHARSET;
283 }
284
285 if (!lpSig) pfsSafe = NULL;
286
287 Ret = HIWORD(ftGdiGetTextCharsetInfo( Dc, pfsSafe, dwFlags));
288
289 if (lpSig)
290 {
291 if (Ret == DEFAULT_CHARSET)
292 RtlZeroMemory(pfsSafe, sizeof(FONTSIGNATURE));
293
294 _SEH2_TRY
295 {
296 ProbeForWrite( lpSig,
297 sizeof(FONTSIGNATURE),
298 1);
299 RtlCopyMemory(lpSig, pfsSafe, sizeof(FONTSIGNATURE));
300 }
301 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
302 {
303 Status = _SEH2_GetExceptionCode();
304 }
305 _SEH2_END;
306
307 if (!NT_SUCCESS(Status))
308 {
309 SetLastNtError(Status);
310 return DEFAULT_CHARSET;
311 }
312 }
313 DC_UnlockDc(Dc);
314 return Ret;
315 }
316
317
318 /*
319 fl :
320 GetTextExtentExPointW = 0 and everything else that uses this.
321 GetTextExtentExPointI = 1
322 */
323 W32KAPI
324 BOOL
325 APIENTRY
NtGdiGetTextExtentExW(IN HDC hDC,IN OPTIONAL LPWSTR UnsafeString,IN ULONG Count,IN ULONG MaxExtent,OUT OPTIONAL PULONG UnsafeFit,OUT OPTIONAL PULONG UnsafeDx,OUT LPSIZE UnsafeSize,IN FLONG fl)326 NtGdiGetTextExtentExW(
327 IN HDC hDC,
328 IN OPTIONAL LPWSTR UnsafeString,
329 IN ULONG Count,
330 IN ULONG MaxExtent,
331 OUT OPTIONAL PULONG UnsafeFit,
332 OUT OPTIONAL PULONG UnsafeDx,
333 OUT LPSIZE UnsafeSize,
334 IN FLONG fl
335 )
336 {
337 PDC dc;
338 PDC_ATTR pdcattr;
339 LPWSTR String;
340 SIZE Size;
341 NTSTATUS Status;
342 BOOLEAN Result;
343 INT Fit;
344 LPINT Dx;
345 PTEXTOBJ TextObj;
346
347 if ((LONG)Count < 0)
348 {
349 EngSetLastError(ERROR_INVALID_PARAMETER);
350 return FALSE;
351 }
352
353 /* FIXME: Handle fl */
354
355 if (0 == Count)
356 {
357 Size.cx = 0;
358 Size.cy = 0;
359 Status = MmCopyToCaller(UnsafeSize, &Size, sizeof(SIZE));
360 if (! NT_SUCCESS(Status))
361 {
362 SetLastNtError(Status);
363 return FALSE;
364 }
365 return TRUE;
366 }
367
368 String = ExAllocatePoolWithTag(PagedPool, Count * sizeof(WCHAR), GDITAG_TEXT);
369 if (NULL == String)
370 {
371 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
372 return FALSE;
373 }
374
375 if (NULL != UnsafeDx)
376 {
377 Dx = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), GDITAG_TEXT);
378 if (NULL == Dx)
379 {
380 ExFreePoolWithTag(String, GDITAG_TEXT);
381 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
382 return FALSE;
383 }
384 }
385 else
386 {
387 Dx = NULL;
388 }
389
390 Status = MmCopyFromCaller(String, UnsafeString, Count * sizeof(WCHAR));
391 if (! NT_SUCCESS(Status))
392 {
393 if (NULL != Dx)
394 {
395 ExFreePoolWithTag(Dx, GDITAG_TEXT);
396 }
397 ExFreePoolWithTag(String, GDITAG_TEXT);
398 SetLastNtError(Status);
399 return FALSE;
400 }
401
402 dc = DC_LockDc(hDC);
403 if (NULL == dc)
404 {
405 if (NULL != Dx)
406 {
407 ExFreePoolWithTag(Dx, GDITAG_TEXT);
408 }
409 ExFreePoolWithTag(String, GDITAG_TEXT);
410 EngSetLastError(ERROR_INVALID_HANDLE);
411 return FALSE;
412 }
413 pdcattr = dc->pdcattr;
414 TextObj = RealizeFontInit(pdcattr->hlfntNew);
415 if ( TextObj )
416 {
417 Result = TextIntGetTextExtentPoint( dc,
418 TextObj,
419 String,
420 Count,
421 MaxExtent,
422 NULL == UnsafeFit ? NULL : &Fit,
423 Dx,
424 &Size,
425 fl);
426 TEXTOBJ_UnlockText(TextObj);
427 }
428 else
429 Result = FALSE;
430 DC_UnlockDc(dc);
431
432 ExFreePoolWithTag(String, GDITAG_TEXT);
433 if (! Result)
434 {
435 if (NULL != Dx)
436 {
437 ExFreePoolWithTag(Dx, GDITAG_TEXT);
438 }
439 return FALSE;
440 }
441
442 if (NULL != UnsafeFit)
443 {
444 Status = MmCopyToCaller(UnsafeFit, &Fit, sizeof(INT));
445 if (! NT_SUCCESS(Status))
446 {
447 if (NULL != Dx)
448 {
449 ExFreePoolWithTag(Dx, GDITAG_TEXT);
450 }
451 SetLastNtError(Status);
452 return FALSE;
453 }
454 }
455
456 if (NULL != UnsafeDx)
457 {
458 Status = MmCopyToCaller(UnsafeDx, Dx, Count * sizeof(INT));
459 if (! NT_SUCCESS(Status))
460 {
461 if (NULL != Dx)
462 {
463 ExFreePoolWithTag(Dx, GDITAG_TEXT);
464 }
465 SetLastNtError(Status);
466 return FALSE;
467 }
468 }
469 if (NULL != Dx)
470 {
471 ExFreePoolWithTag(Dx, GDITAG_TEXT);
472 }
473
474 Status = MmCopyToCaller(UnsafeSize, &Size, sizeof(SIZE));
475 if (! NT_SUCCESS(Status))
476 {
477 SetLastNtError(Status);
478 return FALSE;
479 }
480
481 return TRUE;
482 }
483
484
485 /*
486 flOpts :
487 GetTextExtentPoint32W = 0
488 GetTextExtentPointW = 1
489 */
490 BOOL
491 APIENTRY
NtGdiGetTextExtent(HDC hdc,LPWSTR lpwsz,INT cwc,LPSIZE psize,UINT flOpts)492 NtGdiGetTextExtent(HDC hdc,
493 LPWSTR lpwsz,
494 INT cwc,
495 LPSIZE psize,
496 UINT flOpts)
497 {
498 return NtGdiGetTextExtentExW(hdc, lpwsz, cwc, 0, NULL, NULL, psize, flOpts);
499 }
500
501 BOOL
502 APIENTRY
NtGdiSetTextJustification(HDC hDC,int BreakExtra,int BreakCount)503 NtGdiSetTextJustification(HDC hDC,
504 int BreakExtra,
505 int BreakCount)
506 {
507 PDC pDc;
508 PDC_ATTR pdcattr;
509
510 pDc = DC_LockDc(hDC);
511 if (!pDc)
512 {
513 EngSetLastError(ERROR_INVALID_HANDLE);
514 return FALSE;
515 }
516
517 pdcattr = pDc->pdcattr;
518
519 pdcattr->lBreakExtra = BreakExtra;
520 pdcattr->cBreak = BreakCount;
521
522 DC_UnlockDc(pDc);
523 return TRUE;
524 }
525
526
527 W32KAPI
528 INT
529 APIENTRY
NtGdiGetTextFaceW(IN HDC hDC,IN INT Count,OUT OPTIONAL LPWSTR FaceName,IN BOOL bAliasName)530 NtGdiGetTextFaceW(
531 IN HDC hDC,
532 IN INT Count,
533 OUT OPTIONAL LPWSTR FaceName,
534 IN BOOL bAliasName
535 )
536 {
537 PDC Dc;
538 PDC_ATTR pdcattr;
539 HFONT hFont;
540 PTEXTOBJ TextObj;
541 NTSTATUS Status;
542 SIZE_T fLen;
543 INT ret;
544
545 /* FIXME: Handle bAliasName */
546
547 Dc = DC_LockDc(hDC);
548 if (Dc == NULL)
549 {
550 EngSetLastError(ERROR_INVALID_HANDLE);
551 return FALSE;
552 }
553 pdcattr = Dc->pdcattr;
554 hFont = pdcattr->hlfntNew;
555 DC_UnlockDc(Dc);
556
557 TextObj = RealizeFontInit(hFont);
558 ASSERT(TextObj != NULL);
559 fLen = wcslen(TextObj->TextFace) + 1;
560
561 if (FaceName != NULL)
562 {
563 Count = min(Count, fLen);
564 Status = MmCopyToCaller(FaceName, TextObj->TextFace, Count * sizeof(WCHAR));
565 if (!NT_SUCCESS(Status))
566 {
567 TEXTOBJ_UnlockText(TextObj);
568 SetLastNtError(Status);
569 return 0;
570 }
571 /* Terminate if we copied only part of the font name */
572 if (Count > 0 && Count < fLen)
573 {
574 FaceName[Count - 1] = '\0';
575 }
576 ret = Count;
577 }
578 else
579 {
580 ret = fLen;
581 }
582
583 TEXTOBJ_UnlockText(TextObj);
584 return ret;
585 }
586
587 W32KAPI
588 BOOL
589 APIENTRY
NtGdiGetTextMetricsW(IN HDC hDC,OUT TMW_INTERNAL * pUnsafeTmwi,IN ULONG cj)590 NtGdiGetTextMetricsW(
591 IN HDC hDC,
592 OUT TMW_INTERNAL * pUnsafeTmwi,
593 IN ULONG cj)
594 {
595 TMW_INTERNAL Tmwi;
596
597 if ( cj <= sizeof(TMW_INTERNAL) )
598 {
599 if (ftGdiGetTextMetricsW(hDC, &Tmwi))
600 {
601 IntTMWFixUp(hDC, &Tmwi);
602 _SEH2_TRY
603 {
604 ProbeForWrite(pUnsafeTmwi, cj, 1);
605 RtlCopyMemory(pUnsafeTmwi, &Tmwi, cj);
606 }
607 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
608 {
609 SetLastNtError(_SEH2_GetExceptionCode());
610 _SEH2_YIELD(return FALSE);
611 }
612 _SEH2_END
613
614 return TRUE;
615 }
616 }
617 return FALSE;
618 }
619
620 /* EOF */
621