Removed some of the DOS device hacks (based on a patch by Eric
[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 );
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     {
633         /* convert font metrics */
634         ENUMLOGFONTEXA logfont;
635         NEWTEXTMETRICEXA tmA;
636
637         pfe->dwFlags |= ENUM_CALLED;
638         if (!(pfe->dwFlags & ENUM_UNICODE))
639         {
640             FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
641             FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
642             plf = (LOGFONTW *)&logfont.elfLogFont;
643             ptm = (TEXTMETRICW *)&tmA;
644         }
645         GDI_ReleaseObj( pfe->hdc );  /* release the GDI lock */
646
647         ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
648
649         /* get the lock again and make sure the DC is still valid */
650         dc = DC_GetDCPtr( pfe->hdc );
651         if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
652         {
653             if (dc) GDI_ReleaseObj( pfe->hdc );
654             pfe->hdc = 0;  /* make sure we don't try to release it later on */
655             ret = 0;
656         }
657     }
658     return ret;
659 }
660
661 /***********************************************************************
662  *              EnumFontFamiliesEx      (GDI.613)
663  */
664 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
665                                    FONTENUMPROC16 efproc, LPARAM lParam,
666                                    DWORD dwFlags)
667 {
668     fontEnum16 fe16;
669     INT16       ret = 1, ret2;
670     DC*         dc = DC_GetDCPtr( HDC_32(hDC) );
671     NEWTEXTMETRICEX16 tm16;
672     ENUMLOGFONTEX16 lf16;
673     LOGFONTW lfW;
674     BOOL enum_gdi_fonts;
675
676     if (!dc) return 0;
677     FONT_LogFont16ToW(plf, &lfW);
678
679     fe16.hdc = HDC_32(hDC);
680     fe16.dc = dc;
681     fe16.physDev = dc->physDev;
682     fe16.lpLogFontParam = plf;
683     fe16.lpEnumFunc = efproc;
684     fe16.lpData = lParam;
685     fe16.lpTextMetric = &tm16;
686     fe16.lpLogFont = &lf16;
687     fe16.segTextMetric = MapLS( &tm16 );
688     fe16.segLogFont = MapLS( &lf16 );
689     fe16.dwFlags = 0;
690
691     enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
692
693     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
694     {
695         ret = 0;
696         goto done;
697     }
698
699     if (enum_gdi_fonts)
700         ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
701     fe16.dwFlags &= ~ENUM_CALLED;
702     if (ret && dc->funcs->pEnumDeviceFonts) {
703         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
704         if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
705             ret = ret2;
706     }
707 done:
708     UnMapLS( fe16.segTextMetric );
709     UnMapLS( fe16.segLogFont );
710     if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
711     return ret;
712 }
713
714 /***********************************************************************
715  *              FONT_EnumFontFamiliesEx
716  */
717 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
718                                     FONTENUMPROCW efproc,
719                                     LPARAM lParam, DWORD dwUnicode)
720 {
721     INT ret = 1, ret2;
722     DC *dc = DC_GetDCPtr( hDC );
723     fontEnum32 fe32;
724     BOOL enum_gdi_fonts;
725
726     if (!dc) return 0;
727
728     TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
729           plf->lfCharSet);
730     fe32.lpLogFontParam = plf;
731     fe32.lpEnumFunc = efproc;
732     fe32.lpData = lParam;
733     fe32.dwFlags = dwUnicode;
734     fe32.hdc = hDC;
735     fe32.dc = dc;
736     fe32.physDev = dc->physDev;
737
738     enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
739
740     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
741     {
742         ret = 0;
743         goto done;
744     }
745
746     if (enum_gdi_fonts)
747         ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
748     fe32.dwFlags &= ~ENUM_CALLED;
749     if (ret && dc->funcs->pEnumDeviceFonts) {
750         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
751         if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
752             ret = ret2;
753     }
754  done:
755     if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
756     return ret;
757 }
758
759 /***********************************************************************
760  *              EnumFontFamiliesExW     (GDI32.@)
761  */
762 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
763                                     FONTENUMPROCW efproc,
764                                     LPARAM lParam, DWORD dwFlags )
765 {
766     return  FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
767 }
768
769 /***********************************************************************
770  *              EnumFontFamiliesExA     (GDI32.@)
771  */
772 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
773                                     FONTENUMPROCA efproc,
774                                     LPARAM lParam, DWORD dwFlags)
775 {
776     LOGFONTW lfW;
777     FONT_LogFontAToW( plf, &lfW );
778
779     return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
780 }
781
782 /***********************************************************************
783  *              EnumFontFamilies        (GDI.330)
784  */
785 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
786                                  FONTENUMPROC16 efproc, LPARAM lpData )
787 {
788     LOGFONT16   lf;
789
790     lf.lfCharSet = DEFAULT_CHARSET;
791     if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
792     else lf.lfFaceName[0] = '\0';
793
794     return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
795 }
796
797 /***********************************************************************
798  *              EnumFontFamiliesA       (GDI32.@)
799  */
800 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
801                                   FONTENUMPROCA efproc, LPARAM lpData )
802 {
803     LOGFONTA    lf;
804
805     lf.lfCharSet = DEFAULT_CHARSET;
806     if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
807     else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
808
809     return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
810 }
811
812 /***********************************************************************
813  *              EnumFontFamiliesW       (GDI32.@)
814  */
815 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
816                                   FONTENUMPROCW efproc, LPARAM lpData )
817 {
818     LOGFONTW  lf;
819
820     lf.lfCharSet = DEFAULT_CHARSET;
821     if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
822     else lf.lfFaceName[0] = 0;
823
824     return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
825 }
826
827 /***********************************************************************
828  *              EnumFonts               (GDI.70)
829  */
830 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
831                           LPARAM lpData )
832 {
833     return EnumFontFamilies16( hDC, lpName, efproc, lpData );
834 }
835
836 /***********************************************************************
837  *              EnumFontsA              (GDI32.@)
838  */
839 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
840                            LPARAM lpData )
841 {
842     return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
843 }
844
845 /***********************************************************************
846  *              EnumFontsW              (GDI32.@)
847  */
848 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
849                            LPARAM lpData )
850 {
851     return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
852 }
853
854
855 /***********************************************************************
856  *           GetTextCharacterExtra    (GDI32.@)
857  */
858 INT WINAPI GetTextCharacterExtra( HDC hdc )
859 {
860     INT ret;
861     DC *dc = DC_GetDCPtr( hdc );
862     if (!dc) return 0x80000000;
863     ret = dc->charExtra;
864     GDI_ReleaseObj( hdc );
865     return ret;
866 }
867
868
869 /***********************************************************************
870  *           SetTextCharacterExtra    (GDI32.@)
871  */
872 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
873 {
874     INT prev;
875     DC * dc = DC_GetDCPtr( hdc );
876     if (!dc) return 0x80000000;
877     if (dc->funcs->pSetTextCharacterExtra)
878         prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
879     else
880     {
881         prev = dc->charExtra;
882         dc->charExtra = extra;
883     }
884     GDI_ReleaseObj( hdc );
885     return prev;
886 }
887
888
889 /***********************************************************************
890  *           SetTextJustification    (GDI32.@)
891  */
892 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
893 {
894     BOOL ret = TRUE;
895     DC * dc = DC_GetDCPtr( hdc );
896     if (!dc) return FALSE;
897     if (dc->funcs->pSetTextJustification)
898         ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
899     else
900     {
901         extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
902         if (!extra) breaks = 0;
903         dc->breakCount = breaks;
904         if (breaks)
905         {
906             dc->breakExtra = extra / breaks;
907             dc->breakRem   = extra - (dc->breakCount * 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         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1014         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1015         size->cx += count * dc->charExtra;
1016     }
1017     else if(dc->funcs->pGetTextExtentPoint)
1018         ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
1019
1020     GDI_ReleaseObj( hdc );
1021
1022     TRACE("(%p %s %d %p): returning %ld x %ld\n",
1023           hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
1024     return ret;
1025 }
1026
1027 /***********************************************************************
1028  * GetTextExtentPointI [GDI32.@]
1029  *
1030  * Computes width and height of the array of glyph indices.
1031  *
1032  * RETURNS
1033  *    Success: TRUE
1034  *    Failure: FALSE
1035  */
1036 BOOL WINAPI GetTextExtentPointI(
1037     HDC hdc,     /* [in]  Handle of device context */
1038     const WORD *indices,   /* [in]  Address of glyph index array */
1039     INT count,   /* [in]  Number of glyphs in array */
1040     LPSIZE size) /* [out] Address of structure for string size */
1041 {
1042     BOOL ret = FALSE;
1043     DC * dc = DC_GetDCPtr( hdc );
1044     if (!dc) return FALSE;
1045
1046     if(dc->gdiFont) {
1047         ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1048         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1049         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1050         size->cx += count * dc->charExtra;
1051     }
1052     else if(dc->funcs->pGetTextExtentPoint) {
1053         FIXME("calling GetTextExtentPoint\n");
1054         ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
1055     }
1056
1057     GDI_ReleaseObj( hdc );
1058
1059     TRACE("(%p %p %d %p): returning %ld x %ld\n",
1060           hdc, indices, count, size, size->cx, size->cy );
1061     return ret;
1062 }
1063
1064
1065 /***********************************************************************
1066  *           GetTextExtentPointA    (GDI32.@)
1067  */
1068 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1069                                           LPSIZE size )
1070 {
1071     TRACE("not bug compatible.\n");
1072     return GetTextExtentPoint32A( hdc, str, count, size );
1073 }
1074
1075 /***********************************************************************
1076  *           GetTextExtentPointW   (GDI32.@)
1077  */
1078 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1079                                           LPSIZE size )
1080 {
1081     TRACE("not bug compatible.\n");
1082     return GetTextExtentPoint32W( hdc, str, count, size );
1083 }
1084
1085
1086 /***********************************************************************
1087  *           GetTextExtentExPointA    (GDI32.@)
1088  */
1089 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1090                                    INT maxExt, LPINT lpnFit,
1091                                    LPINT alpDx, LPSIZE size )
1092 {
1093     BOOL ret;
1094     INT wlen;
1095     LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1096     ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1097     if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1098     HeapFree( GetProcessHeap(), 0, p );
1099     return ret;
1100 }
1101
1102
1103 /***********************************************************************
1104  *           GetTextExtentExPointW    (GDI32.@)
1105  *
1106  * Return the size of the string as it would be if it was output properly by
1107  * e.g. TextOut.
1108  *
1109  * This should include
1110  * - Intercharacter spacing
1111  * - justification spacing (not yet done)
1112  * - kerning? see below
1113  *
1114  * Kerning.  Since kerning would be carried out by the rendering code it should
1115  * be done by the driver.  However they don't support it yet.  Also I am not
1116  * yet persuaded that (certainly under Win95) any kerning is actually done.
1117  *
1118  * str: According to MSDN this should be null-terminated.  That is not true; a
1119  *      null will not terminate it early.
1120  * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1121  *       than count.  I have seen it be either the size of the full string or
1122  *       1 less than the size of the full string.  I have not seen it bear any
1123  *       resemblance to the portion that would fit.
1124  * lpnFit: What exactly is fitting?  Stupidly, in my opinion, it includes the
1125  *         trailing intercharacter spacing and any trailing justification.
1126  *
1127  * FIXME
1128  * Currently we do this by measuring each character etc.  We should do it by
1129  * passing the request to the driver, perhaps by extending the
1130  * pGetTextExtentPoint function to take the alpDx argument.  That would avoid
1131  * thinking about kerning issues and rounding issues in the justification.
1132  */
1133
1134 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1135                                    INT maxExt, LPINT lpnFit,
1136                                    LPINT alpDx, LPSIZE size )
1137 {
1138     int index, nFit, extent;
1139     SIZE tSize;
1140     BOOL ret = FALSE;
1141
1142     TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1143
1144     size->cx = size->cy = nFit = extent = 0;
1145     for(index = 0; index < count; index++)
1146     {
1147         if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1148         /* GetTextExtentPoint includes intercharacter spacing. */
1149         /* FIXME - justification needs doing yet.  Remember that the base
1150          * data will not be in logical coordinates.
1151          */
1152         extent += tSize.cx;
1153         if( !lpnFit || extent <= maxExt )
1154         /* It is allowed to be equal. */
1155         {
1156             nFit++;
1157             if( alpDx ) alpDx[index] = extent;
1158         }
1159         if( tSize.cy > size->cy ) size->cy = tSize.cy;
1160         str++;
1161     }
1162     size->cx = extent;
1163     if(lpnFit) *lpnFit = nFit;
1164     ret = TRUE;
1165
1166     TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1167
1168 done:
1169     return ret;
1170 }
1171
1172 /***********************************************************************
1173  *           GetTextMetricsA    (GDI32.@)
1174  */
1175 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1176 {
1177     TEXTMETRICW tm32;
1178
1179     if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1180     FONT_TextMetricWToA( &tm32, metrics );
1181     return TRUE;
1182 }
1183
1184 /***********************************************************************
1185  *           GetTextMetricsW    (GDI32.@)
1186  */
1187 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1188 {
1189     BOOL ret = FALSE;
1190     DC * dc = DC_GetDCPtr( hdc );
1191     if (!dc) return FALSE;
1192
1193     if (dc->gdiFont)
1194         ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1195     else if (dc->funcs->pGetTextMetrics)
1196         ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1197
1198     if (ret)
1199     {
1200     /* device layer returns values in device units
1201      * therefore we have to convert them to logical */
1202
1203 #define WDPTOLP(x) ((x<0)?                                      \
1204                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1205                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1206 #define HDPTOLP(y) ((y<0)?                                      \
1207                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1208                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1209
1210     metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
1211     metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
1212     metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
1213     metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
1214     metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
1215     metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
1216     metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
1217     metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
1218         ret = TRUE;
1219 #undef WDPTOLP
1220 #undef HDPTOLP
1221     TRACE("text metrics:\n"
1222           "    Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1223           "    Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1224           "    UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1225           "    StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1226           "    PitchAndFamily = %02x\n"
1227           "    --------------------\n"
1228           "    InternalLeading = %li\n"
1229           "    Ascent = %li\n"
1230           "    Descent = %li\n"
1231           "    Height = %li\n",
1232           metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1233           metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1234           metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1235           metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1236           metrics->tmPitchAndFamily,
1237           metrics->tmInternalLeading,
1238           metrics->tmAscent,
1239           metrics->tmDescent,
1240           metrics->tmHeight );
1241     }
1242     GDI_ReleaseObj( hdc );
1243     return ret;
1244 }
1245
1246
1247 /***********************************************************************
1248  * GetOutlineTextMetrics [GDI.308]  Gets metrics for TrueType fonts.
1249  *
1250  * NOTES
1251  *    lpOTM should be LPOUTLINETEXTMETRIC
1252  *
1253  * RETURNS
1254  *    Success: Non-zero or size of required buffer
1255  *    Failure: 0
1256  */
1257 UINT16 WINAPI GetOutlineTextMetrics16(
1258     HDC16 hdc,    /* [in]  Handle of device context */
1259     UINT16 cbData, /* [in]  Size of metric data array */
1260     LPOUTLINETEXTMETRIC16 lpOTM)  /* [out] Address of metric data array */
1261 {
1262     FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1263     return 0;
1264 }
1265
1266
1267 /***********************************************************************
1268  *              GetOutlineTextMetricsA (GDI32.@)
1269  * Gets metrics for TrueType fonts.
1270  *
1271  * NOTES
1272  *    If the supplied buffer isn't big enough Windows partially fills it up to
1273  *    its given length and returns that length.
1274  *
1275  * RETURNS
1276  *    Success: Non-zero or size of required buffer
1277  *    Failure: 0
1278  */
1279 UINT WINAPI GetOutlineTextMetricsA(
1280     HDC hdc,    /* [in]  Handle of device context */
1281     UINT cbData, /* [in]  Size of metric data array */
1282     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1283 {
1284     char buf[512], *ptr;
1285     UINT ret, needed;
1286     OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1287     OUTLINETEXTMETRICA *output = lpOTM;
1288     INT left, len;
1289
1290     if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1291         return 0;
1292     if(ret > sizeof(buf))
1293         lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1294     GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1295
1296     needed = sizeof(OUTLINETEXTMETRICA);
1297     if(lpOTMW->otmpFamilyName)
1298         needed += WideCharToMultiByte(CP_ACP, 0,
1299            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1300                                       NULL, 0, NULL, NULL);
1301     if(lpOTMW->otmpFaceName)
1302         needed += WideCharToMultiByte(CP_ACP, 0,
1303            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1304                                       NULL, 0, NULL, NULL);
1305     if(lpOTMW->otmpStyleName)
1306         needed += WideCharToMultiByte(CP_ACP, 0,
1307            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1308                                       NULL, 0, NULL, NULL);
1309     if(lpOTMW->otmpFullName)
1310         needed += WideCharToMultiByte(CP_ACP, 0,
1311            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1312                                       NULL, 0, NULL, NULL);
1313
1314     if(!lpOTM) {
1315         ret = needed;
1316         goto end;
1317     }
1318
1319     TRACE("needed = %d\n", needed);
1320     if(needed > cbData)
1321         /* Since the supplied buffer isn't big enough, we'll alloc one
1322            that is and memcpy the first cbData bytes into the lpOTM at
1323            the end. */
1324         output = HeapAlloc(GetProcessHeap(), 0, needed);
1325
1326     ret = output->otmSize = min(needed, cbData);
1327     FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1328     output->otmFiller = 0;
1329     output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1330     output->otmfsSelection = lpOTMW->otmfsSelection;
1331     output->otmfsType = lpOTMW->otmfsType;
1332     output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1333     output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1334     output->otmItalicAngle = lpOTMW->otmItalicAngle;
1335     output->otmEMSquare = lpOTMW->otmEMSquare;
1336     output->otmAscent = lpOTMW->otmAscent;
1337     output->otmDescent = lpOTMW->otmDescent;
1338     output->otmLineGap = lpOTMW->otmLineGap;
1339     output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1340     output->otmsXHeight = lpOTMW->otmsXHeight;
1341     output->otmrcFontBox = lpOTMW->otmrcFontBox;
1342     output->otmMacAscent = lpOTMW->otmMacAscent;
1343     output->otmMacDescent = lpOTMW->otmMacDescent;
1344     output->otmMacLineGap = lpOTMW->otmMacLineGap;
1345     output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1346     output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1347     output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1348     output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1349     output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1350     output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1351     output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1352     output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1353     output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1354
1355
1356     ptr = (char*)(output + 1);
1357     left = needed - sizeof(*output);
1358
1359     if(lpOTMW->otmpFamilyName) {
1360         output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1361         len = WideCharToMultiByte(CP_ACP, 0,
1362              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1363                                   ptr, left, NULL, NULL);
1364         left -= len;
1365         ptr += len;
1366     } else
1367         output->otmpFamilyName = 0;
1368
1369     if(lpOTMW->otmpFaceName) {
1370         output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1371         len = WideCharToMultiByte(CP_ACP, 0,
1372              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1373                                   ptr, left, NULL, NULL);
1374         left -= len;
1375         ptr += len;
1376     } else
1377         output->otmpFaceName = 0;
1378
1379     if(lpOTMW->otmpStyleName) {
1380         output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1381         len = WideCharToMultiByte(CP_ACP, 0,
1382              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1383                                   ptr, left, NULL, NULL);
1384         left -= len;
1385         ptr += len;
1386     } else
1387         output->otmpStyleName = 0;
1388
1389     if(lpOTMW->otmpFullName) {
1390         output->otmpFullName = (LPSTR)(ptr - (char*)output);
1391         len = WideCharToMultiByte(CP_ACP, 0,
1392              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1393                                   ptr, left, NULL, NULL);
1394         left -= len;
1395     } else
1396         output->otmpFullName = 0;
1397
1398     assert(left == 0);
1399
1400     if(output != lpOTM) {
1401         memcpy(lpOTM, output, cbData);
1402         HeapFree(GetProcessHeap(), 0, output);
1403     }
1404
1405 end:
1406     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1407         HeapFree(GetProcessHeap(), 0, lpOTMW);
1408
1409     return ret;
1410 }
1411
1412
1413 /***********************************************************************
1414  *           GetOutlineTextMetricsW [GDI32.@]
1415  */
1416 UINT WINAPI GetOutlineTextMetricsW(
1417     HDC hdc,    /* [in]  Handle of device context */
1418     UINT cbData, /* [in]  Size of metric data array */
1419     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1420 {
1421     DC *dc = DC_GetDCPtr( hdc );
1422     OUTLINETEXTMETRICW *output = lpOTM;
1423     UINT ret;
1424
1425     TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1426     if(!dc) return 0;
1427
1428     if(dc->gdiFont) {
1429         ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1430         if(lpOTM && ret) {
1431             if(ret > cbData) {
1432                 output = HeapAlloc(GetProcessHeap(), 0, ret);
1433                 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1434             }
1435
1436 #define WDPTOLP(x) ((x<0)?                                      \
1437                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1438                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1439 #define HDPTOLP(y) ((y<0)?                                      \
1440                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1441                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1442
1443             output->otmTextMetrics.tmHeight           = HDPTOLP(output->otmTextMetrics.tmHeight);
1444             output->otmTextMetrics.tmAscent           = HDPTOLP(output->otmTextMetrics.tmAscent);
1445             output->otmTextMetrics.tmDescent          = HDPTOLP(output->otmTextMetrics.tmDescent);
1446             output->otmTextMetrics.tmInternalLeading  = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1447             output->otmTextMetrics.tmExternalLeading  = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1448             output->otmTextMetrics.tmAveCharWidth     = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1449             output->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1450             output->otmTextMetrics.tmOverhang         = WDPTOLP(output->otmTextMetrics.tmOverhang);
1451             output->otmAscent = HDPTOLP(output->otmAscent);
1452             output->otmDescent = HDPTOLP(output->otmDescent);
1453             output->otmLineGap = HDPTOLP(output->otmLineGap);
1454             output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1455             output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1456             output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1457             output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1458             output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1459             output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1460             output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1461             output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1462             output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1463             output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1464             output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1465             output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1466             output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1467             output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1468             output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1469             output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1470             output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1471             output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1472             output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1473             output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1474             output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1475 #undef WDPTOLP
1476 #undef HDPTOLP
1477             if(output != lpOTM) {
1478                 memcpy(lpOTM, output, cbData);
1479                 HeapFree(GetProcessHeap(), 0, output);
1480                 ret = cbData;
1481             }
1482         }
1483     }
1484
1485     else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1486               but really this should just be a return 0. */
1487
1488         ret = sizeof(*lpOTM);
1489         if (lpOTM) {
1490             if(cbData < ret)
1491                 ret = 0;
1492             else {
1493                 memset(lpOTM, 0, ret);
1494                 lpOTM->otmSize = sizeof(*lpOTM);
1495                 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1496                 /*
1497                   Further fill of the structure not implemented,
1498                   Needs real values for the structure members
1499                 */
1500             }
1501         }
1502     }
1503     GDI_ReleaseObj(hdc);
1504     return ret;
1505 }
1506
1507
1508 /***********************************************************************
1509  *           GetCharWidthW      (GDI32.@)
1510  *           GetCharWidth32W    (GDI32.@)
1511  */
1512 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1513                                LPINT buffer )
1514 {
1515     UINT i;
1516     BOOL ret = FALSE;
1517     DC * dc = DC_GetDCPtr( hdc );
1518     if (!dc) return FALSE;
1519
1520     if (dc->gdiFont)
1521         ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1522     else if (dc->funcs->pGetCharWidth)
1523         ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1524
1525     if (ret)
1526     {
1527         /* convert device units to logical */
1528         for( i = firstChar; i <= lastChar; i++, buffer++ )
1529             *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1530         ret = TRUE;
1531     }
1532     GDI_ReleaseObj( hdc );
1533     return ret;
1534 }
1535
1536
1537 /***********************************************************************
1538  *           GetCharWidthA      (GDI32.@)
1539  *           GetCharWidth32A    (GDI32.@)
1540  */
1541 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1542                                LPINT buffer )
1543 {
1544     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1545     LPSTR str;
1546     LPWSTR wstr;
1547     BOOL ret = TRUE;
1548
1549     if(count <= 0) return FALSE;
1550
1551     str = HeapAlloc(GetProcessHeap(), 0, count);
1552     for(i = 0; i < count; i++)
1553         str[i] = (BYTE)(firstChar + i);
1554
1555     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1556
1557     for(i = 0; i < wlen; i++)
1558     {
1559         if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1560         {
1561             ret = FALSE;
1562             break;
1563         }
1564         buffer++;
1565     }
1566
1567     HeapFree(GetProcessHeap(), 0, str);
1568     HeapFree(GetProcessHeap(), 0, wstr);
1569
1570     return ret;
1571 }
1572
1573
1574 /* FIXME: all following APIs ******************************************/
1575
1576
1577 /***********************************************************************
1578  *           SetMapperFlags    (GDI32.@)
1579  */
1580 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1581 {
1582     DC *dc = DC_GetDCPtr( hDC );
1583     DWORD ret = 0;
1584     if(!dc) return 0;
1585     if(dc->funcs->pSetMapperFlags)
1586         ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
1587     else
1588         FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1589     GDI_ReleaseObj( hDC );
1590     return ret;
1591 }
1592
1593 /***********************************************************************
1594  *          GetAspectRatioFilterEx  (GDI.486)
1595  */
1596 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1597 {
1598   FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1599   return FALSE;
1600 }
1601
1602 /***********************************************************************
1603  *          GetAspectRatioFilterEx  (GDI32.@)
1604  */
1605 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1606 {
1607   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1608   return FALSE;
1609 }
1610
1611
1612 /***********************************************************************
1613  *           GetCharABCWidthsA   (GDI32.@)
1614  */
1615 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1616                                   LPABC abc )
1617 {
1618     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1619     LPSTR str;
1620     LPWSTR wstr;
1621     BOOL ret = TRUE;
1622
1623     if(count <= 0) return FALSE;
1624
1625     str = HeapAlloc(GetProcessHeap(), 0, count);
1626     for(i = 0; i < count; i++)
1627         str[i] = (BYTE)(firstChar + i);
1628
1629     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1630
1631     for(i = 0; i < wlen; i++)
1632     {
1633         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
1634         {
1635             ret = FALSE;
1636             break;
1637         }
1638         abc++;
1639     }
1640
1641     HeapFree(GetProcessHeap(), 0, str);
1642     HeapFree(GetProcessHeap(), 0, wstr);
1643
1644     return ret;
1645 }
1646
1647
1648 /******************************************************************************
1649  * GetCharABCWidthsW [GDI32.@]
1650  *
1651  * Retrieves widths of characters in range.
1652  *
1653  * PARAMS
1654  *    hdc       [I] Handle of device context
1655  *    firstChar [I] First character in range to query
1656  *    lastChar  [I] Last character in range to query
1657  *    abc       [O] Address of character-width structure
1658  *
1659  * NOTES
1660  *    Only works with TrueType fonts
1661  *
1662  * RETURNS
1663  *    Success: TRUE
1664  *    Failure: FALSE
1665  */
1666 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1667                                    LPABC abc )
1668 {
1669     DC *dc = DC_GetDCPtr(hdc);
1670     int i;
1671     BOOL ret = FALSE;
1672
1673     if(dc->gdiFont)
1674         ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
1675     else
1676         FIXME(": stub\n");
1677
1678     if (ret)
1679     {
1680         /* convert device units to logical */
1681         for( i = firstChar; i <= lastChar; i++, abc++ ) {
1682             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
1683             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
1684             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
1685         }
1686         ret = TRUE;
1687     }
1688
1689     GDI_ReleaseObj(hdc);
1690     return ret;
1691 }
1692
1693
1694 /***********************************************************************
1695  *           GetGlyphOutline    (GDI.309)
1696  */
1697 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1698                                 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1699                                 LPVOID lpBuffer, const MAT2 *lpmat2 )
1700 {
1701     FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1702           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1703     return ~0UL; /* failure */
1704 }
1705
1706
1707 /***********************************************************************
1708  *           GetGlyphOutlineA    (GDI32.@)
1709  */
1710 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1711                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1712                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
1713 {
1714     LPWSTR p = NULL;
1715     DWORD ret;
1716     UINT c;
1717
1718     if(!(fuFormat & GGO_GLYPH_INDEX)) {
1719         p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL);
1720         c = p[0];
1721     } else
1722         c = uChar;
1723     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
1724                            lpmat2);
1725     if(p)
1726         HeapFree(GetProcessHeap(), 0, p);
1727     return ret;
1728 }
1729
1730 /***********************************************************************
1731  *           GetGlyphOutlineW    (GDI32.@)
1732  */
1733 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1734                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1735                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
1736 {
1737     DC *dc = DC_GetDCPtr(hdc);
1738     DWORD ret;
1739
1740     TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
1741           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1742
1743     if(!dc) return GDI_ERROR;
1744
1745     if(dc->gdiFont)
1746       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
1747                                    cbBuffer, lpBuffer, lpmat2);
1748     else
1749       ret = GDI_ERROR;
1750
1751     GDI_ReleaseObj(hdc);
1752     return ret;
1753 }
1754
1755
1756 /***********************************************************************
1757  *           CreateScalableFontResourceA   (GDI32.@)
1758  */
1759 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1760                                              LPCSTR lpszResourceFile,
1761                                              LPCSTR lpszFontFile,
1762                                              LPCSTR lpszCurrentPath )
1763 {
1764     HANDLE f;
1765
1766     /* fHidden=1 - only visible for the calling app, read-only, not
1767      * enumbered with EnumFonts/EnumFontFamilies
1768      * lpszCurrentPath can be NULL
1769      */
1770     FIXME("(%ld,%s,%s,%s): stub\n",
1771           fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
1772           debugstr_a(lpszCurrentPath) );
1773
1774     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
1775     if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
1776         CloseHandle(f);
1777         SetLastError(ERROR_FILE_EXISTS);
1778         return FALSE;
1779     }
1780     return FALSE; /* create failed */
1781 }
1782
1783 /***********************************************************************
1784  *           CreateScalableFontResourceW   (GDI32.@)
1785  */
1786 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1787                                              LPCWSTR lpszResourceFile,
1788                                              LPCWSTR lpszFontFile,
1789                                              LPCWSTR lpszCurrentPath )
1790 {
1791     FIXME("(%ld,%p,%p,%p): stub\n",
1792           fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1793     return FALSE; /* create failed */
1794 }
1795
1796
1797 /*************************************************************************
1798  *             GetRasterizerCaps   (GDI32.@)
1799  */
1800 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1801 {
1802   lprs->nSize = sizeof(RASTERIZER_STATUS);
1803   lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
1804   lprs->nLanguageID = 0;
1805   return TRUE;
1806 }
1807
1808
1809 /*************************************************************************
1810  *             GetKerningPairsA   (GDI32.@)
1811  */
1812 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
1813                                LPKERNINGPAIR lpKerningPairs )
1814 {
1815     return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
1816 }
1817
1818
1819 /*************************************************************************
1820  *             GetKerningPairsW   (GDI32.@)
1821  */
1822 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
1823                                  LPKERNINGPAIR lpKerningPairs )
1824 {
1825     int i;
1826     FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
1827     for (i = 0; i < cPairs; i++)
1828         lpKerningPairs[i].iKernAmount = 0;
1829     return 0;
1830 }
1831
1832 /*************************************************************************
1833  * TranslateCharsetInfo [GDI32.@]
1834  *
1835  * Fills a CHARSETINFO structure for a character set, code page, or
1836  * font. This allows making the correspondance between different labelings
1837  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1838  * of the same encoding.
1839  *
1840  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1841  * only one codepage should be set in *lpSrc.
1842  *
1843  * RETURNS
1844  *   TRUE on success, FALSE on failure.
1845  *
1846  */
1847 BOOL WINAPI TranslateCharsetInfo(
1848   LPDWORD lpSrc, /* [in]
1849        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1850        if flags == TCI_SRCCHARSET: a character set value
1851        if flags == TCI_SRCCODEPAGE: a code page value
1852                  */
1853   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1854   DWORD flags /* [in] determines interpretation of lpSrc */)
1855 {
1856     int index = 0;
1857     switch (flags) {
1858     case TCI_SRCFONTSIG:
1859         while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1860       break;
1861     case TCI_SRCCODEPAGE:
1862       while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1863       break;
1864     case TCI_SRCCHARSET:
1865       while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1866       break;
1867     default:
1868       return FALSE;
1869     }
1870     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1871     memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1872     return TRUE;
1873 }
1874
1875 /*************************************************************************
1876  *             GetFontLanguageInfo   (GDI32.@)
1877  */
1878 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
1879 {
1880         FONTSIGNATURE fontsig;
1881         static const DWORD GCP_DBCS_MASK=0x003F0000,
1882                 GCP_DIACRITIC_MASK=0x00000000,
1883                 FLI_GLYPHS_MASK=0x00000000,
1884                 GCP_GLYPHSHAPE_MASK=0x00000040,
1885                 GCP_KASHIDA_MASK=0x00000000,
1886                 GCP_LIGATE_MASK=0x00000000,
1887                 GCP_USEKERNING_MASK=0x00000000,
1888                 GCP_REORDER_MASK=0x00000060;
1889
1890         DWORD result=0;
1891
1892         GetTextCharsetInfo( hdc, &fontsig, 0 );
1893         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
1894
1895         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
1896                 result|=GCP_DBCS;
1897
1898         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
1899                 result|=GCP_DIACRITIC;
1900
1901         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
1902                 result|=FLI_GLYPHS;
1903
1904         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
1905                 result|=GCP_GLYPHSHAPE;
1906
1907         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
1908                 result|=GCP_KASHIDA;
1909
1910         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
1911                 result|=GCP_LIGATE;
1912
1913         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
1914                 result|=GCP_USEKERNING;
1915
1916         if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
1917                 result|=GCP_REORDER;
1918
1919         return result;
1920 }
1921
1922
1923 /*************************************************************************
1924  * GetFontData [GDI32.@]
1925  *
1926  * Retrieve data for TrueType font.
1927  *
1928  * RETURNS
1929  *
1930  * success: Number of bytes returned
1931  * failure: GDI_ERROR
1932  *
1933  * NOTES
1934  *
1935  * Calls SetLastError()
1936  *
1937  */
1938 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
1939     LPVOID buffer, DWORD length)
1940 {
1941     DC *dc = DC_GetDCPtr(hdc);
1942     DWORD ret = GDI_ERROR;
1943
1944     if(!dc) return GDI_ERROR;
1945
1946     if(dc->gdiFont)
1947       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
1948
1949     GDI_ReleaseObj(hdc);
1950     return ret;
1951 }
1952
1953 /*************************************************************************
1954  * GetGlyphIndicesA [GDI32.@]
1955  */
1956 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
1957                               LPWORD pgi, DWORD flags)
1958 {
1959     DWORD ret;
1960     WCHAR *lpstrW;
1961     INT countW;
1962
1963     TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1964           hdc, debugstr_an(lpstr, count), count, pgi, flags);
1965
1966     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
1967     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
1968     HeapFree(GetProcessHeap(), 0, lpstrW);
1969
1970     return ret;
1971 }
1972
1973 /*************************************************************************
1974  * GetGlyphIndicesW [GDI32.@]
1975  */
1976 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
1977                               LPWORD pgi, DWORD flags)
1978 {
1979     DC *dc = DC_GetDCPtr(hdc);
1980     DWORD ret = GDI_ERROR;
1981
1982     TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1983           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
1984
1985     if(!dc) return GDI_ERROR;
1986
1987     if(dc->gdiFont)
1988         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
1989
1990     GDI_ReleaseObj(hdc);
1991     return ret;
1992 }
1993
1994 /*************************************************************************
1995  * GetCharacterPlacementA [GDI32.@]
1996  *
1997  * NOTES:
1998  *  the web browser control of ie4 calls this with dwFlags=0
1999  */
2000 DWORD WINAPI
2001 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2002                          INT nMaxExtent, GCP_RESULTSA *lpResults,
2003                          DWORD dwFlags)
2004 {
2005     WCHAR *lpStringW;
2006     INT uCountW;
2007     GCP_RESULTSW resultsW;
2008     DWORD ret;
2009     UINT font_cp;
2010
2011     TRACE("%s, %d, %d, 0x%08lx\n",
2012           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2013
2014     /* both structs are equal in size */
2015     memcpy(&resultsW, lpResults, sizeof(resultsW));
2016
2017     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2018     if(lpResults->lpOutString)
2019         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2020
2021     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2022
2023     if(lpResults->lpOutString) {
2024         WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2025                             lpResults->lpOutString, uCount, NULL, NULL );
2026     }
2027
2028     HeapFree(GetProcessHeap(), 0, lpStringW);
2029     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2030
2031     return ret;
2032 }
2033
2034 /*************************************************************************
2035  * GetCharacterPlacementW [GDI32.@]
2036  *
2037  *   Retrieve information about a string. This includes the width, reordering,
2038  *   Glyphing and so on.
2039  *
2040  * RETURNS
2041  *
2042  *   The width and height of the string if successful, 0 if failed.
2043  *
2044  * BUGS
2045  *
2046  *   All flags except GCP_REORDER are not yet implemented.
2047  *   Reordering is not 100% complient to the Windows BiDi method.
2048  *   Caret positioning is not yet implemented for BiDi.
2049  *   Classes are not yet implemented.
2050  *
2051  */
2052 DWORD WINAPI
2053 GetCharacterPlacementW(
2054                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
2055                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
2056                 INT uCount,             /* [in] Number of WORDS in string. */
2057                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
2058                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2059                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
2060                 )
2061 {
2062     DWORD ret=0;
2063     SIZE size;
2064     UINT i, nSet;
2065
2066     TRACE("%s, %d, %d, 0x%08lx\n",
2067           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2068
2069     TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2070           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2071             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2072             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2073             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2074
2075     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08lx ignored\n", dwFlags);
2076     if(lpResults->lpClass)      FIXME("classes not implemented\n");
2077     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2078         FIXME("Caret positions for complex scripts not implemented\n");
2079
2080         nSet = (UINT)uCount;
2081         if(nSet > lpResults->nGlyphs)
2082                 nSet = lpResults->nGlyphs;
2083
2084         /* return number of initialized fields */
2085         lpResults->nGlyphs = nSet;
2086
2087         if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2088         {
2089                 /* Treat the case where no special handling was requested in a fastpath way */
2090                 /* copy will do if the GCP_REORDER flag is not set */
2091                 if(lpResults->lpOutString)
2092                     strncpyW( lpResults->lpOutString, lpString, nSet );
2093
2094                 if(lpResults->lpOrder)
2095                 {
2096                         for(i = 0; i < nSet; i++)
2097                                 lpResults->lpOrder[i] = i;
2098                 }
2099         } else
2100         {
2101             BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2102                           nSet, lpResults->lpOrder );
2103         }
2104
2105         /* FIXME: Will use the placement chars */
2106         if (lpResults->lpDx)
2107         {
2108                 int c;
2109                 for (i = 0; i < nSet; i++)
2110                 {
2111                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2112                                 lpResults->lpDx[i]= c;
2113                 }
2114         }
2115
2116     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2117     {
2118         int pos = 0;
2119        
2120         lpResults->lpCaretPos[0] = 0;
2121         for (i = 1; i < nSet; i++)
2122             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2123                 lpResults->lpCaretPos[i] = (pos += size.cx);
2124     }
2125    
2126     if(lpResults->lpGlyphs)
2127         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2128
2129     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2130       ret = MAKELONG(size.cx, size.cy);
2131
2132     return ret;
2133 }
2134
2135 /*************************************************************************
2136  *      GetCharABCWidthsFloatA [GDI32.@]
2137  */
2138 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2139                                         LPABCFLOAT lpABCF)
2140 {
2141        FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2142        return 0;
2143 }
2144
2145 /*************************************************************************
2146  *      GetCharABCWidthsFloatW [GDI32.@]
2147  */
2148 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2149                                         UINT iLastChar, LPABCFLOAT lpABCF)
2150 {
2151        FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2152        return 0;
2153 }
2154
2155 /*************************************************************************
2156  *      GetCharWidthFloatA [GDI32.@]
2157  */
2158 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2159                                     UINT iLastChar, PFLOAT pxBuffer)
2160 {
2161        FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2162        return 0;
2163 }
2164
2165 /*************************************************************************
2166  *      GetCharWidthFloatW [GDI32.@]
2167  */
2168 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2169                                     UINT iLastChar, PFLOAT pxBuffer)
2170 {
2171        FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2172        return 0;
2173 }
2174
2175
2176 /***********************************************************************
2177  *                                                                     *
2178  *           Font Resource API                                         *
2179  *                                                                     *
2180  ***********************************************************************/
2181
2182 /***********************************************************************
2183  *           AddFontResourceA    (GDI32.@)
2184  */
2185 INT WINAPI AddFontResourceA( LPCSTR str )
2186 {
2187     return AddFontResourceExA( str, 0, NULL);
2188 }
2189
2190 /***********************************************************************
2191  *           AddFontResourceW    (GDI32.@)
2192  */
2193 INT WINAPI AddFontResourceW( LPCWSTR str )
2194 {
2195     return AddFontResourceExW(str, 0, NULL);
2196 }
2197
2198
2199 /***********************************************************************
2200  *           AddFontResourceExA    (GDI32.@)
2201  */
2202 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2203 {
2204     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2205     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2206     INT ret;
2207
2208     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2209     ret = AddFontResourceExW(strW, fl, pdv);
2210     HeapFree(GetProcessHeap(), 0, strW);
2211     return ret;
2212 }
2213
2214 /***********************************************************************
2215  *           AddFontResourceExW    (GDI32.@)
2216  */
2217 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2218 {
2219     return WineEngAddFontResourceEx(str, fl, pdv);
2220 }
2221
2222 /***********************************************************************
2223  *           RemoveFontResourceA    (GDI32.@)
2224  */
2225 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2226 {
2227     return RemoveFontResourceExA(str, 0, 0);
2228 }
2229
2230 /***********************************************************************
2231  *           RemoveFontResourceW    (GDI32.@)
2232  */
2233 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2234 {
2235     return RemoveFontResourceExW(str, 0, 0);
2236 }
2237
2238 /***********************************************************************
2239  *           RemoveFontResourceExA    (GDI32.@)
2240  */
2241 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2242 {
2243     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2244     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2245     INT ret;
2246
2247     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2248     ret = RemoveFontResourceExW(strW, fl, pdv);
2249     HeapFree(GetProcessHeap(), 0, strW);
2250     return ret;
2251 }
2252
2253 /***********************************************************************
2254  *           RemoveFontResourceExW    (GDI32.@)
2255  */
2256 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2257 {
2258     return WineEngRemoveFontResourceEx(str, fl, pdv);
2259 }
2260
2261 /***********************************************************************
2262  *           GetTextCharset    (GDI32.@)
2263  */
2264 UINT WINAPI GetTextCharset(HDC hdc)
2265 {
2266     /* MSDN docs say this is equivalent */
2267     return GetTextCharsetInfo(hdc, NULL, 0);
2268 }
2269
2270 /***********************************************************************
2271  *           GetTextCharsetInfo    (GDI32.@)
2272  */
2273 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
2274 {
2275     UINT ret = DEFAULT_CHARSET;
2276     DC *dc = DC_GetDCPtr(hdc);
2277
2278     if (!dc) goto done;
2279
2280     if (dc->gdiFont)
2281         ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
2282
2283     GDI_ReleaseObj(hdc);
2284
2285 done:
2286     if (ret == DEFAULT_CHARSET && fs)
2287         memset(fs, 0, sizeof(FONTSIGNATURE));
2288     return ret;
2289 }