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