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