mshtml: Implement IHTMLDOMNode replaceChild.
[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;
924
925     if (count < 0) return FALSE;
926
927     p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
928
929     if (p)
930     {
931         ret = GetTextExtentPoint32W( hdc, p, wlen, size );
932         HeapFree( GetProcessHeap(), 0, p );
933     }
934
935     TRACE("(%p %s %d %p): returning %d x %d\n",
936           hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
937     return ret;
938 }
939
940
941 /***********************************************************************
942  * GetTextExtentPoint32W [GDI32.@]
943  *
944  * Computes width/height for a string.
945  *
946  * Computes width and height of the specified string.
947  *
948  * RETURNS
949  *    Success: TRUE
950  *    Failure: FALSE
951  */
952 BOOL WINAPI GetTextExtentPoint32W(
953     HDC hdc,     /* [in]  Handle of device context */
954     LPCWSTR str,   /* [in]  Address of text string */
955     INT count,   /* [in]  Number of characters in string */
956     LPSIZE size) /* [out] Address of structure for string size */
957 {
958     return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
959 }
960
961 /***********************************************************************
962  * GetTextExtentExPointI [GDI32.@]
963  *
964  * Computes width and height of the array of glyph indices.
965  *
966  * PARAMS
967  *    hdc     [I] Handle of device context.
968  *    indices [I] Glyph index array.
969  *    count   [I] Number of glyphs in array.
970  *    max_ext [I] Maximum width in glyphs.
971  *    nfit    [O] Maximum number of characters.
972  *    dxs     [O] Partial string widths.
973  *    size    [O] Returned string size.
974  *
975  * RETURNS
976  *    Success: TRUE
977  *    Failure: FALSE
978  */
979 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
980                                    LPINT nfit, LPINT dxs, LPSIZE size )
981 {
982     BOOL ret = FALSE;
983     DC *dc;
984
985     if (count < 0) return FALSE;
986
987     dc = get_dc_ptr( hdc );
988     if (!dc) return FALSE;
989
990     if(dc->gdiFont)
991     {
992         ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
993         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
994         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
995         size->cx += count * dc->charExtra;
996     }
997     else
998     {
999         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1000         FIXME("calling GetTextExtentExPoint\n");
1001         ret = physdev->funcs->pGetTextExtentExPoint( physdev, indices, count, max_ext, nfit, dxs, size );
1002     }
1003
1004     release_dc_ptr( dc );
1005
1006     TRACE("(%p %p %d %p): returning %d x %d\n",
1007           hdc, indices, count, size, size->cx, size->cy );
1008     return ret;
1009 }
1010
1011 /***********************************************************************
1012  * GetTextExtentPointI [GDI32.@]
1013  *
1014  * Computes width and height of the array of glyph indices.
1015  *
1016  * PARAMS
1017  *    hdc     [I] Handle of device context.
1018  *    indices [I] Glyph index array.
1019  *    count   [I] Number of glyphs in array.
1020  *    size    [O] Returned string size.
1021  *
1022  * RETURNS
1023  *    Success: TRUE
1024  *    Failure: FALSE
1025  */
1026 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1027 {
1028     return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1029 }
1030
1031
1032 /***********************************************************************
1033  *           GetTextExtentPointA    (GDI32.@)
1034  */
1035 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1036                                           LPSIZE size )
1037 {
1038     TRACE("not bug compatible.\n");
1039     return GetTextExtentPoint32A( hdc, str, count, size );
1040 }
1041
1042 /***********************************************************************
1043  *           GetTextExtentPointW   (GDI32.@)
1044  */
1045 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1046                                           LPSIZE size )
1047 {
1048     TRACE("not bug compatible.\n");
1049     return GetTextExtentPoint32W( hdc, str, count, size );
1050 }
1051
1052
1053 /***********************************************************************
1054  *           GetTextExtentExPointA    (GDI32.@)
1055  */
1056 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1057                                    INT maxExt, LPINT lpnFit,
1058                                    LPINT alpDx, LPSIZE size )
1059 {
1060     BOOL ret;
1061     INT wlen;
1062     INT *walpDx = NULL;
1063     LPWSTR p = NULL;
1064
1065     if (count < 0) return FALSE;
1066
1067     if (alpDx)
1068     {
1069         walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1070         if (!walpDx) return FALSE;
1071     }
1072
1073     p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1074     ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1075     if (walpDx)
1076     {
1077         INT n = lpnFit ? *lpnFit : wlen;
1078         INT i, j;
1079         for(i = 0, j = 0; i < n; i++, j++)
1080         {
1081             alpDx[j] = walpDx[i];
1082             if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1083         }
1084     }
1085     if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1086     HeapFree( GetProcessHeap(), 0, p );
1087     HeapFree( GetProcessHeap(), 0, walpDx );
1088     return ret;
1089 }
1090
1091
1092 /***********************************************************************
1093  *           GetTextExtentExPointW    (GDI32.@)
1094  *
1095  * Return the size of the string as it would be if it was output properly by
1096  * e.g. TextOut.
1097  *
1098  * This should include
1099  * - Intercharacter spacing
1100  * - justification spacing (not yet done)
1101  * - kerning? see below
1102  *
1103  * Kerning.  Since kerning would be carried out by the rendering code it should
1104  * be done by the driver.  However they don't support it yet.  Also I am not
1105  * yet persuaded that (certainly under Win95) any kerning is actually done.
1106  *
1107  * str: According to MSDN this should be null-terminated.  That is not true; a
1108  *      null will not terminate it early.
1109  * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1110  *       than count.  I have seen it be either the size of the full string or
1111  *       1 less than the size of the full string.  I have not seen it bear any
1112  *       resemblance to the portion that would fit.
1113  * lpnFit: What exactly is fitting?  Stupidly, in my opinion, it includes the
1114  *         trailing intercharacter spacing and any trailing justification.
1115  *
1116  * FIXME
1117  * Currently we do this by measuring each character etc.  We should do it by
1118  * passing the request to the driver, perhaps by extending the
1119  * pGetTextExtentPoint function to take the alpDx argument.  That would avoid
1120  * thinking about kerning issues and rounding issues in the justification.
1121  */
1122
1123 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1124                                    INT maxExt, LPINT lpnFit,
1125                                    LPINT alpDx, LPSIZE size )
1126 {
1127     INT nFit = 0;
1128     LPINT dxs = NULL;
1129     DC *dc;
1130     BOOL ret = FALSE;
1131     TEXTMETRICW tm;
1132
1133     TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1134
1135     if (count < 0) return FALSE;
1136
1137     dc = get_dc_ptr(hdc);
1138     if (!dc) return FALSE;
1139
1140     GetTextMetricsW(hdc, &tm);
1141
1142     /* If we need to calculate nFit, then we need the partial extents even if
1143        the user hasn't provided us with an array.  */
1144     if (lpnFit)
1145     {
1146         dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1147         if (! dxs)
1148         {
1149             release_dc_ptr(dc);
1150             SetLastError(ERROR_OUTOFMEMORY);
1151             return FALSE;
1152         }
1153     }
1154     else
1155         dxs = alpDx;
1156
1157     if (dc->gdiFont)
1158         ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1159                                           0, NULL, dxs, size);
1160     else
1161     {
1162         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1163         ret = physdev->funcs->pGetTextExtentExPoint(physdev, str, count, 0, NULL, dxs, size);
1164     }
1165
1166     /* Perform device size to world size transformations.  */
1167     if (ret)
1168     {
1169         INT extra      = dc->charExtra,
1170         breakExtra = dc->breakExtra,
1171         breakRem   = dc->breakRem,
1172         i;
1173
1174         if (dxs)
1175         {
1176             for (i = 0; i < count; ++i)
1177             {
1178                 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1179                 dxs[i] += (i+1) * extra;
1180                 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1181                 {
1182                     dxs[i] += breakExtra;
1183                     if (breakRem > 0)
1184                     {
1185                         breakRem--;
1186                         dxs[i]++;
1187                     }
1188                 }
1189                 if (dxs[i] <= maxExt)
1190                     ++nFit;
1191             }
1192             breakRem = dc->breakRem;
1193         }
1194         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1195         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1196
1197         if (!dxs && count > 1 && (breakExtra || breakRem))
1198         {
1199             for (i = 0; i < count; i++)
1200             {
1201                 if (str[i] == tm.tmBreakChar)
1202                 {
1203                     size->cx += breakExtra;
1204                     if (breakRem > 0)
1205                     {
1206                         breakRem--;
1207                         (size->cx)++;
1208                     }
1209                 }
1210             }
1211         }
1212     }
1213
1214     if (lpnFit)
1215         *lpnFit = nFit;
1216
1217     if (! alpDx)
1218         HeapFree(GetProcessHeap(), 0, dxs);
1219
1220     release_dc_ptr( dc );
1221
1222     TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1223     return ret;
1224 }
1225
1226 /***********************************************************************
1227  *           GetTextMetricsA    (GDI32.@)
1228  */
1229 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1230 {
1231     TEXTMETRICW tm32;
1232
1233     if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1234     FONT_TextMetricWToA( &tm32, metrics );
1235     return TRUE;
1236 }
1237
1238 /***********************************************************************
1239  *           GetTextMetricsW    (GDI32.@)
1240  */
1241 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1242 {
1243     BOOL ret = FALSE;
1244     DC * dc = get_dc_ptr( hdc );
1245     if (!dc) return FALSE;
1246
1247     if (dc->gdiFont)
1248         ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1249     else
1250     {
1251         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1252         ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1253     }
1254
1255     if (ret)
1256     {
1257     /* device layer returns values in device units
1258      * therefore we have to convert them to logical */
1259
1260         metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1261         metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1262
1263 #define WDPTOLP(x) ((x<0)?                                      \
1264                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1265                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1266 #define HDPTOLP(y) ((y<0)?                                      \
1267                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1268                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1269
1270         metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
1271         metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
1272         metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
1273         metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
1274         metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
1275         metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
1276         metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
1277         metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
1278         ret = TRUE;
1279 #undef WDPTOLP
1280 #undef HDPTOLP
1281     TRACE("text metrics:\n"
1282           "    Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1283           "    Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1284           "    UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1285           "    StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1286           "    PitchAndFamily = %02x\n"
1287           "    --------------------\n"
1288           "    InternalLeading = %i\n"
1289           "    Ascent = %i\n"
1290           "    Descent = %i\n"
1291           "    Height = %i\n",
1292           metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1293           metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1294           metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1295           metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1296           metrics->tmPitchAndFamily,
1297           metrics->tmInternalLeading,
1298           metrics->tmAscent,
1299           metrics->tmDescent,
1300           metrics->tmHeight );
1301     }
1302     release_dc_ptr( dc );
1303     return ret;
1304 }
1305
1306
1307 /***********************************************************************
1308  *              GetOutlineTextMetricsA (GDI32.@)
1309  * Gets metrics for TrueType fonts.
1310  *
1311  * NOTES
1312  *    If the supplied buffer isn't big enough Windows partially fills it up to
1313  *    its given length and returns that length.
1314  *
1315  * RETURNS
1316  *    Success: Non-zero or size of required buffer
1317  *    Failure: 0
1318  */
1319 UINT WINAPI GetOutlineTextMetricsA(
1320     HDC hdc,    /* [in]  Handle of device context */
1321     UINT cbData, /* [in]  Size of metric data array */
1322     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1323 {
1324     char buf[512], *ptr;
1325     UINT ret, needed;
1326     OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1327     OUTLINETEXTMETRICA *output = lpOTM;
1328     INT left, len;
1329
1330     if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1331         return 0;
1332     if(ret > sizeof(buf))
1333         lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1334     GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1335
1336     needed = sizeof(OUTLINETEXTMETRICA);
1337     if(lpOTMW->otmpFamilyName)
1338         needed += WideCharToMultiByte(CP_ACP, 0,
1339            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1340                                       NULL, 0, NULL, NULL);
1341     if(lpOTMW->otmpFaceName)
1342         needed += WideCharToMultiByte(CP_ACP, 0,
1343            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1344                                       NULL, 0, NULL, NULL);
1345     if(lpOTMW->otmpStyleName)
1346         needed += WideCharToMultiByte(CP_ACP, 0,
1347            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1348                                       NULL, 0, NULL, NULL);
1349     if(lpOTMW->otmpFullName)
1350         needed += WideCharToMultiByte(CP_ACP, 0,
1351            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1352                                       NULL, 0, NULL, NULL);
1353
1354     if(!lpOTM) {
1355         ret = needed;
1356         goto end;
1357     }
1358
1359     TRACE("needed = %d\n", needed);
1360     if(needed > cbData)
1361         /* Since the supplied buffer isn't big enough, we'll alloc one
1362            that is and memcpy the first cbData bytes into the lpOTM at
1363            the end. */
1364         output = HeapAlloc(GetProcessHeap(), 0, needed);
1365
1366     ret = output->otmSize = min(needed, cbData);
1367     FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1368     output->otmFiller = 0;
1369     output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1370     output->otmfsSelection = lpOTMW->otmfsSelection;
1371     output->otmfsType = lpOTMW->otmfsType;
1372     output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1373     output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1374     output->otmItalicAngle = lpOTMW->otmItalicAngle;
1375     output->otmEMSquare = lpOTMW->otmEMSquare;
1376     output->otmAscent = lpOTMW->otmAscent;
1377     output->otmDescent = lpOTMW->otmDescent;
1378     output->otmLineGap = lpOTMW->otmLineGap;
1379     output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1380     output->otmsXHeight = lpOTMW->otmsXHeight;
1381     output->otmrcFontBox = lpOTMW->otmrcFontBox;
1382     output->otmMacAscent = lpOTMW->otmMacAscent;
1383     output->otmMacDescent = lpOTMW->otmMacDescent;
1384     output->otmMacLineGap = lpOTMW->otmMacLineGap;
1385     output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1386     output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1387     output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1388     output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1389     output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1390     output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1391     output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1392     output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1393     output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1394
1395
1396     ptr = (char*)(output + 1);
1397     left = needed - sizeof(*output);
1398
1399     if(lpOTMW->otmpFamilyName) {
1400         output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1401         len = WideCharToMultiByte(CP_ACP, 0,
1402              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1403                                   ptr, left, NULL, NULL);
1404         left -= len;
1405         ptr += len;
1406     } else
1407         output->otmpFamilyName = 0;
1408
1409     if(lpOTMW->otmpFaceName) {
1410         output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1411         len = WideCharToMultiByte(CP_ACP, 0,
1412              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1413                                   ptr, left, NULL, NULL);
1414         left -= len;
1415         ptr += len;
1416     } else
1417         output->otmpFaceName = 0;
1418
1419     if(lpOTMW->otmpStyleName) {
1420         output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1421         len = WideCharToMultiByte(CP_ACP, 0,
1422              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1423                                   ptr, left, NULL, NULL);
1424         left -= len;
1425         ptr += len;
1426     } else
1427         output->otmpStyleName = 0;
1428
1429     if(lpOTMW->otmpFullName) {
1430         output->otmpFullName = (LPSTR)(ptr - (char*)output);
1431         len = WideCharToMultiByte(CP_ACP, 0,
1432              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1433                                   ptr, left, NULL, NULL);
1434         left -= len;
1435     } else
1436         output->otmpFullName = 0;
1437
1438     assert(left == 0);
1439
1440     if(output != lpOTM) {
1441         memcpy(lpOTM, output, cbData);
1442         HeapFree(GetProcessHeap(), 0, output);
1443
1444         /* check if the string offsets really fit into the provided size */
1445         /* FIXME: should we check string length as well? */
1446         /* make sure that we don't read/write beyond the provided buffer */
1447         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1448         {
1449             if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1450                 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1451         }
1452
1453         /* make sure that we don't read/write beyond the provided buffer */
1454         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1455         {
1456             if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1457                 lpOTM->otmpFaceName = 0; /* doesn't fit */
1458         }
1459
1460             /* make sure that we don't read/write beyond the provided buffer */
1461         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1462         {
1463             if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1464                 lpOTM->otmpStyleName = 0; /* doesn't fit */
1465         }
1466
1467         /* make sure that we don't read/write beyond the provided buffer */
1468         if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1469         {
1470             if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1471                 lpOTM->otmpFullName = 0; /* doesn't fit */
1472         }
1473     }
1474
1475 end:
1476     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1477         HeapFree(GetProcessHeap(), 0, lpOTMW);
1478
1479     return ret;
1480 }
1481
1482
1483 /***********************************************************************
1484  *           GetOutlineTextMetricsW [GDI32.@]
1485  */
1486 UINT WINAPI GetOutlineTextMetricsW(
1487     HDC hdc,    /* [in]  Handle of device context */
1488     UINT cbData, /* [in]  Size of metric data array */
1489     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1490 {
1491     DC *dc = get_dc_ptr( hdc );
1492     OUTLINETEXTMETRICW *output = lpOTM;
1493     UINT ret;
1494
1495     TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1496     if(!dc) return 0;
1497
1498     if(dc->gdiFont) {
1499         ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1500         if(lpOTM && ret) {
1501             if(ret > cbData) {
1502                 output = HeapAlloc(GetProcessHeap(), 0, ret);
1503                 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1504             }
1505
1506         output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1507         output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1508
1509 #define WDPTOLP(x) ((x<0)?                                      \
1510                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1511                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1512 #define HDPTOLP(y) ((y<0)?                                      \
1513                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1514                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1515
1516             output->otmTextMetrics.tmHeight           = HDPTOLP(output->otmTextMetrics.tmHeight);
1517             output->otmTextMetrics.tmAscent           = HDPTOLP(output->otmTextMetrics.tmAscent);
1518             output->otmTextMetrics.tmDescent          = HDPTOLP(output->otmTextMetrics.tmDescent);
1519             output->otmTextMetrics.tmInternalLeading  = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1520             output->otmTextMetrics.tmExternalLeading  = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1521             output->otmTextMetrics.tmAveCharWidth     = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1522             output->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1523             output->otmTextMetrics.tmOverhang         = WDPTOLP(output->otmTextMetrics.tmOverhang);
1524             output->otmAscent = HDPTOLP(output->otmAscent);
1525             output->otmDescent = HDPTOLP(output->otmDescent);
1526             output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1527             output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1528             output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1529             output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1530             output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1531             output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1532             output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1533             output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1534             output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1535             output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1536             output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1537             output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1538             output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1539             output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1540             output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1541             output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1542             output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1543             output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1544             output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1545             output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1546             output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1547             output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1548 #undef WDPTOLP
1549 #undef HDPTOLP
1550             if(output != lpOTM) {
1551                 memcpy(lpOTM, output, cbData);
1552                 HeapFree(GetProcessHeap(), 0, output);
1553                 ret = cbData;
1554             }
1555         }
1556     }
1557
1558     else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1559               but really this should just be a return 0. */
1560
1561         ret = sizeof(*lpOTM);
1562         if (lpOTM) {
1563             if(cbData < ret)
1564                 ret = 0;
1565             else {
1566                 memset(lpOTM, 0, ret);
1567                 lpOTM->otmSize = sizeof(*lpOTM);
1568                 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1569                 /*
1570                   Further fill of the structure not implemented,
1571                   Needs real values for the structure members
1572                 */
1573             }
1574         }
1575     }
1576     release_dc_ptr(dc);
1577     return ret;
1578 }
1579
1580 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1581 {
1582     INT i, count = lastChar - firstChar + 1;
1583     UINT c;
1584     LPSTR str;
1585
1586     if (count <= 0)
1587         return NULL;
1588
1589     switch (GdiGetCodePage(hdc))
1590     {
1591     case 932:
1592     case 936:
1593     case 949:
1594     case 950:
1595     case 1361:
1596         if (lastChar > 0xffff)
1597             return NULL;
1598         if ((firstChar ^ lastChar) > 0xff)
1599             return NULL;
1600         break;
1601     default:
1602         if (lastChar > 0xff)
1603             return NULL;
1604         break;
1605     }
1606
1607     str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1608     if (str == NULL)
1609         return NULL;
1610
1611     for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1612     {
1613         if (c > 0xff)
1614             str[i++] = (BYTE)(c >> 8);
1615         str[i] = (BYTE)c;
1616     }
1617     str[i] = '\0';
1618
1619     *pByteLen = i;
1620
1621     return str;
1622 }
1623
1624 /***********************************************************************
1625  *           GetCharWidthW      (GDI32.@)
1626  *           GetCharWidth32W    (GDI32.@)
1627  */
1628 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1629                                LPINT buffer )
1630 {
1631     UINT i;
1632     BOOL ret;
1633     DC * dc = get_dc_ptr( hdc );
1634     if (!dc) return FALSE;
1635
1636     if (dc->gdiFont)
1637         ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1638     else
1639     {
1640         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1641         ret = physdev->funcs->pGetCharWidth( physdev, firstChar, lastChar, buffer);
1642     }
1643
1644     if (ret)
1645     {
1646         /* convert device units to logical */
1647         for( i = firstChar; i <= lastChar; i++, buffer++ )
1648             *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1649         ret = TRUE;
1650     }
1651     release_dc_ptr( dc );
1652     return ret;
1653 }
1654
1655
1656 /***********************************************************************
1657  *           GetCharWidthA      (GDI32.@)
1658  *           GetCharWidth32A    (GDI32.@)
1659  */
1660 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1661                                LPINT buffer )
1662 {
1663     INT i, wlen;
1664     LPSTR str;
1665     LPWSTR wstr;
1666     BOOL ret = TRUE;
1667
1668     str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1669     if(str == NULL)
1670         return FALSE;
1671
1672     wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1673
1674     for(i = 0; i < wlen; i++)
1675     {
1676         if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1677         {
1678             ret = FALSE;
1679             break;
1680         }
1681         buffer++;
1682     }
1683
1684     HeapFree(GetProcessHeap(), 0, str);
1685     HeapFree(GetProcessHeap(), 0, wstr);
1686
1687     return ret;
1688 }
1689
1690
1691 /***********************************************************************
1692  *           ExtTextOutA    (GDI32.@)
1693  *
1694  * See ExtTextOutW.
1695  */
1696 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1697                          const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1698 {
1699     INT wlen;
1700     UINT codepage;
1701     LPWSTR p;
1702     BOOL ret;
1703     LPINT lpDxW = NULL;
1704
1705     if (flags & ETO_GLYPH_INDEX)
1706         return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1707
1708     p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1709
1710     if (lpDx) {
1711         unsigned int i = 0, j = 0;
1712
1713         /* allocate enough for a ETO_PDY */
1714         lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
1715         while(i < count) {
1716             if(IsDBCSLeadByteEx(codepage, str[i]))
1717             {
1718                 if(flags & ETO_PDY)
1719                 {
1720                     lpDxW[j++] = lpDx[i * 2]     + lpDx[(i + 1) * 2];
1721                     lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
1722                 }
1723                 else
1724                     lpDxW[j++] = lpDx[i] + lpDx[i + 1];
1725                 i = i + 2;
1726             }
1727             else
1728             {
1729                 if(flags & ETO_PDY)
1730                 {
1731                     lpDxW[j++] = lpDx[i * 2];
1732                     lpDxW[j++] = lpDx[i * 2 + 1];
1733                 }
1734                 else
1735                     lpDxW[j++] = lpDx[i];
1736                 i = i + 1;
1737             }
1738         }
1739     }
1740
1741     ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1742
1743     HeapFree( GetProcessHeap(), 0, p );
1744     HeapFree( GetProcessHeap(), 0, lpDxW );
1745     return ret;
1746 }
1747
1748
1749 /***********************************************************************
1750  *           ExtTextOutW    (GDI32.@)
1751  *
1752  * Draws text using the currently selected font, background color, and text color.
1753  * 
1754  * 
1755  * PARAMS
1756  *    x,y    [I] coordinates of string
1757  *    flags  [I]
1758  *        ETO_GRAYED - undocumented on MSDN
1759  *        ETO_OPAQUE - use background color for fill the rectangle
1760  *        ETO_CLIPPED - clipping text to the rectangle
1761  *        ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1762  *                          than encoded characters. Implies ETO_IGNORELANGUAGE
1763  *        ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1764  *                         Affects BiDi ordering
1765  *        ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1766  *        ETO_PDY - unimplemented
1767  *        ETO_NUMERICSLATIN - unimplemented always assumed -
1768  *                            do not translate numbers into locale representations
1769  *        ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1770  *    lprect [I] dimensions for clipping or/and opaquing
1771  *    str    [I] text string
1772  *    count  [I] number of symbols in string
1773  *    lpDx   [I] optional parameter with distance between drawing characters
1774  *
1775  * RETURNS
1776  *    Success: TRUE
1777  *    Failure: FALSE
1778  */
1779 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1780                          const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1781 {
1782     BOOL ret = FALSE;
1783     LPWSTR reordered_str = (LPWSTR)str;
1784     WORD *glyphs = NULL;
1785     UINT align = GetTextAlign( hdc );
1786     DWORD layout = GetLayout( hdc );
1787     POINT pt;
1788     TEXTMETRICW tm;
1789     LOGFONTW lf;
1790     double cosEsc, sinEsc;
1791     INT char_extra;
1792     SIZE sz;
1793     RECT rc;
1794     BOOL done_extents = FALSE;
1795     POINT *deltas = NULL, width = {0, 0};
1796     DWORD type;
1797     DC * dc = get_dc_ptr( hdc );
1798     PHYSDEV physdev;
1799     INT breakRem;
1800     static int quietfixme = 0;
1801
1802     if (!dc) return FALSE;
1803
1804     breakRem = dc->breakRem;
1805
1806     if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1807     {
1808         FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1809         quietfixme = 1;
1810     }
1811
1812     update_dc( dc );
1813     physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
1814     type = GetObjectType(hdc);
1815     if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1816     {
1817         ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
1818         release_dc_ptr( dc );
1819         return ret;
1820     }
1821
1822     if (!lprect)
1823         flags &= ~ETO_CLIPPED;
1824
1825     if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
1826     if (layout & LAYOUT_RTL)
1827     {
1828         if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
1829         align ^= TA_RTLREADING;
1830     }
1831
1832     if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1833     {
1834         INT cGlyphs;
1835         reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1836
1837         BIDI_Reorder( hdc, str, count, GCP_REORDER,
1838                       (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
1839                       reordered_str, count, NULL, &glyphs, &cGlyphs);
1840
1841         flags |= ETO_IGNORELANGUAGE;
1842         if (glyphs)
1843         {
1844             flags |= ETO_GLYPH_INDEX;
1845             if (cGlyphs != count)
1846                 count = cGlyphs;
1847         }
1848     }
1849     else if(flags & ETO_GLYPH_INDEX)
1850         glyphs = reordered_str;
1851
1852     TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
1853           wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
1854     TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1855
1856     if(align & TA_UPDATECP)
1857     {
1858         GetCurrentPositionEx( hdc, &pt );
1859         x = pt.x;
1860         y = pt.y;
1861     }
1862
1863     GetTextMetricsW(hdc, &tm);
1864     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1865
1866     if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1867         lf.lfEscapement = 0;
1868
1869     if(lf.lfEscapement != 0)
1870     {
1871         cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1872         sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1873     }
1874     else
1875     {
1876         cosEsc = 1;
1877         sinEsc = 0;
1878     }
1879
1880     if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1881     {
1882         if(!lprect)
1883         {
1884             if(flags & ETO_GLYPH_INDEX)
1885                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1886             else
1887                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1888
1889             done_extents = TRUE;
1890             rc.left = x;
1891             rc.top = y;
1892             rc.right = x + sz.cx;
1893             rc.bottom = y + sz.cy;
1894         }
1895         else
1896         {
1897             rc = *lprect;
1898         }
1899
1900         LPtoDP(hdc, (POINT*)&rc, 2);
1901
1902         if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1903         if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1904     }
1905
1906     if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1907         physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
1908
1909     if(count == 0)
1910     {
1911         ret = TRUE;
1912         goto done;
1913     }
1914
1915     pt.x = x;
1916     pt.y = y;
1917     LPtoDP(hdc, &pt, 1);
1918     x = pt.x;
1919     y = pt.y;
1920
1921     char_extra = GetTextCharacterExtra(hdc);
1922     if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1923     {
1924         UINT i;
1925         SIZE tmpsz;
1926         POINT total = {0, 0}, desired[2];
1927
1928         deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1929         for(i = 0; i < count; i++)
1930         {
1931             if(lpDx)
1932             {
1933                 if(flags & ETO_PDY)
1934                 {
1935                     deltas[i].x = lpDx[i * 2] + char_extra;
1936                     deltas[i].y = -lpDx[i * 2 + 1];
1937                 }
1938                 else
1939                 {
1940                     deltas[i].x = lpDx[i] + char_extra;
1941                     deltas[i].y = 0;
1942                 }
1943
1944             }
1945             else
1946             {
1947                 if(flags & ETO_GLYPH_INDEX)
1948                     GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1949                 else
1950                     GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1951
1952                 deltas[i].x = tmpsz.cx;
1953                 deltas[i].y = 0;
1954             }
1955             
1956             if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1957             {
1958                 deltas[i].x = deltas[i].x + dc->breakExtra;
1959                 if (breakRem > 0)
1960                 {
1961                     breakRem--;
1962                     deltas[i].x++;
1963                 }
1964             }
1965             total.x += deltas[i].x;
1966             total.y += deltas[i].y;
1967
1968             desired[0].x = desired[0].y = 0;
1969
1970             desired[1].x =  cosEsc * total.x + sinEsc * total.y;
1971             desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1972
1973             LPtoDP(hdc, desired, 2);
1974             desired[1].x -= desired[0].x;
1975             desired[1].y -= desired[0].y;
1976             if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
1977
1978             deltas[i].x = desired[1].x - width.x;
1979             deltas[i].y = desired[1].y - width.y;
1980
1981             width = desired[1];
1982         }
1983         flags |= ETO_PDY;
1984     }
1985     else
1986     {
1987         if(!done_extents)
1988         {
1989             if(flags & ETO_GLYPH_INDEX)
1990                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1991             else
1992                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1993             done_extents = TRUE;
1994         }
1995         width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
1996         width.y = 0;
1997     }
1998
1999     tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2000     tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2001     switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2002     {
2003     case TA_LEFT:
2004         if (align & TA_UPDATECP)
2005         {
2006             pt.x = x + width.x;
2007             pt.y = y + width.y;
2008             DPtoLP(hdc, &pt, 1);
2009             MoveToEx(hdc, pt.x, pt.y, NULL);
2010         }
2011         break;
2012
2013     case TA_CENTER:
2014         x -= width.x / 2;
2015         y -= width.y / 2;
2016         break;
2017
2018     case TA_RIGHT:
2019         x -= width.x;
2020         y -= width.y;
2021         if (align & TA_UPDATECP)
2022         {
2023             pt.x = x;
2024             pt.y = y;
2025             DPtoLP(hdc, &pt, 1);
2026             MoveToEx(hdc, pt.x, pt.y, NULL);
2027         }
2028         break;
2029     }
2030
2031     switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2032     {
2033     case TA_TOP:
2034         y += tm.tmAscent * cosEsc;
2035         x += tm.tmAscent * sinEsc;
2036         break;
2037
2038     case TA_BOTTOM:
2039         y -= tm.tmDescent * cosEsc;
2040         x -= tm.tmDescent * sinEsc;
2041         break;
2042
2043     case TA_BASELINE:
2044         break;
2045     }
2046
2047     if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2048     {
2049         if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2050         {
2051             if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
2052                y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2053             {
2054                 RECT rc;
2055                 rc.left = x;
2056                 rc.right = x + width.x;
2057                 rc.top = y - tm.tmAscent;
2058                 rc.bottom = y + tm.tmDescent;
2059
2060                 if(flags & ETO_CLIPPED)
2061                 {
2062                     rc.left = max(lprect->left, rc.left);
2063                     rc.right = min(lprect->right, rc.right);
2064                     rc.top = max(lprect->top, rc.top);
2065                     rc.bottom = min(lprect->bottom, rc.bottom);
2066                 }
2067                 if(rc.left < rc.right && rc.top < rc.bottom)
2068                     physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2069             }
2070         }
2071     }
2072
2073     if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2074     {
2075         HFONT orig_font = dc->hFont, cur_font;
2076         UINT glyph;
2077         INT span = 0;
2078         POINT *offsets = NULL;
2079         unsigned int i;
2080
2081         glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2082         for(i = 0; i < count; i++)
2083         {
2084             WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2085             if(cur_font != dc->hFont)
2086             {
2087                 if(!offsets)
2088                 {
2089                     unsigned int j;
2090                     offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2091                     offsets[0].x = offsets[0].y = 0;
2092
2093                     if(!deltas)
2094                     {
2095                         SIZE tmpsz;
2096                         for(j = 1; j < count; j++)
2097                         {
2098                             GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2099                             offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2100                             offsets[j].y = 0;
2101                         }
2102                     }
2103                     else
2104                     {
2105                         for(j = 1; j < count; j++)
2106                         {
2107                             offsets[j].x = offsets[j - 1].x + deltas[j].x;
2108                             offsets[j].y = offsets[j - 1].y + deltas[j].y;
2109                         }
2110                     }
2111                 }
2112                 if(span)
2113                 {
2114                     if (PATH_IsPathOpen(dc->path))
2115                         ret = PATH_ExtTextOut(dc, x + offsets[i - span].x, y + offsets[i - span].y,
2116                                               (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2117                                               glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2118                     else
2119                         physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2120                                                      y + offsets[i - span].y,
2121                                                      (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2122                                                      span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2123                     span = 0;
2124                 }
2125                 SelectObject(hdc, cur_font);
2126             }
2127             glyphs[span++] = glyph;
2128
2129             if(i == count - 1)
2130             {
2131                 if (PATH_IsPathOpen(dc->path))
2132                     ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span].x : 0),
2133                                           y + (offsets ? offsets[count - span].y : 0),
2134                                           (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2135                                           glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2136                 else
2137                     ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2138                                                       y + (offsets ? offsets[count - span].y : 0),
2139                                                       (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2140                                                       span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2141                 SelectObject(hdc, orig_font);
2142                 HeapFree(GetProcessHeap(), 0, offsets);
2143            }
2144         }
2145     }
2146     else
2147     {
2148         if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2149         {
2150             glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2151             GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2152             flags |= ETO_GLYPH_INDEX;
2153         }
2154
2155         if (PATH_IsPathOpen(dc->path))
2156             ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2157                                   glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2158         else
2159             ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2160                                                glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2161     }
2162
2163 done:
2164     HeapFree(GetProcessHeap(), 0, deltas);
2165     if(glyphs != reordered_str)
2166         HeapFree(GetProcessHeap(), 0, glyphs);
2167     if(reordered_str != str)
2168         HeapFree(GetProcessHeap(), 0, reordered_str);
2169
2170     release_dc_ptr( dc );
2171
2172     if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2173     {
2174         int underlinePos, strikeoutPos;
2175         int underlineWidth, strikeoutWidth;
2176         UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2177         OUTLINETEXTMETRICW* otm = NULL;
2178
2179         if(!size)
2180         {
2181             underlinePos = 0;
2182             underlineWidth = tm.tmAscent / 20 + 1;
2183             strikeoutPos = tm.tmAscent / 2;
2184             strikeoutWidth = underlineWidth;
2185         }
2186         else
2187         {
2188             otm = HeapAlloc(GetProcessHeap(), 0, size);
2189             GetOutlineTextMetricsW(hdc, size, otm);
2190             underlinePos = otm->otmsUnderscorePosition;
2191             underlineWidth = otm->otmsUnderscoreSize;
2192             strikeoutPos = otm->otmsStrikeoutPosition;
2193             strikeoutWidth = otm->otmsStrikeoutSize;
2194             HeapFree(GetProcessHeap(), 0, otm);
2195         }
2196
2197         if (PATH_IsPathOpen(dc->path))
2198         {
2199             POINT pts[5];
2200             HPEN hpen;
2201             HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2202
2203             hbrush = SelectObject(hdc, hbrush);
2204             hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2205
2206             if (lf.lfUnderline)
2207             {
2208                 pts[0].x = x - underlinePos * sinEsc;
2209                 pts[0].y = y - underlinePos * cosEsc;
2210                 pts[1].x = x + width.x - underlinePos * sinEsc;
2211                 pts[1].y = y + width.y - underlinePos * cosEsc;
2212                 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2213                 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2214                 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2215                 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2216                 pts[4].x = pts[0].x;
2217                 pts[4].y = pts[0].y;
2218                 DPtoLP(hdc, pts, 5);
2219                 Polygon(hdc, pts, 5);
2220             }
2221
2222             if (lf.lfStrikeOut)
2223             {
2224                 pts[0].x = x - strikeoutPos * sinEsc;
2225                 pts[0].y = y - strikeoutPos * cosEsc;
2226                 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2227                 pts[1].y = y + width.y - strikeoutPos * cosEsc;
2228                 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2229                 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2230                 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2231                 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2232                 pts[4].x = pts[0].x;
2233                 pts[4].y = pts[0].y;
2234                 DPtoLP(hdc, pts, 5);
2235                 Polygon(hdc, pts, 5);
2236             }
2237
2238             SelectObject(hdc, hpen);
2239             hbrush = SelectObject(hdc, hbrush);
2240             DeleteObject(hbrush);
2241         }
2242         else
2243         {
2244             POINT pts[2], oldpt;
2245             HPEN hpen;
2246
2247             if (lf.lfUnderline)
2248             {
2249                 hpen = CreatePen(PS_SOLID, underlineWidth, 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 - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2257                 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2258                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2259                 DeleteObject(SelectObject(hdc, hpen));
2260             }
2261
2262             if (lf.lfStrikeOut)
2263             {
2264                 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2265                 hpen = SelectObject(hdc, hpen);
2266                 pts[0].x = x;
2267                 pts[0].y = y;
2268                 pts[1].x = x + width.x;
2269                 pts[1].y = y + width.y;
2270                 DPtoLP(hdc, pts, 2);
2271                 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2272                 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2273                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2274                 DeleteObject(SelectObject(hdc, hpen));
2275             }
2276         }
2277     }
2278
2279     return ret;
2280 }
2281
2282
2283 /***********************************************************************
2284  *           TextOutA    (GDI32.@)
2285  */
2286 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2287 {
2288     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2289 }
2290
2291
2292 /***********************************************************************
2293  *           TextOutW    (GDI32.@)
2294  */
2295 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2296 {
2297     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2298 }
2299
2300
2301 /***********************************************************************
2302  *              PolyTextOutA (GDI32.@)
2303  *
2304  * See PolyTextOutW.
2305  */
2306 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2307 {
2308     for (; cStrings>0; cStrings--, pptxt++)
2309         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2310             return FALSE;
2311     return TRUE;
2312 }
2313
2314
2315
2316 /***********************************************************************
2317  *              PolyTextOutW (GDI32.@)
2318  *
2319  * Draw several Strings
2320  *
2321  * RETURNS
2322  *  TRUE:  Success.
2323  *  FALSE: Failure.
2324  */
2325 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2326 {
2327     for (; cStrings>0; cStrings--, pptxt++)
2328         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2329             return FALSE;
2330     return TRUE;
2331 }
2332
2333
2334 /***********************************************************************
2335  *           SetMapperFlags    (GDI32.@)
2336  */
2337 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2338 {
2339     DC *dc = get_dc_ptr( hdc );
2340     DWORD ret = GDI_ERROR;
2341
2342     if (dc)
2343     {
2344         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2345         flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2346         if (flags != GDI_ERROR)
2347         {
2348             ret = dc->mapperFlags;
2349             dc->mapperFlags = flags;
2350         }
2351         release_dc_ptr( dc );
2352     }
2353     return ret;
2354 }
2355
2356 /***********************************************************************
2357  *          GetAspectRatioFilterEx  (GDI32.@)
2358  */
2359 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2360 {
2361   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2362   return FALSE;
2363 }
2364
2365
2366 /***********************************************************************
2367  *           GetCharABCWidthsA   (GDI32.@)
2368  *
2369  * See GetCharABCWidthsW.
2370  */
2371 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2372                                   LPABC abc )
2373 {
2374     INT i, wlen;
2375     LPSTR str;
2376     LPWSTR wstr;
2377     BOOL ret = TRUE;
2378
2379     str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2380     if (str == NULL)
2381         return FALSE;
2382
2383     wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2384     if (wstr == NULL)
2385     {
2386         HeapFree(GetProcessHeap(), 0, str);
2387         return FALSE;
2388     }
2389
2390     for(i = 0; i < wlen; i++)
2391     {
2392         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2393         {
2394             ret = FALSE;
2395             break;
2396         }
2397         abc++;
2398     }
2399
2400     HeapFree(GetProcessHeap(), 0, str);
2401     HeapFree(GetProcessHeap(), 0, wstr);
2402
2403     return ret;
2404 }
2405
2406
2407 /******************************************************************************
2408  * GetCharABCWidthsW [GDI32.@]
2409  *
2410  * Retrieves widths of characters in range.
2411  *
2412  * PARAMS
2413  *    hdc       [I] Handle of device context
2414  *    firstChar [I] First character in range to query
2415  *    lastChar  [I] Last character in range to query
2416  *    abc       [O] Address of character-width structure
2417  *
2418  * NOTES
2419  *    Only works with TrueType fonts
2420  *
2421  * RETURNS
2422  *    Success: TRUE
2423  *    Failure: FALSE
2424  */
2425 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2426                                    LPABC abc )
2427 {
2428     DC *dc = get_dc_ptr(hdc);
2429     unsigned int i;
2430     BOOL ret = FALSE;
2431
2432     if (!dc) return FALSE;
2433
2434     if (!abc)
2435     {
2436         release_dc_ptr( dc );
2437         return FALSE;
2438     }
2439
2440     if(dc->gdiFont)
2441         ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2442     else
2443         FIXME(": stub\n");
2444
2445     if (ret)
2446     {
2447         /* convert device units to logical */
2448         for( i = firstChar; i <= lastChar; i++, abc++ ) {
2449             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2450             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2451             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2452         }
2453         ret = TRUE;
2454     }
2455
2456     release_dc_ptr( dc );
2457     return ret;
2458 }
2459
2460
2461 /******************************************************************************
2462  * GetCharABCWidthsI [GDI32.@]
2463  *
2464  * Retrieves widths of characters in range.
2465  *
2466  * PARAMS
2467  *    hdc       [I] Handle of device context
2468  *    firstChar [I] First glyphs in range to query
2469  *    count     [I] Last glyphs in range to query
2470  *    pgi       [i] Array of glyphs to query
2471  *    abc       [O] Address of character-width structure
2472  *
2473  * NOTES
2474  *    Only works with TrueType fonts
2475  *
2476  * RETURNS
2477  *    Success: TRUE
2478  *    Failure: FALSE
2479  */
2480 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2481                                LPWORD pgi, LPABC abc)
2482 {
2483     DC *dc = get_dc_ptr(hdc);
2484     unsigned int i;
2485     BOOL ret = FALSE;
2486
2487     if (!dc) return FALSE;
2488
2489     if (!abc)
2490     {
2491         release_dc_ptr( dc );
2492         return FALSE;
2493     }
2494
2495     if(dc->gdiFont)
2496         ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2497     else
2498         FIXME(": stub\n");
2499
2500     if (ret)
2501     {
2502         /* convert device units to logical */
2503         for( i = 0; i < count; i++, abc++ ) {
2504             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2505             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2506             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2507         }
2508         ret = TRUE;
2509     }
2510
2511     release_dc_ptr( dc );
2512     return ret;
2513 }
2514
2515
2516 /***********************************************************************
2517  *           GetGlyphOutlineA    (GDI32.@)
2518  */
2519 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2520                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2521                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2522 {
2523     if (!lpmat2) return GDI_ERROR;
2524
2525     if(!(fuFormat & GGO_GLYPH_INDEX)) {
2526         UINT cp;
2527         int len;
2528         char mbchs[2];
2529
2530         cp = GdiGetCodePage(hdc);
2531         if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2532             len = 2;
2533             mbchs[0] = (uChar & 0xff00) >> 8;
2534             mbchs[1] = (uChar & 0xff);
2535         } else {
2536             len = 1;
2537             mbchs[0] = (uChar & 0xff);
2538         }
2539         uChar = 0;
2540         MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2541     }
2542
2543     return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2544                             lpmat2);
2545 }
2546
2547 /***********************************************************************
2548  *           GetGlyphOutlineW    (GDI32.@)
2549  */
2550 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2551                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2552                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2553 {
2554     DC *dc;
2555     DWORD ret;
2556
2557     TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2558           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2559
2560     if (!lpmat2) return GDI_ERROR;
2561
2562     dc = get_dc_ptr(hdc);
2563     if(!dc) return GDI_ERROR;
2564
2565     if(dc->gdiFont)
2566       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2567                                    cbBuffer, lpBuffer, lpmat2);
2568     else
2569       ret = GDI_ERROR;
2570
2571     release_dc_ptr( dc );
2572     return ret;
2573 }
2574
2575
2576 /***********************************************************************
2577  *           CreateScalableFontResourceA   (GDI32.@)
2578  */
2579 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2580                                              LPCSTR lpszResourceFile,
2581                                              LPCSTR lpszFontFile,
2582                                              LPCSTR lpszCurrentPath )
2583 {
2584     LPWSTR lpszResourceFileW = NULL;
2585     LPWSTR lpszFontFileW = NULL;
2586     LPWSTR lpszCurrentPathW = NULL;
2587     int len;
2588     BOOL ret;
2589
2590     if (lpszResourceFile)
2591     {
2592         len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2593         lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2594         MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2595     }
2596
2597     if (lpszFontFile)
2598     {
2599         len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2600         lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2601         MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2602     }
2603
2604     if (lpszCurrentPath)
2605     {
2606         len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2607         lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2608         MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2609     }
2610
2611     ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2612             lpszFontFileW, lpszCurrentPathW);
2613
2614     HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2615     HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2616     HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2617
2618     return ret;
2619 }
2620
2621 /***********************************************************************
2622  *           CreateScalableFontResourceW   (GDI32.@)
2623  */
2624 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2625                                              LPCWSTR lpszResourceFile,
2626                                              LPCWSTR lpszFontFile,
2627                                              LPCWSTR lpszCurrentPath )
2628 {
2629     HANDLE f;
2630     FIXME("(%d,%s,%s,%s): stub\n",
2631           fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2632           debugstr_w(lpszCurrentPath) );
2633
2634     /* fHidden=1 - only visible for the calling app, read-only, not
2635      * enumerated with EnumFonts/EnumFontFamilies
2636      * lpszCurrentPath can be NULL
2637      */
2638
2639     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2640     if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2641         CloseHandle(f);
2642         SetLastError(ERROR_FILE_EXISTS);
2643         return FALSE;
2644     }
2645     return FALSE; /* create failed */
2646 }
2647
2648 /*************************************************************************
2649  *             GetKerningPairsA   (GDI32.@)
2650  */
2651 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2652                                LPKERNINGPAIR kern_pairA )
2653 {
2654     UINT cp;
2655     CPINFO cpi;
2656     DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2657     KERNINGPAIR *kern_pairW;
2658
2659     if (!cPairs && kern_pairA)
2660     {
2661         SetLastError(ERROR_INVALID_PARAMETER);
2662         return 0;
2663     }
2664
2665     cp = GdiGetCodePage(hDC);
2666
2667     /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2668      * to fail on an invalid character for CP_SYMBOL.
2669      */
2670     cpi.DefaultChar[0] = 0;
2671     if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2672     {
2673         FIXME("Can't find codepage %u info\n", cp);
2674         return 0;
2675     }
2676
2677     total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2678     if (!total_kern_pairs) return 0;
2679
2680     kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2681     GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2682
2683     for (i = 0; i < total_kern_pairs; i++)
2684     {
2685         char first, second;
2686
2687         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2688             continue;
2689
2690         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2691             continue;
2692
2693         if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2694             continue;
2695
2696         if (kern_pairA)
2697         {
2698             if (kern_pairs_copied >= cPairs) break;
2699
2700             kern_pairA->wFirst = (BYTE)first;
2701             kern_pairA->wSecond = (BYTE)second;
2702             kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2703             kern_pairA++;
2704         }
2705         kern_pairs_copied++;
2706     }
2707
2708     HeapFree(GetProcessHeap(), 0, kern_pairW);
2709
2710     return kern_pairs_copied;
2711 }
2712
2713 /*************************************************************************
2714  *             GetKerningPairsW   (GDI32.@)
2715  */
2716 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2717                                  LPKERNINGPAIR lpKerningPairs )
2718 {
2719     DC *dc;
2720     DWORD ret = 0;
2721
2722     TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2723
2724     if (!cPairs && lpKerningPairs)
2725     {
2726         SetLastError(ERROR_INVALID_PARAMETER);
2727         return 0;
2728     }
2729
2730     dc = get_dc_ptr(hDC);
2731     if (!dc) return 0;
2732
2733     if (dc->gdiFont)
2734         ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2735
2736     release_dc_ptr( dc );
2737     return ret;
2738 }
2739
2740 /*************************************************************************
2741  * TranslateCharsetInfo [GDI32.@]
2742  *
2743  * Fills a CHARSETINFO structure for a character set, code page, or
2744  * font. This allows making the correspondence between different labels
2745  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2746  * of the same encoding.
2747  *
2748  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2749  * only one codepage should be set in *lpSrc.
2750  *
2751  * RETURNS
2752  *   TRUE on success, FALSE on failure.
2753  *
2754  */
2755 BOOL WINAPI TranslateCharsetInfo(
2756   LPDWORD lpSrc, /* [in]
2757        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2758        if flags == TCI_SRCCHARSET: a character set value
2759        if flags == TCI_SRCCODEPAGE: a code page value
2760                  */
2761   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2762   DWORD flags /* [in] determines interpretation of lpSrc */)
2763 {
2764     int index = 0;
2765     switch (flags) {
2766     case TCI_SRCFONTSIG:
2767       while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2768       break;
2769     case TCI_SRCCODEPAGE:
2770       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2771       break;
2772     case TCI_SRCCHARSET:
2773       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2774       break;
2775     default:
2776       return FALSE;
2777     }
2778     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2779     *lpCs = FONT_tci[index];
2780     return TRUE;
2781 }
2782
2783 /*************************************************************************
2784  *             GetFontLanguageInfo   (GDI32.@)
2785  */
2786 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2787 {
2788         FONTSIGNATURE fontsig;
2789         static const DWORD GCP_DBCS_MASK=0x003F0000,
2790                 GCP_DIACRITIC_MASK=0x00000000,
2791                 FLI_GLYPHS_MASK=0x00000000,
2792                 GCP_GLYPHSHAPE_MASK=0x00000040,
2793                 GCP_KASHIDA_MASK=0x00000000,
2794                 GCP_LIGATE_MASK=0x00000000,
2795                 GCP_USEKERNING_MASK=0x00000000,
2796                 GCP_REORDER_MASK=0x00000060;
2797
2798         DWORD result=0;
2799
2800         GetTextCharsetInfo( hdc, &fontsig, 0 );
2801         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2802
2803         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2804                 result|=GCP_DBCS;
2805
2806         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2807                 result|=GCP_DIACRITIC;
2808
2809         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2810                 result|=FLI_GLYPHS;
2811
2812         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2813                 result|=GCP_GLYPHSHAPE;
2814
2815         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2816                 result|=GCP_KASHIDA;
2817
2818         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2819                 result|=GCP_LIGATE;
2820
2821         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2822                 result|=GCP_USEKERNING;
2823
2824         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2825         if( GetTextAlign( hdc) & TA_RTLREADING )
2826             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2827                     result|=GCP_REORDER;
2828
2829         return result;
2830 }
2831
2832
2833 /*************************************************************************
2834  * GetFontData [GDI32.@]
2835  *
2836  * Retrieve data for TrueType font.
2837  *
2838  * RETURNS
2839  *
2840  * success: Number of bytes returned
2841  * failure: GDI_ERROR
2842  *
2843  * NOTES
2844  *
2845  * Calls SetLastError()
2846  *
2847  */
2848 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2849     LPVOID buffer, DWORD length)
2850 {
2851     DC *dc = get_dc_ptr(hdc);
2852     DWORD ret = GDI_ERROR;
2853
2854     if(!dc) return GDI_ERROR;
2855
2856     if(dc->gdiFont)
2857       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2858
2859     release_dc_ptr( dc );
2860     return ret;
2861 }
2862
2863 /*************************************************************************
2864  * GetGlyphIndicesA [GDI32.@]
2865  */
2866 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2867                               LPWORD pgi, DWORD flags)
2868 {
2869     DWORD ret;
2870     WCHAR *lpstrW;
2871     INT countW;
2872
2873     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2874           hdc, debugstr_an(lpstr, count), count, pgi, flags);
2875
2876     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2877     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2878     HeapFree(GetProcessHeap(), 0, lpstrW);
2879
2880     return ret;
2881 }
2882
2883 /*************************************************************************
2884  * GetGlyphIndicesW [GDI32.@]
2885  */
2886 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2887                               LPWORD pgi, DWORD flags)
2888 {
2889     DC *dc = get_dc_ptr(hdc);
2890     DWORD ret = GDI_ERROR;
2891
2892     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2893           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2894
2895     if(!dc) return GDI_ERROR;
2896
2897     if(dc->gdiFont)
2898         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2899
2900     release_dc_ptr( dc );
2901     return ret;
2902 }
2903
2904 /*************************************************************************
2905  * GetCharacterPlacementA [GDI32.@]
2906  *
2907  * See GetCharacterPlacementW.
2908  *
2909  * NOTES:
2910  *  the web browser control of ie4 calls this with dwFlags=0
2911  */
2912 DWORD WINAPI
2913 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2914                          INT nMaxExtent, GCP_RESULTSA *lpResults,
2915                          DWORD dwFlags)
2916 {
2917     WCHAR *lpStringW;
2918     INT uCountW;
2919     GCP_RESULTSW resultsW;
2920     DWORD ret;
2921     UINT font_cp;
2922
2923     TRACE("%s, %d, %d, 0x%08x\n",
2924           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2925
2926     /* both structs are equal in size */
2927     memcpy(&resultsW, lpResults, sizeof(resultsW));
2928
2929     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2930     if(lpResults->lpOutString)
2931         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2932
2933     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2934
2935     lpResults->nGlyphs = resultsW.nGlyphs;
2936     lpResults->nMaxFit = resultsW.nMaxFit;
2937
2938     if(lpResults->lpOutString) {
2939         WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2940                             lpResults->lpOutString, uCount, NULL, NULL );
2941     }
2942
2943     HeapFree(GetProcessHeap(), 0, lpStringW);
2944     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2945
2946     return ret;
2947 }
2948
2949 /*************************************************************************
2950  * GetCharacterPlacementW [GDI32.@]
2951  *
2952  *   Retrieve information about a string. This includes the width, reordering,
2953  *   Glyphing and so on.
2954  *
2955  * RETURNS
2956  *
2957  *   The width and height of the string if successful, 0 if failed.
2958  *
2959  * BUGS
2960  *
2961  *   All flags except GCP_REORDER are not yet implemented.
2962  *   Reordering is not 100% compliant to the Windows BiDi method.
2963  *   Caret positioning is not yet implemented for BiDi.
2964  *   Classes are not yet implemented.
2965  *
2966  */
2967 DWORD WINAPI
2968 GetCharacterPlacementW(
2969                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
2970                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
2971                 INT uCount,             /* [in] Number of WORDS in string. */
2972                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
2973                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2974                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
2975                 )
2976 {
2977     DWORD ret=0;
2978     SIZE size;
2979     UINT i, nSet;
2980
2981     TRACE("%s, %d, %d, 0x%08x\n",
2982           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2983
2984     TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2985           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2986             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2987             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2988             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2989
2990     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08x ignored\n", dwFlags);
2991     if(lpResults->lpClass)      FIXME("classes not implemented\n");
2992     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2993         FIXME("Caret positions for complex scripts not implemented\n");
2994
2995         nSet = (UINT)uCount;
2996         if(nSet > lpResults->nGlyphs)
2997                 nSet = lpResults->nGlyphs;
2998
2999         /* return number of initialized fields */
3000         lpResults->nGlyphs = nSet;
3001
3002         if((dwFlags&GCP_REORDER)==0 )
3003         {
3004                 /* Treat the case where no special handling was requested in a fastpath way */
3005                 /* copy will do if the GCP_REORDER flag is not set */
3006                 if(lpResults->lpOutString)
3007                     memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3008
3009                 if(lpResults->lpOrder)
3010                 {
3011                         for(i = 0; i < nSet; i++)
3012                                 lpResults->lpOrder[i] = i;
3013                 }
3014         } else
3015         {
3016             BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3017                           nSet, lpResults->lpOrder, NULL, NULL );
3018         }
3019
3020         /* FIXME: Will use the placement chars */
3021         if (lpResults->lpDx)
3022         {
3023                 int c;
3024                 for (i = 0; i < nSet; i++)
3025                 {
3026                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3027                                 lpResults->lpDx[i]= c;
3028                 }
3029         }
3030
3031     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3032     {
3033         int pos = 0;
3034        
3035         lpResults->lpCaretPos[0] = 0;
3036         for (i = 1; i < nSet; i++)
3037             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3038                 lpResults->lpCaretPos[i] = (pos += size.cx);
3039     }
3040    
3041     if(lpResults->lpGlyphs)
3042         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3043
3044     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3045       ret = MAKELONG(size.cx, size.cy);
3046
3047     return ret;
3048 }
3049
3050 /*************************************************************************
3051  *      GetCharABCWidthsFloatA [GDI32.@]
3052  *
3053  * See GetCharABCWidthsFloatW.
3054  */
3055 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3056 {
3057     INT i, wlen;
3058     LPSTR str;
3059     LPWSTR wstr;
3060     BOOL ret = TRUE;
3061
3062     str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3063     if (str == NULL)
3064         return FALSE;
3065
3066     wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3067
3068     for (i = 0; i < wlen; i++)
3069     {
3070         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3071         {
3072             ret = FALSE;
3073             break;
3074         }
3075         abcf++;
3076     }
3077
3078     HeapFree( GetProcessHeap(), 0, str );
3079     HeapFree( GetProcessHeap(), 0, wstr );
3080
3081     return ret;
3082 }
3083
3084 /*************************************************************************
3085  *      GetCharABCWidthsFloatW [GDI32.@]
3086  *
3087  * Retrieves widths of a range of characters.
3088  *
3089  * PARAMS
3090  *    hdc   [I] Handle to device context.
3091  *    first [I] First character in range to query.
3092  *    last  [I] Last character in range to query.
3093  *    abcf  [O] Array of LPABCFLOAT structures.
3094  *
3095  * RETURNS
3096  *    Success: TRUE
3097  *    Failure: FALSE
3098  */
3099 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3100 {
3101     UINT i;
3102     BOOL ret = FALSE;
3103     DC *dc = get_dc_ptr( hdc );
3104
3105     TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3106
3107     if (!dc) return FALSE;
3108
3109     if (!abcf)
3110     {
3111         release_dc_ptr( dc );
3112         return FALSE;
3113     }
3114
3115     if (dc->gdiFont)
3116         ret = WineEngGetCharABCWidthsFloat( dc->gdiFont, first, last, abcf );
3117     else
3118         FIXME("stub\n");
3119
3120     if (ret)
3121     {
3122         /* convert device units to logical */
3123         for (i = first; i <= last; i++, abcf++)
3124         {
3125             abcf->abcfA = abcf->abcfA * dc->xformVport2World.eM11;
3126             abcf->abcfB = abcf->abcfB * dc->xformVport2World.eM11;
3127             abcf->abcfC = abcf->abcfC * dc->xformVport2World.eM11;
3128         }
3129     }
3130
3131     release_dc_ptr( dc );
3132     return ret;
3133 }
3134
3135 /*************************************************************************
3136  *      GetCharWidthFloatA [GDI32.@]
3137  */
3138 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3139                                     UINT iLastChar, PFLOAT pxBuffer)
3140 {
3141     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3142     return 0;
3143 }
3144
3145 /*************************************************************************
3146  *      GetCharWidthFloatW [GDI32.@]
3147  */
3148 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3149                                     UINT iLastChar, PFLOAT pxBuffer)
3150 {
3151     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3152     return 0;
3153 }
3154
3155
3156 /***********************************************************************
3157  *                                                                     *
3158  *           Font Resource API                                         *
3159  *                                                                     *
3160  ***********************************************************************/
3161
3162 /***********************************************************************
3163  *           AddFontResourceA    (GDI32.@)
3164  */
3165 INT WINAPI AddFontResourceA( LPCSTR str )
3166 {
3167     return AddFontResourceExA( str, 0, NULL);
3168 }
3169
3170 /***********************************************************************
3171  *           AddFontResourceW    (GDI32.@)
3172  */
3173 INT WINAPI AddFontResourceW( LPCWSTR str )
3174 {
3175     return AddFontResourceExW(str, 0, NULL);
3176 }
3177
3178
3179 /***********************************************************************
3180  *           AddFontResourceExA    (GDI32.@)
3181  */
3182 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3183 {
3184     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3185     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3186     INT ret;
3187
3188     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3189     ret = AddFontResourceExW(strW, fl, pdv);
3190     HeapFree(GetProcessHeap(), 0, strW);
3191     return ret;
3192 }
3193
3194 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3195 {
3196     HRSRC rsrc = FindResourceW(hModule, name, type);
3197     HGLOBAL hMem = LoadResource(hModule, rsrc);
3198     LPVOID *pMem = LockResource(hMem);
3199     int *num_total = (int *)lParam;
3200     DWORD num_in_res;
3201
3202     TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3203     if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3204     {
3205         ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3206         return FALSE;
3207     }
3208
3209     *num_total += num_in_res;
3210     return TRUE;
3211 }
3212
3213 /***********************************************************************
3214  *           AddFontResourceExW    (GDI32.@)
3215  */
3216 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3217 {
3218     int ret = WineEngAddFontResourceEx(str, fl, pdv);
3219     if (ret == 0)
3220     {
3221         /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3222         HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3223         if (hModule != NULL)
3224         {
3225             int num_resources = 0;
3226             LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8);  /* we don't want to include winuser.h */
3227
3228             TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3229                 wine_dbgstr_w(str));
3230             if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3231                 ret = num_resources;
3232             FreeLibrary(hModule);
3233         }
3234     }
3235     return ret;
3236 }
3237
3238 /***********************************************************************
3239  *           RemoveFontResourceA    (GDI32.@)
3240  */
3241 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3242 {
3243     return RemoveFontResourceExA(str, 0, 0);
3244 }
3245
3246 /***********************************************************************
3247  *           RemoveFontResourceW    (GDI32.@)
3248  */
3249 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3250 {
3251     return RemoveFontResourceExW(str, 0, 0);
3252 }
3253
3254 /***********************************************************************
3255  *           AddFontMemResourceEx    (GDI32.@)
3256  */
3257 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3258 {
3259     HANDLE ret;
3260     DWORD num_fonts;
3261
3262     if (!pbFont || !cbFont || !pcFonts)
3263     {
3264         SetLastError(ERROR_INVALID_PARAMETER);
3265         return NULL;
3266     }
3267
3268     ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3269     if (ret)
3270     {
3271         __TRY
3272         {
3273             *pcFonts = num_fonts;
3274         }
3275         __EXCEPT_PAGE_FAULT
3276         {
3277             WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3278             RemoveFontMemResourceEx(ret);
3279             ret = 0;
3280         }
3281         __ENDTRY
3282     }
3283     return ret;
3284 }
3285
3286 /***********************************************************************
3287  *           RemoveFontMemResourceEx    (GDI32.@)
3288  */
3289 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3290 {
3291     FIXME("(%p) stub\n", fh);
3292     return TRUE;
3293 }
3294
3295 /***********************************************************************
3296  *           RemoveFontResourceExA    (GDI32.@)
3297  */
3298 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3299 {
3300     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3301     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3302     INT ret;
3303
3304     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3305     ret = RemoveFontResourceExW(strW, fl, pdv);
3306     HeapFree(GetProcessHeap(), 0, strW);
3307     return ret;
3308 }
3309
3310 /***********************************************************************
3311  *           RemoveFontResourceExW    (GDI32.@)
3312  */
3313 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3314 {
3315     return WineEngRemoveFontResourceEx(str, fl, pdv);
3316 }
3317
3318 /***********************************************************************
3319  *           GetTextCharset    (GDI32.@)
3320  */
3321 UINT WINAPI GetTextCharset(HDC hdc)
3322 {
3323     /* MSDN docs say this is equivalent */
3324     return GetTextCharsetInfo(hdc, NULL, 0);
3325 }
3326
3327 /***********************************************************************
3328  *           GetTextCharsetInfo    (GDI32.@)
3329  */
3330 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3331 {
3332     UINT ret = DEFAULT_CHARSET;
3333     DC *dc = get_dc_ptr(hdc);
3334
3335     if (dc)
3336     {
3337         if (dc->gdiFont)
3338             ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3339
3340         release_dc_ptr( dc );
3341     }
3342
3343     if (ret == DEFAULT_CHARSET && fs)
3344         memset(fs, 0, sizeof(FONTSIGNATURE));
3345     return ret;
3346 }
3347
3348 /***********************************************************************
3349  *           GdiGetCharDimensions    (GDI32.@)
3350  *
3351  * Gets the average width of the characters in the English alphabet.
3352  *
3353  * PARAMS
3354  *  hdc    [I] Handle to the device context to measure on.
3355  *  lptm   [O] Pointer to memory to store the text metrics into.
3356  *  height [O] On exit, the maximum height of characters in the English alphabet.
3357  *
3358  * RETURNS
3359  *  The average width of characters in the English alphabet.
3360  *
3361  * NOTES
3362  *  This function is used by the dialog manager to get the size of a dialog
3363  *  unit. It should also be used by other pieces of code that need to know
3364  *  the size of a dialog unit in logical units without having access to the
3365  *  window handle of the dialog.
3366  *  Windows caches the font metrics from this function, but we don't and
3367  *  there doesn't appear to be an immediate advantage to do so.
3368  *
3369  * SEE ALSO
3370  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3371  */
3372 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3373 {
3374     SIZE sz;
3375     static const WCHAR alphabet[] = {
3376         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3377         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3378         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3379
3380     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3381
3382     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3383
3384     if (height) *height = sz.cy;
3385     return (sz.cx / 26 + 1) / 2;
3386 }
3387
3388 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3389 {
3390     FIXME("(%d): stub\n", fEnableEUDC);
3391     return FALSE;
3392 }
3393
3394 /***********************************************************************
3395  *           GetCharWidthI    (GDI32.@)
3396  *
3397  * Retrieve widths of characters.
3398  *
3399  * PARAMS
3400  *  hdc    [I] Handle to a device context.
3401  *  first  [I] First glyph in range to query.
3402  *  count  [I] Number of glyph indices to query.
3403  *  glyphs [I] Array of glyphs to query.
3404  *  buffer [O] Buffer to receive character widths.
3405  *
3406  * NOTES
3407  *  Only works with TrueType fonts.
3408  *
3409  * RETURNS
3410  *  Success: TRUE
3411  *  Failure: FALSE
3412  */
3413 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3414 {
3415     ABC *abc;
3416     unsigned int i;
3417
3418     TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3419
3420     if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3421         return FALSE;
3422
3423     if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3424     {
3425         HeapFree(GetProcessHeap(), 0, abc);
3426         return FALSE;
3427     }
3428
3429     for (i = 0; i < count; i++)
3430         buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3431
3432     HeapFree(GetProcessHeap(), 0, abc);
3433     return TRUE;
3434 }
3435
3436 /***********************************************************************
3437  *           GetFontUnicodeRanges    (GDI32.@)
3438  *
3439  *  Retrieve a list of supported Unicode characters in a font.
3440  *
3441  *  PARAMS
3442  *   hdc  [I] Handle to a device context.
3443  *   lpgs [O] GLYPHSET structure specifying supported character ranges.
3444  *
3445  *  RETURNS
3446  *   Success: Number of bytes written to the buffer pointed to by lpgs.
3447  *   Failure: 0
3448  *
3449  */
3450 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3451 {
3452     DWORD ret = 0;
3453     DC *dc = get_dc_ptr(hdc);
3454
3455     TRACE("(%p, %p)\n", hdc, lpgs);
3456
3457     if (!dc) return 0;
3458
3459     if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3460     release_dc_ptr(dc);
3461     return ret;
3462 }
3463
3464
3465 /*************************************************************
3466  *           FontIsLinked    (GDI32.@)
3467  */
3468 BOOL WINAPI FontIsLinked(HDC hdc)
3469 {
3470     DC *dc = get_dc_ptr(hdc);
3471     BOOL ret = FALSE;
3472
3473     if (!dc) return FALSE;
3474     if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3475     release_dc_ptr(dc);
3476     TRACE("returning %d\n", ret);
3477     return ret;
3478 }
3479
3480 /*************************************************************
3481  *           GdiRealizationInfo    (GDI32.@)
3482  *
3483  * Returns a structure that contains some font information.
3484  */
3485 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3486 {
3487     DC *dc = get_dc_ptr(hdc);
3488     BOOL ret = FALSE;
3489
3490     if (!dc) return FALSE;
3491     if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3492     release_dc_ptr(dc);
3493
3494     return ret;
3495 }