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