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