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