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