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