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