Add idl files required for scripting.
[wine] / objects / 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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.h"
36 #include "gdi_private.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 WINE_DECLARE_DEBUG_CHANNEL(gdi);
42
43   /* Device -> World size conversion */
44
45 /* Performs a device to world transformation on the specified width (which
46  * is in integer format).
47  */
48 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
49 {
50     FLOAT floatWidth;
51
52     /* Perform operation with floating point */
53     floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
54     /* Round to integers */
55     return GDI_ROUND(floatWidth);
56 }
57
58 /* Performs a device to world transformation on the specified size (which
59  * is in integer format).
60  */
61 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
62 {
63     FLOAT floatHeight;
64
65     /* Perform operation with floating point */
66     floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
67     /* Round to integers */
68     return GDI_ROUND(floatHeight);
69 }
70
71
72 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
73 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
74 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
75 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
76 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
77
78 static const struct gdi_obj_funcs font_funcs =
79 {
80     FONT_SelectObject,  /* pSelectObject */
81     FONT_GetObject16,   /* pGetObject16 */
82     FONT_GetObjectA,    /* pGetObjectA */
83     FONT_GetObjectW,    /* pGetObjectW */
84     NULL,               /* pUnrealizeObject */
85     FONT_DeleteObject   /* pDeleteObject */
86 };
87
88 #define ENUM_UNICODE    0x00000001
89 #define ENUM_CALLED     0x00000002
90
91 typedef struct
92 {
93     GDIOBJHDR   header;
94     LOGFONTW    logfont;
95 } FONTOBJ;
96
97 typedef struct
98 {
99   LPLOGFONT16           lpLogFontParam;
100   FONTENUMPROC16        lpEnumFunc;
101   LPARAM                lpData;
102
103   LPNEWTEXTMETRICEX16   lpTextMetric;
104   LPENUMLOGFONTEX16     lpLogFont;
105   SEGPTR                segTextMetric;
106   SEGPTR                segLogFont;
107   DWORD                 dwFlags;
108   HDC                   hdc;
109   DC                   *dc;
110   PHYSDEV               physDev;
111 } fontEnum16;
112
113 typedef struct
114 {
115   LPLOGFONTW          lpLogFontParam;
116   FONTENUMPROCW       lpEnumFunc;
117   LPARAM              lpData;
118   DWORD               dwFlags;
119   HDC                 hdc;
120   DC                 *dc;
121   PHYSDEV             physDev;
122 } fontEnum32;
123
124 /*
125  *  For TranslateCharsetInfo
126  */
127 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
128 #define MAXTCIINDEX 32
129 static CHARSETINFO FONT_tci[MAXTCIINDEX] = {
130   /* ANSI */
131   { ANSI_CHARSET, 1252, FS(0)},
132   { EASTEUROPE_CHARSET, 1250, FS(1)},
133   { RUSSIAN_CHARSET, 1251, FS(2)},
134   { GREEK_CHARSET, 1253, FS(3)},
135   { TURKISH_CHARSET, 1254, FS(4)},
136   { HEBREW_CHARSET, 1255, FS(5)},
137   { ARABIC_CHARSET, 1256, FS(6)},
138   { BALTIC_CHARSET, 1257, FS(7)},
139   { VIETNAMESE_CHARSET, 1258, FS(8)},
140   /* reserved by ANSI */
141   { DEFAULT_CHARSET, 0, FS(0)},
142   { DEFAULT_CHARSET, 0, FS(0)},
143   { DEFAULT_CHARSET, 0, FS(0)},
144   { DEFAULT_CHARSET, 0, FS(0)},
145   { DEFAULT_CHARSET, 0, FS(0)},
146   { DEFAULT_CHARSET, 0, FS(0)},
147   { DEFAULT_CHARSET, 0, FS(0)},
148   /* ANSI and OEM */
149   { THAI_CHARSET,  874,  FS(16)},
150   { SHIFTJIS_CHARSET, 932, FS(17)},
151   { GB2312_CHARSET, 936, FS(18)},
152   { HANGEUL_CHARSET, 949, FS(19)},
153   { CHINESEBIG5_CHARSET, 950, FS(20)},
154   { JOHAB_CHARSET, 1361, FS(21)},
155   /* reserved for alternate ANSI and OEM */
156   { DEFAULT_CHARSET, 0, FS(0)},
157   { DEFAULT_CHARSET, 0, FS(0)},
158   { DEFAULT_CHARSET, 0, FS(0)},
159   { DEFAULT_CHARSET, 0, FS(0)},
160   { DEFAULT_CHARSET, 0, FS(0)},
161   { DEFAULT_CHARSET, 0, FS(0)},
162   { DEFAULT_CHARSET, 0, FS(0)},
163   { DEFAULT_CHARSET, 0, FS(0)},
164   /* reserved for system */
165   { DEFAULT_CHARSET, 0, FS(0)},
166   { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
167 };
168
169 /***********************************************************************
170  *              LOGFONT conversion functions.
171  */
172 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
173 {
174     font16->lfHeight = font32->lfHeight;
175     font16->lfWidth = font32->lfWidth;
176     font16->lfEscapement = font32->lfEscapement;
177     font16->lfOrientation = font32->lfOrientation;
178     font16->lfWeight = font32->lfWeight;
179     font16->lfItalic = font32->lfItalic;
180     font16->lfUnderline = font32->lfUnderline;
181     font16->lfStrikeOut = font32->lfStrikeOut;
182     font16->lfCharSet = font32->lfCharSet;
183     font16->lfOutPrecision = font32->lfOutPrecision;
184     font16->lfClipPrecision = font32->lfClipPrecision;
185     font16->lfQuality = font32->lfQuality;
186     font16->lfPitchAndFamily = font32->lfPitchAndFamily;
187     WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
188                          font16->lfFaceName, LF_FACESIZE, NULL, NULL );
189     font16->lfFaceName[LF_FACESIZE-1] = 0;
190 }
191
192 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
193 {
194     font32->lfHeight = font16->lfHeight;
195     font32->lfWidth = font16->lfWidth;
196     font32->lfEscapement = font16->lfEscapement;
197     font32->lfOrientation = font16->lfOrientation;
198     font32->lfWeight = font16->lfWeight;
199     font32->lfItalic = font16->lfItalic;
200     font32->lfUnderline = font16->lfUnderline;
201     font32->lfStrikeOut = font16->lfStrikeOut;
202     font32->lfCharSet = font16->lfCharSet;
203     font32->lfOutPrecision = font16->lfOutPrecision;
204     font32->lfClipPrecision = font16->lfClipPrecision;
205     font32->lfQuality = font16->lfQuality;
206     font32->lfPitchAndFamily = font16->lfPitchAndFamily;
207     MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
208     font32->lfFaceName[LF_FACESIZE-1] = 0;
209 }
210
211 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
212 {
213     memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
214     MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
215                         LF_FACESIZE);
216 }
217
218 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
219 {
220     memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
221     WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
222                         LF_FACESIZE, NULL, NULL);
223 }
224
225 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
226 {
227     FONT_LogFontWTo16( (LPLOGFONTW)fontW, (LPLOGFONT16)font16);
228
229     WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
230                          font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
231     font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
232     WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
233                          font16->elfStyle, LF_FACESIZE, NULL, NULL );
234     font16->elfStyle[LF_FACESIZE-1] = '\0';
235     WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
236                          font16->elfScript, LF_FACESIZE, NULL, NULL );
237     font16->elfScript[LF_FACESIZE-1] = '\0';
238 }
239
240 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
241 {
242     FONT_LogFontWToA( (LPLOGFONTW)fontW, (LPLOGFONTA)fontA);
243
244     WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
245                          fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
246     fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
247     WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
248                          fontA->elfStyle, LF_FACESIZE, NULL, NULL );
249     fontA->elfStyle[LF_FACESIZE-1] = '\0';
250     WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
251                          fontA->elfScript, LF_FACESIZE, NULL, NULL );
252     fontA->elfScript[LF_FACESIZE-1] = '\0';
253 }
254
255 /***********************************************************************
256  *              TEXTMETRIC conversion functions.
257  */
258 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
259 {
260     ptmA->tmHeight = ptmW->tmHeight;
261     ptmA->tmAscent = ptmW->tmAscent;
262     ptmA->tmDescent = ptmW->tmDescent;
263     ptmA->tmInternalLeading = ptmW->tmInternalLeading;
264     ptmA->tmExternalLeading = ptmW->tmExternalLeading;
265     ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
266     ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
267     ptmA->tmWeight = ptmW->tmWeight;
268     ptmA->tmOverhang = ptmW->tmOverhang;
269     ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
270     ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
271     ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
272     ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
273     ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
274     ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
275     ptmA->tmItalic = ptmW->tmItalic;
276     ptmA->tmUnderlined = ptmW->tmUnderlined;
277     ptmA->tmStruckOut = ptmW->tmStruckOut;
278     ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
279     ptmA->tmCharSet = ptmW->tmCharSet;
280 }
281
282
283 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
284 {
285     ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
286     ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
287     ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
288     ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
289     ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
290     ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
291     ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
292     ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
293     ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
294     ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
295     ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
296     ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
297     ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
298     ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
299     ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
300     ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
301     ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
302     ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
303     ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
304     ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
305     ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
306     ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
307     ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
308     ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
309     memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
310 }
311
312 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
313 {
314     FONT_TextMetricWToA((LPTEXTMETRICW)ptmW, (LPTEXTMETRICA)ptmA);
315     ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
316     ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
317     ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
318     ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
319     memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
320 }
321
322 /***********************************************************************
323  *           CreateFontIndirectA   (GDI32.@)
324  */
325 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
326 {
327     LOGFONTW lfW;
328
329     if (plfA) {
330         FONT_LogFontAToW( plfA, &lfW );
331         return CreateFontIndirectW( &lfW );
332      } else
333         return CreateFontIndirectW( NULL );
334
335 }
336
337 /***********************************************************************
338  *           CreateFontIndirectW   (GDI32.@)
339  */
340 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
341 {
342     HFONT hFont = 0;
343
344     if (plf)
345     {
346         FONTOBJ* fontPtr;
347         if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
348                                         (HGDIOBJ *)&hFont, &font_funcs )))
349         {
350             static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
351             static const WCHAR BoldW[]   = {' ','B','o','l','d','\0'};
352             WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
353             WCHAR* pFaceNameSuffix = NULL;
354
355             memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
356
357             TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s %s => %p\n",
358                   plf->lfHeight, plf->lfWidth,
359                   plf->lfEscapement, plf->lfOrientation,
360                   plf->lfPitchAndFamily,
361                   plf->lfOutPrecision, plf->lfClipPrecision,
362                   plf->lfQuality, plf->lfCharSet,
363                   debugstr_w(plf->lfFaceName),
364                   plf->lfWeight > 400 ? "Bold" : "",
365                   plf->lfItalic ? "Italic" : "",
366                   plf->lfUnderline ? "Underline" : "", hFont);
367
368             if (plf->lfEscapement != plf->lfOrientation) {
369               /* this should really depend on whether GM_ADVANCED is set */
370               fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
371               WARN("orientation angle %f set to "
372                    "escapement angle %f for new font %p\n",
373                    plf->lfOrientation/10., plf->lfEscapement/10., hFont);
374             }
375
376             pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
377             if (pFaceNameItalicSuffix) {
378                 fontPtr->logfont.lfItalic = TRUE;
379                 pFaceNameSuffix = pFaceNameItalicSuffix;
380             }
381
382             pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
383             if (pFaceNameBoldSuffix) {
384                 if (fontPtr->logfont.lfWeight < FW_BOLD) {
385                     fontPtr->logfont.lfWeight = FW_BOLD;
386                 }
387                 if (!pFaceNameSuffix ||
388                     (pFaceNameBoldSuffix < pFaceNameSuffix)) {
389                     pFaceNameSuffix = pFaceNameBoldSuffix;
390                 }
391             }
392
393             if (pFaceNameSuffix) *pFaceNameSuffix = 0;
394
395             GDI_ReleaseObj( hFont );
396         }
397     }
398     else WARN("(NULL) => NULL\n");
399
400     return hFont;
401 }
402
403 /*************************************************************************
404  *           CreateFontA    (GDI32.@)
405  */
406 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
407                               INT orient, INT weight, DWORD italic,
408                               DWORD underline, DWORD strikeout, DWORD charset,
409                               DWORD outpres, DWORD clippres, DWORD quality,
410                               DWORD pitch, LPCSTR name )
411 {
412     LOGFONTA logfont;
413
414     logfont.lfHeight = height;
415     logfont.lfWidth = width;
416     logfont.lfEscapement = esc;
417     logfont.lfOrientation = orient;
418     logfont.lfWeight = weight;
419     logfont.lfItalic = italic;
420     logfont.lfUnderline = underline;
421     logfont.lfStrikeOut = strikeout;
422     logfont.lfCharSet = charset;
423     logfont.lfOutPrecision = outpres;
424     logfont.lfClipPrecision = clippres;
425     logfont.lfQuality = quality;
426     logfont.lfPitchAndFamily = pitch;
427
428     if (name)
429         lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
430     else
431         logfont.lfFaceName[0] = '\0';
432
433     return CreateFontIndirectA( &logfont );
434 }
435
436 /*************************************************************************
437  *           CreateFontW    (GDI32.@)
438  */
439 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
440                               INT orient, INT weight, DWORD italic,
441                               DWORD underline, DWORD strikeout, DWORD charset,
442                               DWORD outpres, DWORD clippres, DWORD quality,
443                               DWORD pitch, LPCWSTR name )
444 {
445     LOGFONTW logfont;
446
447     logfont.lfHeight = height;
448     logfont.lfWidth = width;
449     logfont.lfEscapement = esc;
450     logfont.lfOrientation = orient;
451     logfont.lfWeight = weight;
452     logfont.lfItalic = italic;
453     logfont.lfUnderline = underline;
454     logfont.lfStrikeOut = strikeout;
455     logfont.lfCharSet = charset;
456     logfont.lfOutPrecision = outpres;
457     logfont.lfClipPrecision = clippres;
458     logfont.lfQuality = quality;
459     logfont.lfPitchAndFamily = pitch;
460
461     if (name)
462         lstrcpynW(logfont.lfFaceName, name,
463                   sizeof(logfont.lfFaceName) / sizeof(WCHAR));
464     else
465         logfont.lfFaceName[0] = '\0';
466
467     return CreateFontIndirectW( &logfont );
468 }
469
470
471 /***********************************************************************
472  *           FONT_SelectObject
473  *
474  * If the driver supports vector fonts we create a gdi font first and
475  * then call the driver to give it a chance to supply its own device
476  * font.  If the driver wants to do this it returns TRUE and we can
477  * delete the gdi font, if the driver wants to use the gdi font it
478  * should return FALSE, to signal an error return GDI_ERROR.  For
479  * drivers that don't support vector fonts they must supply their own
480  * font.
481  */
482 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
483 {
484     HGDIOBJ ret = 0;
485     DC *dc = DC_GetDCPtr( hdc );
486
487     if (!dc) return 0;
488
489     if (dc->hFont != handle || dc->gdiFont == NULL)
490     {
491         if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
492             dc->gdiFont = WineEngCreateFontInstance(dc, handle);
493     }
494
495     if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
496
497     if (ret && dc->gdiFont) dc->gdiFont = 0;
498
499     if (ret == HGDI_ERROR)
500         ret = 0; /* SelectObject returns 0 on error */
501     else
502     {
503         ret = dc->hFont;
504         dc->hFont = handle;
505     }
506     GDI_ReleaseObj( hdc );
507     return ret;
508 }
509
510
511 /***********************************************************************
512  *           FONT_GetObject16
513  */
514 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
515 {
516     FONTOBJ *font = obj;
517     LOGFONT16 lf16;
518
519     FONT_LogFontWTo16( &font->logfont, &lf16 );
520
521     if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
522     memcpy( buffer, &lf16, count );
523     return count;
524 }
525
526 /***********************************************************************
527  *           FONT_GetObjectA
528  */
529 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
530 {
531     FONTOBJ *font = obj;
532     LOGFONTA lfA;
533
534     if(!buffer)
535         return sizeof(lfA);
536     FONT_LogFontWToA( &font->logfont, &lfA );
537
538     if (count > sizeof(lfA)) count = sizeof(lfA);
539     memcpy( buffer, &lfA, count );
540     return count;
541 }
542
543 /***********************************************************************
544  *           FONT_GetObjectW
545  */
546 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
547 {
548     FONTOBJ *font = obj;
549     if(!buffer)
550         return sizeof(LOGFONTW);
551     if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
552     memcpy( buffer, &font->logfont, count );
553     return count;
554 }
555
556
557 /***********************************************************************
558  *           FONT_DeleteObject
559  */
560 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
561 {
562     WineEngDestroyFontInstance( handle );
563     return GDI_FreeObject( handle, obj );
564 }
565
566
567 /***********************************************************************
568  *              FONT_EnumInstance16
569  *
570  * Called by the device driver layer to pass font info
571  * down to the application.
572  *
573  * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
574  *       We have to use other types because of the FONTENUMPROCW definition.
575  */
576 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
577                                          DWORD fType, LPARAM lp )
578 {
579     fontEnum16 *pfe = (fontEnum16*)lp;
580     INT ret = 1;
581     DC *dc;
582
583     if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
584         pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
585     {
586         WORD args[7];
587         DWORD result;
588
589         FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
590         FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
591         pfe->dwFlags |= ENUM_CALLED;
592         GDI_ReleaseObj( pfe->hdc );  /* release the GDI lock */
593
594         args[6] = SELECTOROF(pfe->segLogFont);
595         args[5] = OFFSETOF(pfe->segLogFont);
596         args[4] = SELECTOROF(pfe->segTextMetric);
597         args[3] = OFFSETOF(pfe->segTextMetric);
598         args[2] = fType;
599         args[1] = HIWORD(pfe->lpData);
600         args[0] = LOWORD(pfe->lpData);
601         WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
602         ret = LOWORD(result);
603
604         /* get the lock again and make sure the DC is still valid */
605         dc = DC_GetDCPtr( pfe->hdc );
606         if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
607         {
608             if (dc) GDI_ReleaseObj( pfe->hdc );
609             pfe->hdc = 0;  /* make sure we don't try to release it later on */
610             ret = 0;
611         }
612     }
613     return ret;
614 }
615
616 /***********************************************************************
617  *              FONT_EnumInstance
618  *
619  * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
620  *       We have to use other types because of the FONTENUMPROCW definition.
621  */
622 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
623                                        DWORD fType, LPARAM lp )
624 {
625     fontEnum32 *pfe = (fontEnum32*)lp;
626     INT ret = 1;
627     DC *dc;
628
629     /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
630     if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
631         pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
632        (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
633     {
634         /* convert font metrics */
635         ENUMLOGFONTEXA logfont;
636         NEWTEXTMETRICEXA tmA;
637
638         pfe->dwFlags |= ENUM_CALLED;
639         if (!(pfe->dwFlags & ENUM_UNICODE))
640         {
641             FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
642             FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
643             plf = (LOGFONTW *)&logfont.elfLogFont;
644             ptm = (TEXTMETRICW *)&tmA;
645         }
646         GDI_ReleaseObj( pfe->hdc );  /* release the GDI lock */
647
648         ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
649
650         /* get the lock again and make sure the DC is still valid */
651         dc = DC_GetDCPtr( pfe->hdc );
652         if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
653         {
654             if (dc) GDI_ReleaseObj( pfe->hdc );
655             pfe->hdc = 0;  /* make sure we don't try to release it later on */
656             ret = 0;
657         }
658     }
659     return ret;
660 }
661
662 /***********************************************************************
663  *              EnumFontFamiliesEx      (GDI.613)
664  */
665 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
666                                    FONTENUMPROC16 efproc, LPARAM lParam,
667                                    DWORD dwFlags)
668 {
669     fontEnum16 fe16;
670     INT16       ret = 1, ret2;
671     DC*         dc = DC_GetDCPtr( HDC_32(hDC) );
672     NEWTEXTMETRICEX16 tm16;
673     ENUMLOGFONTEX16 lf16;
674     LOGFONTW lfW;
675     BOOL enum_gdi_fonts;
676
677     if (!dc) return 0;
678     FONT_LogFont16ToW(plf, &lfW);
679
680     fe16.hdc = HDC_32(hDC);
681     fe16.dc = dc;
682     fe16.physDev = dc->physDev;
683     fe16.lpLogFontParam = plf;
684     fe16.lpEnumFunc = efproc;
685     fe16.lpData = lParam;
686     fe16.lpTextMetric = &tm16;
687     fe16.lpLogFont = &lf16;
688     fe16.segTextMetric = MapLS( &tm16 );
689     fe16.segLogFont = MapLS( &lf16 );
690     fe16.dwFlags = 0;
691
692     enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
693
694     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
695     {
696         ret = 0;
697         goto done;
698     }
699
700     if (enum_gdi_fonts)
701         ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
702     fe16.dwFlags &= ~ENUM_CALLED;
703     if (ret && dc->funcs->pEnumDeviceFonts) {
704         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
705         if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
706             ret = ret2;
707     }
708 done:
709     UnMapLS( fe16.segTextMetric );
710     UnMapLS( fe16.segLogFont );
711     if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
712     return ret;
713 }
714
715 /***********************************************************************
716  *              FONT_EnumFontFamiliesEx
717  */
718 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
719                                     FONTENUMPROCW efproc,
720                                     LPARAM lParam, DWORD dwUnicode)
721 {
722     INT ret = 1, ret2;
723     DC *dc = DC_GetDCPtr( hDC );
724     fontEnum32 fe32;
725     BOOL enum_gdi_fonts;
726
727     if (!dc) return 0;
728
729     TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
730           plf->lfCharSet);
731     fe32.lpLogFontParam = plf;
732     fe32.lpEnumFunc = efproc;
733     fe32.lpData = lParam;
734     fe32.dwFlags = dwUnicode;
735     fe32.hdc = hDC;
736     fe32.dc = dc;
737     fe32.physDev = dc->physDev;
738
739     enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
740
741     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
742     {
743         ret = 0;
744         goto done;
745     }
746
747     if (enum_gdi_fonts)
748         ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
749     fe32.dwFlags &= ~ENUM_CALLED;
750     if (ret && dc->funcs->pEnumDeviceFonts) {
751         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
752         if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
753             ret = ret2;
754     }
755  done:
756     if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
757     return ret;
758 }
759
760 /***********************************************************************
761  *              EnumFontFamiliesExW     (GDI32.@)
762  */
763 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
764                                     FONTENUMPROCW efproc,
765                                     LPARAM lParam, DWORD dwFlags )
766 {
767     return  FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
768 }
769
770 /***********************************************************************
771  *              EnumFontFamiliesExA     (GDI32.@)
772  */
773 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
774                                     FONTENUMPROCA efproc,
775                                     LPARAM lParam, DWORD dwFlags)
776 {
777     LOGFONTW lfW;
778     FONT_LogFontAToW( plf, &lfW );
779
780     return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
781 }
782
783 /***********************************************************************
784  *              EnumFontFamilies        (GDI.330)
785  */
786 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
787                                  FONTENUMPROC16 efproc, LPARAM lpData )
788 {
789     LOGFONT16   lf;
790
791     lf.lfCharSet = DEFAULT_CHARSET;
792     if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
793     else lf.lfFaceName[0] = '\0';
794
795     return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
796 }
797
798 /***********************************************************************
799  *              EnumFontFamiliesA       (GDI32.@)
800  */
801 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
802                                   FONTENUMPROCA efproc, LPARAM lpData )
803 {
804     LOGFONTA    lf;
805
806     lf.lfCharSet = DEFAULT_CHARSET;
807     if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
808     else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
809
810     return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
811 }
812
813 /***********************************************************************
814  *              EnumFontFamiliesW       (GDI32.@)
815  */
816 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
817                                   FONTENUMPROCW efproc, LPARAM lpData )
818 {
819     LOGFONTW  lf;
820
821     lf.lfCharSet = DEFAULT_CHARSET;
822     if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
823     else lf.lfFaceName[0] = 0;
824
825     return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
826 }
827
828 /***********************************************************************
829  *              EnumFonts               (GDI.70)
830  */
831 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
832                           LPARAM lpData )
833 {
834     return EnumFontFamilies16( hDC, lpName, efproc, lpData );
835 }
836
837 /***********************************************************************
838  *              EnumFontsA              (GDI32.@)
839  */
840 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
841                            LPARAM lpData )
842 {
843     return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
844 }
845
846 /***********************************************************************
847  *              EnumFontsW              (GDI32.@)
848  */
849 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
850                            LPARAM lpData )
851 {
852     return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
853 }
854
855
856 /***********************************************************************
857  *           GetTextCharacterExtra    (GDI32.@)
858  */
859 INT WINAPI GetTextCharacterExtra( HDC hdc )
860 {
861     INT ret;
862     DC *dc = DC_GetDCPtr( hdc );
863     if (!dc) return 0x80000000;
864     ret = dc->charExtra;
865     GDI_ReleaseObj( hdc );
866     return ret;
867 }
868
869
870 /***********************************************************************
871  *           SetTextCharacterExtra    (GDI32.@)
872  */
873 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
874 {
875     INT prev;
876     DC * dc = DC_GetDCPtr( hdc );
877     if (!dc) return 0x80000000;
878     if (dc->funcs->pSetTextCharacterExtra)
879         prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
880     else
881     {
882         prev = dc->charExtra;
883         dc->charExtra = extra;
884     }
885     GDI_ReleaseObj( hdc );
886     return prev;
887 }
888
889
890 /***********************************************************************
891  *           SetTextJustification    (GDI32.@)
892  */
893 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
894 {
895     BOOL ret = TRUE;
896     DC * dc = DC_GetDCPtr( hdc );
897     if (!dc) return FALSE;
898     if (dc->funcs->pSetTextJustification)
899         ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
900     else
901     {
902         extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
903         if (!extra) breaks = 0;
904         if (breaks)
905         {
906             dc->breakExtra = extra / breaks;
907             dc->breakRem   = extra - (breaks * dc->breakExtra);
908         }
909         else
910         {
911             dc->breakExtra = 0;
912             dc->breakRem   = 0;
913         }
914     }
915     GDI_ReleaseObj( hdc );
916     return ret;
917 }
918
919
920 /***********************************************************************
921  *           GetTextFaceA    (GDI32.@)
922  */
923 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
924 {
925     INT res = GetTextFaceW(hdc, 0, NULL);
926     LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
927     GetTextFaceW( hdc, res, nameW );
928
929     if (name)
930     {
931         if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
932             name[count-1] = 0;
933         res = strlen(name);
934     }
935     else
936         res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
937     HeapFree( GetProcessHeap(), 0, nameW );
938     return res;
939 }
940
941 /***********************************************************************
942  *           GetTextFaceW    (GDI32.@)
943  */
944 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
945 {
946     FONTOBJ *font;
947     INT     ret = 0;
948
949     DC * dc = DC_GetDCPtr( hdc );
950     if (!dc) return 0;
951
952     if(dc->gdiFont)
953         ret = WineEngGetTextFace(dc->gdiFont, count, name);
954     else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
955     {
956         if (name)
957         {
958             lstrcpynW( name, font->logfont.lfFaceName, count );
959             ret = strlenW(name);
960         }
961         else ret = strlenW(font->logfont.lfFaceName) + 1;
962         GDI_ReleaseObj( dc->hFont );
963     }
964     GDI_ReleaseObj( hdc );
965     return ret;
966 }
967
968
969 /***********************************************************************
970  *           GetTextExtentPoint32A    (GDI32.@)
971  */
972 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
973                                      LPSIZE size )
974 {
975     BOOL ret = FALSE;
976     INT wlen;
977     LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
978
979     if (p) {
980         ret = GetTextExtentPoint32W( hdc, p, wlen, size );
981         HeapFree( GetProcessHeap(), 0, p );
982     }
983
984     TRACE("(%p %s %d %p): returning %ld x %ld\n",
985           hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
986     return ret;
987 }
988
989
990 /***********************************************************************
991  * GetTextExtentPoint32W [GDI32.@]
992  *
993  * Computes width/height for a string.
994  *
995  * Computes width and height of the specified string.
996  *
997  * RETURNS
998  *    Success: TRUE
999  *    Failure: FALSE
1000  */
1001 BOOL WINAPI GetTextExtentPoint32W(
1002     HDC hdc,     /* [in]  Handle of device context */
1003     LPCWSTR str,   /* [in]  Address of text string */
1004     INT count,   /* [in]  Number of characters in string */
1005     LPSIZE size) /* [out] Address of structure for string size */
1006 {
1007     BOOL ret = FALSE;
1008     DC * dc = DC_GetDCPtr( hdc );
1009     if (!dc) return FALSE;
1010
1011     if(dc->gdiFont)
1012         ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
1013     else if(dc->funcs->pGetTextExtentPoint)
1014         ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
1015
1016     if (ret)
1017     {
1018         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1019         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1020         size->cx += count * dc->charExtra + dc->breakRem;
1021     }
1022
1023     GDI_ReleaseObj( hdc );
1024
1025     TRACE("(%p %s %d %p): returning %ld x %ld\n",
1026           hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
1027     return ret;
1028 }
1029
1030 /***********************************************************************
1031  * GetTextExtentPointI [GDI32.@]
1032  *
1033  * Computes width and height of the array of glyph indices.
1034  *
1035  * RETURNS
1036  *    Success: TRUE
1037  *    Failure: FALSE
1038  */
1039 BOOL WINAPI GetTextExtentPointI(
1040     HDC hdc,     /* [in]  Handle of device context */
1041     const WORD *indices,   /* [in]  Address of glyph index array */
1042     INT count,   /* [in]  Number of glyphs in array */
1043     LPSIZE size) /* [out] Address of structure for string size */
1044 {
1045     BOOL ret = FALSE;
1046     DC * dc = DC_GetDCPtr( hdc );
1047     if (!dc) return FALSE;
1048
1049     if(dc->gdiFont) {
1050         ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1051         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1052         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1053         size->cx += count * dc->charExtra;
1054     }
1055     else if(dc->funcs->pGetTextExtentPoint) {
1056         FIXME("calling GetTextExtentPoint\n");
1057         ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
1058     }
1059
1060     GDI_ReleaseObj( hdc );
1061
1062     TRACE("(%p %p %d %p): returning %ld x %ld\n",
1063           hdc, indices, count, size, size->cx, size->cy );
1064     return ret;
1065 }
1066
1067
1068 /***********************************************************************
1069  *           GetTextExtentPointA    (GDI32.@)
1070  */
1071 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1072                                           LPSIZE size )
1073 {
1074     TRACE("not bug compatible.\n");
1075     return GetTextExtentPoint32A( hdc, str, count, size );
1076 }
1077
1078 /***********************************************************************
1079  *           GetTextExtentPointW   (GDI32.@)
1080  */
1081 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1082                                           LPSIZE size )
1083 {
1084     TRACE("not bug compatible.\n");
1085     return GetTextExtentPoint32W( hdc, str, count, size );
1086 }
1087
1088
1089 /***********************************************************************
1090  *           GetTextExtentExPointA    (GDI32.@)
1091  */
1092 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1093                                    INT maxExt, LPINT lpnFit,
1094                                    LPINT alpDx, LPSIZE size )
1095 {
1096     BOOL ret;
1097     INT wlen;
1098     LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1099     ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1100     if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1101     HeapFree( GetProcessHeap(), 0, p );
1102     return ret;
1103 }
1104
1105
1106 /***********************************************************************
1107  *           GetTextExtentExPointW    (GDI32.@)
1108  *
1109  * Return the size of the string as it would be if it was output properly by
1110  * e.g. TextOut.
1111  *
1112  * This should include
1113  * - Intercharacter spacing
1114  * - justification spacing (not yet done)
1115  * - kerning? see below
1116  *
1117  * Kerning.  Since kerning would be carried out by the rendering code it should
1118  * be done by the driver.  However they don't support it yet.  Also I am not
1119  * yet persuaded that (certainly under Win95) any kerning is actually done.
1120  *
1121  * str: According to MSDN this should be null-terminated.  That is not true; a
1122  *      null will not terminate it early.
1123  * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1124  *       than count.  I have seen it be either the size of the full string or
1125  *       1 less than the size of the full string.  I have not seen it bear any
1126  *       resemblance to the portion that would fit.
1127  * lpnFit: What exactly is fitting?  Stupidly, in my opinion, it includes the
1128  *         trailing intercharacter spacing and any trailing justification.
1129  *
1130  * FIXME
1131  * Currently we do this by measuring each character etc.  We should do it by
1132  * passing the request to the driver, perhaps by extending the
1133  * pGetTextExtentPoint function to take the alpDx argument.  That would avoid
1134  * thinking about kerning issues and rounding issues in the justification.
1135  */
1136
1137 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1138                                    INT maxExt, LPINT lpnFit,
1139                                    LPINT alpDx, LPSIZE size )
1140 {
1141     int index, nFit, extent;
1142     SIZE tSize;
1143     BOOL ret = FALSE;
1144
1145     TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1146
1147     size->cx = size->cy = nFit = extent = 0;
1148     for(index = 0; index < count; index++)
1149     {
1150         if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1151         /* GetTextExtentPoint includes intercharacter spacing. */
1152         /* FIXME - justification needs doing yet.  Remember that the base
1153          * data will not be in logical coordinates.
1154          */
1155         extent += tSize.cx;
1156         if( !lpnFit || extent <= maxExt )
1157         /* It is allowed to be equal. */
1158         {
1159             nFit++;
1160             if( alpDx ) alpDx[index] = extent;
1161         }
1162         if( tSize.cy > size->cy ) size->cy = tSize.cy;
1163         str++;
1164     }
1165     size->cx = extent;
1166     if(lpnFit) *lpnFit = nFit;
1167     ret = TRUE;
1168
1169     TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1170
1171 done:
1172     return ret;
1173 }
1174
1175 /***********************************************************************
1176  *           GetTextMetricsA    (GDI32.@)
1177  */
1178 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1179 {
1180     TEXTMETRICW tm32;
1181
1182     if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1183     FONT_TextMetricWToA( &tm32, metrics );
1184     return TRUE;
1185 }
1186
1187 /***********************************************************************
1188  *           GetTextMetricsW    (GDI32.@)
1189  */
1190 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1191 {
1192     BOOL ret = FALSE;
1193     DC * dc = DC_GetDCPtr( hdc );
1194     if (!dc) return FALSE;
1195
1196     if (dc->gdiFont)
1197         ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1198     else if (dc->funcs->pGetTextMetrics)
1199         ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1200
1201     if (ret)
1202     {
1203     /* device layer returns values in device units
1204      * therefore we have to convert them to logical */
1205
1206 #define WDPTOLP(x) ((x<0)?                                      \
1207                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1208                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1209 #define HDPTOLP(y) ((y<0)?                                      \
1210                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1211                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1212
1213     metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
1214     metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
1215     metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
1216     metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
1217     metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
1218     metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
1219     metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
1220     metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
1221         ret = TRUE;
1222 #undef WDPTOLP
1223 #undef HDPTOLP
1224     TRACE("text metrics:\n"
1225           "    Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1226           "    Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1227           "    UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1228           "    StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1229           "    PitchAndFamily = %02x\n"
1230           "    --------------------\n"
1231           "    InternalLeading = %li\n"
1232           "    Ascent = %li\n"
1233           "    Descent = %li\n"
1234           "    Height = %li\n",
1235           metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1236           metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1237           metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1238           metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1239           metrics->tmPitchAndFamily,
1240           metrics->tmInternalLeading,
1241           metrics->tmAscent,
1242           metrics->tmDescent,
1243           metrics->tmHeight );
1244     }
1245     GDI_ReleaseObj( hdc );
1246     return ret;
1247 }
1248
1249
1250 /***********************************************************************
1251  * GetOutlineTextMetrics [GDI.308]  Gets metrics for TrueType fonts.
1252  *
1253  * NOTES
1254  *    lpOTM should be LPOUTLINETEXTMETRIC
1255  *
1256  * RETURNS
1257  *    Success: Non-zero or size of required buffer
1258  *    Failure: 0
1259  */
1260 UINT16 WINAPI GetOutlineTextMetrics16(
1261     HDC16 hdc,    /* [in]  Handle of device context */
1262     UINT16 cbData, /* [in]  Size of metric data array */
1263     LPOUTLINETEXTMETRIC16 lpOTM)  /* [out] Address of metric data array */
1264 {
1265     FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1266     return 0;
1267 }
1268
1269
1270 /***********************************************************************
1271  *              GetOutlineTextMetricsA (GDI32.@)
1272  * Gets metrics for TrueType fonts.
1273  *
1274  * NOTES
1275  *    If the supplied buffer isn't big enough Windows partially fills it up to
1276  *    its given length and returns that length.
1277  *
1278  * RETURNS
1279  *    Success: Non-zero or size of required buffer
1280  *    Failure: 0
1281  */
1282 UINT WINAPI GetOutlineTextMetricsA(
1283     HDC hdc,    /* [in]  Handle of device context */
1284     UINT cbData, /* [in]  Size of metric data array */
1285     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1286 {
1287     char buf[512], *ptr;
1288     UINT ret, needed;
1289     OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1290     OUTLINETEXTMETRICA *output = lpOTM;
1291     INT left, len;
1292
1293     if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1294         return 0;
1295     if(ret > sizeof(buf))
1296         lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1297     GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1298
1299     needed = sizeof(OUTLINETEXTMETRICA);
1300     if(lpOTMW->otmpFamilyName)
1301         needed += WideCharToMultiByte(CP_ACP, 0,
1302            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1303                                       NULL, 0, NULL, NULL);
1304     if(lpOTMW->otmpFaceName)
1305         needed += WideCharToMultiByte(CP_ACP, 0,
1306            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1307                                       NULL, 0, NULL, NULL);
1308     if(lpOTMW->otmpStyleName)
1309         needed += WideCharToMultiByte(CP_ACP, 0,
1310            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1311                                       NULL, 0, NULL, NULL);
1312     if(lpOTMW->otmpFullName)
1313         needed += WideCharToMultiByte(CP_ACP, 0,
1314            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1315                                       NULL, 0, NULL, NULL);
1316
1317     if(!lpOTM) {
1318         ret = needed;
1319         goto end;
1320     }
1321
1322     TRACE("needed = %d\n", needed);
1323     if(needed > cbData)
1324         /* Since the supplied buffer isn't big enough, we'll alloc one
1325            that is and memcpy the first cbData bytes into the lpOTM at
1326            the end. */
1327         output = HeapAlloc(GetProcessHeap(), 0, needed);
1328
1329     ret = output->otmSize = min(needed, cbData);
1330     FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1331     output->otmFiller = 0;
1332     output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1333     output->otmfsSelection = lpOTMW->otmfsSelection;
1334     output->otmfsType = lpOTMW->otmfsType;
1335     output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1336     output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1337     output->otmItalicAngle = lpOTMW->otmItalicAngle;
1338     output->otmEMSquare = lpOTMW->otmEMSquare;
1339     output->otmAscent = lpOTMW->otmAscent;
1340     output->otmDescent = lpOTMW->otmDescent;
1341     output->otmLineGap = lpOTMW->otmLineGap;
1342     output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1343     output->otmsXHeight = lpOTMW->otmsXHeight;
1344     output->otmrcFontBox = lpOTMW->otmrcFontBox;
1345     output->otmMacAscent = lpOTMW->otmMacAscent;
1346     output->otmMacDescent = lpOTMW->otmMacDescent;
1347     output->otmMacLineGap = lpOTMW->otmMacLineGap;
1348     output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1349     output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1350     output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1351     output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1352     output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1353     output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1354     output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1355     output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1356     output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1357
1358
1359     ptr = (char*)(output + 1);
1360     left = needed - sizeof(*output);
1361
1362     if(lpOTMW->otmpFamilyName) {
1363         output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1364         len = WideCharToMultiByte(CP_ACP, 0,
1365              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1366                                   ptr, left, NULL, NULL);
1367         left -= len;
1368         ptr += len;
1369     } else
1370         output->otmpFamilyName = 0;
1371
1372     if(lpOTMW->otmpFaceName) {
1373         output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1374         len = WideCharToMultiByte(CP_ACP, 0,
1375              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1376                                   ptr, left, NULL, NULL);
1377         left -= len;
1378         ptr += len;
1379     } else
1380         output->otmpFaceName = 0;
1381
1382     if(lpOTMW->otmpStyleName) {
1383         output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1384         len = WideCharToMultiByte(CP_ACP, 0,
1385              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1386                                   ptr, left, NULL, NULL);
1387         left -= len;
1388         ptr += len;
1389     } else
1390         output->otmpStyleName = 0;
1391
1392     if(lpOTMW->otmpFullName) {
1393         output->otmpFullName = (LPSTR)(ptr - (char*)output);
1394         len = WideCharToMultiByte(CP_ACP, 0,
1395              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1396                                   ptr, left, NULL, NULL);
1397         left -= len;
1398     } else
1399         output->otmpFullName = 0;
1400
1401     assert(left == 0);
1402
1403     if(output != lpOTM) {
1404         memcpy(lpOTM, output, cbData);
1405         HeapFree(GetProcessHeap(), 0, output);
1406     }
1407
1408 end:
1409     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1410         HeapFree(GetProcessHeap(), 0, lpOTMW);
1411
1412     return ret;
1413 }
1414
1415
1416 /***********************************************************************
1417  *           GetOutlineTextMetricsW [GDI32.@]
1418  */
1419 UINT WINAPI GetOutlineTextMetricsW(
1420     HDC hdc,    /* [in]  Handle of device context */
1421     UINT cbData, /* [in]  Size of metric data array */
1422     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1423 {
1424     DC *dc = DC_GetDCPtr( hdc );
1425     OUTLINETEXTMETRICW *output = lpOTM;
1426     UINT ret;
1427
1428     TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1429     if(!dc) return 0;
1430
1431     if(dc->gdiFont) {
1432         ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1433         if(lpOTM && ret) {
1434             if(ret > cbData) {
1435                 output = HeapAlloc(GetProcessHeap(), 0, ret);
1436                 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1437             }
1438
1439 #define WDPTOLP(x) ((x<0)?                                      \
1440                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1441                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1442 #define HDPTOLP(y) ((y<0)?                                      \
1443                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1444                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1445
1446             output->otmTextMetrics.tmHeight           = HDPTOLP(output->otmTextMetrics.tmHeight);
1447             output->otmTextMetrics.tmAscent           = HDPTOLP(output->otmTextMetrics.tmAscent);
1448             output->otmTextMetrics.tmDescent          = HDPTOLP(output->otmTextMetrics.tmDescent);
1449             output->otmTextMetrics.tmInternalLeading  = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1450             output->otmTextMetrics.tmExternalLeading  = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1451             output->otmTextMetrics.tmAveCharWidth     = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1452             output->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1453             output->otmTextMetrics.tmOverhang         = WDPTOLP(output->otmTextMetrics.tmOverhang);
1454             output->otmAscent = HDPTOLP(output->otmAscent);
1455             output->otmDescent = HDPTOLP(output->otmDescent);
1456             output->otmLineGap = HDPTOLP(output->otmLineGap);
1457             output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1458             output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1459             output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1460             output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1461             output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1462             output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1463             output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1464             output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1465             output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1466             output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1467             output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1468             output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1469             output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1470             output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1471             output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1472             output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1473             output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1474             output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1475             output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1476             output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1477             output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1478 #undef WDPTOLP
1479 #undef HDPTOLP
1480             if(output != lpOTM) {
1481                 memcpy(lpOTM, output, cbData);
1482                 HeapFree(GetProcessHeap(), 0, output);
1483                 ret = cbData;
1484             }
1485         }
1486     }
1487
1488     else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1489               but really this should just be a return 0. */
1490
1491         ret = sizeof(*lpOTM);
1492         if (lpOTM) {
1493             if(cbData < ret)
1494                 ret = 0;
1495             else {
1496                 memset(lpOTM, 0, ret);
1497                 lpOTM->otmSize = sizeof(*lpOTM);
1498                 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1499                 /*
1500                   Further fill of the structure not implemented,
1501                   Needs real values for the structure members
1502                 */
1503             }
1504         }
1505     }
1506     GDI_ReleaseObj(hdc);
1507     return ret;
1508 }
1509
1510
1511 /***********************************************************************
1512  *           GetCharWidthW      (GDI32.@)
1513  *           GetCharWidth32W    (GDI32.@)
1514  */
1515 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1516                                LPINT buffer )
1517 {
1518     UINT i;
1519     BOOL ret = FALSE;
1520     DC * dc = DC_GetDCPtr( hdc );
1521     if (!dc) return FALSE;
1522
1523     if (dc->gdiFont)
1524         ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1525     else if (dc->funcs->pGetCharWidth)
1526         ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1527
1528     if (ret)
1529     {
1530         /* convert device units to logical */
1531         for( i = firstChar; i <= lastChar; i++, buffer++ )
1532             *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1533         ret = TRUE;
1534     }
1535     GDI_ReleaseObj( hdc );
1536     return ret;
1537 }
1538
1539
1540 /***********************************************************************
1541  *           GetCharWidthA      (GDI32.@)
1542  *           GetCharWidth32A    (GDI32.@)
1543  */
1544 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1545                                LPINT buffer )
1546 {
1547     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1548     LPSTR str;
1549     LPWSTR wstr;
1550     BOOL ret = TRUE;
1551
1552     if(count <= 0) return FALSE;
1553
1554     str = HeapAlloc(GetProcessHeap(), 0, count);
1555     for(i = 0; i < count; i++)
1556         str[i] = (BYTE)(firstChar + i);
1557
1558     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1559
1560     for(i = 0; i < wlen; i++)
1561     {
1562         if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1563         {
1564             ret = FALSE;
1565             break;
1566         }
1567         buffer++;
1568     }
1569
1570     HeapFree(GetProcessHeap(), 0, str);
1571     HeapFree(GetProcessHeap(), 0, wstr);
1572
1573     return ret;
1574 }
1575
1576
1577 /* FIXME: all following APIs ******************************************/
1578
1579
1580 /***********************************************************************
1581  *           SetMapperFlags    (GDI32.@)
1582  */
1583 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1584 {
1585     DC *dc = DC_GetDCPtr( hDC );
1586     DWORD ret = 0;
1587     if(!dc) return 0;
1588     if(dc->funcs->pSetMapperFlags)
1589         ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
1590     else
1591         FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1592     GDI_ReleaseObj( hDC );
1593     return ret;
1594 }
1595
1596 /***********************************************************************
1597  *          GetAspectRatioFilterEx  (GDI.486)
1598  */
1599 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1600 {
1601   FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1602   return FALSE;
1603 }
1604
1605 /***********************************************************************
1606  *          GetAspectRatioFilterEx  (GDI32.@)
1607  */
1608 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1609 {
1610   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1611   return FALSE;
1612 }
1613
1614
1615 /***********************************************************************
1616  *           GetCharABCWidthsA   (GDI32.@)
1617  */
1618 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1619                                   LPABC abc )
1620 {
1621     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1622     LPSTR str;
1623     LPWSTR wstr;
1624     BOOL ret = TRUE;
1625
1626     if(count <= 0) return FALSE;
1627
1628     str = HeapAlloc(GetProcessHeap(), 0, count);
1629     for(i = 0; i < count; i++)
1630         str[i] = (BYTE)(firstChar + i);
1631
1632     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1633
1634     for(i = 0; i < wlen; i++)
1635     {
1636         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
1637         {
1638             ret = FALSE;
1639             break;
1640         }
1641         abc++;
1642     }
1643
1644     HeapFree(GetProcessHeap(), 0, str);
1645     HeapFree(GetProcessHeap(), 0, wstr);
1646
1647     return ret;
1648 }
1649
1650
1651 /******************************************************************************
1652  * GetCharABCWidthsW [GDI32.@]
1653  *
1654  * Retrieves widths of characters in range.
1655  *
1656  * PARAMS
1657  *    hdc       [I] Handle of device context
1658  *    firstChar [I] First character in range to query
1659  *    lastChar  [I] Last character in range to query
1660  *    abc       [O] Address of character-width structure
1661  *
1662  * NOTES
1663  *    Only works with TrueType fonts
1664  *
1665  * RETURNS
1666  *    Success: TRUE
1667  *    Failure: FALSE
1668  */
1669 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1670                                    LPABC abc )
1671 {
1672     DC *dc = DC_GetDCPtr(hdc);
1673     int i;
1674     BOOL ret = FALSE;
1675
1676     if(dc->gdiFont)
1677         ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
1678     else
1679         FIXME(": stub\n");
1680
1681     if (ret)
1682     {
1683         /* convert device units to logical */
1684         for( i = firstChar; i <= lastChar; i++, abc++ ) {
1685             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
1686             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
1687             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
1688         }
1689         ret = TRUE;
1690     }
1691
1692     GDI_ReleaseObj(hdc);
1693     return ret;
1694 }
1695
1696
1697 /***********************************************************************
1698  *           GetGlyphOutline    (GDI.309)
1699  */
1700 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1701                                 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1702                                 LPVOID lpBuffer, const MAT2 *lpmat2 )
1703 {
1704     FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1705           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1706     return ~0UL; /* failure */
1707 }
1708
1709
1710 /***********************************************************************
1711  *           GetGlyphOutlineA    (GDI32.@)
1712  */
1713 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1714                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1715                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
1716 {
1717     LPWSTR p = NULL;
1718     DWORD ret;
1719     UINT c;
1720
1721     if(!(fuFormat & GGO_GLYPH_INDEX)) {
1722         p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL);
1723         c = p[0];
1724     } else
1725         c = uChar;
1726     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
1727                            lpmat2);
1728     if(p)
1729         HeapFree(GetProcessHeap(), 0, p);
1730     return ret;
1731 }
1732
1733 /***********************************************************************
1734  *           GetGlyphOutlineW    (GDI32.@)
1735  */
1736 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1737                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1738                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
1739 {
1740     DC *dc = DC_GetDCPtr(hdc);
1741     DWORD ret;
1742
1743     TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
1744           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1745
1746     if(!dc) return GDI_ERROR;
1747
1748     if(dc->gdiFont)
1749       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
1750                                    cbBuffer, lpBuffer, lpmat2);
1751     else
1752       ret = GDI_ERROR;
1753
1754     GDI_ReleaseObj(hdc);
1755     return ret;
1756 }
1757
1758
1759 /***********************************************************************
1760  *           CreateScalableFontResourceA   (GDI32.@)
1761  */
1762 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1763                                              LPCSTR lpszResourceFile,
1764                                              LPCSTR lpszFontFile,
1765                                              LPCSTR lpszCurrentPath )
1766 {
1767     HANDLE f;
1768
1769     /* fHidden=1 - only visible for the calling app, read-only, not
1770      * enumbered with EnumFonts/EnumFontFamilies
1771      * lpszCurrentPath can be NULL
1772      */
1773     FIXME("(%ld,%s,%s,%s): stub\n",
1774           fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
1775           debugstr_a(lpszCurrentPath) );
1776
1777     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
1778     if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
1779         CloseHandle(f);
1780         SetLastError(ERROR_FILE_EXISTS);
1781         return FALSE;
1782     }
1783     return FALSE; /* create failed */
1784 }
1785
1786 /***********************************************************************
1787  *           CreateScalableFontResourceW   (GDI32.@)
1788  */
1789 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1790                                              LPCWSTR lpszResourceFile,
1791                                              LPCWSTR lpszFontFile,
1792                                              LPCWSTR lpszCurrentPath )
1793 {
1794     FIXME("(%ld,%p,%p,%p): stub\n",
1795           fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1796     return FALSE; /* create failed */
1797 }
1798
1799
1800 /*************************************************************************
1801  *             GetRasterizerCaps   (GDI32.@)
1802  */
1803 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1804 {
1805   lprs->nSize = sizeof(RASTERIZER_STATUS);
1806   lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
1807   lprs->nLanguageID = 0;
1808   return TRUE;
1809 }
1810
1811
1812 /*************************************************************************
1813  *             GetKerningPairsA   (GDI32.@)
1814  */
1815 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
1816                                LPKERNINGPAIR lpKerningPairs )
1817 {
1818     return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
1819 }
1820
1821
1822 /*************************************************************************
1823  *             GetKerningPairsW   (GDI32.@)
1824  */
1825 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
1826                                  LPKERNINGPAIR lpKerningPairs )
1827 {
1828     int i;
1829     FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
1830     for (i = 0; i < cPairs; i++)
1831         lpKerningPairs[i].iKernAmount = 0;
1832     return 0;
1833 }
1834
1835 /*************************************************************************
1836  * TranslateCharsetInfo [GDI32.@]
1837  *
1838  * Fills a CHARSETINFO structure for a character set, code page, or
1839  * font. This allows making the correspondance between different labelings
1840  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1841  * of the same encoding.
1842  *
1843  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1844  * only one codepage should be set in *lpSrc.
1845  *
1846  * RETURNS
1847  *   TRUE on success, FALSE on failure.
1848  *
1849  */
1850 BOOL WINAPI TranslateCharsetInfo(
1851   LPDWORD lpSrc, /* [in]
1852        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1853        if flags == TCI_SRCCHARSET: a character set value
1854        if flags == TCI_SRCCODEPAGE: a code page value
1855                  */
1856   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1857   DWORD flags /* [in] determines interpretation of lpSrc */)
1858 {
1859     int index = 0;
1860     switch (flags) {
1861     case TCI_SRCFONTSIG:
1862         while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1863       break;
1864     case TCI_SRCCODEPAGE:
1865       while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1866       break;
1867     case TCI_SRCCHARSET:
1868       while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1869       break;
1870     default:
1871       return FALSE;
1872     }
1873     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1874     memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1875     return TRUE;
1876 }
1877
1878 /*************************************************************************
1879  *             GetFontLanguageInfo   (GDI32.@)
1880  */
1881 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
1882 {
1883         FONTSIGNATURE fontsig;
1884         static const DWORD GCP_DBCS_MASK=0x003F0000,
1885                 GCP_DIACRITIC_MASK=0x00000000,
1886                 FLI_GLYPHS_MASK=0x00000000,
1887                 GCP_GLYPHSHAPE_MASK=0x00000040,
1888                 GCP_KASHIDA_MASK=0x00000000,
1889                 GCP_LIGATE_MASK=0x00000000,
1890                 GCP_USEKERNING_MASK=0x00000000,
1891                 GCP_REORDER_MASK=0x00000060;
1892
1893         DWORD result=0;
1894
1895         GetTextCharsetInfo( hdc, &fontsig, 0 );
1896         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
1897
1898         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
1899                 result|=GCP_DBCS;
1900
1901         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
1902                 result|=GCP_DIACRITIC;
1903
1904         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
1905                 result|=FLI_GLYPHS;
1906
1907         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
1908                 result|=GCP_GLYPHSHAPE;
1909
1910         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
1911                 result|=GCP_KASHIDA;
1912
1913         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
1914                 result|=GCP_LIGATE;
1915
1916         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
1917                 result|=GCP_USEKERNING;
1918
1919         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
1920         if( GetTextAlign( hdc) & TA_RTLREADING )
1921             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
1922                     result|=GCP_REORDER;
1923
1924         return result;
1925 }
1926
1927
1928 /*************************************************************************
1929  * GetFontData [GDI32.@]
1930  *
1931  * Retrieve data for TrueType font.
1932  *
1933  * RETURNS
1934  *
1935  * success: Number of bytes returned
1936  * failure: GDI_ERROR
1937  *
1938  * NOTES
1939  *
1940  * Calls SetLastError()
1941  *
1942  */
1943 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
1944     LPVOID buffer, DWORD length)
1945 {
1946     DC *dc = DC_GetDCPtr(hdc);
1947     DWORD ret = GDI_ERROR;
1948
1949     if(!dc) return GDI_ERROR;
1950
1951     if(dc->gdiFont)
1952       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
1953
1954     GDI_ReleaseObj(hdc);
1955     return ret;
1956 }
1957
1958 /*************************************************************************
1959  * GetGlyphIndicesA [GDI32.@]
1960  */
1961 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
1962                               LPWORD pgi, DWORD flags)
1963 {
1964     DWORD ret;
1965     WCHAR *lpstrW;
1966     INT countW;
1967
1968     TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1969           hdc, debugstr_an(lpstr, count), count, pgi, flags);
1970
1971     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
1972     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
1973     HeapFree(GetProcessHeap(), 0, lpstrW);
1974
1975     return ret;
1976 }
1977
1978 /*************************************************************************
1979  * GetGlyphIndicesW [GDI32.@]
1980  */
1981 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
1982                               LPWORD pgi, DWORD flags)
1983 {
1984     DC *dc = DC_GetDCPtr(hdc);
1985     DWORD ret = GDI_ERROR;
1986
1987     TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1988           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
1989
1990     if(!dc) return GDI_ERROR;
1991
1992     if(dc->gdiFont)
1993         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
1994
1995     GDI_ReleaseObj(hdc);
1996     return ret;
1997 }
1998
1999 /*************************************************************************
2000  * GetCharacterPlacementA [GDI32.@]
2001  *
2002  * NOTES:
2003  *  the web browser control of ie4 calls this with dwFlags=0
2004  */
2005 DWORD WINAPI
2006 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2007                          INT nMaxExtent, GCP_RESULTSA *lpResults,
2008                          DWORD dwFlags)
2009 {
2010     WCHAR *lpStringW;
2011     INT uCountW;
2012     GCP_RESULTSW resultsW;
2013     DWORD ret;
2014     UINT font_cp;
2015
2016     TRACE("%s, %d, %d, 0x%08lx\n",
2017           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2018
2019     /* both structs are equal in size */
2020     memcpy(&resultsW, lpResults, sizeof(resultsW));
2021
2022     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2023     if(lpResults->lpOutString)
2024         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2025
2026     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2027
2028     if(lpResults->lpOutString) {
2029         WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2030                             lpResults->lpOutString, uCount, NULL, NULL );
2031     }
2032
2033     HeapFree(GetProcessHeap(), 0, lpStringW);
2034     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2035
2036     return ret;
2037 }
2038
2039 /*************************************************************************
2040  * GetCharacterPlacementW [GDI32.@]
2041  *
2042  *   Retrieve information about a string. This includes the width, reordering,
2043  *   Glyphing and so on.
2044  *
2045  * RETURNS
2046  *
2047  *   The width and height of the string if successful, 0 if failed.
2048  *
2049  * BUGS
2050  *
2051  *   All flags except GCP_REORDER are not yet implemented.
2052  *   Reordering is not 100% complient to the Windows BiDi method.
2053  *   Caret positioning is not yet implemented for BiDi.
2054  *   Classes are not yet implemented.
2055  *
2056  */
2057 DWORD WINAPI
2058 GetCharacterPlacementW(
2059                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
2060                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
2061                 INT uCount,             /* [in] Number of WORDS in string. */
2062                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
2063                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2064                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
2065                 )
2066 {
2067     DWORD ret=0;
2068     SIZE size;
2069     UINT i, nSet;
2070
2071     TRACE("%s, %d, %d, 0x%08lx\n",
2072           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2073
2074     TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2075           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2076             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2077             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2078             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2079
2080     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08lx ignored\n", dwFlags);
2081     if(lpResults->lpClass)      FIXME("classes not implemented\n");
2082     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2083         FIXME("Caret positions for complex scripts not implemented\n");
2084
2085         nSet = (UINT)uCount;
2086         if(nSet > lpResults->nGlyphs)
2087                 nSet = lpResults->nGlyphs;
2088
2089         /* return number of initialized fields */
2090         lpResults->nGlyphs = nSet;
2091
2092         if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2093         {
2094                 /* Treat the case where no special handling was requested in a fastpath way */
2095                 /* copy will do if the GCP_REORDER flag is not set */
2096                 if(lpResults->lpOutString)
2097                     strncpyW( lpResults->lpOutString, lpString, nSet );
2098
2099                 if(lpResults->lpOrder)
2100                 {
2101                         for(i = 0; i < nSet; i++)
2102                                 lpResults->lpOrder[i] = i;
2103                 }
2104         } else
2105         {
2106             BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2107                           nSet, lpResults->lpOrder );
2108         }
2109
2110         /* FIXME: Will use the placement chars */
2111         if (lpResults->lpDx)
2112         {
2113                 int c;
2114                 for (i = 0; i < nSet; i++)
2115                 {
2116                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2117                                 lpResults->lpDx[i]= c;
2118                 }
2119         }
2120
2121     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2122     {
2123         int pos = 0;
2124        
2125         lpResults->lpCaretPos[0] = 0;
2126         for (i = 1; i < nSet; i++)
2127             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2128                 lpResults->lpCaretPos[i] = (pos += size.cx);
2129     }
2130    
2131     if(lpResults->lpGlyphs)
2132         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2133
2134     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2135       ret = MAKELONG(size.cx, size.cy);
2136
2137     return ret;
2138 }
2139
2140 /*************************************************************************
2141  *      GetCharABCWidthsFloatA [GDI32.@]
2142  */
2143 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2144                                         LPABCFLOAT lpABCF)
2145 {
2146        FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2147        return 0;
2148 }
2149
2150 /*************************************************************************
2151  *      GetCharABCWidthsFloatW [GDI32.@]
2152  */
2153 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2154                                         UINT iLastChar, LPABCFLOAT lpABCF)
2155 {
2156        FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2157        return 0;
2158 }
2159
2160 /*************************************************************************
2161  *      GetCharWidthFloatA [GDI32.@]
2162  */
2163 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2164                                     UINT iLastChar, PFLOAT pxBuffer)
2165 {
2166        FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2167        return 0;
2168 }
2169
2170 /*************************************************************************
2171  *      GetCharWidthFloatW [GDI32.@]
2172  */
2173 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2174                                     UINT iLastChar, PFLOAT pxBuffer)
2175 {
2176        FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2177        return 0;
2178 }
2179
2180
2181 /***********************************************************************
2182  *                                                                     *
2183  *           Font Resource API                                         *
2184  *                                                                     *
2185  ***********************************************************************/
2186
2187 /***********************************************************************
2188  *           AddFontResourceA    (GDI32.@)
2189  */
2190 INT WINAPI AddFontResourceA( LPCSTR str )
2191 {
2192     return AddFontResourceExA( str, 0, NULL);
2193 }
2194
2195 /***********************************************************************
2196  *           AddFontResourceW    (GDI32.@)
2197  */
2198 INT WINAPI AddFontResourceW( LPCWSTR str )
2199 {
2200     return AddFontResourceExW(str, 0, NULL);
2201 }
2202
2203
2204 /***********************************************************************
2205  *           AddFontResourceExA    (GDI32.@)
2206  */
2207 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2208 {
2209     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2210     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2211     INT ret;
2212
2213     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2214     ret = AddFontResourceExW(strW, fl, pdv);
2215     HeapFree(GetProcessHeap(), 0, strW);
2216     return ret;
2217 }
2218
2219 /***********************************************************************
2220  *           AddFontResourceExW    (GDI32.@)
2221  */
2222 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2223 {
2224     return WineEngAddFontResourceEx(str, fl, pdv);
2225 }
2226
2227 /***********************************************************************
2228  *           RemoveFontResourceA    (GDI32.@)
2229  */
2230 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2231 {
2232     return RemoveFontResourceExA(str, 0, 0);
2233 }
2234
2235 /***********************************************************************
2236  *           RemoveFontResourceW    (GDI32.@)
2237  */
2238 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2239 {
2240     return RemoveFontResourceExW(str, 0, 0);
2241 }
2242
2243 /***********************************************************************
2244  *           RemoveFontResourceExA    (GDI32.@)
2245  */
2246 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2247 {
2248     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2249     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2250     INT ret;
2251
2252     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2253     ret = RemoveFontResourceExW(strW, fl, pdv);
2254     HeapFree(GetProcessHeap(), 0, strW);
2255     return ret;
2256 }
2257
2258 /***********************************************************************
2259  *           RemoveFontResourceExW    (GDI32.@)
2260  */
2261 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2262 {
2263     return WineEngRemoveFontResourceEx(str, fl, pdv);
2264 }
2265
2266 /***********************************************************************
2267  *           GetTextCharset    (GDI32.@)
2268  */
2269 UINT WINAPI GetTextCharset(HDC hdc)
2270 {
2271     /* MSDN docs say this is equivalent */
2272     return GetTextCharsetInfo(hdc, NULL, 0);
2273 }
2274
2275 /***********************************************************************
2276  *           GetTextCharsetInfo    (GDI32.@)
2277  */
2278 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
2279 {
2280     UINT ret = DEFAULT_CHARSET;
2281     DC *dc = DC_GetDCPtr(hdc);
2282
2283     if (!dc) goto done;
2284
2285     if (dc->gdiFont)
2286         ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
2287
2288     GDI_ReleaseObj(hdc);
2289
2290 done:
2291     if (ret == DEFAULT_CHARSET && fs)
2292         memset(fs, 0, sizeof(FONTSIGNATURE));
2293     return ret;
2294 }