[WIN32SS] Rewrite font selection code. Patch by Katayama Hirofumi MZ. CORE-6621
[reactos.git] / reactos / 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 INT fLen, ret;
500
501 /* FIXME: Handle bAliasName */
502
503 Dc = DC_LockDc(hDC);
504 if (Dc == NULL)
505 {
506 EngSetLastError(ERROR_INVALID_HANDLE);
507 return FALSE;
508 }
509 pdcattr = Dc->pdcattr;
510 hFont = pdcattr->hlfntNew;
511 DC_UnlockDc(Dc);
512
513 TextObj = RealizeFontInit(hFont);
514 ASSERT(TextObj != NULL);
515 fLen = wcslen(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfFaceName) + 1;
516
517 if (FaceName != NULL)
518 {
519 Count = min(Count, fLen);
520 Status = MmCopyToCaller(FaceName, TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfFaceName, Count * sizeof(WCHAR));
521 if (!NT_SUCCESS(Status))
522 {
523 TEXTOBJ_UnlockText(TextObj);
524 SetLastNtError(Status);
525 return 0;
526 }
527 /* Terminate if we copied only part of the font name */
528 if (Count > 0 && Count < fLen)
529 {
530 FaceName[Count - 1] = '\0';
531 }
532 ret = Count;
533 }
534 else
535 {
536 ret = fLen;
537 }
538
539 TEXTOBJ_UnlockText(TextObj);
540 return ret;
541 }
542
543 W32KAPI
544 BOOL
545 APIENTRY
546 NtGdiGetTextMetricsW(
547 IN HDC hDC,
548 OUT TMW_INTERNAL * pUnsafeTmwi,
549 IN ULONG cj)
550 {
551 TMW_INTERNAL Tmwi;
552
553 if ( cj <= sizeof(TMW_INTERNAL) )
554 {
555 if (ftGdiGetTextMetricsW(hDC, &Tmwi))
556 {
557 _SEH2_TRY
558 {
559 ProbeForWrite(pUnsafeTmwi, cj, 1);
560 RtlCopyMemory(pUnsafeTmwi, &Tmwi, cj);
561 }
562 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
563 {
564 SetLastNtError(_SEH2_GetExceptionCode());
565 _SEH2_YIELD(return FALSE);
566 }
567 _SEH2_END
568
569 return TRUE;
570 }
571 }
572 return FALSE;
573 }
574
575 /* EOF */