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