gdi32/tests: GetTextFaceA called with a NULL buffer returns 0 on win98 and winMe.
[wine] / dlls / gdi32 / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1997 Alex Korobka
6  * Copyright 2002,2003 Shachar Shemesh
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "wownt32.h"
35 #include "gdi_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
40
41   /* Device -> World size conversion */
42
43 /* Performs a device to world transformation on the specified width (which
44  * is in integer format).
45  */
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
47 {
48     double floatWidth;
49
50     /* Perform operation with floating point */
51     floatWidth = (double)width * dc->xformVport2World.eM11;
52     /* Round to integers */
53     return GDI_ROUND(floatWidth);
54 }
55
56 /* Performs a device to world transformation on the specified size (which
57  * is in integer format).
58  */
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
60 {
61     double floatHeight;
62
63     /* Perform operation with floating point */
64     floatHeight = (double)height * dc->xformVport2World.eM22;
65     /* Round to integers */
66     return GDI_ROUND(floatHeight);
67 }
68
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
70 {
71     POINT pt[2];
72     pt[0].x = pt[0].y = 0;
73     pt[1].x = width;
74     pt[1].y = 0;
75     LPtoDP(dc->hSelf, pt, 2);
76     return pt[1].x - pt[0].x;
77 }
78
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
80 {
81     POINT pt[2];
82     pt[0].x = pt[0].y = 0;
83     pt[1].x = 0;
84     pt[1].y = height;
85     LPtoDP(dc->hSelf, pt, 2);
86     return pt[1].y - pt[0].y;
87 }
88
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle );
93
94 static const struct gdi_obj_funcs font_funcs =
95 {
96     FONT_SelectObject,  /* pSelectObject */
97     FONT_GetObjectA,    /* pGetObjectA */
98     FONT_GetObjectW,    /* pGetObjectW */
99     NULL,               /* pUnrealizeObject */
100     FONT_DeleteObject   /* pDeleteObject */
101 };
102
103 #define ENUM_UNICODE    0x00000001
104 #define ENUM_CALLED     0x00000002
105
106 typedef struct
107 {
108     GDIOBJHDR   header;
109     LOGFONTW    logfont;
110 } FONTOBJ;
111
112 typedef struct
113 {
114   LPLOGFONTW          lpLogFontParam;
115   FONTENUMPROCW       lpEnumFunc;
116   LPARAM              lpData;
117   DWORD               dwFlags;
118   HDC                 hdc;
119 } fontEnum32;
120
121 /*
122  *  For TranslateCharsetInfo
123  */
124 #define MAXTCIINDEX 32
125 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
126   /* ANSI */
127   { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
128   { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
129   { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
130   { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
131   { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
132   { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
133   { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
134   { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
135   { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
136   /* reserved by ANSI */
137   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
142   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
144   /* ANSI and OEM */
145   { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
146   { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
147   { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
148   { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
149   { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
150   { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
151   /* reserved for alternate ANSI and OEM */
152   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160   /* reserved for system */
161   { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162   { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
163 };
164
165 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
166 {
167     memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
168     MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
169                         LF_FACESIZE);
170     fontW->lfFaceName[LF_FACESIZE-1] = 0;
171 }
172
173 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
174 {
175     memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
176     WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
177                         LF_FACESIZE, NULL, NULL);
178     fontA->lfFaceName[LF_FACESIZE-1] = 0;
179 }
180
181 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
182 {
183     FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
184
185     WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
186                          (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
187     fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
188     WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
189                          (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
190     fontA->elfStyle[LF_FACESIZE-1] = '\0';
191     WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
192                          (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
193     fontA->elfScript[LF_FACESIZE-1] = '\0';
194 }
195
196 /***********************************************************************
197  *              TEXTMETRIC conversion functions.
198  */
199 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
200 {
201     ptmA->tmHeight = ptmW->tmHeight;
202     ptmA->tmAscent = ptmW->tmAscent;
203     ptmA->tmDescent = ptmW->tmDescent;
204     ptmA->tmInternalLeading = ptmW->tmInternalLeading;
205     ptmA->tmExternalLeading = ptmW->tmExternalLeading;
206     ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
207     ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
208     ptmA->tmWeight = ptmW->tmWeight;
209     ptmA->tmOverhang = ptmW->tmOverhang;
210     ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
211     ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
212     ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
213     if (ptmW->tmCharSet == SYMBOL_CHARSET)
214     {
215         ptmA->tmFirstChar = 0x1e;
216         ptmA->tmLastChar = 0xff;  /* win9x behaviour - we need the OS2 table data to calculate correctly */
217     }
218     else
219     {
220         ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
221         ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
222     }
223     ptmA->tmDefaultChar = ptmW->tmDefaultChar;
224     ptmA->tmBreakChar = ptmW->tmBreakChar;
225     ptmA->tmItalic = ptmW->tmItalic;
226     ptmA->tmUnderlined = ptmW->tmUnderlined;
227     ptmA->tmStruckOut = ptmW->tmStruckOut;
228     ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
229     ptmA->tmCharSet = ptmW->tmCharSet;
230 }
231
232
233 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
234 {
235     FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
236     ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
237     ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
238     ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
239     ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
240     memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
241 }
242
243
244 /***********************************************************************
245  *           GdiGetCodePage   (GDI32.@)
246  */
247 DWORD WINAPI GdiGetCodePage( HDC hdc )
248 {
249     UINT cp = CP_ACP;
250     CHARSETINFO csi;
251     int charset = GetTextCharset(hdc);
252
253     /* Hmm, nicely designed api this one! */
254     if(TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
255         cp = csi.ciACP;
256     else {
257         switch(charset) {
258         case OEM_CHARSET:
259             cp = GetOEMCP();
260             break;
261         case DEFAULT_CHARSET:
262             cp = GetACP();
263             break;
264
265         case VISCII_CHARSET:
266         case TCVN_CHARSET:
267         case KOI8_CHARSET:
268         case ISO3_CHARSET:
269         case ISO4_CHARSET:
270         case ISO10_CHARSET:
271         case CELTIC_CHARSET:
272             /* FIXME: These have no place here, but because x11drv
273                enumerates fonts with these (made up) charsets some apps
274                might use them and then the FIXME below would become
275                annoying.  Now we could pick the intended codepage for
276                each of these, but since it's broken anyway we'll just
277                use CP_ACP and hope it'll go away...
278             */
279             cp = CP_ACP;
280             break;
281
282         default:
283             FIXME("Can't find codepage for charset %d\n", charset);
284             break;
285         }
286     }
287
288     TRACE("charset %d => cp %d\n", charset, cp);
289     return cp;
290 }
291
292 /***********************************************************************
293  *           FONT_mbtowc
294  *
295  * Returns a Unicode translation of str using the charset of the
296  * currently selected font in hdc.  If count is -1 then str is assumed
297  * to be '\0' terminated, otherwise it contains the number of bytes to
298  * convert.  If plenW is non-NULL, on return it will point to the
299  * number of WCHARs that have been written.  If pCP is non-NULL, on
300  * return it will point to the codepage used in the conversion.  The
301  * caller should free the returned LPWSTR from the process heap
302  * itself.
303  */
304 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
305 {
306     UINT cp;
307     INT lenW;
308     LPWSTR strW;
309
310     cp = GdiGetCodePage( hdc );
311
312     if(count == -1) count = strlen(str);
313     lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
314     strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
315     MultiByteToWideChar(cp, 0, str, count, strW, lenW);
316     TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
317     if(plenW) *plenW = lenW;
318     if(pCP) *pCP = cp;
319     return strW;
320 }
321
322
323 /***********************************************************************
324  *           CreateFontIndirectA   (GDI32.@)
325  */
326 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
327 {
328     LOGFONTW lfW;
329
330     if (!plfA) return 0;
331
332     FONT_LogFontAToW( plfA, &lfW );
333     return CreateFontIndirectW( &lfW );
334 }
335
336 /***********************************************************************
337  *           CreateFontIndirectW   (GDI32.@)
338  */
339 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
340 {
341     static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
342     static const WCHAR BoldW[]   = {' ','B','o','l','d','\0'};
343     WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
344     WCHAR *pFaceNameSuffix = NULL;
345     HFONT hFont;
346     FONTOBJ *fontPtr;
347
348     if (!plf) return 0;
349
350     if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
351
352     fontPtr->logfont = *plf;
353
354     if (plf->lfEscapement != plf->lfOrientation)
355     {
356         /* this should really depend on whether GM_ADVANCED is set */
357         fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
358         WARN("orientation angle %f set to "
359              "escapement angle %f for new font %p\n",
360              plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
361     }
362
363     pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
364     if (pFaceNameItalicSuffix)
365     {
366         fontPtr->logfont.lfItalic = TRUE;
367         pFaceNameSuffix = pFaceNameItalicSuffix;
368     }
369
370     pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
371     if (pFaceNameBoldSuffix)
372     {
373         if (fontPtr->logfont.lfWeight < FW_BOLD)
374             fontPtr->logfont.lfWeight = FW_BOLD;
375         if (!pFaceNameSuffix || (pFaceNameBoldSuffix < pFaceNameSuffix))
376             pFaceNameSuffix = pFaceNameBoldSuffix;
377     }
378
379     if (pFaceNameSuffix) *pFaceNameSuffix = 0;
380
381     if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
382     {
383         HeapFree( GetProcessHeap(), 0, fontPtr );
384         return 0;
385     }
386
387     TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
388           plf->lfHeight, plf->lfWidth,
389           plf->lfEscapement, plf->lfOrientation,
390           plf->lfPitchAndFamily,
391           plf->lfOutPrecision, plf->lfClipPrecision,
392           plf->lfQuality, plf->lfCharSet,
393           debugstr_w(plf->lfFaceName),
394           plf->lfWeight > 400 ? "Bold" : "",
395           plf->lfItalic ? "Italic" : "",
396           plf->lfUnderline ? "Underline" : "", hFont);
397
398     return hFont;
399 }
400
401 /*************************************************************************
402  *           CreateFontA    (GDI32.@)
403  */
404 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
405                               INT orient, INT weight, DWORD italic,
406                               DWORD underline, DWORD strikeout, DWORD charset,
407                               DWORD outpres, DWORD clippres, DWORD quality,
408                               DWORD pitch, LPCSTR name )
409 {
410     LOGFONTA logfont;
411
412     logfont.lfHeight = height;
413     logfont.lfWidth = width;
414     logfont.lfEscapement = esc;
415     logfont.lfOrientation = orient;
416     logfont.lfWeight = weight;
417     logfont.lfItalic = italic;
418     logfont.lfUnderline = underline;
419     logfont.lfStrikeOut = strikeout;
420     logfont.lfCharSet = charset;
421     logfont.lfOutPrecision = outpres;
422     logfont.lfClipPrecision = clippres;
423     logfont.lfQuality = quality;
424     logfont.lfPitchAndFamily = pitch;
425
426     if (name)
427         lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
428     else
429         logfont.lfFaceName[0] = '\0';
430
431     return CreateFontIndirectA( &logfont );
432 }
433
434 /*************************************************************************
435  *           CreateFontW    (GDI32.@)
436  */
437 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
438                               INT orient, INT weight, DWORD italic,
439                               DWORD underline, DWORD strikeout, DWORD charset,
440                               DWORD outpres, DWORD clippres, DWORD quality,
441                               DWORD pitch, LPCWSTR name )
442 {
443     LOGFONTW logfont;
444
445     logfont.lfHeight = height;
446     logfont.lfWidth = width;
447     logfont.lfEscapement = esc;
448     logfont.lfOrientation = orient;
449     logfont.lfWeight = weight;
450     logfont.lfItalic = italic;
451     logfont.lfUnderline = underline;
452     logfont.lfStrikeOut = strikeout;
453     logfont.lfCharSet = charset;
454     logfont.lfOutPrecision = outpres;
455     logfont.lfClipPrecision = clippres;
456     logfont.lfQuality = quality;
457     logfont.lfPitchAndFamily = pitch;
458
459     if (name)
460         lstrcpynW(logfont.lfFaceName, name,
461                   sizeof(logfont.lfFaceName) / sizeof(WCHAR));
462     else
463         logfont.lfFaceName[0] = '\0';
464
465     return CreateFontIndirectW( &logfont );
466 }
467
468
469 /***********************************************************************
470  *           FONT_SelectObject
471  *
472  * If the driver supports vector fonts we create a gdi font first and
473  * then call the driver to give it a chance to supply its own device
474  * font.  If the driver wants to do this it returns TRUE and we can
475  * delete the gdi font, if the driver wants to use the gdi font it
476  * should return FALSE, to signal an error return GDI_ERROR.  For
477  * drivers that don't support vector fonts they must supply their own
478  * font.
479  */
480 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
481 {
482     HGDIOBJ ret = 0;
483     DC *dc = get_dc_ptr( hdc );
484
485     if (!dc) return 0;
486
487     if (!GDI_inc_ref_count( handle ))
488     {
489         release_dc_ptr( dc );
490         return 0;
491     }
492
493     if (GetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_VA_ABLE)
494         dc->gdiFont = WineEngCreateFontInstance( dc, handle );
495
496     if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
497
498     if (ret && dc->gdiFont) dc->gdiFont = 0;
499
500     if (ret == HGDI_ERROR)
501     {
502         GDI_dec_ref_count( handle );
503         ret = 0; /* SelectObject returns 0 on error */
504     }
505     else
506     {
507         ret = dc->hFont;
508         dc->hFont = handle;
509         GDI_dec_ref_count( ret );
510     }
511     release_dc_ptr( dc );
512     return ret;
513 }
514
515
516 /***********************************************************************
517  *           FONT_GetObjectA
518  */
519 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
520 {
521     FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
522     LOGFONTA lfA;
523
524     if (!font) return 0;
525     if (buffer)
526     {
527         FONT_LogFontWToA( &font->logfont, &lfA );
528         if (count > sizeof(lfA)) count = sizeof(lfA);
529         memcpy( buffer, &lfA, count );
530     }
531     else count = sizeof(lfA);
532     GDI_ReleaseObj( handle );
533     return count;
534 }
535
536 /***********************************************************************
537  *           FONT_GetObjectW
538  */
539 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
540 {
541     FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
542
543     if (!font) return 0;
544     if (buffer)
545     {
546         if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
547         memcpy( buffer, &font->logfont, count );
548     }
549     else count = sizeof(LOGFONTW);
550     GDI_ReleaseObj( handle );
551     return count;
552 }
553
554
555 /***********************************************************************
556  *           FONT_DeleteObject
557  */
558 static BOOL FONT_DeleteObject( HGDIOBJ handle )
559 {
560     FONTOBJ *obj;
561
562     WineEngDestroyFontInstance( handle );
563
564     if (!(obj = free_gdi_handle( handle ))) return FALSE;
565     return HeapFree( GetProcessHeap(), 0, obj );
566 }
567
568
569 /***********************************************************************
570  *              FONT_EnumInstance
571  *
572  * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
573  *       We have to use other types because of the FONTENUMPROCW definition.
574  */
575 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
576                                        DWORD fType, LPARAM lp )
577 {
578     fontEnum32 *pfe = (fontEnum32*)lp;
579     INT ret = 1;
580
581     /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
582     if ((!pfe->lpLogFontParam ||
583         pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
584         pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
585        (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
586     {
587         /* convert font metrics */
588         ENUMLOGFONTEXA logfont;
589         NEWTEXTMETRICEXA tmA;
590
591         pfe->dwFlags |= ENUM_CALLED;
592         if (!(pfe->dwFlags & ENUM_UNICODE))
593         {
594             FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
595             FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
596             plf = (LOGFONTW *)&logfont.elfLogFont;
597             ptm = (TEXTMETRICW *)&tmA;
598         }
599
600         ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
601     }
602     return ret;
603 }
604
605 /***********************************************************************
606  *              FONT_EnumFontFamiliesEx
607  */
608 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
609                                     FONTENUMPROCW efproc,
610                                     LPARAM lParam, DWORD dwUnicode)
611 {
612     INT ret = 1, ret2;
613     DC *dc = get_dc_ptr( hDC );
614     fontEnum32 fe32;
615     BOOL enum_gdi_fonts;
616
617     if (!dc) return 0;
618
619     if (plf)
620         TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
621             plf->lfCharSet);
622     fe32.lpLogFontParam = plf;
623     fe32.lpEnumFunc = efproc;
624     fe32.lpData = lParam;
625     fe32.dwFlags = dwUnicode;
626     fe32.hdc = hDC;
627
628     enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
629
630     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
631     {
632         ret = 0;
633         goto done;
634     }
635
636     if (enum_gdi_fonts)
637         ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
638     fe32.dwFlags &= ~ENUM_CALLED;
639     if (ret && dc->funcs->pEnumDeviceFonts) {
640         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
641         if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
642             ret = ret2;
643     }
644  done:
645     release_dc_ptr( dc );
646     return ret;
647 }
648
649 /***********************************************************************
650  *              EnumFontFamiliesExW     (GDI32.@)
651  */
652 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
653                                     FONTENUMPROCW efproc,
654                                     LPARAM lParam, DWORD dwFlags )
655 {
656     return  FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
657 }
658
659 /***********************************************************************
660  *              EnumFontFamiliesExA     (GDI32.@)
661  */
662 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
663                                     FONTENUMPROCA efproc,
664                                     LPARAM lParam, DWORD dwFlags)
665 {
666     LOGFONTW lfW, *plfW;
667
668     if (plf)
669     {
670         FONT_LogFontAToW( plf, &lfW );
671         plfW = &lfW;
672     }
673     else plfW = NULL;
674
675     return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
676 }
677
678 /***********************************************************************
679  *              EnumFontFamiliesA       (GDI32.@)
680  */
681 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
682                                   FONTENUMPROCA efproc, LPARAM lpData )
683 {
684     LOGFONTA lf, *plf;
685
686     if (lpFamily)
687     {
688         if (!*lpFamily) return 1;
689         lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
690         lf.lfCharSet = DEFAULT_CHARSET;
691         lf.lfPitchAndFamily = 0;
692         plf = &lf;
693     }
694     else plf = NULL;
695
696     return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
697 }
698
699 /***********************************************************************
700  *              EnumFontFamiliesW       (GDI32.@)
701  */
702 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
703                                   FONTENUMPROCW efproc, LPARAM lpData )
704 {
705     LOGFONTW lf, *plf;
706
707     if (lpFamily)
708     {
709         if (!*lpFamily) return 1;
710         lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
711         lf.lfCharSet = DEFAULT_CHARSET;
712         lf.lfPitchAndFamily = 0;
713         plf = &lf;
714     }
715     else plf = NULL;
716
717     return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
718 }
719
720 /***********************************************************************
721  *              EnumFontsA              (GDI32.@)
722  */
723 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
724                            LPARAM lpData )
725 {
726     return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
727 }
728
729 /***********************************************************************
730  *              EnumFontsW              (GDI32.@)
731  */
732 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
733                            LPARAM lpData )
734 {
735     return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
736 }
737
738
739 /***********************************************************************
740  *           GetTextCharacterExtra    (GDI32.@)
741  */
742 INT WINAPI GetTextCharacterExtra( HDC hdc )
743 {
744     INT ret;
745     DC *dc = get_dc_ptr( hdc );
746     if (!dc) return 0x80000000;
747     ret = dc->charExtra;
748     release_dc_ptr( dc );
749     return ret;
750 }
751
752
753 /***********************************************************************
754  *           SetTextCharacterExtra    (GDI32.@)
755  */
756 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
757 {
758     INT prev;
759     DC * dc = get_dc_ptr( hdc );
760     if (!dc) return 0x80000000;
761     if (dc->funcs->pSetTextCharacterExtra)
762         prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
763     else
764     {
765         prev = dc->charExtra;
766         dc->charExtra = extra;
767     }
768     release_dc_ptr( dc );
769     return prev;
770 }
771
772
773 /***********************************************************************
774  *           SetTextJustification    (GDI32.@)
775  */
776 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
777 {
778     BOOL ret = TRUE;
779     DC * dc = get_dc_ptr( hdc );
780     if (!dc) return FALSE;
781     if (dc->funcs->pSetTextJustification)
782         ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
783     else
784     {
785         extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
786         if (!extra) breaks = 0;
787         if (breaks)
788         {
789             dc->breakExtra = extra / breaks;
790             dc->breakRem   = extra - (breaks * dc->breakExtra);
791         }
792         else
793         {
794             dc->breakExtra = 0;
795             dc->breakRem   = 0;
796         }
797     }
798     release_dc_ptr( dc );
799     return ret;
800 }
801
802
803 /***********************************************************************
804  *           GetTextFaceA    (GDI32.@)
805  */
806 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
807 {
808     INT res = GetTextFaceW(hdc, 0, NULL);
809     LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
810     GetTextFaceW( hdc, res, nameW );
811
812     if (name)
813     {
814         if (count)
815         {
816             res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
817             if (res == 0)
818                 res = count;
819             name[count-1] = 0;
820             /* GetTextFaceA does NOT include the nul byte in the return count.  */
821             res--;
822         }
823         else
824             res = 0;
825     }
826     else
827         res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
828     HeapFree( GetProcessHeap(), 0, nameW );
829     return res;
830 }
831
832 /***********************************************************************
833  *           GetTextFaceW    (GDI32.@)
834  */
835 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
836 {
837     FONTOBJ *font;
838     INT     ret = 0;
839
840     DC * dc = get_dc_ptr( hdc );
841     if (!dc) return 0;
842
843     if(dc->gdiFont)
844         ret = WineEngGetTextFace(dc->gdiFont, count, name);
845     else if ((font = GDI_GetObjPtr( dc->hFont, OBJ_FONT )))
846     {
847         INT n = strlenW(font->logfont.lfFaceName) + 1;
848         if (name)
849         {
850             lstrcpynW( name, font->logfont.lfFaceName, count );
851             ret = min(count, n);
852         }
853         else ret = n;
854         GDI_ReleaseObj( dc->hFont );
855     }
856     release_dc_ptr( dc );
857     return ret;
858 }
859
860
861 /***********************************************************************
862  *           GetTextExtentPoint32A    (GDI32.@)
863  *
864  * See GetTextExtentPoint32W.
865  */
866 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
867                                      LPSIZE size )
868 {
869     BOOL ret = FALSE;
870     INT wlen;
871     LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
872
873     if (p) {
874         ret = GetTextExtentPoint32W( hdc, p, wlen, size );
875         HeapFree( GetProcessHeap(), 0, p );
876     }
877
878     TRACE("(%p %s %d %p): returning %d x %d\n",
879           hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
880     return ret;
881 }
882
883
884 /***********************************************************************
885  * GetTextExtentPoint32W [GDI32.@]
886  *
887  * Computes width/height for a string.
888  *
889  * Computes width and height of the specified string.
890  *
891  * RETURNS
892  *    Success: TRUE
893  *    Failure: FALSE
894  */
895 BOOL WINAPI GetTextExtentPoint32W(
896     HDC hdc,     /* [in]  Handle of device context */
897     LPCWSTR str,   /* [in]  Address of text string */
898     INT count,   /* [in]  Number of characters in string */
899     LPSIZE size) /* [out] Address of structure for string size */
900 {
901     return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
902 }
903
904 /***********************************************************************
905  * GetTextExtentExPointI [GDI32.@]
906  *
907  * Computes width and height of the array of glyph indices.
908  *
909  * PARAMS
910  *    hdc     [I] Handle of device context.
911  *    indices [I] Glyph index array.
912  *    count   [I] Number of glyphs in array.
913  *    max_ext [I] Maximum width in glyphs.
914  *    nfit    [O] Maximum number of characters.
915  *    dxs     [O] Partial string widths.
916  *    size    [O] Returned string size.
917  *
918  * RETURNS
919  *    Success: TRUE
920  *    Failure: FALSE
921  */
922 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
923                                    LPINT nfit, LPINT dxs, LPSIZE size )
924 {
925     BOOL ret = FALSE;
926     DC * dc = get_dc_ptr( hdc );
927     if (!dc) return FALSE;
928
929     if(dc->gdiFont) {
930         ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
931         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
932         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
933         size->cx += count * dc->charExtra;
934     }
935     else if(dc->funcs->pGetTextExtentExPoint) {
936         FIXME("calling GetTextExtentExPoint\n");
937         ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, indices, count,
938                                                 max_ext, nfit, dxs, size );
939     }
940
941     release_dc_ptr( dc );
942
943     TRACE("(%p %p %d %p): returning %d x %d\n",
944           hdc, indices, count, size, size->cx, size->cy );
945     return ret;
946 }
947
948 /***********************************************************************
949  * GetTextExtentPointI [GDI32.@]
950  *
951  * Computes width and height of the array of glyph indices.
952  *
953  * PARAMS
954  *    hdc     [I] Handle of device context.
955  *    indices [I] Glyph index array.
956  *    count   [I] Number of glyphs in array.
957  *    size    [O] Returned string size.
958  *
959  * RETURNS
960  *    Success: TRUE
961  *    Failure: FALSE
962  */
963 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
964 {
965     return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
966 }
967
968
969 /***********************************************************************
970  *           GetTextExtentPointA    (GDI32.@)
971  */
972 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
973                                           LPSIZE size )
974 {
975     TRACE("not bug compatible.\n");
976     return GetTextExtentPoint32A( hdc, str, count, size );
977 }
978
979 /***********************************************************************
980  *           GetTextExtentPointW   (GDI32.@)
981  */
982 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
983                                           LPSIZE size )
984 {
985     TRACE("not bug compatible.\n");
986     return GetTextExtentPoint32W( hdc, str, count, size );
987 }
988
989
990 /***********************************************************************
991  *           GetTextExtentExPointA    (GDI32.@)
992  */
993 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
994                                    INT maxExt, LPINT lpnFit,
995                                    LPINT alpDx, LPSIZE size )
996 {
997     BOOL ret;
998     INT wlen;
999     INT *walpDx = NULL;
1000     LPWSTR p = NULL;
1001     
1002     if (alpDx &&
1003        NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1004        return FALSE;
1005     
1006     p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1007     ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1008     if (walpDx)
1009     {
1010         INT n = lpnFit ? *lpnFit : wlen;
1011         INT i, j;
1012         for(i = 0, j = 0; i < n; i++, j++)
1013         {
1014             alpDx[j] = walpDx[i];
1015             if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1016         }
1017     }
1018     if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1019     HeapFree( GetProcessHeap(), 0, p );
1020     HeapFree( GetProcessHeap(), 0, walpDx );
1021     return ret;
1022 }
1023
1024
1025 /***********************************************************************
1026  *           GetTextExtentExPointW    (GDI32.@)
1027  *
1028  * Return the size of the string as it would be if it was output properly by
1029  * e.g. TextOut.
1030  *
1031  * This should include
1032  * - Intercharacter spacing
1033  * - justification spacing (not yet done)
1034  * - kerning? see below
1035  *
1036  * Kerning.  Since kerning would be carried out by the rendering code it should
1037  * be done by the driver.  However they don't support it yet.  Also I am not
1038  * yet persuaded that (certainly under Win95) any kerning is actually done.
1039  *
1040  * str: According to MSDN this should be null-terminated.  That is not true; a
1041  *      null will not terminate it early.
1042  * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1043  *       than count.  I have seen it be either the size of the full string or
1044  *       1 less than the size of the full string.  I have not seen it bear any
1045  *       resemblance to the portion that would fit.
1046  * lpnFit: What exactly is fitting?  Stupidly, in my opinion, it includes the
1047  *         trailing intercharacter spacing and any trailing justification.
1048  *
1049  * FIXME
1050  * Currently we do this by measuring each character etc.  We should do it by
1051  * passing the request to the driver, perhaps by extending the
1052  * pGetTextExtentPoint function to take the alpDx argument.  That would avoid
1053  * thinking about kerning issues and rounding issues in the justification.
1054  */
1055
1056 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1057                                    INT maxExt, LPINT lpnFit,
1058                                    LPINT alpDx, LPSIZE size )
1059 {
1060     INT nFit = 0;
1061     LPINT dxs = NULL;
1062     DC *dc;
1063     BOOL ret = FALSE;
1064     TEXTMETRICW tm;
1065
1066     TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1067
1068     dc = get_dc_ptr(hdc);
1069     if (! dc)
1070         return FALSE;
1071
1072     GetTextMetricsW(hdc, &tm);
1073
1074     /* If we need to calculate nFit, then we need the partial extents even if
1075        the user hasn't provided us with an array.  */
1076     if (lpnFit)
1077     {
1078         dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1079         if (! dxs)
1080         {
1081             release_dc_ptr(dc);
1082             SetLastError(ERROR_OUTOFMEMORY);
1083             return FALSE;
1084         }
1085     }
1086     else
1087         dxs = alpDx;
1088
1089     if (dc->gdiFont)
1090         ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1091                                           0, NULL, dxs, size);
1092     else if (dc->funcs->pGetTextExtentExPoint)
1093         ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1094                                                0, NULL, dxs, size);
1095
1096     /* Perform device size to world size transformations.  */
1097     if (ret)
1098     {
1099         INT extra      = dc->charExtra,
1100         breakExtra = dc->breakExtra,
1101         breakRem   = dc->breakRem,
1102         i;
1103
1104         if (dxs)
1105         {
1106             for (i = 0; i < count; ++i)
1107             {
1108                 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1109                 dxs[i] += (i+1) * extra;
1110                 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1111                 {
1112                     dxs[i] += breakExtra;
1113                     if (breakRem > 0)
1114                     {
1115                         breakRem--;
1116                         dxs[i]++;
1117                     }
1118                 }
1119                 if (dxs[i] <= maxExt)
1120                     ++nFit;
1121             }
1122             breakRem = dc->breakRem;
1123         }
1124         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1125         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1126
1127         if (!dxs && count > 1 && (breakExtra || breakRem))
1128         {
1129             for (i = 0; i < count; i++)
1130             {
1131                 if (str[i] == tm.tmBreakChar)
1132                 {
1133                     size->cx += breakExtra;
1134                     if (breakRem > 0)
1135                     {
1136                         breakRem--;
1137                         (size->cx)++;
1138                     }
1139                 }
1140             }
1141         }
1142     }
1143
1144     if (lpnFit)
1145         *lpnFit = nFit;
1146
1147     if (! alpDx)
1148         HeapFree(GetProcessHeap(), 0, dxs);
1149
1150     release_dc_ptr( dc );
1151
1152     TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1153     return ret;
1154 }
1155
1156 /***********************************************************************
1157  *           GetTextMetricsA    (GDI32.@)
1158  */
1159 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1160 {
1161     TEXTMETRICW tm32;
1162
1163     if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1164     FONT_TextMetricWToA( &tm32, metrics );
1165     return TRUE;
1166 }
1167
1168 /***********************************************************************
1169  *           GetTextMetricsW    (GDI32.@)
1170  */
1171 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1172 {
1173     BOOL ret = FALSE;
1174     DC * dc = get_dc_ptr( hdc );
1175     if (!dc) return FALSE;
1176
1177     if (dc->gdiFont)
1178         ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1179     else if (dc->funcs->pGetTextMetrics)
1180         ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1181
1182     if (ret)
1183     {
1184     /* device layer returns values in device units
1185      * therefore we have to convert them to logical */
1186
1187         metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1188         metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1189
1190 #define WDPTOLP(x) ((x<0)?                                      \
1191                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1192                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1193 #define HDPTOLP(y) ((y<0)?                                      \
1194                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1195                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1196
1197     metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
1198     metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
1199     metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
1200     metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
1201     metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
1202     metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
1203     metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
1204     metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
1205         ret = TRUE;
1206 #undef WDPTOLP
1207 #undef HDPTOLP
1208     TRACE("text metrics:\n"
1209           "    Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1210           "    Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1211           "    UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1212           "    StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1213           "    PitchAndFamily = %02x\n"
1214           "    --------------------\n"
1215           "    InternalLeading = %i\n"
1216           "    Ascent = %i\n"
1217           "    Descent = %i\n"
1218           "    Height = %i\n",
1219           metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1220           metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1221           metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1222           metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1223           metrics->tmPitchAndFamily,
1224           metrics->tmInternalLeading,
1225           metrics->tmAscent,
1226           metrics->tmDescent,
1227           metrics->tmHeight );
1228     }
1229     release_dc_ptr( dc );
1230     return ret;
1231 }
1232
1233
1234 /***********************************************************************
1235  *              GetOutlineTextMetricsA (GDI32.@)
1236  * Gets metrics for TrueType fonts.
1237  *
1238  * NOTES
1239  *    If the supplied buffer isn't big enough Windows partially fills it up to
1240  *    its given length and returns that length.
1241  *
1242  * RETURNS
1243  *    Success: Non-zero or size of required buffer
1244  *    Failure: 0
1245  */
1246 UINT WINAPI GetOutlineTextMetricsA(
1247     HDC hdc,    /* [in]  Handle of device context */
1248     UINT cbData, /* [in]  Size of metric data array */
1249     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1250 {
1251     char buf[512], *ptr;
1252     UINT ret, needed;
1253     OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1254     OUTLINETEXTMETRICA *output = lpOTM;
1255     INT left, len;
1256
1257     if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1258         return 0;
1259     if(ret > sizeof(buf))
1260         lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1261     GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1262
1263     needed = sizeof(OUTLINETEXTMETRICA);
1264     if(lpOTMW->otmpFamilyName)
1265         needed += WideCharToMultiByte(CP_ACP, 0,
1266            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1267                                       NULL, 0, NULL, NULL);
1268     if(lpOTMW->otmpFaceName)
1269         needed += WideCharToMultiByte(CP_ACP, 0,
1270            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1271                                       NULL, 0, NULL, NULL);
1272     if(lpOTMW->otmpStyleName)
1273         needed += WideCharToMultiByte(CP_ACP, 0,
1274            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1275                                       NULL, 0, NULL, NULL);
1276     if(lpOTMW->otmpFullName)
1277         needed += WideCharToMultiByte(CP_ACP, 0,
1278            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1279                                       NULL, 0, NULL, NULL);
1280
1281     if(!lpOTM) {
1282         ret = needed;
1283         goto end;
1284     }
1285
1286     TRACE("needed = %d\n", needed);
1287     if(needed > cbData)
1288         /* Since the supplied buffer isn't big enough, we'll alloc one
1289            that is and memcpy the first cbData bytes into the lpOTM at
1290            the end. */
1291         output = HeapAlloc(GetProcessHeap(), 0, needed);
1292
1293     ret = output->otmSize = min(needed, cbData);
1294     FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1295     output->otmFiller = 0;
1296     output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1297     output->otmfsSelection = lpOTMW->otmfsSelection;
1298     output->otmfsType = lpOTMW->otmfsType;
1299     output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1300     output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1301     output->otmItalicAngle = lpOTMW->otmItalicAngle;
1302     output->otmEMSquare = lpOTMW->otmEMSquare;
1303     output->otmAscent = lpOTMW->otmAscent;
1304     output->otmDescent = lpOTMW->otmDescent;
1305     output->otmLineGap = lpOTMW->otmLineGap;
1306     output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1307     output->otmsXHeight = lpOTMW->otmsXHeight;
1308     output->otmrcFontBox = lpOTMW->otmrcFontBox;
1309     output->otmMacAscent = lpOTMW->otmMacAscent;
1310     output->otmMacDescent = lpOTMW->otmMacDescent;
1311     output->otmMacLineGap = lpOTMW->otmMacLineGap;
1312     output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1313     output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1314     output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1315     output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1316     output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1317     output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1318     output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1319     output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1320     output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1321
1322
1323     ptr = (char*)(output + 1);
1324     left = needed - sizeof(*output);
1325
1326     if(lpOTMW->otmpFamilyName) {
1327         output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1328         len = WideCharToMultiByte(CP_ACP, 0,
1329              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1330                                   ptr, left, NULL, NULL);
1331         left -= len;
1332         ptr += len;
1333     } else
1334         output->otmpFamilyName = 0;
1335
1336     if(lpOTMW->otmpFaceName) {
1337         output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1338         len = WideCharToMultiByte(CP_ACP, 0,
1339              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1340                                   ptr, left, NULL, NULL);
1341         left -= len;
1342         ptr += len;
1343     } else
1344         output->otmpFaceName = 0;
1345
1346     if(lpOTMW->otmpStyleName) {
1347         output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1348         len = WideCharToMultiByte(CP_ACP, 0,
1349              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1350                                   ptr, left, NULL, NULL);
1351         left -= len;
1352         ptr += len;
1353     } else
1354         output->otmpStyleName = 0;
1355
1356     if(lpOTMW->otmpFullName) {
1357         output->otmpFullName = (LPSTR)(ptr - (char*)output);
1358         len = WideCharToMultiByte(CP_ACP, 0,
1359              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1360                                   ptr, left, NULL, NULL);
1361         left -= len;
1362     } else
1363         output->otmpFullName = 0;
1364
1365     assert(left == 0);
1366
1367     if(output != lpOTM) {
1368         memcpy(lpOTM, output, cbData);
1369         HeapFree(GetProcessHeap(), 0, output);
1370
1371         /* check if the string offsets really fit into the provided size */
1372         /* FIXME: should we check string length as well? */
1373         /* make sure that we don't read/write beyond the provided buffer */
1374         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1375         {
1376             if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1377                 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1378         }
1379
1380         /* make sure that we don't read/write beyond the provided buffer */
1381         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1382         {
1383             if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1384                 lpOTM->otmpFaceName = 0; /* doesn't fit */
1385         }
1386
1387             /* make sure that we don't read/write beyond the provided buffer */
1388         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1389         {
1390             if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1391                 lpOTM->otmpStyleName = 0; /* doesn't fit */
1392         }
1393
1394         /* make sure that we don't read/write beyond the provided buffer */
1395         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1396         {
1397             if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1398                 lpOTM->otmpFullName = 0; /* doesn't fit */
1399         }
1400     }
1401
1402 end:
1403     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1404         HeapFree(GetProcessHeap(), 0, lpOTMW);
1405
1406     return ret;
1407 }
1408
1409
1410 /***********************************************************************
1411  *           GetOutlineTextMetricsW [GDI32.@]
1412  */
1413 UINT WINAPI GetOutlineTextMetricsW(
1414     HDC hdc,    /* [in]  Handle of device context */
1415     UINT cbData, /* [in]  Size of metric data array */
1416     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1417 {
1418     DC *dc = get_dc_ptr( hdc );
1419     OUTLINETEXTMETRICW *output = lpOTM;
1420     UINT ret;
1421
1422     TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1423     if(!dc) return 0;
1424
1425     if(dc->gdiFont) {
1426         ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1427         if(lpOTM && ret) {
1428             if(ret > cbData) {
1429                 output = HeapAlloc(GetProcessHeap(), 0, ret);
1430                 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1431             }
1432
1433         output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1434         output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1435
1436 #define WDPTOLP(x) ((x<0)?                                      \
1437                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1438                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1439 #define HDPTOLP(y) ((y<0)?                                      \
1440                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1441                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1442
1443             output->otmTextMetrics.tmHeight           = HDPTOLP(output->otmTextMetrics.tmHeight);
1444             output->otmTextMetrics.tmAscent           = HDPTOLP(output->otmTextMetrics.tmAscent);
1445             output->otmTextMetrics.tmDescent          = HDPTOLP(output->otmTextMetrics.tmDescent);
1446             output->otmTextMetrics.tmInternalLeading  = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1447             output->otmTextMetrics.tmExternalLeading  = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1448             output->otmTextMetrics.tmAveCharWidth     = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1449             output->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1450             output->otmTextMetrics.tmOverhang         = WDPTOLP(output->otmTextMetrics.tmOverhang);
1451             output->otmAscent = HDPTOLP(output->otmAscent);
1452             output->otmDescent = HDPTOLP(output->otmDescent);
1453             output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1454             output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1455             output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1456             output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1457             output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1458             output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1459             output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1460             output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1461             output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1462             output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1463             output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1464             output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1465             output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1466             output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1467             output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1468             output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1469             output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1470             output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1471             output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1472             output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1473             output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1474             output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1475 #undef WDPTOLP
1476 #undef HDPTOLP
1477             if(output != lpOTM) {
1478                 memcpy(lpOTM, output, cbData);
1479                 HeapFree(GetProcessHeap(), 0, output);
1480                 ret = cbData;
1481             }
1482         }
1483     }
1484
1485     else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1486               but really this should just be a return 0. */
1487
1488         ret = sizeof(*lpOTM);
1489         if (lpOTM) {
1490             if(cbData < ret)
1491                 ret = 0;
1492             else {
1493                 memset(lpOTM, 0, ret);
1494                 lpOTM->otmSize = sizeof(*lpOTM);
1495                 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1496                 /*
1497                   Further fill of the structure not implemented,
1498                   Needs real values for the structure members
1499                 */
1500             }
1501         }
1502     }
1503     release_dc_ptr(dc);
1504     return ret;
1505 }
1506
1507
1508 /***********************************************************************
1509  *           GetCharWidthW      (GDI32.@)
1510  *           GetCharWidth32W    (GDI32.@)
1511  */
1512 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1513                                LPINT buffer )
1514 {
1515     UINT i;
1516     BOOL ret = FALSE;
1517     DC * dc = get_dc_ptr( hdc );
1518     if (!dc) return FALSE;
1519
1520     if (dc->gdiFont)
1521         ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1522     else if (dc->funcs->pGetCharWidth)
1523         ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1524
1525     if (ret)
1526     {
1527         /* convert device units to logical */
1528         for( i = firstChar; i <= lastChar; i++, buffer++ )
1529             *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1530         ret = TRUE;
1531     }
1532     release_dc_ptr( dc );
1533     return ret;
1534 }
1535
1536
1537 /***********************************************************************
1538  *           GetCharWidthA      (GDI32.@)
1539  *           GetCharWidth32A    (GDI32.@)
1540  */
1541 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1542                                LPINT buffer )
1543 {
1544     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1545     LPSTR str;
1546     LPWSTR wstr;
1547     BOOL ret = TRUE;
1548
1549     if(count <= 0) return FALSE;
1550
1551     str = HeapAlloc(GetProcessHeap(), 0, count);
1552     for(i = 0; i < count; i++)
1553         str[i] = (BYTE)(firstChar + i);
1554
1555     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1556
1557     for(i = 0; i < wlen; i++)
1558     {
1559         if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1560         {
1561             ret = FALSE;
1562             break;
1563         }
1564         buffer++;
1565     }
1566
1567     HeapFree(GetProcessHeap(), 0, str);
1568     HeapFree(GetProcessHeap(), 0, wstr);
1569
1570     return ret;
1571 }
1572
1573
1574 /***********************************************************************
1575  *           ExtTextOutA    (GDI32.@)
1576  *
1577  * See ExtTextOutW.
1578  */
1579 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1580                          const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1581 {
1582     INT wlen;
1583     UINT codepage;
1584     LPWSTR p;
1585     BOOL ret;
1586     LPINT lpDxW = NULL;
1587
1588     if (flags & ETO_GLYPH_INDEX)
1589         return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1590
1591     p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1592
1593     if (lpDx) {
1594         unsigned int i = 0, j = 0;
1595
1596         lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1597         while(i < count) {
1598             if(IsDBCSLeadByteEx(codepage, str[i])) {
1599                 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1600                 i = i + 2;
1601             } else {
1602                 lpDxW[j++] = lpDx[i];
1603                 i = i + 1;
1604             }
1605         }
1606     }
1607
1608     ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1609
1610     HeapFree( GetProcessHeap(), 0, p );
1611     HeapFree( GetProcessHeap(), 0, lpDxW );
1612     return ret;
1613 }
1614
1615
1616 /***********************************************************************
1617  *           ExtTextOutW    (GDI32.@)
1618  *
1619  * Draws text using the currently selected font, background color, and text color.
1620  * 
1621  * 
1622  * PARAMS
1623  *    x,y    [I] coordinates of string
1624  *    flags  [I]
1625  *        ETO_GRAYED - undocumented on MSDN
1626  *        ETO_OPAQUE - use background color for fill the rectangle
1627  *        ETO_CLIPPED - clipping text to the rectangle
1628  *        ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1629  *                          than encoded characters. Implies ETO_IGNORELANGUAGE
1630  *        ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1631  *                         Affects BiDi ordering
1632  *        ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1633  *        ETO_PDY - unimplemented
1634  *        ETO_NUMERICSLATIN - unimplemented always assumed -
1635  *                            do not translate numbers into locale representations
1636  *        ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1637  *    lprect [I] dimensions for clipping or/and opaquing
1638  *    str    [I] text string
1639  *    count  [I] number of symbols in string
1640  *    lpDx   [I] optional parameter with distance between drawing characters
1641  *
1642  * RETURNS
1643  *    Success: TRUE
1644  *    Failure: FALSE
1645  */
1646 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1647                          const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1648 {
1649     BOOL ret = FALSE;
1650     LPWSTR reordered_str = (LPWSTR)str;
1651     WORD *glyphs = NULL;
1652     UINT align = GetTextAlign( hdc );
1653     POINT pt;
1654     TEXTMETRICW tm;
1655     LOGFONTW lf;
1656     double cosEsc, sinEsc;
1657     INT *deltas = NULL, char_extra;
1658     SIZE sz;
1659     RECT rc;
1660     BOOL done_extents = FALSE;
1661     INT width = 0, xwidth = 0, ywidth = 0;
1662     DWORD type;
1663     DC * dc = get_dc_ptr( hdc );
1664     INT breakRem;
1665     static int quietfixme = 0;
1666
1667     if (!dc) return FALSE;
1668
1669     breakRem = dc->breakRem;
1670
1671     if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1672     {
1673         FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1674         quietfixme = 1;
1675     }
1676     if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1677     {
1678         release_dc_ptr( dc );
1679         return ret;
1680     }
1681
1682     update_dc( dc );
1683     type = GetObjectType(hdc);
1684     if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1685     {
1686         ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1687         release_dc_ptr( dc );
1688         return ret;
1689     }
1690
1691     if (!lprect)
1692         flags &= ~ETO_CLIPPED;
1693         
1694     if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1695     {
1696         reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1697
1698         BIDI_Reorder( str, count, GCP_REORDER,
1699                       ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1700                       WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1701                       reordered_str, count, NULL );
1702     
1703         flags |= ETO_IGNORELANGUAGE;
1704     }
1705
1706     TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1707           lprect, debugstr_wn(str, count), count, lpDx);
1708
1709     if(flags & ETO_GLYPH_INDEX)
1710         glyphs = reordered_str;
1711
1712     if(lprect)
1713         TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1714               lprect->bottom);
1715     TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1716
1717     if(align & TA_UPDATECP)
1718     {
1719         GetCurrentPositionEx( hdc, &pt );
1720         x = pt.x;
1721         y = pt.y;
1722     }
1723
1724     GetTextMetricsW(hdc, &tm);
1725     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1726
1727     if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1728         lf.lfEscapement = 0;
1729
1730     if(lf.lfEscapement != 0)
1731     {
1732         cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1733         sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1734     }
1735     else
1736     {
1737         cosEsc = 1;
1738         sinEsc = 0;
1739     }
1740
1741     if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1742     {
1743         if(!lprect)
1744         {
1745             if(flags & ETO_GLYPH_INDEX)
1746                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1747             else
1748                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1749
1750             done_extents = TRUE;
1751             rc.left = x;
1752             rc.top = y;
1753             rc.right = x + sz.cx;
1754             rc.bottom = y + sz.cy;
1755         }
1756         else
1757         {
1758             rc = *lprect;
1759         }
1760
1761         LPtoDP(hdc, (POINT*)&rc, 2);
1762
1763         if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1764         if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1765     }
1766
1767     if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1768         dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1769
1770     if(count == 0)
1771     {
1772         ret = TRUE;
1773         goto done;
1774     }
1775
1776     pt.x = x;
1777     pt.y = y;
1778     LPtoDP(hdc, &pt, 1);
1779     x = pt.x;
1780     y = pt.y;
1781
1782     char_extra = GetTextCharacterExtra(hdc);
1783     if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1784     {
1785         UINT i;
1786         SIZE tmpsz;
1787         deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1788         for(i = 0; i < count; i++)
1789         {
1790             if(lpDx && (flags & ETO_PDY))
1791                 deltas[i] = lpDx[i*2] + char_extra;
1792             else if(lpDx)
1793                 deltas[i] = lpDx[i] + char_extra;
1794             else
1795             {
1796                 if(flags & ETO_GLYPH_INDEX)
1797                     GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1798                 else
1799                     GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1800
1801                 deltas[i] = tmpsz.cx;
1802             }
1803             
1804             if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1805             {
1806                 deltas[i] = deltas[i] + dc->breakExtra;
1807                 if (breakRem > 0)
1808                 {
1809                     breakRem--;
1810                     deltas[i]++;
1811                 }
1812             }
1813             deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1814             width += deltas[i];
1815         }
1816     }
1817     else
1818     {
1819         if(!done_extents)
1820         {
1821             if(flags & ETO_GLYPH_INDEX)
1822                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1823             else
1824                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1825             done_extents = TRUE;
1826         }
1827         width = INTERNAL_XWSTODS(dc, sz.cx);
1828     }
1829     xwidth = width * cosEsc;
1830     ywidth = width * sinEsc;
1831
1832     tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1833     tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1834     switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1835     {
1836     case TA_LEFT:
1837         if (align & TA_UPDATECP)
1838         {
1839             pt.x = x + xwidth;
1840             pt.y = y - ywidth;
1841             DPtoLP(hdc, &pt, 1);
1842             MoveToEx(hdc, pt.x, pt.y, NULL);
1843         }
1844         break;
1845
1846     case TA_CENTER:
1847         x -= xwidth / 2;
1848         y += ywidth / 2;
1849         break;
1850
1851     case TA_RIGHT:
1852         x -= xwidth;
1853         y += ywidth;
1854         if (align & TA_UPDATECP)
1855         {
1856             pt.x = x;
1857             pt.y = y;
1858             DPtoLP(hdc, &pt, 1);
1859             MoveToEx(hdc, pt.x, pt.y, NULL);
1860         }
1861         break;
1862     }
1863
1864     switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1865     {
1866     case TA_TOP:
1867         y += tm.tmAscent * cosEsc;
1868         x += tm.tmAscent * sinEsc;
1869         break;
1870
1871     case TA_BOTTOM:
1872         y -= tm.tmDescent * cosEsc;
1873         x -= tm.tmDescent * sinEsc;
1874         break;
1875
1876     case TA_BASELINE:
1877         break;
1878     }
1879
1880     if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1881     {
1882         if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1883         {
1884             if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1885                y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1886             {
1887                 RECT rc;
1888                 rc.left = x;
1889                 rc.right = x + width;
1890                 rc.top = y - tm.tmAscent;
1891                 rc.bottom = y + tm.tmDescent;
1892                 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1893             }
1894         }
1895     }
1896
1897     if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1898     {
1899         HFONT orig_font = dc->hFont, cur_font;
1900         UINT glyph;
1901         INT span = 0, *offsets = NULL;
1902         unsigned int i;
1903
1904         glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1905         for(i = 0; i < count; i++)
1906         {
1907             WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1908             if(cur_font != dc->hFont)
1909             {
1910                 if(!offsets)
1911                 {
1912                     unsigned int j;
1913                     offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1914                     offsets[0] = 0;
1915                     if(!deltas)
1916                     {
1917                         SIZE tmpsz;
1918                         for(j = 1; j < count; j++)
1919                         {
1920                             GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1921                             offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
1922                         }
1923                     }
1924                     else
1925                     {
1926                         for(j = 1; j < count; j++)
1927                             offsets[j] = offsets[j-1] + deltas[j];
1928                     }
1929                 }
1930                 if(span)
1931                 {
1932                     if (PATH_IsPathOpen(dc->path))
1933                         ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1934                                               (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1935                                               glyphs, span, deltas ? deltas + i - span : NULL);
1936                     else
1937                         dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1938                                            (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1939                                            glyphs, span, deltas ? deltas + i - span : NULL);
1940                     span = 0;
1941                 }
1942                 SelectObject(hdc, cur_font);
1943             }
1944             glyphs[span++] = glyph;
1945
1946             if(i == count - 1)
1947             {
1948                 if (PATH_IsPathOpen(dc->path))
1949                     ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
1950                                           y - (offsets ? offsets[count - span] * sinEsc : 0),
1951                                           (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1952                                           glyphs, span, deltas ? deltas + count - span : NULL);
1953                 else
1954                     ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
1955                                              y - (offsets ? offsets[count - span] * sinEsc : 0),
1956                                              (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1957                                              glyphs, span, deltas ? deltas + count - span : NULL);
1958                 SelectObject(hdc, orig_font);
1959                 HeapFree(GetProcessHeap(), 0, offsets);
1960            }
1961         }
1962     }
1963     else
1964     {
1965         if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
1966         {
1967             glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1968             GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
1969             flags |= ETO_GLYPH_INDEX;
1970         }
1971
1972         if (PATH_IsPathOpen(dc->path))
1973             ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
1974                                   glyphs ? glyphs : reordered_str, count, deltas);
1975         else
1976             ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
1977                                      glyphs ? glyphs : reordered_str, count, deltas);
1978     }
1979
1980 done:
1981     HeapFree(GetProcessHeap(), 0, deltas);
1982     if(glyphs != reordered_str)
1983         HeapFree(GetProcessHeap(), 0, glyphs);
1984     if(reordered_str != str)
1985         HeapFree(GetProcessHeap(), 0, reordered_str);
1986
1987     release_dc_ptr( dc );
1988
1989     if (ret && (lf.lfUnderline || lf.lfStrikeOut))
1990     {
1991         int underlinePos, strikeoutPos;
1992         int underlineWidth, strikeoutWidth;
1993         UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
1994         OUTLINETEXTMETRICW* otm = NULL;
1995
1996         if(!size)
1997         {
1998             underlinePos = 0;
1999             underlineWidth = tm.tmAscent / 20 + 1;
2000             strikeoutPos = tm.tmAscent / 2;
2001             strikeoutWidth = underlineWidth;
2002         }
2003         else
2004         {
2005             otm = HeapAlloc(GetProcessHeap(), 0, size);
2006             GetOutlineTextMetricsW(hdc, size, otm);
2007             underlinePos = otm->otmsUnderscorePosition;
2008             underlineWidth = otm->otmsUnderscoreSize;
2009             strikeoutPos = otm->otmsStrikeoutPosition;
2010             strikeoutWidth = otm->otmsStrikeoutSize;
2011             HeapFree(GetProcessHeap(), 0, otm);
2012         }
2013
2014         if (PATH_IsPathOpen(dc->path))
2015         {
2016             POINT pts[5];
2017             HPEN hpen;
2018             HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2019
2020             hbrush = SelectObject(hdc, hbrush);
2021             hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2022
2023             if (lf.lfUnderline)
2024             {
2025                 pts[0].x = x - underlinePos * sinEsc;
2026                 pts[0].y = y - underlinePos * cosEsc;
2027                 pts[1].x = x + xwidth - underlinePos * sinEsc;
2028                 pts[1].y = y - ywidth - underlinePos * cosEsc;
2029                 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2030                 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2031                 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2032                 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2033                 pts[4].x = pts[0].x;
2034                 pts[4].y = pts[0].y;
2035                 DPtoLP(hdc, pts, 5);
2036                 Polygon(hdc, pts, 5);
2037             }
2038
2039             if (lf.lfStrikeOut)
2040             {
2041                 pts[0].x = x - strikeoutPos * sinEsc;
2042                 pts[0].y = y - strikeoutPos * cosEsc;
2043                 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2044                 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2045                 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2046                 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2047                 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2048                 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2049                 pts[4].x = pts[0].x;
2050                 pts[4].y = pts[0].y;
2051                 DPtoLP(hdc, pts, 5);
2052                 Polygon(hdc, pts, 5);
2053             }
2054
2055             SelectObject(hdc, hpen);
2056             hbrush = SelectObject(hdc, hbrush);
2057             DeleteObject(hbrush);
2058         }
2059         else
2060         {
2061             POINT pts[2], oldpt;
2062             HPEN hpen;
2063
2064             if (lf.lfUnderline)
2065             {
2066                 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2067                 hpen = SelectObject(hdc, hpen);
2068                 pts[0].x = x;
2069                 pts[0].y = y;
2070                 pts[1].x = x + xwidth;
2071                 pts[1].y = y - ywidth;
2072                 DPtoLP(hdc, pts, 2);
2073                 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2074                 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2075                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2076                 DeleteObject(SelectObject(hdc, hpen));
2077             }
2078
2079             if (lf.lfStrikeOut)
2080             {
2081                 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2082                 hpen = SelectObject(hdc, hpen);
2083                 pts[0].x = x;
2084                 pts[0].y = y;
2085                 pts[1].x = x + xwidth;
2086                 pts[1].y = y - ywidth;
2087                 DPtoLP(hdc, pts, 2);
2088                 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2089                 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2090                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2091                 DeleteObject(SelectObject(hdc, hpen));
2092             }
2093         }
2094     }
2095
2096     return ret;
2097 }
2098
2099
2100 /***********************************************************************
2101  *           TextOutA    (GDI32.@)
2102  */
2103 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2104 {
2105     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2106 }
2107
2108
2109 /***********************************************************************
2110  *           TextOutW    (GDI32.@)
2111  */
2112 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2113 {
2114     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2115 }
2116
2117
2118 /***********************************************************************
2119  *              PolyTextOutA (GDI32.@)
2120  *
2121  * See PolyTextOutW.
2122  */
2123 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2124 {
2125     for (; cStrings>0; cStrings--, pptxt++)
2126         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2127             return FALSE;
2128     return TRUE;
2129 }
2130
2131
2132
2133 /***********************************************************************
2134  *              PolyTextOutW (GDI32.@)
2135  *
2136  * Draw several Strings
2137  *
2138  * RETURNS
2139  *  TRUE:  Success.
2140  *  FALSE: Failure.
2141  */
2142 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2143 {
2144     for (; cStrings>0; cStrings--, pptxt++)
2145         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2146             return FALSE;
2147     return TRUE;
2148 }
2149
2150
2151 /* FIXME: all following APIs ******************************************/
2152
2153
2154 /***********************************************************************
2155  *           SetMapperFlags    (GDI32.@)
2156  */
2157 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2158 {
2159     DC *dc = get_dc_ptr( hDC );
2160     DWORD ret = 0;
2161     if(!dc) return 0;
2162     if(dc->funcs->pSetMapperFlags)
2163     {
2164         ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2165         /* FIXME: ret is just a success flag, we should return a proper value */
2166     }
2167     else
2168         FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2169     release_dc_ptr( dc );
2170     return ret;
2171 }
2172
2173 /***********************************************************************
2174  *          GetAspectRatioFilterEx  (GDI32.@)
2175  */
2176 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2177 {
2178   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2179   return FALSE;
2180 }
2181
2182
2183 /***********************************************************************
2184  *           GetCharABCWidthsA   (GDI32.@)
2185  *
2186  * See GetCharABCWidthsW.
2187  */
2188 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2189                                   LPABC abc )
2190 {
2191     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2192     LPSTR str;
2193     LPWSTR wstr;
2194     BOOL ret = TRUE;
2195
2196     if(count <= 0) return FALSE;
2197
2198     str = HeapAlloc(GetProcessHeap(), 0, count);
2199     for(i = 0; i < count; i++)
2200         str[i] = (BYTE)(firstChar + i);
2201
2202     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2203
2204     for(i = 0; i < wlen; i++)
2205     {
2206         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2207         {
2208             ret = FALSE;
2209             break;
2210         }
2211         abc++;
2212     }
2213
2214     HeapFree(GetProcessHeap(), 0, str);
2215     HeapFree(GetProcessHeap(), 0, wstr);
2216
2217     return ret;
2218 }
2219
2220
2221 /******************************************************************************
2222  * GetCharABCWidthsW [GDI32.@]
2223  *
2224  * Retrieves widths of characters in range.
2225  *
2226  * PARAMS
2227  *    hdc       [I] Handle of device context
2228  *    firstChar [I] First character in range to query
2229  *    lastChar  [I] Last character in range to query
2230  *    abc       [O] Address of character-width structure
2231  *
2232  * NOTES
2233  *    Only works with TrueType fonts
2234  *
2235  * RETURNS
2236  *    Success: TRUE
2237  *    Failure: FALSE
2238  */
2239 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2240                                    LPABC abc )
2241 {
2242     DC *dc = get_dc_ptr(hdc);
2243     unsigned int i;
2244     BOOL ret = FALSE;
2245
2246     if (!dc) return FALSE;
2247
2248     if (!abc)
2249     {
2250         release_dc_ptr( dc );
2251         return FALSE;
2252     }
2253
2254     if(dc->gdiFont)
2255         ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2256     else
2257         FIXME(": stub\n");
2258
2259     if (ret)
2260     {
2261         /* convert device units to logical */
2262         for( i = firstChar; i <= lastChar; i++, abc++ ) {
2263             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2264             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2265             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2266         }
2267         ret = TRUE;
2268     }
2269
2270     release_dc_ptr( dc );
2271     return ret;
2272 }
2273
2274
2275 /******************************************************************************
2276  * GetCharABCWidthsI [GDI32.@]
2277  *
2278  * Retrieves widths of characters in range.
2279  *
2280  * PARAMS
2281  *    hdc       [I] Handle of device context
2282  *    firstChar [I] First glyphs in range to query
2283  *    count     [I] Last glyphs in range to query
2284  *    pgi       [i] Array of glyphs to query
2285  *    abc       [O] Address of character-width structure
2286  *
2287  * NOTES
2288  *    Only works with TrueType fonts
2289  *
2290  * RETURNS
2291  *    Success: TRUE
2292  *    Failure: FALSE
2293  */
2294 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2295                                LPWORD pgi, LPABC abc)
2296 {
2297     DC *dc = get_dc_ptr(hdc);
2298     unsigned int i;
2299     BOOL ret = FALSE;
2300
2301     if (!dc) return FALSE;
2302
2303     if (!abc)
2304     {
2305         release_dc_ptr( dc );
2306         return FALSE;
2307     }
2308
2309     if(dc->gdiFont)
2310         ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2311     else
2312         FIXME(": stub\n");
2313
2314     if (ret)
2315     {
2316         /* convert device units to logical */
2317         for( i = 0; i < count; i++, abc++ ) {
2318             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2319             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2320             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2321         }
2322         ret = TRUE;
2323     }
2324
2325     release_dc_ptr( dc );
2326     return ret;
2327 }
2328
2329
2330 /***********************************************************************
2331  *           GetGlyphOutlineA    (GDI32.@)
2332  */
2333 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2334                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2335                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2336 {
2337     LPWSTR p = NULL;
2338     DWORD ret;
2339     UINT c;
2340
2341     if (!lpmat2) return GDI_ERROR;
2342
2343     if(!(fuFormat & GGO_GLYPH_INDEX)) {
2344         int len;
2345         char mbchs[2];
2346         if(uChar > 0xff) { /* but, 2 bytes character only */
2347             len = 2;
2348             mbchs[0] = (uChar & 0xff00) >> 8;
2349             mbchs[1] = (uChar & 0xff);
2350         } else {
2351             len = 1;
2352             mbchs[0] = (uChar & 0xff);
2353         }
2354         p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2355         c = p[0];
2356     } else
2357         c = uChar;
2358     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2359                            lpmat2);
2360     HeapFree(GetProcessHeap(), 0, p);
2361     return ret;
2362 }
2363
2364 /***********************************************************************
2365  *           GetGlyphOutlineW    (GDI32.@)
2366  */
2367 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2368                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2369                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2370 {
2371     DC *dc;
2372     DWORD ret;
2373
2374     TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2375           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2376
2377     if (!lpmat2) return GDI_ERROR;
2378
2379     dc = get_dc_ptr(hdc);
2380     if(!dc) return GDI_ERROR;
2381
2382     if(dc->gdiFont)
2383       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2384                                    cbBuffer, lpBuffer, lpmat2);
2385     else
2386       ret = GDI_ERROR;
2387
2388     release_dc_ptr( dc );
2389     return ret;
2390 }
2391
2392
2393 /***********************************************************************
2394  *           CreateScalableFontResourceA   (GDI32.@)
2395  */
2396 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2397                                              LPCSTR lpszResourceFile,
2398                                              LPCSTR lpszFontFile,
2399                                              LPCSTR lpszCurrentPath )
2400 {
2401     LPWSTR lpszResourceFileW = NULL;
2402     LPWSTR lpszFontFileW = NULL;
2403     LPWSTR lpszCurrentPathW = NULL;
2404     int len;
2405     BOOL ret;
2406
2407     if (lpszResourceFile)
2408     {
2409         len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2410         lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2411         MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2412     }
2413
2414     if (lpszFontFile)
2415     {
2416         len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2417         lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2418         MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2419     }
2420
2421     if (lpszCurrentPath)
2422     {
2423         len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2424         lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2425         MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2426     }
2427
2428     ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2429             lpszFontFileW, lpszCurrentPathW);
2430
2431     HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2432     HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2433     HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2434
2435     return ret;
2436 }
2437
2438 /***********************************************************************
2439  *           CreateScalableFontResourceW   (GDI32.@)
2440  */
2441 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2442                                              LPCWSTR lpszResourceFile,
2443                                              LPCWSTR lpszFontFile,
2444                                              LPCWSTR lpszCurrentPath )
2445 {
2446     HANDLE f;
2447     FIXME("(%d,%s,%s,%s): stub\n",
2448           fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2449           debugstr_w(lpszCurrentPath) );
2450
2451     /* fHidden=1 - only visible for the calling app, read-only, not
2452      * enumerated with EnumFonts/EnumFontFamilies
2453      * lpszCurrentPath can be NULL
2454      */
2455
2456     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2457     if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2458         CloseHandle(f);
2459         SetLastError(ERROR_FILE_EXISTS);
2460         return FALSE;
2461     }
2462     return FALSE; /* create failed */
2463 }
2464
2465 /*************************************************************************
2466  *             GetKerningPairsA   (GDI32.@)
2467  */
2468 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2469                                LPKERNINGPAIR kern_pairA )
2470 {
2471     INT charset;
2472     CHARSETINFO csi;
2473     CPINFO cpi;
2474     DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2475     KERNINGPAIR *kern_pairW;
2476
2477     if (!cPairs && kern_pairA)
2478     {
2479         SetLastError(ERROR_INVALID_PARAMETER);
2480         return 0;
2481     }
2482
2483     charset = GetTextCharset(hDC);
2484     if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2485     {
2486         FIXME("Can't find codepage for charset %d\n", charset);
2487         return 0;
2488     }
2489     /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2490      * to fail on an invalid character for CP_SYMBOL.
2491      */
2492     cpi.DefaultChar[0] = 0;
2493     if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2494     {
2495         FIXME("Can't find codepage %u info\n", csi.ciACP);
2496         return 0;
2497     }
2498     TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2499
2500     total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2501     if (!total_kern_pairs) return 0;
2502
2503     kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2504     GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2505
2506     for (i = 0; i < total_kern_pairs; i++)
2507     {
2508         char first, second;
2509
2510         if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2511             continue;
2512
2513         if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2514             continue;
2515
2516         if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2517             continue;
2518
2519         if (kern_pairA)
2520         {
2521             if (kern_pairs_copied >= cPairs) break;
2522
2523             kern_pairA->wFirst = (BYTE)first;
2524             kern_pairA->wSecond = (BYTE)second;
2525             kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2526             kern_pairA++;
2527         }
2528         kern_pairs_copied++;
2529     }
2530
2531     HeapFree(GetProcessHeap(), 0, kern_pairW);
2532
2533     return kern_pairs_copied;
2534 }
2535
2536 /*************************************************************************
2537  *             GetKerningPairsW   (GDI32.@)
2538  */
2539 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2540                                  LPKERNINGPAIR lpKerningPairs )
2541 {
2542     DC *dc;
2543     DWORD ret = 0;
2544
2545     TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2546
2547     if (!cPairs && lpKerningPairs)
2548     {
2549         SetLastError(ERROR_INVALID_PARAMETER);
2550         return 0;
2551     }
2552
2553     dc = get_dc_ptr(hDC);
2554     if (!dc) return 0;
2555
2556     if (dc->gdiFont)
2557         ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2558
2559     release_dc_ptr( dc );
2560     return ret;
2561 }
2562
2563 /*************************************************************************
2564  * TranslateCharsetInfo [GDI32.@]
2565  *
2566  * Fills a CHARSETINFO structure for a character set, code page, or
2567  * font. This allows making the correspondence between different labels
2568  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2569  * of the same encoding.
2570  *
2571  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2572  * only one codepage should be set in *lpSrc.
2573  *
2574  * RETURNS
2575  *   TRUE on success, FALSE on failure.
2576  *
2577  */
2578 BOOL WINAPI TranslateCharsetInfo(
2579   LPDWORD lpSrc, /* [in]
2580        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2581        if flags == TCI_SRCCHARSET: a character set value
2582        if flags == TCI_SRCCODEPAGE: a code page value
2583                  */
2584   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2585   DWORD flags /* [in] determines interpretation of lpSrc */)
2586 {
2587     int index = 0;
2588     switch (flags) {
2589     case TCI_SRCFONTSIG:
2590         while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2591       break;
2592     case TCI_SRCCODEPAGE:
2593       while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2594       break;
2595     case TCI_SRCCHARSET:
2596       while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2597       break;
2598     default:
2599       return FALSE;
2600     }
2601     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2602     *lpCs = FONT_tci[index];
2603     return TRUE;
2604 }
2605
2606 /*************************************************************************
2607  *             GetFontLanguageInfo   (GDI32.@)
2608  */
2609 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2610 {
2611         FONTSIGNATURE fontsig;
2612         static const DWORD GCP_DBCS_MASK=0x003F0000,
2613                 GCP_DIACRITIC_MASK=0x00000000,
2614                 FLI_GLYPHS_MASK=0x00000000,
2615                 GCP_GLYPHSHAPE_MASK=0x00000040,
2616                 GCP_KASHIDA_MASK=0x00000000,
2617                 GCP_LIGATE_MASK=0x00000000,
2618                 GCP_USEKERNING_MASK=0x00000000,
2619                 GCP_REORDER_MASK=0x00000060;
2620
2621         DWORD result=0;
2622
2623         GetTextCharsetInfo( hdc, &fontsig, 0 );
2624         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2625
2626         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2627                 result|=GCP_DBCS;
2628
2629         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2630                 result|=GCP_DIACRITIC;
2631
2632         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2633                 result|=FLI_GLYPHS;
2634
2635         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2636                 result|=GCP_GLYPHSHAPE;
2637
2638         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2639                 result|=GCP_KASHIDA;
2640
2641         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2642                 result|=GCP_LIGATE;
2643
2644         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2645                 result|=GCP_USEKERNING;
2646
2647         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2648         if( GetTextAlign( hdc) & TA_RTLREADING )
2649             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2650                     result|=GCP_REORDER;
2651
2652         return result;
2653 }
2654
2655
2656 /*************************************************************************
2657  * GetFontData [GDI32.@]
2658  *
2659  * Retrieve data for TrueType font.
2660  *
2661  * RETURNS
2662  *
2663  * success: Number of bytes returned
2664  * failure: GDI_ERROR
2665  *
2666  * NOTES
2667  *
2668  * Calls SetLastError()
2669  *
2670  */
2671 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2672     LPVOID buffer, DWORD length)
2673 {
2674     DC *dc = get_dc_ptr(hdc);
2675     DWORD ret = GDI_ERROR;
2676
2677     if(!dc) return GDI_ERROR;
2678
2679     if(dc->gdiFont)
2680       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2681
2682     release_dc_ptr( dc );
2683     return ret;
2684 }
2685
2686 /*************************************************************************
2687  * GetGlyphIndicesA [GDI32.@]
2688  */
2689 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2690                               LPWORD pgi, DWORD flags)
2691 {
2692     DWORD ret;
2693     WCHAR *lpstrW;
2694     INT countW;
2695
2696     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2697           hdc, debugstr_an(lpstr, count), count, pgi, flags);
2698
2699     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2700     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2701     HeapFree(GetProcessHeap(), 0, lpstrW);
2702
2703     return ret;
2704 }
2705
2706 /*************************************************************************
2707  * GetGlyphIndicesW [GDI32.@]
2708  */
2709 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2710                               LPWORD pgi, DWORD flags)
2711 {
2712     DC *dc = get_dc_ptr(hdc);
2713     DWORD ret = GDI_ERROR;
2714
2715     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2716           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2717
2718     if(!dc) return GDI_ERROR;
2719
2720     if(dc->gdiFont)
2721         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2722
2723     release_dc_ptr( dc );
2724     return ret;
2725 }
2726
2727 /*************************************************************************
2728  * GetCharacterPlacementA [GDI32.@]
2729  *
2730  * See GetCharacterPlacementW.
2731  *
2732  * NOTES:
2733  *  the web browser control of ie4 calls this with dwFlags=0
2734  */
2735 DWORD WINAPI
2736 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2737                          INT nMaxExtent, GCP_RESULTSA *lpResults,
2738                          DWORD dwFlags)
2739 {
2740     WCHAR *lpStringW;
2741     INT uCountW;
2742     GCP_RESULTSW resultsW;
2743     DWORD ret;
2744     UINT font_cp;
2745
2746     TRACE("%s, %d, %d, 0x%08x\n",
2747           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2748
2749     /* both structs are equal in size */
2750     memcpy(&resultsW, lpResults, sizeof(resultsW));
2751
2752     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2753     if(lpResults->lpOutString)
2754         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2755
2756     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2757
2758     lpResults->nGlyphs = resultsW.nGlyphs;
2759     lpResults->nMaxFit = resultsW.nMaxFit;
2760
2761     if(lpResults->lpOutString) {
2762         WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2763                             lpResults->lpOutString, uCount, NULL, NULL );
2764     }
2765
2766     HeapFree(GetProcessHeap(), 0, lpStringW);
2767     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2768
2769     return ret;
2770 }
2771
2772 /*************************************************************************
2773  * GetCharacterPlacementW [GDI32.@]
2774  *
2775  *   Retrieve information about a string. This includes the width, reordering,
2776  *   Glyphing and so on.
2777  *
2778  * RETURNS
2779  *
2780  *   The width and height of the string if successful, 0 if failed.
2781  *
2782  * BUGS
2783  *
2784  *   All flags except GCP_REORDER are not yet implemented.
2785  *   Reordering is not 100% compliant to the Windows BiDi method.
2786  *   Caret positioning is not yet implemented for BiDi.
2787  *   Classes are not yet implemented.
2788  *
2789  */
2790 DWORD WINAPI
2791 GetCharacterPlacementW(
2792                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
2793                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
2794                 INT uCount,             /* [in] Number of WORDS in string. */
2795                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
2796                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2797                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
2798                 )
2799 {
2800     DWORD ret=0;
2801     SIZE size;
2802     UINT i, nSet;
2803
2804     TRACE("%s, %d, %d, 0x%08x\n",
2805           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2806
2807     TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2808           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2809             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2810             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2811             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2812
2813     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08x ignored\n", dwFlags);
2814     if(lpResults->lpClass)      FIXME("classes not implemented\n");
2815     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2816         FIXME("Caret positions for complex scripts not implemented\n");
2817
2818         nSet = (UINT)uCount;
2819         if(nSet > lpResults->nGlyphs)
2820                 nSet = lpResults->nGlyphs;
2821
2822         /* return number of initialized fields */
2823         lpResults->nGlyphs = nSet;
2824
2825         if((dwFlags&GCP_REORDER)==0 )
2826         {
2827                 /* Treat the case where no special handling was requested in a fastpath way */
2828                 /* copy will do if the GCP_REORDER flag is not set */
2829                 if(lpResults->lpOutString)
2830                     memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2831
2832                 if(lpResults->lpOrder)
2833                 {
2834                         for(i = 0; i < nSet; i++)
2835                                 lpResults->lpOrder[i] = i;
2836                 }
2837         } else
2838         {
2839             BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2840                           nSet, lpResults->lpOrder );
2841         }
2842
2843         /* FIXME: Will use the placement chars */
2844         if (lpResults->lpDx)
2845         {
2846                 int c;
2847                 for (i = 0; i < nSet; i++)
2848                 {
2849                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2850                                 lpResults->lpDx[i]= c;
2851                 }
2852         }
2853
2854     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2855     {
2856         int pos = 0;
2857        
2858         lpResults->lpCaretPos[0] = 0;
2859         for (i = 1; i < nSet; i++)
2860             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2861                 lpResults->lpCaretPos[i] = (pos += size.cx);
2862     }
2863    
2864     if(lpResults->lpGlyphs)
2865         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2866
2867     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2868       ret = MAKELONG(size.cx, size.cy);
2869
2870     return ret;
2871 }
2872
2873 /*************************************************************************
2874  *      GetCharABCWidthsFloatA [GDI32.@]
2875  *
2876  * See GetCharABCWidthsFloatW.
2877  */
2878 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2879 {
2880     INT i, wlen, count = (INT)(last - first + 1);
2881     LPSTR str;
2882     LPWSTR wstr;
2883     BOOL ret = TRUE;
2884
2885     if (count <= 0) return FALSE;
2886
2887     str = HeapAlloc(GetProcessHeap(), 0, count);
2888
2889     for(i = 0; i < count; i++)
2890         str[i] = (BYTE)(first + i);
2891
2892     wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2893
2894     for (i = 0; i < wlen; i++)
2895     {
2896         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2897         {
2898             ret = FALSE;
2899             break;
2900         }
2901         abcf++;
2902     }
2903
2904     HeapFree( GetProcessHeap(), 0, str );
2905     HeapFree( GetProcessHeap(), 0, wstr );
2906
2907     return ret;
2908 }
2909
2910 /*************************************************************************
2911  *      GetCharABCWidthsFloatW [GDI32.@]
2912  *
2913  * Retrieves widths of a range of characters.
2914  *
2915  * PARAMS
2916  *    hdc   [I] Handle to device context.
2917  *    first [I] First character in range to query.
2918  *    last  [I] Last character in range to query.
2919  *    abcf  [O] Array of LPABCFLOAT structures.
2920  *
2921  * RETURNS
2922  *    Success: TRUE
2923  *    Failure: FALSE
2924  *
2925  * BUGS
2926  *    Only works with TrueType fonts. It also doesn't return real
2927  *    floats but converted integers because it's implemented on
2928  *    top of GetCharABCWidthsW.
2929  */
2930 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2931 {
2932     ABC *abc, *abc_base;
2933     unsigned int i, size = sizeof(ABC) * (last - first + 1);
2934     BOOL ret;
2935
2936     TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2937
2938     abc = abc_base = HeapAlloc( GetProcessHeap(), 0, size );
2939     if (!abc) return FALSE;
2940
2941     ret = GetCharABCWidthsW( hdc, first, last, abc );
2942     if (ret)
2943     {
2944         for (i = first; i <= last; i++, abc++, abcf++)
2945         {
2946             abcf->abcfA = abc->abcA;
2947             abcf->abcfB = abc->abcB;
2948             abcf->abcfC = abc->abcC;
2949         }
2950     }
2951     HeapFree( GetProcessHeap(), 0, abc_base );
2952     return ret;
2953 }
2954
2955 /*************************************************************************
2956  *      GetCharWidthFloatA [GDI32.@]
2957  */
2958 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2959                                     UINT iLastChar, PFLOAT pxBuffer)
2960 {
2961     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2962     return 0;
2963 }
2964
2965 /*************************************************************************
2966  *      GetCharWidthFloatW [GDI32.@]
2967  */
2968 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2969                                     UINT iLastChar, PFLOAT pxBuffer)
2970 {
2971     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2972     return 0;
2973 }
2974
2975
2976 /***********************************************************************
2977  *                                                                     *
2978  *           Font Resource API                                         *
2979  *                                                                     *
2980  ***********************************************************************/
2981
2982 /***********************************************************************
2983  *           AddFontResourceA    (GDI32.@)
2984  */
2985 INT WINAPI AddFontResourceA( LPCSTR str )
2986 {
2987     return AddFontResourceExA( str, 0, NULL);
2988 }
2989
2990 /***********************************************************************
2991  *           AddFontResourceW    (GDI32.@)
2992  */
2993 INT WINAPI AddFontResourceW( LPCWSTR str )
2994 {
2995     return AddFontResourceExW(str, 0, NULL);
2996 }
2997
2998
2999 /***********************************************************************
3000  *           AddFontResourceExA    (GDI32.@)
3001  */
3002 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3003 {
3004     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3005     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3006     INT ret;
3007
3008     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3009     ret = AddFontResourceExW(strW, fl, pdv);
3010     HeapFree(GetProcessHeap(), 0, strW);
3011     return ret;
3012 }
3013
3014 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3015 {
3016     HRSRC rsrc = FindResourceW(hModule, name, type);
3017     HGLOBAL hMem = LoadResource(hModule, rsrc);
3018     LPVOID *pMem = LockResource(hMem);
3019     int *num_total = (int *)lParam;
3020     DWORD num_in_res;
3021
3022     TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3023     if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3024     {
3025         ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3026         return FALSE;
3027     }
3028
3029     *num_total += num_in_res;
3030     return TRUE;
3031 }
3032
3033 /***********************************************************************
3034  *           AddFontResourceExW    (GDI32.@)
3035  */
3036 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3037 {
3038     int ret = WineEngAddFontResourceEx(str, fl, pdv);
3039     if (ret == 0)
3040     {
3041         /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3042         HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3043         if (hModule != NULL)
3044         {
3045             int num_resources = 0;
3046             LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8);  /* we don't want to include winuser.h */
3047
3048             TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3049                 wine_dbgstr_w(str));
3050             if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3051                 ret = num_resources;
3052             FreeLibrary(hModule);
3053         }
3054     }
3055     return ret;
3056 }
3057
3058 /***********************************************************************
3059  *           RemoveFontResourceA    (GDI32.@)
3060  */
3061 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3062 {
3063     return RemoveFontResourceExA(str, 0, 0);
3064 }
3065
3066 /***********************************************************************
3067  *           RemoveFontResourceW    (GDI32.@)
3068  */
3069 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3070 {
3071     return RemoveFontResourceExW(str, 0, 0);
3072 }
3073
3074 /***********************************************************************
3075  *           AddFontMemResourceEx    (GDI32.@)
3076  */
3077 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3078 {
3079     return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3080 }
3081
3082 /***********************************************************************
3083  *           RemoveFontMemResourceEx    (GDI32.@)
3084  */
3085 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3086 {
3087     FIXME("(%p) stub\n", fh);
3088     return TRUE;
3089 }
3090
3091 /***********************************************************************
3092  *           RemoveFontResourceExA    (GDI32.@)
3093  */
3094 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3095 {
3096     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3097     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3098     INT ret;
3099
3100     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3101     ret = RemoveFontResourceExW(strW, fl, pdv);
3102     HeapFree(GetProcessHeap(), 0, strW);
3103     return ret;
3104 }
3105
3106 /***********************************************************************
3107  *           RemoveFontResourceExW    (GDI32.@)
3108  */
3109 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3110 {
3111     return WineEngRemoveFontResourceEx(str, fl, pdv);
3112 }
3113
3114 /***********************************************************************
3115  *           GetTextCharset    (GDI32.@)
3116  */
3117 UINT WINAPI GetTextCharset(HDC hdc)
3118 {
3119     /* MSDN docs say this is equivalent */
3120     return GetTextCharsetInfo(hdc, NULL, 0);
3121 }
3122
3123 /***********************************************************************
3124  *           GetTextCharsetInfo    (GDI32.@)
3125  */
3126 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3127 {
3128     UINT ret = DEFAULT_CHARSET;
3129     DC *dc = get_dc_ptr(hdc);
3130
3131     if (dc)
3132     {
3133         if (dc->gdiFont)
3134             ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3135
3136         release_dc_ptr( dc );
3137     }
3138
3139     if (ret == DEFAULT_CHARSET && fs)
3140         memset(fs, 0, sizeof(FONTSIGNATURE));
3141     return ret;
3142 }
3143
3144 /***********************************************************************
3145  *           GdiGetCharDimensions    (GDI32.@)
3146  *
3147  * Gets the average width of the characters in the English alphabet.
3148  *
3149  * PARAMS
3150  *  hdc    [I] Handle to the device context to measure on.
3151  *  lptm   [O] Pointer to memory to store the text metrics into.
3152  *  height [O] On exit, the maximum height of characters in the English alphabet.
3153  *
3154  * RETURNS
3155  *  The average width of characters in the English alphabet.
3156  *
3157  * NOTES
3158  *  This function is used by the dialog manager to get the size of a dialog
3159  *  unit. It should also be used by other pieces of code that need to know
3160  *  the size of a dialog unit in logical units without having access to the
3161  *  window handle of the dialog.
3162  *  Windows caches the font metrics from this function, but we don't and
3163  *  there doesn't appear to be an immediate advantage to do so.
3164  *
3165  * SEE ALSO
3166  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3167  */
3168 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3169 {
3170     SIZE sz;
3171     static const WCHAR alphabet[] = {
3172         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3173         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3174         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3175
3176     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3177
3178     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3179
3180     if (height) *height = sz.cy;
3181     return (sz.cx / 26 + 1) / 2;
3182 }
3183
3184 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3185 {
3186     FIXME("(%d): stub\n", fEnableEUDC);
3187     return FALSE;
3188 }
3189
3190 /***********************************************************************
3191  *           GetCharWidthI    (GDI32.@)
3192  *
3193  * Retrieve widths of characters.
3194  *
3195  * PARAMS
3196  *  hdc    [I] Handle to a device context.
3197  *  first  [I] First glyph in range to query.
3198  *  count  [I] Number of glyph indices to query.
3199  *  glyphs [I] Array of glyphs to query.
3200  *  buffer [O] Buffer to receive character widths.
3201  *
3202  * NOTES
3203  *  Only works with TrueType fonts.
3204  *
3205  * RETURNS
3206  *  Success: TRUE
3207  *  Failure: FALSE
3208  */
3209 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3210 {
3211     ABC *abc;
3212     unsigned int i;
3213
3214     TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3215
3216     if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3217         return FALSE;
3218
3219     if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3220     {
3221         HeapFree(GetProcessHeap(), 0, abc);
3222         return FALSE;
3223     }
3224
3225     for (i = 0; i < count; i++)
3226         buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3227
3228     HeapFree(GetProcessHeap(), 0, abc);
3229     return TRUE;
3230 }
3231
3232 /***********************************************************************
3233  *           GetFontUnicodeRanges    (GDI32.@)
3234  *
3235  *  Retrieve a list of supported Unicode characters in a font.
3236  *
3237  *  PARAMS
3238  *   hdc  [I] Handle to a device context.
3239  *   lpgs [O] GLYPHSET structure specifying supported character ranges.
3240  *
3241  *  RETURNS
3242  *   Success: Number of bytes written to the buffer pointed to by lpgs.
3243  *   Failure: 0
3244  *
3245  */
3246 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3247 {
3248     DWORD ret = 0;
3249     DC *dc = get_dc_ptr(hdc);
3250
3251     TRACE("(%p, %p)\n", hdc, lpgs);
3252
3253     if (!dc) return 0;
3254
3255     if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3256     release_dc_ptr(dc);
3257     return ret;
3258 }
3259
3260
3261 /*************************************************************
3262  *           FontIsLinked    (GDI32.@)
3263  */
3264 BOOL WINAPI FontIsLinked(HDC hdc)
3265 {
3266     DC *dc = get_dc_ptr(hdc);
3267     BOOL ret = FALSE;
3268
3269     if (!dc) return FALSE;
3270     if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3271     release_dc_ptr(dc);
3272     TRACE("returning %d\n", ret);
3273     return ret;
3274 }
3275
3276 /*************************************************************
3277  *           GdiRealizationInfo    (GDI32.@)
3278  *
3279  * Returns a structure that contains some font information.
3280  */
3281 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3282 {
3283     DC *dc = get_dc_ptr(hdc);
3284     BOOL ret = FALSE;
3285
3286     if (!dc) return FALSE;
3287     if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3288     release_dc_ptr(dc);
3289
3290     return ret;
3291 }