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