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