mapi32/tests: Fix typo.
[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 (!lpmat2) return GDI_ERROR;
2340
2341     if(!(fuFormat & GGO_GLYPH_INDEX)) {
2342         int len;
2343         char mbchs[2];
2344         if(uChar > 0xff) { /* but, 2 bytes character only */
2345             len = 2;
2346             mbchs[0] = (uChar & 0xff00) >> 8;
2347             mbchs[1] = (uChar & 0xff);
2348         } else {
2349             len = 1;
2350             mbchs[0] = (uChar & 0xff);
2351         }
2352         p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2353         c = p[0];
2354     } else
2355         c = uChar;
2356     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2357                            lpmat2);
2358     HeapFree(GetProcessHeap(), 0, p);
2359     return ret;
2360 }
2361
2362 /***********************************************************************
2363  *           GetGlyphOutlineW    (GDI32.@)
2364  */
2365 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2366                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2367                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2368 {
2369     DC *dc;
2370     DWORD ret;
2371
2372     TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2373           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2374
2375     if (!lpmat2) return GDI_ERROR;
2376
2377     dc = get_dc_ptr(hdc);
2378     if(!dc) return GDI_ERROR;
2379
2380     if(dc->gdiFont)
2381       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2382                                    cbBuffer, lpBuffer, lpmat2);
2383     else
2384       ret = GDI_ERROR;
2385
2386     release_dc_ptr( dc );
2387     return ret;
2388 }
2389
2390
2391 /***********************************************************************
2392  *           CreateScalableFontResourceA   (GDI32.@)
2393  */
2394 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2395                                              LPCSTR lpszResourceFile,
2396                                              LPCSTR lpszFontFile,
2397                                              LPCSTR lpszCurrentPath )
2398 {
2399     LPWSTR lpszResourceFileW = NULL;
2400     LPWSTR lpszFontFileW = NULL;
2401     LPWSTR lpszCurrentPathW = NULL;
2402     int len;
2403     BOOL ret;
2404
2405     if (lpszResourceFile)
2406     {
2407         len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2408         lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2409         MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2410     }
2411
2412     if (lpszFontFile)
2413     {
2414         len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2415         lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2416         MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2417     }
2418
2419     if (lpszCurrentPath)
2420     {
2421         len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2422         lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2423         MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2424     }
2425
2426     ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2427             lpszFontFileW, lpszCurrentPathW);
2428
2429     HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2430     HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2431     HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2432
2433     return ret;
2434 }
2435
2436 /***********************************************************************
2437  *           CreateScalableFontResourceW   (GDI32.@)
2438  */
2439 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2440                                              LPCWSTR lpszResourceFile,
2441                                              LPCWSTR lpszFontFile,
2442                                              LPCWSTR lpszCurrentPath )
2443 {
2444     HANDLE f;
2445     FIXME("(%d,%s,%s,%s): stub\n",
2446           fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2447           debugstr_w(lpszCurrentPath) );
2448
2449     /* fHidden=1 - only visible for the calling app, read-only, not
2450      * enumerated with EnumFonts/EnumFontFamilies
2451      * lpszCurrentPath can be NULL
2452      */
2453
2454     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2455     if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2456         CloseHandle(f);
2457         SetLastError(ERROR_FILE_EXISTS);
2458         return FALSE;
2459     }
2460     return FALSE; /* create failed */
2461 }
2462
2463 /*************************************************************************
2464  *             GetKerningPairsA   (GDI32.@)
2465  */
2466 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2467                                LPKERNINGPAIR kern_pairA )
2468 {
2469     INT charset;
2470     CHARSETINFO csi;
2471     CPINFO cpi;
2472     DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2473     KERNINGPAIR *kern_pairW;
2474
2475     if (!cPairs && kern_pairA)
2476     {
2477         SetLastError(ERROR_INVALID_PARAMETER);
2478         return 0;
2479     }
2480
2481     charset = GetTextCharset(hDC);
2482     if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2483     {
2484         FIXME("Can't find codepage for charset %d\n", charset);
2485         return 0;
2486     }
2487     /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2488      * to fail on an invalid character for CP_SYMBOL.
2489      */
2490     cpi.DefaultChar[0] = 0;
2491     if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2492     {
2493         FIXME("Can't find codepage %u info\n", csi.ciACP);
2494         return 0;
2495     }
2496     TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2497
2498     total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2499     if (!total_kern_pairs) return 0;
2500
2501     kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2502     GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2503
2504     for (i = 0; i < total_kern_pairs; i++)
2505     {
2506         char first, second;
2507
2508         if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2509             continue;
2510
2511         if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2512             continue;
2513
2514         if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2515             continue;
2516
2517         if (kern_pairA)
2518         {
2519             if (kern_pairs_copied >= cPairs) break;
2520
2521             kern_pairA->wFirst = (BYTE)first;
2522             kern_pairA->wSecond = (BYTE)second;
2523             kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2524             kern_pairA++;
2525         }
2526         kern_pairs_copied++;
2527     }
2528
2529     HeapFree(GetProcessHeap(), 0, kern_pairW);
2530
2531     return kern_pairs_copied;
2532 }
2533
2534 /*************************************************************************
2535  *             GetKerningPairsW   (GDI32.@)
2536  */
2537 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2538                                  LPKERNINGPAIR lpKerningPairs )
2539 {
2540     DC *dc;
2541     DWORD ret = 0;
2542
2543     TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2544
2545     if (!cPairs && lpKerningPairs)
2546     {
2547         SetLastError(ERROR_INVALID_PARAMETER);
2548         return 0;
2549     }
2550
2551     dc = get_dc_ptr(hDC);
2552     if (!dc) return 0;
2553
2554     if (dc->gdiFont)
2555         ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2556
2557     release_dc_ptr( dc );
2558     return ret;
2559 }
2560
2561 /*************************************************************************
2562  * TranslateCharsetInfo [GDI32.@]
2563  *
2564  * Fills a CHARSETINFO structure for a character set, code page, or
2565  * font. This allows making the correspondence between different labels
2566  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2567  * of the same encoding.
2568  *
2569  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2570  * only one codepage should be set in *lpSrc.
2571  *
2572  * RETURNS
2573  *   TRUE on success, FALSE on failure.
2574  *
2575  */
2576 BOOL WINAPI TranslateCharsetInfo(
2577   LPDWORD lpSrc, /* [in]
2578        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2579        if flags == TCI_SRCCHARSET: a character set value
2580        if flags == TCI_SRCCODEPAGE: a code page value
2581                  */
2582   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2583   DWORD flags /* [in] determines interpretation of lpSrc */)
2584 {
2585     int index = 0;
2586     switch (flags) {
2587     case TCI_SRCFONTSIG:
2588         while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2589       break;
2590     case TCI_SRCCODEPAGE:
2591       while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2592       break;
2593     case TCI_SRCCHARSET:
2594       while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2595       break;
2596     default:
2597       return FALSE;
2598     }
2599     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2600     *lpCs = FONT_tci[index];
2601     return TRUE;
2602 }
2603
2604 /*************************************************************************
2605  *             GetFontLanguageInfo   (GDI32.@)
2606  */
2607 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2608 {
2609         FONTSIGNATURE fontsig;
2610         static const DWORD GCP_DBCS_MASK=0x003F0000,
2611                 GCP_DIACRITIC_MASK=0x00000000,
2612                 FLI_GLYPHS_MASK=0x00000000,
2613                 GCP_GLYPHSHAPE_MASK=0x00000040,
2614                 GCP_KASHIDA_MASK=0x00000000,
2615                 GCP_LIGATE_MASK=0x00000000,
2616                 GCP_USEKERNING_MASK=0x00000000,
2617                 GCP_REORDER_MASK=0x00000060;
2618
2619         DWORD result=0;
2620
2621         GetTextCharsetInfo( hdc, &fontsig, 0 );
2622         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2623
2624         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2625                 result|=GCP_DBCS;
2626
2627         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2628                 result|=GCP_DIACRITIC;
2629
2630         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2631                 result|=FLI_GLYPHS;
2632
2633         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2634                 result|=GCP_GLYPHSHAPE;
2635
2636         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2637                 result|=GCP_KASHIDA;
2638
2639         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2640                 result|=GCP_LIGATE;
2641
2642         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2643                 result|=GCP_USEKERNING;
2644
2645         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2646         if( GetTextAlign( hdc) & TA_RTLREADING )
2647             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2648                     result|=GCP_REORDER;
2649
2650         return result;
2651 }
2652
2653
2654 /*************************************************************************
2655  * GetFontData [GDI32.@]
2656  *
2657  * Retrieve data for TrueType font.
2658  *
2659  * RETURNS
2660  *
2661  * success: Number of bytes returned
2662  * failure: GDI_ERROR
2663  *
2664  * NOTES
2665  *
2666  * Calls SetLastError()
2667  *
2668  */
2669 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2670     LPVOID buffer, DWORD length)
2671 {
2672     DC *dc = get_dc_ptr(hdc);
2673     DWORD ret = GDI_ERROR;
2674
2675     if(!dc) return GDI_ERROR;
2676
2677     if(dc->gdiFont)
2678       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2679
2680     release_dc_ptr( dc );
2681     return ret;
2682 }
2683
2684 /*************************************************************************
2685  * GetGlyphIndicesA [GDI32.@]
2686  */
2687 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2688                               LPWORD pgi, DWORD flags)
2689 {
2690     DWORD ret;
2691     WCHAR *lpstrW;
2692     INT countW;
2693
2694     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2695           hdc, debugstr_an(lpstr, count), count, pgi, flags);
2696
2697     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2698     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2699     HeapFree(GetProcessHeap(), 0, lpstrW);
2700
2701     return ret;
2702 }
2703
2704 /*************************************************************************
2705  * GetGlyphIndicesW [GDI32.@]
2706  */
2707 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2708                               LPWORD pgi, DWORD flags)
2709 {
2710     DC *dc = get_dc_ptr(hdc);
2711     DWORD ret = GDI_ERROR;
2712
2713     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2714           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2715
2716     if(!dc) return GDI_ERROR;
2717
2718     if(dc->gdiFont)
2719         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2720
2721     release_dc_ptr( dc );
2722     return ret;
2723 }
2724
2725 /*************************************************************************
2726  * GetCharacterPlacementA [GDI32.@]
2727  *
2728  * See GetCharacterPlacementW.
2729  *
2730  * NOTES:
2731  *  the web browser control of ie4 calls this with dwFlags=0
2732  */
2733 DWORD WINAPI
2734 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2735                          INT nMaxExtent, GCP_RESULTSA *lpResults,
2736                          DWORD dwFlags)
2737 {
2738     WCHAR *lpStringW;
2739     INT uCountW;
2740     GCP_RESULTSW resultsW;
2741     DWORD ret;
2742     UINT font_cp;
2743
2744     TRACE("%s, %d, %d, 0x%08x\n",
2745           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2746
2747     /* both structs are equal in size */
2748     memcpy(&resultsW, lpResults, sizeof(resultsW));
2749
2750     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2751     if(lpResults->lpOutString)
2752         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2753
2754     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2755
2756     lpResults->nGlyphs = resultsW.nGlyphs;
2757     lpResults->nMaxFit = resultsW.nMaxFit;
2758
2759     if(lpResults->lpOutString) {
2760         WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2761                             lpResults->lpOutString, uCount, NULL, NULL );
2762     }
2763
2764     HeapFree(GetProcessHeap(), 0, lpStringW);
2765     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2766
2767     return ret;
2768 }
2769
2770 /*************************************************************************
2771  * GetCharacterPlacementW [GDI32.@]
2772  *
2773  *   Retrieve information about a string. This includes the width, reordering,
2774  *   Glyphing and so on.
2775  *
2776  * RETURNS
2777  *
2778  *   The width and height of the string if successful, 0 if failed.
2779  *
2780  * BUGS
2781  *
2782  *   All flags except GCP_REORDER are not yet implemented.
2783  *   Reordering is not 100% compliant to the Windows BiDi method.
2784  *   Caret positioning is not yet implemented for BiDi.
2785  *   Classes are not yet implemented.
2786  *
2787  */
2788 DWORD WINAPI
2789 GetCharacterPlacementW(
2790                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
2791                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
2792                 INT uCount,             /* [in] Number of WORDS in string. */
2793                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
2794                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2795                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
2796                 )
2797 {
2798     DWORD ret=0;
2799     SIZE size;
2800     UINT i, nSet;
2801
2802     TRACE("%s, %d, %d, 0x%08x\n",
2803           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2804
2805     TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2806           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2807             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2808             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2809             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2810
2811     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08x ignored\n", dwFlags);
2812     if(lpResults->lpClass)      FIXME("classes not implemented\n");
2813     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2814         FIXME("Caret positions for complex scripts not implemented\n");
2815
2816         nSet = (UINT)uCount;
2817         if(nSet > lpResults->nGlyphs)
2818                 nSet = lpResults->nGlyphs;
2819
2820         /* return number of initialized fields */
2821         lpResults->nGlyphs = nSet;
2822
2823         if((dwFlags&GCP_REORDER)==0 )
2824         {
2825                 /* Treat the case where no special handling was requested in a fastpath way */
2826                 /* copy will do if the GCP_REORDER flag is not set */
2827                 if(lpResults->lpOutString)
2828                     memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2829
2830                 if(lpResults->lpOrder)
2831                 {
2832                         for(i = 0; i < nSet; i++)
2833                                 lpResults->lpOrder[i] = i;
2834                 }
2835         } else
2836         {
2837             BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2838                           nSet, lpResults->lpOrder );
2839         }
2840
2841         /* FIXME: Will use the placement chars */
2842         if (lpResults->lpDx)
2843         {
2844                 int c;
2845                 for (i = 0; i < nSet; i++)
2846                 {
2847                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2848                                 lpResults->lpDx[i]= c;
2849                 }
2850         }
2851
2852     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2853     {
2854         int pos = 0;
2855        
2856         lpResults->lpCaretPos[0] = 0;
2857         for (i = 1; i < nSet; i++)
2858             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2859                 lpResults->lpCaretPos[i] = (pos += size.cx);
2860     }
2861    
2862     if(lpResults->lpGlyphs)
2863         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2864
2865     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2866       ret = MAKELONG(size.cx, size.cy);
2867
2868     return ret;
2869 }
2870
2871 /*************************************************************************
2872  *      GetCharABCWidthsFloatA [GDI32.@]
2873  *
2874  * See GetCharABCWidthsFloatW.
2875  */
2876 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2877 {
2878     INT i, wlen, count = (INT)(last - first + 1);
2879     LPSTR str;
2880     LPWSTR wstr;
2881     BOOL ret = TRUE;
2882
2883     if (count <= 0) return FALSE;
2884
2885     str = HeapAlloc(GetProcessHeap(), 0, count);
2886
2887     for(i = 0; i < count; i++)
2888         str[i] = (BYTE)(first + i);
2889
2890     wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2891
2892     for (i = 0; i < wlen; i++)
2893     {
2894         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2895         {
2896             ret = FALSE;
2897             break;
2898         }
2899         abcf++;
2900     }
2901
2902     HeapFree( GetProcessHeap(), 0, str );
2903     HeapFree( GetProcessHeap(), 0, wstr );
2904
2905     return ret;
2906 }
2907
2908 /*************************************************************************
2909  *      GetCharABCWidthsFloatW [GDI32.@]
2910  *
2911  * Retrieves widths of a range of characters.
2912  *
2913  * PARAMS
2914  *    hdc   [I] Handle to device context.
2915  *    first [I] First character in range to query.
2916  *    last  [I] Last character in range to query.
2917  *    abcf  [O] Array of LPABCFLOAT structures.
2918  *
2919  * RETURNS
2920  *    Success: TRUE
2921  *    Failure: FALSE
2922  *
2923  * BUGS
2924  *    Only works with TrueType fonts. It also doesn't return real
2925  *    floats but converted integers because it's implemented on
2926  *    top of GetCharABCWidthsW.
2927  */
2928 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2929 {
2930     ABC *abc, *abc_base;
2931     unsigned int i, size = sizeof(ABC) * (last - first + 1);
2932     BOOL ret;
2933
2934     TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2935
2936     abc = abc_base = HeapAlloc( GetProcessHeap(), 0, size );
2937     if (!abc) return FALSE;
2938
2939     ret = GetCharABCWidthsW( hdc, first, last, abc );
2940     if (ret)
2941     {
2942         for (i = first; i <= last; i++, abc++, abcf++)
2943         {
2944             abcf->abcfA = abc->abcA;
2945             abcf->abcfB = abc->abcB;
2946             abcf->abcfC = abc->abcC;
2947         }
2948     }
2949     HeapFree( GetProcessHeap(), 0, abc_base );
2950     return ret;
2951 }
2952
2953 /*************************************************************************
2954  *      GetCharWidthFloatA [GDI32.@]
2955  */
2956 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2957                                     UINT iLastChar, PFLOAT pxBuffer)
2958 {
2959     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2960     return 0;
2961 }
2962
2963 /*************************************************************************
2964  *      GetCharWidthFloatW [GDI32.@]
2965  */
2966 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2967                                     UINT iLastChar, PFLOAT pxBuffer)
2968 {
2969     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2970     return 0;
2971 }
2972
2973
2974 /***********************************************************************
2975  *                                                                     *
2976  *           Font Resource API                                         *
2977  *                                                                     *
2978  ***********************************************************************/
2979
2980 /***********************************************************************
2981  *           AddFontResourceA    (GDI32.@)
2982  */
2983 INT WINAPI AddFontResourceA( LPCSTR str )
2984 {
2985     return AddFontResourceExA( str, 0, NULL);
2986 }
2987
2988 /***********************************************************************
2989  *           AddFontResourceW    (GDI32.@)
2990  */
2991 INT WINAPI AddFontResourceW( LPCWSTR str )
2992 {
2993     return AddFontResourceExW(str, 0, NULL);
2994 }
2995
2996
2997 /***********************************************************************
2998  *           AddFontResourceExA    (GDI32.@)
2999  */
3000 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3001 {
3002     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3003     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3004     INT ret;
3005
3006     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3007     ret = AddFontResourceExW(strW, fl, pdv);
3008     HeapFree(GetProcessHeap(), 0, strW);
3009     return ret;
3010 }
3011
3012 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3013 {
3014     HRSRC rsrc = FindResourceW(hModule, name, type);
3015     HGLOBAL hMem = LoadResource(hModule, rsrc);
3016     LPVOID *pMem = LockResource(hMem);
3017     int *num_total = (int *)lParam;
3018     DWORD num_in_res;
3019
3020     TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3021     if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3022     {
3023         ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3024         return FALSE;
3025     }
3026
3027     *num_total += num_in_res;
3028     return TRUE;
3029 }
3030
3031 /***********************************************************************
3032  *           AddFontResourceExW    (GDI32.@)
3033  */
3034 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3035 {
3036     int ret = WineEngAddFontResourceEx(str, fl, pdv);
3037     if (ret == 0)
3038     {
3039         /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3040         HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3041         if (hModule != NULL)
3042         {
3043             int num_resources = 0;
3044             LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8);  /* we don't want to include winuser.h */
3045
3046             TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3047                 wine_dbgstr_w(str));
3048             if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3049                 ret = num_resources;
3050             FreeLibrary(hModule);
3051         }
3052     }
3053     return ret;
3054 }
3055
3056 /***********************************************************************
3057  *           RemoveFontResourceA    (GDI32.@)
3058  */
3059 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3060 {
3061     return RemoveFontResourceExA(str, 0, 0);
3062 }
3063
3064 /***********************************************************************
3065  *           RemoveFontResourceW    (GDI32.@)
3066  */
3067 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3068 {
3069     return RemoveFontResourceExW(str, 0, 0);
3070 }
3071
3072 /***********************************************************************
3073  *           AddFontMemResourceEx    (GDI32.@)
3074  */
3075 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3076 {
3077     return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3078 }
3079
3080 /***********************************************************************
3081  *           RemoveFontMemResourceEx    (GDI32.@)
3082  */
3083 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3084 {
3085     FIXME("(%p) stub\n", fh);
3086     return TRUE;
3087 }
3088
3089 /***********************************************************************
3090  *           RemoveFontResourceExA    (GDI32.@)
3091  */
3092 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3093 {
3094     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3095     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3096     INT ret;
3097
3098     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3099     ret = RemoveFontResourceExW(strW, fl, pdv);
3100     HeapFree(GetProcessHeap(), 0, strW);
3101     return ret;
3102 }
3103
3104 /***********************************************************************
3105  *           RemoveFontResourceExW    (GDI32.@)
3106  */
3107 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3108 {
3109     return WineEngRemoveFontResourceEx(str, fl, pdv);
3110 }
3111
3112 /***********************************************************************
3113  *           GetTextCharset    (GDI32.@)
3114  */
3115 UINT WINAPI GetTextCharset(HDC hdc)
3116 {
3117     /* MSDN docs say this is equivalent */
3118     return GetTextCharsetInfo(hdc, NULL, 0);
3119 }
3120
3121 /***********************************************************************
3122  *           GetTextCharsetInfo    (GDI32.@)
3123  */
3124 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3125 {
3126     UINT ret = DEFAULT_CHARSET;
3127     DC *dc = get_dc_ptr(hdc);
3128
3129     if (dc)
3130     {
3131         if (dc->gdiFont)
3132             ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3133
3134         release_dc_ptr( dc );
3135     }
3136
3137     if (ret == DEFAULT_CHARSET && fs)
3138         memset(fs, 0, sizeof(FONTSIGNATURE));
3139     return ret;
3140 }
3141
3142 /***********************************************************************
3143  *           GdiGetCharDimensions    (GDI32.@)
3144  *
3145  * Gets the average width of the characters in the English alphabet.
3146  *
3147  * PARAMS
3148  *  hdc    [I] Handle to the device context to measure on.
3149  *  lptm   [O] Pointer to memory to store the text metrics into.
3150  *  height [O] On exit, the maximum height of characters in the English alphabet.
3151  *
3152  * RETURNS
3153  *  The average width of characters in the English alphabet.
3154  *
3155  * NOTES
3156  *  This function is used by the dialog manager to get the size of a dialog
3157  *  unit. It should also be used by other pieces of code that need to know
3158  *  the size of a dialog unit in logical units without having access to the
3159  *  window handle of the dialog.
3160  *  Windows caches the font metrics from this function, but we don't and
3161  *  there doesn't appear to be an immediate advantage to do so.
3162  *
3163  * SEE ALSO
3164  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3165  */
3166 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3167 {
3168     SIZE sz;
3169     static const WCHAR alphabet[] = {
3170         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3171         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3172         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3173
3174     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3175
3176     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3177
3178     if (height) *height = sz.cy;
3179     return (sz.cx / 26 + 1) / 2;
3180 }
3181
3182 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3183 {
3184     FIXME("(%d): stub\n", fEnableEUDC);
3185     return FALSE;
3186 }
3187
3188 /***********************************************************************
3189  *           GetCharWidthI    (GDI32.@)
3190  *
3191  * Retrieve widths of characters.
3192  *
3193  * PARAMS
3194  *  hdc    [I] Handle to a device context.
3195  *  first  [I] First glyph in range to query.
3196  *  count  [I] Number of glyph indices to query.
3197  *  glyphs [I] Array of glyphs to query.
3198  *  buffer [O] Buffer to receive character widths.
3199  *
3200  * NOTES
3201  *  Only works with TrueType fonts.
3202  *
3203  * RETURNS
3204  *  Success: TRUE
3205  *  Failure: FALSE
3206  */
3207 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3208 {
3209     ABC *abc;
3210     unsigned int i;
3211
3212     TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3213
3214     if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3215         return FALSE;
3216
3217     if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3218     {
3219         HeapFree(GetProcessHeap(), 0, abc);
3220         return FALSE;
3221     }
3222
3223     for (i = 0; i < count; i++)
3224         buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3225
3226     HeapFree(GetProcessHeap(), 0, abc);
3227     return TRUE;
3228 }
3229
3230 /***********************************************************************
3231  *           GetFontUnicodeRanges    (GDI32.@)
3232  *
3233  *  Retrieve a list of supported Unicode characters in a font.
3234  *
3235  *  PARAMS
3236  *   hdc  [I] Handle to a device context.
3237  *   lpgs [O] GLYPHSET structure specifying supported character ranges.
3238  *
3239  *  RETURNS
3240  *   Success: Number of bytes written to the buffer pointed to by lpgs.
3241  *   Failure: 0
3242  *
3243  */
3244 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3245 {
3246     DWORD ret = 0;
3247     DC *dc = get_dc_ptr(hdc);
3248
3249     TRACE("(%p, %p)\n", hdc, lpgs);
3250
3251     if (!dc) return 0;
3252
3253     if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3254     release_dc_ptr(dc);
3255     return ret;
3256 }
3257
3258
3259 /*************************************************************
3260  *           FontIsLinked    (GDI32.@)
3261  */
3262 BOOL WINAPI FontIsLinked(HDC hdc)
3263 {
3264     DC *dc = get_dc_ptr(hdc);
3265     BOOL ret = FALSE;
3266
3267     if (!dc) return FALSE;
3268     if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3269     release_dc_ptr(dc);
3270     TRACE("returning %d\n", ret);
3271     return ret;
3272 }
3273
3274 /*************************************************************
3275  *           GdiRealizationInfo    (GDI32.@)
3276  *
3277  * Returns a structure that contains some font information.
3278  */
3279 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3280 {
3281     DC *dc = get_dc_ptr(hdc);
3282     BOOL ret = FALSE;
3283
3284     if (!dc) return FALSE;
3285     if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3286     release_dc_ptr(dc);
3287
3288     return ret;
3289 }