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