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