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