Sync to trunk revision 63857.
[reactos.git] / win32ss / gdi / ntgdi / text.c
1 /*
2 * PROJECT: ReactOS win32 kernel mode subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/objects/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, (LPWSTR)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 LPWSTR 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 LPWSTR 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 DWORD
150 APIENTRY
151 NtGdiGetCharSet(HDC hDC)
152 {
153 PDC Dc;
154 PDC_ATTR pdcattr;
155 DWORD cscp;
156 // If here, update everything!
157 Dc = DC_LockDc(hDC);
158 if (!Dc)
159 {
160 EngSetLastError(ERROR_INVALID_HANDLE);
161 return 0;
162 }
163 cscp = ftGdiGetTextCharsetInfo(Dc, NULL, 0);
164 pdcattr = Dc->pdcattr;
165 pdcattr->iCS_CP = cscp;
166 pdcattr->ulDirty_ &= ~DIRTY_CHARSET;
167 DC_UnlockDc( Dc );
168 return cscp;
169 }
170
171 BOOL
172 APIENTRY
173 NtGdiGetRasterizerCaps(
174 OUT LPRASTERIZER_STATUS praststat,
175 IN ULONG cjBytes)
176 {
177 NTSTATUS Status = STATUS_SUCCESS;
178 RASTERIZER_STATUS rsSafe;
179
180 if (praststat && cjBytes)
181 {
182 if ( cjBytes >= sizeof(RASTERIZER_STATUS) ) cjBytes = sizeof(RASTERIZER_STATUS);
183 if ( ftGdiGetRasterizerCaps(&rsSafe))
184 {
185 _SEH2_TRY
186 {
187 ProbeForWrite( praststat,
188 sizeof(RASTERIZER_STATUS),
189 1);
190 RtlCopyMemory(praststat, &rsSafe, cjBytes );
191 }
192 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
193 {
194 Status = _SEH2_GetExceptionCode();
195 }
196 _SEH2_END;
197
198 if (!NT_SUCCESS(Status))
199 {
200 SetLastNtError(Status);
201 return FALSE;
202 }
203
204 return TRUE;
205 }
206 }
207 return FALSE;
208 }
209
210 INT
211 APIENTRY
212 NtGdiGetTextCharsetInfo(
213 IN HDC hdc,
214 OUT OPTIONAL LPFONTSIGNATURE lpSig,
215 IN DWORD dwFlags)
216 {
217 PDC Dc;
218 INT Ret;
219 FONTSIGNATURE fsSafe;
220 PFONTSIGNATURE pfsSafe = &fsSafe;
221 NTSTATUS Status = STATUS_SUCCESS;
222
223 Dc = DC_LockDc(hdc);
224 if (!Dc)
225 {
226 EngSetLastError(ERROR_INVALID_HANDLE);
227 return DEFAULT_CHARSET;
228 }
229
230 if (!lpSig) pfsSafe = NULL;
231
232 Ret = HIWORD(ftGdiGetTextCharsetInfo( Dc, pfsSafe, dwFlags));
233
234 if (lpSig)
235 {
236 if (Ret == DEFAULT_CHARSET)
237 RtlZeroMemory(pfsSafe, sizeof(FONTSIGNATURE));
238
239 _SEH2_TRY
240 {
241 ProbeForWrite( lpSig,
242 sizeof(FONTSIGNATURE),
243 1);
244 RtlCopyMemory(lpSig, pfsSafe, sizeof(FONTSIGNATURE));
245 }
246 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
247 {
248 Status = _SEH2_GetExceptionCode();
249 }
250 _SEH2_END;
251
252 if (!NT_SUCCESS(Status))
253 {
254 SetLastNtError(Status);
255 return DEFAULT_CHARSET;
256 }
257 }
258 DC_UnlockDc(Dc);
259 return Ret;
260 }
261
262
263 /*
264 fl :
265 GetTextExtentExPointW = 0 and everything else that uses this.
266 GetTextExtentExPointI = 1
267 */
268 W32KAPI
269 BOOL
270 APIENTRY
271 NtGdiGetTextExtentExW(
272 IN HDC hDC,
273 IN OPTIONAL LPWSTR UnsafeString,
274 IN ULONG Count,
275 IN ULONG MaxExtent,
276 OUT OPTIONAL PULONG UnsafeFit,
277 OUT OPTIONAL PULONG UnsafeDx,
278 OUT LPSIZE UnsafeSize,
279 IN FLONG fl
280 )
281 {
282 PDC dc;
283 PDC_ATTR pdcattr;
284 LPWSTR String;
285 SIZE Size;
286 NTSTATUS Status;
287 BOOLEAN Result;
288 INT Fit;
289 LPINT Dx;
290 PTEXTOBJ TextObj;
291
292 if ((LONG)Count < 0)
293 {
294 EngSetLastError(ERROR_INVALID_PARAMETER);
295 return FALSE;
296 }
297
298 /* FIXME: Handle fl */
299
300 if (0 == Count)
301 {
302 Size.cx = 0;
303 Size.cy = 0;
304 Status = MmCopyToCaller(UnsafeSize, &Size, sizeof(SIZE));
305 if (! NT_SUCCESS(Status))
306 {
307 SetLastNtError(Status);
308 return FALSE;
309 }
310 return TRUE;
311 }
312
313 String = ExAllocatePoolWithTag(PagedPool, Count * sizeof(WCHAR), GDITAG_TEXT);
314 if (NULL == String)
315 {
316 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
317 return FALSE;
318 }
319
320 if (NULL != UnsafeDx)
321 {
322 Dx = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), GDITAG_TEXT);
323 if (NULL == Dx)
324 {
325 ExFreePoolWithTag(String, GDITAG_TEXT);
326 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
327 return FALSE;
328 }
329 }
330 else
331 {
332 Dx = NULL;
333 }
334
335 Status = MmCopyFromCaller(String, UnsafeString, Count * sizeof(WCHAR));
336 if (! NT_SUCCESS(Status))
337 {
338 if (NULL != Dx)
339 {
340 ExFreePoolWithTag(Dx, GDITAG_TEXT);
341 }
342 ExFreePoolWithTag(String, GDITAG_TEXT);
343 SetLastNtError(Status);
344 return FALSE;
345 }
346
347 dc = DC_LockDc(hDC);
348 if (NULL == dc)
349 {
350 if (NULL != Dx)
351 {
352 ExFreePoolWithTag(Dx, GDITAG_TEXT);
353 }
354 ExFreePoolWithTag(String, GDITAG_TEXT);
355 EngSetLastError(ERROR_INVALID_HANDLE);
356 return FALSE;
357 }
358 pdcattr = dc->pdcattr;
359 TextObj = RealizeFontInit(pdcattr->hlfntNew);
360 if ( TextObj )
361 {
362 Result = TextIntGetTextExtentPoint( dc,
363 TextObj,
364 String,
365 Count,
366 MaxExtent,
367 NULL == UnsafeFit ? NULL : &Fit,
368 Dx,
369 &Size,
370 fl);
371 TEXTOBJ_UnlockText(TextObj);
372 }
373 else
374 Result = FALSE;
375 DC_UnlockDc(dc);
376
377 ExFreePoolWithTag(String, GDITAG_TEXT);
378 if (! Result)
379 {
380 if (NULL != Dx)
381 {
382 ExFreePoolWithTag(Dx, GDITAG_TEXT);
383 }
384 return FALSE;
385 }
386
387 if (NULL != UnsafeFit)
388 {
389 Status = MmCopyToCaller(UnsafeFit, &Fit, sizeof(INT));
390 if (! NT_SUCCESS(Status))
391 {
392 if (NULL != Dx)
393 {
394 ExFreePoolWithTag(Dx, GDITAG_TEXT);
395 }
396 SetLastNtError(Status);
397 return FALSE;
398 }
399 }
400
401 if (NULL != UnsafeDx)
402 {
403 Status = MmCopyToCaller(UnsafeDx, Dx, Count * sizeof(INT));
404 if (! NT_SUCCESS(Status))
405 {
406 if (NULL != Dx)
407 {
408 ExFreePoolWithTag(Dx, GDITAG_TEXT);
409 }
410 SetLastNtError(Status);
411 return FALSE;
412 }
413 }
414 if (NULL != Dx)
415 {
416 ExFreePoolWithTag(Dx, GDITAG_TEXT);
417 }
418
419 Status = MmCopyToCaller(UnsafeSize, &Size, sizeof(SIZE));
420 if (! NT_SUCCESS(Status))
421 {
422 SetLastNtError(Status);
423 return FALSE;
424 }
425
426 return TRUE;
427 }
428
429
430 /*
431 flOpts :
432 GetTextExtentPoint32W = 0
433 GetTextExtentPointW = 1
434 */
435 BOOL
436 APIENTRY
437 NtGdiGetTextExtent(HDC hdc,
438 LPWSTR lpwsz,
439 INT cwc,
440 LPSIZE psize,
441 UINT flOpts)
442 {
443 return NtGdiGetTextExtentExW(hdc, lpwsz, cwc, 0, NULL, NULL, psize, flOpts);
444 }
445
446 BOOL
447 APIENTRY
448 NtGdiSetTextJustification(HDC hDC,
449 int BreakExtra,
450 int BreakCount)
451 {
452 PDC pDc;
453 PDC_ATTR pdcattr;
454
455 pDc = DC_LockDc(hDC);
456 if (!pDc)
457 {
458 EngSetLastError(ERROR_INVALID_HANDLE);
459 return FALSE;
460 }
461
462 pdcattr = pDc->pdcattr;
463
464 pdcattr->lBreakExtra = BreakExtra;
465 pdcattr->cBreak = BreakCount;
466
467 DC_UnlockDc(pDc);
468 return TRUE;
469 }
470
471
472 W32KAPI
473 INT
474 APIENTRY
475 NtGdiGetTextFaceW(
476 IN HDC hDC,
477 IN INT Count,
478 OUT OPTIONAL LPWSTR FaceName,
479 IN BOOL bAliasName
480 )
481 {
482 PDC Dc;
483 PDC_ATTR pdcattr;
484 HFONT hFont;
485 PTEXTOBJ TextObj;
486 NTSTATUS Status;
487 INT fLen, ret;
488
489 /* FIXME: Handle bAliasName */
490
491 Dc = DC_LockDc(hDC);
492 if (Dc == NULL)
493 {
494 EngSetLastError(ERROR_INVALID_HANDLE);
495 return FALSE;
496 }
497 pdcattr = Dc->pdcattr;
498 hFont = pdcattr->hlfntNew;
499 DC_UnlockDc(Dc);
500
501 TextObj = RealizeFontInit(hFont);
502 ASSERT(TextObj != NULL);
503 fLen = wcslen(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfFaceName) + 1;
504
505 if (FaceName != NULL)
506 {
507 Count = min(Count, fLen);
508 Status = MmCopyToCaller(FaceName, TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfFaceName, Count * sizeof(WCHAR));
509 if (!NT_SUCCESS(Status))
510 {
511 TEXTOBJ_UnlockText(TextObj);
512 SetLastNtError(Status);
513 return 0;
514 }
515 /* Terminate if we copied only part of the font name */
516 if (Count > 0 && Count < fLen)
517 {
518 FaceName[Count - 1] = '\0';
519 }
520 ret = Count;
521 }
522 else
523 {
524 ret = fLen;
525 }
526
527 TEXTOBJ_UnlockText(TextObj);
528 return ret;
529 }
530
531 W32KAPI
532 BOOL
533 APIENTRY
534 NtGdiGetTextMetricsW(
535 IN HDC hDC,
536 OUT TMW_INTERNAL * pUnsafeTmwi,
537 IN ULONG cj)
538 {
539 TMW_INTERNAL Tmwi;
540
541 if ( cj <= sizeof(TMW_INTERNAL) )
542 {
543 if (ftGdiGetTextMetricsW(hDC, &Tmwi))
544 {
545 _SEH2_TRY
546 {
547 ProbeForWrite(pUnsafeTmwi, cj, 1);
548 RtlCopyMemory(pUnsafeTmwi, &Tmwi, cj);
549 }
550 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
551 {
552 SetLastNtError(_SEH2_GetExceptionCode());
553 _SEH2_YIELD(return FALSE);
554 }
555 _SEH2_END
556
557 return TRUE;
558 }
559 }
560 return FALSE;
561 }
562
563 /* EOF */