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