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