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