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