ec0503fa465785cfa87524362415874467f12f02
[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: 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->FaceName) + 1;
517
518 if (FaceName != NULL)
519 {
520 Count = min(Count, fLen);
521 Status = MmCopyToCaller(FaceName, TextObj->FaceName, 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 */