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