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