dinput: Silence incorrect warning and move it to a valid place.
[wine] / dlls / gdi32 / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1997 Alex Korobka
6  * Copyright 2002,2003 Shachar Shemesh
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "wownt32.h"
35 #include "gdi_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
40
41   /* Device -> World size conversion */
42
43 /* Performs a device to world transformation on the specified width (which
44  * is in integer format).
45  */
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
47 {
48     FLOAT floatWidth;
49
50     /* Perform operation with floating point */
51     floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
52     /* Round to integers */
53     return GDI_ROUND(floatWidth);
54 }
55
56 /* Performs a device to world transformation on the specified size (which
57  * is in integer format).
58  */
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
60 {
61     FLOAT floatHeight;
62
63     /* Perform operation with floating point */
64     floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
65     /* Round to integers */
66     return GDI_ROUND(floatHeight);
67 }
68
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
70 {
71     POINT pt[2];
72     pt[0].x = pt[0].y = 0;
73     pt[1].x = width;
74     pt[1].y = 0;
75     LPtoDP(dc->hSelf, pt, 2);
76     return pt[1].x - pt[0].x;
77 }
78
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
80 {
81     POINT pt[2];
82     pt[0].x = pt[0].y = 0;
83     pt[1].x = 0;
84     pt[1].y = height;
85     LPtoDP(dc->hSelf, pt, 2);
86     return pt[1].y - pt[0].y;
87 }
88
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
91 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
93 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
94
95 static const struct gdi_obj_funcs font_funcs =
96 {
97     FONT_SelectObject,  /* pSelectObject */
98     FONT_GetObject16,   /* pGetObject16 */
99     FONT_GetObjectA,    /* pGetObjectA */
100     FONT_GetObjectW,    /* pGetObjectW */
101     NULL,               /* pUnrealizeObject */
102     FONT_DeleteObject   /* pDeleteObject */
103 };
104
105 #define ENUM_UNICODE    0x00000001
106 #define ENUM_CALLED     0x00000002
107
108 typedef struct
109 {
110     GDIOBJHDR   header;
111     LOGFONTW    logfont;
112 } FONTOBJ;
113
114 typedef struct
115 {
116   LPLOGFONT16           lpLogFontParam;
117   FONTENUMPROC16        lpEnumFunc;
118   LPARAM                lpData;
119
120   LPNEWTEXTMETRICEX16   lpTextMetric;
121   LPENUMLOGFONTEX16     lpLogFont;
122   SEGPTR                segTextMetric;
123   SEGPTR                segLogFont;
124   DWORD                 dwFlags;
125   HDC                   hdc;
126   DC                   *dc;
127   PHYSDEV               physDev;
128 } fontEnum16;
129
130 typedef struct
131 {
132   LPLOGFONTW          lpLogFontParam;
133   FONTENUMPROCW       lpEnumFunc;
134   LPARAM              lpData;
135   DWORD               dwFlags;
136   HDC                 hdc;
137   DC                 *dc;
138   PHYSDEV             physDev;
139 } fontEnum32;
140
141 /*
142  *  For TranslateCharsetInfo
143  */
144 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
145 #define MAXTCIINDEX 32
146 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
147   /* ANSI */
148   { ANSI_CHARSET, 1252, FS(0)},
149   { EASTEUROPE_CHARSET, 1250, FS(1)},
150   { RUSSIAN_CHARSET, 1251, FS(2)},
151   { GREEK_CHARSET, 1253, FS(3)},
152   { TURKISH_CHARSET, 1254, FS(4)},
153   { HEBREW_CHARSET, 1255, FS(5)},
154   { ARABIC_CHARSET, 1256, FS(6)},
155   { BALTIC_CHARSET, 1257, FS(7)},
156   { VIETNAMESE_CHARSET, 1258, FS(8)},
157   /* reserved by ANSI */
158   { DEFAULT_CHARSET, 0, FS(0)},
159   { DEFAULT_CHARSET, 0, FS(0)},
160   { DEFAULT_CHARSET, 0, FS(0)},
161   { DEFAULT_CHARSET, 0, FS(0)},
162   { DEFAULT_CHARSET, 0, FS(0)},
163   { DEFAULT_CHARSET, 0, FS(0)},
164   { DEFAULT_CHARSET, 0, FS(0)},
165   /* ANSI and OEM */
166   { THAI_CHARSET,  874,  FS(16)},
167   { SHIFTJIS_CHARSET, 932, FS(17)},
168   { GB2312_CHARSET, 936, FS(18)},
169   { HANGEUL_CHARSET, 949, FS(19)},
170   { CHINESEBIG5_CHARSET, 950, FS(20)},
171   { JOHAB_CHARSET, 1361, FS(21)},
172   /* reserved for alternate ANSI and OEM */
173   { DEFAULT_CHARSET, 0, FS(0)},
174   { DEFAULT_CHARSET, 0, FS(0)},
175   { DEFAULT_CHARSET, 0, FS(0)},
176   { DEFAULT_CHARSET, 0, FS(0)},
177   { DEFAULT_CHARSET, 0, FS(0)},
178   { DEFAULT_CHARSET, 0, FS(0)},
179   { DEFAULT_CHARSET, 0, FS(0)},
180   { DEFAULT_CHARSET, 0, FS(0)},
181   /* reserved for system */
182   { DEFAULT_CHARSET, 0, FS(0)},
183   { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
184 };
185
186 /***********************************************************************
187  *              LOGFONT conversion functions.
188  */
189 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
190 {
191     font16->lfHeight = font32->lfHeight;
192     font16->lfWidth = font32->lfWidth;
193     font16->lfEscapement = font32->lfEscapement;
194     font16->lfOrientation = font32->lfOrientation;
195     font16->lfWeight = font32->lfWeight;
196     font16->lfItalic = font32->lfItalic;
197     font16->lfUnderline = font32->lfUnderline;
198     font16->lfStrikeOut = font32->lfStrikeOut;
199     font16->lfCharSet = font32->lfCharSet;
200     font16->lfOutPrecision = font32->lfOutPrecision;
201     font16->lfClipPrecision = font32->lfClipPrecision;
202     font16->lfQuality = font32->lfQuality;
203     font16->lfPitchAndFamily = font32->lfPitchAndFamily;
204     WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
205                          font16->lfFaceName, LF_FACESIZE, NULL, NULL );
206     font16->lfFaceName[LF_FACESIZE-1] = 0;
207 }
208
209 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
210 {
211     font32->lfHeight = font16->lfHeight;
212     font32->lfWidth = font16->lfWidth;
213     font32->lfEscapement = font16->lfEscapement;
214     font32->lfOrientation = font16->lfOrientation;
215     font32->lfWeight = font16->lfWeight;
216     font32->lfItalic = font16->lfItalic;
217     font32->lfUnderline = font16->lfUnderline;
218     font32->lfStrikeOut = font16->lfStrikeOut;
219     font32->lfCharSet = font16->lfCharSet;
220     font32->lfOutPrecision = font16->lfOutPrecision;
221     font32->lfClipPrecision = font16->lfClipPrecision;
222     font32->lfQuality = font16->lfQuality;
223     font32->lfPitchAndFamily = font16->lfPitchAndFamily;
224     MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
225     font32->lfFaceName[LF_FACESIZE-1] = 0;
226 }
227
228 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
229 {
230     memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
231     MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
232                         LF_FACESIZE);
233     fontW->lfFaceName[LF_FACESIZE-1] = 0;
234 }
235
236 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
237 {
238     memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
239     WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
240                         LF_FACESIZE, NULL, NULL);
241     fontA->lfFaceName[LF_FACESIZE-1] = 0;
242 }
243
244 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
245 {
246     FONT_LogFontWTo16( (const LOGFONTW *)fontW, (LPLOGFONT16)font16);
247
248     WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
249                          (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
250     font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
251     WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
252                          (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
253     font16->elfStyle[LF_FACESIZE-1] = '\0';
254     WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
255                          (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
256     font16->elfScript[LF_FACESIZE-1] = '\0';
257 }
258
259 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
260 {
261     FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
262
263     WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
264                          (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
265     fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
266     WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
267                          (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
268     fontA->elfStyle[LF_FACESIZE-1] = '\0';
269     WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
270                          (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
271     fontA->elfScript[LF_FACESIZE-1] = '\0';
272 }
273
274 /***********************************************************************
275  *              TEXTMETRIC conversion functions.
276  */
277 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
278 {
279     ptmA->tmHeight = ptmW->tmHeight;
280     ptmA->tmAscent = ptmW->tmAscent;
281     ptmA->tmDescent = ptmW->tmDescent;
282     ptmA->tmInternalLeading = ptmW->tmInternalLeading;
283     ptmA->tmExternalLeading = ptmW->tmExternalLeading;
284     ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
285     ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
286     ptmA->tmWeight = ptmW->tmWeight;
287     ptmA->tmOverhang = ptmW->tmOverhang;
288     ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
289     ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
290     ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
291     if (ptmW->tmCharSet == SYMBOL_CHARSET)
292     {
293         UINT last_char = ptmW->tmLastChar;
294         if (last_char > 0xf000) last_char -= 0xf000;
295         ptmA->tmLastChar = min(last_char, 255);
296     }
297     else
298         ptmA->tmLastChar = min(ptmW->tmLastChar, 255);
299     ptmA->tmDefaultChar = min(ptmW->tmDefaultChar, 255);
300     ptmA->tmBreakChar = min(ptmW->tmBreakChar, 255);
301     ptmA->tmItalic = ptmW->tmItalic;
302     ptmA->tmUnderlined = ptmW->tmUnderlined;
303     ptmA->tmStruckOut = ptmW->tmStruckOut;
304     ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
305     ptmA->tmCharSet = ptmW->tmCharSet;
306 }
307
308
309 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
310 {
311     ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
312     ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
313     ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
314     ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
315     ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
316     ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
317     ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
318     ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
319     ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
320     ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
321     ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
322     ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
323     ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
324     ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
325     ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
326     ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
327     ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
328     ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
329     ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
330     ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
331     ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
332     ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
333     ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
334     ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
335     memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
336 }
337
338 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
339 {
340     FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
341     ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
342     ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
343     ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
344     ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
345     memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
346 }
347
348
349 /***********************************************************************
350  *           GdiGetCodePage   (GDI32.@)
351  */
352 DWORD WINAPI GdiGetCodePage( HDC hdc )
353 {
354     UINT cp = CP_ACP;
355     CHARSETINFO csi;
356     int charset = GetTextCharset(hdc);
357
358     /* Hmm, nicely designed api this one! */
359     if(TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
360         cp = csi.ciACP;
361     else {
362         switch(charset) {
363         case OEM_CHARSET:
364             cp = GetOEMCP();
365             break;
366         case DEFAULT_CHARSET:
367             cp = GetACP();
368             break;
369
370         case VISCII_CHARSET:
371         case TCVN_CHARSET:
372         case KOI8_CHARSET:
373         case ISO3_CHARSET:
374         case ISO4_CHARSET:
375         case ISO10_CHARSET:
376         case CELTIC_CHARSET:
377             /* FIXME: These have no place here, but because x11drv
378                enumerates fonts with these (made up) charsets some apps
379                might use them and then the FIXME below would become
380                annoying.  Now we could pick the intended codepage for
381                each of these, but since it's broken anyway we'll just
382                use CP_ACP and hope it'll go away...
383             */
384             cp = CP_ACP;
385             break;
386
387         default:
388             FIXME("Can't find codepage for charset %d\n", charset);
389             break;
390         }
391     }
392
393     TRACE("charset %d => cp %d\n", charset, cp);
394     return cp;
395 }
396
397 /***********************************************************************
398  *           FONT_mbtowc
399  *
400  * Returns a Unicode translation of str using the charset of the
401  * currently selected font in hdc.  If count is -1 then str is assumed
402  * to be '\0' terminated, otherwise it contains the number of bytes to
403  * convert.  If plenW is non-NULL, on return it will point to the
404  * number of WCHARs that have been written.  If pCP is non-NULL, on
405  * return it will point to the codepage used in the conversion.  The
406  * caller should free the returned LPWSTR from the process heap
407  * itself.
408  */
409 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
410 {
411     UINT cp;
412     INT lenW;
413     LPWSTR strW;
414
415     cp = GdiGetCodePage( hdc );
416
417     if(count == -1) count = strlen(str);
418     lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
419     strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
420     MultiByteToWideChar(cp, 0, str, count, strW, lenW);
421     TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
422     if(plenW) *plenW = lenW;
423     if(pCP) *pCP = cp;
424     return strW;
425 }
426
427
428 /***********************************************************************
429  *           CreateFontIndirectA   (GDI32.@)
430  */
431 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
432 {
433     LOGFONTW lfW;
434
435     if (!plfA) return 0;
436
437     FONT_LogFontAToW( plfA, &lfW );
438     return CreateFontIndirectW( &lfW );
439 }
440
441 /***********************************************************************
442  *           CreateFontIndirectW   (GDI32.@)
443  */
444 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
445 {
446     static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
447     static const WCHAR BoldW[]   = {' ','B','o','l','d','\0'};
448     WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
449     WCHAR *pFaceNameSuffix = NULL;
450     HFONT hFont;
451     FONTOBJ *fontPtr;
452
453     if (!plf) return 0;
454
455     if (!(fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC, (HGDIOBJ *)&hFont,
456                                      &font_funcs ))) return 0;
457
458     memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
459
460     TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
461           plf->lfHeight, plf->lfWidth,
462           plf->lfEscapement, plf->lfOrientation,
463           plf->lfPitchAndFamily,
464           plf->lfOutPrecision, plf->lfClipPrecision,
465           plf->lfQuality, plf->lfCharSet,
466           debugstr_w(plf->lfFaceName),
467           plf->lfWeight > 400 ? "Bold" : "",
468           plf->lfItalic ? "Italic" : "",
469           plf->lfUnderline ? "Underline" : "", hFont);
470
471     if (plf->lfEscapement != plf->lfOrientation)
472     {
473         /* this should really depend on whether GM_ADVANCED is set */
474         fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
475         WARN("orientation angle %f set to "
476              "escapement angle %f for new font %p\n",
477              plf->lfOrientation/10., plf->lfEscapement/10., hFont);
478     }
479
480     pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
481     if (pFaceNameItalicSuffix)
482     {
483         fontPtr->logfont.lfItalic = TRUE;
484         pFaceNameSuffix = pFaceNameItalicSuffix;
485     }
486
487     pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
488     if (pFaceNameBoldSuffix)
489     {
490         if (fontPtr->logfont.lfWeight < FW_BOLD)
491             fontPtr->logfont.lfWeight = FW_BOLD;
492         if (!pFaceNameSuffix || (pFaceNameBoldSuffix < pFaceNameSuffix))
493             pFaceNameSuffix = pFaceNameBoldSuffix;
494     }
495
496     if (pFaceNameSuffix) *pFaceNameSuffix = 0;
497
498     GDI_ReleaseObj( hFont );
499     return hFont;
500 }
501
502 /*************************************************************************
503  *           CreateFontA    (GDI32.@)
504  */
505 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
506                               INT orient, INT weight, DWORD italic,
507                               DWORD underline, DWORD strikeout, DWORD charset,
508                               DWORD outpres, DWORD clippres, DWORD quality,
509                               DWORD pitch, LPCSTR name )
510 {
511     LOGFONTA logfont;
512
513     logfont.lfHeight = height;
514     logfont.lfWidth = width;
515     logfont.lfEscapement = esc;
516     logfont.lfOrientation = orient;
517     logfont.lfWeight = weight;
518     logfont.lfItalic = italic;
519     logfont.lfUnderline = underline;
520     logfont.lfStrikeOut = strikeout;
521     logfont.lfCharSet = charset;
522     logfont.lfOutPrecision = outpres;
523     logfont.lfClipPrecision = clippres;
524     logfont.lfQuality = quality;
525     logfont.lfPitchAndFamily = pitch;
526
527     if (name)
528         lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
529     else
530         logfont.lfFaceName[0] = '\0';
531
532     return CreateFontIndirectA( &logfont );
533 }
534
535 /*************************************************************************
536  *           CreateFontW    (GDI32.@)
537  */
538 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
539                               INT orient, INT weight, DWORD italic,
540                               DWORD underline, DWORD strikeout, DWORD charset,
541                               DWORD outpres, DWORD clippres, DWORD quality,
542                               DWORD pitch, LPCWSTR name )
543 {
544     LOGFONTW logfont;
545
546     logfont.lfHeight = height;
547     logfont.lfWidth = width;
548     logfont.lfEscapement = esc;
549     logfont.lfOrientation = orient;
550     logfont.lfWeight = weight;
551     logfont.lfItalic = italic;
552     logfont.lfUnderline = underline;
553     logfont.lfStrikeOut = strikeout;
554     logfont.lfCharSet = charset;
555     logfont.lfOutPrecision = outpres;
556     logfont.lfClipPrecision = clippres;
557     logfont.lfQuality = quality;
558     logfont.lfPitchAndFamily = pitch;
559
560     if (name)
561         lstrcpynW(logfont.lfFaceName, name,
562                   sizeof(logfont.lfFaceName) / sizeof(WCHAR));
563     else
564         logfont.lfFaceName[0] = '\0';
565
566     return CreateFontIndirectW( &logfont );
567 }
568
569
570 /***********************************************************************
571  *           FONT_SelectObject
572  *
573  * If the driver supports vector fonts we create a gdi font first and
574  * then call the driver to give it a chance to supply its own device
575  * font.  If the driver wants to do this it returns TRUE and we can
576  * delete the gdi font, if the driver wants to use the gdi font it
577  * should return FALSE, to signal an error return GDI_ERROR.  For
578  * drivers that don't support vector fonts they must supply their own
579  * font.
580  */
581 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
582 {
583     HGDIOBJ ret = 0;
584     DC *dc = get_dc_ptr( hdc );
585
586     if (!dc) return 0;
587
588     if (!GDI_inc_ref_count( handle ))
589     {
590         release_dc_ptr( dc );
591         return 0;
592     }
593
594     if (dc->hFont != handle || dc->gdiFont == NULL)
595     {
596         if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
597         {
598             FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC );  /* to grab the GDI lock (FIXME) */
599             dc->gdiFont = WineEngCreateFontInstance(dc, handle);
600             if (font) GDI_ReleaseObj( handle );
601         }
602     }
603
604     if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
605
606     if (ret && dc->gdiFont) dc->gdiFont = 0;
607
608     if (ret == HGDI_ERROR)
609     {
610         GDI_dec_ref_count( handle );
611         ret = 0; /* SelectObject returns 0 on error */
612     }
613     else
614     {
615         ret = dc->hFont;
616         dc->hFont = handle;
617         GDI_dec_ref_count( ret );
618     }
619     release_dc_ptr( dc );
620     return ret;
621 }
622
623
624 /***********************************************************************
625  *           FONT_GetObject16
626  */
627 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
628 {
629     FONTOBJ *font = obj;
630     LOGFONT16 lf16;
631
632     FONT_LogFontWTo16( &font->logfont, &lf16 );
633
634     if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
635     memcpy( buffer, &lf16, count );
636     return count;
637 }
638
639 /***********************************************************************
640  *           FONT_GetObjectA
641  */
642 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
643 {
644     FONTOBJ *font = obj;
645     LOGFONTA lfA;
646
647     if(!buffer)
648         return sizeof(lfA);
649     FONT_LogFontWToA( &font->logfont, &lfA );
650
651     if (count > sizeof(lfA)) count = sizeof(lfA);
652     memcpy( buffer, &lfA, count );
653     return count;
654 }
655
656 /***********************************************************************
657  *           FONT_GetObjectW
658  */
659 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
660 {
661     FONTOBJ *font = obj;
662     if(!buffer)
663         return sizeof(LOGFONTW);
664     if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
665     memcpy( buffer, &font->logfont, count );
666     return count;
667 }
668
669
670 /***********************************************************************
671  *           FONT_DeleteObject
672  */
673 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
674 {
675     WineEngDestroyFontInstance( handle );
676     return GDI_FreeObject( handle, obj );
677 }
678
679
680 /***********************************************************************
681  *              FONT_EnumInstance16
682  *
683  * Called by the device driver layer to pass font info
684  * down to the application.
685  *
686  * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
687  *       We have to use other types because of the FONTENUMPROCW definition.
688  */
689 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
690                                          DWORD fType, LPARAM lp )
691 {
692     fontEnum16 *pfe = (fontEnum16*)lp;
693     INT ret = 1;
694     DC *dc;
695
696     if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
697         pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
698     {
699         WORD args[7];
700         DWORD result;
701
702         FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
703         FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
704         pfe->dwFlags |= ENUM_CALLED;
705         DC_ReleaseDCPtr( pfe->dc );  /* release the GDI lock */
706
707         args[6] = SELECTOROF(pfe->segLogFont);
708         args[5] = OFFSETOF(pfe->segLogFont);
709         args[4] = SELECTOROF(pfe->segTextMetric);
710         args[3] = OFFSETOF(pfe->segTextMetric);
711         args[2] = fType;
712         args[1] = HIWORD(pfe->lpData);
713         args[0] = LOWORD(pfe->lpData);
714         WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
715         ret = LOWORD(result);
716
717         /* get the lock again and make sure the DC is still valid */
718         dc = DC_GetDCPtr( pfe->hdc );
719         if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
720         {
721             if (dc) DC_ReleaseDCPtr( dc );
722             pfe->hdc = 0;  /* make sure we don't try to release it later on */
723             pfe->dc = NULL;
724             ret = 0;
725         }
726     }
727     return ret;
728 }
729
730 /***********************************************************************
731  *              FONT_EnumInstance
732  *
733  * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
734  *       We have to use other types because of the FONTENUMPROCW definition.
735  */
736 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
737                                        DWORD fType, LPARAM lp )
738 {
739     fontEnum32 *pfe = (fontEnum32*)lp;
740     INT ret = 1;
741     DC *dc;
742
743     /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
744     if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
745         pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
746        (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
747     {
748         /* convert font metrics */
749         ENUMLOGFONTEXA logfont;
750         NEWTEXTMETRICEXA tmA;
751
752         pfe->dwFlags |= ENUM_CALLED;
753         if (!(pfe->dwFlags & ENUM_UNICODE))
754         {
755             FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
756             FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
757             plf = (LOGFONTW *)&logfont.elfLogFont;
758             ptm = (TEXTMETRICW *)&tmA;
759         }
760         DC_ReleaseDCPtr( pfe->dc );  /* release the GDI lock */
761
762         ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
763
764         /* get the lock again and make sure the DC is still valid */
765         dc = DC_GetDCPtr( pfe->hdc );
766         if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
767         {
768             if (dc) DC_ReleaseDCPtr( dc );
769             pfe->hdc = 0;  /* make sure we don't try to release it later on */
770             pfe->dc = NULL;
771             ret = 0;
772         }
773     }
774     return ret;
775 }
776
777 /***********************************************************************
778  *              EnumFontFamiliesEx      (GDI.613)
779  */
780 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
781                                    FONTENUMPROC16 efproc, LPARAM lParam,
782                                    DWORD dwFlags)
783 {
784     fontEnum16 fe16;
785     INT16       ret = 1, ret2;
786     DC*         dc = DC_GetDCPtr( HDC_32(hDC) );
787     NEWTEXTMETRICEX16 tm16;
788     ENUMLOGFONTEX16 lf16;
789     LOGFONTW lfW;
790     BOOL enum_gdi_fonts;
791
792     if (!dc) return 0;
793     FONT_LogFont16ToW(plf, &lfW);
794
795     fe16.hdc = HDC_32(hDC);
796     fe16.dc = dc;
797     fe16.physDev = dc->physDev;
798     fe16.lpLogFontParam = plf;
799     fe16.lpEnumFunc = efproc;
800     fe16.lpData = lParam;
801     fe16.lpTextMetric = &tm16;
802     fe16.lpLogFont = &lf16;
803     fe16.segTextMetric = MapLS( &tm16 );
804     fe16.segLogFont = MapLS( &lf16 );
805     fe16.dwFlags = 0;
806
807     enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
808
809     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
810     {
811         ret = 0;
812         goto done;
813     }
814
815     if (enum_gdi_fonts)
816         ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
817     fe16.dwFlags &= ~ENUM_CALLED;
818     if (ret && dc->funcs->pEnumDeviceFonts) {
819         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
820         if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
821             ret = ret2;
822     }
823 done:
824     UnMapLS( fe16.segTextMetric );
825     UnMapLS( fe16.segLogFont );
826     if (fe16.dc) DC_ReleaseDCPtr( fe16.dc );
827     return ret;
828 }
829
830 /***********************************************************************
831  *              FONT_EnumFontFamiliesEx
832  */
833 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
834                                     FONTENUMPROCW efproc,
835                                     LPARAM lParam, DWORD dwUnicode)
836 {
837     INT ret = 1, ret2;
838     DC *dc = DC_GetDCPtr( hDC );
839     fontEnum32 fe32;
840     BOOL enum_gdi_fonts;
841
842     if (!dc) return 0;
843
844     TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
845           plf->lfCharSet);
846     fe32.lpLogFontParam = plf;
847     fe32.lpEnumFunc = efproc;
848     fe32.lpData = lParam;
849     fe32.dwFlags = dwUnicode;
850     fe32.hdc = hDC;
851     fe32.dc = dc;
852     fe32.physDev = dc->physDev;
853
854     enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
855
856     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
857     {
858         ret = 0;
859         goto done;
860     }
861
862     if (enum_gdi_fonts)
863         ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
864     fe32.dwFlags &= ~ENUM_CALLED;
865     if (ret && dc->funcs->pEnumDeviceFonts) {
866         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
867         if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
868             ret = ret2;
869     }
870  done:
871     if (fe32.dc) DC_ReleaseDCPtr( fe32.dc );
872     return ret;
873 }
874
875 /***********************************************************************
876  *              EnumFontFamiliesExW     (GDI32.@)
877  */
878 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
879                                     FONTENUMPROCW efproc,
880                                     LPARAM lParam, DWORD dwFlags )
881 {
882     return  FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
883 }
884
885 /***********************************************************************
886  *              EnumFontFamiliesExA     (GDI32.@)
887  */
888 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
889                                     FONTENUMPROCA efproc,
890                                     LPARAM lParam, DWORD dwFlags)
891 {
892     LOGFONTW lfW;
893     FONT_LogFontAToW( plf, &lfW );
894
895     return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
896 }
897
898 /***********************************************************************
899  *              EnumFontFamilies        (GDI.330)
900  */
901 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
902                                  FONTENUMPROC16 efproc, LPARAM lpData )
903 {
904     LOGFONT16   lf;
905
906     lf.lfCharSet = DEFAULT_CHARSET;
907     if (lpFamily)
908     {
909         if (!*lpFamily) return 1;
910         lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
911     }
912     else lf.lfFaceName[0] = '\0';
913
914     return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
915 }
916
917 /***********************************************************************
918  *              EnumFontFamiliesA       (GDI32.@)
919  */
920 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
921                                   FONTENUMPROCA efproc, LPARAM lpData )
922 {
923     LOGFONTA    lf;
924
925     lf.lfCharSet = DEFAULT_CHARSET;
926     if (lpFamily)
927     {
928         if (!*lpFamily) return 1;
929         lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
930     }
931     else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
932
933     return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
934 }
935
936 /***********************************************************************
937  *              EnumFontFamiliesW       (GDI32.@)
938  */
939 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
940                                   FONTENUMPROCW efproc, LPARAM lpData )
941 {
942     LOGFONTW  lf;
943
944     lf.lfCharSet = DEFAULT_CHARSET;
945     if (lpFamily)
946     {
947         if (!*lpFamily) return 1;
948         lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
949     }
950     else lf.lfFaceName[0] = 0;
951
952     return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
953 }
954
955 /***********************************************************************
956  *              EnumFonts               (GDI.70)
957  */
958 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
959                           LPARAM lpData )
960 {
961     return EnumFontFamilies16( hDC, lpName, efproc, lpData );
962 }
963
964 /***********************************************************************
965  *              EnumFontsA              (GDI32.@)
966  */
967 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
968                            LPARAM lpData )
969 {
970     return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
971 }
972
973 /***********************************************************************
974  *              EnumFontsW              (GDI32.@)
975  */
976 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
977                            LPARAM lpData )
978 {
979     return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
980 }
981
982
983 /***********************************************************************
984  *           GetTextCharacterExtra    (GDI32.@)
985  */
986 INT WINAPI GetTextCharacterExtra( HDC hdc )
987 {
988     INT ret;
989     DC *dc = DC_GetDCPtr( hdc );
990     if (!dc) return 0x80000000;
991     ret = dc->charExtra;
992     DC_ReleaseDCPtr( dc );
993     return ret;
994 }
995
996
997 /***********************************************************************
998  *           SetTextCharacterExtra    (GDI32.@)
999  */
1000 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
1001 {
1002     INT prev;
1003     DC * dc = DC_GetDCPtr( hdc );
1004     if (!dc) return 0x80000000;
1005     if (dc->funcs->pSetTextCharacterExtra)
1006         prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
1007     else
1008     {
1009         prev = dc->charExtra;
1010         dc->charExtra = extra;
1011     }
1012     DC_ReleaseDCPtr( dc );
1013     return prev;
1014 }
1015
1016
1017 /***********************************************************************
1018  *           SetTextJustification    (GDI32.@)
1019  */
1020 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1021 {
1022     BOOL ret = TRUE;
1023     DC * dc = DC_GetDCPtr( hdc );
1024     if (!dc) return FALSE;
1025     if (dc->funcs->pSetTextJustification)
1026         ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1027     else
1028     {
1029         extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1030         if (!extra) breaks = 0;
1031         if (breaks)
1032         {
1033             dc->breakExtra = extra / breaks;
1034             dc->breakRem   = extra - (breaks * dc->breakExtra);
1035         }
1036         else
1037         {
1038             dc->breakExtra = 0;
1039             dc->breakRem   = 0;
1040         }
1041     }
1042     DC_ReleaseDCPtr( dc );
1043     return ret;
1044 }
1045
1046
1047 /***********************************************************************
1048  *           GetTextFaceA    (GDI32.@)
1049  */
1050 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1051 {
1052     INT res = GetTextFaceW(hdc, 0, NULL);
1053     LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1054     GetTextFaceW( hdc, res, nameW );
1055
1056     if (name)
1057     {
1058         if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1059             name[count-1] = 0;
1060         res = strlen(name);
1061     }
1062     else
1063         res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1064     HeapFree( GetProcessHeap(), 0, nameW );
1065     return res;
1066 }
1067
1068 /***********************************************************************
1069  *           GetTextFaceW    (GDI32.@)
1070  */
1071 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1072 {
1073     FONTOBJ *font;
1074     INT     ret = 0;
1075
1076     DC * dc = DC_GetDCPtr( hdc );
1077     if (!dc) return 0;
1078
1079     if(dc->gdiFont)
1080         ret = WineEngGetTextFace(dc->gdiFont, count, name);
1081     else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1082     {
1083         if (name)
1084         {
1085             lstrcpynW( name, font->logfont.lfFaceName, count );
1086             ret = strlenW(name);
1087         }
1088         else ret = strlenW(font->logfont.lfFaceName) + 1;
1089         GDI_ReleaseObj( dc->hFont );
1090     }
1091     DC_ReleaseDCPtr( dc );
1092     return ret;
1093 }
1094
1095
1096 /***********************************************************************
1097  *           GetTextExtentPoint32A    (GDI32.@)
1098  *
1099  * See GetTextExtentPoint32W.
1100  */
1101 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1102                                      LPSIZE size )
1103 {
1104     BOOL ret = FALSE;
1105     INT wlen;
1106     LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1107
1108     if (p) {
1109         ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1110         HeapFree( GetProcessHeap(), 0, p );
1111     }
1112
1113     TRACE("(%p %s %d %p): returning %d x %d\n",
1114           hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1115     return ret;
1116 }
1117
1118
1119 /***********************************************************************
1120  * GetTextExtentPoint32W [GDI32.@]
1121  *
1122  * Computes width/height for a string.
1123  *
1124  * Computes width and height of the specified string.
1125  *
1126  * RETURNS
1127  *    Success: TRUE
1128  *    Failure: FALSE
1129  */
1130 BOOL WINAPI GetTextExtentPoint32W(
1131     HDC hdc,     /* [in]  Handle of device context */
1132     LPCWSTR str,   /* [in]  Address of text string */
1133     INT count,   /* [in]  Number of characters in string */
1134     LPSIZE size) /* [out] Address of structure for string size */
1135 {
1136     return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1137 }
1138
1139 /***********************************************************************
1140  * GetTextExtentExPointI [GDI32.@]
1141  *
1142  * Computes width and height of the array of glyph indices.
1143  *
1144  * PARAMS
1145  *    hdc     [I] Handle of device context.
1146  *    indices [I] Glyph index array.
1147  *    count   [I] Number of glyphs in array.
1148  *    max_ext [I] Maximum width in glyphs.
1149  *    nfit    [O] Maximum number of characters.
1150  *    dxs     [O] Partial string widths.
1151  *    size    [O] Returned string size.
1152  *
1153  * RETURNS
1154  *    Success: TRUE
1155  *    Failure: FALSE
1156  */
1157 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1158                                    LPINT nfit, LPINT dxs, LPSIZE size )
1159 {
1160     BOOL ret = FALSE;
1161     DC * dc = DC_GetDCPtr( hdc );
1162     if (!dc) return FALSE;
1163
1164     if(dc->gdiFont) {
1165         ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
1166         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1167         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1168         size->cx += count * dc->charExtra;
1169     }
1170     else if(dc->funcs->pGetTextExtentExPoint) {
1171         FIXME("calling GetTextExtentExPoint\n");
1172         ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1173                                                 count, max_ext, nfit, dxs, size );
1174     }
1175
1176     DC_ReleaseDCPtr( dc );
1177
1178     TRACE("(%p %p %d %p): returning %d x %d\n",
1179           hdc, indices, count, size, size->cx, size->cy );
1180     return ret;
1181 }
1182
1183 /***********************************************************************
1184  * GetTextExtentPointI [GDI32.@]
1185  *
1186  * Computes width and height of the array of glyph indices.
1187  *
1188  * PARAMS
1189  *    hdc     [I] Handle of device context.
1190  *    indices [I] Glyph index array.
1191  *    count   [I] Number of glyphs in array.
1192  *    size    [O] Returned string size.
1193  *
1194  * RETURNS
1195  *    Success: TRUE
1196  *    Failure: FALSE
1197  */
1198 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1199 {
1200     return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1201 }
1202
1203
1204 /***********************************************************************
1205  *           GetTextExtentPointA    (GDI32.@)
1206  */
1207 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1208                                           LPSIZE size )
1209 {
1210     TRACE("not bug compatible.\n");
1211     return GetTextExtentPoint32A( hdc, str, count, size );
1212 }
1213
1214 /***********************************************************************
1215  *           GetTextExtentPointW   (GDI32.@)
1216  */
1217 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1218                                           LPSIZE size )
1219 {
1220     TRACE("not bug compatible.\n");
1221     return GetTextExtentPoint32W( hdc, str, count, size );
1222 }
1223
1224
1225 /***********************************************************************
1226  *           GetTextExtentExPointA    (GDI32.@)
1227  */
1228 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1229                                    INT maxExt, LPINT lpnFit,
1230                                    LPINT alpDx, LPSIZE size )
1231 {
1232     BOOL ret;
1233     INT wlen;
1234     INT *walpDx = NULL;
1235     LPWSTR p = NULL;
1236     
1237     if (alpDx &&
1238        NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1239        return FALSE;
1240     
1241     p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1242     ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1243     if (walpDx)
1244     {
1245         INT n = lpnFit ? *lpnFit : wlen;
1246         INT i, j;
1247         for(i = 0, j = 0; i < n; i++, j++)
1248         {
1249             alpDx[j] = walpDx[i];
1250             if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1251         }
1252     }
1253     if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1254     HeapFree( GetProcessHeap(), 0, p );
1255     HeapFree( GetProcessHeap(), 0, walpDx );
1256     return ret;
1257 }
1258
1259
1260 /***********************************************************************
1261  *           GetTextExtentExPointW    (GDI32.@)
1262  *
1263  * Return the size of the string as it would be if it was output properly by
1264  * e.g. TextOut.
1265  *
1266  * This should include
1267  * - Intercharacter spacing
1268  * - justification spacing (not yet done)
1269  * - kerning? see below
1270  *
1271  * Kerning.  Since kerning would be carried out by the rendering code it should
1272  * be done by the driver.  However they don't support it yet.  Also I am not
1273  * yet persuaded that (certainly under Win95) any kerning is actually done.
1274  *
1275  * str: According to MSDN this should be null-terminated.  That is not true; a
1276  *      null will not terminate it early.
1277  * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1278  *       than count.  I have seen it be either the size of the full string or
1279  *       1 less than the size of the full string.  I have not seen it bear any
1280  *       resemblance to the portion that would fit.
1281  * lpnFit: What exactly is fitting?  Stupidly, in my opinion, it includes the
1282  *         trailing intercharacter spacing and any trailing justification.
1283  *
1284  * FIXME
1285  * Currently we do this by measuring each character etc.  We should do it by
1286  * passing the request to the driver, perhaps by extending the
1287  * pGetTextExtentPoint function to take the alpDx argument.  That would avoid
1288  * thinking about kerning issues and rounding issues in the justification.
1289  */
1290
1291 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1292                                    INT maxExt, LPINT lpnFit,
1293                                    LPINT alpDx, LPSIZE size )
1294 {
1295     INT nFit = 0;
1296     LPINT dxs = NULL;
1297     DC *dc;
1298     BOOL ret = FALSE;
1299     TEXTMETRICW tm;
1300
1301     TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1302
1303     dc = DC_GetDCPtr(hdc);
1304     if (! dc)
1305         return FALSE;
1306
1307     GetTextMetricsW(hdc, &tm);
1308
1309     /* If we need to calculate nFit, then we need the partial extents even if
1310        the user hasn't provided us with an array.  */
1311     if (lpnFit)
1312     {
1313         dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1314         if (! dxs)
1315         {
1316             DC_ReleaseDCPtr(dc);
1317             SetLastError(ERROR_OUTOFMEMORY);
1318             return FALSE;
1319         }
1320     }
1321     else
1322         dxs = alpDx;
1323
1324     if (dc->gdiFont)
1325         ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1326                                           0, NULL, dxs, size);
1327     else if (dc->funcs->pGetTextExtentExPoint)
1328         ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1329                                                0, NULL, dxs, size);
1330
1331     /* Perform device size to world size transformations.  */
1332     if (ret)
1333     {
1334         INT extra      = dc->charExtra,
1335         breakExtra = dc->breakExtra,
1336         breakRem   = dc->breakRem,
1337         i;
1338
1339         if (dxs)
1340         {
1341             for (i = 0; i < count; ++i)
1342             {
1343                 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1344                 dxs[i] += (i+1) * extra;
1345                 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1346                 {
1347                     dxs[i] += breakExtra;
1348                     if (breakRem > 0)
1349                     {
1350                         breakRem--;
1351                         dxs[i]++;
1352                     }
1353                 }
1354                 if (dxs[i] <= maxExt)
1355                     ++nFit;
1356             }
1357             breakRem = dc->breakRem;
1358         }
1359         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1360         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1361
1362         if (!dxs && count > 1 && (breakExtra || breakRem))
1363         {
1364             for (i = 0; i < count; i++)
1365             {
1366                 if (str[i] == tm.tmBreakChar)
1367                 {
1368                     size->cx += breakExtra;
1369                     if (breakRem > 0)
1370                     {
1371                         breakRem--;
1372                         (size->cx)++;
1373                     }
1374                 }
1375             }
1376         }
1377     }
1378
1379     if (lpnFit)
1380         *lpnFit = nFit;
1381
1382     if (! alpDx)
1383         HeapFree(GetProcessHeap(), 0, dxs);
1384
1385     DC_ReleaseDCPtr( dc );
1386
1387     TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1388     return ret;
1389 }
1390
1391 /***********************************************************************
1392  *           GetTextMetricsA    (GDI32.@)
1393  */
1394 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1395 {
1396     TEXTMETRICW tm32;
1397
1398     if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1399     FONT_TextMetricWToA( &tm32, metrics );
1400     return TRUE;
1401 }
1402
1403 /***********************************************************************
1404  *           GetTextMetricsW    (GDI32.@)
1405  */
1406 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1407 {
1408     BOOL ret = FALSE;
1409     DC * dc = DC_GetDCPtr( hdc );
1410     if (!dc) return FALSE;
1411
1412     if (dc->gdiFont)
1413         ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1414     else if (dc->funcs->pGetTextMetrics)
1415         ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1416
1417     if (ret)
1418     {
1419     /* device layer returns values in device units
1420      * therefore we have to convert them to logical */
1421
1422         metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1423         metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1424
1425 #define WDPTOLP(x) ((x<0)?                                      \
1426                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1427                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1428 #define HDPTOLP(y) ((y<0)?                                      \
1429                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1430                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1431
1432     metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
1433     metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
1434     metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
1435     metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
1436     metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
1437     metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
1438     metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
1439     metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
1440         ret = TRUE;
1441 #undef WDPTOLP
1442 #undef HDPTOLP
1443     TRACE("text metrics:\n"
1444           "    Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1445           "    Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1446           "    UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1447           "    StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1448           "    PitchAndFamily = %02x\n"
1449           "    --------------------\n"
1450           "    InternalLeading = %i\n"
1451           "    Ascent = %i\n"
1452           "    Descent = %i\n"
1453           "    Height = %i\n",
1454           metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1455           metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1456           metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1457           metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1458           metrics->tmPitchAndFamily,
1459           metrics->tmInternalLeading,
1460           metrics->tmAscent,
1461           metrics->tmDescent,
1462           metrics->tmHeight );
1463     }
1464     DC_ReleaseDCPtr( dc );
1465     return ret;
1466 }
1467
1468
1469 /***********************************************************************
1470  * GetOutlineTextMetrics [GDI.308]  Gets metrics for TrueType fonts.
1471  *
1472  * NOTES
1473  *    lpOTM should be LPOUTLINETEXTMETRIC
1474  *
1475  * RETURNS
1476  *    Success: Non-zero or size of required buffer
1477  *    Failure: 0
1478  */
1479 UINT16 WINAPI GetOutlineTextMetrics16(
1480     HDC16 hdc,    /* [in]  Handle of device context */
1481     UINT16 cbData, /* [in]  Size of metric data array */
1482     LPOUTLINETEXTMETRIC16 lpOTM)  /* [out] Address of metric data array */
1483 {
1484     FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1485     return 0;
1486 }
1487
1488
1489 /***********************************************************************
1490  *              GetOutlineTextMetricsA (GDI32.@)
1491  * Gets metrics for TrueType fonts.
1492  *
1493  * NOTES
1494  *    If the supplied buffer isn't big enough Windows partially fills it up to
1495  *    its given length and returns that length.
1496  *
1497  * RETURNS
1498  *    Success: Non-zero or size of required buffer
1499  *    Failure: 0
1500  */
1501 UINT WINAPI GetOutlineTextMetricsA(
1502     HDC hdc,    /* [in]  Handle of device context */
1503     UINT cbData, /* [in]  Size of metric data array */
1504     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1505 {
1506     char buf[512], *ptr;
1507     UINT ret, needed;
1508     OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1509     OUTLINETEXTMETRICA *output = lpOTM;
1510     INT left, len;
1511
1512     if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1513         return 0;
1514     if(ret > sizeof(buf))
1515         lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1516     GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1517
1518     needed = sizeof(OUTLINETEXTMETRICA);
1519     if(lpOTMW->otmpFamilyName)
1520         needed += WideCharToMultiByte(CP_ACP, 0,
1521            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1522                                       NULL, 0, NULL, NULL);
1523     if(lpOTMW->otmpFaceName)
1524         needed += WideCharToMultiByte(CP_ACP, 0,
1525            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1526                                       NULL, 0, NULL, NULL);
1527     if(lpOTMW->otmpStyleName)
1528         needed += WideCharToMultiByte(CP_ACP, 0,
1529            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1530                                       NULL, 0, NULL, NULL);
1531     if(lpOTMW->otmpFullName)
1532         needed += WideCharToMultiByte(CP_ACP, 0,
1533            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1534                                       NULL, 0, NULL, NULL);
1535
1536     if(!lpOTM) {
1537         ret = needed;
1538         goto end;
1539     }
1540
1541     TRACE("needed = %d\n", needed);
1542     if(needed > cbData)
1543         /* Since the supplied buffer isn't big enough, we'll alloc one
1544            that is and memcpy the first cbData bytes into the lpOTM at
1545            the end. */
1546         output = HeapAlloc(GetProcessHeap(), 0, needed);
1547
1548     ret = output->otmSize = min(needed, cbData);
1549     FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1550     output->otmFiller = 0;
1551     output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1552     output->otmfsSelection = lpOTMW->otmfsSelection;
1553     output->otmfsType = lpOTMW->otmfsType;
1554     output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1555     output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1556     output->otmItalicAngle = lpOTMW->otmItalicAngle;
1557     output->otmEMSquare = lpOTMW->otmEMSquare;
1558     output->otmAscent = lpOTMW->otmAscent;
1559     output->otmDescent = lpOTMW->otmDescent;
1560     output->otmLineGap = lpOTMW->otmLineGap;
1561     output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1562     output->otmsXHeight = lpOTMW->otmsXHeight;
1563     output->otmrcFontBox = lpOTMW->otmrcFontBox;
1564     output->otmMacAscent = lpOTMW->otmMacAscent;
1565     output->otmMacDescent = lpOTMW->otmMacDescent;
1566     output->otmMacLineGap = lpOTMW->otmMacLineGap;
1567     output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1568     output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1569     output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1570     output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1571     output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1572     output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1573     output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1574     output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1575     output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1576
1577
1578     ptr = (char*)(output + 1);
1579     left = needed - sizeof(*output);
1580
1581     if(lpOTMW->otmpFamilyName) {
1582         output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1583         len = WideCharToMultiByte(CP_ACP, 0,
1584              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1585                                   ptr, left, NULL, NULL);
1586         left -= len;
1587         ptr += len;
1588     } else
1589         output->otmpFamilyName = 0;
1590
1591     if(lpOTMW->otmpFaceName) {
1592         output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1593         len = WideCharToMultiByte(CP_ACP, 0,
1594              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1595                                   ptr, left, NULL, NULL);
1596         left -= len;
1597         ptr += len;
1598     } else
1599         output->otmpFaceName = 0;
1600
1601     if(lpOTMW->otmpStyleName) {
1602         output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1603         len = WideCharToMultiByte(CP_ACP, 0,
1604              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1605                                   ptr, left, NULL, NULL);
1606         left -= len;
1607         ptr += len;
1608     } else
1609         output->otmpStyleName = 0;
1610
1611     if(lpOTMW->otmpFullName) {
1612         output->otmpFullName = (LPSTR)(ptr - (char*)output);
1613         len = WideCharToMultiByte(CP_ACP, 0,
1614              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1615                                   ptr, left, NULL, NULL);
1616         left -= len;
1617     } else
1618         output->otmpFullName = 0;
1619
1620     assert(left == 0);
1621
1622     if(output != lpOTM) {
1623         memcpy(lpOTM, output, cbData);
1624         HeapFree(GetProcessHeap(), 0, output);
1625
1626         /* check if the string offsets really fit into the provided size */
1627         /* FIXME: should we check string length as well? */
1628         /* make sure that we don't read/write beyond the provided buffer */
1629         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1630         {
1631             if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1632                 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1633         }
1634
1635         /* make sure that we don't read/write beyond the provided buffer */
1636         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1637         {
1638             if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1639                 lpOTM->otmpFaceName = 0; /* doesn't fit */
1640         }
1641
1642             /* make sure that we don't read/write beyond the provided buffer */
1643         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1644         {
1645             if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1646                 lpOTM->otmpStyleName = 0; /* doesn't fit */
1647         }
1648
1649         /* make sure that we don't read/write beyond the provided buffer */
1650         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1651         {
1652             if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1653                 lpOTM->otmpFullName = 0; /* doesn't fit */
1654         }
1655     }
1656
1657 end:
1658     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1659         HeapFree(GetProcessHeap(), 0, lpOTMW);
1660
1661     return ret;
1662 }
1663
1664
1665 /***********************************************************************
1666  *           GetOutlineTextMetricsW [GDI32.@]
1667  */
1668 UINT WINAPI GetOutlineTextMetricsW(
1669     HDC hdc,    /* [in]  Handle of device context */
1670     UINT cbData, /* [in]  Size of metric data array */
1671     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1672 {
1673     DC *dc = DC_GetDCPtr( hdc );
1674     OUTLINETEXTMETRICW *output = lpOTM;
1675     UINT ret;
1676
1677     TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1678     if(!dc) return 0;
1679
1680     if(dc->gdiFont) {
1681         ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1682         if(lpOTM && ret) {
1683             if(ret > cbData) {
1684                 output = HeapAlloc(GetProcessHeap(), 0, ret);
1685                 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1686             }
1687
1688 #define WDPTOLP(x) ((x<0)?                                      \
1689                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1690                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1691 #define HDPTOLP(y) ((y<0)?                                      \
1692                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1693                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1694
1695             output->otmTextMetrics.tmHeight           = HDPTOLP(output->otmTextMetrics.tmHeight);
1696             output->otmTextMetrics.tmAscent           = HDPTOLP(output->otmTextMetrics.tmAscent);
1697             output->otmTextMetrics.tmDescent          = HDPTOLP(output->otmTextMetrics.tmDescent);
1698             output->otmTextMetrics.tmInternalLeading  = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1699             output->otmTextMetrics.tmExternalLeading  = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1700             output->otmTextMetrics.tmAveCharWidth     = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1701             output->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1702             output->otmTextMetrics.tmOverhang         = WDPTOLP(output->otmTextMetrics.tmOverhang);
1703             output->otmAscent = HDPTOLP(output->otmAscent);
1704             output->otmDescent = HDPTOLP(output->otmDescent);
1705             output->otmLineGap = HDPTOLP(output->otmLineGap);
1706             output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1707             output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1708             output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1709             output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1710             output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1711             output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1712             output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1713             output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1714             output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1715             output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1716             output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1717             output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1718             output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1719             output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1720             output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1721             output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1722             output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1723             output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1724             output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1725             output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1726             output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1727 #undef WDPTOLP
1728 #undef HDPTOLP
1729             if(output != lpOTM) {
1730                 memcpy(lpOTM, output, cbData);
1731                 HeapFree(GetProcessHeap(), 0, output);
1732                 ret = cbData;
1733             }
1734         }
1735     }
1736
1737     else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1738               but really this should just be a return 0. */
1739
1740         ret = sizeof(*lpOTM);
1741         if (lpOTM) {
1742             if(cbData < ret)
1743                 ret = 0;
1744             else {
1745                 memset(lpOTM, 0, ret);
1746                 lpOTM->otmSize = sizeof(*lpOTM);
1747                 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1748                 /*
1749                   Further fill of the structure not implemented,
1750                   Needs real values for the structure members
1751                 */
1752             }
1753         }
1754     }
1755     DC_ReleaseDCPtr(dc);
1756     return ret;
1757 }
1758
1759
1760 /***********************************************************************
1761  *           GetCharWidthW      (GDI32.@)
1762  *           GetCharWidth32W    (GDI32.@)
1763  */
1764 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1765                                LPINT buffer )
1766 {
1767     UINT i;
1768     BOOL ret = FALSE;
1769     DC * dc = DC_GetDCPtr( hdc );
1770     if (!dc) return FALSE;
1771
1772     if (dc->gdiFont)
1773         ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1774     else if (dc->funcs->pGetCharWidth)
1775         ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1776
1777     if (ret)
1778     {
1779         /* convert device units to logical */
1780         for( i = firstChar; i <= lastChar; i++, buffer++ )
1781             *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1782         ret = TRUE;
1783     }
1784     DC_ReleaseDCPtr( dc );
1785     return ret;
1786 }
1787
1788
1789 /***********************************************************************
1790  *           GetCharWidthA      (GDI32.@)
1791  *           GetCharWidth32A    (GDI32.@)
1792  */
1793 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1794                                LPINT buffer )
1795 {
1796     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1797     LPSTR str;
1798     LPWSTR wstr;
1799     BOOL ret = TRUE;
1800
1801     if(count <= 0) return FALSE;
1802
1803     str = HeapAlloc(GetProcessHeap(), 0, count);
1804     for(i = 0; i < count; i++)
1805         str[i] = (BYTE)(firstChar + i);
1806
1807     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1808
1809     for(i = 0; i < wlen; i++)
1810     {
1811         if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1812         {
1813             ret = FALSE;
1814             break;
1815         }
1816         buffer++;
1817     }
1818
1819     HeapFree(GetProcessHeap(), 0, str);
1820     HeapFree(GetProcessHeap(), 0, wstr);
1821
1822     return ret;
1823 }
1824
1825
1826 /***********************************************************************
1827  *           ExtTextOutA    (GDI32.@)
1828  *
1829  * See ExtTextOutW.
1830  */
1831 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1832                          const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1833 {
1834     INT wlen;
1835     UINT codepage;
1836     LPWSTR p;
1837     BOOL ret;
1838     LPINT lpDxW = NULL;
1839
1840     if (flags & ETO_GLYPH_INDEX)
1841         return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1842
1843     p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1844
1845     if (lpDx) {
1846         unsigned int i = 0, j = 0;
1847
1848         lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1849         while(i < count) {
1850             if(IsDBCSLeadByteEx(codepage, str[i])) {
1851                 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1852                 i = i + 2;
1853             } else {
1854                 lpDxW[j++] = lpDx[i];
1855                 i = i + 1;
1856             }
1857         }
1858     }
1859
1860     ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1861
1862     HeapFree( GetProcessHeap(), 0, p );
1863     HeapFree( GetProcessHeap(), 0, lpDxW );
1864     return ret;
1865 }
1866
1867
1868 /***********************************************************************
1869  *           ExtTextOutW    (GDI32.@)
1870  *
1871  * Draws text using the currently selected font, background color, and text color.
1872  * 
1873  * 
1874  * PARAMS
1875  *    x,y    [I] coordinates of string
1876  *    flags  [I]
1877  *        ETO_GRAYED - undocumented on MSDN
1878  *        ETO_OPAQUE - use background color for fill the rectangle
1879  *        ETO_CLIPPED - clipping text to the rectangle
1880  *        ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1881  *                          than encoded characters. Implies ETO_IGNORELANGUAGE
1882  *        ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1883  *                         Affects BiDi ordering
1884  *        ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1885  *        ETO_PDY - unimplemented
1886  *        ETO_NUMERICSLATIN - unimplemented always assumed -
1887  *                            do not translate numbers into locale representations
1888  *        ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1889  *    lprect [I] dimensions for clipping or/and opaquing
1890  *    str    [I] text string
1891  *    count  [I] number of symbols in string
1892  *    lpDx   [I] optional parameter with distance between drawing characters
1893  *
1894  * RETURNS
1895  *    Success: TRUE
1896  *    Failure: FALSE
1897  */
1898 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1899                          const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1900 {
1901     BOOL ret = FALSE;
1902     LPWSTR reordered_str = (LPWSTR)str;
1903     WORD *glyphs = NULL;
1904     UINT align = GetTextAlign( hdc );
1905     POINT pt;
1906     TEXTMETRICW tm;
1907     LOGFONTW lf;
1908     double cosEsc, sinEsc;
1909     INT *deltas = NULL, char_extra;
1910     SIZE sz;
1911     RECT rc;
1912     BOOL done_extents = FALSE;
1913     INT width = 0, xwidth = 0, ywidth = 0;
1914     DWORD type;
1915     DC * dc = get_dc_ptr( hdc );
1916     INT breakRem;
1917
1918     if (!dc) return FALSE;
1919
1920     breakRem = dc->breakRem;
1921
1922     if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1923         FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1924
1925     if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1926     {
1927         release_dc_ptr( dc );
1928         return ret;
1929     }
1930
1931     update_dc( dc );
1932     type = GetObjectType(hdc);
1933     if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1934     {
1935         ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1936         release_dc_ptr( dc );
1937         return ret;
1938     }
1939
1940     if (!lprect)
1941         flags &= ~ETO_CLIPPED;
1942         
1943     if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1944     {
1945         reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1946
1947         BIDI_Reorder( str, count, GCP_REORDER,
1948                       ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1949                       WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1950                       reordered_str, count, NULL );
1951     
1952         flags |= ETO_IGNORELANGUAGE;
1953     }
1954
1955     TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1956           lprect, debugstr_wn(str, count), count, lpDx);
1957
1958     if(flags & ETO_GLYPH_INDEX)
1959         glyphs = reordered_str;
1960
1961     if(lprect)
1962         TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1963               lprect->bottom);
1964     TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1965
1966     if(align & TA_UPDATECP)
1967     {
1968         GetCurrentPositionEx( hdc, &pt );
1969         x = pt.x;
1970         y = pt.y;
1971     }
1972
1973     GetTextMetricsW(hdc, &tm);
1974     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1975
1976     if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1977         lf.lfEscapement = 0;
1978
1979     if(lf.lfEscapement != 0)
1980     {
1981         cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1982         sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1983     }
1984     else
1985     {
1986         cosEsc = 1;
1987         sinEsc = 0;
1988     }
1989
1990     if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1991     {
1992         if(!lprect)
1993         {
1994             if(flags & ETO_GLYPH_INDEX)
1995                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1996             else
1997                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1998
1999             done_extents = TRUE;
2000             rc.left = x;
2001             rc.top = y;
2002             rc.right = x + sz.cx;
2003             rc.bottom = y + sz.cy;
2004         }
2005         else
2006         {
2007             rc = *lprect;
2008         }
2009
2010         LPtoDP(hdc, (POINT*)&rc, 2);
2011
2012         if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
2013         if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
2014     }
2015
2016     if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
2017         dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2018
2019     if(count == 0)
2020     {
2021         ret = TRUE;
2022         goto done;
2023     }
2024
2025     pt.x = x;
2026     pt.y = y;
2027     LPtoDP(hdc, &pt, 1);
2028     x = pt.x;
2029     y = pt.y;
2030
2031     char_extra = GetTextCharacterExtra(hdc);
2032     if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2033     {
2034         UINT i;
2035         SIZE tmpsz;
2036         deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
2037         for(i = 0; i < count; i++)
2038         {
2039             if(lpDx && (flags & ETO_PDY))
2040                 deltas[i] = lpDx[i*2] + char_extra;
2041             else if(lpDx)
2042                 deltas[i] = lpDx[i] + char_extra;
2043             else
2044             {
2045                 if(flags & ETO_GLYPH_INDEX)
2046                     GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2047                 else
2048                     GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2049
2050                 deltas[i] = tmpsz.cx;
2051             }
2052             
2053             if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2054             {
2055                 deltas[i] = deltas[i] + dc->breakExtra;
2056                 if (breakRem > 0)
2057                 {
2058                     breakRem--;
2059                     deltas[i]++;
2060                 }
2061             }
2062             deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2063             width += deltas[i];
2064         }
2065     }
2066     else
2067     {
2068         if(!done_extents)
2069         {
2070             if(flags & ETO_GLYPH_INDEX)
2071                 GetTextExtentPointI(hdc, glyphs, count, &sz);
2072             else
2073                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2074             done_extents = TRUE;
2075         }
2076         width = INTERNAL_XWSTODS(dc, sz.cx);
2077     }
2078     xwidth = width * cosEsc;
2079     ywidth = width * sinEsc;
2080
2081     tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2082     tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2083     switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2084     {
2085     case TA_LEFT:
2086         if (align & TA_UPDATECP)
2087         {
2088             pt.x = x + xwidth;
2089             pt.y = y - ywidth;
2090             DPtoLP(hdc, &pt, 1);
2091             MoveToEx(hdc, pt.x, pt.y, NULL);
2092         }
2093         break;
2094
2095     case TA_CENTER:
2096         x -= xwidth / 2;
2097         y += ywidth / 2;
2098         break;
2099
2100     case TA_RIGHT:
2101         x -= xwidth;
2102         y += ywidth;
2103         if (align & TA_UPDATECP)
2104         {
2105             pt.x = x;
2106             pt.y = y;
2107             DPtoLP(hdc, &pt, 1);
2108             MoveToEx(hdc, pt.x, pt.y, NULL);
2109         }
2110         break;
2111     }
2112
2113     switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2114     {
2115     case TA_TOP:
2116         y += tm.tmAscent * cosEsc;
2117         x += tm.tmAscent * sinEsc;
2118         break;
2119
2120     case TA_BOTTOM:
2121         y -= tm.tmDescent * cosEsc;
2122         x -= tm.tmDescent * sinEsc;
2123         break;
2124
2125     case TA_BASELINE:
2126         break;
2127     }
2128
2129     if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2130     {
2131         if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2132         {
2133             if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2134                y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2135             {
2136                 RECT rc;
2137                 rc.left = x;
2138                 rc.right = x + width;
2139                 rc.top = y - tm.tmAscent;
2140                 rc.bottom = y + tm.tmDescent;
2141                 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2142             }
2143         }
2144     }
2145
2146     if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2147     {
2148         HFONT orig_font = dc->hFont, cur_font;
2149         UINT glyph;
2150         INT span = 0, *offsets = NULL;
2151         unsigned int i;
2152
2153         glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2154         for(i = 0; i < count; i++)
2155         {
2156             WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2157             if(cur_font != dc->hFont)
2158             {
2159                 if(!offsets)
2160                 {
2161                     unsigned int j;
2162                     offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2163                     offsets[0] = 0;
2164                     if(!deltas)
2165                     {
2166                         SIZE tmpsz;
2167                         for(j = 1; j < count; j++)
2168                         {
2169                             GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2170                             offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2171                         }
2172                     }
2173                     else
2174                     {
2175                         for(j = 1; j < count; j++)
2176                             offsets[j] = offsets[j-1] + deltas[j];
2177                     }
2178                 }
2179                 if(span)
2180                 {
2181                     if (PATH_IsPathOpen(dc->path))
2182                         ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2183                                               (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2184                                               glyphs, span, deltas ? deltas + i - span : NULL);
2185                     else
2186                         dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2187                                            (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2188                                            glyphs, span, deltas ? deltas + i - span : NULL);
2189                     span = 0;
2190                 }
2191                 SelectObject(hdc, cur_font);
2192             }
2193             glyphs[span++] = glyph;
2194
2195             if(i == count - 1)
2196             {
2197                 if (PATH_IsPathOpen(dc->path))
2198                     ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2199                                           y - (offsets ? offsets[count - span] * sinEsc : 0),
2200                                           (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2201                                           glyphs, span, deltas ? deltas + count - span : NULL);
2202                 else
2203                     ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2204                                              y - (offsets ? offsets[count - span] * sinEsc : 0),
2205                                              (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2206                                              glyphs, span, deltas ? deltas + count - span : NULL);
2207                 SelectObject(hdc, orig_font);
2208                 HeapFree(GetProcessHeap(), 0, offsets);
2209            }
2210         }
2211     }
2212     else
2213     {
2214         if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2215         {
2216             glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2217             GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2218             flags |= ETO_GLYPH_INDEX;
2219         }
2220
2221         if (PATH_IsPathOpen(dc->path))
2222             ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2223                                   glyphs ? glyphs : reordered_str, count, deltas);
2224         else
2225             ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2226                                      glyphs ? glyphs : reordered_str, count, deltas);
2227     }
2228
2229 done:
2230     HeapFree(GetProcessHeap(), 0, deltas);
2231     if(glyphs != reordered_str)
2232         HeapFree(GetProcessHeap(), 0, glyphs);
2233     if(reordered_str != str)
2234         HeapFree(GetProcessHeap(), 0, reordered_str);
2235
2236     release_dc_ptr( dc );
2237
2238     if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2239     {
2240         int underlinePos, strikeoutPos;
2241         int underlineWidth, strikeoutWidth;
2242         UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2243         OUTLINETEXTMETRICW* otm = NULL;
2244
2245         if(!size)
2246         {
2247             underlinePos = 0;
2248             underlineWidth = tm.tmAscent / 20 + 1;
2249             strikeoutPos = tm.tmAscent / 2;
2250             strikeoutWidth = underlineWidth;
2251         }
2252         else
2253         {
2254             otm = HeapAlloc(GetProcessHeap(), 0, size);
2255             GetOutlineTextMetricsW(hdc, size, otm);
2256             underlinePos = otm->otmsUnderscorePosition;
2257             underlineWidth = otm->otmsUnderscoreSize;
2258             strikeoutPos = otm->otmsStrikeoutPosition;
2259             strikeoutWidth = otm->otmsStrikeoutSize;
2260             HeapFree(GetProcessHeap(), 0, otm);
2261         }
2262
2263         if (PATH_IsPathOpen(dc->path))
2264         {
2265             POINT pts[5];
2266             HPEN hpen;
2267             HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2268
2269             hbrush = SelectObject(hdc, hbrush);
2270             hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2271
2272             if (lf.lfUnderline)
2273             {
2274                 pts[0].x = x - underlinePos * sinEsc;
2275                 pts[0].y = y - underlinePos * cosEsc;
2276                 pts[1].x = x + xwidth - underlinePos * sinEsc;
2277                 pts[1].y = y - ywidth - underlinePos * cosEsc;
2278                 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2279                 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2280                 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2281                 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2282                 pts[4].x = pts[0].x;
2283                 pts[4].y = pts[0].y;
2284                 DPtoLP(hdc, pts, 5);
2285                 Polygon(hdc, pts, 5);
2286             }
2287
2288             if (lf.lfStrikeOut)
2289             {
2290                 pts[0].x = x - strikeoutPos * sinEsc;
2291                 pts[0].y = y - strikeoutPos * cosEsc;
2292                 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2293                 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2294                 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2295                 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2296                 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2297                 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2298                 pts[4].x = pts[0].x;
2299                 pts[4].y = pts[0].y;
2300                 DPtoLP(hdc, pts, 5);
2301                 Polygon(hdc, pts, 5);
2302             }
2303
2304             SelectObject(hdc, hpen);
2305             hbrush = SelectObject(hdc, hbrush);
2306             DeleteObject(hbrush);
2307         }
2308         else
2309         {
2310             POINT pts[2], oldpt;
2311             HPEN hpen;
2312
2313             if (lf.lfUnderline)
2314             {
2315                 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2316                 hpen = SelectObject(hdc, hpen);
2317                 pts[0].x = x;
2318                 pts[0].y = y;
2319                 pts[1].x = x + xwidth;
2320                 pts[1].y = y - ywidth;
2321                 DPtoLP(hdc, pts, 2);
2322                 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2323                 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2324                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2325                 DeleteObject(SelectObject(hdc, hpen));
2326             }
2327
2328             if (lf.lfStrikeOut)
2329             {
2330                 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2331                 hpen = SelectObject(hdc, hpen);
2332                 pts[0].x = x;
2333                 pts[0].y = y;
2334                 pts[1].x = x + xwidth;
2335                 pts[1].y = y - ywidth;
2336                 DPtoLP(hdc, pts, 2);
2337                 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2338                 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2339                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2340                 DeleteObject(SelectObject(hdc, hpen));
2341             }
2342         }
2343     }
2344
2345     return ret;
2346 }
2347
2348
2349 /***********************************************************************
2350  *           TextOutA    (GDI32.@)
2351  */
2352 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2353 {
2354     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2355 }
2356
2357
2358 /***********************************************************************
2359  *           TextOutW    (GDI32.@)
2360  */
2361 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2362 {
2363     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2364 }
2365
2366
2367 /***********************************************************************
2368  *              PolyTextOutA (GDI32.@)
2369  *
2370  * See PolyTextOutW.
2371  */
2372 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2373 {
2374     for (; cStrings>0; cStrings--, pptxt++)
2375         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2376             return FALSE;
2377     return TRUE;
2378 }
2379
2380
2381
2382 /***********************************************************************
2383  *              PolyTextOutW (GDI32.@)
2384  *
2385  * Draw several Strings
2386  *
2387  * RETURNS
2388  *  TRUE:  Success.
2389  *  FALSE: Failure.
2390  */
2391 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2392 {
2393     for (; cStrings>0; cStrings--, pptxt++)
2394         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2395             return FALSE;
2396     return TRUE;
2397 }
2398
2399
2400 /* FIXME: all following APIs ******************************************/
2401
2402
2403 /***********************************************************************
2404  *           SetMapperFlags    (GDI32.@)
2405  */
2406 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2407 {
2408     DC *dc = DC_GetDCPtr( hDC );
2409     DWORD ret = 0;
2410     if(!dc) return 0;
2411     if(dc->funcs->pSetMapperFlags)
2412     {
2413         ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2414         /* FIXME: ret is just a success flag, we should return a proper value */
2415     }
2416     else
2417         FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2418     DC_ReleaseDCPtr( dc );
2419     return ret;
2420 }
2421
2422 /***********************************************************************
2423  *          GetAspectRatioFilterEx  (GDI.486)
2424  */
2425 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2426 {
2427   FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2428   return FALSE;
2429 }
2430
2431 /***********************************************************************
2432  *          GetAspectRatioFilterEx  (GDI32.@)
2433  */
2434 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2435 {
2436   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2437   return FALSE;
2438 }
2439
2440
2441 /***********************************************************************
2442  *           GetCharABCWidthsA   (GDI32.@)
2443  *
2444  * See GetCharABCWidthsW.
2445  */
2446 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2447                                   LPABC abc )
2448 {
2449     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2450     LPSTR str;
2451     LPWSTR wstr;
2452     BOOL ret = TRUE;
2453
2454     if(count <= 0) return FALSE;
2455
2456     str = HeapAlloc(GetProcessHeap(), 0, count);
2457     for(i = 0; i < count; i++)
2458         str[i] = (BYTE)(firstChar + i);
2459
2460     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2461
2462     for(i = 0; i < wlen; i++)
2463     {
2464         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2465         {
2466             ret = FALSE;
2467             break;
2468         }
2469         abc++;
2470     }
2471
2472     HeapFree(GetProcessHeap(), 0, str);
2473     HeapFree(GetProcessHeap(), 0, wstr);
2474
2475     return ret;
2476 }
2477
2478
2479 /******************************************************************************
2480  * GetCharABCWidthsW [GDI32.@]
2481  *
2482  * Retrieves widths of characters in range.
2483  *
2484  * PARAMS
2485  *    hdc       [I] Handle of device context
2486  *    firstChar [I] First character in range to query
2487  *    lastChar  [I] Last character in range to query
2488  *    abc       [O] Address of character-width structure
2489  *
2490  * NOTES
2491  *    Only works with TrueType fonts
2492  *
2493  * RETURNS
2494  *    Success: TRUE
2495  *    Failure: FALSE
2496  */
2497 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2498                                    LPABC abc )
2499 {
2500     DC *dc = DC_GetDCPtr(hdc);
2501     unsigned int i;
2502     BOOL ret = FALSE;
2503
2504     if (!dc) return FALSE;
2505
2506     if (!abc)
2507     {
2508         DC_ReleaseDCPtr( dc );
2509         return FALSE;
2510     }
2511
2512     if(dc->gdiFont)
2513         ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2514     else
2515         FIXME(": stub\n");
2516
2517     if (ret)
2518     {
2519         /* convert device units to logical */
2520         for( i = firstChar; i <= lastChar; i++, abc++ ) {
2521             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2522             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2523             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2524         }
2525         ret = TRUE;
2526     }
2527
2528     DC_ReleaseDCPtr( dc );
2529     return ret;
2530 }
2531
2532
2533 /******************************************************************************
2534  * GetCharABCWidthsI [GDI32.@]
2535  *
2536  * Retrieves widths of characters in range.
2537  *
2538  * PARAMS
2539  *    hdc       [I] Handle of device context
2540  *    firstChar [I] First glyphs in range to query
2541  *    count     [I] Last glyphs in range to query
2542  *    pgi       [i] Array of glyphs to query
2543  *    abc       [O] Address of character-width structure
2544  *
2545  * NOTES
2546  *    Only works with TrueType fonts
2547  *
2548  * RETURNS
2549  *    Success: TRUE
2550  *    Failure: FALSE
2551  */
2552 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2553                                LPWORD pgi, LPABC abc)
2554 {
2555     DC *dc = DC_GetDCPtr(hdc);
2556     unsigned int i;
2557     BOOL ret = FALSE;
2558
2559     if (!dc) return FALSE;
2560
2561     if (!abc)
2562     {
2563         DC_ReleaseDCPtr( dc );
2564         return FALSE;
2565     }
2566
2567     if(dc->gdiFont)
2568         ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2569     else
2570         FIXME(": stub\n");
2571
2572     if (ret)
2573     {
2574         /* convert device units to logical */
2575         for( i = 0; i < count; i++, abc++ ) {
2576             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2577             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2578             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2579         }
2580         ret = TRUE;
2581     }
2582
2583     DC_ReleaseDCPtr( dc );
2584     return ret;
2585 }
2586
2587
2588 /***********************************************************************
2589  *           GetGlyphOutlineA    (GDI32.@)
2590  */
2591 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2592                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2593                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2594 {
2595     LPWSTR p = NULL;
2596     DWORD ret;
2597     UINT c;
2598
2599     if(!(fuFormat & GGO_GLYPH_INDEX)) {
2600         int len;
2601         char mbchs[2];
2602         if(uChar > 0xff) { /* but, 2 bytes character only */
2603             len = 2;
2604             mbchs[0] = (uChar & 0xff00) >> 8;
2605             mbchs[1] = (uChar & 0xff);
2606         } else {
2607             len = 1;
2608             mbchs[0] = (uChar & 0xff);
2609         }
2610         p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2611         c = p[0];
2612     } else
2613         c = uChar;
2614     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2615                            lpmat2);
2616     HeapFree(GetProcessHeap(), 0, p);
2617     return ret;
2618 }
2619
2620 /***********************************************************************
2621  *           GetGlyphOutlineW    (GDI32.@)
2622  */
2623 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2624                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2625                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2626 {
2627     DC *dc = DC_GetDCPtr(hdc);
2628     DWORD ret;
2629
2630     TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2631           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2632
2633     if(!dc) return GDI_ERROR;
2634
2635     if(dc->gdiFont)
2636       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2637                                    cbBuffer, lpBuffer, lpmat2);
2638     else
2639       ret = GDI_ERROR;
2640
2641     DC_ReleaseDCPtr( dc );
2642     return ret;
2643 }
2644
2645
2646 /***********************************************************************
2647  *           CreateScalableFontResourceA   (GDI32.@)
2648  */
2649 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2650                                              LPCSTR lpszResourceFile,
2651                                              LPCSTR lpszFontFile,
2652                                              LPCSTR lpszCurrentPath )
2653 {
2654     HANDLE f;
2655
2656     /* fHidden=1 - only visible for the calling app, read-only, not
2657      * enumbered with EnumFonts/EnumFontFamilies
2658      * lpszCurrentPath can be NULL
2659      */
2660     FIXME("(%d,%s,%s,%s): stub\n",
2661           fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2662           debugstr_a(lpszCurrentPath) );
2663
2664     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2665     if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2666         CloseHandle(f);
2667         SetLastError(ERROR_FILE_EXISTS);
2668         return FALSE;
2669     }
2670     return FALSE; /* create failed */
2671 }
2672
2673 /***********************************************************************
2674  *           CreateScalableFontResourceW   (GDI32.@)
2675  */
2676 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2677                                              LPCWSTR lpszResourceFile,
2678                                              LPCWSTR lpszFontFile,
2679                                              LPCWSTR lpszCurrentPath )
2680 {
2681     FIXME("(%d,%p,%p,%p): stub\n",
2682           fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2683     return FALSE; /* create failed */
2684 }
2685
2686 /*************************************************************************
2687  *             GetKerningPairsA   (GDI32.@)
2688  */
2689 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2690                                LPKERNINGPAIR kern_pairA )
2691 {
2692     INT charset;
2693     CHARSETINFO csi;
2694     CPINFO cpi;
2695     DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2696     KERNINGPAIR *kern_pairW;
2697
2698     if (!cPairs && kern_pairA)
2699     {
2700         SetLastError(ERROR_INVALID_PARAMETER);
2701         return 0;
2702     }
2703
2704     charset = GetTextCharset(hDC);
2705     if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2706     {
2707         FIXME("Can't find codepage for charset %d\n", charset);
2708         return 0;
2709     }
2710     /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2711      * to fail on an invalid character for CP_SYMBOL.
2712      */
2713     cpi.DefaultChar[0] = 0;
2714     if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2715     {
2716         FIXME("Can't find codepage %u info\n", csi.ciACP);
2717         return 0;
2718     }
2719     TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2720
2721     total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2722     if (!total_kern_pairs) return 0;
2723
2724     kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2725     GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2726
2727     for (i = 0; i < total_kern_pairs; i++)
2728     {
2729         char first, second;
2730
2731         if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2732             continue;
2733
2734         if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2735             continue;
2736
2737         if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2738             continue;
2739
2740         if (kern_pairA)
2741         {
2742             if (kern_pairs_copied >= cPairs) break;
2743
2744             kern_pairA->wFirst = (BYTE)first;
2745             kern_pairA->wSecond = (BYTE)second;
2746             kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2747             kern_pairA++;
2748         }
2749         kern_pairs_copied++;
2750     }
2751
2752     HeapFree(GetProcessHeap(), 0, kern_pairW);
2753
2754     return kern_pairs_copied;
2755 }
2756
2757 /*************************************************************************
2758  *             GetKerningPairsW   (GDI32.@)
2759  */
2760 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2761                                  LPKERNINGPAIR lpKerningPairs )
2762 {
2763     DC *dc;
2764     DWORD ret = 0;
2765
2766     TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2767
2768     if (!cPairs && lpKerningPairs)
2769     {
2770         SetLastError(ERROR_INVALID_PARAMETER);
2771         return 0;
2772     }
2773
2774     dc = DC_GetDCPtr(hDC);
2775     if (!dc) return 0;
2776
2777     if (dc->gdiFont)
2778         ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2779
2780     DC_ReleaseDCPtr( dc );
2781     return ret;
2782 }
2783
2784 /*************************************************************************
2785  * TranslateCharsetInfo [GDI32.@]
2786  *
2787  * Fills a CHARSETINFO structure for a character set, code page, or
2788  * font. This allows making the correspondence between different labels
2789  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2790  * of the same encoding.
2791  *
2792  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2793  * only one codepage should be set in *lpSrc.
2794  *
2795  * RETURNS
2796  *   TRUE on success, FALSE on failure.
2797  *
2798  */
2799 BOOL WINAPI TranslateCharsetInfo(
2800   LPDWORD lpSrc, /* [in]
2801        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2802        if flags == TCI_SRCCHARSET: a character set value
2803        if flags == TCI_SRCCODEPAGE: a code page value
2804                  */
2805   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2806   DWORD flags /* [in] determines interpretation of lpSrc */)
2807 {
2808     int index = 0;
2809     switch (flags) {
2810     case TCI_SRCFONTSIG:
2811         while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2812       break;
2813     case TCI_SRCCODEPAGE:
2814       while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2815       break;
2816     case TCI_SRCCHARSET:
2817       while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2818       break;
2819     default:
2820       return FALSE;
2821     }
2822     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2823     memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2824     return TRUE;
2825 }
2826
2827 /*************************************************************************
2828  *             GetFontLanguageInfo   (GDI32.@)
2829  */
2830 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2831 {
2832         FONTSIGNATURE fontsig;
2833         static const DWORD GCP_DBCS_MASK=0x003F0000,
2834                 GCP_DIACRITIC_MASK=0x00000000,
2835                 FLI_GLYPHS_MASK=0x00000000,
2836                 GCP_GLYPHSHAPE_MASK=0x00000040,
2837                 GCP_KASHIDA_MASK=0x00000000,
2838                 GCP_LIGATE_MASK=0x00000000,
2839                 GCP_USEKERNING_MASK=0x00000000,
2840                 GCP_REORDER_MASK=0x00000060;
2841
2842         DWORD result=0;
2843
2844         GetTextCharsetInfo( hdc, &fontsig, 0 );
2845         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2846
2847         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2848                 result|=GCP_DBCS;
2849
2850         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2851                 result|=GCP_DIACRITIC;
2852
2853         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2854                 result|=FLI_GLYPHS;
2855
2856         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2857                 result|=GCP_GLYPHSHAPE;
2858
2859         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2860                 result|=GCP_KASHIDA;
2861
2862         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2863                 result|=GCP_LIGATE;
2864
2865         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2866                 result|=GCP_USEKERNING;
2867
2868         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2869         if( GetTextAlign( hdc) & TA_RTLREADING )
2870             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2871                     result|=GCP_REORDER;
2872
2873         return result;
2874 }
2875
2876
2877 /*************************************************************************
2878  * GetFontData [GDI32.@]
2879  *
2880  * Retrieve data for TrueType font.
2881  *
2882  * RETURNS
2883  *
2884  * success: Number of bytes returned
2885  * failure: GDI_ERROR
2886  *
2887  * NOTES
2888  *
2889  * Calls SetLastError()
2890  *
2891  */
2892 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2893     LPVOID buffer, DWORD length)
2894 {
2895     DC *dc = DC_GetDCPtr(hdc);
2896     DWORD ret = GDI_ERROR;
2897
2898     if(!dc) return GDI_ERROR;
2899
2900     if(dc->gdiFont)
2901       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2902
2903     DC_ReleaseDCPtr( dc );
2904     return ret;
2905 }
2906
2907 /*************************************************************************
2908  * GetGlyphIndicesA [GDI32.@]
2909  */
2910 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2911                               LPWORD pgi, DWORD flags)
2912 {
2913     DWORD ret;
2914     WCHAR *lpstrW;
2915     INT countW;
2916
2917     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2918           hdc, debugstr_an(lpstr, count), count, pgi, flags);
2919
2920     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2921     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2922     HeapFree(GetProcessHeap(), 0, lpstrW);
2923
2924     return ret;
2925 }
2926
2927 /*************************************************************************
2928  * GetGlyphIndicesW [GDI32.@]
2929  */
2930 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2931                               LPWORD pgi, DWORD flags)
2932 {
2933     DC *dc = DC_GetDCPtr(hdc);
2934     DWORD ret = GDI_ERROR;
2935
2936     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2937           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2938
2939     if(!dc) return GDI_ERROR;
2940
2941     if(dc->gdiFont)
2942         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2943
2944     DC_ReleaseDCPtr( dc );
2945     return ret;
2946 }
2947
2948 /*************************************************************************
2949  * GetCharacterPlacementA [GDI32.@]
2950  *
2951  * See GetCharacterPlacementW.
2952  *
2953  * NOTES:
2954  *  the web browser control of ie4 calls this with dwFlags=0
2955  */
2956 DWORD WINAPI
2957 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2958                          INT nMaxExtent, GCP_RESULTSA *lpResults,
2959                          DWORD dwFlags)
2960 {
2961     WCHAR *lpStringW;
2962     INT uCountW;
2963     GCP_RESULTSW resultsW;
2964     DWORD ret;
2965     UINT font_cp;
2966
2967     TRACE("%s, %d, %d, 0x%08x\n",
2968           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2969
2970     /* both structs are equal in size */
2971     memcpy(&resultsW, lpResults, sizeof(resultsW));
2972
2973     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2974     if(lpResults->lpOutString)
2975         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2976
2977     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2978
2979     lpResults->nGlyphs = resultsW.nGlyphs;
2980     lpResults->nMaxFit = resultsW.nMaxFit;
2981
2982     if(lpResults->lpOutString) {
2983         WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2984                             lpResults->lpOutString, uCount, NULL, NULL );
2985     }
2986
2987     HeapFree(GetProcessHeap(), 0, lpStringW);
2988     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2989
2990     return ret;
2991 }
2992
2993 /*************************************************************************
2994  * GetCharacterPlacementW [GDI32.@]
2995  *
2996  *   Retrieve information about a string. This includes the width, reordering,
2997  *   Glyphing and so on.
2998  *
2999  * RETURNS
3000  *
3001  *   The width and height of the string if successful, 0 if failed.
3002  *
3003  * BUGS
3004  *
3005  *   All flags except GCP_REORDER are not yet implemented.
3006  *   Reordering is not 100% complient to the Windows BiDi method.
3007  *   Caret positioning is not yet implemented for BiDi.
3008  *   Classes are not yet implemented.
3009  *
3010  */
3011 DWORD WINAPI
3012 GetCharacterPlacementW(
3013                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
3014                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
3015                 INT uCount,             /* [in] Number of WORDS in string. */
3016                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
3017                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3018                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
3019                 )
3020 {
3021     DWORD ret=0;
3022     SIZE size;
3023     UINT i, nSet;
3024
3025     TRACE("%s, %d, %d, 0x%08x\n",
3026           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3027
3028     TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3029           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3030             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3031             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3032             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3033
3034     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08x ignored\n", dwFlags);
3035     if(lpResults->lpClass)      FIXME("classes not implemented\n");
3036     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3037         FIXME("Caret positions for complex scripts not implemented\n");
3038
3039         nSet = (UINT)uCount;
3040         if(nSet > lpResults->nGlyphs)
3041                 nSet = lpResults->nGlyphs;
3042
3043         /* return number of initialized fields */
3044         lpResults->nGlyphs = nSet;
3045
3046         if((dwFlags&GCP_REORDER)==0 )
3047         {
3048                 /* Treat the case where no special handling was requested in a fastpath way */
3049                 /* copy will do if the GCP_REORDER flag is not set */
3050                 if(lpResults->lpOutString)
3051                     memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3052
3053                 if(lpResults->lpOrder)
3054                 {
3055                         for(i = 0; i < nSet; i++)
3056                                 lpResults->lpOrder[i] = i;
3057                 }
3058         } else
3059         {
3060             BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3061                           nSet, lpResults->lpOrder );
3062         }
3063
3064         /* FIXME: Will use the placement chars */
3065         if (lpResults->lpDx)
3066         {
3067                 int c;
3068                 for (i = 0; i < nSet; i++)
3069                 {
3070                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3071                                 lpResults->lpDx[i]= c;
3072                 }
3073         }
3074
3075     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3076     {
3077         int pos = 0;
3078        
3079         lpResults->lpCaretPos[0] = 0;
3080         for (i = 1; i < nSet; i++)
3081             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3082                 lpResults->lpCaretPos[i] = (pos += size.cx);
3083     }
3084    
3085     if(lpResults->lpGlyphs)
3086         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3087
3088     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3089       ret = MAKELONG(size.cx, size.cy);
3090
3091     return ret;
3092 }
3093
3094 /*************************************************************************
3095  *      GetCharABCWidthsFloatA [GDI32.@]
3096  *
3097  * See GetCharABCWidthsFloatW.
3098  */
3099 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3100 {
3101     INT i, wlen, count = (INT)(last - first + 1);
3102     LPSTR str;
3103     LPWSTR wstr;
3104     BOOL ret = TRUE;
3105
3106     if (count <= 0) return FALSE;
3107
3108     str = HeapAlloc(GetProcessHeap(), 0, count);
3109
3110     for(i = 0; i < count; i++)
3111         str[i] = (BYTE)(first + i);
3112
3113     wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3114
3115     for (i = 0; i < wlen; i++)
3116     {
3117         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3118         {
3119             ret = FALSE;
3120             break;
3121         }
3122         abcf++;
3123     }
3124
3125     HeapFree( GetProcessHeap(), 0, str );
3126     HeapFree( GetProcessHeap(), 0, wstr );
3127
3128     return ret;
3129 }
3130
3131 /*************************************************************************
3132  *      GetCharABCWidthsFloatW [GDI32.@]
3133  *
3134  * Retrieves widths of a range of characters.
3135  *
3136  * PARAMS
3137  *    hdc   [I] Handle to device context.
3138  *    first [I] First character in range to query.
3139  *    last  [I] Last character in range to query.
3140  *    abcf  [O] Array of LPABCFLOAT structures.
3141  *
3142  * RETURNS
3143  *    Success: TRUE
3144  *    Failure: FALSE
3145  *
3146  * BUGS
3147  *    Only works with TrueType fonts. It also doesn't return real
3148  *    floats but converted integers because it's implemented on
3149  *    top of GetCharABCWidthsW.
3150  */
3151 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3152 {
3153     ABC *abc;
3154     unsigned int i, size = sizeof(ABC) * (last - first + 1);
3155     BOOL ret;
3156
3157     TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3158
3159     abc = HeapAlloc( GetProcessHeap(), 0, size );
3160     if (!abc) return FALSE;
3161
3162     ret = GetCharABCWidthsW( hdc, first, last, abc );
3163     if (ret)
3164     {
3165         for (i = first; i <= last; i++, abc++, abcf++)
3166         {
3167             abcf->abcfA = abc->abcA;
3168             abcf->abcfB = abc->abcB;
3169             abcf->abcfC = abc->abcC;
3170         }
3171     }
3172     HeapFree( GetProcessHeap(), 0, abc );
3173     return ret;
3174 }
3175
3176 /*************************************************************************
3177  *      GetCharWidthFloatA [GDI32.@]
3178  */
3179 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3180                                     UINT iLastChar, PFLOAT pxBuffer)
3181 {
3182     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3183     return 0;
3184 }
3185
3186 /*************************************************************************
3187  *      GetCharWidthFloatW [GDI32.@]
3188  */
3189 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3190                                     UINT iLastChar, PFLOAT pxBuffer)
3191 {
3192     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3193     return 0;
3194 }
3195
3196
3197 /***********************************************************************
3198  *                                                                     *
3199  *           Font Resource API                                         *
3200  *                                                                     *
3201  ***********************************************************************/
3202
3203 /***********************************************************************
3204  *           AddFontResourceA    (GDI32.@)
3205  */
3206 INT WINAPI AddFontResourceA( LPCSTR str )
3207 {
3208     return AddFontResourceExA( str, 0, NULL);
3209 }
3210
3211 /***********************************************************************
3212  *           AddFontResourceW    (GDI32.@)
3213  */
3214 INT WINAPI AddFontResourceW( LPCWSTR str )
3215 {
3216     return AddFontResourceExW(str, 0, NULL);
3217 }
3218
3219
3220 /***********************************************************************
3221  *           AddFontResourceExA    (GDI32.@)
3222  */
3223 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3224 {
3225     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3226     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3227     INT ret;
3228
3229     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3230     ret = AddFontResourceExW(strW, fl, pdv);
3231     HeapFree(GetProcessHeap(), 0, strW);
3232     return ret;
3233 }
3234
3235 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3236 {
3237     HRSRC rsrc = FindResourceW(hModule, name, type);
3238     HGLOBAL hMem = LoadResource(hModule, rsrc);
3239     LPVOID *pMem = LockResource(hMem);
3240     int *num_total = (int *)lParam;
3241     DWORD num_in_res;
3242
3243     TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3244     if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3245     {
3246         ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3247         return FALSE;
3248     }
3249
3250     *num_total += num_in_res;
3251     return TRUE;
3252 }
3253
3254 /***********************************************************************
3255  *           AddFontResourceExW    (GDI32.@)
3256  */
3257 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3258 {
3259     int ret = WineEngAddFontResourceEx(str, fl, pdv);
3260     if (ret == 0)
3261     {
3262         /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3263         HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3264         if (hModule != NULL)
3265         {
3266             int num_resources = 0;
3267             LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8);  /* we don't want to include winuser.h */
3268
3269             TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3270                 wine_dbgstr_w(str));
3271             if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3272                 ret = num_resources;
3273             FreeLibrary(hModule);
3274         }
3275     }
3276     return ret;
3277 }
3278
3279 /***********************************************************************
3280  *           RemoveFontResourceA    (GDI32.@)
3281  */
3282 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3283 {
3284     return RemoveFontResourceExA(str, 0, 0);
3285 }
3286
3287 /***********************************************************************
3288  *           RemoveFontResourceW    (GDI32.@)
3289  */
3290 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3291 {
3292     return RemoveFontResourceExW(str, 0, 0);
3293 }
3294
3295 /***********************************************************************
3296  *           AddFontMemResourceEx    (GDI32.@)
3297  */
3298 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3299 {
3300     return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3301 }
3302
3303 /***********************************************************************
3304  *           RemoveFontMemResourceEx    (GDI32.@)
3305  */
3306 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3307 {
3308     FIXME("(%p) stub\n", fh);
3309     return TRUE;
3310 }
3311
3312 /***********************************************************************
3313  *           RemoveFontResourceExA    (GDI32.@)
3314  */
3315 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3316 {
3317     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3318     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3319     INT ret;
3320
3321     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3322     ret = RemoveFontResourceExW(strW, fl, pdv);
3323     HeapFree(GetProcessHeap(), 0, strW);
3324     return ret;
3325 }
3326
3327 /***********************************************************************
3328  *           RemoveFontResourceExW    (GDI32.@)
3329  */
3330 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3331 {
3332     return WineEngRemoveFontResourceEx(str, fl, pdv);
3333 }
3334
3335 /***********************************************************************
3336  *           GetTextCharset    (GDI32.@)
3337  */
3338 UINT WINAPI GetTextCharset(HDC hdc)
3339 {
3340     /* MSDN docs say this is equivalent */
3341     return GetTextCharsetInfo(hdc, NULL, 0);
3342 }
3343
3344 /***********************************************************************
3345  *           GetTextCharsetInfo    (GDI32.@)
3346  */
3347 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3348 {
3349     UINT ret = DEFAULT_CHARSET;
3350     DC *dc = DC_GetDCPtr(hdc);
3351
3352     if (dc)
3353     {
3354         if (dc->gdiFont)
3355             ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3356
3357         DC_ReleaseDCPtr( dc );
3358     }
3359
3360     if (ret == DEFAULT_CHARSET && fs)
3361         memset(fs, 0, sizeof(FONTSIGNATURE));
3362     return ret;
3363 }
3364
3365 /***********************************************************************
3366  *           GdiGetCharDimensions    (GDI32.@)
3367  *
3368  * Gets the average width of the characters in the English alphabet.
3369  *
3370  * PARAMS
3371  *  hdc    [I] Handle to the device context to measure on.
3372  *  lptm   [O] Pointer to memory to store the text metrics into.
3373  *  height [O] On exit, the maximum height of characters in the English alphabet.
3374  *
3375  * RETURNS
3376  *  The average width of characters in the English alphabet.
3377  *
3378  * NOTES
3379  *  This function is used by the dialog manager to get the size of a dialog
3380  *  unit. It should also be used by other pieces of code that need to know
3381  *  the size of a dialog unit in logical units without having access to the
3382  *  window handle of the dialog.
3383  *  Windows caches the font metrics from this function, but we don't and
3384  *  there doesn't appear to be an immediate advantage to do so.
3385  *
3386  * SEE ALSO
3387  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3388  */
3389 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3390 {
3391     SIZE sz;
3392     static const WCHAR alphabet[] = {
3393         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3394         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3395         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3396
3397     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3398
3399     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3400
3401     if (height) *height = sz.cy;
3402     return (sz.cx / 26 + 1) / 2;
3403 }
3404
3405 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3406 {
3407     FIXME("(%d): stub\n", fEnableEUDC);
3408     return FALSE;
3409 }
3410
3411 /***********************************************************************
3412  *           GetCharWidthI    (GDI32.@)
3413  *
3414  * Retrieve widths of characters.
3415  *
3416  * PARAMS
3417  *  hdc    [I] Handle to a device context.
3418  *  first  [I] First glyph in range to query.
3419  *  count  [I] Number of glyph indices to query.
3420  *  glyphs [I] Array of glyphs to query.
3421  *  buffer [O] Buffer to receive character widths.
3422  *
3423  * NOTES
3424  *  Only works with TrueType fonts.
3425  *
3426  * RETURNS
3427  *  Success: TRUE
3428  *  Failure: FALSE
3429  */
3430 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3431 {
3432     ABC *abc;
3433     unsigned int i;
3434
3435     TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3436
3437     if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3438         return FALSE;
3439
3440     if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3441     {
3442         HeapFree(GetProcessHeap(), 0, abc);
3443         return FALSE;
3444     }
3445
3446     for (i = 0; i < count; i++)
3447         buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3448
3449     HeapFree(GetProcessHeap(), 0, abc);
3450     return TRUE;
3451 }
3452
3453 /***********************************************************************
3454  *           GetFontUnicodeRanges    (GDI32.@)
3455  *
3456  *  Retrieve a list of supported Unicode characters in a font.
3457  *
3458  *  PARAMS
3459  *   hdc  [I] Handle to a device context.
3460  *   lpgs [O] GLYPHSET structure specifying supported character ranges.
3461  *
3462  *  RETURNS
3463  *   Success: Number of bytes written to the buffer pointed to by lpgs.
3464  *   Failure: 0
3465  *
3466  */
3467 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3468 {
3469     DWORD ret = 0;
3470     DC *dc = DC_GetDCPtr(hdc);
3471
3472     TRACE("(%p, %p)\n", hdc, lpgs);
3473
3474     if (!dc) return 0;
3475
3476     if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3477     DC_ReleaseDCPtr(dc);
3478     return ret;
3479 }
3480
3481
3482 /*************************************************************
3483  *           FontIsLinked    (GDI32.@)
3484  */
3485 BOOL WINAPI FontIsLinked(HDC hdc)
3486 {
3487     DC *dc = DC_GetDCPtr(hdc);
3488     BOOL ret = FALSE;
3489
3490     if (!dc) return FALSE;
3491     if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3492     DC_ReleaseDCPtr(dc);
3493     TRACE("returning %d\n", ret);
3494     return ret;
3495 }