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