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