urlmon: Implemented functionality for retrieving the scheme name of a IUri.
[wine] / dlls / gdi32 / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1997 Alex Korobka
6  * Copyright 2002,2003 Shachar Shemesh
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "wownt32.h"
35 #include "gdi_private.h"
36 #include "wine/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  *           CreateFontIndirectExA   (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     POINT pt;
1719     TEXTMETRICW tm;
1720     LOGFONTW lf;
1721     double cosEsc, sinEsc;
1722     INT char_extra;
1723     SIZE sz;
1724     RECT rc;
1725     BOOL done_extents = FALSE;
1726     POINT *deltas = NULL, width = {0, 0};
1727     DWORD type;
1728     DC * dc = get_dc_ptr( hdc );
1729     INT breakRem;
1730     static int quietfixme = 0;
1731
1732     if (!dc) return FALSE;
1733
1734     breakRem = dc->breakRem;
1735
1736     if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
1737     {
1738         FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1739         quietfixme = 1;
1740     }
1741     if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1742     {
1743         release_dc_ptr( dc );
1744         return ret;
1745     }
1746
1747     update_dc( dc );
1748     type = GetObjectType(hdc);
1749     if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1750     {
1751         ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1752         release_dc_ptr( dc );
1753         return ret;
1754     }
1755
1756     if (!lprect)
1757         flags &= ~ETO_CLIPPED;
1758         
1759     if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1760     {
1761         INT cGlyphs;
1762         reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1763
1764         BIDI_Reorder( hdc, str, count, GCP_REORDER,
1765                       ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1766                       WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1767                       reordered_str, count, NULL, &glyphs, &cGlyphs);
1768     
1769         flags |= ETO_IGNORELANGUAGE;
1770         if (glyphs)
1771         {
1772             flags |= ETO_GLYPH_INDEX;
1773             if (cGlyphs != count)
1774                 count = cGlyphs;
1775         }
1776     }
1777     else if(flags & ETO_GLYPH_INDEX)
1778         glyphs = reordered_str;
1779
1780     TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1781           lprect, debugstr_wn(str, count), count, lpDx);
1782
1783     if(lprect)
1784         TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1785               lprect->bottom);
1786     TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1787
1788     if(align & TA_UPDATECP)
1789     {
1790         GetCurrentPositionEx( hdc, &pt );
1791         x = pt.x;
1792         y = pt.y;
1793     }
1794
1795     GetTextMetricsW(hdc, &tm);
1796     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1797
1798     if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1799         lf.lfEscapement = 0;
1800
1801     if(lf.lfEscapement != 0)
1802     {
1803         cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1804         sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1805     }
1806     else
1807     {
1808         cosEsc = 1;
1809         sinEsc = 0;
1810     }
1811
1812     if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1813     {
1814         if(!lprect)
1815         {
1816             if(flags & ETO_GLYPH_INDEX)
1817                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1818             else
1819                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1820
1821             done_extents = TRUE;
1822             rc.left = x;
1823             rc.top = y;
1824             rc.right = x + sz.cx;
1825             rc.bottom = y + sz.cy;
1826         }
1827         else
1828         {
1829             rc = *lprect;
1830         }
1831
1832         LPtoDP(hdc, (POINT*)&rc, 2);
1833
1834         if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1835         if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1836     }
1837
1838     if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1839         dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1840
1841     if(count == 0)
1842     {
1843         ret = TRUE;
1844         goto done;
1845     }
1846
1847     pt.x = x;
1848     pt.y = y;
1849     LPtoDP(hdc, &pt, 1);
1850     x = pt.x;
1851     y = pt.y;
1852
1853     char_extra = GetTextCharacterExtra(hdc);
1854     if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1855     {
1856         UINT i;
1857         SIZE tmpsz;
1858         POINT total = {0, 0}, desired[2];
1859
1860         deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1861         for(i = 0; i < count; i++)
1862         {
1863             if(lpDx)
1864             {
1865                 if(flags & ETO_PDY)
1866                 {
1867                     deltas[i].x = lpDx[i * 2] + char_extra;
1868                     deltas[i].y = -lpDx[i * 2 + 1];
1869                 }
1870                 else
1871                 {
1872                     deltas[i].x = lpDx[i] + char_extra;
1873                     deltas[i].y = 0;
1874                 }
1875
1876             }
1877             else
1878             {
1879                 if(flags & ETO_GLYPH_INDEX)
1880                     GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1881                 else
1882                     GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1883
1884                 deltas[i].x = tmpsz.cx;
1885                 deltas[i].y = 0;
1886             }
1887             
1888             if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1889             {
1890                 deltas[i].x = deltas[i].x + dc->breakExtra;
1891                 if (breakRem > 0)
1892                 {
1893                     breakRem--;
1894                     deltas[i].x++;
1895                 }
1896             }
1897             total.x += deltas[i].x;
1898             total.y += deltas[i].y;
1899
1900             desired[0].x = desired[0].y = 0;
1901
1902             desired[1].x =  cosEsc * total.x + sinEsc * total.y;
1903             desired[1].y = -sinEsc * total.x + cosEsc * total.y;
1904
1905             LPtoDP(hdc, desired, 2);
1906             desired[1].x -= desired[0].x;
1907             desired[1].y -= desired[0].y;
1908
1909             deltas[i].x = desired[1].x - width.x;
1910             deltas[i].y = desired[1].y - width.y;
1911
1912             width = desired[1];
1913         }
1914         flags |= ETO_PDY;
1915     }
1916     else
1917     {
1918         if(!done_extents)
1919         {
1920             if(flags & ETO_GLYPH_INDEX)
1921                 GetTextExtentPointI(hdc, glyphs, count, &sz);
1922             else
1923                 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1924             done_extents = TRUE;
1925         }
1926         width.x = INTERNAL_XWSTODS(dc, sz.cx);
1927         width.y = 0;
1928     }
1929
1930     tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1931     tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1932     switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1933     {
1934     case TA_LEFT:
1935         if (align & TA_UPDATECP)
1936         {
1937             pt.x = x + width.x;
1938             pt.y = y + width.y;
1939             DPtoLP(hdc, &pt, 1);
1940             MoveToEx(hdc, pt.x, pt.y, NULL);
1941         }
1942         break;
1943
1944     case TA_CENTER:
1945         x -= width.x / 2;
1946         y -= width.y / 2;
1947         break;
1948
1949     case TA_RIGHT:
1950         x -= width.x;
1951         y -= width.y;
1952         if (align & TA_UPDATECP)
1953         {
1954             pt.x = x;
1955             pt.y = y;
1956             DPtoLP(hdc, &pt, 1);
1957             MoveToEx(hdc, pt.x, pt.y, NULL);
1958         }
1959         break;
1960     }
1961
1962     switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1963     {
1964     case TA_TOP:
1965         y += tm.tmAscent * cosEsc;
1966         x += tm.tmAscent * sinEsc;
1967         break;
1968
1969     case TA_BOTTOM:
1970         y -= tm.tmDescent * cosEsc;
1971         x -= tm.tmDescent * sinEsc;
1972         break;
1973
1974     case TA_BASELINE:
1975         break;
1976     }
1977
1978     if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1979     {
1980         if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1981         {
1982             if(!(flags & ETO_OPAQUE) || x < rc.left || x + width.x >= rc.right ||
1983                y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1984             {
1985                 RECT rc;
1986                 rc.left = x;
1987                 rc.right = x + width.x;
1988                 rc.top = y - tm.tmAscent;
1989                 rc.bottom = y + tm.tmDescent;
1990                 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1991             }
1992         }
1993     }
1994
1995     if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1996     {
1997         HFONT orig_font = dc->hFont, cur_font;
1998         UINT glyph;
1999         INT span = 0;
2000         POINT *offsets = NULL;
2001         unsigned int i;
2002
2003         glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2004         for(i = 0; i < count; i++)
2005         {
2006             WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2007             if(cur_font != dc->hFont)
2008             {
2009                 if(!offsets)
2010                 {
2011                     unsigned int j;
2012                     offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2013                     offsets[0].x = offsets[0].y = 0;
2014
2015                     if(!deltas)
2016                     {
2017                         SIZE tmpsz;
2018                         for(j = 1; j < count; j++)
2019                         {
2020                             GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2021                             offsets[j].x = offsets[j - 1].x + INTERNAL_XWSTODS(dc, tmpsz.cx);
2022                             offsets[j].y = 0;
2023                         }
2024                     }
2025                     else
2026                     {
2027                         for(j = 1; j < count; j++)
2028                         {
2029                             offsets[j].x = offsets[j - 1].x + deltas[j].x;
2030                             offsets[j].y = offsets[j - 1].y + deltas[j].y;
2031                         }
2032                     }
2033                 }
2034                 if(span)
2035                 {
2036                     if (PATH_IsPathOpen(dc->path))
2037                         ret = PATH_ExtTextOut(dc, x + offsets[i - span].x, y + offsets[i - span].y,
2038                                               (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2039                                               glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2040                     else
2041                         dc->funcs->pExtTextOut(dc->physDev, 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                     span = 0;
2045                 }
2046                 SelectObject(hdc, cur_font);
2047             }
2048             glyphs[span++] = glyph;
2049
2050             if(i == count - 1)
2051             {
2052                 if (PATH_IsPathOpen(dc->path))
2053                     ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span].x : 0),
2054                                           y + (offsets ? offsets[count - span].y : 0),
2055                                           (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2056                                           glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2057                 else
2058                     ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span].x : 0),
2059                                                  y + (offsets ? offsets[count - span].y : 0),
2060                                                  (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2061                                                  glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2062                 SelectObject(hdc, orig_font);
2063                 HeapFree(GetProcessHeap(), 0, offsets);
2064            }
2065         }
2066     }
2067     else
2068     {
2069         if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2070         {
2071             glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2072             GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2073             flags |= ETO_GLYPH_INDEX;
2074         }
2075
2076         if (PATH_IsPathOpen(dc->path))
2077             ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2078                                   glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2079         else
2080             ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2081                                          glyphs ? glyphs : reordered_str, count, (INT*)deltas);
2082     }
2083
2084 done:
2085     HeapFree(GetProcessHeap(), 0, deltas);
2086     if(glyphs != reordered_str)
2087         HeapFree(GetProcessHeap(), 0, glyphs);
2088     if(reordered_str != str)
2089         HeapFree(GetProcessHeap(), 0, reordered_str);
2090
2091     release_dc_ptr( dc );
2092
2093     if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2094     {
2095         int underlinePos, strikeoutPos;
2096         int underlineWidth, strikeoutWidth;
2097         UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2098         OUTLINETEXTMETRICW* otm = NULL;
2099
2100         if(!size)
2101         {
2102             underlinePos = 0;
2103             underlineWidth = tm.tmAscent / 20 + 1;
2104             strikeoutPos = tm.tmAscent / 2;
2105             strikeoutWidth = underlineWidth;
2106         }
2107         else
2108         {
2109             otm = HeapAlloc(GetProcessHeap(), 0, size);
2110             GetOutlineTextMetricsW(hdc, size, otm);
2111             underlinePos = otm->otmsUnderscorePosition;
2112             underlineWidth = otm->otmsUnderscoreSize;
2113             strikeoutPos = otm->otmsStrikeoutPosition;
2114             strikeoutWidth = otm->otmsStrikeoutSize;
2115             HeapFree(GetProcessHeap(), 0, otm);
2116         }
2117
2118         if (PATH_IsPathOpen(dc->path))
2119         {
2120             POINT pts[5];
2121             HPEN hpen;
2122             HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2123
2124             hbrush = SelectObject(hdc, hbrush);
2125             hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2126
2127             if (lf.lfUnderline)
2128             {
2129                 pts[0].x = x - underlinePos * sinEsc;
2130                 pts[0].y = y - underlinePos * cosEsc;
2131                 pts[1].x = x + width.x - underlinePos * sinEsc;
2132                 pts[1].y = y + width.y - underlinePos * cosEsc;
2133                 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2134                 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2135                 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2136                 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2137                 pts[4].x = pts[0].x;
2138                 pts[4].y = pts[0].y;
2139                 DPtoLP(hdc, pts, 5);
2140                 Polygon(hdc, pts, 5);
2141             }
2142
2143             if (lf.lfStrikeOut)
2144             {
2145                 pts[0].x = x - strikeoutPos * sinEsc;
2146                 pts[0].y = y - strikeoutPos * cosEsc;
2147                 pts[1].x = x + width.x - strikeoutPos * sinEsc;
2148                 pts[1].y = y + width.y - strikeoutPos * cosEsc;
2149                 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2150                 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2151                 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2152                 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2153                 pts[4].x = pts[0].x;
2154                 pts[4].y = pts[0].y;
2155                 DPtoLP(hdc, pts, 5);
2156                 Polygon(hdc, pts, 5);
2157             }
2158
2159             SelectObject(hdc, hpen);
2160             hbrush = SelectObject(hdc, hbrush);
2161             DeleteObject(hbrush);
2162         }
2163         else
2164         {
2165             POINT pts[2], oldpt;
2166             HPEN hpen;
2167
2168             if (lf.lfUnderline)
2169             {
2170                 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2171                 hpen = SelectObject(hdc, hpen);
2172                 pts[0].x = x;
2173                 pts[0].y = y;
2174                 pts[1].x = x + width.x;
2175                 pts[1].y = y + width.y;
2176                 DPtoLP(hdc, pts, 2);
2177                 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2178                 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2179                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2180                 DeleteObject(SelectObject(hdc, hpen));
2181             }
2182
2183             if (lf.lfStrikeOut)
2184             {
2185                 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2186                 hpen = SelectObject(hdc, hpen);
2187                 pts[0].x = x;
2188                 pts[0].y = y;
2189                 pts[1].x = x + width.x;
2190                 pts[1].y = y + width.y;
2191                 DPtoLP(hdc, pts, 2);
2192                 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2193                 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2194                 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2195                 DeleteObject(SelectObject(hdc, hpen));
2196             }
2197         }
2198     }
2199
2200     return ret;
2201 }
2202
2203
2204 /***********************************************************************
2205  *           TextOutA    (GDI32.@)
2206  */
2207 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2208 {
2209     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2210 }
2211
2212
2213 /***********************************************************************
2214  *           TextOutW    (GDI32.@)
2215  */
2216 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2217 {
2218     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2219 }
2220
2221
2222 /***********************************************************************
2223  *              PolyTextOutA (GDI32.@)
2224  *
2225  * See PolyTextOutW.
2226  */
2227 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2228 {
2229     for (; cStrings>0; cStrings--, pptxt++)
2230         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2231             return FALSE;
2232     return TRUE;
2233 }
2234
2235
2236
2237 /***********************************************************************
2238  *              PolyTextOutW (GDI32.@)
2239  *
2240  * Draw several Strings
2241  *
2242  * RETURNS
2243  *  TRUE:  Success.
2244  *  FALSE: Failure.
2245  */
2246 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2247 {
2248     for (; cStrings>0; cStrings--, pptxt++)
2249         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2250             return FALSE;
2251     return TRUE;
2252 }
2253
2254
2255 /* FIXME: all following APIs ******************************************/
2256
2257
2258 /***********************************************************************
2259  *           SetMapperFlags    (GDI32.@)
2260  */
2261 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2262 {
2263     DC *dc = get_dc_ptr( hDC );
2264     DWORD ret = 0;
2265     if(!dc) return 0;
2266     if(dc->funcs->pSetMapperFlags)
2267     {
2268         ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2269         /* FIXME: ret is just a success flag, we should return a proper value */
2270     }
2271     else
2272         FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2273     release_dc_ptr( dc );
2274     return ret;
2275 }
2276
2277 /***********************************************************************
2278  *          GetAspectRatioFilterEx  (GDI32.@)
2279  */
2280 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2281 {
2282   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2283   return FALSE;
2284 }
2285
2286
2287 /***********************************************************************
2288  *           GetCharABCWidthsA   (GDI32.@)
2289  *
2290  * See GetCharABCWidthsW.
2291  */
2292 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2293                                   LPABC abc )
2294 {
2295     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2296     LPSTR str;
2297     LPWSTR wstr;
2298     BOOL ret = TRUE;
2299
2300     if(count <= 0) return FALSE;
2301
2302     str = HeapAlloc(GetProcessHeap(), 0, count);
2303     for(i = 0; i < count; i++)
2304         str[i] = (BYTE)(firstChar + i);
2305
2306     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2307
2308     for(i = 0; i < wlen; i++)
2309     {
2310         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2311         {
2312             ret = FALSE;
2313             break;
2314         }
2315         abc++;
2316     }
2317
2318     HeapFree(GetProcessHeap(), 0, str);
2319     HeapFree(GetProcessHeap(), 0, wstr);
2320
2321     return ret;
2322 }
2323
2324
2325 /******************************************************************************
2326  * GetCharABCWidthsW [GDI32.@]
2327  *
2328  * Retrieves widths of characters in range.
2329  *
2330  * PARAMS
2331  *    hdc       [I] Handle of device context
2332  *    firstChar [I] First character in range to query
2333  *    lastChar  [I] Last character in range to query
2334  *    abc       [O] Address of character-width structure
2335  *
2336  * NOTES
2337  *    Only works with TrueType fonts
2338  *
2339  * RETURNS
2340  *    Success: TRUE
2341  *    Failure: FALSE
2342  */
2343 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2344                                    LPABC abc )
2345 {
2346     DC *dc = get_dc_ptr(hdc);
2347     unsigned int i;
2348     BOOL ret = FALSE;
2349
2350     if (!dc) return FALSE;
2351
2352     if (!abc)
2353     {
2354         release_dc_ptr( dc );
2355         return FALSE;
2356     }
2357
2358     if(dc->gdiFont)
2359         ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2360     else
2361         FIXME(": stub\n");
2362
2363     if (ret)
2364     {
2365         /* convert device units to logical */
2366         for( i = firstChar; i <= lastChar; i++, abc++ ) {
2367             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2368             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2369             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2370         }
2371         ret = TRUE;
2372     }
2373
2374     release_dc_ptr( dc );
2375     return ret;
2376 }
2377
2378
2379 /******************************************************************************
2380  * GetCharABCWidthsI [GDI32.@]
2381  *
2382  * Retrieves widths of characters in range.
2383  *
2384  * PARAMS
2385  *    hdc       [I] Handle of device context
2386  *    firstChar [I] First glyphs in range to query
2387  *    count     [I] Last glyphs in range to query
2388  *    pgi       [i] Array of glyphs to query
2389  *    abc       [O] Address of character-width structure
2390  *
2391  * NOTES
2392  *    Only works with TrueType fonts
2393  *
2394  * RETURNS
2395  *    Success: TRUE
2396  *    Failure: FALSE
2397  */
2398 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2399                                LPWORD pgi, LPABC abc)
2400 {
2401     DC *dc = get_dc_ptr(hdc);
2402     unsigned int i;
2403     BOOL ret = FALSE;
2404
2405     if (!dc) return FALSE;
2406
2407     if (!abc)
2408     {
2409         release_dc_ptr( dc );
2410         return FALSE;
2411     }
2412
2413     if(dc->gdiFont)
2414         ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2415     else
2416         FIXME(": stub\n");
2417
2418     if (ret)
2419     {
2420         /* convert device units to logical */
2421         for( i = 0; i < count; i++, abc++ ) {
2422             abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2423             abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2424             abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2425         }
2426         ret = TRUE;
2427     }
2428
2429     release_dc_ptr( dc );
2430     return ret;
2431 }
2432
2433
2434 /***********************************************************************
2435  *           GetGlyphOutlineA    (GDI32.@)
2436  */
2437 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2438                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2439                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2440 {
2441     LPWSTR p = NULL;
2442     DWORD ret;
2443     UINT c;
2444
2445     if (!lpmat2) return GDI_ERROR;
2446
2447     if(!(fuFormat & GGO_GLYPH_INDEX)) {
2448         int len;
2449         char mbchs[2];
2450         if(uChar > 0xff) { /* but, 2 bytes character only */
2451             len = 2;
2452             mbchs[0] = (uChar & 0xff00) >> 8;
2453             mbchs[1] = (uChar & 0xff);
2454         } else {
2455             len = 1;
2456             mbchs[0] = (uChar & 0xff);
2457         }
2458         p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2459         c = p[0];
2460     } else
2461         c = uChar;
2462     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2463                            lpmat2);
2464     HeapFree(GetProcessHeap(), 0, p);
2465     return ret;
2466 }
2467
2468 /***********************************************************************
2469  *           GetGlyphOutlineW    (GDI32.@)
2470  */
2471 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2472                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2473                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
2474 {
2475     DC *dc;
2476     DWORD ret;
2477
2478     TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2479           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2480
2481     if (!lpmat2) return GDI_ERROR;
2482
2483     dc = get_dc_ptr(hdc);
2484     if(!dc) return GDI_ERROR;
2485
2486     if(dc->gdiFont)
2487       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2488                                    cbBuffer, lpBuffer, lpmat2);
2489     else
2490       ret = GDI_ERROR;
2491
2492     release_dc_ptr( dc );
2493     return ret;
2494 }
2495
2496
2497 /***********************************************************************
2498  *           CreateScalableFontResourceA   (GDI32.@)
2499  */
2500 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2501                                              LPCSTR lpszResourceFile,
2502                                              LPCSTR lpszFontFile,
2503                                              LPCSTR lpszCurrentPath )
2504 {
2505     LPWSTR lpszResourceFileW = NULL;
2506     LPWSTR lpszFontFileW = NULL;
2507     LPWSTR lpszCurrentPathW = NULL;
2508     int len;
2509     BOOL ret;
2510
2511     if (lpszResourceFile)
2512     {
2513         len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2514         lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2515         MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2516     }
2517
2518     if (lpszFontFile)
2519     {
2520         len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2521         lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2522         MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2523     }
2524
2525     if (lpszCurrentPath)
2526     {
2527         len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2528         lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2529         MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2530     }
2531
2532     ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2533             lpszFontFileW, lpszCurrentPathW);
2534
2535     HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2536     HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2537     HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2538
2539     return ret;
2540 }
2541
2542 /***********************************************************************
2543  *           CreateScalableFontResourceW   (GDI32.@)
2544  */
2545 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2546                                              LPCWSTR lpszResourceFile,
2547                                              LPCWSTR lpszFontFile,
2548                                              LPCWSTR lpszCurrentPath )
2549 {
2550     HANDLE f;
2551     FIXME("(%d,%s,%s,%s): stub\n",
2552           fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2553           debugstr_w(lpszCurrentPath) );
2554
2555     /* fHidden=1 - only visible for the calling app, read-only, not
2556      * enumerated with EnumFonts/EnumFontFamilies
2557      * lpszCurrentPath can be NULL
2558      */
2559
2560     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2561     if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2562         CloseHandle(f);
2563         SetLastError(ERROR_FILE_EXISTS);
2564         return FALSE;
2565     }
2566     return FALSE; /* create failed */
2567 }
2568
2569 /*************************************************************************
2570  *             GetKerningPairsA   (GDI32.@)
2571  */
2572 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2573                                LPKERNINGPAIR kern_pairA )
2574 {
2575     UINT cp;
2576     CPINFO cpi;
2577     DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2578     KERNINGPAIR *kern_pairW;
2579
2580     if (!cPairs && kern_pairA)
2581     {
2582         SetLastError(ERROR_INVALID_PARAMETER);
2583         return 0;
2584     }
2585
2586     cp = GdiGetCodePage(hDC);
2587
2588     /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2589      * to fail on an invalid character for CP_SYMBOL.
2590      */
2591     cpi.DefaultChar[0] = 0;
2592     if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2593     {
2594         FIXME("Can't find codepage %u info\n", cp);
2595         return 0;
2596     }
2597
2598     total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2599     if (!total_kern_pairs) return 0;
2600
2601     kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2602     GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2603
2604     for (i = 0; i < total_kern_pairs; i++)
2605     {
2606         char first, second;
2607
2608         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2609             continue;
2610
2611         if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2612             continue;
2613
2614         if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2615             continue;
2616
2617         if (kern_pairA)
2618         {
2619             if (kern_pairs_copied >= cPairs) break;
2620
2621             kern_pairA->wFirst = (BYTE)first;
2622             kern_pairA->wSecond = (BYTE)second;
2623             kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2624             kern_pairA++;
2625         }
2626         kern_pairs_copied++;
2627     }
2628
2629     HeapFree(GetProcessHeap(), 0, kern_pairW);
2630
2631     return kern_pairs_copied;
2632 }
2633
2634 /*************************************************************************
2635  *             GetKerningPairsW   (GDI32.@)
2636  */
2637 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2638                                  LPKERNINGPAIR lpKerningPairs )
2639 {
2640     DC *dc;
2641     DWORD ret = 0;
2642
2643     TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2644
2645     if (!cPairs && lpKerningPairs)
2646     {
2647         SetLastError(ERROR_INVALID_PARAMETER);
2648         return 0;
2649     }
2650
2651     dc = get_dc_ptr(hDC);
2652     if (!dc) return 0;
2653
2654     if (dc->gdiFont)
2655         ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2656
2657     release_dc_ptr( dc );
2658     return ret;
2659 }
2660
2661 /*************************************************************************
2662  * TranslateCharsetInfo [GDI32.@]
2663  *
2664  * Fills a CHARSETINFO structure for a character set, code page, or
2665  * font. This allows making the correspondence between different labels
2666  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2667  * of the same encoding.
2668  *
2669  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2670  * only one codepage should be set in *lpSrc.
2671  *
2672  * RETURNS
2673  *   TRUE on success, FALSE on failure.
2674  *
2675  */
2676 BOOL WINAPI TranslateCharsetInfo(
2677   LPDWORD lpSrc, /* [in]
2678        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2679        if flags == TCI_SRCCHARSET: a character set value
2680        if flags == TCI_SRCCODEPAGE: a code page value
2681                  */
2682   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2683   DWORD flags /* [in] determines interpretation of lpSrc */)
2684 {
2685     int index = 0;
2686     switch (flags) {
2687     case TCI_SRCFONTSIG:
2688       while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
2689       break;
2690     case TCI_SRCCODEPAGE:
2691       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
2692       break;
2693     case TCI_SRCCHARSET:
2694       while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
2695       break;
2696     default:
2697       return FALSE;
2698     }
2699     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2700     *lpCs = FONT_tci[index];
2701     return TRUE;
2702 }
2703
2704 /*************************************************************************
2705  *             GetFontLanguageInfo   (GDI32.@)
2706  */
2707 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2708 {
2709         FONTSIGNATURE fontsig;
2710         static const DWORD GCP_DBCS_MASK=0x003F0000,
2711                 GCP_DIACRITIC_MASK=0x00000000,
2712                 FLI_GLYPHS_MASK=0x00000000,
2713                 GCP_GLYPHSHAPE_MASK=0x00000040,
2714                 GCP_KASHIDA_MASK=0x00000000,
2715                 GCP_LIGATE_MASK=0x00000000,
2716                 GCP_USEKERNING_MASK=0x00000000,
2717                 GCP_REORDER_MASK=0x00000060;
2718
2719         DWORD result=0;
2720
2721         GetTextCharsetInfo( hdc, &fontsig, 0 );
2722         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2723
2724         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2725                 result|=GCP_DBCS;
2726
2727         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2728                 result|=GCP_DIACRITIC;
2729
2730         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2731                 result|=FLI_GLYPHS;
2732
2733         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2734                 result|=GCP_GLYPHSHAPE;
2735
2736         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2737                 result|=GCP_KASHIDA;
2738
2739         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2740                 result|=GCP_LIGATE;
2741
2742         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2743                 result|=GCP_USEKERNING;
2744
2745         /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2746         if( GetTextAlign( hdc) & TA_RTLREADING )
2747             if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2748                     result|=GCP_REORDER;
2749
2750         return result;
2751 }
2752
2753
2754 /*************************************************************************
2755  * GetFontData [GDI32.@]
2756  *
2757  * Retrieve data for TrueType font.
2758  *
2759  * RETURNS
2760  *
2761  * success: Number of bytes returned
2762  * failure: GDI_ERROR
2763  *
2764  * NOTES
2765  *
2766  * Calls SetLastError()
2767  *
2768  */
2769 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2770     LPVOID buffer, DWORD length)
2771 {
2772     DC *dc = get_dc_ptr(hdc);
2773     DWORD ret = GDI_ERROR;
2774
2775     if(!dc) return GDI_ERROR;
2776
2777     if(dc->gdiFont)
2778       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2779
2780     release_dc_ptr( dc );
2781     return ret;
2782 }
2783
2784 /*************************************************************************
2785  * GetGlyphIndicesA [GDI32.@]
2786  */
2787 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2788                               LPWORD pgi, DWORD flags)
2789 {
2790     DWORD ret;
2791     WCHAR *lpstrW;
2792     INT countW;
2793
2794     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2795           hdc, debugstr_an(lpstr, count), count, pgi, flags);
2796
2797     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2798     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2799     HeapFree(GetProcessHeap(), 0, lpstrW);
2800
2801     return ret;
2802 }
2803
2804 /*************************************************************************
2805  * GetGlyphIndicesW [GDI32.@]
2806  */
2807 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2808                               LPWORD pgi, DWORD flags)
2809 {
2810     DC *dc = get_dc_ptr(hdc);
2811     DWORD ret = GDI_ERROR;
2812
2813     TRACE("(%p, %s, %d, %p, 0x%x)\n",
2814           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2815
2816     if(!dc) return GDI_ERROR;
2817
2818     if(dc->gdiFont)
2819         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2820
2821     release_dc_ptr( dc );
2822     return ret;
2823 }
2824
2825 /*************************************************************************
2826  * GetCharacterPlacementA [GDI32.@]
2827  *
2828  * See GetCharacterPlacementW.
2829  *
2830  * NOTES:
2831  *  the web browser control of ie4 calls this with dwFlags=0
2832  */
2833 DWORD WINAPI
2834 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2835                          INT nMaxExtent, GCP_RESULTSA *lpResults,
2836                          DWORD dwFlags)
2837 {
2838     WCHAR *lpStringW;
2839     INT uCountW;
2840     GCP_RESULTSW resultsW;
2841     DWORD ret;
2842     UINT font_cp;
2843
2844     TRACE("%s, %d, %d, 0x%08x\n",
2845           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2846
2847     /* both structs are equal in size */
2848     memcpy(&resultsW, lpResults, sizeof(resultsW));
2849
2850     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2851     if(lpResults->lpOutString)
2852         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2853
2854     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2855
2856     lpResults->nGlyphs = resultsW.nGlyphs;
2857     lpResults->nMaxFit = resultsW.nMaxFit;
2858
2859     if(lpResults->lpOutString) {
2860         WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2861                             lpResults->lpOutString, uCount, NULL, NULL );
2862     }
2863
2864     HeapFree(GetProcessHeap(), 0, lpStringW);
2865     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2866
2867     return ret;
2868 }
2869
2870 /*************************************************************************
2871  * GetCharacterPlacementW [GDI32.@]
2872  *
2873  *   Retrieve information about a string. This includes the width, reordering,
2874  *   Glyphing and so on.
2875  *
2876  * RETURNS
2877  *
2878  *   The width and height of the string if successful, 0 if failed.
2879  *
2880  * BUGS
2881  *
2882  *   All flags except GCP_REORDER are not yet implemented.
2883  *   Reordering is not 100% compliant to the Windows BiDi method.
2884  *   Caret positioning is not yet implemented for BiDi.
2885  *   Classes are not yet implemented.
2886  *
2887  */
2888 DWORD WINAPI
2889 GetCharacterPlacementW(
2890                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
2891                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
2892                 INT uCount,             /* [in] Number of WORDS in string. */
2893                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
2894                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2895                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
2896                 )
2897 {
2898     DWORD ret=0;
2899     SIZE size;
2900     UINT i, nSet;
2901
2902     TRACE("%s, %d, %d, 0x%08x\n",
2903           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2904
2905     TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2906           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2907             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2908             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2909             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2910
2911     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08x ignored\n", dwFlags);
2912     if(lpResults->lpClass)      FIXME("classes not implemented\n");
2913     if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2914         FIXME("Caret positions for complex scripts not implemented\n");
2915
2916         nSet = (UINT)uCount;
2917         if(nSet > lpResults->nGlyphs)
2918                 nSet = lpResults->nGlyphs;
2919
2920         /* return number of initialized fields */
2921         lpResults->nGlyphs = nSet;
2922
2923         if((dwFlags&GCP_REORDER)==0 )
2924         {
2925                 /* Treat the case where no special handling was requested in a fastpath way */
2926                 /* copy will do if the GCP_REORDER flag is not set */
2927                 if(lpResults->lpOutString)
2928                     memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2929
2930                 if(lpResults->lpOrder)
2931                 {
2932                         for(i = 0; i < nSet; i++)
2933                                 lpResults->lpOrder[i] = i;
2934                 }
2935         } else
2936         {
2937             BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2938                           nSet, lpResults->lpOrder, NULL, NULL );
2939         }
2940
2941         /* FIXME: Will use the placement chars */
2942         if (lpResults->lpDx)
2943         {
2944                 int c;
2945                 for (i = 0; i < nSet; i++)
2946                 {
2947                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2948                                 lpResults->lpDx[i]= c;
2949                 }
2950         }
2951
2952     if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2953     {
2954         int pos = 0;
2955        
2956         lpResults->lpCaretPos[0] = 0;
2957         for (i = 1; i < nSet; i++)
2958             if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2959                 lpResults->lpCaretPos[i] = (pos += size.cx);
2960     }
2961    
2962     if(lpResults->lpGlyphs)
2963         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2964
2965     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2966       ret = MAKELONG(size.cx, size.cy);
2967
2968     return ret;
2969 }
2970
2971 /*************************************************************************
2972  *      GetCharABCWidthsFloatA [GDI32.@]
2973  *
2974  * See GetCharABCWidthsFloatW.
2975  */
2976 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2977 {
2978     INT i, wlen, count = (INT)(last - first + 1);
2979     LPSTR str;
2980     LPWSTR wstr;
2981     BOOL ret = TRUE;
2982
2983     if (count <= 0) return FALSE;
2984
2985     str = HeapAlloc(GetProcessHeap(), 0, count);
2986
2987     for(i = 0; i < count; i++)
2988         str[i] = (BYTE)(first + i);
2989
2990     wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2991
2992     for (i = 0; i < wlen; i++)
2993     {
2994         if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2995         {
2996             ret = FALSE;
2997             break;
2998         }
2999         abcf++;
3000     }
3001
3002     HeapFree( GetProcessHeap(), 0, str );
3003     HeapFree( GetProcessHeap(), 0, wstr );
3004
3005     return ret;
3006 }
3007
3008 /*************************************************************************
3009  *      GetCharABCWidthsFloatW [GDI32.@]
3010  *
3011  * Retrieves widths of a range of characters.
3012  *
3013  * PARAMS
3014  *    hdc   [I] Handle to device context.
3015  *    first [I] First character in range to query.
3016  *    last  [I] Last character in range to query.
3017  *    abcf  [O] Array of LPABCFLOAT structures.
3018  *
3019  * RETURNS
3020  *    Success: TRUE
3021  *    Failure: FALSE
3022  */
3023 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3024 {
3025     UINT i;
3026     BOOL ret = FALSE;
3027     DC *dc = get_dc_ptr( hdc );
3028
3029     TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3030
3031     if (!dc) return FALSE;
3032
3033     if (!abcf)
3034     {
3035         release_dc_ptr( dc );
3036         return FALSE;
3037     }
3038
3039     if (dc->gdiFont)
3040         ret = WineEngGetCharABCWidthsFloat( dc->gdiFont, first, last, abcf );
3041     else
3042         FIXME("stub\n");
3043
3044     if (ret)
3045     {
3046         /* convert device units to logical */
3047         for (i = first; i <= last; i++, abcf++)
3048         {
3049             abcf->abcfA = abcf->abcfA * dc->xformVport2World.eM11;
3050             abcf->abcfB = abcf->abcfB * dc->xformVport2World.eM11;
3051             abcf->abcfC = abcf->abcfC * dc->xformVport2World.eM11;
3052         }
3053     }
3054
3055     release_dc_ptr( dc );
3056     return ret;
3057 }
3058
3059 /*************************************************************************
3060  *      GetCharWidthFloatA [GDI32.@]
3061  */
3062 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3063                                     UINT iLastChar, PFLOAT pxBuffer)
3064 {
3065     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3066     return 0;
3067 }
3068
3069 /*************************************************************************
3070  *      GetCharWidthFloatW [GDI32.@]
3071  */
3072 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3073                                     UINT iLastChar, PFLOAT pxBuffer)
3074 {
3075     FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3076     return 0;
3077 }
3078
3079
3080 /***********************************************************************
3081  *                                                                     *
3082  *           Font Resource API                                         *
3083  *                                                                     *
3084  ***********************************************************************/
3085
3086 /***********************************************************************
3087  *           AddFontResourceA    (GDI32.@)
3088  */
3089 INT WINAPI AddFontResourceA( LPCSTR str )
3090 {
3091     return AddFontResourceExA( str, 0, NULL);
3092 }
3093
3094 /***********************************************************************
3095  *           AddFontResourceW    (GDI32.@)
3096  */
3097 INT WINAPI AddFontResourceW( LPCWSTR str )
3098 {
3099     return AddFontResourceExW(str, 0, NULL);
3100 }
3101
3102
3103 /***********************************************************************
3104  *           AddFontResourceExA    (GDI32.@)
3105  */
3106 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3107 {
3108     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3109     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3110     INT ret;
3111
3112     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3113     ret = AddFontResourceExW(strW, fl, pdv);
3114     HeapFree(GetProcessHeap(), 0, strW);
3115     return ret;
3116 }
3117
3118 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3119 {
3120     HRSRC rsrc = FindResourceW(hModule, name, type);
3121     HGLOBAL hMem = LoadResource(hModule, rsrc);
3122     LPVOID *pMem = LockResource(hMem);
3123     int *num_total = (int *)lParam;
3124     DWORD num_in_res;
3125
3126     TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3127     if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3128     {
3129         ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3130         return FALSE;
3131     }
3132
3133     *num_total += num_in_res;
3134     return TRUE;
3135 }
3136
3137 /***********************************************************************
3138  *           AddFontResourceExW    (GDI32.@)
3139  */
3140 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3141 {
3142     int ret = WineEngAddFontResourceEx(str, fl, pdv);
3143     if (ret == 0)
3144     {
3145         /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3146         HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3147         if (hModule != NULL)
3148         {
3149             int num_resources = 0;
3150             LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8);  /* we don't want to include winuser.h */
3151
3152             TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3153                 wine_dbgstr_w(str));
3154             if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3155                 ret = num_resources;
3156             FreeLibrary(hModule);
3157         }
3158     }
3159     return ret;
3160 }
3161
3162 /***********************************************************************
3163  *           RemoveFontResourceA    (GDI32.@)
3164  */
3165 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3166 {
3167     return RemoveFontResourceExA(str, 0, 0);
3168 }
3169
3170 /***********************************************************************
3171  *           RemoveFontResourceW    (GDI32.@)
3172  */
3173 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3174 {
3175     return RemoveFontResourceExW(str, 0, 0);
3176 }
3177
3178 /***********************************************************************
3179  *           AddFontMemResourceEx    (GDI32.@)
3180  */
3181 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3182 {
3183     return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3184 }
3185
3186 /***********************************************************************
3187  *           RemoveFontMemResourceEx    (GDI32.@)
3188  */
3189 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3190 {
3191     FIXME("(%p) stub\n", fh);
3192     return TRUE;
3193 }
3194
3195 /***********************************************************************
3196  *           RemoveFontResourceExA    (GDI32.@)
3197  */
3198 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3199 {
3200     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3201     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3202     INT ret;
3203
3204     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3205     ret = RemoveFontResourceExW(strW, fl, pdv);
3206     HeapFree(GetProcessHeap(), 0, strW);
3207     return ret;
3208 }
3209
3210 /***********************************************************************
3211  *           RemoveFontResourceExW    (GDI32.@)
3212  */
3213 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3214 {
3215     return WineEngRemoveFontResourceEx(str, fl, pdv);
3216 }
3217
3218 /***********************************************************************
3219  *           GetTextCharset    (GDI32.@)
3220  */
3221 UINT WINAPI GetTextCharset(HDC hdc)
3222 {
3223     /* MSDN docs say this is equivalent */
3224     return GetTextCharsetInfo(hdc, NULL, 0);
3225 }
3226
3227 /***********************************************************************
3228  *           GetTextCharsetInfo    (GDI32.@)
3229  */
3230 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3231 {
3232     UINT ret = DEFAULT_CHARSET;
3233     DC *dc = get_dc_ptr(hdc);
3234
3235     if (dc)
3236     {
3237         if (dc->gdiFont)
3238             ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3239
3240         release_dc_ptr( dc );
3241     }
3242
3243     if (ret == DEFAULT_CHARSET && fs)
3244         memset(fs, 0, sizeof(FONTSIGNATURE));
3245     return ret;
3246 }
3247
3248 /***********************************************************************
3249  *           GdiGetCharDimensions    (GDI32.@)
3250  *
3251  * Gets the average width of the characters in the English alphabet.
3252  *
3253  * PARAMS
3254  *  hdc    [I] Handle to the device context to measure on.
3255  *  lptm   [O] Pointer to memory to store the text metrics into.
3256  *  height [O] On exit, the maximum height of characters in the English alphabet.
3257  *
3258  * RETURNS
3259  *  The average width of characters in the English alphabet.
3260  *
3261  * NOTES
3262  *  This function is used by the dialog manager to get the size of a dialog
3263  *  unit. It should also be used by other pieces of code that need to know
3264  *  the size of a dialog unit in logical units without having access to the
3265  *  window handle of the dialog.
3266  *  Windows caches the font metrics from this function, but we don't and
3267  *  there doesn't appear to be an immediate advantage to do so.
3268  *
3269  * SEE ALSO
3270  *  GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3271  */
3272 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3273 {
3274     SIZE sz;
3275     static const WCHAR alphabet[] = {
3276         'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3277         'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3278         'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3279
3280     if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3281
3282     if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3283
3284     if (height) *height = sz.cy;
3285     return (sz.cx / 26 + 1) / 2;
3286 }
3287
3288 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3289 {
3290     FIXME("(%d): stub\n", fEnableEUDC);
3291     return FALSE;
3292 }
3293
3294 /***********************************************************************
3295  *           GetCharWidthI    (GDI32.@)
3296  *
3297  * Retrieve widths of characters.
3298  *
3299  * PARAMS
3300  *  hdc    [I] Handle to a device context.
3301  *  first  [I] First glyph in range to query.
3302  *  count  [I] Number of glyph indices to query.
3303  *  glyphs [I] Array of glyphs to query.
3304  *  buffer [O] Buffer to receive character widths.
3305  *
3306  * NOTES
3307  *  Only works with TrueType fonts.
3308  *
3309  * RETURNS
3310  *  Success: TRUE
3311  *  Failure: FALSE
3312  */
3313 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3314 {
3315     ABC *abc;
3316     unsigned int i;
3317
3318     TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3319
3320     if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3321         return FALSE;
3322
3323     if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3324     {
3325         HeapFree(GetProcessHeap(), 0, abc);
3326         return FALSE;
3327     }
3328
3329     for (i = 0; i < count; i++)
3330         buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3331
3332     HeapFree(GetProcessHeap(), 0, abc);
3333     return TRUE;
3334 }
3335
3336 /***********************************************************************
3337  *           GetFontUnicodeRanges    (GDI32.@)
3338  *
3339  *  Retrieve a list of supported Unicode characters in a font.
3340  *
3341  *  PARAMS
3342  *   hdc  [I] Handle to a device context.
3343  *   lpgs [O] GLYPHSET structure specifying supported character ranges.
3344  *
3345  *  RETURNS
3346  *   Success: Number of bytes written to the buffer pointed to by lpgs.
3347  *   Failure: 0
3348  *
3349  */
3350 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3351 {
3352     DWORD ret = 0;
3353     DC *dc = get_dc_ptr(hdc);
3354
3355     TRACE("(%p, %p)\n", hdc, lpgs);
3356
3357     if (!dc) return 0;
3358
3359     if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3360     release_dc_ptr(dc);
3361     return ret;
3362 }
3363
3364
3365 /*************************************************************
3366  *           FontIsLinked    (GDI32.@)
3367  */
3368 BOOL WINAPI FontIsLinked(HDC hdc)
3369 {
3370     DC *dc = get_dc_ptr(hdc);
3371     BOOL ret = FALSE;
3372
3373     if (!dc) return FALSE;
3374     if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3375     release_dc_ptr(dc);
3376     TRACE("returning %d\n", ret);
3377     return ret;
3378 }
3379
3380 /*************************************************************
3381  *           GdiRealizationInfo    (GDI32.@)
3382  *
3383  * Returns a structure that contains some font information.
3384  */
3385 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3386 {
3387     DC *dc = get_dc_ptr(hdc);
3388     BOOL ret = FALSE;
3389
3390     if (!dc) return FALSE;
3391     if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3392     release_dc_ptr(dc);
3393
3394     return ret;
3395 }